001    package com.thaiopensource.util;
002    
003    import java.util.Hashtable;
004    import java.util.Enumeration;
005    
006    public class PropertyMapBuilder {
007      private Hashtable map;
008      private PropertyId[] keys;
009    
010      private static class PropertyMapImpl implements PropertyMap {
011        private final Hashtable map;
012        private final PropertyId[] keys;
013    
014        private PropertyMapImpl(Hashtable map, PropertyId[] keys) {
015          this.map = map;
016          this.keys = keys;
017        }
018    
019        public Object get(PropertyId pid) {
020          return map.get(pid);
021        }
022    
023        public int size() {
024          return keys.length;
025        }
026    
027        public boolean contains(PropertyId pid) {
028          return map.get(pid) != null;
029        }
030    
031        public PropertyId getKey(int i) {
032          return keys[i];
033        }
034      }
035    
036      public PropertyMapBuilder() {
037        this.map = new Hashtable();
038      }
039    
040      public PropertyMapBuilder(PropertyMap pm) {
041        if (pm instanceof PropertyMapImpl) {
042          PropertyMapImpl pmi = (PropertyMapImpl)pm;
043          this.map = pmi.map;
044          this.keys = pmi.keys;
045        }
046        else {
047          this.map = new Hashtable();
048          for (int i = 0, len = pm.size(); i < len; i++) {
049            PropertyId pid = pm.getKey(i);
050            put(pid, pm.get(pid));
051          }
052        }
053      }
054    
055      private void lock() {
056        if (keys != null)
057          return;
058        keys = new PropertyId[map.size()];
059        int i = 0;
060        for (Enumeration e = map.keys(); e.hasMoreElements();)
061          keys[i++] = (PropertyId)e.nextElement();
062      }
063    
064      private void copyIfLocked() {
065        if (keys == null)
066          return;
067        Hashtable newMap = new Hashtable();
068        for (int i = 0; i < keys.length; i++)
069          newMap.put(keys[i], map.get(keys[i]));
070        map = newMap;
071        keys = null;
072      }
073    
074      public PropertyMap toPropertyMap() {
075        lock();
076        return new PropertyMapImpl(map, keys);
077      }
078    
079      public Object put(PropertyId id, Object value) {
080        copyIfLocked();
081        if (value == null)
082          return map.remove(id);
083        if (!id.getValueClass().isInstance(value))
084          throw new ClassCastException();
085        return map.put(id, value);
086      }
087    
088      public Object get(PropertyId pid) {
089        return map.get(pid);
090      }
091    
092      public boolean contains(PropertyId pid) {
093        return map.get(pid) != null;
094      }
095    }