001: /*
002: * $Id: ModelReader.java,v 1.5 2003/12/04 20:54:53 jonesde Exp $
003: *
004: * Copyright (c) 2001, 2002 The Open For Business Project - www.ofbiz.org
005: *
006: * Permission is hereby granted, free of charge, to any person obtaining a
007: * copy of this software and associated documentation files (the "Software"),
008: * to deal in the Software without restriction, including without limitation
009: * the rights to use, copy, modify, merge, publish, distribute, sublicense,
010: * and/or sell copies of the Software, and to permit persons to whom the
011: * Software is furnished to do so, subject to the following conditions:
012: *
013: * The above copyright notice and this permission notice shall be included
014: * in all copies or substantial portions of the Software.
015: *
016: * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
017: * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
018: * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
019: * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
020: * CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT
021: * OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR
022: * THE USE OR OTHER DEALINGS IN THE SOFTWARE.
023: */
024: package org.ofbiz.entity.model;
025:
026: import java.util.Collection;
027: import java.util.HashMap;
028: import java.util.Hashtable;
029: import java.util.Iterator;
030: import java.util.LinkedList;
031: import java.util.List;
032: import java.util.Map;
033:
034: import org.ofbiz.base.component.ComponentConfig;
035: import org.ofbiz.base.config.GenericConfigException;
036: import org.ofbiz.base.config.MainResourceHandler;
037: import org.ofbiz.base.config.ResourceHandler;
038: import org.ofbiz.entity.GenericEntityConfException;
039: import org.ofbiz.entity.GenericEntityException;
040: import org.ofbiz.entity.GenericModelException;
041: import org.ofbiz.entity.config.EntityConfigUtil;
042: import org.ofbiz.base.util.Debug;
043: import org.ofbiz.base.util.UtilCache;
044: import org.ofbiz.base.util.UtilTimer;
045: import org.ofbiz.base.util.UtilXml;
046: import org.w3c.dom.Document;
047: import org.w3c.dom.Element;
048: import org.w3c.dom.Node;
049:
050: /**
051: * Generic Entity - Entity Definition Reader
052: *
053: * @author <a href="mailto:jonesde@ofbiz.org">David E. Jones</a>
054: * @author <a href="mailto:jaz@ofbiz.org">Andy Zeneski</a>
055: * @version $Revision: 1.5 $
056: * @since 2.0
057: */
058: public class ModelReader {
059:
060: public static final String module = ModelReader.class.getName();
061: public static UtilCache readers = new UtilCache(
062: "entity.ModelReader", 0, 0);
063:
064: protected Map entityCache = null;
065:
066: protected int numEntities = 0;
067: protected int numViewEntities = 0;
068: protected int numFields = 0;
069: protected int numRelations = 0;
070:
071: protected String modelName;
072:
073: /** collection of filenames for entity definitions */
074: protected Collection entityResourceHandlers;
075:
076: /** contains a collection of entity names for each ResourceHandler, populated as they are loaded */
077: protected Map resourceHandlerEntities;
078:
079: /** for each entity contains a map to the ResourceHandler that the entity came from */
080: protected Map entityResourceHandlerMap;
081:
082: public static ModelReader getModelReader(String delegatorName)
083: throws GenericEntityException {
084: EntityConfigUtil.DelegatorInfo delegatorInfo = EntityConfigUtil
085: .getDelegatorInfo(delegatorName);
086:
087: if (delegatorInfo == null) {
088: throw new GenericEntityConfException(
089: "Could not find a delegator with the name "
090: + delegatorName);
091: }
092:
093: String tempModelName = delegatorInfo.entityModelReader;
094: ModelReader reader = (ModelReader) readers.get(tempModelName);
095:
096: if (reader == null) { // don't want to block here
097: synchronized (ModelReader.class) {
098: // must check if null again as one of the blocked threads can still enter
099: reader = (ModelReader) readers.get(tempModelName);
100: if (reader == null) {
101: reader = new ModelReader(tempModelName);
102: // preload caches...
103: reader.getEntityCache();
104: readers.put(tempModelName, reader);
105: }
106: }
107: }
108: return reader;
109: }
110:
111: public ModelReader(String modelName) throws GenericEntityException {
112: this .modelName = modelName;
113: entityResourceHandlers = new LinkedList();
114: resourceHandlerEntities = new HashMap();
115: entityResourceHandlerMap = new HashMap();
116:
117: EntityConfigUtil.EntityModelReaderInfo entityModelReaderInfo = EntityConfigUtil
118: .getEntityModelReaderInfo(modelName);
119:
120: if (entityModelReaderInfo == null) {
121: throw new GenericEntityConfException(
122: "Cound not find an entity-model-reader with the name "
123: + modelName);
124: }
125:
126: // get all of the main resource model stuff, ie specified in the entityengine.xml file
127: List resourceElements = entityModelReaderInfo.resourceElements;
128: Iterator resIter = resourceElements.iterator();
129: while (resIter.hasNext()) {
130: Element resourceElement = (Element) resIter.next();
131: ResourceHandler handler = new MainResourceHandler(
132: EntityConfigUtil.ENTITY_ENGINE_XML_FILENAME,
133: resourceElement);
134: entityResourceHandlers.add(handler);
135: }
136:
137: // get all of the component resource model stuff, ie specified in each ofbiz-component.xml file
138: List componentResourceInfos = ComponentConfig
139: .getAllEntityResourceInfos("model");
140: Iterator componentResourceInfoIter = componentResourceInfos
141: .iterator();
142: while (componentResourceInfoIter.hasNext()) {
143: ComponentConfig.EntityResourceInfo componentResourceInfo = (ComponentConfig.EntityResourceInfo) componentResourceInfoIter
144: .next();
145: if (modelName.equals(componentResourceInfo.readerName)) {
146: entityResourceHandlers.add(componentResourceInfo
147: .createResourceHandler());
148: }
149: }
150: }
151:
152: public Map getEntityCache() throws GenericEntityException {
153: if (entityCache == null) { // don't want to block here
154: synchronized (ModelReader.class) {
155: // must check if null again as one of the blocked threads can still enter
156: if (entityCache == null) { // now it's safe
157: numEntities = 0;
158: numViewEntities = 0;
159: numFields = 0;
160: numRelations = 0;
161:
162: entityCache = new HashMap();
163: List tempViewEntityList = new LinkedList();
164:
165: UtilTimer utilTimer = new UtilTimer();
166:
167: Iterator rhIter = entityResourceHandlers.iterator();
168: while (rhIter.hasNext()) {
169: ResourceHandler entityResourceHandler = (ResourceHandler) rhIter
170: .next();
171:
172: // utilTimer.timerString("Before getDocument in file " + entityFileName);
173: Document document = null;
174:
175: try {
176: document = entityResourceHandler
177: .getDocument();
178: } catch (GenericConfigException e) {
179: throw new GenericEntityConfException(
180: "Error getting document from resource handler",
181: e);
182: }
183: if (document == null) {
184: throw new GenericEntityConfException(
185: "Could not get document for "
186: + entityResourceHandler
187: .toString());
188: }
189:
190: Hashtable docElementValues = null;
191: docElementValues = new Hashtable();
192:
193: // utilTimer.timerString("Before getDocumentElement in " + entityResourceHandler.toString());
194: Element docElement = document
195: .getDocumentElement();
196:
197: if (docElement == null) {
198: entityCache = null;
199: return null;
200: }
201: docElement.normalize();
202: Node curChild = docElement.getFirstChild();
203:
204: int i = 0;
205:
206: if (curChild != null) {
207: utilTimer
208: .timerString("Before start of entity loop in "
209: + entityResourceHandler
210: .toString());
211: do {
212: boolean isEntity = "entity"
213: .equals(curChild.getNodeName());
214: boolean isViewEntity = "view-entity"
215: .equals(curChild.getNodeName());
216:
217: if ((isEntity || isViewEntity)
218: && curChild.getNodeType() == Node.ELEMENT_NODE) {
219: i++;
220: Element curEntity = (Element) curChild;
221: String entityName = UtilXml
222: .checkEmpty(curEntity
223: .getAttribute("entity-name"));
224:
225: // add entityName to appropriate resourceHandlerEntities collection
226: Collection resourceHandlerEntityNames = (Collection) resourceHandlerEntities
227: .get(entityResourceHandler);
228:
229: if (resourceHandlerEntityNames == null) {
230: resourceHandlerEntityNames = new LinkedList();
231: resourceHandlerEntities
232: .put(
233: entityResourceHandler,
234: resourceHandlerEntityNames);
235: }
236: resourceHandlerEntityNames
237: .add(entityName);
238:
239: // check to see if entity with same name has already been read
240: if (entityCache
241: .containsKey(entityName)) {
242: Debug
243: .logWarning(
244: "WARNING: Entity "
245: + entityName
246: + " is defined more than once, most recent will over-write "
247: + "previous definition(s)",
248: module);
249: Debug
250: .logWarning(
251: "WARNING: Entity "
252: + entityName
253: + " was found in "
254: + entityResourceHandler
255: + ", but was already defined in "
256: + entityResourceHandlerMap
257: .get(
258: entityName)
259: .toString(),
260: module);
261: }
262:
263: // add entityName, entityFileName pair to entityResourceHandlerMap map
264: entityResourceHandlerMap.put(
265: entityName,
266: entityResourceHandler);
267:
268: // utilTimer.timerString(" After entityEntityName -- " + i + " --");
269: // ModelEntity entity = createModelEntity(curEntity, docElement, utilTimer, docElementValues);
270:
271: ModelEntity entity = null;
272:
273: if (isEntity) {
274: entity = createModelEntity(
275: curEntity, docElement,
276: null, docElementValues);
277: } else {
278: entity = createModelViewEntity(
279: curEntity, docElement,
280: null, docElementValues);
281: // put the view entity in a list to get ready for the second pass to populate fields...
282: tempViewEntityList.add(entity);
283: }
284:
285: // utilTimer.timerString(" After createModelEntity -- " + i + " --");
286: if (entity != null) {
287: entityCache.put(entityName,
288: entity);
289: // utilTimer.timerString(" After entityCache.put -- " + i + " --");
290: if (isEntity) {
291: if (Debug.verboseOn())
292: Debug
293: .logVerbose(
294: "-- [Entity]: #"
295: + i
296: + ": "
297: + entityName,
298: module);
299: } else {
300: if (Debug.verboseOn())
301: Debug
302: .logVerbose(
303: "-- [ViewEntity]: #"
304: + i
305: + ": "
306: + entityName,
307: module);
308: }
309: } else {
310: Debug
311: .logWarning(
312: "-- -- ENTITYGEN ERROR:getModelEntity: Could not create "
313: + "entity for entityName: "
314: + entityName,
315: module);
316: }
317:
318: }
319: } while ((curChild = curChild
320: .getNextSibling()) != null);
321: } else {
322: Debug.logWarning("No child nodes found.",
323: module);
324: }
325: utilTimer.timerString("Finished "
326: + entityResourceHandler.toString()
327: + " - Total Entities: " + i
328: + " FINISHED");
329: }
330:
331: // do a pass on all of the view entities now that all of the entities have
332: // loaded and populate the fields
333: for (int velInd = 0; velInd < tempViewEntityList
334: .size(); velInd++) {
335: ModelViewEntity curViewEntity = (ModelViewEntity) tempViewEntityList
336: .get(velInd);
337: curViewEntity.populateFields(this );
338: }
339:
340: Debug.log(
341: "FINISHED LOADING ENTITIES - ALL FILES; #Entities="
342: + numEntities + " #ViewEntities="
343: + numViewEntities + " #Fields="
344: + numFields + " #Relationships="
345: + numRelations, module);
346: }
347: }
348: }
349: return entityCache;
350: }
351:
352: /** rebuilds the resourceHandlerEntities Map of Collections based on the current
353: * entityResourceHandlerMap Map, must be done whenever a manual change is made to the
354: * entityResourceHandlerMap Map after the initial load to make them consistent again.
355: */
356: public void rebuildResourceHandlerEntities() {
357: resourceHandlerEntities = new HashMap();
358: Iterator entityResourceIter = entityResourceHandlerMap
359: .entrySet().iterator();
360:
361: while (entityResourceIter.hasNext()) {
362: Map.Entry entry = (Map.Entry) entityResourceIter.next();
363: // add entityName to appropriate resourceHandlerEntities collection
364: Collection resourceHandlerEntityNames = (Collection) resourceHandlerEntities
365: .get(entry.getValue());
366:
367: if (resourceHandlerEntityNames == null) {
368: resourceHandlerEntityNames = new LinkedList();
369: resourceHandlerEntities.put(entry.getValue(),
370: resourceHandlerEntityNames);
371: }
372: resourceHandlerEntityNames.add(entry.getKey());
373: }
374: }
375:
376: public Iterator getResourceHandlerEntitiesKeyIterator() {
377: if (resourceHandlerEntities == null)
378: return null;
379: return resourceHandlerEntities.keySet().iterator();
380: }
381:
382: public Collection getResourceHandlerEntities(
383: ResourceHandler resourceHandler) {
384: if (resourceHandlerEntities == null)
385: return null;
386: return (Collection) resourceHandlerEntities
387: .get(resourceHandler);
388: }
389:
390: public void addEntityToResourceHandler(String entityName,
391: String loaderName, String location) {
392: entityResourceHandlerMap.put(entityName,
393: new MainResourceHandler(
394: EntityConfigUtil.ENTITY_ENGINE_XML_FILENAME,
395: loaderName, location));
396: }
397:
398: public ResourceHandler getEntityResourceHandler(String entityName) {
399: return (ResourceHandler) entityResourceHandlerMap
400: .get(entityName);
401: }
402:
403: /** Gets an Entity object based on a definition from the specified XML Entity descriptor file.
404: * @param entityName The entityName of the Entity definition to use.
405: * @return An Entity object describing the specified entity of the specified descriptor file.
406: */
407: public ModelEntity getModelEntity(String entityName)
408: throws GenericEntityException {
409: Map ec = getEntityCache();
410:
411: if (ec == null) {
412: throw new GenericEntityConfException(
413: "ERROR: Unable to load Entity Cache");
414: }
415:
416: ModelEntity modelEntity = (ModelEntity) ec.get(entityName);
417:
418: if (modelEntity == null) {
419: throw new GenericModelException(
420: "Could not find definition for entity name "
421: + entityName);
422: }
423: return modelEntity;
424: }
425:
426: public ModelEntity getModelEntityNoCheck(String entityName) {
427: Map ec = null;
428: try {
429: ec = getEntityCache();
430: } catch (GenericEntityException e) {
431: Debug.logError(e, "Error getting entity cache", module);
432: }
433: if (ec == null) {
434: return null;
435: }
436: ModelEntity modelEntity = (ModelEntity) ec.get(entityName);
437: return modelEntity;
438: }
439:
440: /** Creates a Iterator with the entityName of each Entity defined in the specified XML Entity Descriptor file.
441: * @return A Iterator of entityName Strings
442: */
443: public Iterator getEntityNamesIterator()
444: throws GenericEntityException {
445: Collection collection = getEntityNames();
446:
447: if (collection != null) {
448: return collection.iterator();
449: } else {
450: return null;
451: }
452: }
453:
454: /** Creates a Collection with the entityName of each Entity defined in the specified XML Entity Descriptor file.
455: * @return A Collection of entityName Strings
456: */
457: public Collection getEntityNames() throws GenericEntityException {
458: Map ec = getEntityCache();
459:
460: if (ec == null) {
461: throw new GenericEntityConfException(
462: "ERROR: Unable to load Entity Cache");
463: }
464: return ec.keySet();
465: }
466:
467: ModelEntity createModelEntity(Element entityElement,
468: Element docElement, UtilTimer utilTimer,
469: Hashtable docElementValues) {
470: if (entityElement == null)
471: return null;
472: this .numEntities++;
473: ModelEntity entity = new ModelEntity(this , entityElement,
474: docElement, utilTimer, docElementValues);
475:
476: return entity;
477: }
478:
479: ModelEntity createModelViewEntity(Element entityElement,
480: Element docElement, UtilTimer utilTimer,
481: Hashtable docElementValues) {
482: if (entityElement == null)
483: return null;
484: this .numViewEntities++;
485: ModelViewEntity entity = new ModelViewEntity(this ,
486: entityElement, docElement, utilTimer, docElementValues);
487:
488: return entity;
489: }
490:
491: public ModelRelation createRelation(ModelEntity entity,
492: Element relationElement) {
493: this .numRelations++;
494: ModelRelation relation = new ModelRelation(entity,
495: relationElement);
496:
497: return relation;
498: }
499:
500: public ModelField findModelField(ModelEntity entity,
501: String fieldName) {
502: for (int i = 0; i < entity.fields.size(); i++) {
503: ModelField field = (ModelField) entity.fields.get(i);
504:
505: if (field.name.compareTo(fieldName) == 0) {
506: return field;
507: }
508: }
509: return null;
510: }
511:
512: public ModelField createModelField(String name, String type,
513: String colName, boolean isPk) {
514: this .numFields++;
515: ModelField field = new ModelField(name, type, colName, isPk);
516: return field;
517: }
518:
519: public ModelField createModelField(Element fieldElement,
520: Element docElement, Hashtable docElementValues) {
521: if (fieldElement == null) {
522: return null;
523: }
524:
525: this .numFields++;
526: ModelField field = new ModelField(fieldElement);
527: return field;
528: }
529: }
|