KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > ofbiz > entity > GenericDelegator


1 /*
2  * $Id: GenericDelegator.java 7003 2006-03-16 15:40:40Z jaz $
3  *
4  * Copyright (c) 2001-2005 The Open For Business Project - www.ofbiz.org
5  *
6  * Permission is hereby granted, free of charge, to any person obtaining a
7  * copy of this software and associated documentation files (the "Software"),
8  * to deal in the Software without restriction, including without limitation
9  * the rights to use, copy, modify, merge, publish, distribute, sublicense,
10  * and/or sell copies of the Software, and to permit persons to whom the
11  * Software is furnished to do so, subject to the following conditions:
12  *
13  * The above copyright notice and this permission notice shall be included
14  * in all copies or substantial portions of the Software.
15  *
16  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
17  * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
18  * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
19  * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
20  * CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT
21  * OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR
22  * THE USE OR OTHER DEALINGS IN THE SOFTWARE.
23  *
24  */

25 package org.ofbiz.entity;
26
27 import java.io.FileNotFoundException JavaDoc;
28 import java.io.IOException JavaDoc;
29 import java.net.URL JavaDoc;
30 import java.util.Collection JavaDoc;
31 import java.util.Iterator JavaDoc;
32 import java.util.List JavaDoc;
33 import java.util.Map JavaDoc;
34 import java.util.Set JavaDoc;
35 import java.util.TreeSet JavaDoc;
36 import javax.xml.parsers.ParserConfigurationException JavaDoc;
37
38 import javolution.util.FastList;
39 import javolution.util.FastMap;
40 import org.w3c.dom.Document JavaDoc;
41 import org.w3c.dom.Element JavaDoc;
42 import org.w3c.dom.Node JavaDoc;
43 import org.xml.sax.SAXException JavaDoc;
44
45 import org.ofbiz.base.util.Debug;
46 import org.ofbiz.base.util.UtilFormatOut;
47 import org.ofbiz.base.util.UtilMisc;
48 import org.ofbiz.base.util.UtilValidate;
49 import org.ofbiz.base.util.UtilXml;
50 import org.ofbiz.base.util.cache.CacheLine;
51 import org.ofbiz.base.util.cache.UtilCache;
52 import org.ofbiz.entity.cache.Cache;
53 import org.ofbiz.entity.condition.EntityCondition;
54 import org.ofbiz.entity.condition.EntityConditionList;
55 import org.ofbiz.entity.condition.EntityExpr;
56 import org.ofbiz.entity.condition.EntityFieldMap;
57 import org.ofbiz.entity.condition.EntityOperator;
58 import org.ofbiz.entity.config.DatasourceInfo;
59 import org.ofbiz.entity.config.DelegatorInfo;
60 import org.ofbiz.entity.config.EntityConfigUtil;
61 import org.ofbiz.entity.datasource.GenericHelper;
62 import org.ofbiz.entity.datasource.GenericHelperFactory;
63 import org.ofbiz.entity.eca.EntityEcaHandler;
64 import org.ofbiz.entity.model.*;
65 import org.ofbiz.entity.serialize.SerializeException;
66 import org.ofbiz.entity.serialize.XmlSerializer;
67 import org.ofbiz.entity.transaction.GenericTransactionException;
68 import org.ofbiz.entity.transaction.TransactionUtil;
69 import org.ofbiz.entity.util.DistributedCacheClear;
70 import org.ofbiz.entity.util.EntityCrypto;
71 import org.ofbiz.entity.util.EntityFindOptions;
72 import org.ofbiz.entity.util.EntityListIterator;
73 import org.ofbiz.entity.util.SequenceUtil;
74
75 /**
76  * Generic Data Source Delegator Class
77  *
78  * @author <a HREF="mailto:jonesde@ofbiz.org">David E. Jones</a>
79  * @author <a HREF="mailto:chris_maurer@altavista.com">Chris Maurer</a>
80  * @author <a HREF="mailto:jaz@ofbiz.org">Andy Zeneski</a
81  * @version $Rev: 7003 $
82  * @since 1.0
83  */

84 public class GenericDelegator implements DelegatorInterface {
85
86     public static final String JavaDoc module = GenericDelegator.class.getName();
87
88     /** set this to true for better performance; set to false to be able to reload definitions at runtime throught the cache manager */
89     public static final boolean keepLocalReaders = true;
90     protected ModelReader modelReader = null;
91     protected ModelGroupReader modelGroupReader = null;
92
93     /** This flag is only here for lower level technical testing, it shouldn't be user configurable (or at least I don't think so yet); when true all operations without a transaction will be wrapped in one; seems to be necessary for some (all?) XA aware connection pools, and should improve overall stability and consistency */
94     public static final boolean alwaysUseTransaction = true;
95
96     /** the delegatorCache will now be a HashMap, allowing reload of definitions,
97      * but the delegator will always be the same object for the given name */

98     protected static Map JavaDoc delegatorCache = FastMap.newInstance();
99     protected String JavaDoc delegatorName = null;
100     protected DelegatorInfo delegatorInfo = null;
101
102     protected Cache cache = null;
103
104     // keeps a list of field key sets used in the by and cache, a Set (of Sets of fieldNames) for each entityName
105
protected Map JavaDoc andCacheFieldSets = FastMap.newInstance();
106
107     protected DistributedCacheClear distributedCacheClear = null;
108     protected EntityEcaHandler entityEcaHandler = null;
109     protected SequenceUtil sequencer = null;
110     protected EntityCrypto crypto = null;
111
112     public static GenericDelegator getGenericDelegator(String JavaDoc delegatorName) {
113         if (delegatorName == null) {
114             delegatorName = "default";
115             Debug.logWarning("Got a getGenericDelegator call with a null delegatorName, assuming default for the name.", module);
116         }
117         GenericDelegator delegator = (GenericDelegator) delegatorCache.get(delegatorName);
118
119         if (delegator == null) {
120             synchronized (GenericDelegator.class) {
121                 // must check if null again as one of the blocked threads can still enter
122
delegator = (GenericDelegator) delegatorCache.get(delegatorName);
123                 if (delegator == null) {
124                     if (Debug.infoOn()) Debug.logInfo("Creating new delegator [" + delegatorName + "] (" + Thread.currentThread().getName() + ")", module);
125                     //Debug.logInfo(new Exception(), "Showing stack where new delegator is being created...", module);
126
try {
127                         delegator = new GenericDelegator(delegatorName);
128                     } catch (GenericEntityException e) {
129                         Debug.logError(e, "Error creating delegator", module);
130                     }
131                     if (delegator != null) {
132                         delegatorCache.put(delegatorName, delegator);
133                     } else {
134                         Debug.logError("Could not create delegator with name " + delegatorName + ", constructor failed (got null value) not sure why/how.", module);
135                     }
136                 }
137             }
138         }
139         return delegator;
140     }
141
142     /** Only allow creation through the factory method */
143     protected GenericDelegator() {}
144
145     /** Only allow creation through the factory method */
146     protected GenericDelegator(String JavaDoc delegatorName) throws GenericEntityException {
147         //if (Debug.infoOn()) Debug.logInfo("Creating new Delegator with name \"" + delegatorName + "\".", module);
148

149         this.delegatorName = delegatorName;
150         if (keepLocalReaders) {
151             modelReader = ModelReader.getModelReader(delegatorName);
152             modelGroupReader = ModelGroupReader.getModelGroupReader(delegatorName);
153         }
154
155         cache = new Cache(delegatorName);
156
157         // do the entity model check
158
List JavaDoc warningList = FastList.newInstance();
159         Debug.logImportant("Doing entity definition check...", module);
160         ModelEntityChecker.checkEntities(this, warningList);
161         if (warningList.size() > 0) {
162             Debug.logWarning("=-=-=-=-= Found " + warningList.size() + " warnings when checking the entity definitions:", module);
163             Iterator JavaDoc warningIter = warningList.iterator();
164             while (warningIter.hasNext()) {
165                 String JavaDoc warning = (String JavaDoc) warningIter.next();
166                 Debug.logWarning(warning, module);
167             }
168         }
169
170         // initialize helpers by group
171
Iterator JavaDoc groups = UtilMisc.toIterator(getModelGroupReader().getGroupNames());
172         while (groups != null && groups.hasNext()) {
173             String JavaDoc groupName = (String JavaDoc) groups.next();
174             String JavaDoc helperName = this.getGroupHelperName(groupName);
175
176             if (Debug.infoOn()) Debug.logInfo("Delegator \"" + delegatorName + "\" initializing helper \"" +
177                     helperName + "\" for entity group \"" + groupName + "\".", module);
178             TreeSet JavaDoc helpersDone = new TreeSet JavaDoc();
179             if (helperName != null && helperName.length() > 0) {
180                 // make sure each helper is only loaded once
181
if (helpersDone.contains(helperName)) {
182                     if (Debug.infoOn()) Debug.logInfo("Helper \"" + helperName + "\" already initialized, not re-initializing.", module);
183                     continue;
184                 }
185                 helpersDone.add(helperName);
186                 // pre-load field type defs, the return value is ignored
187
ModelFieldTypeReader.getModelFieldTypeReader(helperName);
188                 // get the helper and if configured, do the datasource check
189
GenericHelper helper = GenericHelperFactory.getHelper(helperName);
190
191                 DatasourceInfo datasourceInfo = EntityConfigUtil.getDatasourceInfo(helperName);
192                 if (datasourceInfo.checkOnStart) {
193                     if (Debug.infoOn()) Debug.logInfo("Doing database check as requested in entityengine.xml with addMissing=" + datasourceInfo.addMissingOnStart, module);
194                     try {
195                         helper.checkDataSource(this.getModelEntityMapByGroup(groupName), null, datasourceInfo.addMissingOnStart);
196                     } catch (GenericEntityException e) {
197                         Debug.logWarning(e, e.getMessage(), module);
198                     }
199                 }
200             }
201         }
202
203         // NOTE: doing some things before the ECAs and such to make sure it is in place just in case it is used in a service engine startup thing or something
204
// put the delegator in the master Map by its name
205
delegatorCache.put(delegatorName, this);
206
207         // setup the crypto class
208
this.crypto = new EntityCrypto(this);
209
210         //time to do some tricks with manual class loading that resolves circular dependencies, like calling services...
211
ClassLoader JavaDoc loader = Thread.currentThread().getContextClassLoader();
212
213         // if useDistributedCacheClear is false do nothing since the
214
// distributedCacheClear member field with a null value will cause the
215
// dcc code to do nothing
216
if (getDelegatorInfo().useDistributedCacheClear) {
217             // initialize the distributedCacheClear mechanism
218
String JavaDoc distributedCacheClearClassName = getDelegatorInfo().distributedCacheClearClassName;
219
220             try {
221                 Class JavaDoc dccClass = loader.loadClass(distributedCacheClearClassName);
222                 this.distributedCacheClear = (DistributedCacheClear) dccClass.newInstance();
223                 this.distributedCacheClear.setDelegator(this, getDelegatorInfo().distributedCacheClearUserLoginId);
224             } catch (ClassNotFoundException JavaDoc e) {
225                 Debug.logWarning(e, "DistributedCacheClear class with name " + distributedCacheClearClassName + " was not found, distributed cache clearing will be disabled", module);
226             } catch (InstantiationException JavaDoc e) {
227                 Debug.logWarning(e, "DistributedCacheClear class with name " + distributedCacheClearClassName + " could not be instantiated, distributed cache clearing will be disabled", module);
228             } catch (IllegalAccessException JavaDoc e) {
229                 Debug.logWarning(e, "DistributedCacheClear class with name " + distributedCacheClearClassName + " could not be accessed (illegal), distributed cache clearing will be disabled", module);
230             } catch (ClassCastException JavaDoc e) {
231                 Debug.logWarning(e, "DistributedCacheClear class with name " + distributedCacheClearClassName + " does not implement the DistributedCacheClear interface, distributed cache clearing will be disabled", module);
232             }
233         } else {
234             Debug.logInfo("Distributed Cache Clear System disabled for delegator [" + delegatorName + "]", module);
235         }
236
237         // setup the Entity ECA Handler
238
if (getDelegatorInfo().useEntityEca) {
239             // initialize the entity eca handler
240
String JavaDoc entityEcaHandlerClassName = getDelegatorInfo().entityEcaHandlerClassName;
241
242             try {
243                 Class JavaDoc eecahClass = loader.loadClass(entityEcaHandlerClassName);
244                 this.entityEcaHandler = (EntityEcaHandler) eecahClass.newInstance();
245                 this.entityEcaHandler.setDelegator(this);
246             } catch (ClassNotFoundException JavaDoc e) {
247                 Debug.logWarning(e, "EntityEcaHandler class with name " + entityEcaHandlerClassName + " was not found, Entity ECA Rules will be disabled", module);
248             } catch (InstantiationException JavaDoc e) {
249                 Debug.logWarning(e, "EntityEcaHandler class with name " + entityEcaHandlerClassName + " could not be instantiated, Entity ECA Rules will be disabled", module);
250             } catch (IllegalAccessException JavaDoc e) {
251                 Debug.logWarning(e, "EntityEcaHandler class with name " + entityEcaHandlerClassName + " could not be accessed (illegal), Entity ECA Rules will be disabled", module);
252             } catch (ClassCastException JavaDoc e) {
253                 Debug.logWarning(e, "EntityEcaHandler class with name " + entityEcaHandlerClassName + " does not implement the EntityEcaHandler interface, Entity ECA Rules will be disabled", module);
254             }
255         } else {
256             Debug.logInfo("Entity ECA Handler disabled for delegator [" + delegatorName + "]", module);
257         }
258     }
259
260     /** Gets the name of the server configuration that corresponds to this delegator
261      * @return server configuration name
262      */

263     public String JavaDoc getDelegatorName() {
264         return this.delegatorName;
265     }
266
267     protected DelegatorInfo getDelegatorInfo() {
268         if (delegatorInfo == null) {
269             delegatorInfo = EntityConfigUtil.getDelegatorInfo(this.delegatorName);
270         }
271         return delegatorInfo;
272     }
273
274     /** Gets the instance of ModelReader that corresponds to this delegator
275      *@return ModelReader that corresponds to this delegator
276      */

277     public ModelReader getModelReader() {
278         if (keepLocalReaders) {
279             return this.modelReader;
280         } else {
281             try {
282                 return ModelReader.getModelReader(delegatorName);
283             } catch (GenericEntityException e) {
284                 Debug.logError(e, "Error loading entity model", module);
285                 return null;
286             }
287         }
288     }
289
290     /** Gets the instance of ModelGroupReader that corresponds to this delegator
291      *@return ModelGroupReader that corresponds to this delegator
292      */

293     public ModelGroupReader getModelGroupReader() {
294         if (keepLocalReaders) {
295             return this.modelGroupReader;
296         } else {
297             try {
298                 return ModelGroupReader.getModelGroupReader(delegatorName);
299             } catch (GenericEntityException e) {
300                 Debug.logError(e, "Error loading entity group model", module);
301                 return null;
302             }
303         }
304     }
305
306     /** Gets the instance of ModelEntity that corresponds to this delegator and the specified entityName
307      *@param entityName The name of the entity to get
308      *@return ModelEntity that corresponds to this delegator and the specified entityName
309      */

310     public ModelEntity getModelEntity(String JavaDoc entityName) {
311         try {
312             return getModelReader().getModelEntity(entityName);
313         } catch (GenericEntityException e) {
314             Debug.logError(e, "Error getting entity definition from model", module);
315             return null;
316         }
317     }
318
319     /** Gets the helper name that corresponds to this delegator and the specified entityName
320      *@param entityName The name of the entity to get the helper for
321      *@return String with the helper name that corresponds to this delegator and the specified entityName
322      */

323     public String JavaDoc getEntityGroupName(String JavaDoc entityName) {
324         String JavaDoc groupName = getModelGroupReader().getEntityGroupName(entityName);
325
326         return groupName;
327     }
328
329     /** Gets a list of entity models that are in a group corresponding to the specified group name
330      *@param groupName The name of the group
331      *@return List of ModelEntity instances
332      */

333     public List JavaDoc getModelEntitiesByGroup(String JavaDoc groupName) {
334         Iterator JavaDoc enames = UtilMisc.toIterator(getModelGroupReader().getEntityNamesByGroup(groupName));
335         List JavaDoc entities = FastList.newInstance();
336
337         if (enames == null || !enames.hasNext())
338             return entities;
339         while (enames.hasNext()) {
340             String JavaDoc ename = (String JavaDoc) enames.next();
341             ModelEntity entity = this.getModelEntity(ename);
342
343             if (entity != null)
344                 entities.add(entity);
345         }
346         return entities;
347     }
348
349     /** Gets a Map of entity name & entity model pairs that are in the named group
350      *@param groupName The name of the group
351      *@return Map of entityName String keys and ModelEntity instance values
352      */

353     public Map JavaDoc getModelEntityMapByGroup(String JavaDoc groupName) {
354         Iterator JavaDoc enames = UtilMisc.toIterator(getModelGroupReader().getEntityNamesByGroup(groupName));
355         Map JavaDoc entities = FastMap.newInstance();
356
357         if (enames == null || !enames.hasNext()) {
358             return entities;
359         }
360
361         int errorCount = 0;
362         while (enames.hasNext()) {
363             String JavaDoc ename = (String JavaDoc) enames.next();
364             try {
365                 ModelEntity entity = getModelReader().getModelEntity(ename);
366                 if (entity != null) {
367                     entities.put(entity.getEntityName(), entity);
368                 } else {
369                     throw new IllegalStateException JavaDoc("Could not find entity with name " + ename);
370                 }
371             } catch (GenericEntityException ex) {
372                 errorCount++;
373                 Debug.logError("Entity " + ename + " named in Entity Group with name " + groupName + " are not defined in any Entity Definition file", module);
374             }
375         }
376
377         if (errorCount > 0) {
378             Debug.logError(errorCount + " entities were named in ModelGroup but not defined in any EntityModel", module);
379         }
380
381         return entities;
382     }
383
384     /** Gets the helper name that corresponds to this delegator and the specified entityName
385      *@param groupName The name of the group to get the helper name for
386      *@return String with the helper name that corresponds to this delegator and the specified entityName
387      */

388     public String JavaDoc getGroupHelperName(String JavaDoc groupName) {
389         return (String JavaDoc) this.getDelegatorInfo().groupMap.get(groupName);
390     }
391
392     /** Gets the helper name that corresponds to this delegator and the specified entityName
393      *@param entityName The name of the entity to get the helper name for
394      *@return String with the helper name that corresponds to this delegator and the specified entityName
395      */

396     public String JavaDoc getEntityHelperName(String JavaDoc entityName) {
397         String JavaDoc groupName = getModelGroupReader().getEntityGroupName(entityName);
398
399         return this.getGroupHelperName(groupName);
400     }
401
402     /** Gets the helper name that corresponds to this delegator and the specified entity
403      *@param entity The entity to get the helper for
404      *@return String with the helper name that corresponds to this delegator and the specified entity
405      */

406     public String JavaDoc getEntityHelperName(ModelEntity entity) {
407         if (entity == null)
408             return null;
409         return getEntityHelperName(entity.getEntityName());
410     }
411
412     /** Gets the an instance of helper that corresponds to this delegator and the specified entityName
413      *@param entityName The name of the entity to get the helper for
414      *@return GenericHelper that corresponds to this delegator and the specified entityName
415      */

416     public GenericHelper getEntityHelper(String JavaDoc entityName) throws GenericEntityException {
417         String JavaDoc helperName = getEntityHelperName(entityName);
418
419         if (helperName != null && helperName.length() > 0)
420             return GenericHelperFactory.getHelper(helperName);
421         else
422             throw new GenericEntityException("Helper name not found for entity " + entityName);
423     }
424
425     /** Gets the an instance of helper that corresponds to this delegator and the specified entity
426      *@param entity The entity to get the helper for
427      *@return GenericHelper that corresponds to this delegator and the specified entity
428      */

429     public GenericHelper getEntityHelper(ModelEntity entity) throws GenericEntityException {
430         return getEntityHelper(entity.getEntityName());
431     }
432
433     /** Gets a field type instance by name from the helper that corresponds to the specified entity
434      *@param entity The entity
435      *@param type The name of the type
436      *@return ModelFieldType instance for the named type from the helper that corresponds to the specified entity
437      */

438     public ModelFieldType getEntityFieldType(ModelEntity entity, String JavaDoc type) throws GenericEntityException {
439         String JavaDoc helperName = getEntityHelperName(entity);
440
441         if (helperName == null || helperName.length() <= 0)
442             return null;
443         ModelFieldTypeReader modelFieldTypeReader = ModelFieldTypeReader.getModelFieldTypeReader(helperName);
444
445         if (modelFieldTypeReader == null) {
446             throw new GenericEntityException("ModelFieldTypeReader not found for entity " + entity.getEntityName() + " with helper name " + helperName);
447         }
448         return modelFieldTypeReader.getModelFieldType(type);
449     }
450
451     /** Gets field type names from the helper that corresponds to the specified entity
452      *@param entity The entity
453      *@return Collection of field type names from the helper that corresponds to the specified entity
454      */

455     public Collection JavaDoc getEntityFieldTypeNames(ModelEntity entity) throws GenericEntityException {
456         String JavaDoc helperName = getEntityHelperName(entity);
457
458         if (helperName == null || helperName.length() <= 0)
459             return null;
460         ModelFieldTypeReader modelFieldTypeReader = ModelFieldTypeReader.getModelFieldTypeReader(helperName);
461
462         if (modelFieldTypeReader == null) {
463             throw new GenericEntityException("ModelFieldTypeReader not found for entity " + entity.getEntityName() + " with helper name " + helperName);
464         }
465         return modelFieldTypeReader.getFieldTypeNames();
466     }
467
468     /** Creates a Entity in the form of a GenericValue without persisting it */
469     public GenericValue makeValue(String JavaDoc entityName, Map JavaDoc fields) {
470         ModelEntity entity = this.getModelEntity(entityName);
471         if (entity == null) {
472             throw new IllegalArgumentException JavaDoc("[GenericDelegator.makeValue] could not find entity for entityName: " + entityName);
473         }
474         GenericValue value = GenericValue.create(entity, fields);
475         value.setDelegator(this);
476         return value;
477     }
478
479     /** Creates a Entity in the form of a GenericValue without persisting it; only valid fields will be pulled from the fields Map */
480     public GenericValue makeValidValue(String JavaDoc entityName, Map JavaDoc fields) {
481         ModelEntity entity = this.getModelEntity(entityName);
482         if (entity == null) {
483             throw new IllegalArgumentException JavaDoc("[GenericDelegator.makeValidValue] could not find entity for entityName: " + entityName);
484         }
485         GenericValue value = GenericValue.create(entity, null);
486         value.setPKFields(fields, true);
487         value.setNonPKFields(fields, true);
488         value.setDelegator(this);
489         return value;
490     }
491
492     /** Creates a Primary Key in the form of a GenericPK without persisting it */
493     public GenericPK makePK(String JavaDoc entityName, Map JavaDoc fields) {
494         ModelEntity entity = this.getModelEntity(entityName);
495         if (entity == null) {
496             throw new IllegalArgumentException JavaDoc("[GenericDelegator.makePK] could not find entity for entityName: " + entityName);
497         }
498         GenericPK pk = GenericPK.create(entity, fields);
499
500         pk.setDelegator(this);
501         return pk;
502     }
503
504     /** Creates a Entity in the form of a GenericValue and write it to the datasource
505      *@param primaryKey The GenericPK to create a value in the datasource from
506      *@return GenericValue instance containing the new instance
507      */

508     public GenericValue create(GenericPK primaryKey) throws GenericEntityException {
509         return this.create(primaryKey, true);
510     }
511
512     /** Creates a Entity in the form of a GenericValue and write it to the datasource
513      *@param primaryKey The GenericPK to create a value in the datasource from
514      *@param doCacheClear boolean that specifies whether to clear related cache entries for this primaryKey to be created
515      *@return GenericValue instance containing the new instance
516      */

517     public GenericValue create(GenericPK primaryKey, boolean doCacheClear) throws GenericEntityException {
518         if (primaryKey == null) {
519             throw new GenericEntityException("Cannot create from a null primaryKey");
520         }
521
522         return this.create(GenericValue.create(primaryKey), doCacheClear);
523     }
524
525     /** Creates a Entity in the form of a GenericValue and write it to the database
526      *@return GenericValue instance containing the new instance
527      */

528     public GenericValue create(String JavaDoc entityName, Map JavaDoc fields) throws GenericEntityException {
529         if (entityName == null || fields == null) {
530             return null;
531         }
532         ModelEntity entity = this.getModelReader().getModelEntity(entityName);
533         GenericValue genericValue = GenericValue.create(entity, fields);
534
535         return this.create(genericValue, true);
536     }
537
538     /** Creates a Entity in the form of a GenericValue and write it to the datasource
539      *@param value The GenericValue to create a value in the datasource from
540      *@return GenericValue instance containing the new instance
541      */

542     public GenericValue create(GenericValue value) throws GenericEntityException {
543         return this.create(value, true);
544     }
545
546     /** Creates a Entity in the form of a GenericValue and write it to the datasource
547      *@param value The GenericValue to create a value in the datasource from
548      *@param doCacheClear boolean that specifies whether or not to automatically clear cache entries related to this operation
549      *@return GenericValue instance containing the new instance
550      */

551     public GenericValue create(GenericValue value, boolean doCacheClear) throws GenericEntityException {
552         boolean beganTransaction = false;
553         try {
554             if (alwaysUseTransaction) {
555                 beganTransaction = TransactionUtil.begin();
556             }
557
558             Map JavaDoc ecaEventMap = this.getEcaEntityEventMap(value.getEntityName());
559             this.evalEcaRules(EntityEcaHandler.EV_VALIDATE, EntityEcaHandler.OP_CREATE, value, ecaEventMap, (ecaEventMap == null), false);
560
561             if (value == null) {
562                 throw new GenericEntityException("Cannot create a null value");
563             }
564             GenericHelper helper = getEntityHelper(value.getEntityName());
565
566             this.evalEcaRules(EntityEcaHandler.EV_RUN, EntityEcaHandler.OP_CREATE, value, ecaEventMap, (ecaEventMap == null), false);
567
568             value.setDelegator(this);
569             this.encryptFields(value);
570             value = helper.create(value);
571
572             if (value != null) {
573                 value.setDelegator(this);
574                 if (value.lockEnabled()) {
575                     refresh(value, doCacheClear);
576                 } else {
577                     if (doCacheClear) {
578                         this.evalEcaRules(EntityEcaHandler.EV_CACHE_CLEAR, EntityEcaHandler.OP_CREATE, value, ecaEventMap, (ecaEventMap == null), false);
579                         this.clearCacheLine(value);
580                     }
581                 }
582             }
583
584             this.evalEcaRules(EntityEcaHandler.EV_RETURN, EntityEcaHandler.OP_CREATE, value, ecaEventMap, (ecaEventMap == null), false);
585             return value;
586         } catch (GenericEntityException e) {
587             String JavaDoc errMsg = "Failure in create operation for entity [" + value.getEntityName() + "]: " + e.toString() + ". Rolling back transaction.";
588             Debug.logError(e, errMsg, module);
589             try {
590                 // only rollback the transaction if we started one...
591
TransactionUtil.rollback(beganTransaction, errMsg, e);
592             } catch (GenericEntityException e2) {
593                 Debug.logError(e2, "[GenericDelegator] Could not rollback transaction: " + e2.toString(), module);
594             }
595             // after rolling back, rethrow the exception
596
throw e;
597         } finally {
598             // only commit the transaction if we started one... this will throw an exception if it fails
599
TransactionUtil.commit(beganTransaction);
600         }
601     }
602
603     /** Creates or stores an Entity
604      *@param value The GenericValue instance containing the new or existing instance
605      *@param doCacheClear boolean that specifies whether or not to automatically clear cache entries related to this operation
606      *@return GenericValue instance containing the new or updated instance
607      */

608     public GenericValue createOrStore(GenericValue value, boolean doCacheClear) throws GenericEntityException {
609         boolean beganTransaction = false;
610         try {
611             if (alwaysUseTransaction) {
612                 beganTransaction = TransactionUtil.begin();
613             }
614
615             GenericValue checkValue = this.findByPrimaryKey(value.getPrimaryKey());
616             if (checkValue != null) {
617                 this.store(value, doCacheClear);
618             } else {
619                 this.create(value, doCacheClear);
620             }
621             if (value.lockEnabled()) {
622                 this.refresh(value);
623             }
624
625             return value;
626         } catch (GenericEntityException e) {
627             String JavaDoc errMsg = "Failure in createOrStore operation for entity [" + value.getEntityName() + "]: " + e.toString() + ". Rolling back transaction.";
628             Debug.logError(e, errMsg, module);
629             try {
630                 // only rollback the transaction if we started one...
631
TransactionUtil.rollback(beganTransaction, errMsg, e);
632             } catch (GenericEntityException e2) {
633                 Debug.logError(e2, "[GenericDelegator] Could not rollback transaction: " + e2.toString(), module);
634             }
635             // after rolling back, rethrow the exception
636
throw e;
637         } finally {
638             // only commit the transaction if we started one... this will throw an exception if it fails
639
TransactionUtil.commit(beganTransaction);
640         }
641     }
642
643     /** Creates or stores an Entity
644      *@param value The GenericValue instance containing the new or existing instance
645      *@return GenericValue instance containing the new or updated instance
646      */

647     public GenericValue createOrStore(GenericValue value) throws GenericEntityException {
648         return createOrStore(value, true);
649     }
650
651     protected void saveEntitySyncRemoveInfo(GenericEntity dummyPK) throws GenericEntityException {
652         // don't store remove info on entities where it is disabled
653
if (dummyPK.getModelEntity().getNoAutoStamp()) {
654             return;
655         }
656
657         // don't store remove info on things removed on an entity sync
658
if (dummyPK.getIsFromEntitySync()) {
659             return;
660         }
661
662         String JavaDoc serializedPK = null;
663         try {
664             serializedPK = XmlSerializer.serialize(dummyPK);
665         } catch (SerializeException e) {
666             Debug.logError(e, "Could not serialize primary key to save EntitySyncRemove", module);
667         } catch (FileNotFoundException JavaDoc e) {
668             Debug.logError(e, "Could not serialize primary key to save EntitySyncRemove", module);
669         } catch (IOException JavaDoc e) {
670             Debug.logError(e, "Could not serialize primary key to save EntitySyncRemove", module);
671         }
672
673         if (serializedPK != null) {
674             GenericValue entitySyncRemove = this.makeValue("EntitySyncRemove", null);
675             entitySyncRemove.set("entitySyncRemoveId", this.getNextSeqId("EntitySyncRemove"));
676             entitySyncRemove.set("primaryKeyRemoved", serializedPK);
677             entitySyncRemove.create();
678         }
679     }
680
681     /** Remove a Generic Entity corresponding to the primaryKey
682      *@param primaryKey The primary key of the entity to remove.
683      *@return int representing number of rows effected by this operation
684      */

685     public int removeByPrimaryKey(GenericPK primaryKey) throws GenericEntityException {
686         int retVal = this.removeByPrimaryKey(primaryKey, true);
687         return retVal;
688     }
689
690     /** Remove a Generic Entity corresponding to the primaryKey
691      *@param primaryKey The primary key of the entity to remove.
692      *@param doCacheClear boolean that specifies whether to clear cache entries for this primaryKey to be removed
693      *@return int representing number of rows effected by this operation
694      */

695     public int removeByPrimaryKey(GenericPK primaryKey, boolean doCacheClear) throws GenericEntityException {
696         boolean beganTransaction = false;
697         try {
698             if (alwaysUseTransaction) {
699                 beganTransaction = TransactionUtil.begin();
700             }
701
702             Map JavaDoc ecaEventMap = this.getEcaEntityEventMap(primaryKey.getEntityName());
703             this.evalEcaRules(EntityEcaHandler.EV_VALIDATE, EntityEcaHandler.OP_REMOVE, primaryKey, ecaEventMap, (ecaEventMap == null), false);
704
705             GenericHelper helper = getEntityHelper(primaryKey.getEntityName());
706
707             if (doCacheClear) {
708                 // always clear cache before the operation
709
this.evalEcaRules(EntityEcaHandler.EV_CACHE_CLEAR, EntityEcaHandler.OP_REMOVE, primaryKey, ecaEventMap, (ecaEventMap == null), false);
710                 this.clearCacheLine(primaryKey);
711             }
712
713             this.evalEcaRules(EntityEcaHandler.EV_RUN, EntityEcaHandler.OP_REMOVE, primaryKey, ecaEventMap, (ecaEventMap == null), false);
714             int num = helper.removeByPrimaryKey(primaryKey);
715             this.saveEntitySyncRemoveInfo(primaryKey);
716
717             this.evalEcaRules(EntityEcaHandler.EV_RETURN, EntityEcaHandler.OP_REMOVE, primaryKey, ecaEventMap, (ecaEventMap == null), false);
718             return num;
719         } catch (GenericEntityException e) {
720             String JavaDoc errMsg = "Failure in removeByPrimaryKey operation for entity [" + primaryKey.getEntityName() + "]: " + e.toString() + ". Rolling back transaction.";
721             Debug.logError(e, errMsg, module);
722             try {
723                 // only rollback the transaction if we started one...
724
TransactionUtil.rollback(beganTransaction, errMsg, e);
725             } catch (GenericEntityException e2) {
726                 Debug.logError(e2, "[GenericDelegator] Could not rollback transaction: " + e2.toString(), module);
727             }
728             // after rolling back, rethrow the exception
729
throw e;
730         } finally {
731             // only commit the transaction if we started one... this will throw an exception if it fails
732
TransactionUtil.commit(beganTransaction);
733         }
734     }
735
736     /** Remove a Generic Value from the database
737      *@param value The GenericValue object of the entity to remove.
738      *@return int representing number of rows effected by this operation
739      */

740     public int removeValue(GenericValue value) throws GenericEntityException {
741         return this.removeValue(value, true);
742     }
743
744     /** Remove a Generic Value from the database
745      *@param value The GenericValue object of the entity to remove.
746      *@param doCacheClear boolean that specifies whether to clear cache entries for this value to be removed
747      *@return int representing number of rows effected by this operation
748      */

749     public int removeValue(GenericValue value, boolean doCacheClear) throws GenericEntityException {
750         // NOTE: this does not call the GenericDelegator.removeByPrimaryKey method because it has more information to pass to the ECA rule hander
751
boolean beganTransaction = false;
752         try {
753             if (alwaysUseTransaction) {
754                 beganTransaction = TransactionUtil.begin();
755             }
756
757             Map JavaDoc ecaEventMap = this.getEcaEntityEventMap(value.getEntityName());
758             this.evalEcaRules(EntityEcaHandler.EV_VALIDATE, EntityEcaHandler.OP_REMOVE, value, ecaEventMap, (ecaEventMap == null), false);
759
760             GenericHelper helper = getEntityHelper(value.getEntityName());
761
762             if (doCacheClear) {
763                 this.evalEcaRules(EntityEcaHandler.EV_CACHE_CLEAR, EntityEcaHandler.OP_REMOVE, value, ecaEventMap, (ecaEventMap == null), false);
764                 this.clearCacheLine(value);
765             }
766
767             this.evalEcaRules(EntityEcaHandler.EV_RUN, EntityEcaHandler.OP_REMOVE, value, ecaEventMap, (ecaEventMap == null), false);
768             int num = helper.removeByPrimaryKey(value.getPrimaryKey());
769             this.saveEntitySyncRemoveInfo(value.getPrimaryKey());
770
771             this.evalEcaRules(EntityEcaHandler.EV_RETURN, EntityEcaHandler.OP_REMOVE, value, ecaEventMap, (ecaEventMap == null), false);
772             return num;
773         } catch (GenericEntityException e) {
774             String JavaDoc errMsg = "Failure in removeValue operation for entity [" + value.getEntityName() + "]: " + e.toString() + ". Rolling back transaction.";
775             Debug.logError(e, errMsg, module);
776             try {
777                 // only rollback the transaction if we started one...
778
TransactionUtil.rollback(beganTransaction, errMsg, e);
779             } catch (GenericEntityException e2) {
780                 Debug.logError(e2, "[GenericDelegator] Could not rollback transaction: " + e2.toString(), module);
781             }
782             // after rolling back, rethrow the exception
783
throw e;
784         } finally {
785             // only commit the transaction if we started one... this will throw an exception if it fails
786
TransactionUtil.commit(beganTransaction);
787         }
788     }
789
790     /** Removes/deletes Generic Entity records found by all of the specified fields (ie: combined using AND)
791      *@param entityName The Name of the Entity as defined in the entity XML file
792      *@param fields The fields of the named entity to query by with their corresponging values
793      *@return int representing number of rows effected by this operation
794      */

795     public int removeByAnd(String JavaDoc entityName, Map JavaDoc fields) throws GenericEntityException {
796         return this.removeByAnd(entityName, fields, true);
797     }
798
799     /** Removes/deletes Generic Entity records found by all of the specified fields (ie: combined using AND)
800      *@param entityName The Name of the Entity as defined in the entity XML file
801      *@param fields The fields of the named entity to query by with their corresponging values
802      *@param doCacheClear boolean that specifies whether to clear cache entries for this value to be removed
803      *@return int representing number of rows effected by this operation
804      */

805     public int removeByAnd(String JavaDoc entityName, Map JavaDoc fields, boolean doCacheClear) throws GenericEntityException {
806         EntityCondition ecl = new EntityFieldMap(fields, EntityOperator.AND);
807         return removeByCondition(entityName, ecl, doCacheClear);
808     }
809
810     /** Removes/deletes Generic Entity records found by the condition
811      *@param entityName The Name of the Entity as defined in the entity XML file
812      *@param condition The condition used to restrict the removing
813      *@return int representing number of rows effected by this operation
814      */

815     public int removeByCondition(String JavaDoc entityName, EntityCondition condition) throws GenericEntityException {
816         return this.removeByCondition(entityName, condition, true);
817     }
818
819     /** Removes/deletes Generic Entity records found by the condition
820      *@param entityName The Name of the Entity as defined in the entity XML file
821      *@param condition The condition used to restrict the removing
822      *@param doCacheClear boolean that specifies whether to clear cache entries for this value to be removed
823      *@return int representing number of rows effected by this operation
824      */

825     public int removeByCondition(String JavaDoc entityName, EntityCondition condition, boolean doCacheClear) throws GenericEntityException {
826         boolean beganTransaction = false;
827         try {
828             if (alwaysUseTransaction) {
829                 beganTransaction = TransactionUtil.begin();
830             }
831
832             if (doCacheClear) {
833                 // always clear cache before the operation
834
this.clearCacheLineByCondition(entityName, condition);
835             }
836             ModelEntity modelEntity = getModelReader().getModelEntity(entityName);
837             GenericHelper helper = getEntityHelper(entityName);
838
839             return helper.removeByCondition(modelEntity, condition);
840         } catch (GenericEntityException e) {
841             String JavaDoc errMsg = "Failure in removeByCondition operation for entity [" + entityName + "]: " + e.toString() + ". Rolling back transaction.";
842             Debug.logError(e, errMsg, module);
843             try {
844                 // only rollback the transaction if we started one...
845
TransactionUtil.rollback(beganTransaction, errMsg, e);
846             } catch (GenericEntityException e2) {
847                 Debug.logError(e2, "[GenericDelegator] Could not rollback transaction: " + e2.toString(), module);
848             }
849             // after rolling back, rethrow the exception
850
throw e;
851         } finally {
852             // only commit the transaction if we started one... this will throw an exception if it fails
853
TransactionUtil.commit(beganTransaction);
854         }
855     }
856
857     /** Remove the named Related Entity for the GenericValue from the persistent store
858      *@param relationName String containing the relation name which is the
859      * combination of relation.title and relation.rel-entity-name as
860      * specified in the entity XML definition file
861      *@param value GenericValue instance containing the entity
862      *@return int representing number of rows effected by this operation
863      */

864     public int removeRelated(String JavaDoc relationName, GenericValue value) throws GenericEntityException {
865         return this.removeRelated(relationName, value, true);
866     }
867
868     /** Remove the named Related Entity for the GenericValue from the persistent store
869      *@param relationName String containing the relation name which is the
870      * combination of relation.title and relation.rel-entity-name as
871      * specified in the entity XML definition file
872      *@param value GenericValue instance containing the entity
873      *@param doCacheClear boolean that specifies whether to clear cache entries for this value to be removed
874      *@return int representing number of rows effected by this operation
875      */

876     public int removeRelated(String JavaDoc relationName, GenericValue value, boolean doCacheClear) throws GenericEntityException {
877         ModelEntity modelEntity = value.getModelEntity();
878         ModelRelation relation = modelEntity.getRelation(relationName);
879
880         if (relation == null) {
881             throw new GenericModelException("Could not find relation for relationName: " + relationName + " for value " + value);
882         }
883
884         Map JavaDoc fields = FastMap.newInstance();
885         for (int i = 0; i < relation.getKeyMapsSize(); i++) {
886             ModelKeyMap keyMap = relation.getKeyMap(i);
887             fields.put(keyMap.getRelFieldName(), value.get(keyMap.getFieldName()));
888         }
889
890         return this.removeByAnd(relation.getRelEntityName(), fields, doCacheClear);
891     }
892
893     /** Refresh the Entity for the GenericValue from the persistent store
894      *@param value GenericValue instance containing the entity to refresh
895      */

896     public void refresh(GenericValue value) throws GenericEntityException {
897         this.refresh(value, true);
898     }
899
900     /** Refresh the Entity for the GenericValue from the persistent store
901      *@param value GenericValue instance containing the entity to refresh
902      *@param doCacheClear boolean that specifies whether or not to automatically clear cache entries related to this operation
903      */

904     public void refresh(GenericValue value, boolean doCacheClear) throws GenericEntityException {
905         if (doCacheClear) {
906             // always clear cache before the operation
907
clearCacheLine(value);
908         }
909         GenericPK pk = value.getPrimaryKey();
910         GenericValue newValue = findByPrimaryKey(pk);
911         value.refreshFromValue(newValue);
912     }
913
914     /** Refresh the Entity for the GenericValue from the cache
915      *@param value GenericValue instance containing the entity to refresh
916      */

917     public void refreshFromCache(GenericValue value) throws GenericEntityException {
918         GenericPK pk = value.getPrimaryKey();
919         GenericValue newValue = findByPrimaryKeyCache(pk);
920         value.refreshFromValue(newValue);
921     }
922
923    /** Store a group of values
924      *@param entityName The name of the Entity as defined in the entity XML file
925      *@param fieldsToSet The fields of the named entity to set in the database
926      *@param condition The condition that restricts the list of stored values
927      *@return int representing number of rows effected by this operation
928      *@throws GenericEntityException
929      */

930     public int storeByCondition(String JavaDoc entityName, Map JavaDoc fieldsToSet, EntityCondition condition) throws GenericEntityException {
931         return storeByCondition(entityName, fieldsToSet, condition, true);
932     }
933
934     /** Store a group of values
935      *@param entityName The name of the Entity as defined in the entity XML file
936      *@param fieldsToSet The fields of the named entity to set in the database
937      *@param condition The condition that restricts the list of stored values
938      *@param doCacheClear boolean that specifies whether to clear cache entries for these values
939      *@return int representing number of rows effected by this operation
940      *@throws GenericEntityException
941      */

942     public int storeByCondition(String JavaDoc entityName, Map JavaDoc fieldsToSet, EntityCondition condition, boolean doCacheClear) throws GenericEntityException {
943         boolean beganTransaction = false;
944         try {
945             if (alwaysUseTransaction) {
946                 beganTransaction = TransactionUtil.begin();
947             }
948
949             if (doCacheClear) {
950                 // always clear cache before the operation
951
this.clearCacheLineByCondition(entityName, condition);
952             }
953             ModelEntity modelEntity = getModelReader().getModelEntity(entityName);
954             GenericHelper helper = getEntityHelper(entityName);
955
956             return helper.storeByCondition(modelEntity, fieldsToSet, condition);
957         } catch (GenericEntityException e) {
958             String JavaDoc errMsg = "Failure in storeByCondition operation for entity [" + entityName + "]: " + e.toString() + ". Rolling back transaction.";
959             Debug.logError(e, errMsg, module);
960             try {
961                 // only rollback the transaction if we started one...
962
TransactionUtil.rollback(beganTransaction, errMsg, e);
963             } catch (GenericEntityException e2) {
964                 Debug.logError(e2, "[GenericDelegator] Could not rollback transaction: " + e2.toString(), module);
965             }
966             // after rolling back, rethrow the exception
967
throw e;
968         } finally {
969             // only commit the transaction if we started one... this will throw an exception if it fails
970
TransactionUtil.commit(beganTransaction);
971         }
972     }
973
974     /** Store the Entity from the GenericValue to the persistent store
975      *@param value GenericValue instance containing the entity
976      *@return int representing number of rows effected by this operation
977      */

978     public int store(GenericValue value) throws GenericEntityException {
979         return this.store(value, true);
980     }
981
982     /** Store the Entity from the GenericValue to the persistent store
983      *@param value GenericValue instance containing the entity
984      *@param doCacheClear boolean that specifies whether or not to automatically clear cache entries related to this operation
985      *@return int representing number of rows effected by this operation
986      */

987     public int store(GenericValue value, boolean doCacheClear) throws GenericEntityException {
988         boolean beganTransaction = false;
989         try {
990             if (alwaysUseTransaction) {
991                 beganTransaction = TransactionUtil.begin();
992             }
993
994             Map JavaDoc ecaEventMap = this.getEcaEntityEventMap(value.getEntityName());
995             this.evalEcaRules(EntityEcaHandler.EV_VALIDATE, EntityEcaHandler.OP_STORE, value, ecaEventMap, (ecaEventMap == null), false);
996             GenericHelper helper = getEntityHelper(value.getEntityName());
997
998             if (doCacheClear) {
999                 // always clear cache before the operation
1000
this.evalEcaRules(EntityEcaHandler.EV_CACHE_CLEAR, EntityEcaHandler.OP_STORE, value, ecaEventMap, (ecaEventMap == null), false);
1001                this.clearCacheLine(value);
1002            }
1003
1004            this.evalEcaRules(EntityEcaHandler.EV_RUN, EntityEcaHandler.OP_STORE, value, ecaEventMap, (ecaEventMap == null), false);
1005            this.encryptFields(value);
1006            int retVal = helper.store(value);
1007
1008            // refresh the valueObject to get the new version
1009
if (value.lockEnabled()) {
1010                refresh(value, doCacheClear);
1011            }
1012
1013            this.evalEcaRules(EntityEcaHandler.EV_RETURN, EntityEcaHandler.OP_STORE, value, ecaEventMap, (ecaEventMap == null), false);
1014            return retVal;
1015        } catch (GenericEntityException e) {
1016            String JavaDoc errMsg = "Failure in store operation for entity [" + value.getEntityName() + "]: " + e.toString() + ". Rolling back transaction.";
1017            Debug.logError(e, errMsg, module);
1018            try {
1019                // only rollback the transaction if we started one...
1020
TransactionUtil.rollback(beganTransaction, errMsg, e);
1021            } catch (GenericEntityException e2) {
1022                Debug.logError(e2, "[GenericDelegator] Could not rollback transaction: " + e2.toString(), module);
1023            }
1024            // after rolling back, rethrow the exception
1025
throw e;
1026        } finally {
1027            // only commit the transaction if we started one... this will throw an exception if it fails
1028
TransactionUtil.commit(beganTransaction);
1029        }
1030    }
1031
1032    /** Store the Entities from the List GenericValue instances to the persistent store.
1033     * <br/>This is different than the normal store method in that the store method only does
1034     * an update, while the storeAll method checks to see if each entity exists, then
1035     * either does an insert or an update as appropriate.
1036     * <br/>These updates all happen in one transaction, so they will either all succeed or all fail,
1037     * if the data source supports transactions. This is just like to othersToStore feature
1038     * of the GenericEntity on a create or store.
1039     *@param values List of GenericValue instances containing the entities to store
1040     *@return int representing number of rows effected by this operation
1041     */

1042    public int storeAll(List JavaDoc values) throws GenericEntityException {
1043        return this.storeAll(values, true);
1044    }
1045
1046    /** Store the Entities from the List GenericValue instances to the persistent store.
1047     * <br/>This is different than the normal store method in that the store method only does
1048     * an update, while the storeAll method checks to see if each entity exists, then
1049     * either does an insert or an update as appropriate.
1050     * <br/>These updates all happen in one transaction, so they will either all succeed or all fail,
1051     * if the data source supports transactions. This is just like to othersToStore feature
1052     * of the GenericEntity on a create or store.
1053     *@param values List of GenericValue instances containing the entities to store
1054     *@param doCacheClear boolean that specifies whether or not to automatically clear cache entries related to this operation
1055     *@return int representing number of rows effected by this operation
1056     */

1057    public int storeAll(List JavaDoc values, boolean doCacheClear) throws GenericEntityException {
1058        return this.storeAll(values, doCacheClear, false);
1059    }
1060
1061    /** Store the Entities from the List GenericValue instances to the persistent store.
1062     * <br/>This is different than the normal store method in that the store method only does
1063     * an update, while the storeAll method checks to see if each entity exists, then
1064     * either does an insert or an update as appropriate.
1065     * <br/>These updates all happen in one transaction, so they will either all succeed or all fail,
1066     * if the data source supports transactions. This is just like to othersToStore feature
1067     * of the GenericEntity on a create or store.
1068     *@param values List of GenericValue instances containing the entities to store
1069     *@param doCacheClear boolean that specifies whether or not to automatically clear cache entries related to this operation
1070     *@param createDummyFks boolean that specifies whether or not to automatically create "dummy" place holder FKs
1071     *@return int representing number of rows effected by this operation
1072     */

1073    public int storeAll(List JavaDoc values, boolean doCacheClear, boolean createDummyFks) throws GenericEntityException {
1074        if (values == null) {
1075            return 0;
1076        }
1077
1078        int numberChanged = 0;
1079
1080        boolean beganTransaction = false;
1081        try {
1082            beganTransaction = TransactionUtil.begin();
1083
1084            Iterator JavaDoc viter = values.iterator();
1085            while (viter.hasNext()) {
1086                GenericValue value = (GenericValue) viter.next();
1087                String JavaDoc entityName = value.getEntityName();
1088                GenericPK primaryKey = value.getPrimaryKey();
1089                Map JavaDoc ecaEventMap = this.getEcaEntityEventMap(entityName);
1090                GenericHelper helper = getEntityHelper(entityName);
1091
1092                // exists?
1093
// NOTE: don't use findByPrimaryKey because we don't want to the ECA events to fire and such
1094
if (!primaryKey.isPrimaryKey()) {
1095                    throw new GenericModelException("[GenericDelegator.storeAll] One of the passed primary keys is not a valid primary key: " + primaryKey);
1096                }
1097                GenericValue existing = null;
1098                try {
1099                    existing = helper.findByPrimaryKey(primaryKey);
1100                    this.decryptFields(existing);
1101                } catch (GenericEntityNotFoundException e) {
1102                    existing = null;
1103                }
1104
1105                if (existing == null) {
1106                    if (createDummyFks) {
1107                        value.checkFks(true);
1108                    }
1109                    this.create(value, doCacheClear);
1110                    numberChanged++;
1111                } else {
1112                    // don't send fields that are the same, and if no fields have changed, update nothing
1113
ModelEntity modelEntity = value.getModelEntity();
1114                    GenericValue toStore = GenericValue.create(modelEntity, value.getPrimaryKey());
1115                    toStore.setDelegator(this);
1116                    boolean atLeastOneField = false;
1117                    Iterator JavaDoc nonPksIter = modelEntity.getNopksIterator();
1118                    while (nonPksIter.hasNext()) {
1119                        ModelField modelField = (ModelField) nonPksIter.next();
1120                        String JavaDoc fieldName = modelField.getName();
1121                        if (value.containsKey(fieldName)) {
1122                            Object JavaDoc fieldValue = value.get(fieldName);
1123                            Object JavaDoc oldValue = existing.get(fieldName);
1124                            if ((fieldValue == null && oldValue != null) || (fieldValue != null && !fieldValue.equals(oldValue))) {
1125                                toStore.put(fieldName, fieldValue);
1126                                atLeastOneField = true;
1127                            }
1128                        }
1129                    }
1130
1131                    if (atLeastOneField) {
1132                        if (createDummyFks) {
1133                            value.checkFks(true);
1134                        }
1135                        numberChanged += this.store(toStore, doCacheClear);
1136                    }
1137                }
1138            }
1139
1140            return numberChanged;
1141        } catch (GenericEntityException e) {
1142            String JavaDoc errMsg = "Failure in storeAll operation: " + e.toString() + ". Rolling back transaction.";
1143            Debug.logError(e, errMsg, module);
1144            try {
1145                // only rollback the transaction if we started one...
1146
TransactionUtil.rollback(beganTransaction, errMsg, e);
1147            } catch (GenericEntityException e2) {
1148                Debug.logError(e2, "[GenericDelegator] Could not rollback transaction: " + e2.toString(), module);
1149            }
1150            // after rolling back, rethrow the exception
1151
throw e;
1152        } finally {
1153            // only commit the transaction if we started one... this will throw an exception if it fails
1154
TransactionUtil.commit(beganTransaction);
1155        }
1156    }
1157
1158    /** Remove the Entities from the List from the persistent store.
1159     * <br/>The List contains GenericEntity objects, can be either GenericPK or GenericValue.
1160     * <br/>If a certain entity contains a complete primary key, the entity in the datasource corresponding
1161     * to that primary key will be removed, this is like a removeByPrimary Key.
1162     * <br/>On the other hand, if a certain entity is an incomplete or non primary key,
1163     * if will behave like the removeByAnd method.
1164     * <br/>These updates all happen in one transaction, so they will either all succeed or all fail,
1165     * if the data source supports transactions.
1166     *@param dummyPKs Collection of GenericEntity instances containing the entities or by and fields to remove
1167     *@return int representing number of rows effected by this operation
1168     */

1169    public int removeAll(List JavaDoc dummyPKs) throws GenericEntityException {
1170        return this.removeAll(dummyPKs, true);
1171    }
1172
1173    /** Remove the Entities from the List from the persistent store.
1174     * <br/>The List contains GenericEntity objects, can be either GenericPK or GenericValue.
1175     * <br/>If a certain entity contains a complete primary key, the entity in the datasource corresponding
1176     * to that primary key will be removed, this is like a removeByPrimary Key.
1177     * <br/>On the other hand, if a certain entity is an incomplete or non primary key,
1178     * if will behave like the removeByAnd method.
1179     * <br/>These updates all happen in one transaction, so they will either all succeed or all fail,
1180     * if the data source supports transactions.
1181     *@param dummyPKs Collection of GenericEntity instances containing the entities or by and fields to remove
1182     *@param doCacheClear boolean that specifies whether or not to automatically clear cache entries related to this operation
1183     *@return int representing number of rows effected by this operation
1184     */

1185    public int removeAll(List JavaDoc dummyPKs, boolean doCacheClear) throws GenericEntityException {
1186        if (dummyPKs == null) {
1187            return 0;
1188        }
1189
1190        boolean beganTransaction = false;
1191        int numRemoved = 0;
1192
1193        try {
1194            Iterator JavaDoc viter = dummyPKs.iterator();
1195            while (viter.hasNext()) {
1196                GenericEntity value = (GenericEntity) viter.next();
1197                if (value.containsPrimaryKey()) {
1198                    numRemoved += this.removeByPrimaryKey(value.getPrimaryKey(), doCacheClear);
1199                } else {
1200                    numRemoved += this.removeByAnd(value.getEntityName(), value.getAllFields(), doCacheClear);
1201                }
1202            }
1203
1204            return numRemoved;
1205        } catch (GenericEntityException e) {
1206            String JavaDoc errMsg = "Failure in removeAll operation: " + e.toString() + ". Rolling back transaction.";
1207            Debug.logError(e, errMsg, module);
1208            try {
1209                // only rollback the transaction if we started one...
1210
TransactionUtil.rollback(beganTransaction, errMsg, e);
1211            } catch (GenericEntityException e2) {
1212                Debug.logError(e2, "[GenericDelegator] Could not rollback transaction: " + e2.toString(), module);
1213            }
1214            // after rolling back, rethrow the exception
1215
throw e;
1216        } finally {
1217            // only commit the transaction if we started one... this will throw an exception if it fails
1218
TransactionUtil.commit(beganTransaction);
1219        }
1220    }
1221
1222    // ======================================
1223
// ======= Find Methods =================
1224
// ======================================
1225

1226    /** Find a Generic Entity by its Primary Key
1227     *@param primaryKey The primary key to find by.
1228     *@return The GenericValue corresponding to the primaryKey
1229     */

1230    public GenericValue findByPrimaryKey(GenericPK primaryKey) throws GenericEntityException {
1231        boolean beganTransaction = false;
1232        try {
1233            if (alwaysUseTransaction) {
1234                beganTransaction = TransactionUtil.begin();
1235            }
1236
1237            Map JavaDoc ecaEventMap = this.getEcaEntityEventMap(primaryKey.getEntityName());
1238            this.evalEcaRules(EntityEcaHandler.EV_VALIDATE, EntityEcaHandler.OP_FIND, primaryKey, ecaEventMap, (ecaEventMap == null), false);
1239
1240            GenericHelper helper = getEntityHelper(primaryKey.getEntityName());
1241            GenericValue value = null;
1242
1243            if (!primaryKey.isPrimaryKey()) {
1244                throw new GenericModelException("[GenericDelegator.findByPrimaryKey] Passed primary key is not a valid primary key: " + primaryKey);
1245            }
1246            this.evalEcaRules(EntityEcaHandler.EV_RUN, EntityEcaHandler.OP_FIND, primaryKey, ecaEventMap, (ecaEventMap == null), false);
1247            try {
1248                value = helper.findByPrimaryKey(primaryKey);
1249            } catch (GenericEntityNotFoundException e) {
1250                value = null;
1251            }
1252            if (value != null) {
1253                value.setDelegator(this);
1254                this.decryptFields(value);
1255            }
1256
1257            this.evalEcaRules(EntityEcaHandler.EV_RETURN, EntityEcaHandler.OP_FIND, primaryKey, ecaEventMap, (ecaEventMap == null), false);
1258            return value;
1259        } catch (GenericEntityException e) {
1260            String JavaDoc errMsg = "Failure in findByPrimaryKey operation for entity [" + primaryKey.getEntityName() + "]: " + e.toString() + ". Rolling back transaction.";
1261            Debug.logError(e, errMsg, module);
1262            try {
1263                // only rollback the transaction if we started one...
1264
TransactionUtil.rollback(beganTransaction, errMsg, e);
1265            } catch (GenericEntityException e2) {
1266                Debug.logError(e2, "[GenericDelegator] Could not rollback transaction: " + e2.toString(), module);
1267            }
1268            // after rolling back, rethrow the exception
1269
throw e;
1270        } finally {
1271            // only commit the transaction if we started one... this will throw an exception if it fails
1272
TransactionUtil.commit(beganTransaction);
1273        }
1274    }
1275
1276    /** Find a CACHED Generic Entity by its Primary Key
1277     *@param primaryKey The primary key to find by.
1278     *@return The GenericValue corresponding to the primaryKey
1279     */

1280    public GenericValue findByPrimaryKeyCache(GenericPK primaryKey) throws GenericEntityException {
1281        Map JavaDoc ecaEventMap = this.getEcaEntityEventMap(primaryKey.getEntityName());
1282        this.evalEcaRules(EntityEcaHandler.EV_CACHE_CHECK, EntityEcaHandler.OP_FIND, primaryKey, ecaEventMap, (ecaEventMap == null), false);
1283
1284        GenericValue value = this.getFromPrimaryKeyCache(primaryKey);
1285        if (value instanceof GenericEntity.NULL) return null;
1286        if (value == null) {
1287            value = findByPrimaryKey(primaryKey);
1288            if (value != null) {
1289                this.evalEcaRules(EntityEcaHandler.EV_CACHE_PUT, EntityEcaHandler.OP_FIND, primaryKey, ecaEventMap, (ecaEventMap == null), false);
1290                this.putInPrimaryKeyCache(primaryKey, value);
1291            } else {
1292                this.putInPrimaryKeyCache(primaryKey, GenericValue.NULL_VALUE);
1293            }
1294        }
1295        return value;
1296    }
1297
1298    /** Find a Generic Entity by its Primary Key
1299     *@param entityName The Name of the Entity as defined in the entity XML file
1300     *@param fields The fields of the named entity to query by with their corresponging values
1301     *@return The GenericValue corresponding to the primaryKey
1302     */

1303    public GenericValue findByPrimaryKey(String JavaDoc entityName, Map JavaDoc fields) throws GenericEntityException {
1304        return findByPrimaryKey(makePK(entityName, fields));
1305    }
1306
1307    /** Find a CACHED Generic Entity by its Primary Key
1308     *@param entityName The Name of the Entity as defined in the entity XML file
1309     *@param fields The fields of the named entity to query by with their corresponging values
1310     *@return The GenericValue corresponding to the primaryKey
1311     */

1312    public GenericValue findByPrimaryKeyCache(String JavaDoc entityName, Map JavaDoc fields) throws GenericEntityException {
1313        return findByPrimaryKeyCache(makePK(entityName, fields));
1314    }
1315
1316    /** Find a Generic Entity by its Primary Key and only returns the values requested by the passed keys (names)
1317     *@param primaryKey The primary key to find by.
1318     *@param keys The keys, or names, of the values to retrieve; only these values will be retrieved
1319     *@return The GenericValue corresponding to the primaryKey
1320     */

1321    public GenericValue findByPrimaryKeyPartial(GenericPK primaryKey, Set JavaDoc keys) throws GenericEntityException {
1322        boolean beganTransaction = false;
1323        try {
1324            if (alwaysUseTransaction) {
1325                beganTransaction = TransactionUtil.begin();
1326            }
1327
1328            Map JavaDoc ecaEventMap = this.getEcaEntityEventMap(primaryKey.getEntityName());
1329            this.evalEcaRules(EntityEcaHandler.EV_VALIDATE, EntityEcaHandler.OP_FIND, primaryKey, ecaEventMap, (ecaEventMap == null), false);
1330
1331            GenericHelper helper = getEntityHelper(primaryKey.getEntityName());
1332            GenericValue value = null;
1333
1334            if (!primaryKey.isPrimaryKey()) {
1335                throw new GenericModelException("[GenericDelegator.findByPrimaryKey] Passed primary key is not a valid primary key: " + primaryKey);
1336            }
1337
1338            this.evalEcaRules(EntityEcaHandler.EV_RUN, EntityEcaHandler.OP_FIND, primaryKey, ecaEventMap, (ecaEventMap == null), false);
1339            try {
1340                value = helper.findByPrimaryKeyPartial(primaryKey, keys);
1341            } catch (GenericEntityNotFoundException e) {
1342                value = null;
1343            }
1344            if (value != null) value.setDelegator(this);
1345
1346            this.evalEcaRules(EntityEcaHandler.EV_RETURN, EntityEcaHandler.OP_FIND, primaryKey, ecaEventMap, (ecaEventMap == null), false);
1347            return value;
1348        } catch (GenericEntityException e) {
1349            String JavaDoc errMsg = "Failure in findByPrimaryKeyPartial operation for entity [" + primaryKey.getEntityName() + "]: " + e.toString() + ". Rolling back transaction.";
1350            Debug.logError(e, errMsg, module);
1351            try {
1352                // only rollback the transaction if we started one...
1353
TransactionUtil.rollback(beganTransaction, errMsg, e);
1354            } catch (GenericEntityException e2) {
1355                Debug.logError(e2, "[GenericDelegator] Could not rollback transaction: " + e2.toString(), module);
1356            }
1357            // after rolling back, rethrow the exception
1358
throw e;
1359        } finally {
1360            // only commit the transaction if we started one... this will throw an exception if it fails
1361
TransactionUtil.commit(beganTransaction);
1362        }
1363    }
1364
1365    /** Find a number of Generic Value objects by their Primary Keys, all at once
1366     *@param primaryKeys A Collection of primary keys to find by.
1367     *@return List of GenericValue objects corresponding to the passed primaryKey objects
1368     */

1369    public List JavaDoc findAllByPrimaryKeys(Collection JavaDoc primaryKeys) throws GenericEntityException {
1370        boolean beganTransaction = false;
1371        try {
1372            if (alwaysUseTransaction) {
1373                beganTransaction = TransactionUtil.begin();
1374            }
1375
1376            //TODO: add eca eval calls
1377
//TODO: maybe this should use the internal findBy methods
1378
if (primaryKeys == null) return null;
1379            List JavaDoc results = FastList.newInstance();
1380
1381            // from the delegator level this is complicated because different GenericPK
1382
// objects in the list may correspond to different helpers
1383
Map JavaDoc pksPerHelper = FastMap.newInstance();
1384            Iterator JavaDoc pkiter = primaryKeys.iterator();
1385            while (pkiter.hasNext()) {
1386                GenericPK curPK = (GenericPK) pkiter.next();
1387                String JavaDoc helperName = this.getEntityHelperName(curPK.getEntityName());
1388                List JavaDoc pks = (List JavaDoc) pksPerHelper.get(helperName);
1389
1390                if (pks == null) {
1391                    pks = FastList.newInstance();
1392                    pksPerHelper.put(helperName, pks);
1393                }
1394                pks.add(curPK);
1395            }
1396
1397            Iterator JavaDoc helperIter = pksPerHelper.entrySet().iterator();
1398
1399            while (helperIter.hasNext()) {
1400                Map.Entry JavaDoc curEntry = (Map.Entry JavaDoc) helperIter.next();
1401                String JavaDoc helperName = (String JavaDoc) curEntry.getKey();
1402                GenericHelper helper = GenericHelperFactory.getHelper(helperName);
1403                List JavaDoc values = helper.findAllByPrimaryKeys((List JavaDoc) curEntry.getValue());
1404
1405                results.addAll(values);
1406            }
1407
1408            this.decryptFields(results);
1409            return results;
1410        } catch (GenericEntityException e) {
1411            String JavaDoc errMsg = "Failure in findAllByPrimaryKeys operation, rolling back transaction";
1412            Debug.logError(e, errMsg, module);
1413            try {
1414                // only rollback the transaction if we started one...
1415
TransactionUtil.rollback(beganTransaction, errMsg, e);
1416            } catch (GenericEntityException e2) {
1417                Debug.logError(e2, "[GenericDelegator] Could not rollback transaction: " + e2.toString(), module);
1418            }
1419            // after rolling back, rethrow the exception
1420
throw e;
1421        } finally {
1422            // only commit the transaction if we started one... this will throw an exception if it fails
1423
TransactionUtil.commit(beganTransaction);
1424        }
1425    }
1426
1427    /** Find a number of Generic Value objects by their Primary Keys, all at once;
1428     * this first looks in the local cache for each PK and if there then it puts it
1429     * in the return list rather than putting it in the batch to send to
1430     * a given helper.
1431     *@param primaryKeys A Collection of primary keys to find by.
1432     *@return List of GenericValue objects corresponding to the passed primaryKey objects
1433     */

1434    public List JavaDoc findAllByPrimaryKeysCache(Collection JavaDoc primaryKeys) throws GenericEntityException {
1435        boolean beganTransaction = false;
1436        try {
1437            if (alwaysUseTransaction) {
1438                beganTransaction = TransactionUtil.begin();
1439            }
1440
1441            //TODO: add eca eval calls
1442
//TODO: maybe this should use the internal findBy methods
1443
if (primaryKeys == null)
1444                return null;
1445            List JavaDoc results = FastList.newInstance();
1446
1447            // from the delegator level this is complicated because different GenericPK
1448
// objects in the list may correspond to different helpers
1449
Map JavaDoc pksPerHelper = FastMap.newInstance();
1450            Iterator JavaDoc pkiter = primaryKeys.iterator();
1451
1452            while (pkiter.hasNext()) {
1453                GenericPK curPK = (GenericPK) pkiter.next();
1454
1455                GenericValue value = this.getFromPrimaryKeyCache(curPK);
1456
1457                if (value != null) {
1458                    // it is in the cache, so just put the cached value in the results
1459
results.add(value);
1460                } else {
1461                    // is not in the cache, so put in a list for a call to the helper
1462
String JavaDoc helperName = this.getEntityHelperName(curPK.getEntityName());
1463                    List JavaDoc pks = (List JavaDoc) pksPerHelper.get(helperName);
1464
1465                    if (pks == null) {
1466                        pks = FastList.newInstance();
1467                        pksPerHelper.put(helperName, pks);
1468                    }
1469                    pks.add(curPK);
1470                }
1471            }
1472
1473            Iterator JavaDoc helperIter = pksPerHelper.entrySet().iterator();
1474
1475            while (helperIter.hasNext()) {
1476                Map.Entry JavaDoc curEntry = (Map.Entry JavaDoc) helperIter.next();
1477                String JavaDoc helperName = (String JavaDoc) curEntry.getKey();
1478                GenericHelper helper = GenericHelperFactory.getHelper(helperName);
1479                List JavaDoc values = helper.findAllByPrimaryKeys((List JavaDoc) curEntry.getValue());
1480
1481                this.putAllInPrimaryKeyCache(values);
1482                results.addAll(values);
1483            }
1484
1485            this.decryptFields(results);
1486            return results;
1487        } catch (GenericEntityException e) {
1488            String JavaDoc errMsg = "Failure in findAllByPrimaryKeysCache operation, rolling back transaction";
1489            Debug.logError(e, errMsg, module);
1490            try {
1491                // only rollback the transaction if we started one...
1492
TransactionUtil.rollback(beganTransaction, errMsg, e);
1493            } catch (GenericEntityException e2) {
1494                Debug.logError(e2, "[GenericDelegator] Could not rollback transaction: " + e2.toString(), module);
1495            }
1496            // after rolling back, rethrow the exception
1497
throw e;
1498        } finally {
1499            // only commit the transaction if we started one... this will throw an exception if it fails
1500
TransactionUtil.commit(beganTransaction);
1501        }
1502    }
1503
1504    /** Finds all Generic entities
1505     *@param entityName The Name of the Entity as defined in the entity XML file
1506     *@return List containing all Generic entities
1507     */

1508    public List JavaDoc findAll(String JavaDoc entityName) throws GenericEntityException {
1509        return this.findByAnd(entityName, FastMap.newInstance(), null);
1510    }
1511
1512    /** Finds all Generic entities
1513     *@param entityName The Name of the Entity as defined in the entity XML file
1514     *@param orderBy The fields of the named entity to order the query by; optionally add a " ASC" for ascending or " DESC" for descending
1515     *@return List containing all Generic entities
1516     */

1517    public List JavaDoc findAll(String JavaDoc entityName, List JavaDoc orderBy) throws GenericEntityException {
1518        return this.findByAnd(entityName, FastMap.newInstance(), orderBy);
1519    }
1520
1521    /** Finds all Generic entities, looking first in the cache
1522     *@param entityName The Name of the Entity as defined in the entity XML file
1523     *@return List containing all Generic entities
1524     */

1525    public List JavaDoc findAllCache(String JavaDoc entityName) throws GenericEntityException {
1526        return this.findAllCache(entityName, null);
1527    }
1528
1529    /** Finds all Generic entities, looking first in the cache; uses orderBy for lookup, but only keys results on the entityName and fields
1530     *@param entityName The Name of the Entity as defined in the entity XML file
1531     *@param orderBy The fields of the named entity to order the query by; optionally add a " ASC" for ascending or " DESC" for descending
1532     *@return List containing all Generic entities
1533     */

1534    public List JavaDoc findAllCache(String JavaDoc entityName, List JavaDoc orderBy) throws GenericEntityException {
1535        GenericValue dummyValue = makeValue(entityName, null);
1536        Map JavaDoc ecaEventMap = this.getEcaEntityEventMap(entityName);
1537        this.evalEcaRules(EntityEcaHandler.EV_CACHE_CHECK, EntityEcaHandler.OP_FIND, dummyValue, ecaEventMap, (ecaEventMap == null), false);
1538
1539        List JavaDoc lst = cache.get(entityName, null, orderBy);
1540
1541        if (lst == null) {
1542            lst = findAll(entityName, orderBy);
1543            if (lst != null) {
1544                this.evalEcaRules(EntityEcaHandler.EV_CACHE_PUT, EntityEcaHandler.OP_FIND, dummyValue, ecaEventMap, (ecaEventMap == null), false);
1545                cache.put(entityName, null, orderBy, lst);
1546            }
1547        }
1548        return lst;
1549    }
1550
1551    /** Finds Generic Entity records by all of the specified fields (ie: combined using AND)
1552     * @param entityName The Name of the Entity as defined in the entity XML file
1553     * @param fields The fields of the named entity to query by with their corresponging values
1554     * @return List of GenericValue instances that match the query
1555     */

1556    public List JavaDoc findByAnd(String JavaDoc entityName, Map JavaDoc fields) throws GenericEntityException {
1557        return this.findByAnd(entityName, fields, null);
1558    }
1559
1560    /** Finds Generic Entity records by all of the specified fields (ie: combined using OR)
1561     * @param entityName The Name of the Entity as defined in the entity XML file
1562     * @param fields The fields of the named entity to query by with their corresponging values
1563     * @return List of GenericValue instances that match the query
1564     */

1565    public List JavaDoc findByOr(String JavaDoc entityName, Map JavaDoc fields) throws GenericEntityException {
1566        return this.findByOr(entityName, fields, null);
1567    }
1568
1569    /** Finds Generic Entity records by all of the specified fields (ie: combined using AND)
1570     * @param entityName The Name of the Entity as defined in the entity XML file
1571     * @param fields The fields of the named entity to query by with their corresponging values
1572     * @param orderBy The fields of the named entity to order the query by;
1573     * optionally add a " ASC" for ascending or " DESC" for descending
1574     * @return List of GenericValue instances that match the query
1575     */

1576    public List JavaDoc findByAnd(String JavaDoc entityName, Map JavaDoc fields, List JavaDoc orderBy) throws GenericEntityException {
1577        EntityCondition ecl = new EntityFieldMap(fields, EntityOperator.AND);
1578        return findByCondition(entityName, ecl, null, orderBy);
1579    }
1580
1581    /* is this actually used anywhere? public List findByAnd(ModelEntity modelEntity, Map fields, List orderBy) throws GenericEntityException {
1582        EntityCondition ecl = new EntityFieldMap(fields, EntityOperator.AND);
1583        return findByCondition(modelEntity.getEntityName(), ecl, null, orderBy);
1584    }*/

1585
1586    /** Finds Generic Entity records by all of the specified fields (ie: combined using OR)
1587     * @param entityName The Name of the Entity as defined in the entity XML file
1588     * @param fields The fields of the named entity to query by with their corresponging values
1589     * @param orderBy The fields of the named entity to order the query by;
1590     * optionally add a " ASC" for ascending or " DESC" for descending
1591     * @return List of GenericValue instances that match the query
1592     */

1593    public List JavaDoc findByOr(String JavaDoc entityName, Map JavaDoc fields, List JavaDoc orderBy) throws GenericEntityException {
1594        EntityCondition ecl = new EntityFieldMap(fields, EntityOperator.OR);
1595        return findByCondition(entityName, ecl, null, orderBy);
1596    }
1597
1598    /** Finds Generic Entity records by all of the specified fields (ie: combined using AND), looking first in the cache; uses orderBy for lookup, but only keys results on the entityName and fields
1599     *@param entityName The Name of the Entity as defined in the entity XML file
1600     *@param fields The fields of the named entity to query by with their corresponging values
1601     *@return List of GenericValue instances that match the query
1602     */

1603    public List JavaDoc findByAndCache(String JavaDoc entityName, Map JavaDoc fields) throws GenericEntityException {
1604        return this.findByAndCache(entityName, fields, null);
1605    }
1606
1607    /** Finds Generic Entity records by all of the specified fields (ie: combined using AND), looking first in the cache; uses orderBy for lookup, but only keys results on the entityName and fields
1608     *@param entityName The Name of the Entity as defined in the entity XML file
1609     *@param fields The fields of the named entity to query by with their corresponging values
1610     *@param orderBy The fields of the named entity to order the query by; optionally add a " ASC" for ascending or " DESC" for descending
1611     *@return List of GenericValue instances that match the query
1612     */

1613    public List JavaDoc findByAndCache(String JavaDoc entityName, Map JavaDoc fields, List JavaDoc orderBy) throws GenericEntityException {
1614        return findByConditionCache(entityName, new EntityFieldMap(fields, EntityOperator.AND), null, orderBy);
1615    }
1616
1617    /** Finds Generic Entity records by all of the specified expressions (ie: combined using AND)
1618     *@param entityName The Name of the Entity as defined in the entity XML file
1619     *@param expressions The expressions to use for the lookup, each consisting of at least a field name, an EntityOperator, and a value to compare to
1620     *@return List of GenericValue instances that match the query
1621     */

1622    public List JavaDoc findByAnd(String JavaDoc entityName, List JavaDoc expressions) throws GenericEntityException {
1623        EntityConditionList ecl = new EntityConditionList(expressions, EntityOperator.AND);
1624        return findByCondition(entityName, ecl, null, null);
1625    }
1626
1627    /** Finds Generic Entity records by all of the specified expressions (ie: combined using AND)
1628     *@param entityName The Name of the Entity as defined in the entity XML file
1629     *@param expressions The expressions to use for the lookup, each consisting of at least a field name, an EntityOperator, and a value to compare to
1630     *@param orderBy The fields of the named entity to order the query by; optionally add a " ASC" for ascending or " DESC" for descending
1631     *@return List of GenericValue instances that match the query
1632     */

1633    public List JavaDoc findByAnd(String JavaDoc entityName, List JavaDoc expressions, List JavaDoc orderBy) throws GenericEntityException {
1634        EntityConditionList ecl = new EntityConditionList(expressions, EntityOperator.AND);
1635        return findByCondition(entityName, ecl, null, orderBy);
1636    }
1637
1638    /** Finds Generic Entity records by all of the specified expressions (ie: combined using OR)
1639     *@param entityName The Name of the Entity as defined in the entity XML file
1640     *@param expressions The expressions to use for the lookup, each consisting of at least a field name, an EntityOperator, and a value to compare to
1641     *@return List of GenericValue instances that match the query
1642     */

1643    public List JavaDoc findByOr(String JavaDoc entityName, List JavaDoc expressions) throws GenericEntityException {
1644        EntityConditionList ecl = new EntityConditionList(expressions, EntityOperator.OR);
1645        return findByCondition(entityName, ecl, null, null);
1646    }
1647
1648    /** Finds Generic Entity records by all of the specified expressions (ie: combined using OR)
1649     *@param entityName The Name of the Entity as defined in the entity XML file
1650     *@param expressions The expressions to use for the lookup, each consisting of at least a field name, an EntityOperator, and a value to compare to
1651     *@param orderBy The fields of the named entity to order the query by; optionally add a " ASC" for ascending or " DESC" for descending
1652     *@return List of GenericValue instances that match the query
1653     */

1654    public List JavaDoc findByOr(String JavaDoc entityName, List JavaDoc expressions, List JavaDoc orderBy) throws GenericEntityException {
1655        EntityConditionList ecl = new EntityConditionList(expressions, EntityOperator.OR);
1656        return findByCondition(entityName, ecl, null, orderBy);
1657    }
1658
1659    public List JavaDoc findByLike(String JavaDoc entityName, Map JavaDoc fields) throws GenericEntityException {
1660        return findByLike(entityName, fields, null);
1661    }
1662
1663    public List JavaDoc findByLike(String JavaDoc entityName, Map JavaDoc fields, List JavaDoc orderBy) throws GenericEntityException {
1664        List JavaDoc likeExpressions = FastList.newInstance();
1665        if (fields != null) {
1666            Iterator JavaDoc fieldEntries = fields.entrySet().iterator();
1667            while (fieldEntries.hasNext()) {
1668                Map.Entry JavaDoc fieldEntry = (Map.Entry JavaDoc) fieldEntries.next();
1669                likeExpressions.add(new EntityExpr((String JavaDoc) fieldEntry.getKey(), EntityOperator.LIKE, fieldEntry.getValue()));
1670            }
1671        }
1672        EntityConditionList ecl = new EntityConditionList(likeExpressions, EntityOperator.AND);
1673        return findByCondition(entityName, ecl, null, orderBy);
1674    }
1675
1676    /** Finds GenericValues by the conditions specified in the EntityCondition object, the the EntityCondition javadoc for more details.
1677     *@param entityName The Name of the Entity as defined in the entity model XML file
1678     *@param entityCondition The EntityCondition object that specifies how to constrain this query
1679     *@param fieldsToSelect The fields of the named entity to get from the database; if empty or null all fields will be retreived
1680     *@param orderBy The fields of the named entity to order the query by; optionally add a " ASC" for ascending or " DESC" for descending
1681     *@return List of GenericValue objects representing the result
1682     */

1683    public List JavaDoc findByCondition(String JavaDoc entityName, EntityCondition entityCondition, Collection JavaDoc fieldsToSelect, List JavaDoc orderBy) throws GenericEntityException {
1684        return this.findByCondition(entityName, entityCondition, null, fieldsToSelect, orderBy, null);
1685    }
1686
1687    /** Finds GenericValues by the conditions specified in the EntityCondition object, the the EntityCondition javadoc for more details.
1688     *@param entityName The name of the Entity as defined in the entity XML file
1689     *@param whereEntityCondition The EntityCondition object that specifies how to constrain this query before any groupings are done (if this is a view entity with group-by aliases)
1690     *@param havingEntityCondition The EntityCondition object that specifies how to constrain this query after any groupings are done (if this is a view entity with group-by aliases)
1691     *@param fieldsToSelect The fields of the named entity to get from the database; if empty or null all fields will be retreived
1692     *@param orderBy The fields of the named entity to order the query by; optionally add a " ASC" for ascending or " DESC" for descending
1693     *@param findOptions An instance of EntityFindOptions that specifies advanced query options. See the EntityFindOptions JavaDoc for more details.
1694     *@return List of GenericValue objects representing the result
1695     */

1696    public List JavaDoc findByCondition(String JavaDoc entityName, EntityCondition whereEntityCondition,
1697            EntityCondition havingEntityCondition, Collection JavaDoc fieldsToSelect, List JavaDoc orderBy, EntityFindOptions findOptions)
1698            throws GenericEntityException {
1699        boolean beganTransaction = false;
1700        try {
1701            if (alwaysUseTransaction) {
1702                beganTransaction = TransactionUtil.begin();
1703            }
1704
1705            EntityListIterator eli = this.findListIteratorByCondition(entityName, whereEntityCondition, havingEntityCondition, fieldsToSelect, orderBy, findOptions);
1706            eli.setDelegator(this);
1707            List JavaDoc list = eli.getCompleteList();
1708            eli.close();
1709
1710            return list;
1711        } catch (GenericEntityException e) {
1712            String JavaDoc errMsg = "Failure in findByCondition operation for entity [" + entityName + "]: " + e.toString() + ". Rolling back transaction.";
1713            Debug.logError(e, errMsg, module);
1714            try {
1715                // only rollback the transaction if we started one...
1716
TransactionUtil.rollback(beganTransaction, errMsg, e);
1717            } catch (GenericEntityException e2) {
1718                Debug.logError(e2, "[GenericDelegator] Could not rollback transaction: " + e2.toString(), module);
1719            }
1720            // after rolling back, rethrow the exception
1721
throw e;
1722        } finally {
1723            // only commit the transaction if we started one... this will throw an exception if it fails
1724
TransactionUtil.commit(beganTransaction);
1725        }
1726    }
1727
1728    /** Finds GenericValues by the conditions specified in the EntityCondition object, looking first in the cache, see the EntityCondition javadoc for more details.
1729     *@param entityName The Name of the Entity as defined in the entity model XML file
1730     *@param entityCondition The EntityCondition object that specifies how to constrain this query
1731     *@param fieldsToSelect The fields of the named entity to get from the database; if empty or null all fields will be retreived
1732     *@param orderBy The fields of the named entity to order the query by; optionally add a " ASC" for ascending or " DESC" for descending
1733     *@return List of GenericValue objects representing the result
1734     */

1735    public List JavaDoc findByConditionCache(String JavaDoc entityName, EntityCondition entityCondition, Collection JavaDoc fieldsToSelect, List JavaDoc orderBy) throws GenericEntityException {
1736        ModelEntity modelEntity = getModelReader().getModelEntity(entityName);
1737        GenericValue dummyValue = GenericValue.create(modelEntity);
1738        Map JavaDoc ecaEventMap = this.getEcaEntityEventMap(entityName);
1739        this.evalEcaRules(EntityEcaHandler.EV_CACHE_CHECK, EntityEcaHandler.OP_FIND, dummyValue, ecaEventMap, (ecaEventMap == null), false);
1740
1741        List JavaDoc lst = cache.get(entityName, entityCondition, orderBy);
1742
1743        if (lst == null) {
1744            lst = findByCondition(entityName, entityCondition, fieldsToSelect, orderBy);
1745            if (lst != null) {
1746                this.evalEcaRules(EntityEcaHandler.EV_CACHE_PUT, EntityEcaHandler.OP_FIND, dummyValue, ecaEventMap, (ecaEventMap == null), false);
1747                cache.put(entityName, entityCondition, orderBy, lst);
1748            }
1749        }
1750        return lst;
1751    }
1752
1753    /** Finds GenericValues by the conditions specified in the EntityCondition object, the the EntityCondition javadoc for more details.
1754     *@param entityName The Name of the Entity as defined in the entity model XML file
1755     *@param entityCondition The EntityCondition object that specifies how to constrain this query before any groupings are done (if this is a view entity with group-by aliases)
1756     *@param fieldsToSelect The fields of the named entity to get from the database; if empty or null all fields will be retreived
1757     *@param orderBy The fields of the named entity to order the query by; optionally add a " ASC" for ascending or " DESC" for descending
1758     *@return EntityListIterator representing the result of the query: NOTE THAT THIS MUST BE CLOSED WHEN YOU ARE
1759     * DONE WITH IT, AND DON'T LEAVE IT OPEN TOO LONG BEACUSE IT WILL MAINTAIN A DATABASE CONNECTION.
1760     */

1761    public EntityListIterator findListIteratorByCondition(String JavaDoc entityName, EntityCondition entityCondition,
1762            Collection JavaDoc fieldsToSelect, List JavaDoc orderBy) throws GenericEntityException {
1763        return this.findListIteratorByCondition(entityName, entityCondition, null, fieldsToSelect, orderBy, null);
1764    }
1765
1766    /** Finds GenericValues by the conditions specified in the EntityCondition object, the the EntityCondition javadoc for more details.
1767     *@param entityName The name of the Entity as defined in the entity XML file
1768     *@param whereEntityCondition The EntityCondition object that specifies how to constrain this query before any groupings are done (if this is a view entity with group-by aliases)
1769     *@param havingEntityCondition The EntityCondition object that specifies how to constrain this query after any groupings are done (if this is a view entity with group-by aliases)
1770     *@param fieldsToSelect The fields of the named entity to get from the database; if empty or null all fields will be retreived
1771     *@param orderBy The fields of the named entity to order the query by; optionally add a " ASC" for ascending or " DESC" for descending
1772     *@param findOptions An instance of EntityFindOptions that specifies advanced query options. See the EntityFindOptions JavaDoc for more details.
1773     *@return EntityListIterator representing the result of the query: NOTE THAT THIS MUST BE CLOSED WHEN YOU ARE
1774     * DONE WITH IT, AND DON'T LEAVE IT OPEN TOO LONG BEACUSE IT WILL MAINTAIN A DATABASE CONNECTION.
1775     */

1776    public EntityListIterator findListIteratorByCondition(String JavaDoc entityName, EntityCondition whereEntityCondition,
1777            EntityCondition havingEntityCondition, Collection JavaDoc fieldsToSelect, List JavaDoc orderBy, EntityFindOptions findOptions)
1778            throws GenericEntityException {
1779
1780        // if there is no transaction throw an exception, we don't want to create a transaction here since closing it would mess up the ELI
1781
if (!TransactionUtil.isTransactionInPlace()) {
1782            //throw new GenericEntityException("ERROR: Cannot do a find that returns an EntityListIterator with no transaction in place. Wrap this call in a transaction.");
1783

1784            //throwing an exception is a little harsh for now, just display a really big error message since we want to get all of these fixed...
1785
Exception JavaDoc newE = new Exception JavaDoc("Stack Trace");
1786            Debug.logError(newE, "ERROR: Cannot do a find that returns an EntityListIterator with no transaction in place. Wrap this call in a transaction.", module);
1787        }
1788
1789        ModelEntity modelEntity = getModelReader().getModelEntity(entityName);
1790        GenericValue dummyValue = GenericValue.create(modelEntity);
1791        Map JavaDoc ecaEventMap = this.getEcaEntityEventMap(modelEntity.getEntityName());
1792        this.evalEcaRules(EntityEcaHandler.EV_VALIDATE, EntityEcaHandler.OP_FIND, dummyValue, ecaEventMap, (ecaEventMap == null), false);
1793
1794        if (whereEntityCondition != null) {
1795            whereEntityCondition.checkCondition(modelEntity);
1796            whereEntityCondition.encryptConditionFields(modelEntity, this);
1797        }
1798        if (havingEntityCondition != null) {
1799            havingEntityCondition.checkCondition(modelEntity);
1800            havingEntityCondition.encryptConditionFields(modelEntity, this);
1801        }
1802
1803        this.evalEcaRules(EntityEcaHandler.EV_RUN, EntityEcaHandler.OP_FIND, dummyValue, ecaEventMap, (ecaEventMap == null), false);
1804        GenericHelper helper = getEntityHelper(modelEntity.getEntityName());
1805        EntityListIterator eli = helper.findListIteratorByCondition(modelEntity, whereEntityCondition,
1806                havingEntityCondition, fieldsToSelect, orderBy, findOptions);
1807        eli.setDelegator(this);
1808
1809        this.evalEcaRules(EntityEcaHandler.EV_RETURN, EntityEcaHandler.OP_FIND, dummyValue, ecaEventMap, (ecaEventMap == null), false);
1810        return eli;
1811    }
1812
1813    /** Finds GenericValues by the conditions specified in the EntityCondition object, the the EntityCondition javadoc for more details.
1814     *@param dynamicViewEntity The DynamicViewEntity to use for the entity model for this query; generally created on the fly for limited use
1815     *@param whereEntityCondition The EntityCondition object that specifies how to constrain this query before any groupings are done (if this is a view entity with group-by aliases)
1816     *@param havingEntityCondition The EntityCondition object that specifies how to constrain this query after any groupings are done (if this is a view entity with group-by aliases)
1817     *@param fieldsToSelect The fields of the named entity to get from the database; if empty or null all fields will be retreived
1818     *@param orderBy The fields of the named entity to order the query by; optionally add a " ASC" for ascending or " DESC" for descending
1819     *@param findOptions An instance of EntityFindOptions that specifies advanced query options. See the EntityFindOptions JavaDoc for more details.
1820     *@return EntityListIterator representing the result of the query: NOTE THAT THIS MUST BE CLOSED WHEN YOU ARE
1821     * DONE WITH IT, AND DON'T LEAVE IT OPEN TOO LONG BEACUSE IT WILL MAINTAIN A DATABASE CONNECTION.
1822     */

1823    public EntityListIterator findListIteratorByCondition(DynamicViewEntity dynamicViewEntity, EntityCondition whereEntityCondition,
1824            EntityCondition havingEntityCondition, Collection JavaDoc fieldsToSelect, List JavaDoc orderBy, EntityFindOptions findOptions)
1825            throws GenericEntityException {
1826
1827        // if there is no transaction throw an exception, we don't want to create a transaction here since closing it would mess up the ELI
1828
if (!TransactionUtil.isTransactionInPlace()) {
1829            //throw new GenericEntityException("ERROR: Cannot do a find that returns an EntityListIterator with no transaction in place. Wrap this call in a transaction.");
1830

1831            //throwing an exception is a little harsh for now, just display a really big error message since we want to get all of these fixed...
1832
Exception JavaDoc newE = new Exception JavaDoc("Stack Trace");
1833            Debug.logError(newE, "ERROR: Cannot do a find that returns an EntityListIterator with no transaction in place. Wrap this call in a transaction.", module);
1834        }
1835
1836        ModelViewEntity modelViewEntity = dynamicViewEntity.makeModelViewEntity(this);
1837        if (whereEntityCondition != null) whereEntityCondition.checkCondition(modelViewEntity);
1838        if (havingEntityCondition != null) havingEntityCondition.checkCondition(modelViewEntity);
1839
1840        GenericHelper helper = getEntityHelper(dynamicViewEntity.getOneRealEntityName());
1841        EntityListIterator eli = helper.findListIteratorByCondition(modelViewEntity, whereEntityCondition,
1842                havingEntityCondition, fieldsToSelect, orderBy, findOptions);
1843        eli.setDelegator(this);
1844        //TODO: add decrypt fields
1845
return eli;
1846    }
1847
1848    public long findCountByAnd(String JavaDoc entityName, Map JavaDoc fields) throws GenericEntityException {
1849        return findCountByCondition(entityName, new EntityFieldMap(fields, EntityOperator.AND), null);
1850    }
1851
1852    public long findCountByCondition(String JavaDoc entityName, EntityCondition whereEntityCondition,
1853            EntityCondition havingEntityCondition) throws GenericEntityException {
1854
1855        boolean beganTransaction = false;
1856        try {
1857            if (alwaysUseTransaction) {
1858                beganTransaction = TransactionUtil.begin();
1859            }
1860
1861            ModelEntity modelEntity = getModelReader().getModelEntity(entityName);
1862            GenericValue dummyValue = GenericValue.create(modelEntity);
1863            Map JavaDoc ecaEventMap = this.getEcaEntityEventMap(modelEntity.getEntityName());
1864            this.evalEcaRules(EntityEcaHandler.EV_VALIDATE, EntityEcaHandler.OP_FIND, dummyValue, ecaEventMap, (ecaEventMap == null), false);
1865
1866            if (whereEntityCondition != null) {
1867                whereEntityCondition.checkCondition(modelEntity);
1868                whereEntityCondition.encryptConditionFields(modelEntity, this);
1869            }
1870            if (havingEntityCondition != null) {
1871                havingEntityCondition.checkCondition(modelEntity);
1872                havingEntityCondition.encryptConditionFields(modelEntity, this);
1873            }
1874
1875            this.evalEcaRules(EntityEcaHandler.EV_RUN, EntityEcaHandler.OP_FIND, dummyValue, ecaEventMap, (ecaEventMap == null), false);
1876            GenericHelper helper = getEntityHelper(modelEntity.getEntityName());
1877            long count = helper.findCountByCondition(modelEntity, whereEntityCondition, havingEntityCondition);
1878
1879            this.evalEcaRules(EntityEcaHandler.EV_RETURN, EntityEcaHandler.OP_FIND, dummyValue, ecaEventMap, (ecaEventMap == null), false);
1880            return count;
1881        } catch (GenericEntityException e) {
1882            String JavaDoc errMsg = "Failure in findListIteratorByCondition operation for entity [DynamicView]: " + e.toString() + ". Rolling back transaction.";
1883            Debug.logError(e, errMsg, module);
1884            try {
1885                // only rollback the transaction if we started one...
1886
TransactionUtil.rollback(beganTransaction, errMsg, e);
1887            } catch (GenericEntityException e2) {
1888                Debug.logError(e2, "[GenericDelegator] Could not rollback transaction: " + e2.toString(), module);
1889            }
1890            // after rolling back, rethrow the exception
1891
throw e;
1892        } finally {
1893            // only commit the transaction if we started one... this will throw an exception if it fails
1894
TransactionUtil.commit(beganTransaction);
1895        }
1896    }
1897
1898    /**
1899     * Get the named Related Entity for the GenericValue from the persistent store across another Relation.
1900     * Helps to get related Values in a multi-to-multi relationship.
1901     * @param relationNameOne String containing the relation name which is the
1902     * combination of relation.title and relation.rel-entity-name as
1903     * specified in the entity XML definition file, for first relation
1904     * @param relationNameTwo String containing the relation name for second relation
1905     * @param value GenericValue instance containing the entity
1906     * @param orderBy The fields of the named entity to order the query by; may be null;
1907     * optionally add a " ASC" for ascending or " DESC" for descending
1908     * @return List of GenericValue instances as specified in the relation definition
1909     */

1910    public List JavaDoc getMultiRelation(GenericValue value, String JavaDoc relationNameOne, String JavaDoc relationNameTwo, List JavaDoc orderBy) throws GenericEntityException {
1911        boolean beganTransaction = false;
1912        try {
1913            if (alwaysUseTransaction) {
1914                beganTransaction = TransactionUtil.begin();
1915            }
1916
1917            //TODO: add eca eval calls
1918
// traverse the relationships
1919
ModelEntity modelEntity = value.getModelEntity();
1920            ModelRelation modelRelationOne = modelEntity.getRelation(relationNameOne);
1921            ModelEntity modelEntityOne = getModelEntity(modelRelationOne.getRelEntityName());
1922            ModelRelation modelRelationTwo = modelEntityOne.getRelation(relationNameTwo);
1923            ModelEntity modelEntityTwo = getModelEntity(modelRelationTwo.getRelEntityName());
1924
1925            GenericHelper helper = getEntityHelper(modelEntity);
1926
1927            return helper.findByMultiRelation(value, modelRelationOne, modelEntityOne, modelRelationTwo, modelEntityTwo, orderBy);
1928        } catch (GenericEntityException e) {
1929            String JavaDoc errMsg = "Failure in getMultiRelation operation for entity [" + value.getEntityName() + "]: " + e.toString() + ". Rolling back transaction.";
1930            Debug.logError(e, errMsg, module);
1931            try {
1932                // only rollback the transaction if we started one...
1933
TransactionUtil.rollback(beganTransaction, errMsg, e);
1934            } catch (GenericEntityException e2) {
1935                Debug.logError(e2, "[GenericDelegator] Could not rollback transaction: " + e2.toString(), module);
1936            }
1937            // after rolling back, rethrow the exception
1938
throw e;
1939        } finally {
1940            // only commit the transaction if we started one... this will throw an exception if it fails
1941
TransactionUtil.commit(beganTransaction);
1942        }
1943    }
1944
1945    /**
1946     * Get the named Related Entity for the GenericValue from the persistent store across another Relation.
1947     * Helps to get related Values in a multi-to-multi relationship.
1948     * @param relationNameOne String containing the relation name which is the
1949     * combination of relation.title and relation.rel-entity-name as
1950     * specified in the entity XML definition file, for first relation
1951     * @param relationNameTwo String containing the relation name for second relation
1952     * @param value GenericValue instance containing the entity
1953     * @return List of GenericValue instances as specified in the relation definition
1954     */

1955    public List JavaDoc getMultiRelation(GenericValue value, String JavaDoc relationNameOne, String JavaDoc relationNameTwo) throws GenericEntityException {
1956        return getMultiRelation(value, relationNameOne, relationNameTwo, null);
1957    }
1958
1959    /** Get the named Related Entity for the GenericValue from the persistent store
1960     * @param relationName String containing the relation name which is the
1961     * combination of relation.title and relation.rel-entity-name as
1962     * specified in the entity XML definition file
1963     * @param value GenericValue instance containing the entity
1964     * @return List of GenericValue instances as specified in the relation definition
1965     */

1966    public List JavaDoc getRelated(String JavaDoc relationName, GenericValue value) throws GenericEntityException {
1967        return getRelated(relationName, null, null, value);
1968    }
1969
1970    /** Get the named Related Entity for the GenericValue from the persistent store
1971     * @param relationName String containing the relation name which is the
1972     * combination of relation.title and relation.rel-entity-name as
1973     * specified in the entity XML definition file
1974     * @param byAndFields the fields that must equal in order to keep; may be null
1975     * @param value GenericValue instance containing the entity
1976     * @return List of GenericValue instances as specified in the relation definition
1977     */

1978    public List JavaDoc getRelatedByAnd(String JavaDoc relationName, Map JavaDoc byAndFields, GenericValue value) throws GenericEntityException {
1979        return this.getRelated(relationName, byAndFields, null, value);
1980    }
1981
1982    /** Get the named Related Entity for the GenericValue from the persistent store
1983     * @param relationName String containing the relation name which is the
1984     * combination of relation.title and relation.rel-entity-name as
1985     * specified in the entity XML definition file
1986     * @param orderBy The fields of the named entity to order the query by; may be null;
1987     * optionally add a " ASC" for ascending or " DESC" for descending
1988     * @param value GenericValue instance containing the entity
1989     * @return List of GenericValue instances as specified in the relation definition
1990     */

1991    public List JavaDoc getRelatedOrderBy(String JavaDoc relationName, List JavaDoc orderBy, GenericValue value) throws GenericEntityException {
1992        return this.getRelated(relationName, null, orderBy, value);
1993    }
1994
1995    /** Get the named Related Entity for the GenericValue from the persistent store
1996     * @param relationName String containing the relation name which is the
1997     * combination of relation.title and relation.rel-entity-name as
1998     * specified in the entity XML definition file
1999     * @param byAndFields the fields that must equal in order to keep; may be null
2000     * @param orderBy The fields of the named entity to order the query by; may be null;
2001     * optionally add a " ASC" for ascending or " DESC" for descending
2002     * @param value GenericValue instance containing the entity
2003     * @return List of GenericValue instances as specified in the relation definition
2004     */

2005    public List JavaDoc getRelated(String JavaDoc relationName, Map JavaDoc byAndFields, List JavaDoc orderBy, GenericValue value) throws GenericEntityException {
2006        ModelEntity modelEntity = value.getModelEntity();
2007        ModelRelation relation = modelEntity.getRelation(relationName);
2008
2009        if (relation == null) {
2010            throw new GenericModelException("Could not find relation for relationName: " + relationName + " for value " + value);
2011        }
2012
2013        // put the byAndFields (if not null) into the hash map first,
2014
// they will be overridden by value's fields if over-specified this is important for security and cleanliness
2015
Map JavaDoc fields = FastMap.newInstance();
2016        if (byAndFields != null) fields.putAll(byAndFields);
2017        for (int i = 0; i < relation.getKeyMapsSize(); i++) {
2018            ModelKeyMap keyMap = relation.getKeyMap(i);
2019            fields.put(keyMap.getRelFieldName(), value.get(keyMap.getFieldName()));
2020        }
2021
2022        return this.findByAnd(relation.getRelEntityName(), fields, orderBy);
2023    }
2024
2025    /** Get a dummy primary key for the named Related Entity for the GenericValue
2026     * @param relationName String containing the relation name which is the
2027     * combination of relation.title and relation.rel-entity-name as
2028     * specified in the entity XML definition file
2029     * @param byAndFields the fields that must equal in order to keep; may be null
2030     * @param value GenericValue instance containing the entity
2031     * @return GenericPK containing a possibly incomplete PrimaryKey object representing the related entity or entities
2032     */

2033    public GenericPK getRelatedDummyPK(String JavaDoc relationName, Map JavaDoc byAndFields, GenericValue value) throws GenericEntityException {
2034        ModelEntity modelEntity = value.getModelEntity();
2035        ModelRelation relation = modelEntity.getRelation(relationName);
2036
2037        if (relation == null) {
2038            throw new GenericModelException("Could not find relation for relationName: " + relationName + " for value " + value);
2039        }
2040        ModelEntity relatedEntity = getModelReader().getModelEntity(relation.getRelEntityName());
2041
2042        // put the byAndFields (if not null) into the hash map first,
2043
// they will be overridden by value's fields if over-specified this is important for security and cleanliness
2044
Map JavaDoc fields = FastMap.newInstance();
2045        if (byAndFields != null) fields.putAll(byAndFields);
2046        for (int i = 0; i < relation.getKeyMapsSize(); i++) {
2047            ModelKeyMap keyMap = relation.getKeyMap(i);
2048            fields.put(keyMap.getRelFieldName(), value.get(keyMap.getFieldName()));
2049        }
2050
2051        GenericPK dummyPK = GenericPK.create(relatedEntity, fields);
2052        dummyPK.setDelegator(this);
2053        return dummyPK;
2054    }
2055
2056    /** Get the named Related Entity for the GenericValue from the persistent store, checking first in the cache to see if the desired value is there
2057     * @param relationName String containing the relation name which is the
2058     * combination of relation.title and relation.rel-entity-name as
2059     * specified in the entity XML definition file
2060     * @param value GenericValue instance containing the entity
2061     * @return List of GenericValue instances as specified in the relation definition
2062     */

2063    public List JavaDoc getRelatedCache(String JavaDoc relationName, GenericValue value) throws GenericEntityException {
2064        ModelEntity modelEntity = value.getModelEntity();
2065        ModelRelation relation = modelEntity.getRelation(relationName);
2066
2067        if (relation == null) {
2068            throw new GenericModelException("Could not find relation for relationName: " + relationName + " for value " + value);
2069        }
2070
2071        Map JavaDoc fields = FastMap.newInstance();
2072        for (int i = 0; i < relation.getKeyMapsSize(); i++) {
2073            ModelKeyMap keyMap = relation.getKeyMap(i);
2074            fields.put(keyMap.getRelFieldName(), value.get(keyMap.getFieldName()));
2075        }
2076
2077        return this.findByAndCache(relation.getRelEntityName(), fields, null);
2078    }
2079
2080    /** Get related entity where relation is of type one, uses findByPrimaryKey
2081     * @throws IllegalArgumentException if the list found has more than one item
2082     */

2083    public GenericValue getRelatedOne(String JavaDoc relationName, GenericValue value) throws GenericEntityException {
2084        ModelRelation relation = value.getModelEntity().getRelation(relationName);
2085
2086        if (relation == null) {
2087            throw new GenericModelException("Could not find relation for relationName: " + relationName + " for value " + value);
2088        }
2089        if (!"one".equals(relation.getType()) && !"one-nofk".equals(relation.getType())) {
2090            throw new GenericModelException("Relation is not a 'one' or a 'one-nofk' relation: " + relationName + " of entity " + value.getEntityName());
2091        }
2092
2093        Map JavaDoc fields = FastMap.newInstance();
2094        for (int i = 0; i < relation.getKeyMapsSize(); i++) {
2095            ModelKeyMap keyMap = relation.getKeyMap(i);
2096            fields.put(keyMap.getRelFieldName(), value.get(keyMap.getFieldName()));
2097        }
2098
2099        return this.findByPrimaryKey(relation.getRelEntityName(), fields);
2100    }
2101
2102    /** Get related entity where relation is of type one, uses findByPrimaryKey, checking first in the cache to see if the desired value is there
2103     * @throws IllegalArgumentException if the list found has more than one item
2104     */

2105    public GenericValue getRelatedOneCache(String JavaDoc relationName, GenericValue value) throws GenericEntityException {
2106        ModelEntity modelEntity = value.getModelEntity();
2107        ModelRelation relation = modelEntity.getRelation(relationName);
2108
2109        if (relation == null) {
2110            throw new GenericModelException("Could not find relation for relationName: " + relationName + " for value " + value);
2111        }
2112        if (!"one".equals(relation.getType()) && !"one-nofk".equals(relation.getType())) {
2113            throw new GenericModelException("Relation is not a 'one' or a 'one-nofk' relation: " + relationName + " of entity " + value.getEntityName());
2114        }
2115
2116        Map JavaDoc fields = FastMap.newInstance();
2117        for (int i = 0; i < relation.getKeyMapsSize(); i++) {
2118            ModelKeyMap keyMap = relation.getKeyMap(i);
2119            fields.put(keyMap.getRelFieldName(), value.get(keyMap.getFieldName()));
2120        }
2121
2122        return this.findByPrimaryKeyCache(relation.getRelEntityName(), fields);
2123    }
2124
2125
2126    // ======================================
2127
// ======= Cache Related Methods ========
2128
// ======================================
2129

2130    /** This method is a shortcut to completely clear all entity engine caches.
2131     * For performance reasons this should not be called very often.
2132     */

2133    public void clearAllCaches() {
2134        this.clearAllCaches(true);
2135    }
2136
2137    public void clearAllCaches(boolean distribute) {
2138        cache.clear();
2139
2140        if (distribute && this.distributedCacheClear != null) {
2141            this.distributedCacheClear.clearAllCaches();
2142        }
2143    }
2144
2145    /** Remove a CACHED Generic Entity (List) from the cache, either a PK, ByAnd, or All
2146     *@param entityName The Name of the Entity as defined in the entity XML file
2147     *@param fields The fields of the named entity to query by with their corresponging values
2148     */

2149    public void clearCacheLine(String JavaDoc entityName, Map JavaDoc fields) {
2150        // if no fields passed, do the all cache quickly and return
2151
if (fields == null) {
2152            cache.remove(entityName);
2153            return;
2154        }
2155
2156        ModelEntity entity = this.getModelEntity(entityName);
2157        if (entity == null) {
2158            throw new IllegalArgumentException JavaDoc("[GenericDelegator.clearCacheLine] could not find entity for entityName: " + entityName);
2159        }
2160        //if never cached, then don't bother clearing
2161
if (entity.getNeverCache()) return;
2162
2163        GenericValue dummyValue = GenericValue.create(entity, fields);
2164        dummyValue.setDelegator(this);
2165        this.clearCacheLineFlexible(dummyValue);
2166    }
2167
2168    /** Remove a CACHED Generic Entity from the cache by its primary key.
2169     * Checks to see if the passed GenericPK is a complete primary key, if
2170     * it is then the cache line will be removed from the primaryKeyCache; if it
2171     * is NOT a complete primary key it will remove the cache line from the andCache.
2172     * If the fields map is empty, then the allCache for the entity will be cleared.
2173     *@param dummyPK The dummy primary key to clear by.
2174     */

2175    public void clearCacheLineFlexible(GenericEntity dummyPK) {
2176        this.clearCacheLineFlexible(dummyPK, true);
2177    }
2178
2179    public void clearCacheLineFlexible(GenericEntity dummyPK, boolean distribute) {
2180        if (dummyPK != null) {
2181            //if never cached, then don't bother clearing
2182
if (dummyPK.getModelEntity().getNeverCache()) return;
2183
2184            cache.remove(dummyPK);
2185
2186            if (distribute && this.distributedCacheClear != null) {
2187                this.distributedCacheClear.distributedClearCacheLineFlexible(dummyPK);
2188            }
2189        }
2190    }
2191
2192    protected void clearCacheValues(UtilCache cache, String JavaDoc entityName, EntityCondition condition) {
2193        Iterator JavaDoc iterator = cache.cacheLineTable.values().iterator();
2194        while (iterator.hasNext()) {
2195            CacheLine line = (CacheLine) iterator.next();
2196            GenericValue value = (GenericValue) line.getValue();
2197            if (value != null && value.getEntityName().equals(entityName) && condition.entityMatches(value)) {
2198                iterator.remove();
2199            }
2200        }
2201    }
2202
2203    public void clearCacheLineByCondition(String JavaDoc entityName, EntityCondition condition) {
2204        clearCacheLineByCondition(entityName, condition, true);
2205    }
2206
2207    public void clearCacheLineByCondition(String JavaDoc entityName, EntityCondition condition, boolean distribute) {
2208        if (entityName != null) {
2209            //if never cached, then don't bother clearing
2210
if (getModelEntity(entityName).getNeverCache()) return;
2211
2212            cache.remove(entityName, condition);
2213
2214            if (distribute && this.distributedCacheClear != null) {
2215                this.distributedCacheClear.distributedClearCacheLineByCondition(entityName, condition);
2216            }
2217        }
2218    }
2219
2220    /** Remove a CACHED Generic Entity from the cache by its primary key, does NOT
2221     * check to see if the passed GenericPK is a complete primary key.
2222     * Also tries to clear the corresponding all cache entry.
2223     *@param primaryKey The primary key to clear by.
2224     */

2225    public void clearCacheLine(GenericPK primaryKey) {
2226        this.clearCacheLine(primaryKey, true);
2227    }
2228
2229    public void clearCacheLine(GenericPK primaryKey, boolean distribute) {
2230        if (primaryKey == null) return;
2231
2232        //if never cached, then don't bother clearing
2233
if (primaryKey.getModelEntity().getNeverCache()) return;
2234
2235        cache.remove(primaryKey);
2236
2237        if (distribute && this.distributedCacheClear != null) {
2238            this.distributedCacheClear.distributedClearCacheLine(primaryKey);
2239        }
2240    }
2241
2242    /** Remove a CACHED GenericValue from as many caches as it can. Automatically
2243     * tries to remove entries from the all cache, the by primary key cache, and
2244     * the by and cache. This is the ONLY method that tries to clear automatically
2245     * from the by and cache.
2246     *@param value The GenericValue to clear by.
2247     */

2248    public void clearCacheLine(GenericValue value) {
2249        this.clearCacheLine(value, true);
2250    }
2251
2252    public void clearCacheLine(GenericValue value, boolean distribute) {
2253        // TODO: make this a bit more intelligent by passing in the operation being done (create, update, remove) so we can not do unnecessary cache clears...
2254
// for instance:
2255
// on create don't clear by primary cache (and won't clear original values because there won't be any)
2256
// on remove don't clear by and for new values, but do for original values
2257

2258        // Debug.logInfo("running clearCacheLine for value: " + value + ", distribute: " + distribute, module);
2259
if (value == null) return;
2260
2261        //if never cached, then don't bother clearing
2262
if (value.getModelEntity().getNeverCache()) return;
2263
2264        cache.remove(value);
2265
2266        if (distribute && this.distributedCacheClear != null) {
2267            this.distributedCacheClear.distributedClearCacheLine(value);
2268        }
2269    }
2270
2271    public void clearAllCacheLinesByDummyPK(Collection JavaDoc dummyPKs) {
2272        if (dummyPKs == null) return;
2273        Iterator JavaDoc iter = dummyPKs.iterator();
2274
2275        while (iter.hasNext()) {
2276            GenericEntity entity = (GenericEntity) iter.next();
2277
2278            this.clearCacheLineFlexible(entity);
2279        }
2280    }
2281
2282    public void clearAllCacheLinesByValue(Collection JavaDoc values) {
2283        if (values == null) return;
2284        Iterator JavaDoc iter = values.iterator();
2285
2286        while (iter.hasNext()) {
2287            GenericValue value = (GenericValue) iter.next();
2288
2289            this.clearCacheLine(value);
2290        }
2291    }
2292
2293    public GenericValue getFromPrimaryKeyCache(GenericPK primaryKey) {
2294        if (primaryKey == null) return null;
2295        return (GenericValue) cache.get(primaryKey);
2296    }
2297
2298    public void putInPrimaryKeyCache(GenericPK primaryKey, GenericValue value) {
2299        if (primaryKey == null) return;
2300
2301        if (primaryKey.getModelEntity().getNeverCache()) {
2302            Debug.logWarning("Tried to put a value of the " + value.getEntityName() + " entity in the BY PRIMARY KEY cache but this entity has never-cache set to true, not caching.", module);
2303            return;
2304        }
2305
2306        // before going into the cache, make this value immutable
2307
value.setImmutable();
2308        cache.put(primaryKey, value);
2309    }
2310
2311    public void putAllInPrimaryKeyCache(List JavaDoc values) {
2312        if (values == null) return;
2313        Iterator JavaDoc iter = values.iterator();
2314        while (iter.hasNext()) {
2315            GenericValue value = (GenericValue) iter.next();
2316            this.putInPrimaryKeyCache(value.getPrimaryKey(), value);
2317        }
2318    }
2319
2320    public void setDistributedCacheClear(DistributedCacheClear distributedCacheClear) {
2321        this.distributedCacheClear = distributedCacheClear;
2322    }
2323
2324    // ======= XML Related Methods ========
2325
public List JavaDoc readXmlDocument(URL JavaDoc url) throws SAXException JavaDoc, ParserConfigurationException JavaDoc, java.io.IOException JavaDoc {
2326        if (url == null) return null;
2327        return this.makeValues(UtilXml.readXmlDocument(url, false));
2328    }
2329
2330    public List JavaDoc makeValues(Document JavaDoc document) {
2331        if (document == null) return null;
2332        List JavaDoc values = FastList.newInstance();
2333
2334        Element JavaDoc docElement = document.getDocumentElement();
2335
2336        if (docElement == null)
2337            return null;
2338        if (!"entity-engine-xml".equals(docElement.getTagName())) {
2339            Debug.logError("[GenericDelegator.makeValues] Root node was not <entity-engine-xml>", module);
2340            throw new java.lang.IllegalArgumentException JavaDoc("Root node was not <entity-engine-xml>");
2341        }
2342        docElement.normalize();
2343        Node JavaDoc curChild = docElement.getFirstChild();
2344
2345        if (curChild != null) {
2346            do {
2347                if (curChild.getNodeType() == Node.ELEMENT_NODE) {
2348                    Element JavaDoc element = (Element JavaDoc) curChild;
2349                    GenericValue value = this.makeValue(element);
2350
2351                    if (value != null)
2352                        values.add(value);
2353                }
2354            } while ((curChild = curChild.getNextSibling()) != null);
2355        } else {
2356            Debug.logWarning("[GenericDelegator.makeValues] No child nodes found in document.", module);
2357        }
2358
2359        return values;
2360    }
2361
2362    public GenericPK makePK(Element JavaDoc element) {
2363        GenericValue value = makeValue(element);
2364
2365        return value.getPrimaryKey();
2366    }
2367
2368    public GenericValue makeValue(Element JavaDoc element) {
2369        if (element == null) return null;
2370        String JavaDoc entityName = element.getTagName();
2371
2372        // if a dash or colon is in the tag name, grab what is after it
2373
if (entityName.indexOf('-') > 0)
2374            entityName = entityName.substring(entityName.indexOf('-') + 1);
2375        if (entityName.indexOf(':') > 0)
2376            entityName = entityName.substring(entityName.indexOf(':') + 1);
2377        GenericValue value = this.makeValue(entityName, null);
2378
2379        ModelEntity modelEntity = value.getModelEntity();
2380
2381        Iterator JavaDoc modelFields = modelEntity.getFieldsIterator();
2382
2383        while (modelFields.hasNext()) {
2384            ModelField modelField = (ModelField) modelFields.next();
2385            String JavaDoc name = modelField.getName();
2386            String JavaDoc attr = element.getAttribute(name);
2387
2388            if (attr != null && attr.length() > 0) {
2389                value.setString(name, attr);
2390            } else {
2391                // if no attribute try a subelement
2392
Element JavaDoc subElement = UtilXml.firstChildElement(element, name);
2393
2394                if (subElement != null) {
2395                    value.setString(name, UtilXml.elementValue(subElement));
2396                }
2397            }
2398        }
2399
2400        return value;
2401    }
2402
2403    // ======= Misc Methods ========
2404

2405    protected Map JavaDoc getEcaEntityEventMap(String JavaDoc entityName) {
2406        if (this.entityEcaHandler == null) return null;
2407        Map JavaDoc ecaEventMap = this.entityEcaHandler.getEntityEventMap(entityName);
2408        //Debug.logWarning("for entityName " + entityName + " got ecaEventMap: " + ecaEventMap, module);
2409
return ecaEventMap;
2410    }
2411
2412    protected void evalEcaRules(String JavaDoc event, String JavaDoc currentOperation, GenericEntity value, Map JavaDoc eventMap, boolean noEventMapFound, boolean isError) throws GenericEntityException {
2413        // if this is true then it means that the caller had looked for an event map but found none for this entity
2414
if (noEventMapFound) return;
2415        if (this.entityEcaHandler == null) return;
2416        //if (!"find".equals(currentOperation)) Debug.logWarning("evalRules for entity " + value.getEntityName() + ", currentOperation " + currentOperation + ", event " + event, module);
2417
this.entityEcaHandler.evalRules(currentOperation, eventMap, event, value, isError);
2418    }
2419
2420    public void setEntityEcaHandler(EntityEcaHandler entityEcaHandler) {
2421        this.entityEcaHandler = entityEcaHandler;
2422    }
2423
2424    public EntityEcaHandler getEntityEcaHandler() {
2425        return this.entityEcaHandler;
2426    }
2427
2428    /** Get the next guaranteed unique seq id from the sequence with the given sequence name;
2429     * if the named sequence doesn't exist, it will be created
2430     *@param seqName The name of the sequence to get the next seq id from
2431     *@return String with the next sequenced id for the given sequence name
2432     */

2433    public String JavaDoc getNextSeqId(String JavaDoc seqName) {
2434        return this.getNextSeqId(seqName, 1);
2435    }
2436
2437    /** Get the next guaranteed unique seq id from the sequence with the given sequence name;
2438     * if the named sequence doesn't exist, it will be created
2439     *@param seqName The name of the sequence to get the next seq id from
2440     *@param staggerMax The maximum amount to stagger the sequenced ID, if 1 the sequence will be incremented by 1, otherwise the current sequence ID will be incremented by a value between 1 and staggerMax
2441     *@return Long with the next seq id for the given sequence name
2442     */

2443    public String JavaDoc getNextSeqId(String JavaDoc seqName, long staggerMax) {
2444        boolean beganTransaction = false;
2445        try {
2446            if (alwaysUseTransaction) {
2447                beganTransaction = TransactionUtil.begin();
2448            }
2449
2450            Long JavaDoc nextSeqLong = this.getNextSeqIdLong(seqName, staggerMax);
2451
2452            if (nextSeqLong == null) {
2453                throw new IllegalArgumentException JavaDoc("Could not get next sequenced ID for sequence name: " + seqName);
2454            }
2455
2456            if (UtilValidate.isNotEmpty(this.getDelegatorInfo().sequencedIdPrefix)) {
2457                return this.getDelegatorInfo().sequencedIdPrefix + nextSeqLong.toString();
2458            } else {
2459                return nextSeqLong.toString();
2460            }
2461        } catch (Exception JavaDoc e) {
2462            String JavaDoc errMsg = "Failure in getNextSeqId operation for seqName [" + seqName + "]: " + e.toString() + ". Rolling back transaction";
2463            Debug.logError(e, errMsg, module);
2464            try {
2465                // only rollback the transaction if we started one...
2466
TransactionUtil.rollback(beganTransaction, errMsg, e);
2467            } catch (GenericEntityException e2) {
2468                Debug.logError(e2, "[GenericDelegator] Could not rollback transaction: " + e2.toString(), module);
2469            }
2470            Debug.logError(e, "[GenericDelegator] Error getting next sequence ID: " + e.toString(), module);
2471            return null;
2472        } finally {
2473            try {
2474                // only commit the transaction if we started one...
2475
TransactionUtil.commit(beganTransaction);
2476            } catch (GenericTransactionException e1) {
2477                Debug.logError(e1, "[GenericDelegator] Could not commit transaction: " + e1.toString(), module);
2478            }
2479        }
2480    }
2481
2482    /** Get the next guaranteed unique seq id from the sequence with the given sequence name;
2483     * if the named sequence doesn't exist, it will be created
2484     *@param seqName The name of the sequence to get the next seq id from
2485     *@return Long with the next sequenced id for the given sequence name
2486     */

2487    public Long JavaDoc getNextSeqIdLong(String JavaDoc seqName) {
2488        return this.getNextSeqIdLong(seqName, 1);
2489    }
2490
2491    /** Get the next guaranteed unique seq id from the sequence with the given sequence name;
2492     * if the named sequence doesn't exist, it will be created
2493     *@param seqName The name of the sequence to get the next seq id from
2494     *@param staggerMax The maximum amount to stagger the sequenced ID, if 1 the sequence will be incremented by 1, otherwise the current sequence ID will be incremented by a value between 1 and staggerMax
2495     *@return Long with the next seq id for the given sequence name
2496     */

2497    public Long JavaDoc getNextSeqIdLong(String JavaDoc seqName, long staggerMax) {
2498        boolean beganTransaction = false;
2499        try {
2500            if (alwaysUseTransaction) {
2501                beganTransaction = TransactionUtil.begin();
2502            }
2503
2504            if (sequencer == null) {
2505                synchronized (this) {
2506                    if (sequencer == null) {
2507                        String JavaDoc helperName = this.getEntityHelperName("SequenceValueItem");
2508                        ModelEntity seqEntity = this.getModelEntity("SequenceValueItem");
2509                        sequencer = new SequenceUtil(helperName, seqEntity, "seqName", "seqId");
2510                    }
2511                }
2512            }
2513
2514            Long JavaDoc newSeqId = sequencer == null ? null : sequencer.getNextSeqId(seqName, staggerMax);
2515
2516            // only commit the transaction if we started one...
2517
TransactionUtil.commit(beganTransaction);
2518
2519            return newSeqId;
2520        } catch (GenericEntityException e) {
2521            String JavaDoc errMsg = "Failure in getNextSeqIdLong operation for seqName [" + seqName + "]: " + e.toString() + ". Rolling back transaction.";
2522            Debug.logError(e, errMsg, module);
2523            try {
2524                // only rollback the transaction if we started one...
2525
TransactionUtil.rollback(beganTransaction, errMsg, e);
2526            } catch (GenericEntityException e2) {
2527                Debug.logError(e2, "[GenericDelegator] Could not rollback transaction: " + e2.toString(), module);
2528            }
2529            Debug.logError(e, "[GenericDelegator] Error getting next sequence ID: " + e.toString(), module);
2530            return null;
2531        }
2532    }
2533
2534    /** Allows you to pass a SequenceUtil class (possibly one that overrides the getNextSeqId method);
2535     * if null is passed will effectively refresh the sequencer. */

2536    public void setSequencer(SequenceUtil sequencer) {
2537        this.sequencer = sequencer;
2538    }
2539
2540    /** Refreshes the ID sequencer clearing all cached bank values. */
2541    public void refreshSequencer() {
2542        this.sequencer = null;
2543    }
2544
2545
2546    /** Look at existing values for a sub-entity with a sequenced secondary ID, and get the highest plus 1 */
2547    public void setNextSubSeqId(GenericValue value, String JavaDoc seqFieldName, int numericPadding, int incrementBy) {
2548        if (value != null && UtilValidate.isEmpty(value.getString(seqFieldName))) {
2549            String JavaDoc sequencedIdPrefix = this.getDelegatorInfo().sequencedIdPrefix;
2550
2551            value.remove(seqFieldName);
2552            GenericValue lookupValue = this.makeValue(value.getEntityName(), null);
2553            lookupValue.setPKFields(value);
2554
2555            boolean beganTransaction = false;
2556            try {
2557                if (alwaysUseTransaction) {
2558                    beganTransaction = TransactionUtil.begin();
2559                }
2560
2561                // get values in whatever order, we will go through all of them to find the highest value
2562
List JavaDoc allValues = this.findByAnd(value.getEntityName(), lookupValue, null);
2563                //Debug.logInfo("Get existing values from entity " + value.getEntityName() + " with lookupValue: " + lookupValue + ", and the seqFieldName: " + seqFieldName + ", and the results are: " + allValues, module);
2564
Iterator JavaDoc allValueIter = allValues.iterator();
2565                Integer JavaDoc highestSeqVal = null;
2566                while (allValueIter.hasNext()) {
2567                    GenericValue curValue = (GenericValue) allValueIter.next();
2568                    String JavaDoc currentSeqId = curValue.getString(seqFieldName);
2569                    if (currentSeqId != null) {
2570                        if (UtilValidate.isNotEmpty(sequencedIdPrefix)) {
2571                            if (currentSeqId.startsWith(sequencedIdPrefix)) {
2572                                currentSeqId = currentSeqId.substring(sequencedIdPrefix.length());
2573                            } else {
2574                                continue;
2575                            }
2576                        }
2577                        try {
2578                            int seqVal = Integer.parseInt(currentSeqId);
2579                            if (highestSeqVal == null || seqVal > highestSeqVal.intValue()) {
2580                                highestSeqVal = new Integer JavaDoc(seqVal);
2581                            }
2582                        } catch (Exception JavaDoc e) {
2583                            Debug.logWarning("Error in make-next-seq-id converting SeqId [" + currentSeqId + "] to a number: " + e.toString(), module);
2584                        }
2585                    }
2586                }
2587
2588                int seqValToUse = (highestSeqVal == null ? 1 : highestSeqVal.intValue() + incrementBy);
2589                String JavaDoc newSeqId = sequencedIdPrefix + UtilFormatOut.formatPaddedNumber(seqValToUse, numericPadding);
2590                value.set(seqFieldName, newSeqId);
2591
2592                // only commit the transaction if we started one...
2593
TransactionUtil.commit(beganTransaction);
2594            } catch (Exception JavaDoc e) {
2595                String JavaDoc errMsg = "Failure in setNextSubSeqId operation for entity [" + value.getEntityName() + "]: " + e.toString() + ". Rolling back transaction.";
2596                Debug.logError(e, errMsg, module);
2597                try {
2598                    // only rollback the transaction if we started one...
2599
TransactionUtil.rollback(beganTransaction, errMsg, e);
2600                } catch (GenericEntityException e2) {
2601                    Debug.logError(e2, "[GenericDelegator] Could not rollback transaction: " + e2.toString(), module);
2602                }
2603                Debug.logError(e, "Error making next seqId", module);
2604            }
2605        }
2606    }
2607
2608    public void encryptFields(List JavaDoc entities) throws GenericEntityException {
2609        if (entities != null) {
2610            for (int i = 0; i < entities.size(); i++) {
2611                GenericEntity entity = (GenericEntity) entities.get(i);
2612                this.encryptFields(entity);
2613            }
2614        }
2615    }
2616
2617    public void encryptFields(GenericEntity entity) throws GenericEntityException {
2618        ModelEntity model = entity.getModelEntity();
2619        String JavaDoc entityName = model.getEntityName();
2620
2621        Iterator JavaDoc i = model.getFieldsIterator();
2622        while (i.hasNext()) {
2623            ModelField field = (ModelField) i.next();
2624            if (field.getEncrypt()) {
2625                Object JavaDoc obj = entity.get(field.getName());
2626                if (obj != null) {
2627                    if (obj instanceof String JavaDoc && UtilValidate.isEmpty((String JavaDoc) obj)) {
2628                        continue;
2629                    }
2630                    entity.dangerousSetNoCheckButFast(field, this.encryptFieldValue(entityName, obj));
2631                }
2632            }
2633        }
2634    }
2635    
2636    public Object JavaDoc encryptFieldValue(String JavaDoc entityName, Object JavaDoc fieldValue) throws EntityCryptoException {
2637        if (fieldValue != null) {
2638            if (fieldValue instanceof String JavaDoc && UtilValidate.isEmpty((String JavaDoc) fieldValue)) {
2639                return fieldValue;
2640            }
2641            return this.crypto.encrypt(entityName, fieldValue);
2642        }
2643        return fieldValue;
2644    }
2645
2646    public void decryptFields(List JavaDoc entities) throws GenericEntityException {
2647        if (entities != null) {
2648            for (int i = 0; i < entities.size(); i++) {
2649                GenericEntity entity = (GenericEntity) entities.get(i);
2650                this.decryptFields(entity);
2651            }
2652        }
2653    }
2654
2655    public void decryptFields(GenericEntity entity) throws GenericEntityException {
2656        ModelEntity model = entity.getModelEntity();
2657        String JavaDoc entityName = model.getEntityName();
2658
2659        Iterator JavaDoc i = model.getFieldsIterator();
2660        while (i.hasNext()) {
2661            ModelField field = (ModelField) i.next();
2662            if (field.getEncrypt()) {
2663                String JavaDoc encHex = (String JavaDoc) entity.get(field.getName());
2664                if (UtilValidate.isNotEmpty(encHex)) {
2665                    try {
2666                        entity.dangerousSetNoCheckButFast(field, crypto.decrypt(entityName, encHex));
2667                    } catch (EntityCryptoException e) {
2668                        // not fatal -- allow returning of the encrypted value
2669
Debug.logWarning(e, "Problem decrypting field [" + entityName + " / " + field.getName() + "]", module);
2670                    }
2671                }
2672            }
2673        }
2674    }
2675
2676    public void setEntityCrypto(EntityCrypto crypto) {
2677        this.crypto = crypto;
2678    }
2679
2680    protected void absorbList(List JavaDoc lst) {
2681        if (lst == null) return;
2682        Iterator JavaDoc iter = lst.iterator();
2683
2684        while (iter.hasNext()) {
2685            GenericValue value = (GenericValue) iter.next();
2686
2687            value.setDelegator(this);
2688        }
2689    }
2690
2691    public Cache getCache() {
2692        return cache;
2693    }
2694
2695    public GenericDelegator cloneDelegator(String JavaDoc delegatorName) {
2696        // creates an exact clone of the delegator; except for the sequencer
2697
// note that this will not be cached and should be used only when
2698
// needed to change something for single instance (use).
2699
GenericDelegator newDelegator = new GenericDelegator();
2700        newDelegator.modelReader = this.modelReader;
2701        newDelegator.modelGroupReader = this.modelGroupReader;
2702        newDelegator.delegatorName = delegatorName;
2703        newDelegator.delegatorInfo = this.delegatorInfo;
2704        newDelegator.cache = this.cache;
2705        newDelegator.andCacheFieldSets = this.andCacheFieldSets;
2706        newDelegator.distributedCacheClear = this.distributedCacheClear;
2707        newDelegator.entityEcaHandler = this.entityEcaHandler;
2708        newDelegator.crypto = this.crypto;
2709        // not setting the sequencer so that we have unique sequences.
2710

2711        return newDelegator;
2712    }
2713
2714    public GenericDelegator cloneDelegator() {
2715        return this.cloneDelegator(this.delegatorName);
2716    }
2717}
2718
Popular Tags