1
2
3
4
5
6
7
8
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
51
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
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
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
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;
229
230
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
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
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
265 if (part.isOwnedAttribute() && (part.getPartType() != null)) {
266 String key = getPartKey(parentType, part.getPartType());
267
268
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
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 }