package org.infosec.ismp.applet.manager.controller; import java.beans.PropertyChangeEvent; import java.beans.PropertyChangeListener; import java.lang.reflect.Method; import java.util.ArrayList; import org.infosec.ismp.applet.manager.model.AbstractModel; import org.infosec.ismp.applet.manager.view.AbstractViewPanel; /** * This class provides base level functionality for each controller. This includes the * ability to register multiple models and views, propogating model change events to * each of the views, and providing a utility function to broadcast model property * changes when necessary. */ public abstract class AbstractController implements PropertyChangeListener { // Vectors that hold a list of the registered models and views for this controller. private ArrayList<AbstractViewPanel> registeredViews; private ArrayList<AbstractModel> registeredModels; /** Creates a new instance of Controller */ public AbstractController() { registeredViews = new ArrayList<AbstractViewPanel>(); registeredModels = new ArrayList<AbstractModel>(); } /** * Binds a model to this controller. Once added, the controller will listen for all * model property changes and propogate them on to registered views. In addition, * it is also responsible for resetting the model properties when a view changes * state. * @param model The model to be added */ public void addModel(AbstractModel model) { registeredModels.add(model); model.addPropertyChangeListener(this); } /** * Unbinds a model from this controller. * @param model The model to be removed */ public void removeModel(AbstractModel model) { registeredModels.remove(model); model.removePropertyChangeListener(this); } /** * Binds a view to this controller. The controller will propogate all model property * changes to each view for consideration. * @param view The view to be added */ public void addView(AbstractViewPanel view) { registeredViews.add(view); } /** * Unbinds a view from this controller. * @param view The view to be removed */ public void removeView(AbstractViewPanel view) { registeredViews.remove(view); } // Used to observe property changes from registered models and propogate // them on to all the views. /** * This method is used to implement the PropertyChangeListener interface. Any model * changes will be sent to this controller through the use of this method. * @param evt An object that describes the model's property change. */ public void propertyChange(PropertyChangeEvent evt) { for (AbstractViewPanel view: registeredViews) { view.modelPropertyChange(evt); } } /** * Convienence method that subclasses can call upon to fire off property changes * back to the models. This method used reflection to inspect each of the model * classes to determine if it is the owner of the property in question. If it * isn't, a NoSuchMethodException is throws (which the method ignores). * * @param propertyName The name of the property * @param newValue An object that represents the new value of the property. */ protected void setModelProperty(String propertyName, Object newValue) { for (AbstractModel model: registeredModels) { try { Method method = model.getClass(). getMethod("set"+propertyName, new Class[] { newValue.getClass() } ); method.invoke(model, newValue); } catch (Exception ex) { //TODO Handle exception } } } }