/*
Copyright (C) 2005 Laurent Martelli <laurent@aopsys.com>
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU Lesser General Public License as
published by the Free Software Foundation; either version 2 of the
License, or (at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public
License along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
USA */
package org.objectweb.jac.aspects.gui;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
import java.util.Vector;
import org.apache.log4j.Logger;
import org.objectweb.jac.core.rtti.FieldItem;
import org.objectweb.jac.eval.ExprParser;
import org.objectweb.jac.eval.ExprScanner;
/**
* Watches an expression and notifies listeners whenever it changes.
*
* @see org.objectweb.jac.eval.Evaluator
*/
public class ExprWatcher implements FieldUpdate {
Logger logger = Logger.getLogger("gui.expr");
public ExprWatcher(String expr, Object substance) {
this.substance = substance;
this.expr = expr;
reparse();
}
Object substance;
String expr;
List registeredFields = new ArrayList();
/**
* Unregisters from all events and reparse the expression to register again.
*/
protected void reparse() {
// Unregister from all fields
Iterator it = registeredFields.iterator();
while(it.hasNext()) {
Field field = (Field)it.next();
Utils.unregisterField(field.substance,field.field,this);
}
// reparse
ExprParser parser = new ExprWatcherParser(new ExprScanner(expr), this, substance);
try {
value = parser.parse().value;
} catch (Exception e) {
logger.warn("reparse",e);
}
}
/**
* Called by the parser to tell us that the field of an object
* should be watched.
*/
public void watchField(Object substance, FieldItem field) {
Utils.registerField(substance, field, this);
registeredFields.add(new Field(field,substance));
}
static class Field {
public Field(FieldItem field, Object substance) {
this.field = field;
this.substance = substance;
}
FieldItem field;
Object substance;
}
/**
* Notifies all listeners if the oldValue!=newValue.
*/
protected void notifyListeners(Object oldValue, Object newValue) {
if (oldValue!=newValue) {
logger.debug("expressionChanged "+expr+":"+oldValue+"->"+newValue);
Iterator it = listeners.iterator();
while(it.hasNext()) {
((ExpressionListener)it.next()).expressionChanged(oldValue,newValue);
}
}
}
List listeners = new Vector();
public void addListener(ExpressionListener listener) {
listeners.add(listener);
}
public void removeListener(ExpressionListener listener) {
listeners.remove(listener);
}
Object value;
/**
* Reparses the expression and notifies listener if needed.
*/
protected void reparseAndNotify() {
Object oldValue = value;
reparse();
notifyListeners(oldValue,value);
}
// FieldUpdate interface
public void fieldUpdated(Object substance, FieldItem field,
Object value, Object param) {
reparseAndNotify();
}
}