View Javadoc

1   /* ===================================================================
2    * Copyright 2002-04 SRI International.
3    * Released under the MOZILLA PUBLIC LICENSE Version 1.1
4    * which can be obtained at http://www.mozilla.org/MPL/MPL-1.1.html
5    * This software is distributed on an "AS IS"
6    * basis, WITHOUT WARRANTY OF ANY KIND, either express or implied.
7    * See the License for the specific language governing rights and
8    * limitations under the License.
9    * =================================================================== */
10  package com.sri.emo.dbobj;
11  
12  import com.jcorporate.expresso.core.db.DBConnection;
13  import com.jcorporate.expresso.core.db.DBException;
14  import com.jcorporate.expresso.core.registry.RequestRegistry;
15  import com.jcorporate.expresso.core.security.User;
16  import org.apache.log4j.Category;
17  import org.apache.log4j.Logger;
18  
19  import java.util.*;
20  
21  
22  /***
23   * Factory for determing the parts of each type of node.
24   */
25  public class PartsFactory {
26      public static final String DELIMITER = "|";
27      private static Logger slog = null;
28      private static Hashtable sHashOfPartArrays = new Hashtable();
29  
30      /***
31       * individual attributes hashed here
32       */
33      private static Hashtable sAttribHash = new Hashtable();
34      private static Hashtable sNodeTypeHash = new Hashtable();
35      private static Hashtable sFakeTypeHash = new Hashtable();
36  
37      /***
38       * put node types in RAM cache
39       */
40      static {
41          try {
42              NodeType nodeType = new NodeType(User.getAdmin());
43              List nodes = nodeType.searchAndRetrieveList();
44  
45              for (Iterator iter = nodes.iterator(); iter.hasNext();) {
46                  NodeType type = (NodeType) iter.next();
47                  addType(type);
48              }
49  
50              // only appropriate for dev. database
51              //            Populate.populateAllParts();
52          } catch (DBException e) {
53              e.printStackTrace();
54          }
55      }
56  
57      /***
58       * add a new type; typically, there will be no parts associated with new type,
59       * but an empty array will be added to hash
60       */
61      public static void addType(NodeType type) throws DBException {
62          sNodeTypeHash.put(type.getEntityName(), type);
63  
64          Part[] parts = type.getParts();
65          sHashOfPartArrays.put(type.getEntityName(), parts);
66  
67          for (int i = 0; i < parts.length; i++) {
68              Part part = parts[i];
69  
70              // add to univ. hash of all attributes
71              if (part.isOwnedAttribute() && (part.getPartType() != null)) {
72                  String key = getPartKey(type.getEntityName(), part.getPartType());
73  
74                  if (sAttribHash.get(key) != null) {
75                      getLogger().error("overwriting existing hashed Type with key: " +
76                              key);
77                  } else {
78                      sAttribHash.put(key, part);
79                  }
80  
81                  //System.out.println("adding attrib key: " + key);
82              }
83          }
84      }
85  
86      /***
87       * add a new fake type; fake types are just used for getting list of all types (for footer)
88       */
89      public static void addFakeType(NodeType type) throws DBException {
90          sFakeTypeHash.put(type.getEntityName(), type);
91      }
92  
93      private static String getPartKey(String parent, String partName) {
94          // use buf because parent may be null
95          StringBuffer buf = new StringBuffer();
96          buf.append(parent);
97          buf.append(DELIMITER);
98          buf.append(partName);
99          return buf.toString();
100     }
101 
102     /***
103      * @return a list of parts for paradigms, or empty array if not found; never null
104      */
105     public static Part[] getParts(String nodeType) {
106         Part[] result;
107         synchronized (sHashOfPartArrays) {
108             Part[] resultsToClone = (Part[]) sHashOfPartArrays.get(nodeType);
109 
110             if (resultsToClone == null) {
111                 result = new Part[0];
112             } else {
113                 result = new Part[resultsToClone.length];
114 
115                 for (int i = 0; i < resultsToClone.length; i++) {
116                     try {
117                         result[i] = (Part) resultsToClone[i].clone();
118                         result[i].setRequestingUser(RequestRegistry.getUser());
119                     } catch (CloneNotSupportedException ex) {
120                         throw new Error("Caught CloneNotSupportedException for a cloneable object: " + ex);
121                     }
122 
123                 }
124             }
125 
126 
127         }
128 
129         return result;
130     }
131 
132     /***
133      * necessary since the JSP doesn't know anything, but
134      * must iterate to display attributes and send back edits with some discernable
135      * connection between input text and attribute destination.
136      *
137      * @param type      type of node
138      * @param attribNum number of attribute in parts list of node
139      * @return name of attribute which corresponds to given type, num.  return null if cannot find
140      */
141     public static String getAttributeType(String type, int attribNum)
142             throws DBException {
143         Part[] parts = getParts(type);
144 
145         return parts[attribNum].getPartType();
146     }
147 
148     /***
149      * @return part corresponding to node, attrib params; null if not found
150      */
151     public static Part getAttribPart(String srcNodetype, String attribName) {
152         Part part = (Part) sAttribHash.get(getPartKey(srcNodetype, attribName));
153 
154         if (part == null) {
155             slog.error("cannot find object|attribute: " +
156                     getPartKey(srcNodetype, attribName));
157         }
158 
159         return part;
160     }
161 
162     /***
163      * @return array of parts that have picklists (i.e., the values for the part are chosen from a closed list, like the type of a MeasurementModel)
164      */
165     public static Part[] getPartsWithPicklists() throws DBException {
166         LinkedList list = new LinkedList();
167         Enumeration enumeration = sAttribHash.keys();
168 
169         while (enumeration.hasMoreElements()) {
170             String partkey = (String) enumeration.nextElement();
171             Part part = (Part) sAttribHash.get(partkey);
172 
173             if (part.hasPicklist()) {
174                 list.add(part);
175             }
176         }
177 
178         return (Part[]) list.toArray(new Part[list.size()]);
179     }
180 
181     /***
182      */
183     public static Hashtable getAllParts() {
184         return sHashOfPartArrays;
185     }
186 
187     /***
188      * @param relation relation for this part; pass in null for owned attributes
189      * @return first part which matches partType, or null if not found
190      */
191     public static Part getPart(String parentType, String partType,
192                                String relation) throws DBException {
193         Part result = null;
194 
195         Part[] parts = getParts(parentType);
196 
197         for (int i = 0; i < parts.length; i++) {
198             Part part = parts[i];
199 
200             if (part.getPartType().equals(partType)) {
201                 if (relation == null) {
202                     result = part;
203 
204                     break;
205                 } else {
206                     if (part.getNodeRelation().equals(relation)) {
207                         result = part;
208 
209                         break;
210                     }
211                 }
212             }
213         }
214 
215         if (result == null) {
216             getLogger().error("cannot find part with parent/type: " +
217                     parentType + "/" + partType);
218         }
219 
220         return result;
221     }
222 
223     /***
224      * after adding or deleting parts, call this
225      */
226     public static void refreshCache(String parentType)
227             throws DBException {
228         String dbcontext = DBConnection.DEFAULT_DB_CONTEXT_NAME; // overwrite from parts, below
229 
230         // first remove existing parts
231         Part[] oldparts = getParts(parentType);
232 
233         for (int i = 0; i < oldparts.length; i++) {
234             Part oldpart = oldparts[i];
235             dbcontext = oldpart.getDataContext();
236 
237             // add to univ. hash of all attributes
238             if (oldpart.isOwnedAttribute()) {
239                 String key = getPartKey(parentType, oldpart.getPartType());
240                 sAttribHash.remove(key);
241             }
242         }
243 
244         NodeType type = new NodeType(User.getAdmin(dbcontext));
245 
246         if (dbcontext != null) {
247             type.setDBName(dbcontext);
248         }
249 
250         type.setEntityName(parentType);
251 
252         if (!type.find()) {
253             // deleted
254             sNodeTypeHash.remove(parentType);
255         } else {
256             sNodeTypeHash.put(parentType, type);
257 
258             Part[] parts = type.getParts();
259             sHashOfPartArrays.put(parentType, parts);
260 
261             for (int i = 0; i < parts.length; i++) {
262                 Part part = parts[i];
263 
264                 // add to univ. hash of all attributes
265                 if (part.isOwnedAttribute() && (part.getPartType() != null)) {
266                     String key = getPartKey(parentType, part.getPartType());
267 
268                     // we expected to delete old ones, above, so give warning and overwrite
269                     if (sAttribHash.get(key) != null) {
270                         getLogger().error("unexpectedly overwriting existing, hashed Part with key: " +
271                                 key);
272                     }
273 
274                     sAttribHash.put(key, part);
275 
276                     //System.out.println("adding attrib key: " + key);
277                 }
278             }
279         }
280     }
281 
282     /***
283      * @return a nodetype for the given string, or null if not found
284      */
285     public static NodeType getEntity(String nodeType) {
286         return (NodeType) sNodeTypeHash.get(nodeType);
287     }
288 
289     /***
290      * @return list of REGISTERED NodeType objects.  this may exclude actual DB types
291      *         that are not registered with partFactory. this method is more efficent since it uses cache.
292      * @see NodeType#getAllTypes for a complete list of DB entries, though it is less efficient than this method
293      * @see #addType
294      * @see #getFakeEntities
295      */
296     public static TreeSet getEntities() {
297         return new TreeSet(sNodeTypeHash.values());
298     }
299 
300     /***
301      * @return array of fake node types.
302      * @see #addFakeType
303      */
304     public static ArrayList getFakeEntities() {
305         return new ArrayList(sFakeTypeHash.values());
306     }
307 
308     /***
309      * convenience for getting logger for current (sub) class
310      *
311      * @return Category for logging
312      */
313     public static Category getLogger() {
314         if (slog == null) {
315             slog = Logger.getLogger(PartsFactory.class.getName());
316         }
317 
318         return slog;
319     }
320 
321     /***
322      * convenience method to get part from ID; hits db, so not as effective as other methods which retrieve from hash table.
323      *
324      * @return part with given ID, or null if not found.
325      */
326     public static Part getPart(int partId) throws DBException {
327         Part part = new Part();
328         part.setPartId(partId);
329         part.find();
330         return part;
331     }
332 
333     /***
334      * convenience method to get part from ID; hits db, so not as effective as other methods which retrieve from hash table.
335      *
336      * @return part with given ID, or null if not found.
337      */
338     public static Part getPart(String partId) throws DBException {
339         Part part = new Part();
340         part.setPartId(partId);
341         part.find();
342         return part;
343     }
344 
345 }