001    package jigcell.compare.data;
002    
003    import java.beans.DefaultPersistenceDelegate;
004    import java.beans.Encoder;
005    import java.beans.Statement;
006    import java.util.StringTokenizer;
007    import jigcell.compare.IDataElement;
008    import jigcell.compare.IEditableDataGenerator;
009    import jigcell.compare.IProgrammableDataGenerator;
010    import jigcell.compare.impl.Compare;
011    
012    /**
013     * Implementation of DataGenerator that supports editing the generator fields.  The default element type of an EditableDataGenerator is a
014     * SparseTreeDataElement.
015     *
016     * <p>
017     * This code is licensed under the DARPA BioCOMP Open Source License.  See LICENSE for more details.
018     * </p>
019     *
020     * @author Nicholas Allen
021     */
022    
023    public class EditableDataGenerator extends DataGenerator implements IEditableDataGenerator {
024    
025       /**
026        * Cached version of the associated element
027        */
028    
029       private transient IDataElement element;
030    
031       /**
032        * Persist the generator using the setElement method with a flat string rather than trying to expand the element.
033        */
034    
035       protected static class EditableDataGeneratorDelegate extends DefaultPersistenceDelegate {
036          protected void initialize (Class clazz, Object o1, Object o2, Encoder encoder) {
037             super.initialize (clazz, o1, o2, encoder);
038             if (!(o1 instanceof IProgrammableDataGenerator))
039                encoder.writeStatement (new Statement (o1, "setElement", new Object [] {((EditableDataGenerator) o1).getElement ().toString ()}));
040          }
041       }
042    
043       static {
044          Compare.addTransient (EditableDataGenerator.class, "element");
045          Compare.addDelegate (EditableDataGenerator.class, new EditableDataGeneratorDelegate ());
046       }
047    
048       /**
049        * Creates a new data generator that supports editing.
050        */
051    
052       public EditableDataGenerator () {
053          this (new SparseTreeDataElement ());
054       }
055    
056       /**
057        * Creates a new data generator that supports editing.
058        *
059        * @param element Element to link to
060        */
061    
062       public EditableDataGenerator (IDataElement element) {
063          super ();
064          this.element = element;
065          setName ("New");
066          setWriteDescriptionOption ("Write to Generator");
067       }
068    
069       /**
070        * {@inheritDoc}
071        */
072    
073       public synchronized void clear () {
074          element = null;
075       }
076    
077       /**
078        * {@inheritDoc}
079        */
080    
081       public IDataElement getElement () {
082          return element;
083       }
084    
085       /**
086        * {@inheritDoc}
087        */
088    
089       public boolean getPredictedCompatibility (Class clazz) {
090          return String.class.isAssignableFrom (clazz) || IDataElement.class.isAssignableFrom (clazz);
091       }
092    
093       /**
094        * {@inheritDoc}
095        */
096    
097       public boolean getPredictedCompatibility (Object instance) {
098          return instance instanceof String || instance instanceof IDataElement;
099       }
100    
101       /**
102        * {@inheritDoc}
103        */
104    
105       public boolean isCached () {
106          return true;
107       }
108    
109       /**
110        * Whether this generator has a set value.
111        */
112    
113       public boolean isSet () {
114          return element != null;
115       }
116    
117       /**
118        * {@inheritDoc}
119        */
120    
121       public synchronized boolean setAttribute (String key, String value) {
122          String oldValue = (String) getOption (key);
123          if (value == oldValue || value != null && value.equals (oldValue))
124             return false;
125          setOptionType (key, Option.SAFE);
126          setOption (key, value);
127          return true;
128       }
129    
130       /**
131        * {@inheritDoc}
132        */
133    
134       public void setComment (String displayableComment) {
135          setAttribute (ATTRIBUTE_COMMENT, displayableComment);
136       }
137    
138       /**
139        * {@inheritDoc}
140        */
141    
142       public synchronized void setElement (IDataElement element) {
143          this.element = element == null ? SparseTreeDataElement.createElement ("null") : element;
144       }
145    
146       /**
147        * Creates a new associated data element and initializes it with the given text.
148        *
149        * @param text Textual representation of an element
150        */
151    
152       public synchronized void setElement (String text) {
153          element = SparseTreeDataElement.createElement (text);
154       }
155    
156       /**
157        * {@inheritDoc}
158        */
159    
160       public synchronized boolean setOption (String key, Object value) {
161          return super.setOption (key, value);
162       }
163    
164       /**
165        * {@inheritDoc}
166        */
167    
168       public void setState (String state) {
169          for (StringTokenizer tokenizer = new StringTokenizer (state, SEPARATORS); tokenizer.hasMoreElements (); ) {
170             String key = tokenizer.nextToken ();
171             if (!tokenizer.hasMoreElements ())
172                throw new IllegalArgumentException ("Unable to fully parse expression");
173             setAttribute (key, tokenizer.nextToken ());
174          }
175       }
176    
177       /**
178        * {@inheritDoc}
179        */
180    
181       public void write (Object data) throws Exception {
182          if (data instanceof IDataElement)
183             setElement ((IDataElement) data);
184          else
185             setElement ((String) data);
186       }
187    }