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 }