more efficient synchronized methods
[jalview.git] / src / jalview / io / vamsas / DatastoreRegistry.java
1 package jalview.io.vamsas;
2
3 import java.util.Enumeration;
4 import java.util.IdentityHashMap;
5 import java.util.Iterator;
6 import java.util.Map;
7
8 import uk.ac.vamsas.client.Vobject;
9
10 public class DatastoreRegistry
11 {
12   protected static org.apache.log4j.Logger log = org.apache.log4j.Logger
13           .getLogger(DatastoreRegistry.class);
14
15   /**
16    * map between Datastore objects and the objects they are handling- used to
17    * prevent cycles in the synchronization pattern. Keys are both vamsas objects
18    * and jalview objects, values are datastore objects.
19    */
20   IdentityHashMap dsObjReg;
21
22   /**
23    * all datastore items - value is [jvObject,vObject]
24    */
25   IdentityHashMap dsItemReg;
26
27   public DatastoreRegistry()
28   {
29     dsObjReg = new IdentityHashMap();
30     dsItemReg = new IdentityHashMap();
31   }
32
33   /**
34    * 
35    * @param obj
36    * @return true if obj is in the registry
37    */
38   public boolean isInvolvedInDsitem(Object obj)
39   {
40     return (obj instanceof DatastoreItem) ? dsItemReg.containsKey(obj)
41             : dsObjReg.containsKey(obj);
42   }
43
44   /**
45    * 
46    * @param obj
47    * @return DatastoreItem associated with obj - or null
48    */
49   public DatastoreItem getDatastoreItemFor(Object obj)
50   {
51     if (obj instanceof DatastoreItem)
52     {
53       log.debug("Returning DatastoreItem self reference.");// TODO: we could
54       // store the update
55       // hierarchy - so
56       // retrieve parent
57       // for obj.
58       return (DatastoreItem) obj;
59     }
60     return (DatastoreItem) dsObjReg.get(obj);
61   }
62
63   synchronized void registerDsObj(DatastoreItem dsitem)
64   {
65     Object[] dsregitem = (Object[]) dsItemReg.get(dsitem);
66     if (dsregitem == null)
67     {
68       // create a new item entry
69       dsregitem = new Object[]
70       { dsitem.jvobj, dsitem.vobj };
71       dsItemReg.put(dsitem, dsregitem);
72       dsObjReg.put(dsitem.jvobj, dsitem);
73       dsObjReg.put(dsitem.vobj, dsitem);
74     }
75     else
76     {
77       // update registry for any changed references
78       // for the jvobject
79       if (dsitem.jvobj != dsregitem[0])
80       {
81         // overwrite existing involved entries.
82         if (dsregitem[0] != null)
83         {
84           dsObjReg.remove(dsregitem[0]);
85         }
86         if ((dsregitem[0] = dsitem.jvobj) != null)
87         {
88           dsObjReg.put(dsregitem[0], dsitem);
89         }
90       }
91       // and for the vobject
92       if (dsitem.vobj != dsregitem[1])
93       {
94         // overwrite existing involved entries.
95         if (dsregitem[1] != null)
96         {
97           dsObjReg.remove(dsregitem[1]);
98         }
99         if ((dsregitem[1] = dsitem.vobj) != null)
100         {
101           dsObjReg.put(dsregitem[1], dsitem);
102         }
103       }
104     }
105   }
106
107   /**
108    * Remove dsitem from the registry
109    * 
110    * @param dsitem
111    * @return null or last known Object[] { jvobject, vobject } references for
112    *         this dsitem
113    */
114   public synchronized Object[] removeDsObj(DatastoreItem dsitem)
115   {
116     Object[] dsregitem = null;
117     // synchronized (dsItemReg)
118     {
119       // synchronized (dsObjReg)
120       {
121         dsregitem = (Object[]) dsItemReg.remove(dsitem);
122         if (dsregitem != null)
123         {
124           // eliminate object refs too
125           if (dsregitem[0] != null)
126           {
127             dsObjReg.remove(dsregitem[0]);
128           }
129           if (dsregitem[1] != null)
130           {
131             dsObjReg.remove(dsregitem[1]);
132           }
133         }
134       }
135     }
136     return dsregitem;
137   }
138
139   protected void finalize()
140   {
141     if (dsObjReg != null)
142     {
143       Iterator items = dsObjReg.entrySet().iterator();
144       // avoid the nested reference memory leak.
145       while (items.hasNext())
146       {
147         Object[] vals = (Object[]) ((Map.Entry) items.next()).getValue();
148         vals[0] = null;
149         vals[1] = null;
150       }
151       items = null;
152       dsObjReg.clear();
153     }
154     if (dsItemReg != null)
155     {
156       dsItemReg.clear();
157     }
158   }
159 }