/* * Copyright (c) 2006,2009 Declarative Engineering LLC. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Declarative Engineering LLC * verson 1 which accompanies this distribution, and is available at * http://declarativeengineering.com/legal/DE_Developer_License_v1.txt */ package com.foundation.view; import com.common.debug.Debug; import com.common.util.IIterator; import com.foundation.event.EventSupport; public class SingleAssociationContainer extends AssociationContainer implements IValueHolderListener { /** A simple flag that turns thread verification on and off. */ private static final boolean VERIFY_THREAD = true; private SingleAssociation[] associations = null; private SingleAssociation firstNode = null; private SingleAssociation lastNode = null; private Object row = null; private String valueHolderName = null; private EventSupport eventSupport = null; private IValueHolder valueHolder = null; /** * AssociationContainer constructor. * @param valueHolderName The name of the value holder whose value will be the input for the associations. * @param associations The associations that are the roots for the single resource association that will be using them. */ public SingleAssociationContainer(String valueHolderName, SingleAssociation[] associations) { this.valueHolderName = valueHolderName; this.associations = associations; }//AssociationContainer()// /** * Locates the value holder by looking in the component's parents (and the component its self if it is a container) until a value holder with the given name is found. *

Note: The name is not case sensitive. * @return The found value holder, or null if one could not be found. */ protected IValueHolder locateValueHolder(IAbstractComponent component) { IAbstractContainer container = null; IValueHolder result = null; if(component instanceof IAbstractContainer) { container = (IAbstractContainer) component; }//if// else { container = component.getContainer(); }//else// while((result == null) && (container != null)) { IIterator iterator = container.getComponents().iterator(); while((result == null) && (iterator.hasNext())) { Object next = iterator.next(); if((next instanceof IValueHolder) && (((IValueHolder) next).getName().equalsIgnoreCase(valueHolderName))) { result = (IValueHolder) next; }//if// }//while// container = container.getContainer(); }//while// return result; }//locateValueHolder()// /** * Initializes the container of associations. */ public void initialize() { if(associations != null) { for(int index = 0; index < associations.length; index++) { associations[index].initialize(this); }//for// }//if// }//initialize()// /** * Releases the container of associations. */ public void release() { if(associations != null) { for(int index = 0; index < associations.length; index++) { associations[index].release(); }//for// }//if// }//release()// /** * Registers the associations. */ public void register() { SingleAssociation association = null; if(valueHolderName != null) { if(valueHolder == null) { valueHolder = locateValueHolder(getResourceAssociation().getComponent()); valueHolder.registerListener(this); }//if// row = valueHolder.getValue(); }//if// //Find the first applicable association.// for(int index = 0; association == null && index < associations.length; index++) { if(associations[index].isApplicable(row)) { association = associations[index]; }//if// }//for// //If an applicable association was found then register the row with it.// if(association != null) { firstNode = association; association.register(row); }//if// //Register with the child associations until we find a target association.// while((association != null) && (!association.isTargetAssociation())) { SingleAssociation next = null; Object result = association.getResult(); for(int index = 0; next == null && index < associations.length; index++) { if(associations[index].isApplicable(result)) { next = associations[index]; }//if// }//for// if(next != null) { association.setNext(next); next.register(result); }//if// association = next; }//while// if((association != null) && (association.isTargetAssociation())) { lastNode = association; }//if// }//register()// /** * Unregisters the associations. */ public void unregister() { if(firstNode != null) { unregister(firstNode, row); firstNode = null; lastNode = null; }//if// row = null; if(eventSupport != null) { eventSupport.unregisterAll(); }//if// }//unregister()// /** * Recursively unregisters associations. * @param association The association to unregister with. * @param value The previous association's value which is the given association's input. */ protected void unregister(SingleAssociation association, Object value) { if(association.getNext() != null) { unregister(association.getNext(), association.getResult()); association.setNext(null); }//if// association.unregister(value); }//unregister()// /** * Gets the value in the model. * @return The value the row resolves to. This will be NO_VALUE if the row does not resolve to a target association. */ public Object getValue() { Object result = NO_VALUE; SingleAssociation association = firstNode; if(association != null) { while(association.getNext() != null) { association = association.getNext(); }//while// if(association.isTargetAssociation()) { result = association.getResult(); }//if// }//if// return result; }//getValue()// /** * Gets the last association node in the chain to the result. * @return The last association which produces the result. This will be null if there is no input, or no path to a target association. */ public SingleAssociation getEndAssociation() { return lastNode; }//getEndAssociation()// /** * Sets the value in the model. * @param value The value to be set in the model. */ public void setValue(Object value) { SingleAssociation association = firstNode; if(VERIFY_THREAD) { verifyThread(); }//if// if(firstNode == null) { Debug.log("Error"); }//if// while(association.getNext() != null) { association = association.getNext(); }//while// if(association.isTargetAssociation()) { association.setResult(value); }//if// }//setValue()// /** * Updates the associations after one of the associations alters its value. * @param association The association that altered its value. * @param oldValue The previous value for the given association. * @param eventFlags The event flags that for the event that triggered the update. This will only be non-zero if an event triggered the call and the event was either an original value changed or cleared event. */ public void updateAssociations(SingleAssociation association, Object oldValue, int eventFlags) { if(!EventSupport.isOriginalValueChanged(eventFlags) && !EventSupport.isOriginalValueCleared(eventFlags)) { if(association.getNext() != null) { unregister(association.getNext(), oldValue); }//if// //Register with the child associations until we find a target association.// while((association != null) && (!association.isTargetAssociation())) { SingleAssociation next = null; Object result = association.getResult(); for(int index = 0; next == null && index < associations.length; index++) { if(associations[index].isApplicable(result)) { next = associations[index]; }//if// }//for// if(next != null) { association.setNext(next); next.register(result); }//if// association = next; }//while// //Update the last node reference.// if((association != null) && (association.isTargetAssociation())) { lastNode = association; }//if// }//if// //Notify the SingleResourceAssociation.// ((SingleResourceAssociation) getResourceAssociation()).modelChanged(eventFlags, false); }//updateAssociations()// /** * Gets the event support for the association. * @return The event support used by the association to manage event registrations. */ public EventSupport getEventSupport() { return eventSupport == null ? (eventSupport = new EventSupport(null)) : eventSupport; }//getEventSupport()// /* (non-Javadoc) * @see com.foundation.view.IValueHolderListener#heldValueChanged() */ public void heldValueChanged() { if(VERIFY_THREAD) { verifyThread(); }//if// //Called when the value holder related to this container has changed its held value.// unregister(); register(); ((SingleResourceAssociation) getResourceAssociation()).modelChanged(0, true); }//heldValueChanged()// }//AssociationContainer//