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