KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > apache > cayenne > wocompat > EOModelHelper


1 /*****************************************************************
2  * Licensed to the Apache Software Foundation (ASF) under one
3  * or more contributor license agreements. See the NOTICE file
4  * distributed with this work for additional information
5  * regarding copyright ownership. The ASF licenses this file
6  * to you under the Apache License, Version 2.0 (the
7  * "License"); you may not use this file except in compliance
8  * with the License. You may obtain a copy of the License at
9  *
10  * http://www.apache.org/licenses/LICENSE-2.0
11  *
12  * Unless required by applicable law or agreed to in writing,
13  * software distributed under the License is distributed on an
14  * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
15  * KIND, either express or implied. See the License for the
16  * specific language governing permissions and limitations
17  * under the License.
18  ****************************************************************/

19
20
21 package org.apache.cayenne.wocompat;
22
23 import java.io.IOException JavaDoc;
24 import java.io.InputStream JavaDoc;
25 import java.math.BigDecimal JavaDoc;
26 import java.net.URL JavaDoc;
27 import java.util.ArrayList JavaDoc;
28 import java.util.Collections JavaDoc;
29 import java.util.HashMap JavaDoc;
30 import java.util.Iterator JavaDoc;
31 import java.util.List JavaDoc;
32 import java.util.Map JavaDoc;
33
34 import org.apache.commons.collections.IteratorUtils;
35 import org.apache.cayenne.map.DataMap;
36 import org.apache.cayenne.util.ResourceLocator;
37 import org.apache.cayenne.wocompat.parser.Parser;
38
39 /**
40  * Helper class used by EOModelProcessor. EOModelHelper loads an EOModel from the
41  * specified location and gives its users access to the untyped EOModel information.
42  */

43 public class EOModelHelper {
44
45     private static final ResourceLocator locator = new ResourceLocator();
46
47     private Parser plistParser = new Parser();
48     protected URL JavaDoc modelUrl;
49     protected Map JavaDoc entityIndex;
50     protected Map JavaDoc entityClassIndex;
51     protected Map JavaDoc entityQueryIndex;
52     protected Map JavaDoc entityClientClassIndex;
53     protected DataMap dataMap;
54     private Map JavaDoc prototypeValues;
55
56     static {
57         // configure locator
58
locator.setSkipClasspath(false);
59         locator.setSkipCurrentDirectory(false);
60         locator.setSkipHomeDirectory(true);
61         locator.setSkipAbsolutePath(false);
62     }
63
64     /**
65      * Creates helper instance and tries to locate EOModel and load index file.
66      */

67     public EOModelHelper(String JavaDoc path) throws Exception JavaDoc {
68
69         this.modelUrl = findModelUrl(path);
70         this.dataMap = new DataMap(findModelName(path));
71
72         // load index file
73
List JavaDoc modelIndex = (List JavaDoc) loadModelIndex().get("entities");
74
75         // load entity indices
76
entityIndex = new HashMap JavaDoc();
77         entityClassIndex = new HashMap JavaDoc();
78         entityClientClassIndex = new HashMap JavaDoc();
79         entityQueryIndex = new HashMap JavaDoc();
80
81         Iterator JavaDoc it = modelIndex.iterator();
82         while (it.hasNext()) {
83             Map JavaDoc info = (Map JavaDoc) it.next();
84             String JavaDoc name = (String JavaDoc) info.get("name");
85
86             entityIndex.put(name, loadEntityIndex(name));
87             entityQueryIndex.put(name, loadQueryIndex(name));
88             entityClassIndex.put(name, info.get("className"));
89             Map JavaDoc entityPlistMap = entityPListMap(name);
90
91             // get client class information
92
Map JavaDoc internalInfo = (Map JavaDoc) entityPlistMap.get("internalInfo");
93
94             if (internalInfo != null) {
95                 String JavaDoc clientClassName = (String JavaDoc) internalInfo
96                         .get("_javaClientClassName");
97                 entityClientClassIndex.put(name, clientClassName);
98             }
99         }
100
101         it = modelIndex.iterator();
102         while (it.hasNext()) {
103             Map JavaDoc info = (Map JavaDoc) it.next();
104             String JavaDoc name = (String JavaDoc) info.get("name");
105             Map JavaDoc entityPlistMap = entityPListMap(name);
106             List JavaDoc classProperties = (List JavaDoc) entityPlistMap.get("classProperties");
107             if(classProperties == null) {
108                 classProperties = Collections.EMPTY_LIST;
109             }
110
111             // get client class information
112
Map JavaDoc internalInfo = (Map JavaDoc) entityPlistMap.get("internalInfo");
113
114             List JavaDoc clientClassProperties = (internalInfo != null) ? (List JavaDoc) internalInfo
115                     .get("_clientClassPropertyNames") : null;
116
117             // guard against no internal info and no client class properties
118
if (clientClassProperties == null) {
119                 clientClassProperties = Collections.EMPTY_LIST;
120             }
121
122             // there is a bug in EOModeler it sometimes keeps outdated properties in
123
// the client property list. This removes them
124
clientClassProperties.retainAll(classProperties);
125
126             // remove all properties from the entity properties that are already defined
127
// in
128
// a potential parent class.
129
String JavaDoc parentEntity = (String JavaDoc) entityPlistMap.get("parent");
130             while (parentEntity != null) {
131                 Map JavaDoc parentEntityPListMap = entityPListMap(parentEntity);
132                 List JavaDoc parentClassProps = (List JavaDoc) parentEntityPListMap
133                         .get("classProperties");
134                 classProperties.removeAll(parentClassProps);
135                 // get client class information of parent
136
Map JavaDoc parentInternalInfo = (Map JavaDoc) parentEntityPListMap.get("internalInfo");
137
138                 if (parentInternalInfo != null) {
139                     List JavaDoc parentClientClassProps = (List JavaDoc) parentInternalInfo
140                             .get("_clientClassPropertyNames");
141                     clientClassProperties.removeAll(parentClientClassProps);
142                 }
143
144                 parentEntity = (String JavaDoc) parentEntityPListMap.get("parent");
145             }
146
147             // put back processed properties to the map
148
entityPlistMap.put("classProperties", classProperties);
149             // add client classes directly for easier access
150
entityPlistMap.put("clientClassProperties", clientClassProperties);
151         }
152     }
153
154     /**
155      * Performs Objective C data types conversion to Java types.
156      *
157      * @since 1.1
158      * @return String representation for Java type corresponding to String representation
159      * of Objective C type.
160      */

161     public String JavaDoc javaTypeForEOModelerType(String JavaDoc valueClassName, String JavaDoc valueType) {
162         if (valueClassName == null) {
163             return null;
164         }
165
166         if (valueClassName.equals("NSString")) {
167             return String JavaDoc.class.getName();
168         }
169
170         if (valueClassName.equals("NSNumber")) {
171             Class JavaDoc numericClass = numericAttributeClass(valueType);
172             return (numericClass != null) ? numericClass.getName() : Number JavaDoc.class
173                     .getName();
174         }
175
176         if (valueClassName.equals("NSCalendarDate"))
177             return "java.sql.Timestamp";
178
179         if (valueClassName.equals("NSDecimalNumber")) {
180             Class JavaDoc numericClass = numericAttributeClass(valueType);
181             return (numericClass != null) ? numericClass.getName() : BigDecimal JavaDoc.class
182                     .getName();
183         }
184
185         if (valueClassName.equals("NSData"))
186             return "byte[]";
187
188         // don't know what the class is mapped to...
189
// do some minimum sanity check and use as is
190
try {
191             return Class.forName(valueClassName).getName();
192         }
193         catch (ClassNotFoundException JavaDoc aClassNotFoundException) {
194             try {
195                 return Class.forName("java.lang." + valueClassName).getName();
196             }
197             catch (ClassNotFoundException JavaDoc anotherClassNotFoundException) {
198                 try {
199                     return Class.forName("java.util." + valueClassName).getName();
200                 }
201                 catch (ClassNotFoundException JavaDoc yetAnotherClassNotFoundException) {
202                     try {
203                         return ClassLoader.getSystemClassLoader().loadClass(
204                                 valueClassName).getName();
205                     }
206                     catch (ClassNotFoundException JavaDoc e) {
207                         // likely a custom class
208
return valueClassName;
209                     }
210                 }
211             }
212         }
213     }
214
215     /**
216      * @since 1.1
217      */

218     // TODO: create a lookup map, maybe XML-loaded...
219
protected Class JavaDoc numericAttributeClass(String JavaDoc valueType) {
220         if (valueType == null) {
221             return null;
222         } else if ("b".equals(valueType)) {
223             return Byte JavaDoc.class;
224         } else if ("s".equals(valueType)) {
225             return Short JavaDoc.class;
226         } else if ("i".equals(valueType)) {
227             return Integer JavaDoc.class;
228         } else if ("l".equals(valueType)) {
229             return Long JavaDoc.class;
230         } else if ("f".equals(valueType)) {
231             return Float JavaDoc.class;
232         } else if ("d".equals(valueType)) {
233             return Double JavaDoc.class;
234         } else if ("B".equals(valueType)) {
235             return BigDecimal JavaDoc.class;
236         } else if ("c".equals(valueType)) {
237             return Boolean JavaDoc.class;
238         } else {
239             return null;
240         }
241     }
242
243     /** Returns a DataMap associated with this helper. */
244     public DataMap getDataMap() {
245         return dataMap;
246     }
247
248     /** Returns EOModel location as URL. */
249     public URL JavaDoc getModelUrl() {
250         return modelUrl;
251     }
252
253     /**
254      * Returns an iterator of model names.
255      */

256     public Iterator JavaDoc modelNames() {
257         return entityClassIndex.keySet().iterator();
258     }
259     
260     /**
261      * Returns a list of model entity names.
262      *
263      * @since 1.1
264      */

265     public List JavaDoc modelNamesAsList() {
266         return new ArrayList JavaDoc(entityClassIndex.keySet());
267     }
268
269     public Map JavaDoc getPrototypeAttributeMapFor(String JavaDoc aPrototypeAttributeName) {
270         if (prototypeValues == null) {
271
272             Map JavaDoc eoPrototypesEntityMap = this.entityPListMap("EOPrototypes");
273
274             // no prototypes
275
if (eoPrototypesEntityMap == null) {
276                 prototypeValues = Collections.EMPTY_MAP;
277             } else {
278                 List JavaDoc eoPrototypeAttributes = (List JavaDoc) eoPrototypesEntityMap
279                         .get("attributes");
280
281                 prototypeValues = new HashMap JavaDoc();
282                 Iterator JavaDoc it = eoPrototypeAttributes.iterator();
283                 while (it.hasNext()) {
284                     Map JavaDoc attrMap = (Map JavaDoc) it.next();
285
286                     String JavaDoc attrName = (String JavaDoc) attrMap.get("name");
287
288                     // TODO: why are we copying the original map? can we just use it as is?
289
Map JavaDoc prototypeAttrMap = new HashMap JavaDoc();
290                     prototypeValues.put(attrName, prototypeAttrMap);
291
292                     prototypeAttrMap.put("name", attrMap.get("name"));
293                     prototypeAttrMap.put("prototypeName", attrMap.get("prototypeName"));
294                     prototypeAttrMap.put("columnName", attrMap.get("columnName"));
295                     prototypeAttrMap.put("valueClassName", attrMap.get("valueClassName"));
296                     prototypeAttrMap.put("width", attrMap.get("width"));
297                     prototypeAttrMap.put("allowsNull", attrMap.get("allowsNull"));
298                     prototypeAttrMap.put("scale", attrMap.get("scale"));
299                     prototypeAttrMap.put("valueType", attrMap.get("valueType"));
300                 }
301             }
302         }
303
304         Map JavaDoc aMap = (Map JavaDoc) prototypeValues.get(aPrototypeAttributeName);
305         if (null == aMap)
306             aMap = Collections.EMPTY_MAP;
307
308         return aMap;
309     }
310
311     /** Returns an info map for the entity called <code>entityName</code>. */
312     public Map JavaDoc entityPListMap(String JavaDoc entityName) {
313         return (Map JavaDoc) entityIndex.get(entityName);
314     }
315
316     /**
317      * Returns the iterator over EOFetchSpecification names for a given entity.
318      *
319      * @since 1.1
320      */

321     public Iterator JavaDoc queryNames(String JavaDoc entityName) {
322         Map JavaDoc queryPlist = (Map JavaDoc) entityQueryIndex.get(entityName);
323         if (queryPlist == null || queryPlist.isEmpty()) {
324             return IteratorUtils.EMPTY_ITERATOR;
325         }
326
327         return queryPlist.keySet().iterator();
328     }
329
330     /**
331      * Returns a map containing EOFetchSpecification information for entity name and query
332      * name. Returns null if no such query is found.
333      *
334      * @since 1.1
335      */

336     public Map JavaDoc queryPListMap(String JavaDoc entityName, String JavaDoc queryName) {
337         Map JavaDoc queryPlist = (Map JavaDoc) entityQueryIndex.get(entityName);
338         if (queryPlist == null || queryPlist.isEmpty()) {
339             return null;
340         }
341
342         return (Map JavaDoc) queryPlist.get(queryName);
343     }
344
345     public String JavaDoc entityClass(String JavaDoc entityName, boolean getClientClass) {
346         if (getClientClass) {
347             return (String JavaDoc) entityClientClassIndex.get(entityName);
348         } else {
349             return (String JavaDoc) entityClassIndex.get(entityName);
350         }
351     }
352
353     /** Loads EOModel index and returns it as a map. */
354     protected Map JavaDoc loadModelIndex() throws Exception JavaDoc {
355         InputStream JavaDoc indexIn = openIndexStream();
356         try {
357             plistParser.ReInit(indexIn);
358             return (Map JavaDoc) plistParser.propertyList();
359         }
360         finally {
361             indexIn.close();
362         }
363     }
364
365     /**
366      * Loads EOEntity information and returns it as a map.
367      */

368     protected Map JavaDoc loadEntityIndex(String JavaDoc entityName) throws Exception JavaDoc {
369         InputStream JavaDoc entIn = openEntityStream(entityName);
370         try {
371             plistParser.ReInit(entIn);
372             return (Map JavaDoc) plistParser.propertyList();
373         }
374         finally {
375             entIn.close();
376         }
377     }
378
379     /**
380      * Loads EOFetchSpecification information and returns it as a map.
381      */

382     protected Map JavaDoc loadQueryIndex(String JavaDoc entityName) throws Exception JavaDoc {
383         InputStream JavaDoc queryIn = null;
384
385         // catch file open exceptions since not all entities have query files....
386
try {
387             queryIn = openQueryStream(entityName);
388         }
389         catch (IOException JavaDoc ioex) {
390             return Collections.EMPTY_MAP;
391         }
392
393         try {
394             plistParser.ReInit(queryIn);
395             return (Map JavaDoc) plistParser.propertyList();
396         }
397         finally {
398             queryIn.close();
399         }
400     }
401
402     /** Returns EOModel name based on its path. */
403     protected String JavaDoc findModelName(String JavaDoc path) {
404         // strip trailing slashes
405
if (path.endsWith("/") || path.endsWith("\\")) {
406             path = path.substring(0, path.length() - 1);
407         }
408
409         // strip path components
410
int i1 = path.lastIndexOf("/");
411         int i2 = path.lastIndexOf("\\");
412         int i = (i1 > i2) ? i1 : i2;
413         if (i >= 0) {
414             path = path.substring(i + 1);
415         }
416
417         // strip .eomodeld suffix
418
if (path.endsWith(".eomodeld")) {
419             path = path.substring(0, path.length() - ".eomodeld".length());
420         }
421
422         return path;
423     }
424
425     /**
426      * Returns a URL of the EOModel directory. Throws exception if it can't be found.
427      */

428     protected URL JavaDoc findModelUrl(String JavaDoc path) {
429         if (!path.endsWith(".eomodeld")) {
430             path += ".eomodeld";
431         }
432
433         URL JavaDoc base = locator.findDirectoryResource(path);
434         if (base == null) {
435             throw new IllegalArgumentException JavaDoc("Can't find EOModel: " + path);
436         }
437         return base;
438     }
439
440     /**
441      * Returns InputStream to read an EOModel index file.
442      */

443     protected InputStream JavaDoc openIndexStream() throws Exception JavaDoc {
444         return new URL JavaDoc(modelUrl, "index.eomodeld").openStream();
445     }
446
447     /**
448      * Returns InputStream to read an EOEntity plist file.
449      *
450      * @param entityName
451      * name of EOEntity to be loaded.
452      * @return InputStream to read an EOEntity plist file or null if
453      * <code>entityname.plist</code> file can not be located.
454      */

455     protected InputStream JavaDoc openEntityStream(String JavaDoc entityName) throws Exception JavaDoc {
456         return new URL JavaDoc(modelUrl, entityName + ".plist").openStream();
457     }
458
459     /**
460      * Returns InputStream to read an EOFetchSpecification plist file.
461      *
462      * @param entityName
463      * name of EOEntity to be loaded.
464      * @return InputStream to read an EOEntity plist file or null if
465      * <code>entityname.plist</code> file can not be located.
466      */

467     protected InputStream JavaDoc openQueryStream(String JavaDoc entityName) throws Exception JavaDoc {
468         return new URL JavaDoc(modelUrl, entityName + ".fspec").openStream();
469     }
470 }
471
Popular Tags