Merge branch 'JAL-1378_jb2.1cli' into RNAalifold
[jalview.git] / src / jalview / io / vamsas / DatastoreRegistry.java
1 /*
2  * Jalview - A Sequence Alignment Editor and Viewer (Version 2.8)
3  * Copyright (C) 2012 J Procter, AM Waterhouse, LM Lui, J Engelhardt, G Barton, M Clamp, S Searle
4  * 
5  * This file is part of Jalview.
6  * 
7  * Jalview is free software: you can redistribute it and/or
8  * modify it under the terms of the GNU General Public License 
9  * as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version.
10  *  
11  * Jalview is distributed in the hope that it will be useful, but 
12  * WITHOUT ANY WARRANTY; without even the implied warranty 
13  * of MERCHANTABILITY or FITNESS FOR A PARTICULAR 
14  * PURPOSE.  See the GNU General Public License for more details.
15  * 
16  * You should have received a copy of the GNU General Public License along with Jalview.  If not, see <http://www.gnu.org/licenses/>.
17  */
18 package jalview.io.vamsas;
19
20 import java.util.IdentityHashMap;
21 import java.util.Iterator;
22 import java.util.Map;
23
24 public class DatastoreRegistry
25 {
26   protected static org.apache.log4j.Logger log = org.apache.log4j.Logger
27           .getLogger(DatastoreRegistry.class);
28
29   /**
30    * map between Datastore objects and the objects they are handling- used to
31    * prevent cycles in the synchronization pattern. Keys are both vamsas objects
32    * and jalview objects, values are datastore objects.
33    */
34   IdentityHashMap dsObjReg;
35
36   /**
37    * all datastore items - value is [jvObject,vObject]
38    */
39   IdentityHashMap dsItemReg;
40
41   public DatastoreRegistry()
42   {
43     dsObjReg = new IdentityHashMap();
44     dsItemReg = new IdentityHashMap();
45   }
46
47   /**
48    * 
49    * @param obj
50    * @return true if obj is in the registry
51    */
52   public boolean isInvolvedInDsitem(Object obj)
53   {
54     return (obj instanceof DatastoreItem) ? dsItemReg.containsKey(obj)
55             : dsObjReg.containsKey(obj);
56   }
57
58   /**
59    * 
60    * @param obj
61    * @return DatastoreItem associated with obj - or null
62    */
63   public DatastoreItem getDatastoreItemFor(Object obj)
64   {
65     if (obj instanceof DatastoreItem)
66     {
67       log.debug("Returning DatastoreItem self reference.");// TODO: we could
68       // store the update
69       // hierarchy - so
70       // retrieve parent
71       // for obj.
72       return (DatastoreItem) obj;
73     }
74     return (DatastoreItem) dsObjReg.get(obj);
75   }
76
77   synchronized void registerDsObj(DatastoreItem dsitem)
78   {
79     Object[] dsregitem = (Object[]) dsItemReg.get(dsitem);
80     if (dsregitem == null)
81     {
82       // create a new item entry
83       dsregitem = new Object[]
84       { dsitem.jvobj, dsitem.vobj };
85       dsItemReg.put(dsitem, dsregitem);
86       dsObjReg.put(dsitem.jvobj, dsitem);
87       dsObjReg.put(dsitem.vobj, dsitem);
88     }
89     else
90     {
91       // update registry for any changed references
92       // for the jvobject
93       if (dsitem.jvobj != dsregitem[0])
94       {
95         // overwrite existing involved entries.
96         if (dsregitem[0] != null)
97         {
98           dsObjReg.remove(dsregitem[0]);
99         }
100         if ((dsregitem[0] = dsitem.jvobj) != null)
101         {
102           dsObjReg.put(dsregitem[0], dsitem);
103         }
104       }
105       // and for the vobject
106       if (dsitem.vobj != dsregitem[1])
107       {
108         // overwrite existing involved entries.
109         if (dsregitem[1] != null)
110         {
111           dsObjReg.remove(dsregitem[1]);
112         }
113         if ((dsregitem[1] = dsitem.vobj) != null)
114         {
115           dsObjReg.put(dsregitem[1], dsitem);
116         }
117       }
118     }
119   }
120
121   /**
122    * Remove dsitem from the registry
123    * 
124    * @param dsitem
125    * @return null or last known Object[] { jvobject, vobject } references for
126    *         this dsitem
127    */
128   public synchronized Object[] removeDsObj(DatastoreItem dsitem)
129   {
130     Object[] dsregitem = null;
131     // synchronized (dsItemReg)
132     {
133       // synchronized (dsObjReg)
134       {
135         dsregitem = (Object[]) dsItemReg.remove(dsitem);
136         if (dsregitem != null)
137         {
138           // eliminate object refs too
139           if (dsregitem[0] != null)
140           {
141             dsObjReg.remove(dsregitem[0]);
142           }
143           if (dsregitem[1] != null)
144           {
145             dsObjReg.remove(dsregitem[1]);
146           }
147         }
148       }
149     }
150     return dsregitem;
151   }
152
153   protected void finalize()
154   {
155     if (dsObjReg != null)
156     {
157       Iterator items = dsObjReg.entrySet().iterator();
158       // avoid the nested reference memory leak.
159       while (items.hasNext())
160       {
161         Object[] vals = (Object[]) ((Map.Entry) items.next()).getValue();
162         vals[0] = null;
163         vals[1] = null;
164       }
165       items = null;
166       dsObjReg.clear();
167     }
168     if (dsItemReg != null)
169     {
170       dsItemReg.clear();
171     }
172   }
173 }