JAL-3949 Complete new abstracted logging framework in jalview.log. Updated log calls...
[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 import jalview.log.JLoggerLog4j;
28
29 public class DatastoreRegistry implements AutoCloseable
30 {
31   protected static JLoggerLog4j log = JLoggerLog4j
32           .getLogger(DatastoreRegistry.class.getCanonicalName());
33
34   /**
35    * map between Datastore objects and the objects they are handling- used to
36    * prevent cycles in the synchronization pattern. Keys are both vamsas objects
37    * and jalview objects, values are datastore objects.
38    */
39   IdentityHashMap dsObjReg;
40
41   /**
42    * all datastore items - value is [jvObject,vObject]
43    */
44   IdentityHashMap dsItemReg;
45
46   public DatastoreRegistry()
47   {
48     dsObjReg = new IdentityHashMap();
49     dsItemReg = new IdentityHashMap();
50   }
51
52   /**
53    * 
54    * @param obj
55    * @return true if obj is in the registry
56    */
57   public boolean isInvolvedInDsitem(Object obj)
58   {
59     return (obj instanceof DatastoreItem) ? dsItemReg.containsKey(obj)
60             : dsObjReg.containsKey(obj);
61   }
62
63   /**
64    * 
65    * @param obj
66    * @return DatastoreItem associated with obj - or null
67    */
68   public DatastoreItem getDatastoreItemFor(Object obj)
69   {
70     if (obj instanceof DatastoreItem)
71     {
72       log.debug("Returning DatastoreItem self reference.");// TODO: we could
73       // store the update
74       // hierarchy - so
75       // retrieve parent
76       // for obj.
77       return (DatastoreItem) obj;
78     }
79     return (DatastoreItem) dsObjReg.get(obj);
80   }
81
82   synchronized void registerDsObj(DatastoreItem dsitem)
83   {
84     Object[] dsregitem = (Object[]) dsItemReg.get(dsitem);
85     if (dsregitem == null)
86     {
87       // create a new item entry
88       dsregitem = new Object[] { dsitem.jvobj, dsitem.vobj };
89       dsItemReg.put(dsitem, dsregitem);
90       dsObjReg.put(dsitem.jvobj, dsitem);
91       dsObjReg.put(dsitem.vobj, dsitem);
92     }
93     else
94     {
95       // update registry for any changed references
96       // for the jvobject
97       if (dsitem.jvobj != dsregitem[0])
98       {
99         // overwrite existing involved entries.
100         if (dsregitem[0] != null)
101         {
102           dsObjReg.remove(dsregitem[0]);
103         }
104         if ((dsregitem[0] = dsitem.jvobj) != null)
105         {
106           dsObjReg.put(dsregitem[0], dsitem);
107         }
108       }
109       // and for the vobject
110       if (dsitem.vobj != dsregitem[1])
111       {
112         // overwrite existing involved entries.
113         if (dsregitem[1] != null)
114         {
115           dsObjReg.remove(dsregitem[1]);
116         }
117         if ((dsregitem[1] = dsitem.vobj) != null)
118         {
119           dsObjReg.put(dsregitem[1], dsitem);
120         }
121       }
122     }
123   }
124
125   /**
126    * Remove dsitem from the registry
127    * 
128    * @param dsitem
129    * @return null or last known Object[] { jvobject, vobject } references for
130    *         this dsitem
131    */
132   public synchronized Object[] removeDsObj(DatastoreItem dsitem)
133   {
134     Object[] dsregitem = null;
135     // synchronized (dsItemReg)
136     {
137       // synchronized (dsObjReg)
138       {
139         dsregitem = (Object[]) dsItemReg.remove(dsitem);
140         if (dsregitem != null)
141         {
142           // eliminate object refs too
143           if (dsregitem[0] != null)
144           {
145             dsObjReg.remove(dsregitem[0]);
146           }
147           if (dsregitem[1] != null)
148           {
149             dsObjReg.remove(dsregitem[1]);
150           }
151         }
152       }
153     }
154     return dsregitem;
155   }
156
157   @Override
158   public void close()
159   {
160     if (dsObjReg != null)
161     {
162       Iterator items = dsObjReg.entrySet().iterator();
163       // avoid the nested reference memory leak.
164       while (items.hasNext())
165       {
166         Object[] vals = (Object[]) ((Map.Entry) items.next()).getValue();
167         vals[0] = null;
168         vals[1] = null;
169       }
170       items = null;
171       dsObjReg.clear();
172     }
173     if (dsItemReg != null)
174     {
175       dsItemReg.clear();
176     }
177     // super.finalize();
178   }
179 }