Main Page | Packages | Class Hierarchy | Alphabetical List | Class List | File List | Class Members | Related Pages

AdapterCacheFlyweight.java

Go to the documentation of this file.
00001 
00065 package com.arcle.rmt.j2se.model.domimpl;
00066 
00067 import java.util.WeakHashMap;
00068 import java.util.Hashtable;
00069 import java.util.Map;
00070 import java.util.Observer;
00071 import java.util.Observable;
00072 import org.w3c.dom.Element;
00073 import com.arcle.rmt.rqml.*;
00074 import com.arcle.rmt.j2se.model.domimpl.rqml.*;
00075 import com.arcle.rmt.j2se.util.CounterMap;
00076 import com.arcle.rmt.j2se.util.StringUtilities;
00077 
00091 public class AdapterCacheFlyweight implements RQMLSecondClassFactory {
00092 
00098     public AdapterCacheFlyweight(Observer elementObserver) {
00099         if (elementObserver == null) {
00100             throw new IllegalArgumentException(
00101                 "Parameter 'elementObserver' cannot be null.");
00102         }
00103         _elementObserver = elementObserver;
00104     }
00105 
00114     public RQMLSecondClass createRQMLSecondClass(Element elem) {
00115         RQMLSecondClass rqml = (RQMLSecondClass) getCache().get(elem);
00116         if (rqml == null) {
00117             RQMLSecondClassFactory fac = getElementFactory(elem.getNodeName());
00118             if (fac == null) {
00119                 throw new UnsupportedOperationException(
00120                     "Factory not found for element: " + elem.getNodeName());
00121             }
00122             rqml = fac.createRQMLSecondClass(elem);
00123             assignID(rqml);
00124             addObservable(rqml);
00125             getCache().put(elem, rqml);
00126         }
00127         return rqml;
00128     }
00129 
00133     public boolean remove(Element elem) {
00134         Object rqml = getCache().get(elem);
00135         if (rqml instanceof ElementAdapter) {
00136             ElementAdapter ea = (ElementAdapter) rqml;
00137             // since we use a WeakHashMap, all of its children adapters
00138             // will eventually die out from the cache.
00139             ea.deleteElement();
00140         }
00141         return getCache().remove(elem) != null;
00142     }
00143 
00144 
00145     protected boolean addObservable(Object o) {
00146         if (o instanceof Observable) {
00147             Observable obs = (Observable) o;
00148             obs.addObserver(getElementObserver());
00149             return true;
00150         }
00151         return false;
00152     }
00153 
00162     protected void assignID(RQMLSecondClass elem) {
00163         String id = elem.getID();
00164         String name = ((RQMLSecondClassImpl) elem).getElementName();
00165         String stripped = StringUtilities.stripAllExceptConsonantsOrFirstChar(name);
00166         int endIndex = Math.min(NAME_PREFIX_LEN, stripped.length());
00167         String prefix = stripped.substring(0, endIndex);
00168         /* To prevent ID clashes when two elements with different element
00169            names resolve to the same prefix, we use the prefix instead
00170            of the element name as the counter key.
00171            Even though we might not need the counter value, we increment
00172            the counter anyway to account those elements already
00173            having an ID.
00174         */
00175         int idValue = getElementIDGenerator().incrementCounter(prefix);
00176         if (id.length() == 0) {
00177             id =  prefix + "-" + idValue;
00178             elem.setID(id);
00179         }
00180     }
00181 
00182 
00183     //-----------------------------------------------------------------------
00184     // Accessor Methods
00185 
00192     protected Map getCache() {
00193         if (_cache == null) {
00194             _cache = createCache();
00195         }
00196         return _cache;
00197     }
00198 
00205     protected RQMLSecondClassFactory getElementFactory(String elementName) {
00206         if (_elementFactories == null) {
00207             _elementFactories = createElementFactories();
00208         }
00209         return _elementFactories.getFactory(elementName);
00210     }
00211 
00216     protected Observer getElementObserver() {
00217         return _elementObserver;
00218     }
00219 
00223     protected CounterMap getElementIDGenerator() {
00224         if (_IDGenerator == null) {
00225             _IDGenerator = createElementIDGenerator();
00226         }
00227         return _IDGenerator;
00228     }
00229 
00230 
00231     //-----------------------------------------------------------------------
00232     // Factory Methods
00233 
00239     protected Map createCache() {
00240         return new WeakHashMap();
00241     }
00242 
00247     protected RQMLSecondClassFactoryFacade createElementFactories() {
00248         return new RQMLSecondClassFactoryFacade(this);
00249     }
00250 
00255     protected CounterMap createElementIDGenerator() {
00256         return new CounterMap();
00257     }
00258 
00259     //-----------------------------------------------------------------------
00260     // Member Variables
00261 
00267     private RQMLSecondClassFactoryFacade _elementFactories = null;
00268 
00275     private Map _cache = null;
00276 
00281     private Observer _elementObserver;
00282 
00286     private CounterMap _IDGenerator = null;
00287 
00291     protected static final int NAME_PREFIX_LEN = 4;
00292 
00293     //-----------------------------------------------------------------------
00294     // Inner classes
00295 
00305     protected abstract class ElementFactory implements RQMLSecondClassFactory {
00306 
00312         public RQMLSecondClass createRQMLSecondClass(Element e) {
00313             RQMLSecondClassImpl rcs = doCreateRQMLSecondClass(e);
00314             return rcs;
00315         }
00316 
00323         protected abstract RQMLSecondClassImpl doCreateRQMLSecondClass(Element e);
00324     }
00325 }
00326 

Generated on Fri Jun 18 19:50:37 2004 for Arcle Rambutan by doxygen 1.3.5