0001: /*******************************************************************************
0002: * Licensed to the Apache Software Foundation (ASF) under one
0003: * or more contributor license agreements. See the NOTICE file
0004: * distributed with this work for additional information
0005: * regarding copyright ownership. The ASF licenses this file
0006: * to you under the Apache License, Version 2.0 (the
0007: * "License"); you may not use this file except in compliance
0008: * with the License. You may obtain a copy of the License at
0009: *
0010: * http://www.apache.org/licenses/LICENSE-2.0
0011: *
0012: * Unless required by applicable law or agreed to in writing,
0013: * software distributed under the License is distributed on an
0014: * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
0015: * KIND, either express or implied. See the License for the
0016: * specific language governing permissions and limitations
0017: * under the License.
0018: *******************************************************************************/package org.ofbiz.entity;
0019:
0020: import java.io.FileNotFoundException;
0021: import java.io.IOException;
0022: import java.net.URL;
0023: import java.util.Collection;
0024: import java.util.Iterator;
0025: import java.util.List;
0026: import java.util.Map;
0027: import java.util.Set;
0028: import java.util.TreeSet;
0029: import javax.xml.parsers.ParserConfigurationException;
0030:
0031: import javolution.util.FastList;
0032: import javolution.util.FastMap;
0033: import org.w3c.dom.Document;
0034: import org.w3c.dom.Element;
0035: import org.w3c.dom.Node;
0036: import org.xml.sax.SAXException;
0037:
0038: import org.ofbiz.base.util.Debug;
0039: import org.ofbiz.base.util.GeneralRuntimeException;
0040: import org.ofbiz.base.util.UtilFormatOut;
0041: import org.ofbiz.base.util.UtilMisc;
0042: import org.ofbiz.base.util.UtilValidate;
0043: import org.ofbiz.base.util.UtilXml;
0044: import org.ofbiz.base.util.cache.CacheLine;
0045: import org.ofbiz.base.util.cache.UtilCache;
0046: import org.ofbiz.entity.cache.Cache;
0047: import org.ofbiz.entity.condition.EntityCondition;
0048: import org.ofbiz.entity.condition.EntityConditionList;
0049: import org.ofbiz.entity.condition.EntityExpr;
0050: import org.ofbiz.entity.condition.EntityFieldMap;
0051: import org.ofbiz.entity.condition.EntityOperator;
0052: import org.ofbiz.entity.config.DatasourceInfo;
0053: import org.ofbiz.entity.config.DelegatorInfo;
0054: import org.ofbiz.entity.config.EntityConfigUtil;
0055: import org.ofbiz.entity.datasource.GenericHelper;
0056: import org.ofbiz.entity.datasource.GenericHelperFactory;
0057: import org.ofbiz.entity.eca.EntityEcaHandler;
0058: import org.ofbiz.entity.model.*;
0059: import org.ofbiz.entity.serialize.SerializeException;
0060: import org.ofbiz.entity.serialize.XmlSerializer;
0061: import org.ofbiz.entity.transaction.GenericTransactionException;
0062: import org.ofbiz.entity.transaction.TransactionUtil;
0063: import org.ofbiz.entity.util.DistributedCacheClear;
0064: import org.ofbiz.entity.util.EntityCrypto;
0065: import org.ofbiz.entity.util.EntityFindOptions;
0066: import org.ofbiz.entity.util.EntityListIterator;
0067: import org.ofbiz.entity.util.SequenceUtil;
0068:
0069: /**
0070: * Generic Data Source Delegator Class
0071: *
0072: */
0073: public class GenericDelegator implements DelegatorInterface {
0074:
0075: public static final String module = GenericDelegator.class
0076: .getName();
0077:
0078: /** set this to true for better performance; set to false to be able to reload definitions at runtime throught the cache manager */
0079: public static final boolean keepLocalReaders = true;
0080: protected ModelReader modelReader = null;
0081: protected ModelGroupReader modelGroupReader = null;
0082:
0083: /** 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 */
0084: public static final boolean alwaysUseTransaction = true;
0085:
0086: /** the delegatorCache will now be a HashMap, allowing reload of definitions,
0087: * but the delegator will always be the same object for the given name */
0088: protected static Map delegatorCache = FastMap.newInstance();
0089: protected String delegatorName = null;
0090: protected DelegatorInfo delegatorInfo = null;
0091:
0092: protected Cache cache = null;
0093:
0094: // keeps a list of field key sets used in the by and cache, a Set (of Sets of fieldNames) for each entityName
0095: protected Map andCacheFieldSets = FastMap.newInstance();
0096:
0097: protected DistributedCacheClear distributedCacheClear = null;
0098: protected EntityEcaHandler entityEcaHandler = null;
0099: protected SequenceUtil sequencer = null;
0100: protected EntityCrypto crypto = null;
0101:
0102: public static GenericDelegator getGenericDelegator(
0103: String delegatorName) {
0104: if (delegatorName == null) {
0105: delegatorName = "default";
0106: Debug
0107: .logWarning(
0108: "Got a getGenericDelegator call with a null delegatorName, assuming default for the name.",
0109: module);
0110: }
0111: GenericDelegator delegator = (GenericDelegator) delegatorCache
0112: .get(delegatorName);
0113:
0114: if (delegator == null) {
0115: synchronized (GenericDelegator.class) {
0116: // must check if null again as one of the blocked threads can still enter
0117: delegator = (GenericDelegator) delegatorCache
0118: .get(delegatorName);
0119: if (delegator == null) {
0120: if (Debug.infoOn())
0121: Debug.logInfo("Creating new delegator ["
0122: + delegatorName + "] ("
0123: + Thread.currentThread().getName()
0124: + ")", module);
0125: //Debug.logInfo(new Exception(), "Showing stack where new delegator is being created...", module);
0126: try {
0127: delegator = new GenericDelegator(delegatorName);
0128: } catch (GenericEntityException e) {
0129: Debug.logError(e, "Error creating delegator",
0130: module);
0131: }
0132: if (delegator != null) {
0133: delegatorCache.put(delegatorName, delegator);
0134: } else {
0135: Debug
0136: .logError(
0137: "Could not create delegator with name "
0138: + delegatorName
0139: + ", constructor failed (got null value) not sure why/how.",
0140: module);
0141: }
0142: }
0143: }
0144: }
0145: return delegator;
0146: }
0147:
0148: /** Only allow creation through the factory method */
0149: protected GenericDelegator() {
0150: }
0151:
0152: /** Only allow creation through the factory method */
0153: protected GenericDelegator(String delegatorName)
0154: throws GenericEntityException {
0155: //if (Debug.infoOn()) Debug.logInfo("Creating new Delegator with name \"" + delegatorName + "\".", module);
0156:
0157: this .delegatorName = delegatorName;
0158: if (keepLocalReaders) {
0159: modelReader = ModelReader.getModelReader(delegatorName);
0160: modelGroupReader = ModelGroupReader
0161: .getModelGroupReader(delegatorName);
0162: }
0163:
0164: cache = new Cache(delegatorName);
0165:
0166: // do the entity model check
0167: List warningList = FastList.newInstance();
0168: Debug.logImportant("Doing entity definition check...", module);
0169: ModelEntityChecker.checkEntities(this , warningList);
0170: if (warningList.size() > 0) {
0171: Debug
0172: .logWarning(
0173: "=-=-=-=-= Found "
0174: + warningList.size()
0175: + " warnings when checking the entity definitions:",
0176: module);
0177: Iterator warningIter = warningList.iterator();
0178: while (warningIter.hasNext()) {
0179: String warning = (String) warningIter.next();
0180: Debug.logWarning(warning, module);
0181: }
0182: }
0183:
0184: // initialize helpers by group
0185: Iterator groups = UtilMisc.toIterator(getModelGroupReader()
0186: .getGroupNames());
0187: while (groups != null && groups.hasNext()) {
0188: String groupName = (String) groups.next();
0189: String helperName = this .getGroupHelperName(groupName);
0190:
0191: if (Debug.infoOn())
0192: Debug.logInfo("Delegator \"" + delegatorName
0193: + "\" initializing helper \"" + helperName
0194: + "\" for entity group \"" + groupName + "\".",
0195: module);
0196: TreeSet helpersDone = new TreeSet();
0197: if (helperName != null && helperName.length() > 0) {
0198: // make sure each helper is only loaded once
0199: if (helpersDone.contains(helperName)) {
0200: if (Debug.infoOn())
0201: Debug
0202: .logInfo(
0203: "Helper \""
0204: + helperName
0205: + "\" already initialized, not re-initializing.",
0206: module);
0207: continue;
0208: }
0209: helpersDone.add(helperName);
0210: // pre-load field type defs, the return value is ignored
0211: ModelFieldTypeReader
0212: .getModelFieldTypeReader(helperName);
0213: // get the helper and if configured, do the datasource check
0214: GenericHelper helper = GenericHelperFactory
0215: .getHelper(helperName);
0216:
0217: DatasourceInfo datasourceInfo = EntityConfigUtil
0218: .getDatasourceInfo(helperName);
0219: if (datasourceInfo.checkOnStart) {
0220: if (Debug.infoOn())
0221: Debug
0222: .logInfo(
0223: "Doing database check as requested in entityengine.xml with addMissing="
0224: + datasourceInfo.addMissingOnStart,
0225: module);
0226: try {
0227: helper.checkDataSource(this
0228: .getModelEntityMapByGroup(groupName),
0229: null, datasourceInfo.addMissingOnStart);
0230: } catch (GenericEntityException e) {
0231: Debug.logWarning(e, e.getMessage(), module);
0232: }
0233: }
0234: }
0235: }
0236:
0237: // 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
0238: // put the delegator in the master Map by its name
0239: delegatorCache.put(delegatorName, this );
0240:
0241: // setup the crypto class
0242: this .crypto = new EntityCrypto(this );
0243:
0244: //time to do some tricks with manual class loading that resolves circular dependencies, like calling services...
0245: ClassLoader loader = Thread.currentThread()
0246: .getContextClassLoader();
0247:
0248: // if useDistributedCacheClear is false do nothing since the
0249: // distributedCacheClear member field with a null value will cause the
0250: // dcc code to do nothing
0251: if (getDelegatorInfo().useDistributedCacheClear) {
0252: // initialize the distributedCacheClear mechanism
0253: String distributedCacheClearClassName = getDelegatorInfo().distributedCacheClearClassName;
0254:
0255: try {
0256: Class dccClass = loader
0257: .loadClass(distributedCacheClearClassName);
0258: this .distributedCacheClear = (DistributedCacheClear) dccClass
0259: .newInstance();
0260: this .distributedCacheClear
0261: .setDelegator(
0262: this ,
0263: getDelegatorInfo().distributedCacheClearUserLoginId);
0264: } catch (ClassNotFoundException e) {
0265: Debug
0266: .logWarning(
0267: e,
0268: "DistributedCacheClear class with name "
0269: + distributedCacheClearClassName
0270: + " was not found, distributed cache clearing will be disabled",
0271: module);
0272: } catch (InstantiationException e) {
0273: Debug
0274: .logWarning(
0275: e,
0276: "DistributedCacheClear class with name "
0277: + distributedCacheClearClassName
0278: + " could not be instantiated, distributed cache clearing will be disabled",
0279: module);
0280: } catch (IllegalAccessException e) {
0281: Debug
0282: .logWarning(
0283: e,
0284: "DistributedCacheClear class with name "
0285: + distributedCacheClearClassName
0286: + " could not be accessed (illegal), distributed cache clearing will be disabled",
0287: module);
0288: } catch (ClassCastException e) {
0289: Debug
0290: .logWarning(
0291: e,
0292: "DistributedCacheClear class with name "
0293: + distributedCacheClearClassName
0294: + " does not implement the DistributedCacheClear interface, distributed cache clearing will be disabled",
0295: module);
0296: }
0297: } else {
0298: Debug.logInfo(
0299: "Distributed Cache Clear System disabled for delegator ["
0300: + delegatorName + "]", module);
0301: }
0302:
0303: // setup the Entity ECA Handler
0304: if (getDelegatorInfo().useEntityEca) {
0305: // initialize the entity eca handler
0306: String entityEcaHandlerClassName = getDelegatorInfo().entityEcaHandlerClassName;
0307:
0308: try {
0309: Class eecahClass = loader
0310: .loadClass(entityEcaHandlerClassName);
0311: this .entityEcaHandler = (EntityEcaHandler) eecahClass
0312: .newInstance();
0313: this .entityEcaHandler.setDelegator(this );
0314: } catch (ClassNotFoundException e) {
0315: Debug
0316: .logWarning(
0317: e,
0318: "EntityEcaHandler class with name "
0319: + entityEcaHandlerClassName
0320: + " was not found, Entity ECA Rules will be disabled",
0321: module);
0322: } catch (InstantiationException e) {
0323: Debug
0324: .logWarning(
0325: e,
0326: "EntityEcaHandler class with name "
0327: + entityEcaHandlerClassName
0328: + " could not be instantiated, Entity ECA Rules will be disabled",
0329: module);
0330: } catch (IllegalAccessException e) {
0331: Debug
0332: .logWarning(
0333: e,
0334: "EntityEcaHandler class with name "
0335: + entityEcaHandlerClassName
0336: + " could not be accessed (illegal), Entity ECA Rules will be disabled",
0337: module);
0338: } catch (ClassCastException e) {
0339: Debug
0340: .logWarning(
0341: e,
0342: "EntityEcaHandler class with name "
0343: + entityEcaHandlerClassName
0344: + " does not implement the EntityEcaHandler interface, Entity ECA Rules will be disabled",
0345: module);
0346: }
0347: } else {
0348: Debug.logInfo("Entity ECA Handler disabled for delegator ["
0349: + delegatorName + "]", module);
0350: }
0351: }
0352:
0353: /** Gets the name of the server configuration that corresponds to this delegator
0354: * @return server configuration name
0355: */
0356: public String getDelegatorName() {
0357: return this .delegatorName;
0358: }
0359:
0360: protected DelegatorInfo getDelegatorInfo() {
0361: if (delegatorInfo == null) {
0362: delegatorInfo = EntityConfigUtil
0363: .getDelegatorInfo(this .delegatorName);
0364: }
0365: return delegatorInfo;
0366: }
0367:
0368: /** Gets the instance of ModelReader that corresponds to this delegator
0369: *@return ModelReader that corresponds to this delegator
0370: */
0371: public ModelReader getModelReader() {
0372: if (keepLocalReaders) {
0373: return this .modelReader;
0374: } else {
0375: try {
0376: return ModelReader.getModelReader(delegatorName);
0377: } catch (GenericEntityException e) {
0378: Debug.logError(e, "Error loading entity model", module);
0379: return null;
0380: }
0381: }
0382: }
0383:
0384: /** Gets the instance of ModelGroupReader that corresponds to this delegator
0385: *@return ModelGroupReader that corresponds to this delegator
0386: */
0387: public ModelGroupReader getModelGroupReader() {
0388: if (keepLocalReaders) {
0389: return this .modelGroupReader;
0390: } else {
0391: try {
0392: return ModelGroupReader
0393: .getModelGroupReader(delegatorName);
0394: } catch (GenericEntityException e) {
0395: Debug.logError(e, "Error loading entity group model",
0396: module);
0397: return null;
0398: }
0399: }
0400: }
0401:
0402: /** Gets the instance of ModelEntity that corresponds to this delegator and the specified entityName
0403: *@param entityName The name of the entity to get
0404: *@return ModelEntity that corresponds to this delegator and the specified entityName
0405: */
0406: public ModelEntity getModelEntity(String entityName) {
0407: try {
0408: return getModelReader().getModelEntity(entityName);
0409: } catch (GenericEntityException e) {
0410: Debug.logError(e,
0411: "Error getting entity definition from model",
0412: module);
0413: return null;
0414: }
0415: }
0416:
0417: /** Gets the helper name that corresponds to this delegator and the specified entityName
0418: *@param entityName The name of the entity to get the helper for
0419: *@return String with the helper name that corresponds to this delegator and the specified entityName
0420: */
0421: public String getEntityGroupName(String entityName) {
0422: String groupName = getModelGroupReader().getEntityGroupName(
0423: entityName);
0424:
0425: return groupName;
0426: }
0427:
0428: /** Gets a list of entity models that are in a group corresponding to the specified group name
0429: *@param groupName The name of the group
0430: *@return List of ModelEntity instances
0431: */
0432: public List getModelEntitiesByGroup(String groupName) {
0433: Iterator enames = UtilMisc.toIterator(getModelGroupReader()
0434: .getEntityNamesByGroup(groupName));
0435: List entities = FastList.newInstance();
0436:
0437: if (enames == null || !enames.hasNext())
0438: return entities;
0439: while (enames.hasNext()) {
0440: String ename = (String) enames.next();
0441: ModelEntity entity = this .getModelEntity(ename);
0442:
0443: if (entity != null)
0444: entities.add(entity);
0445: }
0446: return entities;
0447: }
0448:
0449: /** Gets a Map of entity name & entity model pairs that are in the named group
0450: *@param groupName The name of the group
0451: *@return Map of entityName String keys and ModelEntity instance values
0452: */
0453: public Map getModelEntityMapByGroup(String groupName) {
0454: Iterator enames = UtilMisc.toIterator(getModelGroupReader()
0455: .getEntityNamesByGroup(groupName));
0456: Map entities = FastMap.newInstance();
0457:
0458: if (enames == null || !enames.hasNext()) {
0459: return entities;
0460: }
0461:
0462: int errorCount = 0;
0463: while (enames.hasNext()) {
0464: String ename = (String) enames.next();
0465: try {
0466: ModelEntity entity = getModelReader().getModelEntity(
0467: ename);
0468: if (entity != null) {
0469: entities.put(entity.getEntityName(), entity);
0470: } else {
0471: throw new IllegalStateException(
0472: "Could not find entity with name " + ename);
0473: }
0474: } catch (GenericEntityException ex) {
0475: errorCount++;
0476: Debug
0477: .logError(
0478: "Entity "
0479: + ename
0480: + " named in Entity Group with name "
0481: + groupName
0482: + " are not defined in any Entity Definition file",
0483: module);
0484: }
0485: }
0486:
0487: if (errorCount > 0) {
0488: Debug
0489: .logError(
0490: errorCount
0491: + " entities were named in ModelGroup but not defined in any EntityModel",
0492: module);
0493: }
0494:
0495: return entities;
0496: }
0497:
0498: /** Gets the helper name that corresponds to this delegator and the specified entityName
0499: *@param groupName The name of the group to get the helper name for
0500: *@return String with the helper name that corresponds to this delegator and the specified entityName
0501: */
0502: public String getGroupHelperName(String groupName) {
0503: return (String) this .getDelegatorInfo().groupMap.get(groupName);
0504: }
0505:
0506: /** Gets the helper name that corresponds to this delegator and the specified entityName
0507: *@param entityName The name of the entity to get the helper name for
0508: *@return String with the helper name that corresponds to this delegator and the specified entityName
0509: */
0510: public String getEntityHelperName(String entityName) {
0511: String groupName = getModelGroupReader().getEntityGroupName(
0512: entityName);
0513:
0514: return this .getGroupHelperName(groupName);
0515: }
0516:
0517: /** Gets the helper name that corresponds to this delegator and the specified entity
0518: *@param entity The entity to get the helper for
0519: *@return String with the helper name that corresponds to this delegator and the specified entity
0520: */
0521: public String getEntityHelperName(ModelEntity entity) {
0522: if (entity == null)
0523: return null;
0524: return getEntityHelperName(entity.getEntityName());
0525: }
0526:
0527: /** Gets the an instance of helper that corresponds to this delegator and the specified entityName
0528: *@param entityName The name of the entity to get the helper for
0529: *@return GenericHelper that corresponds to this delegator and the specified entityName
0530: */
0531: public GenericHelper getEntityHelper(String entityName)
0532: throws GenericEntityException {
0533: String helperName = getEntityHelperName(entityName);
0534:
0535: if (helperName != null && helperName.length() > 0)
0536: return GenericHelperFactory.getHelper(helperName);
0537: else
0538: throw new GenericEntityException(
0539: "Helper name not found for entity " + entityName);
0540: }
0541:
0542: /** Gets the an instance of helper that corresponds to this delegator and the specified entity
0543: *@param entity The entity to get the helper for
0544: *@return GenericHelper that corresponds to this delegator and the specified entity
0545: */
0546: public GenericHelper getEntityHelper(ModelEntity entity)
0547: throws GenericEntityException {
0548: return getEntityHelper(entity.getEntityName());
0549: }
0550:
0551: /** Gets a field type instance by name from the helper that corresponds to the specified entity
0552: *@param entity The entity
0553: *@param type The name of the type
0554: *@return ModelFieldType instance for the named type from the helper that corresponds to the specified entity
0555: */
0556: public ModelFieldType getEntityFieldType(ModelEntity entity,
0557: String type) throws GenericEntityException {
0558: String helperName = getEntityHelperName(entity);
0559:
0560: if (helperName == null || helperName.length() <= 0)
0561: return null;
0562: ModelFieldTypeReader modelFieldTypeReader = ModelFieldTypeReader
0563: .getModelFieldTypeReader(helperName);
0564:
0565: if (modelFieldTypeReader == null) {
0566: throw new GenericEntityException(
0567: "ModelFieldTypeReader not found for entity "
0568: + entity.getEntityName()
0569: + " with helper name " + helperName);
0570: }
0571: return modelFieldTypeReader.getModelFieldType(type);
0572: }
0573:
0574: /** Gets field type names from the helper that corresponds to the specified entity
0575: *@param entity The entity
0576: *@return Collection of field type names from the helper that corresponds to the specified entity
0577: */
0578: public Collection getEntityFieldTypeNames(ModelEntity entity)
0579: throws GenericEntityException {
0580: String helperName = getEntityHelperName(entity);
0581:
0582: if (helperName == null || helperName.length() <= 0)
0583: return null;
0584: ModelFieldTypeReader modelFieldTypeReader = ModelFieldTypeReader
0585: .getModelFieldTypeReader(helperName);
0586:
0587: if (modelFieldTypeReader == null) {
0588: throw new GenericEntityException(
0589: "ModelFieldTypeReader not found for entity "
0590: + entity.getEntityName()
0591: + " with helper name " + helperName);
0592: }
0593: return modelFieldTypeReader.getFieldTypeNames();
0594: }
0595:
0596: /** Creates a Entity in the form of a GenericValue without persisting it */
0597: public GenericValue makeValue(String entityName, Map fields) {
0598: ModelEntity entity = this .getModelEntity(entityName);
0599: if (entity == null) {
0600: throw new IllegalArgumentException(
0601: "[GenericDelegator.makeValue] could not find entity for entityName: "
0602: + entityName);
0603: }
0604: GenericValue value = GenericValue.create(entity, fields);
0605: value.setDelegator(this );
0606: return value;
0607: }
0608:
0609: /** Creates a Entity in the form of a GenericValue without persisting it; only valid fields will be pulled from the fields Map */
0610: public GenericValue makeValidValue(String entityName, Map fields) {
0611: ModelEntity entity = this .getModelEntity(entityName);
0612: if (entity == null) {
0613: throw new IllegalArgumentException(
0614: "[GenericDelegator.makeValidValue] could not find entity for entityName: "
0615: + entityName);
0616: }
0617: GenericValue value = GenericValue.create(entity, null);
0618: value.setPKFields(fields, true);
0619: value.setNonPKFields(fields, true);
0620: value.setDelegator(this );
0621: return value;
0622: }
0623:
0624: /** Creates a Primary Key in the form of a GenericPK without persisting it */
0625: public GenericPK makePK(String entityName, Map fields) {
0626: ModelEntity entity = this .getModelEntity(entityName);
0627: if (entity == null) {
0628: throw new IllegalArgumentException(
0629: "[GenericDelegator.makePK] could not find entity for entityName: "
0630: + entityName);
0631: }
0632: GenericPK pk = GenericPK.create(entity, fields);
0633:
0634: pk.setDelegator(this );
0635: return pk;
0636: }
0637:
0638: /** Creates a Entity in the form of a GenericValue and write it to the datasource
0639: *@param primaryKey The GenericPK to create a value in the datasource from
0640: *@return GenericValue instance containing the new instance
0641: */
0642: public GenericValue create(GenericPK primaryKey)
0643: throws GenericEntityException {
0644: return this .create(primaryKey, true);
0645: }
0646:
0647: /** Creates a Entity in the form of a GenericValue and write it to the datasource
0648: *@param primaryKey The GenericPK to create a value in the datasource from
0649: *@param doCacheClear boolean that specifies whether to clear related cache entries for this primaryKey to be created
0650: *@return GenericValue instance containing the new instance
0651: */
0652: public GenericValue create(GenericPK primaryKey,
0653: boolean doCacheClear) throws GenericEntityException {
0654: if (primaryKey == null) {
0655: throw new GenericEntityException(
0656: "Cannot create from a null primaryKey");
0657: }
0658:
0659: return this .create(GenericValue.create(primaryKey),
0660: doCacheClear);
0661: }
0662:
0663: /** Creates a Entity in the form of a GenericValue and write it to the database
0664: *@return GenericValue instance containing the new instance
0665: */
0666: public GenericValue create(String entityName, Map fields)
0667: throws GenericEntityException {
0668: if (entityName == null || fields == null) {
0669: return null;
0670: }
0671: ModelEntity entity = this .getModelReader().getModelEntity(
0672: entityName);
0673: GenericValue genericValue = GenericValue.create(entity, fields);
0674:
0675: return this .create(genericValue, true);
0676: }
0677:
0678: /** Creates a Entity in the form of a GenericValue and write it to the datasource
0679: *@param value The GenericValue to create a value in the datasource from
0680: *@return GenericValue instance containing the new instance
0681: */
0682: public GenericValue create(GenericValue value)
0683: throws GenericEntityException {
0684: return this .create(value, true);
0685: }
0686:
0687: /** Creates a Entity in the form of a GenericValue and write it to the datasource
0688: *@param value The GenericValue to create a value in the datasource from
0689: *@param doCacheClear boolean that specifies whether or not to automatically clear cache entries related to this operation
0690: *@return GenericValue instance containing the new instance
0691: */
0692: public GenericValue create(GenericValue value, boolean doCacheClear)
0693: throws GenericEntityException {
0694: boolean beganTransaction = false;
0695: try {
0696: if (alwaysUseTransaction) {
0697: beganTransaction = TransactionUtil.begin();
0698: }
0699:
0700: Map ecaEventMap = this .getEcaEntityEventMap(value
0701: .getEntityName());
0702: this .evalEcaRules(EntityEcaHandler.EV_VALIDATE,
0703: EntityEcaHandler.OP_CREATE, value, ecaEventMap,
0704: (ecaEventMap == null), false);
0705:
0706: if (value == null) {
0707: throw new GenericEntityException(
0708: "Cannot create a null value");
0709: }
0710: GenericHelper helper = getEntityHelper(value
0711: .getEntityName());
0712:
0713: this .evalEcaRules(EntityEcaHandler.EV_RUN,
0714: EntityEcaHandler.OP_CREATE, value, ecaEventMap,
0715: (ecaEventMap == null), false);
0716:
0717: value.setDelegator(this );
0718: this .encryptFields(value);
0719: value = helper.create(value);
0720:
0721: if (value != null) {
0722: value.setDelegator(this );
0723: if (value.lockEnabled()) {
0724: refresh(value, doCacheClear);
0725: } else {
0726: if (doCacheClear) {
0727: this .evalEcaRules(
0728: EntityEcaHandler.EV_CACHE_CLEAR,
0729: EntityEcaHandler.OP_CREATE, value,
0730: ecaEventMap, (ecaEventMap == null),
0731: false);
0732: this .clearCacheLine(value);
0733: }
0734: }
0735: }
0736:
0737: this .evalEcaRules(EntityEcaHandler.EV_RETURN,
0738: EntityEcaHandler.OP_CREATE, value, ecaEventMap,
0739: (ecaEventMap == null), false);
0740: return value;
0741: } catch (GenericEntityException e) {
0742: String errMsg = "Failure in create operation for entity ["
0743: + value.getEntityName() + "]: " + e.toString()
0744: + ". Rolling back transaction.";
0745: Debug.logError(e, errMsg, module);
0746: try {
0747: // only rollback the transaction if we started one...
0748: TransactionUtil.rollback(beganTransaction, errMsg, e);
0749: } catch (GenericEntityException e2) {
0750: Debug.logError(e2,
0751: "[GenericDelegator] Could not rollback transaction: "
0752: + e2.toString(), module);
0753: }
0754: // after rolling back, rethrow the exception
0755: throw e;
0756: } finally {
0757: // only commit the transaction if we started one... this will throw an exception if it fails
0758: TransactionUtil.commit(beganTransaction);
0759: }
0760: }
0761:
0762: /** Creates or stores an Entity
0763: *@param value The GenericValue instance containing the new or existing instance
0764: *@param doCacheClear boolean that specifies whether or not to automatically clear cache entries related to this operation
0765: *@return GenericValue instance containing the new or updated instance
0766: */
0767: public GenericValue createOrStore(GenericValue value,
0768: boolean doCacheClear) throws GenericEntityException {
0769: boolean beganTransaction = false;
0770: try {
0771: if (alwaysUseTransaction) {
0772: beganTransaction = TransactionUtil.begin();
0773: }
0774:
0775: GenericValue checkValue = this .findByPrimaryKey(value
0776: .getPrimaryKey());
0777: if (checkValue != null) {
0778: this .store(value, doCacheClear);
0779: } else {
0780: this .create(value, doCacheClear);
0781: }
0782: if (value.lockEnabled()) {
0783: this .refresh(value);
0784: }
0785:
0786: return value;
0787: } catch (GenericEntityException e) {
0788: String errMsg = "Failure in createOrStore operation for entity ["
0789: + value.getEntityName()
0790: + "]: "
0791: + e.toString()
0792: + ". Rolling back transaction.";
0793: Debug.logError(e, errMsg, module);
0794: try {
0795: // only rollback the transaction if we started one...
0796: TransactionUtil.rollback(beganTransaction, errMsg, e);
0797: } catch (GenericEntityException e2) {
0798: Debug.logError(e2,
0799: "[GenericDelegator] Could not rollback transaction: "
0800: + e2.toString(), module);
0801: }
0802: // after rolling back, rethrow the exception
0803: throw e;
0804: } finally {
0805: // only commit the transaction if we started one... this will throw an exception if it fails
0806: TransactionUtil.commit(beganTransaction);
0807: }
0808: }
0809:
0810: /** Creates or stores an Entity
0811: *@param value The GenericValue instance containing the new or existing instance
0812: *@return GenericValue instance containing the new or updated instance
0813: */
0814: public GenericValue createOrStore(GenericValue value)
0815: throws GenericEntityException {
0816: return createOrStore(value, true);
0817: }
0818:
0819: protected void saveEntitySyncRemoveInfo(GenericEntity dummyPK)
0820: throws GenericEntityException {
0821: // don't store remove info on entities where it is disabled
0822: if (dummyPK.getModelEntity().getNoAutoStamp()) {
0823: return;
0824: }
0825:
0826: // don't store remove info on things removed on an entity sync
0827: if (dummyPK.getIsFromEntitySync()) {
0828: return;
0829: }
0830:
0831: String serializedPK = null;
0832: try {
0833: serializedPK = XmlSerializer.serialize(dummyPK);
0834: } catch (SerializeException e) {
0835: Debug
0836: .logError(
0837: e,
0838: "Could not serialize primary key to save EntitySyncRemove",
0839: module);
0840: } catch (FileNotFoundException e) {
0841: Debug
0842: .logError(
0843: e,
0844: "Could not serialize primary key to save EntitySyncRemove",
0845: module);
0846: } catch (IOException e) {
0847: Debug
0848: .logError(
0849: e,
0850: "Could not serialize primary key to save EntitySyncRemove",
0851: module);
0852: }
0853:
0854: if (serializedPK != null) {
0855: GenericValue entitySyncRemove = this .makeValue(
0856: "EntitySyncRemove", null);
0857: entitySyncRemove.set("entitySyncRemoveId", this
0858: .getNextSeqId("EntitySyncRemove"));
0859: entitySyncRemove.set("primaryKeyRemoved", serializedPK);
0860: entitySyncRemove.create();
0861: }
0862: }
0863:
0864: /** Remove a Generic Entity corresponding to the primaryKey
0865: *@param primaryKey The primary key of the entity to remove.
0866: *@return int representing number of rows effected by this operation
0867: */
0868: public int removeByPrimaryKey(GenericPK primaryKey)
0869: throws GenericEntityException {
0870: int retVal = this .removeByPrimaryKey(primaryKey, true);
0871: return retVal;
0872: }
0873:
0874: /** Remove a Generic Entity corresponding to the primaryKey
0875: *@param primaryKey The primary key of the entity to remove.
0876: *@param doCacheClear boolean that specifies whether to clear cache entries for this primaryKey to be removed
0877: *@return int representing number of rows effected by this operation
0878: */
0879: public int removeByPrimaryKey(GenericPK primaryKey,
0880: boolean doCacheClear) throws GenericEntityException {
0881: boolean beganTransaction = false;
0882: try {
0883: if (alwaysUseTransaction) {
0884: beganTransaction = TransactionUtil.begin();
0885: }
0886:
0887: Map ecaEventMap = this .getEcaEntityEventMap(primaryKey
0888: .getEntityName());
0889: this .evalEcaRules(EntityEcaHandler.EV_VALIDATE,
0890: EntityEcaHandler.OP_REMOVE, primaryKey,
0891: ecaEventMap, (ecaEventMap == null), false);
0892:
0893: GenericHelper helper = getEntityHelper(primaryKey
0894: .getEntityName());
0895:
0896: if (doCacheClear) {
0897: // always clear cache before the operation
0898: this .evalEcaRules(EntityEcaHandler.EV_CACHE_CLEAR,
0899: EntityEcaHandler.OP_REMOVE, primaryKey,
0900: ecaEventMap, (ecaEventMap == null), false);
0901: this .clearCacheLine(primaryKey);
0902: }
0903:
0904: this .evalEcaRules(EntityEcaHandler.EV_RUN,
0905: EntityEcaHandler.OP_REMOVE, primaryKey,
0906: ecaEventMap, (ecaEventMap == null), false);
0907: int num = helper.removeByPrimaryKey(primaryKey);
0908: this .saveEntitySyncRemoveInfo(primaryKey);
0909:
0910: this .evalEcaRules(EntityEcaHandler.EV_RETURN,
0911: EntityEcaHandler.OP_REMOVE, primaryKey,
0912: ecaEventMap, (ecaEventMap == null), false);
0913: return num;
0914: } catch (GenericEntityException e) {
0915: String errMsg = "Failure in removeByPrimaryKey operation for entity ["
0916: + primaryKey.getEntityName()
0917: + "]: "
0918: + e.toString()
0919: + ". Rolling back transaction.";
0920: Debug.logError(e, errMsg, module);
0921: try {
0922: // only rollback the transaction if we started one...
0923: TransactionUtil.rollback(beganTransaction, errMsg, e);
0924: } catch (GenericEntityException e2) {
0925: Debug.logError(e2,
0926: "[GenericDelegator] Could not rollback transaction: "
0927: + e2.toString(), module);
0928: }
0929: // after rolling back, rethrow the exception
0930: throw e;
0931: } finally {
0932: // only commit the transaction if we started one... this will throw an exception if it fails
0933: TransactionUtil.commit(beganTransaction);
0934: }
0935: }
0936:
0937: /** Remove a Generic Value from the database
0938: *@param value The GenericValue object of the entity to remove.
0939: *@return int representing number of rows effected by this operation
0940: */
0941: public int removeValue(GenericValue value)
0942: throws GenericEntityException {
0943: return this .removeValue(value, true);
0944: }
0945:
0946: /** Remove a Generic Value from the database
0947: *@param value The GenericValue object of the entity to remove.
0948: *@param doCacheClear boolean that specifies whether to clear cache entries for this value to be removed
0949: *@return int representing number of rows effected by this operation
0950: */
0951: public int removeValue(GenericValue value, boolean doCacheClear)
0952: throws GenericEntityException {
0953: // NOTE: this does not call the GenericDelegator.removeByPrimaryKey method because it has more information to pass to the ECA rule hander
0954: boolean beganTransaction = false;
0955: try {
0956: if (alwaysUseTransaction) {
0957: beganTransaction = TransactionUtil.begin();
0958: }
0959:
0960: Map ecaEventMap = this .getEcaEntityEventMap(value
0961: .getEntityName());
0962: this .evalEcaRules(EntityEcaHandler.EV_VALIDATE,
0963: EntityEcaHandler.OP_REMOVE, value, ecaEventMap,
0964: (ecaEventMap == null), false);
0965:
0966: GenericHelper helper = getEntityHelper(value
0967: .getEntityName());
0968:
0969: if (doCacheClear) {
0970: this .evalEcaRules(EntityEcaHandler.EV_CACHE_CLEAR,
0971: EntityEcaHandler.OP_REMOVE, value, ecaEventMap,
0972: (ecaEventMap == null), false);
0973: this .clearCacheLine(value);
0974: }
0975:
0976: this .evalEcaRules(EntityEcaHandler.EV_RUN,
0977: EntityEcaHandler.OP_REMOVE, value, ecaEventMap,
0978: (ecaEventMap == null), false);
0979: int num = helper.removeByPrimaryKey(value.getPrimaryKey());
0980: this .saveEntitySyncRemoveInfo(value.getPrimaryKey());
0981:
0982: this .evalEcaRules(EntityEcaHandler.EV_RETURN,
0983: EntityEcaHandler.OP_REMOVE, value, ecaEventMap,
0984: (ecaEventMap == null), false);
0985: return num;
0986: } catch (GenericEntityException e) {
0987: String errMsg = "Failure in removeValue operation for entity ["
0988: + value.getEntityName()
0989: + "]: "
0990: + e.toString()
0991: + ". Rolling back transaction.";
0992: Debug.logError(e, errMsg, module);
0993: try {
0994: // only rollback the transaction if we started one...
0995: TransactionUtil.rollback(beganTransaction, errMsg, e);
0996: } catch (GenericEntityException e2) {
0997: Debug.logError(e2,
0998: "[GenericDelegator] Could not rollback transaction: "
0999: + e2.toString(), module);
1000: }
1001: // after rolling back, rethrow the exception
1002: throw e;
1003: } finally {
1004: // only commit the transaction if we started one... this will throw an exception if it fails
1005: TransactionUtil.commit(beganTransaction);
1006: }
1007: }
1008:
1009: /** Removes/deletes Generic Entity records found by all of the specified fields (ie: combined using AND)
1010: *@param entityName The Name of the Entity as defined in the entity XML file
1011: *@param fields The fields of the named entity to query by with their corresponging values
1012: *@return int representing number of rows effected by this operation
1013: */
1014: public int removeByAnd(String entityName, Map fields)
1015: throws GenericEntityException {
1016: return this .removeByAnd(entityName, fields, true);
1017: }
1018:
1019: /** Removes/deletes Generic Entity records found by all of the specified fields (ie: combined using AND)
1020: *@param entityName The Name of the Entity as defined in the entity XML file
1021: *@param fields The fields of the named entity to query by with their corresponging values
1022: *@param doCacheClear boolean that specifies whether to clear cache entries for this value to be removed
1023: *@return int representing number of rows effected by this operation
1024: */
1025: public int removeByAnd(String entityName, Map fields,
1026: boolean doCacheClear) throws GenericEntityException {
1027: EntityCondition ecl = new EntityFieldMap(fields,
1028: EntityOperator.AND);
1029: return removeByCondition(entityName, ecl, doCacheClear);
1030: }
1031:
1032: /** Removes/deletes Generic Entity records found by the condition
1033: *@param entityName The Name of the Entity as defined in the entity XML file
1034: *@param condition The condition used to restrict the removing
1035: *@return int representing number of rows effected by this operation
1036: */
1037: public int removeByCondition(String entityName,
1038: EntityCondition condition) throws GenericEntityException {
1039: return this .removeByCondition(entityName, condition, true);
1040: }
1041:
1042: /** Removes/deletes Generic Entity records found by the condition
1043: *@param entityName The Name of the Entity as defined in the entity XML file
1044: *@param condition The condition used to restrict the removing
1045: *@param doCacheClear boolean that specifies whether to clear cache entries for this value to be removed
1046: *@return int representing number of rows effected by this operation
1047: */
1048: public int removeByCondition(String entityName,
1049: EntityCondition condition, boolean doCacheClear)
1050: throws GenericEntityException {
1051: boolean beganTransaction = false;
1052: try {
1053: if (alwaysUseTransaction) {
1054: beganTransaction = TransactionUtil.begin();
1055: }
1056:
1057: if (doCacheClear) {
1058: // always clear cache before the operation
1059: this .clearCacheLineByCondition(entityName, condition);
1060: }
1061: ModelEntity modelEntity = getModelReader().getModelEntity(
1062: entityName);
1063: GenericHelper helper = getEntityHelper(entityName);
1064:
1065: return helper.removeByCondition(modelEntity, condition);
1066: } catch (GenericEntityException e) {
1067: String errMsg = "Failure in removeByCondition operation for entity ["
1068: + entityName
1069: + "]: "
1070: + e.toString()
1071: + ". Rolling back transaction.";
1072: Debug.logError(e, errMsg, module);
1073: try {
1074: // only rollback the transaction if we started one...
1075: TransactionUtil.rollback(beganTransaction, errMsg, e);
1076: } catch (GenericEntityException e2) {
1077: Debug.logError(e2,
1078: "[GenericDelegator] Could not rollback transaction: "
1079: + e2.toString(), module);
1080: }
1081: // after rolling back, rethrow the exception
1082: throw e;
1083: } finally {
1084: // only commit the transaction if we started one... this will throw an exception if it fails
1085: TransactionUtil.commit(beganTransaction);
1086: }
1087: }
1088:
1089: /** Remove the named Related Entity for the GenericValue from the persistent store
1090: *@param relationName String containing the relation name which is the
1091: * combination of relation.title and relation.rel-entity-name as
1092: * specified in the entity XML definition file
1093: *@param value GenericValue instance containing the entity
1094: *@return int representing number of rows effected by this operation
1095: */
1096: public int removeRelated(String relationName, GenericValue value)
1097: throws GenericEntityException {
1098: return this .removeRelated(relationName, value, true);
1099: }
1100:
1101: /** Remove the named Related Entity for the GenericValue from the persistent store
1102: *@param relationName String containing the relation name which is the
1103: * combination of relation.title and relation.rel-entity-name as
1104: * specified in the entity XML definition file
1105: *@param value GenericValue instance containing the entity
1106: *@param doCacheClear boolean that specifies whether to clear cache entries for this value to be removed
1107: *@return int representing number of rows effected by this operation
1108: */
1109: public int removeRelated(String relationName, GenericValue value,
1110: boolean doCacheClear) throws GenericEntityException {
1111: ModelEntity modelEntity = value.getModelEntity();
1112: ModelRelation relation = modelEntity.getRelation(relationName);
1113:
1114: if (relation == null) {
1115: throw new GenericModelException(
1116: "Could not find relation for relationName: "
1117: + relationName + " for value " + value);
1118: }
1119:
1120: Map fields = FastMap.newInstance();
1121: for (int i = 0; i < relation.getKeyMapsSize(); i++) {
1122: ModelKeyMap keyMap = relation.getKeyMap(i);
1123: fields.put(keyMap.getRelFieldName(), value.get(keyMap
1124: .getFieldName()));
1125: }
1126:
1127: return this .removeByAnd(relation.getRelEntityName(), fields,
1128: doCacheClear);
1129: }
1130:
1131: /** Refresh the Entity for the GenericValue from the persistent store
1132: *@param value GenericValue instance containing the entity to refresh
1133: */
1134: public void refresh(GenericValue value)
1135: throws GenericEntityException {
1136: this .refresh(value, true);
1137: }
1138:
1139: /** Refresh the Entity for the GenericValue from the persistent store
1140: *@param value GenericValue instance containing the entity to refresh
1141: *@param doCacheClear boolean that specifies whether or not to automatically clear cache entries related to this operation
1142: */
1143: public void refresh(GenericValue value, boolean doCacheClear)
1144: throws GenericEntityException {
1145: if (doCacheClear) {
1146: // always clear cache before the operation
1147: clearCacheLine(value);
1148: }
1149: GenericPK pk = value.getPrimaryKey();
1150: GenericValue newValue = findByPrimaryKey(pk);
1151: value.refreshFromValue(newValue);
1152: }
1153:
1154: /** Refresh the Entity for the GenericValue from the cache
1155: *@param value GenericValue instance containing the entity to refresh
1156: */
1157: public void refreshFromCache(GenericValue value)
1158: throws GenericEntityException {
1159: GenericPK pk = value.getPrimaryKey();
1160: GenericValue newValue = findByPrimaryKeyCache(pk);
1161: value.refreshFromValue(newValue);
1162: }
1163:
1164: /** Store a group of values
1165: *@param entityName The name of the Entity as defined in the entity XML file
1166: *@param fieldsToSet The fields of the named entity to set in the database
1167: *@param condition The condition that restricts the list of stored values
1168: *@return int representing number of rows effected by this operation
1169: *@throws GenericEntityException
1170: */
1171: public int storeByCondition(String entityName, Map fieldsToSet,
1172: EntityCondition condition) throws GenericEntityException {
1173: return storeByCondition(entityName, fieldsToSet, condition,
1174: true);
1175: }
1176:
1177: /** Store a group of values
1178: *@param entityName The name of the Entity as defined in the entity XML file
1179: *@param fieldsToSet The fields of the named entity to set in the database
1180: *@param condition The condition that restricts the list of stored values
1181: *@param doCacheClear boolean that specifies whether to clear cache entries for these values
1182: *@return int representing number of rows effected by this operation
1183: *@throws GenericEntityException
1184: */
1185: public int storeByCondition(String entityName, Map fieldsToSet,
1186: EntityCondition condition, boolean doCacheClear)
1187: throws GenericEntityException {
1188: boolean beganTransaction = false;
1189: try {
1190: if (alwaysUseTransaction) {
1191: beganTransaction = TransactionUtil.begin();
1192: }
1193:
1194: if (doCacheClear) {
1195: // always clear cache before the operation
1196: this .clearCacheLineByCondition(entityName, condition);
1197: }
1198: ModelEntity modelEntity = getModelReader().getModelEntity(
1199: entityName);
1200: GenericHelper helper = getEntityHelper(entityName);
1201:
1202: return helper.storeByCondition(modelEntity, fieldsToSet,
1203: condition);
1204: } catch (GenericEntityException e) {
1205: String errMsg = "Failure in storeByCondition operation for entity ["
1206: + entityName
1207: + "]: "
1208: + e.toString()
1209: + ". Rolling back transaction.";
1210: Debug.logError(e, errMsg, module);
1211: try {
1212: // only rollback the transaction if we started one...
1213: TransactionUtil.rollback(beganTransaction, errMsg, e);
1214: } catch (GenericEntityException e2) {
1215: Debug.logError(e2,
1216: "[GenericDelegator] Could not rollback transaction: "
1217: + e2.toString(), module);
1218: }
1219: // after rolling back, rethrow the exception
1220: throw e;
1221: } finally {
1222: // only commit the transaction if we started one... this will throw an exception if it fails
1223: TransactionUtil.commit(beganTransaction);
1224: }
1225: }
1226:
1227: /** Store the Entity from the GenericValue to the persistent store
1228: *@param value GenericValue instance containing the entity
1229: *@return int representing number of rows effected by this operation
1230: */
1231: public int store(GenericValue value) throws GenericEntityException {
1232: return this .store(value, true);
1233: }
1234:
1235: /** Store the Entity from the GenericValue to the persistent store
1236: *@param value GenericValue instance containing the entity
1237: *@param doCacheClear boolean that specifies whether or not to automatically clear cache entries related to this operation
1238: *@return int representing number of rows effected by this operation
1239: */
1240: public int store(GenericValue value, boolean doCacheClear)
1241: throws GenericEntityException {
1242: boolean beganTransaction = false;
1243: try {
1244: if (alwaysUseTransaction) {
1245: beganTransaction = TransactionUtil.begin();
1246: }
1247:
1248: Map ecaEventMap = this .getEcaEntityEventMap(value
1249: .getEntityName());
1250: this .evalEcaRules(EntityEcaHandler.EV_VALIDATE,
1251: EntityEcaHandler.OP_STORE, value, ecaEventMap,
1252: (ecaEventMap == null), false);
1253: GenericHelper helper = getEntityHelper(value
1254: .getEntityName());
1255:
1256: if (doCacheClear) {
1257: // always clear cache before the operation
1258: this .evalEcaRules(EntityEcaHandler.EV_CACHE_CLEAR,
1259: EntityEcaHandler.OP_STORE, value, ecaEventMap,
1260: (ecaEventMap == null), false);
1261: this .clearCacheLine(value);
1262: }
1263:
1264: this .evalEcaRules(EntityEcaHandler.EV_RUN,
1265: EntityEcaHandler.OP_STORE, value, ecaEventMap,
1266: (ecaEventMap == null), false);
1267: this .encryptFields(value);
1268: int retVal = helper.store(value);
1269:
1270: // refresh the valueObject to get the new version
1271: if (value.lockEnabled()) {
1272: refresh(value, doCacheClear);
1273: }
1274:
1275: this .evalEcaRules(EntityEcaHandler.EV_RETURN,
1276: EntityEcaHandler.OP_STORE, value, ecaEventMap,
1277: (ecaEventMap == null), false);
1278: return retVal;
1279: } catch (GenericEntityException e) {
1280: String errMsg = "Failure in store operation for entity ["
1281: + value.getEntityName() + "]: " + e.toString()
1282: + ". Rolling back transaction.";
1283: Debug.logError(e, errMsg, module);
1284: try {
1285: // only rollback the transaction if we started one...
1286: TransactionUtil.rollback(beganTransaction, errMsg, e);
1287: } catch (GenericEntityException e2) {
1288: Debug.logError(e2,
1289: "[GenericDelegator] Could not rollback transaction: "
1290: + e2.toString(), module);
1291: }
1292: // after rolling back, rethrow the exception
1293: throw e;
1294: } finally {
1295: // only commit the transaction if we started one... this will throw an exception if it fails
1296: TransactionUtil.commit(beganTransaction);
1297: }
1298: }
1299:
1300: /** Store the Entities from the List GenericValue instances to the persistent store.
1301: * <br/>This is different than the normal store method in that the store method only does
1302: * an update, while the storeAll method checks to see if each entity exists, then
1303: * either does an insert or an update as appropriate.
1304: * <br/>These updates all happen in one transaction, so they will either all succeed or all fail,
1305: * if the data source supports transactions. This is just like to othersToStore feature
1306: * of the GenericEntity on a create or store.
1307: *@param values List of GenericValue instances containing the entities to store
1308: *@return int representing number of rows effected by this operation
1309: */
1310: public int storeAll(List values) throws GenericEntityException {
1311: return this .storeAll(values, true);
1312: }
1313:
1314: /** Store the Entities from the List GenericValue instances to the persistent store.
1315: * <br/>This is different than the normal store method in that the store method only does
1316: * an update, while the storeAll method checks to see if each entity exists, then
1317: * either does an insert or an update as appropriate.
1318: * <br/>These updates all happen in one transaction, so they will either all succeed or all fail,
1319: * if the data source supports transactions. This is just like to othersToStore feature
1320: * of the GenericEntity on a create or store.
1321: *@param values List of GenericValue instances containing the entities to store
1322: *@param doCacheClear boolean that specifies whether or not to automatically clear cache entries related to this operation
1323: *@return int representing number of rows effected by this operation
1324: */
1325: public int storeAll(List values, boolean doCacheClear)
1326: throws GenericEntityException {
1327: return this .storeAll(values, doCacheClear, false);
1328: }
1329:
1330: /** Store the Entities from the List GenericValue instances to the persistent store.
1331: * <br/>This is different than the normal store method in that the store method only does
1332: * an update, while the storeAll method checks to see if each entity exists, then
1333: * either does an insert or an update as appropriate.
1334: * <br/>These updates all happen in one transaction, so they will either all succeed or all fail,
1335: * if the data source supports transactions. This is just like to othersToStore feature
1336: * of the GenericEntity on a create or store.
1337: *@param values List of GenericValue instances containing the entities to store
1338: *@param doCacheClear boolean that specifies whether or not to automatically clear cache entries related to this operation
1339: *@param createDummyFks boolean that specifies whether or not to automatically create "dummy" place holder FKs
1340: *@return int representing number of rows effected by this operation
1341: */
1342: public int storeAll(List values, boolean doCacheClear,
1343: boolean createDummyFks) throws GenericEntityException {
1344: if (values == null) {
1345: return 0;
1346: }
1347:
1348: int numberChanged = 0;
1349:
1350: boolean beganTransaction = false;
1351: try {
1352: beganTransaction = TransactionUtil.begin();
1353:
1354: Iterator viter = values.iterator();
1355: while (viter.hasNext()) {
1356: GenericValue value = (GenericValue) viter.next();
1357: String entityName = value.getEntityName();
1358: GenericPK primaryKey = value.getPrimaryKey();
1359: GenericHelper helper = getEntityHelper(entityName);
1360:
1361: // exists?
1362: // NOTE: don't use findByPrimaryKey because we don't want to the ECA events to fire and such
1363: if (!primaryKey.isPrimaryKey()) {
1364: throw new GenericModelException(
1365: "[GenericDelegator.storeAll] One of the passed primary keys is not a valid primary key: "
1366: + primaryKey);
1367: }
1368: GenericValue existing = null;
1369: try {
1370: existing = helper.findByPrimaryKey(primaryKey);
1371: this .decryptFields(existing);
1372: } catch (GenericEntityNotFoundException e) {
1373: existing = null;
1374: }
1375:
1376: if (existing == null) {
1377: if (createDummyFks) {
1378: value.checkFks(true);
1379: }
1380: this .create(value, doCacheClear);
1381: numberChanged++;
1382: } else {
1383: // don't send fields that are the same, and if no fields have changed, update nothing
1384: ModelEntity modelEntity = value.getModelEntity();
1385: GenericValue toStore = GenericValue.create(
1386: modelEntity, value.getPrimaryKey());
1387: toStore.setDelegator(this );
1388: boolean atLeastOneField = false;
1389: Iterator nonPksIter = modelEntity
1390: .getNopksIterator();
1391: while (nonPksIter.hasNext()) {
1392: ModelField modelField = (ModelField) nonPksIter
1393: .next();
1394: String fieldName = modelField.getName();
1395: if (value.containsKey(fieldName)) {
1396: Object fieldValue = value.get(fieldName);
1397: Object oldValue = existing.get(fieldName);
1398: if ((fieldValue == null && oldValue != null)
1399: || (fieldValue != null && !fieldValue
1400: .equals(oldValue))) {
1401: toStore.put(fieldName, fieldValue);
1402: atLeastOneField = true;
1403: }
1404: }
1405: }
1406:
1407: if (atLeastOneField) {
1408: if (createDummyFks) {
1409: value.checkFks(true);
1410: }
1411: numberChanged += this .store(toStore,
1412: doCacheClear);
1413: }
1414: }
1415: }
1416:
1417: return numberChanged;
1418: } catch (GenericEntityException e) {
1419: String errMsg = "Failure in storeAll operation: "
1420: + e.toString() + ". Rolling back transaction.";
1421: Debug.logError(e, errMsg, module);
1422: try {
1423: // only rollback the transaction if we started one...
1424: TransactionUtil.rollback(beganTransaction, errMsg, e);
1425: } catch (GenericEntityException e2) {
1426: Debug.logError(e2,
1427: "[GenericDelegator] Could not rollback transaction: "
1428: + e2.toString(), module);
1429: }
1430: // after rolling back, rethrow the exception
1431: throw e;
1432: } finally {
1433: // only commit the transaction if we started one... this will throw an exception if it fails
1434: TransactionUtil.commit(beganTransaction);
1435: }
1436: }
1437:
1438: /** Remove the Entities from the List from the persistent store.
1439: * <br/>The List contains GenericEntity objects, can be either GenericPK or GenericValue.
1440: * <br/>If a certain entity contains a complete primary key, the entity in the datasource corresponding
1441: * to that primary key will be removed, this is like a removeByPrimary Key.
1442: * <br/>On the other hand, if a certain entity is an incomplete or non primary key,
1443: * if will behave like the removeByAnd method.
1444: * <br/>These updates all happen in one transaction, so they will either all succeed or all fail,
1445: * if the data source supports transactions.
1446: *@param dummyPKs Collection of GenericEntity instances containing the entities or by and fields to remove
1447: *@return int representing number of rows effected by this operation
1448: */
1449: public int removeAll(List dummyPKs) throws GenericEntityException {
1450: return this .removeAll(dummyPKs, true);
1451: }
1452:
1453: /** Remove the Entities from the List from the persistent store.
1454: * <br/>The List contains GenericEntity objects, can be either GenericPK or GenericValue.
1455: * <br/>If a certain entity contains a complete primary key, the entity in the datasource corresponding
1456: * to that primary key will be removed, this is like a removeByPrimary Key.
1457: * <br/>On the other hand, if a certain entity is an incomplete or non primary key,
1458: * if will behave like the removeByAnd method.
1459: * <br/>These updates all happen in one transaction, so they will either all succeed or all fail,
1460: * if the data source supports transactions.
1461: *@param dummyPKs Collection of GenericEntity instances containing the entities or by and fields to remove
1462: *@param doCacheClear boolean that specifies whether or not to automatically clear cache entries related to this operation
1463: *@return int representing number of rows effected by this operation
1464: */
1465: public int removeAll(List dummyPKs, boolean doCacheClear)
1466: throws GenericEntityException {
1467: if (dummyPKs == null) {
1468: return 0;
1469: }
1470:
1471: boolean beganTransaction = false;
1472: int numRemoved = 0;
1473:
1474: try {
1475: Iterator viter = dummyPKs.iterator();
1476: while (viter.hasNext()) {
1477: GenericEntity value = (GenericEntity) viter.next();
1478: if (value.containsPrimaryKey()) {
1479: numRemoved += this .removeByPrimaryKey(value
1480: .getPrimaryKey(), doCacheClear);
1481: } else {
1482: numRemoved += this .removeByAnd(value
1483: .getEntityName(), value.getAllFields(),
1484: doCacheClear);
1485: }
1486: }
1487:
1488: return numRemoved;
1489: } catch (GenericEntityException e) {
1490: String errMsg = "Failure in removeAll operation: "
1491: + e.toString() + ". Rolling back transaction.";
1492: Debug.logError(e, errMsg, module);
1493: try {
1494: // only rollback the transaction if we started one...
1495: TransactionUtil.rollback(beganTransaction, errMsg, e);
1496: } catch (GenericEntityException e2) {
1497: Debug.logError(e2,
1498: "[GenericDelegator] Could not rollback transaction: "
1499: + e2.toString(), module);
1500: }
1501: // after rolling back, rethrow the exception
1502: throw e;
1503: } finally {
1504: // only commit the transaction if we started one... this will throw an exception if it fails
1505: TransactionUtil.commit(beganTransaction);
1506: }
1507: }
1508:
1509: // ======================================
1510: // ======= Find Methods =================
1511: // ======================================
1512:
1513: /** Find a Generic Entity by its Primary Key
1514: *@param primaryKey The primary key to find by.
1515: *@return The GenericValue corresponding to the primaryKey
1516: */
1517: public GenericValue findByPrimaryKey(GenericPK primaryKey)
1518: throws GenericEntityException {
1519: boolean beganTransaction = false;
1520: try {
1521: if (alwaysUseTransaction) {
1522: beganTransaction = TransactionUtil.begin();
1523: }
1524:
1525: Map ecaEventMap = this .getEcaEntityEventMap(primaryKey
1526: .getEntityName());
1527: this .evalEcaRules(EntityEcaHandler.EV_VALIDATE,
1528: EntityEcaHandler.OP_FIND, primaryKey, ecaEventMap,
1529: (ecaEventMap == null), false);
1530:
1531: GenericHelper helper = getEntityHelper(primaryKey
1532: .getEntityName());
1533: GenericValue value = null;
1534:
1535: if (!primaryKey.isPrimaryKey()) {
1536: throw new GenericModelException(
1537: "[GenericDelegator.findByPrimaryKey] Passed primary key is not a valid primary key: "
1538: + primaryKey);
1539: }
1540: this .evalEcaRules(EntityEcaHandler.EV_RUN,
1541: EntityEcaHandler.OP_FIND, primaryKey, ecaEventMap,
1542: (ecaEventMap == null), false);
1543: try {
1544: value = helper.findByPrimaryKey(primaryKey);
1545: } catch (GenericEntityNotFoundException e) {
1546: value = null;
1547: }
1548: if (value != null) {
1549: value.setDelegator(this );
1550: this .decryptFields(value);
1551: }
1552:
1553: this .evalEcaRules(EntityEcaHandler.EV_RETURN,
1554: EntityEcaHandler.OP_FIND, primaryKey, ecaEventMap,
1555: (ecaEventMap == null), false);
1556: return value;
1557: } catch (GenericEntityException e) {
1558: String errMsg = "Failure in findByPrimaryKey operation for entity ["
1559: + primaryKey.getEntityName()
1560: + "]: "
1561: + e.toString()
1562: + ". Rolling back transaction.";
1563: Debug.logError(e, errMsg, module);
1564: try {
1565: // only rollback the transaction if we started one...
1566: TransactionUtil.rollback(beganTransaction, errMsg, e);
1567: } catch (GenericEntityException e2) {
1568: Debug.logError(e2,
1569: "[GenericDelegator] Could not rollback transaction: "
1570: + e2.toString(), module);
1571: }
1572: // after rolling back, rethrow the exception
1573: throw e;
1574: } finally {
1575: // only commit the transaction if we started one... this will throw an exception if it fails
1576: TransactionUtil.commit(beganTransaction);
1577: }
1578: }
1579:
1580: /** Find a CACHED Generic Entity by its Primary Key
1581: *@param primaryKey The primary key to find by.
1582: *@return The GenericValue corresponding to the primaryKey
1583: */
1584: public GenericValue findByPrimaryKeyCache(GenericPK primaryKey)
1585: throws GenericEntityException {
1586: Map ecaEventMap = this .getEcaEntityEventMap(primaryKey
1587: .getEntityName());
1588: this .evalEcaRules(EntityEcaHandler.EV_CACHE_CHECK,
1589: EntityEcaHandler.OP_FIND, primaryKey, ecaEventMap,
1590: (ecaEventMap == null), false);
1591:
1592: GenericValue value = this .getFromPrimaryKeyCache(primaryKey);
1593: if (value instanceof GenericEntity.NULL)
1594: return null;
1595: if (value == null) {
1596: value = findByPrimaryKey(primaryKey);
1597: if (value != null) {
1598: this .evalEcaRules(EntityEcaHandler.EV_CACHE_PUT,
1599: EntityEcaHandler.OP_FIND, primaryKey,
1600: ecaEventMap, (ecaEventMap == null), false);
1601: this .putInPrimaryKeyCache(primaryKey, value);
1602: } else {
1603: this .putInPrimaryKeyCache(primaryKey,
1604: GenericValue.NULL_VALUE);
1605: }
1606: }
1607: return value;
1608: }
1609:
1610: /** Find a Generic Entity by its Primary Key
1611: *@param entityName The Name of the Entity as defined in the entity XML file
1612: *@param fields The fields of the named entity to query by with their corresponging values
1613: *@return The GenericValue corresponding to the primaryKey
1614: */
1615: public GenericValue findByPrimaryKey(String entityName, Map fields)
1616: throws GenericEntityException {
1617: return findByPrimaryKey(makePK(entityName, fields));
1618: }
1619:
1620: /** Find a CACHED Generic Entity by its Primary Key
1621: *@param entityName The Name of the Entity as defined in the entity XML file
1622: *@param fields The fields of the named entity to query by with their corresponging values
1623: *@return The GenericValue corresponding to the primaryKey
1624: */
1625: public GenericValue findByPrimaryKeyCache(String entityName,
1626: Map fields) throws GenericEntityException {
1627: return findByPrimaryKeyCache(makePK(entityName, fields));
1628: }
1629:
1630: /** Find a Generic Entity by its Primary Key and only returns the values requested by the passed keys (names)
1631: *@param primaryKey The primary key to find by.
1632: *@param keys The keys, or names, of the values to retrieve; only these values will be retrieved
1633: *@return The GenericValue corresponding to the primaryKey
1634: */
1635: public GenericValue findByPrimaryKeyPartial(GenericPK primaryKey,
1636: Set keys) throws GenericEntityException {
1637: boolean beganTransaction = false;
1638: try {
1639: if (alwaysUseTransaction) {
1640: beganTransaction = TransactionUtil.begin();
1641: }
1642:
1643: Map ecaEventMap = this .getEcaEntityEventMap(primaryKey
1644: .getEntityName());
1645: this .evalEcaRules(EntityEcaHandler.EV_VALIDATE,
1646: EntityEcaHandler.OP_FIND, primaryKey, ecaEventMap,
1647: (ecaEventMap == null), false);
1648:
1649: GenericHelper helper = getEntityHelper(primaryKey
1650: .getEntityName());
1651: GenericValue value = null;
1652:
1653: if (!primaryKey.isPrimaryKey()) {
1654: throw new GenericModelException(
1655: "[GenericDelegator.findByPrimaryKey] Passed primary key is not a valid primary key: "
1656: + primaryKey);
1657: }
1658:
1659: this .evalEcaRules(EntityEcaHandler.EV_RUN,
1660: EntityEcaHandler.OP_FIND, primaryKey, ecaEventMap,
1661: (ecaEventMap == null), false);
1662: try {
1663: value = helper
1664: .findByPrimaryKeyPartial(primaryKey, keys);
1665: } catch (GenericEntityNotFoundException e) {
1666: value = null;
1667: }
1668: if (value != null)
1669: value.setDelegator(this );
1670:
1671: this .evalEcaRules(EntityEcaHandler.EV_RETURN,
1672: EntityEcaHandler.OP_FIND, primaryKey, ecaEventMap,
1673: (ecaEventMap == null), false);
1674: return value;
1675: } catch (GenericEntityException e) {
1676: String errMsg = "Failure in findByPrimaryKeyPartial operation for entity ["
1677: + primaryKey.getEntityName()
1678: + "]: "
1679: + e.toString()
1680: + ". Rolling back transaction.";
1681: Debug.logError(e, errMsg, module);
1682: try {
1683: // only rollback the transaction if we started one...
1684: TransactionUtil.rollback(beganTransaction, errMsg, e);
1685: } catch (GenericEntityException e2) {
1686: Debug.logError(e2,
1687: "[GenericDelegator] Could not rollback transaction: "
1688: + e2.toString(), module);
1689: }
1690: // after rolling back, rethrow the exception
1691: throw e;
1692: } finally {
1693: // only commit the transaction if we started one... this will throw an exception if it fails
1694: TransactionUtil.commit(beganTransaction);
1695: }
1696: }
1697:
1698: /** Find a number of Generic Value objects by their Primary Keys, all at once
1699: *@param primaryKeys A Collection of primary keys to find by.
1700: *@return List of GenericValue objects corresponding to the passed primaryKey objects
1701: */
1702: public List findAllByPrimaryKeys(Collection primaryKeys)
1703: throws GenericEntityException {
1704: boolean beganTransaction = false;
1705: try {
1706: if (alwaysUseTransaction) {
1707: beganTransaction = TransactionUtil.begin();
1708: }
1709:
1710: //TODO: add eca eval calls
1711: //TODO: maybe this should use the internal findBy methods
1712: if (primaryKeys == null)
1713: return null;
1714: List results = FastList.newInstance();
1715:
1716: // from the delegator level this is complicated because different GenericPK
1717: // objects in the list may correspond to different helpers
1718: Map pksPerHelper = FastMap.newInstance();
1719: Iterator pkiter = primaryKeys.iterator();
1720: while (pkiter.hasNext()) {
1721: GenericPK curPK = (GenericPK) pkiter.next();
1722: String helperName = this .getEntityHelperName(curPK
1723: .getEntityName());
1724: List pks = (List) pksPerHelper.get(helperName);
1725:
1726: if (pks == null) {
1727: pks = FastList.newInstance();
1728: pksPerHelper.put(helperName, pks);
1729: }
1730: pks.add(curPK);
1731: }
1732:
1733: Iterator helperIter = pksPerHelper.entrySet().iterator();
1734:
1735: while (helperIter.hasNext()) {
1736: Map.Entry curEntry = (Map.Entry) helperIter.next();
1737: String helperName = (String) curEntry.getKey();
1738: GenericHelper helper = GenericHelperFactory
1739: .getHelper(helperName);
1740: List values = helper
1741: .findAllByPrimaryKeys((List) curEntry
1742: .getValue());
1743:
1744: results.addAll(values);
1745: }
1746:
1747: this .decryptFields(results);
1748: return results;
1749: } catch (GenericEntityException e) {
1750: String errMsg = "Failure in findAllByPrimaryKeys operation, rolling back transaction";
1751: Debug.logError(e, errMsg, module);
1752: try {
1753: // only rollback the transaction if we started one...
1754: TransactionUtil.rollback(beganTransaction, errMsg, e);
1755: } catch (GenericEntityException e2) {
1756: Debug.logError(e2,
1757: "[GenericDelegator] Could not rollback transaction: "
1758: + e2.toString(), module);
1759: }
1760: // after rolling back, rethrow the exception
1761: throw e;
1762: } finally {
1763: // only commit the transaction if we started one... this will throw an exception if it fails
1764: TransactionUtil.commit(beganTransaction);
1765: }
1766: }
1767:
1768: /** Find a number of Generic Value objects by their Primary Keys, all at once;
1769: * this first looks in the local cache for each PK and if there then it puts it
1770: * in the return list rather than putting it in the batch to send to
1771: * a given helper.
1772: *@param primaryKeys A Collection of primary keys to find by.
1773: *@return List of GenericValue objects corresponding to the passed primaryKey objects
1774: */
1775: public List findAllByPrimaryKeysCache(Collection primaryKeys)
1776: throws GenericEntityException {
1777: boolean beganTransaction = false;
1778: try {
1779: if (alwaysUseTransaction) {
1780: beganTransaction = TransactionUtil.begin();
1781: }
1782:
1783: //TODO: add eca eval calls
1784: //TODO: maybe this should use the internal findBy methods
1785: if (primaryKeys == null)
1786: return null;
1787: List results = FastList.newInstance();
1788:
1789: // from the delegator level this is complicated because different GenericPK
1790: // objects in the list may correspond to different helpers
1791: Map pksPerHelper = FastMap.newInstance();
1792: Iterator pkiter = primaryKeys.iterator();
1793:
1794: while (pkiter.hasNext()) {
1795: GenericPK curPK = (GenericPK) pkiter.next();
1796:
1797: GenericValue value = this .getFromPrimaryKeyCache(curPK);
1798:
1799: if (value != null) {
1800: // it is in the cache, so just put the cached value in the results
1801: results.add(value);
1802: } else {
1803: // is not in the cache, so put in a list for a call to the helper
1804: String helperName = this .getEntityHelperName(curPK
1805: .getEntityName());
1806: List pks = (List) pksPerHelper.get(helperName);
1807:
1808: if (pks == null) {
1809: pks = FastList.newInstance();
1810: pksPerHelper.put(helperName, pks);
1811: }
1812: pks.add(curPK);
1813: }
1814: }
1815:
1816: Iterator helperIter = pksPerHelper.entrySet().iterator();
1817:
1818: while (helperIter.hasNext()) {
1819: Map.Entry curEntry = (Map.Entry) helperIter.next();
1820: String helperName = (String) curEntry.getKey();
1821: GenericHelper helper = GenericHelperFactory
1822: .getHelper(helperName);
1823: List values = helper
1824: .findAllByPrimaryKeys((List) curEntry
1825: .getValue());
1826:
1827: this .putAllInPrimaryKeyCache(values);
1828: results.addAll(values);
1829: }
1830:
1831: this .decryptFields(results);
1832: return results;
1833: } catch (GenericEntityException e) {
1834: String errMsg = "Failure in findAllByPrimaryKeysCache operation, rolling back transaction";
1835: Debug.logError(e, errMsg, module);
1836: try {
1837: // only rollback the transaction if we started one...
1838: TransactionUtil.rollback(beganTransaction, errMsg, e);
1839: } catch (GenericEntityException e2) {
1840: Debug.logError(e2,
1841: "[GenericDelegator] Could not rollback transaction: "
1842: + e2.toString(), module);
1843: }
1844: // after rolling back, rethrow the exception
1845: throw e;
1846: } finally {
1847: // only commit the transaction if we started one... this will throw an exception if it fails
1848: TransactionUtil.commit(beganTransaction);
1849: }
1850: }
1851:
1852: /** Finds all Generic entities
1853: *@param entityName The Name of the Entity as defined in the entity XML file
1854: *@return List containing all Generic entities
1855: */
1856: public List findAll(String entityName)
1857: throws GenericEntityException {
1858: return this .findByAnd(entityName, FastMap.newInstance(), null);
1859: }
1860:
1861: /** Finds all Generic entities
1862: *@param entityName The Name of the Entity as defined in the entity XML file
1863: *@param orderBy The fields of the named entity to order the query by; optionally add a " ASC" for ascending or " DESC" for descending
1864: *@return List containing all Generic entities
1865: */
1866: public List findAll(String entityName, List orderBy)
1867: throws GenericEntityException {
1868: return this .findByAnd(entityName, FastMap.newInstance(),
1869: orderBy);
1870: }
1871:
1872: /** Finds all Generic entities, looking first in the cache
1873: *@param entityName The Name of the Entity as defined in the entity XML file
1874: *@return List containing all Generic entities
1875: */
1876: public List findAllCache(String entityName)
1877: throws GenericEntityException {
1878: return this .findAllCache(entityName, null);
1879: }
1880:
1881: /** Finds all Generic entities, looking first in the cache; uses orderBy for lookup, but only keys results on the entityName and fields
1882: *@param entityName The Name of the Entity as defined in the entity XML file
1883: *@param orderBy The fields of the named entity to order the query by; optionally add a " ASC" for ascending or " DESC" for descending
1884: *@return List containing all Generic entities
1885: */
1886: public List findAllCache(String entityName, List orderBy)
1887: throws GenericEntityException {
1888: GenericValue dummyValue = makeValue(entityName, null);
1889: Map ecaEventMap = this .getEcaEntityEventMap(entityName);
1890: this .evalEcaRules(EntityEcaHandler.EV_CACHE_CHECK,
1891: EntityEcaHandler.OP_FIND, dummyValue, ecaEventMap,
1892: (ecaEventMap == null), false);
1893:
1894: List lst = cache.get(entityName, null, orderBy);
1895:
1896: if (lst == null) {
1897: lst = findAll(entityName, orderBy);
1898: if (lst != null) {
1899: this .evalEcaRules(EntityEcaHandler.EV_CACHE_PUT,
1900: EntityEcaHandler.OP_FIND, dummyValue,
1901: ecaEventMap, (ecaEventMap == null), false);
1902: cache.put(entityName, null, orderBy, lst);
1903: }
1904: }
1905: return lst;
1906: }
1907:
1908: /** Finds Generic Entity records by all of the specified fields (ie: combined using AND)
1909: * @param entityName The Name of the Entity as defined in the entity XML file
1910: * @param fields The fields of the named entity to query by with their corresponging values
1911: * @return List of GenericValue instances that match the query
1912: */
1913: public List findByAnd(String entityName, Map fields)
1914: throws GenericEntityException {
1915: return this .findByAnd(entityName, fields, null);
1916: }
1917:
1918: /** Finds Generic Entity records by all of the specified fields (ie: combined using OR)
1919: * @param entityName The Name of the Entity as defined in the entity XML file
1920: * @param fields The fields of the named entity to query by with their corresponging values
1921: * @return List of GenericValue instances that match the query
1922: */
1923: public List findByOr(String entityName, Map fields)
1924: throws GenericEntityException {
1925: return this .findByOr(entityName, fields, null);
1926: }
1927:
1928: /** Finds Generic Entity records by all of the specified fields (ie: combined using AND)
1929: * @param entityName The Name of the Entity as defined in the entity XML file
1930: * @param fields The fields of the named entity to query by with their corresponging values
1931: * @param orderBy The fields of the named entity to order the query by;
1932: * optionally add a " ASC" for ascending or " DESC" for descending
1933: * @return List of GenericValue instances that match the query
1934: */
1935: public List findByAnd(String entityName, Map fields, List orderBy)
1936: throws GenericEntityException {
1937: EntityCondition ecl = new EntityFieldMap(fields,
1938: EntityOperator.AND);
1939: return findByCondition(entityName, ecl, null, orderBy);
1940: }
1941:
1942: /* is this actually used anywhere? public List findByAnd(ModelEntity modelEntity, Map fields, List orderBy) throws GenericEntityException {
1943: EntityCondition ecl = new EntityFieldMap(fields, EntityOperator.AND);
1944: return findByCondition(modelEntity.getEntityName(), ecl, null, orderBy);
1945: }*/
1946:
1947: /** Finds Generic Entity records by all of the specified fields (ie: combined using OR)
1948: * @param entityName The Name of the Entity as defined in the entity XML file
1949: * @param fields The fields of the named entity to query by with their corresponging values
1950: * @param orderBy The fields of the named entity to order the query by;
1951: * optionally add a " ASC" for ascending or " DESC" for descending
1952: * @return List of GenericValue instances that match the query
1953: */
1954: public List findByOr(String entityName, Map fields, List orderBy)
1955: throws GenericEntityException {
1956: EntityCondition ecl = new EntityFieldMap(fields,
1957: EntityOperator.OR);
1958: return findByCondition(entityName, ecl, null, orderBy);
1959: }
1960:
1961: /** 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
1962: *@param entityName The Name of the Entity as defined in the entity XML file
1963: *@param fields The fields of the named entity to query by with their corresponging values
1964: *@return List of GenericValue instances that match the query
1965: */
1966: public List findByAndCache(String entityName, Map fields)
1967: throws GenericEntityException {
1968: return this .findByAndCache(entityName, fields, null);
1969: }
1970:
1971: /** 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
1972: *@param entityName The Name of the Entity as defined in the entity XML file
1973: *@param fields The fields of the named entity to query by with their corresponging values
1974: *@param orderBy The fields of the named entity to order the query by; optionally add a " ASC" for ascending or " DESC" for descending
1975: *@return List of GenericValue instances that match the query
1976: */
1977: public List findByAndCache(String entityName, Map fields,
1978: List orderBy) throws GenericEntityException {
1979: return findByConditionCache(entityName, new EntityFieldMap(
1980: fields, EntityOperator.AND), null, orderBy);
1981: }
1982:
1983: /** Finds Generic Entity records by all of the specified expressions (ie: combined using AND)
1984: *@param entityName The Name of the Entity as defined in the entity XML file
1985: *@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
1986: *@return List of GenericValue instances that match the query
1987: */
1988: public List findByAnd(String entityName, List expressions)
1989: throws GenericEntityException {
1990: EntityConditionList ecl = new EntityConditionList(expressions,
1991: EntityOperator.AND);
1992: return findByCondition(entityName, ecl, null, null);
1993: }
1994:
1995: /** Finds Generic Entity records by all of the specified expressions (ie: combined using AND)
1996: *@param entityName The Name of the Entity as defined in the entity XML file
1997: *@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
1998: *@param orderBy The fields of the named entity to order the query by; optionally add a " ASC" for ascending or " DESC" for descending
1999: *@return List of GenericValue instances that match the query
2000: */
2001: public List findByAnd(String entityName, List expressions,
2002: List orderBy) throws GenericEntityException {
2003: EntityConditionList ecl = new EntityConditionList(expressions,
2004: EntityOperator.AND);
2005: return findByCondition(entityName, ecl, null, orderBy);
2006: }
2007:
2008: /** Finds Generic Entity records by all of the specified expressions (ie: combined using OR)
2009: *@param entityName The Name of the Entity as defined in the entity XML file
2010: *@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
2011: *@return List of GenericValue instances that match the query
2012: */
2013: public List findByOr(String entityName, List expressions)
2014: throws GenericEntityException {
2015: EntityConditionList ecl = new EntityConditionList(expressions,
2016: EntityOperator.OR);
2017: return findByCondition(entityName, ecl, null, null);
2018: }
2019:
2020: /** Finds Generic Entity records by all of the specified expressions (ie: combined using OR)
2021: *@param entityName The Name of the Entity as defined in the entity XML file
2022: *@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
2023: *@param orderBy The fields of the named entity to order the query by; optionally add a " ASC" for ascending or " DESC" for descending
2024: *@return List of GenericValue instances that match the query
2025: */
2026: public List findByOr(String entityName, List expressions,
2027: List orderBy) throws GenericEntityException {
2028: EntityConditionList ecl = new EntityConditionList(expressions,
2029: EntityOperator.OR);
2030: return findByCondition(entityName, ecl, null, orderBy);
2031: }
2032:
2033: public List findByLike(String entityName, Map fields)
2034: throws GenericEntityException {
2035: return findByLike(entityName, fields, null);
2036: }
2037:
2038: public List findByLike(String entityName, Map fields, List orderBy)
2039: throws GenericEntityException {
2040: List likeExpressions = FastList.newInstance();
2041: if (fields != null) {
2042: Iterator fieldEntries = fields.entrySet().iterator();
2043: while (fieldEntries.hasNext()) {
2044: Map.Entry fieldEntry = (Map.Entry) fieldEntries.next();
2045: likeExpressions.add(new EntityExpr((String) fieldEntry
2046: .getKey(), EntityOperator.LIKE, fieldEntry
2047: .getValue()));
2048: }
2049: }
2050: EntityConditionList ecl = new EntityConditionList(
2051: likeExpressions, EntityOperator.AND);
2052: return findByCondition(entityName, ecl, null, orderBy);
2053: }
2054:
2055: /** Finds GenericValues by the conditions specified in the EntityCondition object, the the EntityCondition javadoc for more details.
2056: *@param entityName The Name of the Entity as defined in the entity model XML file
2057: *@param entityCondition The EntityCondition object that specifies how to constrain this query
2058: *@param fieldsToSelect The fields of the named entity to get from the database; if empty or null all fields will be retreived
2059: *@param orderBy The fields of the named entity to order the query by; optionally add a " ASC" for ascending or " DESC" for descending
2060: *@return List of GenericValue objects representing the result
2061: */
2062: public List findByCondition(String entityName,
2063: EntityCondition entityCondition, Collection fieldsToSelect,
2064: List orderBy) throws GenericEntityException {
2065: return this .findByCondition(entityName, entityCondition, null,
2066: fieldsToSelect, orderBy, null);
2067: }
2068:
2069: /** Finds GenericValues by the conditions specified in the EntityCondition object, the the EntityCondition javadoc for more details.
2070: *@param entityName The name of the Entity as defined in the entity XML file
2071: *@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)
2072: *@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)
2073: *@param fieldsToSelect The fields of the named entity to get from the database; if empty or null all fields will be retreived
2074: *@param orderBy The fields of the named entity to order the query by; optionally add a " ASC" for ascending or " DESC" for descending
2075: *@param findOptions An instance of EntityFindOptions that specifies advanced query options. See the EntityFindOptions JavaDoc for more details.
2076: *@return List of GenericValue objects representing the result
2077: */
2078: public List findByCondition(String entityName,
2079: EntityCondition whereEntityCondition,
2080: EntityCondition havingEntityCondition,
2081: Collection fieldsToSelect, List orderBy,
2082: EntityFindOptions findOptions)
2083: throws GenericEntityException {
2084: boolean beganTransaction = false;
2085: try {
2086: if (alwaysUseTransaction) {
2087: beganTransaction = TransactionUtil.begin();
2088: }
2089:
2090: EntityListIterator eli = this .findListIteratorByCondition(
2091: entityName, whereEntityCondition,
2092: havingEntityCondition, fieldsToSelect, orderBy,
2093: findOptions);
2094: eli.setDelegator(this );
2095: List list = eli.getCompleteList();
2096: eli.close();
2097:
2098: return list;
2099: } catch (GenericEntityException e) {
2100: String errMsg = "Failure in findByCondition operation for entity ["
2101: + entityName
2102: + "]: "
2103: + e.toString()
2104: + ". Rolling back transaction.";
2105: Debug.logError(e, errMsg, module);
2106: try {
2107: // only rollback the transaction if we started one...
2108: TransactionUtil.rollback(beganTransaction, errMsg, e);
2109: } catch (GenericEntityException e2) {
2110: Debug.logError(e2,
2111: "[GenericDelegator] Could not rollback transaction: "
2112: + e2.toString(), module);
2113: }
2114: // after rolling back, rethrow the exception
2115: throw e;
2116: } finally {
2117: // only commit the transaction if we started one... this will throw an exception if it fails
2118: TransactionUtil.commit(beganTransaction);
2119: }
2120: }
2121:
2122: /** Finds GenericValues by the conditions specified in the EntityCondition object, looking first in the cache, see the EntityCondition javadoc for more details.
2123: *@param entityName The Name of the Entity as defined in the entity model XML file
2124: *@param entityCondition The EntityCondition object that specifies how to constrain this query
2125: *@param fieldsToSelect The fields of the named entity to get from the database; if empty or null all fields will be retreived
2126: *@param orderBy The fields of the named entity to order the query by; optionally add a " ASC" for ascending or " DESC" for descending
2127: *@return List of GenericValue objects representing the result
2128: */
2129: public List findByConditionCache(String entityName,
2130: EntityCondition entityCondition, Collection fieldsToSelect,
2131: List orderBy) throws GenericEntityException {
2132: ModelEntity modelEntity = getModelReader().getModelEntity(
2133: entityName);
2134: GenericValue dummyValue = GenericValue.create(modelEntity);
2135: Map ecaEventMap = this .getEcaEntityEventMap(entityName);
2136: this .evalEcaRules(EntityEcaHandler.EV_CACHE_CHECK,
2137: EntityEcaHandler.OP_FIND, dummyValue, ecaEventMap,
2138: (ecaEventMap == null), false);
2139:
2140: List lst = cache.get(entityName, entityCondition, orderBy);
2141:
2142: if (lst == null) {
2143: lst = findByCondition(entityName, entityCondition,
2144: fieldsToSelect, orderBy);
2145: if (lst != null) {
2146: this .evalEcaRules(EntityEcaHandler.EV_CACHE_PUT,
2147: EntityEcaHandler.OP_FIND, dummyValue,
2148: ecaEventMap, (ecaEventMap == null), false);
2149: cache.put(entityName, entityCondition, orderBy, lst);
2150: }
2151: }
2152: return lst;
2153: }
2154:
2155: /** Finds GenericValues by the conditions specified in the EntityCondition object, the the EntityCondition javadoc for more details.
2156: *@param entityName The Name of the Entity as defined in the entity model XML file
2157: *@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)
2158: *@param fieldsToSelect The fields of the named entity to get from the database; if empty or null all fields will be retreived
2159: *@param orderBy The fields of the named entity to order the query by; optionally add a " ASC" for ascending or " DESC" for descending
2160: *@return EntityListIterator representing the result of the query: NOTE THAT THIS MUST BE CLOSED WHEN YOU ARE
2161: * DONE WITH IT, AND DON'T LEAVE IT OPEN TOO LONG BEACUSE IT WILL MAINTAIN A DATABASE CONNECTION.
2162: */
2163: public EntityListIterator findListIteratorByCondition(
2164: String entityName, EntityCondition entityCondition,
2165: Collection fieldsToSelect, List orderBy)
2166: throws GenericEntityException {
2167: return this .findListIteratorByCondition(entityName,
2168: entityCondition, null, fieldsToSelect, orderBy, null);
2169: }
2170:
2171: /** Finds GenericValues by the conditions specified in the EntityCondition object, the the EntityCondition javadoc for more details.
2172: *@param entityName The name of the Entity as defined in the entity XML file
2173: *@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)
2174: *@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)
2175: *@param fieldsToSelect The fields of the named entity to get from the database; if empty or null all fields will be retreived
2176: *@param orderBy The fields of the named entity to order the query by; optionally add a " ASC" for ascending or " DESC" for descending
2177: *@param findOptions An instance of EntityFindOptions that specifies advanced query options. See the EntityFindOptions JavaDoc for more details.
2178: *@return EntityListIterator representing the result of the query: NOTE THAT THIS MUST BE CLOSED WHEN YOU ARE
2179: * DONE WITH IT, AND DON'T LEAVE IT OPEN TOO LONG BEACUSE IT WILL MAINTAIN A DATABASE CONNECTION.
2180: */
2181: public EntityListIterator findListIteratorByCondition(
2182: String entityName, EntityCondition whereEntityCondition,
2183: EntityCondition havingEntityCondition,
2184: Collection fieldsToSelect, List orderBy,
2185: EntityFindOptions findOptions)
2186: throws GenericEntityException {
2187:
2188: // 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
2189: if (!TransactionUtil.isTransactionInPlace()) {
2190: //throw new GenericEntityException("ERROR: Cannot do a find that returns an EntityListIterator with no transaction in place. Wrap this call in a transaction.");
2191:
2192: //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...
2193: Exception newE = new Exception("Stack Trace");
2194: Debug
2195: .logError(
2196: newE,
2197: "ERROR: Cannot do a find that returns an EntityListIterator with no transaction in place. Wrap this call in a transaction.",
2198: module);
2199: }
2200:
2201: ModelEntity modelEntity = getModelReader().getModelEntity(
2202: entityName);
2203: GenericValue dummyValue = GenericValue.create(modelEntity);
2204: Map ecaEventMap = this .getEcaEntityEventMap(modelEntity
2205: .getEntityName());
2206: this .evalEcaRules(EntityEcaHandler.EV_VALIDATE,
2207: EntityEcaHandler.OP_FIND, dummyValue, ecaEventMap,
2208: (ecaEventMap == null), false);
2209:
2210: if (whereEntityCondition != null) {
2211: whereEntityCondition.checkCondition(modelEntity);
2212: whereEntityCondition.encryptConditionFields(modelEntity,
2213: this );
2214: }
2215: if (havingEntityCondition != null) {
2216: havingEntityCondition.checkCondition(modelEntity);
2217: havingEntityCondition.encryptConditionFields(modelEntity,
2218: this );
2219: }
2220:
2221: this .evalEcaRules(EntityEcaHandler.EV_RUN,
2222: EntityEcaHandler.OP_FIND, dummyValue, ecaEventMap,
2223: (ecaEventMap == null), false);
2224: GenericHelper helper = getEntityHelper(modelEntity
2225: .getEntityName());
2226: EntityListIterator eli = helper.findListIteratorByCondition(
2227: modelEntity, whereEntityCondition,
2228: havingEntityCondition, fieldsToSelect, orderBy,
2229: findOptions);
2230: eli.setDelegator(this );
2231:
2232: this .evalEcaRules(EntityEcaHandler.EV_RETURN,
2233: EntityEcaHandler.OP_FIND, dummyValue, ecaEventMap,
2234: (ecaEventMap == null), false);
2235: return eli;
2236: }
2237:
2238: /** Finds GenericValues by the conditions specified in the EntityCondition object, the the EntityCondition javadoc for more details.
2239: *@param dynamicViewEntity The DynamicViewEntity to use for the entity model for this query; generally created on the fly for limited use
2240: *@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)
2241: *@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)
2242: *@param fieldsToSelect The fields of the named entity to get from the database; if empty or null all fields will be retreived
2243: *@param orderBy The fields of the named entity to order the query by; optionally add a " ASC" for ascending or " DESC" for descending
2244: *@param findOptions An instance of EntityFindOptions that specifies advanced query options. See the EntityFindOptions JavaDoc for more details.
2245: *@return EntityListIterator representing the result of the query: NOTE THAT THIS MUST BE CLOSED WHEN YOU ARE
2246: * DONE WITH IT, AND DON'T LEAVE IT OPEN TOO LONG BEACUSE IT WILL MAINTAIN A DATABASE CONNECTION.
2247: */
2248: public EntityListIterator findListIteratorByCondition(
2249: DynamicViewEntity dynamicViewEntity,
2250: EntityCondition whereEntityCondition,
2251: EntityCondition havingEntityCondition,
2252: Collection fieldsToSelect, List orderBy,
2253: EntityFindOptions findOptions)
2254: throws GenericEntityException {
2255:
2256: // 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
2257: if (!TransactionUtil.isTransactionInPlace()) {
2258: //throw new GenericEntityException("ERROR: Cannot do a find that returns an EntityListIterator with no transaction in place. Wrap this call in a transaction.");
2259:
2260: //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...
2261: Exception newE = new Exception("Stack Trace");
2262: Debug
2263: .logError(
2264: newE,
2265: "ERROR: Cannot do a find that returns an EntityListIterator with no transaction in place. Wrap this call in a transaction.",
2266: module);
2267: }
2268:
2269: ModelViewEntity modelViewEntity = dynamicViewEntity
2270: .makeModelViewEntity(this );
2271: if (whereEntityCondition != null)
2272: whereEntityCondition.checkCondition(modelViewEntity);
2273: if (havingEntityCondition != null)
2274: havingEntityCondition.checkCondition(modelViewEntity);
2275:
2276: GenericHelper helper = getEntityHelper(dynamicViewEntity
2277: .getOneRealEntityName());
2278: EntityListIterator eli = helper.findListIteratorByCondition(
2279: modelViewEntity, whereEntityCondition,
2280: havingEntityCondition, fieldsToSelect, orderBy,
2281: findOptions);
2282: eli.setDelegator(this );
2283: //TODO: add decrypt fields
2284: return eli;
2285: }
2286:
2287: public long findCountByAnd(String entityName, Map fields)
2288: throws GenericEntityException {
2289: return findCountByCondition(entityName, new EntityFieldMap(
2290: fields, EntityOperator.AND), null);
2291: }
2292:
2293: public long findCountByCondition(String entityName,
2294: EntityCondition whereEntityCondition,
2295: EntityCondition havingEntityCondition)
2296: throws GenericEntityException {
2297: return findCountByCondition(entityName, whereEntityCondition,
2298: havingEntityCondition, null);
2299: }
2300:
2301: public long findCountByCondition(String entityName,
2302: EntityCondition whereEntityCondition,
2303: EntityCondition havingEntityCondition,
2304: EntityFindOptions findOptions)
2305: throws GenericEntityException {
2306:
2307: boolean beganTransaction = false;
2308: try {
2309: if (alwaysUseTransaction) {
2310: beganTransaction = TransactionUtil.begin();
2311: }
2312:
2313: ModelEntity modelEntity = getModelReader().getModelEntity(
2314: entityName);
2315: GenericValue dummyValue = GenericValue.create(modelEntity);
2316: Map ecaEventMap = this .getEcaEntityEventMap(modelEntity
2317: .getEntityName());
2318: this .evalEcaRules(EntityEcaHandler.EV_VALIDATE,
2319: EntityEcaHandler.OP_FIND, dummyValue, ecaEventMap,
2320: (ecaEventMap == null), false);
2321:
2322: if (whereEntityCondition != null) {
2323: whereEntityCondition.checkCondition(modelEntity);
2324: whereEntityCondition.encryptConditionFields(
2325: modelEntity, this );
2326: }
2327: if (havingEntityCondition != null) {
2328: havingEntityCondition.checkCondition(modelEntity);
2329: havingEntityCondition.encryptConditionFields(
2330: modelEntity, this );
2331: }
2332:
2333: this .evalEcaRules(EntityEcaHandler.EV_RUN,
2334: EntityEcaHandler.OP_FIND, dummyValue, ecaEventMap,
2335: (ecaEventMap == null), false);
2336: GenericHelper helper = getEntityHelper(modelEntity
2337: .getEntityName());
2338: long count = helper.findCountByCondition(modelEntity,
2339: whereEntityCondition, havingEntityCondition,
2340: findOptions);
2341:
2342: this .evalEcaRules(EntityEcaHandler.EV_RETURN,
2343: EntityEcaHandler.OP_FIND, dummyValue, ecaEventMap,
2344: (ecaEventMap == null), false);
2345: return count;
2346: } catch (GenericEntityException e) {
2347: String errMsg = "Failure in findListIteratorByCondition operation for entity [DynamicView]: "
2348: + e.toString() + ". Rolling back transaction.";
2349: Debug.logError(e, errMsg, module);
2350: try {
2351: // only rollback the transaction if we started one...
2352: TransactionUtil.rollback(beganTransaction, errMsg, e);
2353: } catch (GenericEntityException e2) {
2354: Debug.logError(e2,
2355: "[GenericDelegator] Could not rollback transaction: "
2356: + e2.toString(), module);
2357: }
2358: // after rolling back, rethrow the exception
2359: throw e;
2360: } finally {
2361: // only commit the transaction if we started one... this will throw an exception if it fails
2362: TransactionUtil.commit(beganTransaction);
2363: }
2364: }
2365:
2366: /**
2367: * Get the named Related Entity for the GenericValue from the persistent store across another Relation.
2368: * Helps to get related Values in a multi-to-multi relationship.
2369: * @param relationNameOne String containing the relation name which is the
2370: * combination of relation.title and relation.rel-entity-name as
2371: * specified in the entity XML definition file, for first relation
2372: * @param relationNameTwo String containing the relation name for second relation
2373: * @param value GenericValue instance containing the entity
2374: * @param orderBy The fields of the named entity to order the query by; may be null;
2375: * optionally add a " ASC" for ascending or " DESC" for descending
2376: * @return List of GenericValue instances as specified in the relation definition
2377: */
2378: public List getMultiRelation(GenericValue value,
2379: String relationNameOne, String relationNameTwo, List orderBy)
2380: throws GenericEntityException {
2381: boolean beganTransaction = false;
2382: try {
2383: if (alwaysUseTransaction) {
2384: beganTransaction = TransactionUtil.begin();
2385: }
2386:
2387: //TODO: add eca eval calls
2388: // traverse the relationships
2389: ModelEntity modelEntity = value.getModelEntity();
2390: ModelRelation modelRelationOne = modelEntity
2391: .getRelation(relationNameOne);
2392: ModelEntity modelEntityOne = getModelEntity(modelRelationOne
2393: .getRelEntityName());
2394: ModelRelation modelRelationTwo = modelEntityOne
2395: .getRelation(relationNameTwo);
2396: ModelEntity modelEntityTwo = getModelEntity(modelRelationTwo
2397: .getRelEntityName());
2398:
2399: GenericHelper helper = getEntityHelper(modelEntity);
2400:
2401: return helper.findByMultiRelation(value, modelRelationOne,
2402: modelEntityOne, modelRelationTwo, modelEntityTwo,
2403: orderBy);
2404: } catch (GenericEntityException e) {
2405: String errMsg = "Failure in getMultiRelation operation for entity ["
2406: + value.getEntityName()
2407: + "]: "
2408: + e.toString()
2409: + ". Rolling back transaction.";
2410: Debug.logError(e, errMsg, module);
2411: try {
2412: // only rollback the transaction if we started one...
2413: TransactionUtil.rollback(beganTransaction, errMsg, e);
2414: } catch (GenericEntityException e2) {
2415: Debug.logError(e2,
2416: "[GenericDelegator] Could not rollback transaction: "
2417: + e2.toString(), module);
2418: }
2419: // after rolling back, rethrow the exception
2420: throw e;
2421: } finally {
2422: // only commit the transaction if we started one... this will throw an exception if it fails
2423: TransactionUtil.commit(beganTransaction);
2424: }
2425: }
2426:
2427: /**
2428: * Get the named Related Entity for the GenericValue from the persistent store across another Relation.
2429: * Helps to get related Values in a multi-to-multi relationship.
2430: * @param relationNameOne String containing the relation name which is the
2431: * combination of relation.title and relation.rel-entity-name as
2432: * specified in the entity XML definition file, for first relation
2433: * @param relationNameTwo String containing the relation name for second relation
2434: * @param value GenericValue instance containing the entity
2435: * @return List of GenericValue instances as specified in the relation definition
2436: */
2437: public List getMultiRelation(GenericValue value,
2438: String relationNameOne, String relationNameTwo)
2439: throws GenericEntityException {
2440: return getMultiRelation(value, relationNameOne,
2441: relationNameTwo, null);
2442: }
2443:
2444: /** Get the named Related Entity for the GenericValue from the persistent store
2445: * @param relationName String containing the relation name which is the
2446: * combination of relation.title and relation.rel-entity-name as
2447: * specified in the entity XML definition file
2448: * @param value GenericValue instance containing the entity
2449: * @return List of GenericValue instances as specified in the relation definition
2450: */
2451: public List getRelated(String relationName, GenericValue value)
2452: throws GenericEntityException {
2453: return getRelated(relationName, null, null, value);
2454: }
2455:
2456: /** Get the named Related Entity for the GenericValue from the persistent store
2457: * @param relationName String containing the relation name which is the
2458: * combination of relation.title and relation.rel-entity-name as
2459: * specified in the entity XML definition file
2460: * @param byAndFields the fields that must equal in order to keep; may be null
2461: * @param value GenericValue instance containing the entity
2462: * @return List of GenericValue instances as specified in the relation definition
2463: */
2464: public List getRelatedByAnd(String relationName, Map byAndFields,
2465: GenericValue value) throws GenericEntityException {
2466: return this .getRelated(relationName, byAndFields, null, value);
2467: }
2468:
2469: /** Get the named Related Entity for the GenericValue from the persistent store
2470: * @param relationName String containing the relation name which is the
2471: * combination of relation.title and relation.rel-entity-name as
2472: * specified in the entity XML definition file
2473: * @param orderBy The fields of the named entity to order the query by; may be null;
2474: * optionally add a " ASC" for ascending or " DESC" for descending
2475: * @param value GenericValue instance containing the entity
2476: * @return List of GenericValue instances as specified in the relation definition
2477: */
2478: public List getRelatedOrderBy(String relationName, List orderBy,
2479: GenericValue value) throws GenericEntityException {
2480: return this .getRelated(relationName, null, orderBy, value);
2481: }
2482:
2483: /** Get the named Related Entity for the GenericValue from the persistent store
2484: * @param relationName String containing the relation name which is the
2485: * combination of relation.title and relation.rel-entity-name as
2486: * specified in the entity XML definition file
2487: * @param byAndFields the fields that must equal in order to keep; may be null
2488: * @param orderBy The fields of the named entity to order the query by; may be null;
2489: * optionally add a " ASC" for ascending or " DESC" for descending
2490: * @param value GenericValue instance containing the entity
2491: * @return List of GenericValue instances as specified in the relation definition
2492: */
2493: public List getRelated(String relationName, Map byAndFields,
2494: List orderBy, GenericValue value)
2495: throws GenericEntityException {
2496: ModelEntity modelEntity = value.getModelEntity();
2497: ModelRelation relation = modelEntity.getRelation(relationName);
2498:
2499: if (relation == null) {
2500: throw new GenericModelException(
2501: "Could not find relation for relationName: "
2502: + relationName + " for value " + value);
2503: }
2504:
2505: // put the byAndFields (if not null) into the hash map first,
2506: // they will be overridden by value's fields if over-specified this is important for security and cleanliness
2507: Map fields = FastMap.newInstance();
2508: if (byAndFields != null)
2509: fields.putAll(byAndFields);
2510: for (int i = 0; i < relation.getKeyMapsSize(); i++) {
2511: ModelKeyMap keyMap = relation.getKeyMap(i);
2512: fields.put(keyMap.getRelFieldName(), value.get(keyMap
2513: .getFieldName()));
2514: }
2515:
2516: return this .findByAnd(relation.getRelEntityName(), fields,
2517: orderBy);
2518: }
2519:
2520: /** Get a dummy primary key for the named Related Entity for the GenericValue
2521: * @param relationName String containing the relation name which is the
2522: * combination of relation.title and relation.rel-entity-name as
2523: * specified in the entity XML definition file
2524: * @param byAndFields the fields that must equal in order to keep; may be null
2525: * @param value GenericValue instance containing the entity
2526: * @return GenericPK containing a possibly incomplete PrimaryKey object representing the related entity or entities
2527: */
2528: public GenericPK getRelatedDummyPK(String relationName,
2529: Map byAndFields, GenericValue value)
2530: throws GenericEntityException {
2531: ModelEntity modelEntity = value.getModelEntity();
2532: ModelRelation relation = modelEntity.getRelation(relationName);
2533:
2534: if (relation == null) {
2535: throw new GenericModelException(
2536: "Could not find relation for relationName: "
2537: + relationName + " for value " + value);
2538: }
2539: ModelEntity relatedEntity = getModelReader().getModelEntity(
2540: relation.getRelEntityName());
2541:
2542: // put the byAndFields (if not null) into the hash map first,
2543: // they will be overridden by value's fields if over-specified this is important for security and cleanliness
2544: Map fields = FastMap.newInstance();
2545: if (byAndFields != null)
2546: fields.putAll(byAndFields);
2547: for (int i = 0; i < relation.getKeyMapsSize(); i++) {
2548: ModelKeyMap keyMap = relation.getKeyMap(i);
2549: fields.put(keyMap.getRelFieldName(), value.get(keyMap
2550: .getFieldName()));
2551: }
2552:
2553: GenericPK dummyPK = GenericPK.create(relatedEntity, fields);
2554: dummyPK.setDelegator(this );
2555: return dummyPK;
2556: }
2557:
2558: /** 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
2559: * @param relationName String containing the relation name which is the
2560: * combination of relation.title and relation.rel-entity-name as
2561: * specified in the entity XML definition file
2562: * @param value GenericValue instance containing the entity
2563: * @return List of GenericValue instances as specified in the relation definition
2564: */
2565: public List getRelatedCache(String relationName, GenericValue value)
2566: throws GenericEntityException {
2567: ModelEntity modelEntity = value.getModelEntity();
2568: ModelRelation relation = modelEntity.getRelation(relationName);
2569:
2570: if (relation == null) {
2571: throw new GenericModelException(
2572: "Could not find relation for relationName: "
2573: + relationName + " for value " + value);
2574: }
2575:
2576: Map fields = FastMap.newInstance();
2577: for (int i = 0; i < relation.getKeyMapsSize(); i++) {
2578: ModelKeyMap keyMap = relation.getKeyMap(i);
2579: fields.put(keyMap.getRelFieldName(), value.get(keyMap
2580: .getFieldName()));
2581: }
2582:
2583: return this .findByAndCache(relation.getRelEntityName(), fields,
2584: null);
2585: }
2586:
2587: /** Get related entity where relation is of type one, uses findByPrimaryKey
2588: * @throws IllegalArgumentException if the list found has more than one item
2589: */
2590: public GenericValue getRelatedOne(String relationName,
2591: GenericValue value) throws GenericEntityException {
2592: ModelRelation relation = value.getModelEntity().getRelation(
2593: relationName);
2594:
2595: if (relation == null) {
2596: throw new GenericModelException(
2597: "Could not find relation for relationName: "
2598: + relationName + " for value " + value);
2599: }
2600: if (!"one".equals(relation.getType())
2601: && !"one-nofk".equals(relation.getType())) {
2602: throw new GenericModelException(
2603: "Relation is not a 'one' or a 'one-nofk' relation: "
2604: + relationName + " of entity "
2605: + value.getEntityName());
2606: }
2607:
2608: Map fields = FastMap.newInstance();
2609: for (int i = 0; i < relation.getKeyMapsSize(); i++) {
2610: ModelKeyMap keyMap = relation.getKeyMap(i);
2611: fields.put(keyMap.getRelFieldName(), value.get(keyMap
2612: .getFieldName()));
2613: }
2614:
2615: return this .findByPrimaryKey(relation.getRelEntityName(),
2616: fields);
2617: }
2618:
2619: /** Get related entity where relation is of type one, uses findByPrimaryKey, checking first in the cache to see if the desired value is there
2620: * @throws IllegalArgumentException if the list found has more than one item
2621: */
2622: public GenericValue getRelatedOneCache(String relationName,
2623: GenericValue value) throws GenericEntityException {
2624: ModelEntity modelEntity = value.getModelEntity();
2625: ModelRelation relation = modelEntity.getRelation(relationName);
2626:
2627: if (relation == null) {
2628: throw new GenericModelException(
2629: "Could not find relation for relationName: "
2630: + relationName + " for value " + value);
2631: }
2632: if (!"one".equals(relation.getType())
2633: && !"one-nofk".equals(relation.getType())) {
2634: throw new GenericModelException(
2635: "Relation is not a 'one' or a 'one-nofk' relation: "
2636: + relationName + " of entity "
2637: + value.getEntityName());
2638: }
2639:
2640: Map fields = FastMap.newInstance();
2641: for (int i = 0; i < relation.getKeyMapsSize(); i++) {
2642: ModelKeyMap keyMap = relation.getKeyMap(i);
2643: fields.put(keyMap.getRelFieldName(), value.get(keyMap
2644: .getFieldName()));
2645: }
2646:
2647: return this .findByPrimaryKeyCache(relation.getRelEntityName(),
2648: fields);
2649: }
2650:
2651: // ======================================
2652: // ======= Cache Related Methods ========
2653: // ======================================
2654:
2655: /** This method is a shortcut to completely clear all entity engine caches.
2656: * For performance reasons this should not be called very often.
2657: */
2658: public void clearAllCaches() {
2659: this .clearAllCaches(true);
2660: }
2661:
2662: public void clearAllCaches(boolean distribute) {
2663: cache.clear();
2664:
2665: if (distribute && this .distributedCacheClear != null) {
2666: this .distributedCacheClear.clearAllCaches();
2667: }
2668: }
2669:
2670: /** Remove a CACHED Generic Entity (List) from the cache, either a PK, ByAnd, or All
2671: *@param entityName The Name of the Entity as defined in the entity XML file
2672: *@param fields The fields of the named entity to query by with their corresponging values
2673: */
2674: public void clearCacheLine(String entityName, Map fields) {
2675: // if no fields passed, do the all cache quickly and return
2676: if (fields == null) {
2677: cache.remove(entityName);
2678: return;
2679: }
2680:
2681: ModelEntity entity = this .getModelEntity(entityName);
2682: if (entity == null) {
2683: throw new IllegalArgumentException(
2684: "[GenericDelegator.clearCacheLine] could not find entity for entityName: "
2685: + entityName);
2686: }
2687: //if never cached, then don't bother clearing
2688: if (entity.getNeverCache())
2689: return;
2690:
2691: GenericValue dummyValue = GenericValue.create(entity, fields);
2692: dummyValue.setDelegator(this );
2693: this .clearCacheLineFlexible(dummyValue);
2694: }
2695:
2696: /** Remove a CACHED Generic Entity from the cache by its primary key.
2697: * Checks to see if the passed GenericPK is a complete primary key, if
2698: * it is then the cache line will be removed from the primaryKeyCache; if it
2699: * is NOT a complete primary key it will remove the cache line from the andCache.
2700: * If the fields map is empty, then the allCache for the entity will be cleared.
2701: *@param dummyPK The dummy primary key to clear by.
2702: */
2703: public void clearCacheLineFlexible(GenericEntity dummyPK) {
2704: this .clearCacheLineFlexible(dummyPK, true);
2705: }
2706:
2707: public void clearCacheLineFlexible(GenericEntity dummyPK,
2708: boolean distribute) {
2709: if (dummyPK != null) {
2710: //if never cached, then don't bother clearing
2711: if (dummyPK.getModelEntity().getNeverCache())
2712: return;
2713:
2714: cache.remove(dummyPK);
2715:
2716: if (distribute && this .distributedCacheClear != null) {
2717: this .distributedCacheClear
2718: .distributedClearCacheLineFlexible(dummyPK);
2719: }
2720: }
2721: }
2722:
2723: protected void clearCacheValues(UtilCache cache, String entityName,
2724: EntityCondition condition) {
2725: Iterator iterator = cache.cacheLineTable.values().iterator();
2726: while (iterator.hasNext()) {
2727: CacheLine line = (CacheLine) iterator.next();
2728: GenericValue value = (GenericValue) line.getValue();
2729: if (value != null
2730: && value.getEntityName().equals(entityName)
2731: && condition.entityMatches(value)) {
2732: iterator.remove();
2733: }
2734: }
2735: }
2736:
2737: public void clearCacheLineByCondition(String entityName,
2738: EntityCondition condition) {
2739: clearCacheLineByCondition(entityName, condition, true);
2740: }
2741:
2742: public void clearCacheLineByCondition(String entityName,
2743: EntityCondition condition, boolean distribute) {
2744: if (entityName != null) {
2745: //if never cached, then don't bother clearing
2746: if (getModelEntity(entityName).getNeverCache())
2747: return;
2748:
2749: cache.remove(entityName, condition);
2750:
2751: if (distribute && this .distributedCacheClear != null) {
2752: this .distributedCacheClear
2753: .distributedClearCacheLineByCondition(
2754: entityName, condition);
2755: }
2756: }
2757: }
2758:
2759: /** Remove a CACHED Generic Entity from the cache by its primary key, does NOT
2760: * check to see if the passed GenericPK is a complete primary key.
2761: * Also tries to clear the corresponding all cache entry.
2762: *@param primaryKey The primary key to clear by.
2763: */
2764: public void clearCacheLine(GenericPK primaryKey) {
2765: this .clearCacheLine(primaryKey, true);
2766: }
2767:
2768: public void clearCacheLine(GenericPK primaryKey, boolean distribute) {
2769: if (primaryKey == null)
2770: return;
2771:
2772: //if never cached, then don't bother clearing
2773: if (primaryKey.getModelEntity().getNeverCache())
2774: return;
2775:
2776: cache.remove(primaryKey);
2777:
2778: if (distribute && this .distributedCacheClear != null) {
2779: this .distributedCacheClear
2780: .distributedClearCacheLine(primaryKey);
2781: }
2782: }
2783:
2784: /** Remove a CACHED GenericValue from as many caches as it can. Automatically
2785: * tries to remove entries from the all cache, the by primary key cache, and
2786: * the by and cache. This is the ONLY method that tries to clear automatically
2787: * from the by and cache.
2788: *@param value The GenericValue to clear by.
2789: */
2790: public void clearCacheLine(GenericValue value) {
2791: this .clearCacheLine(value, true);
2792: }
2793:
2794: public void clearCacheLine(GenericValue value, boolean distribute) {
2795: // 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...
2796: // for instance:
2797: // on create don't clear by primary cache (and won't clear original values because there won't be any)
2798: // on remove don't clear by and for new values, but do for original values
2799:
2800: // Debug.logInfo("running clearCacheLine for value: " + value + ", distribute: " + distribute, module);
2801: if (value == null)
2802: return;
2803:
2804: //if never cached, then don't bother clearing
2805: if (value.getModelEntity().getNeverCache())
2806: return;
2807:
2808: cache.remove(value);
2809:
2810: if (distribute && this .distributedCacheClear != null) {
2811: this .distributedCacheClear.distributedClearCacheLine(value);
2812: }
2813: }
2814:
2815: public void clearAllCacheLinesByDummyPK(Collection dummyPKs) {
2816: if (dummyPKs == null)
2817: return;
2818: Iterator iter = dummyPKs.iterator();
2819:
2820: while (iter.hasNext()) {
2821: GenericEntity entity = (GenericEntity) iter.next();
2822:
2823: this .clearCacheLineFlexible(entity);
2824: }
2825: }
2826:
2827: public void clearAllCacheLinesByValue(Collection values) {
2828: if (values == null)
2829: return;
2830: Iterator iter = values.iterator();
2831:
2832: while (iter.hasNext()) {
2833: GenericValue value = (GenericValue) iter.next();
2834:
2835: this .clearCacheLine(value);
2836: }
2837: }
2838:
2839: public GenericValue getFromPrimaryKeyCache(GenericPK primaryKey) {
2840: if (primaryKey == null)
2841: return null;
2842: return (GenericValue) cache.get(primaryKey);
2843: }
2844:
2845: public void putInPrimaryKeyCache(GenericPK primaryKey,
2846: GenericValue value) {
2847: if (primaryKey == null)
2848: return;
2849:
2850: if (primaryKey.getModelEntity().getNeverCache()) {
2851: Debug
2852: .logWarning(
2853: "Tried to put a value of the "
2854: + value.getEntityName()
2855: + " entity in the BY PRIMARY KEY cache but this entity has never-cache set to true, not caching.",
2856: module);
2857: return;
2858: }
2859:
2860: // before going into the cache, make this value immutable
2861: value.setImmutable();
2862: cache.put(primaryKey, value);
2863: }
2864:
2865: public void putAllInPrimaryKeyCache(List values) {
2866: if (values == null)
2867: return;
2868: Iterator iter = values.iterator();
2869: while (iter.hasNext()) {
2870: GenericValue value = (GenericValue) iter.next();
2871: this .putInPrimaryKeyCache(value.getPrimaryKey(), value);
2872: }
2873: }
2874:
2875: public void setDistributedCacheClear(
2876: DistributedCacheClear distributedCacheClear) {
2877: this .distributedCacheClear = distributedCacheClear;
2878: }
2879:
2880: // ======= XML Related Methods ========
2881: public List readXmlDocument(URL url) throws SAXException,
2882: ParserConfigurationException, java.io.IOException {
2883: if (url == null)
2884: return null;
2885: return this .makeValues(UtilXml.readXmlDocument(url, false));
2886: }
2887:
2888: public List makeValues(Document document) {
2889: if (document == null)
2890: return null;
2891: List values = FastList.newInstance();
2892:
2893: Element docElement = document.getDocumentElement();
2894:
2895: if (docElement == null)
2896: return null;
2897: if (!"entity-engine-xml".equals(docElement.getTagName())) {
2898: Debug
2899: .logError(
2900: "[GenericDelegator.makeValues] Root node was not <entity-engine-xml>",
2901: module);
2902: throw new java.lang.IllegalArgumentException(
2903: "Root node was not <entity-engine-xml>");
2904: }
2905: docElement.normalize();
2906: Node curChild = docElement.getFirstChild();
2907:
2908: if (curChild != null) {
2909: do {
2910: if (curChild.getNodeType() == Node.ELEMENT_NODE) {
2911: Element element = (Element) curChild;
2912: GenericValue value = this .makeValue(element);
2913:
2914: if (value != null)
2915: values.add(value);
2916: }
2917: } while ((curChild = curChild.getNextSibling()) != null);
2918: } else {
2919: Debug
2920: .logWarning(
2921: "[GenericDelegator.makeValues] No child nodes found in document.",
2922: module);
2923: }
2924:
2925: return values;
2926: }
2927:
2928: public GenericPK makePK(Element element) {
2929: GenericValue value = makeValue(element);
2930:
2931: return value.getPrimaryKey();
2932: }
2933:
2934: public GenericValue makeValue(Element element) {
2935: if (element == null)
2936: return null;
2937: String entityName = element.getTagName();
2938:
2939: // if a dash or colon is in the tag name, grab what is after it
2940: if (entityName.indexOf('-') > 0)
2941: entityName = entityName
2942: .substring(entityName.indexOf('-') + 1);
2943: if (entityName.indexOf(':') > 0)
2944: entityName = entityName
2945: .substring(entityName.indexOf(':') + 1);
2946: GenericValue value = this .makeValue(entityName, null);
2947:
2948: ModelEntity modelEntity = value.getModelEntity();
2949:
2950: Iterator modelFields = modelEntity.getFieldsIterator();
2951:
2952: while (modelFields.hasNext()) {
2953: ModelField modelField = (ModelField) modelFields.next();
2954: String name = modelField.getName();
2955: String attr = element.getAttribute(name);
2956:
2957: if (attr != null && attr.length() > 0) {
2958: value.setString(name, attr);
2959: } else {
2960: // if no attribute try a subelement
2961: Element subElement = UtilXml.firstChildElement(element,
2962: name);
2963:
2964: if (subElement != null) {
2965: value.setString(name, UtilXml
2966: .elementValue(subElement));
2967: }
2968: }
2969: }
2970:
2971: return value;
2972: }
2973:
2974: // ======= Misc Methods ========
2975:
2976: protected Map getEcaEntityEventMap(String entityName) {
2977: if (this .entityEcaHandler == null)
2978: return null;
2979: Map ecaEventMap = this .entityEcaHandler
2980: .getEntityEventMap(entityName);
2981: //Debug.logWarning("for entityName " + entityName + " got ecaEventMap: " + ecaEventMap, module);
2982: return ecaEventMap;
2983: }
2984:
2985: protected void evalEcaRules(String event, String currentOperation,
2986: GenericEntity value, Map eventMap, boolean noEventMapFound,
2987: boolean isError) throws GenericEntityException {
2988: // if this is true then it means that the caller had looked for an event map but found none for this entity
2989: if (noEventMapFound)
2990: return;
2991: if (this .entityEcaHandler == null)
2992: return;
2993: //if (!"find".equals(currentOperation)) Debug.logWarning("evalRules for entity " + value.getEntityName() + ", currentOperation " + currentOperation + ", event " + event, module);
2994: this .entityEcaHandler.evalRules(currentOperation, eventMap,
2995: event, value, isError);
2996: }
2997:
2998: public void setEntityEcaHandler(EntityEcaHandler entityEcaHandler) {
2999: this .entityEcaHandler = entityEcaHandler;
3000: }
3001:
3002: public EntityEcaHandler getEntityEcaHandler() {
3003: return this .entityEcaHandler;
3004: }
3005:
3006: /** Get the next guaranteed unique seq id from the sequence with the given sequence name;
3007: * if the named sequence doesn't exist, it will be created
3008: *@param seqName The name of the sequence to get the next seq id from
3009: *@return String with the next sequenced id for the given sequence name
3010: */
3011: public String getNextSeqId(String seqName) {
3012: return this .getNextSeqId(seqName, 1);
3013: }
3014:
3015: /** Get the next guaranteed unique seq id from the sequence with the given sequence name;
3016: * if the named sequence doesn't exist, it will be created
3017: *@param seqName The name of the sequence to get the next seq id from
3018: *@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
3019: *@return Long with the next seq id for the given sequence name
3020: */
3021: public String getNextSeqId(String seqName, long staggerMax) {
3022: Long nextSeqLong = this .getNextSeqIdLong(seqName, staggerMax);
3023:
3024: if (nextSeqLong == null) {
3025: // NOTE: the getNextSeqIdLong method SHOULD throw a runtime exception when no sequence value is found, which means we should never see it get here
3026: throw new IllegalArgumentException(
3027: "Could not get next sequenced ID for sequence name: "
3028: + seqName);
3029: }
3030:
3031: if (UtilValidate
3032: .isNotEmpty(this .getDelegatorInfo().sequencedIdPrefix)) {
3033: return this .getDelegatorInfo().sequencedIdPrefix
3034: + nextSeqLong.toString();
3035: } else {
3036: return nextSeqLong.toString();
3037: }
3038: }
3039:
3040: /** Get the next guaranteed unique seq id from the sequence with the given sequence name;
3041: * if the named sequence doesn't exist, it will be created
3042: *@param seqName The name of the sequence to get the next seq id from
3043: *@return Long with the next sequenced id for the given sequence name
3044: */
3045: public Long getNextSeqIdLong(String seqName) {
3046: return this .getNextSeqIdLong(seqName, 1);
3047: }
3048:
3049: /** Get the next guaranteed unique seq id from the sequence with the given sequence name;
3050: * if the named sequence doesn't exist, it will be created
3051: *@param seqName The name of the sequence to get the next seq id from
3052: *@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
3053: *@return Long with the next seq id for the given sequence name
3054: */
3055: public Long getNextSeqIdLong(String seqName, long staggerMax) {
3056: boolean beganTransaction = false;
3057: try {
3058: if (alwaysUseTransaction) {
3059: beganTransaction = TransactionUtil.begin();
3060: }
3061:
3062: if (sequencer == null) {
3063: synchronized (this ) {
3064: if (sequencer == null) {
3065: String helperName = this
3066: .getEntityHelperName("SequenceValueItem");
3067: ModelEntity seqEntity = this
3068: .getModelEntity("SequenceValueItem");
3069: sequencer = new SequenceUtil(helperName,
3070: seqEntity, "seqName", "seqId");
3071: }
3072: }
3073: }
3074:
3075: Long newSeqId = sequencer == null ? null : sequencer
3076: .getNextSeqId(seqName, staggerMax);
3077:
3078: return newSeqId;
3079: } catch (GenericEntityException e) {
3080: String errMsg = "Failure in getNextSeqIdLong operation for seqName ["
3081: + seqName
3082: + "]: "
3083: + e.toString()
3084: + ". Rolling back transaction.";
3085: try {
3086: // only rollback the transaction if we started one...
3087: TransactionUtil.rollback(beganTransaction, errMsg, e);
3088: } catch (GenericEntityException e2) {
3089: Debug.logError(e2,
3090: "[GenericDelegator] Could not rollback transaction: "
3091: + e2.toString(), module);
3092: }
3093: // rather than logging the problem and returning null, thus hiding the problem, throw an exception
3094: throw new GeneralRuntimeException(errMsg, e);
3095: } finally {
3096: try {
3097: // only commit the transaction if we started one...
3098: TransactionUtil.commit(beganTransaction);
3099: } catch (GenericTransactionException e1) {
3100: Debug.logError(e1,
3101: "[GenericDelegator] Could not commit transaction: "
3102: + e1.toString(), module);
3103: }
3104: }
3105: }
3106:
3107: /** Allows you to pass a SequenceUtil class (possibly one that overrides the getNextSeqId method);
3108: * if null is passed will effectively refresh the sequencer. */
3109: public void setSequencer(SequenceUtil sequencer) {
3110: this .sequencer = sequencer;
3111: }
3112:
3113: /** Refreshes the ID sequencer clearing all cached bank values. */
3114: public void refreshSequencer() {
3115: this .sequencer = null;
3116: }
3117:
3118: /** Look at existing values for a sub-entity with a sequenced secondary ID, and get the highest plus 1 */
3119: public void setNextSubSeqId(GenericValue value,
3120: String seqFieldName, int numericPadding, int incrementBy) {
3121: if (value != null
3122: && UtilValidate.isEmpty(value.getString(seqFieldName))) {
3123: String sequencedIdPrefix = this .getDelegatorInfo().sequencedIdPrefix;
3124:
3125: value.remove(seqFieldName);
3126: GenericValue lookupValue = this .makeValue(value
3127: .getEntityName(), null);
3128: lookupValue.setPKFields(value);
3129:
3130: boolean beganTransaction = false;
3131: try {
3132: if (alwaysUseTransaction) {
3133: beganTransaction = TransactionUtil.begin();
3134: }
3135:
3136: // get values in whatever order, we will go through all of them to find the highest value
3137: List allValues = this .findByAnd(value.getEntityName(),
3138: lookupValue, null);
3139: //Debug.logInfo("Get existing values from entity " + value.getEntityName() + " with lookupValue: " + lookupValue + ", and the seqFieldName: " + seqFieldName + ", and the results are: " + allValues, module);
3140: Iterator allValueIter = allValues.iterator();
3141: Integer highestSeqVal = null;
3142: while (allValueIter.hasNext()) {
3143: GenericValue curValue = (GenericValue) allValueIter
3144: .next();
3145: String currentSeqId = curValue
3146: .getString(seqFieldName);
3147: if (currentSeqId != null) {
3148: if (UtilValidate.isNotEmpty(sequencedIdPrefix)) {
3149: if (currentSeqId
3150: .startsWith(sequencedIdPrefix)) {
3151: currentSeqId = currentSeqId
3152: .substring(sequencedIdPrefix
3153: .length());
3154: } else {
3155: continue;
3156: }
3157: }
3158: try {
3159: int seqVal = Integer.parseInt(currentSeqId);
3160: if (highestSeqVal == null
3161: || seqVal > highestSeqVal
3162: .intValue()) {
3163: highestSeqVal = new Integer(seqVal);
3164: }
3165: } catch (Exception e) {
3166: Debug.logWarning(
3167: "Error in make-next-seq-id converting SeqId ["
3168: + currentSeqId
3169: + "] to a number: "
3170: + e.toString(), module);
3171: }
3172: }
3173: }
3174:
3175: int seqValToUse = (highestSeqVal == null ? 1
3176: : highestSeqVal.intValue() + incrementBy);
3177: String newSeqId = sequencedIdPrefix
3178: + UtilFormatOut.formatPaddedNumber(seqValToUse,
3179: numericPadding);
3180: value.set(seqFieldName, newSeqId);
3181:
3182: // only commit the transaction if we started one...
3183: TransactionUtil.commit(beganTransaction);
3184: } catch (Exception e) {
3185: String errMsg = "Failure in setNextSubSeqId operation for entity ["
3186: + value.getEntityName()
3187: + "]: "
3188: + e.toString()
3189: + ". Rolling back transaction.";
3190: Debug.logError(e, errMsg, module);
3191: try {
3192: // only rollback the transaction if we started one...
3193: TransactionUtil.rollback(beganTransaction, errMsg,
3194: e);
3195: } catch (GenericEntityException e2) {
3196: Debug.logError(e2,
3197: "[GenericDelegator] Could not rollback transaction: "
3198: + e2.toString(), module);
3199: }
3200: Debug.logError(e, "Error making next seqId", module);
3201: }
3202: }
3203: }
3204:
3205: public void encryptFields(List entities)
3206: throws GenericEntityException {
3207: if (entities != null) {
3208: for (int i = 0; i < entities.size(); i++) {
3209: GenericEntity entity = (GenericEntity) entities.get(i);
3210: this .encryptFields(entity);
3211: }
3212: }
3213: }
3214:
3215: public void encryptFields(GenericEntity entity)
3216: throws GenericEntityException {
3217: ModelEntity model = entity.getModelEntity();
3218: String entityName = model.getEntityName();
3219:
3220: Iterator i = model.getFieldsIterator();
3221: while (i.hasNext()) {
3222: ModelField field = (ModelField) i.next();
3223: if (field.getEncrypt()) {
3224: Object obj = entity.get(field.getName());
3225: if (obj != null) {
3226: if (obj instanceof String
3227: && UtilValidate.isEmpty((String) obj)) {
3228: continue;
3229: }
3230: entity.dangerousSetNoCheckButFast(field, this
3231: .encryptFieldValue(entityName, obj));
3232: }
3233: }
3234: }
3235: }
3236:
3237: public Object encryptFieldValue(String entityName, Object fieldValue)
3238: throws EntityCryptoException {
3239: if (fieldValue != null) {
3240: if (fieldValue instanceof String
3241: && UtilValidate.isEmpty((String) fieldValue)) {
3242: return fieldValue;
3243: }
3244: return this .crypto.encrypt(entityName, fieldValue);
3245: }
3246: return fieldValue;
3247: }
3248:
3249: public void decryptFields(List entities)
3250: throws GenericEntityException {
3251: if (entities != null) {
3252: for (int i = 0; i < entities.size(); i++) {
3253: GenericEntity entity = (GenericEntity) entities.get(i);
3254: this .decryptFields(entity);
3255: }
3256: }
3257: }
3258:
3259: public void decryptFields(GenericEntity entity)
3260: throws GenericEntityException {
3261: ModelEntity model = entity.getModelEntity();
3262: String entityName = model.getEntityName();
3263:
3264: Iterator i = model.getFieldsIterator();
3265: while (i.hasNext()) {
3266: ModelField field = (ModelField) i.next();
3267: if (field.getEncrypt()) {
3268: String encHex = (String) entity.get(field.getName());
3269: if (UtilValidate.isNotEmpty(encHex)) {
3270: try {
3271: entity.dangerousSetNoCheckButFast(field, crypto
3272: .decrypt(entityName, encHex));
3273: } catch (EntityCryptoException e) {
3274: // not fatal -- allow returning of the encrypted value
3275: Debug
3276: .logWarning(
3277: e,
3278: "Problem decrypting field ["
3279: + entityName + " / "
3280: + field.getName() + "]",
3281: module);
3282: }
3283: }
3284: }
3285: }
3286: }
3287:
3288: public void setEntityCrypto(EntityCrypto crypto) {
3289: this .crypto = crypto;
3290: }
3291:
3292: protected void absorbList(List lst) {
3293: if (lst == null)
3294: return;
3295: Iterator iter = lst.iterator();
3296:
3297: while (iter.hasNext()) {
3298: GenericValue value = (GenericValue) iter.next();
3299:
3300: value.setDelegator(this );
3301: }
3302: }
3303:
3304: public Cache getCache() {
3305: return cache;
3306: }
3307:
3308: public GenericDelegator cloneDelegator(String delegatorName) {
3309: // creates an exact clone of the delegator; except for the sequencer
3310: // note that this will not be cached and should be used only when
3311: // needed to change something for single instance (use).
3312: GenericDelegator newDelegator = new GenericDelegator();
3313: newDelegator.modelReader = this .modelReader;
3314: newDelegator.modelGroupReader = this .modelGroupReader;
3315: newDelegator.delegatorName = delegatorName;
3316: newDelegator.delegatorInfo = this .delegatorInfo;
3317: newDelegator.cache = this .cache;
3318: newDelegator.andCacheFieldSets = this .andCacheFieldSets;
3319: newDelegator.distributedCacheClear = this .distributedCacheClear;
3320: newDelegator.entityEcaHandler = this .entityEcaHandler;
3321: newDelegator.crypto = this .crypto;
3322: // not setting the sequencer so that we have unique sequences.
3323:
3324: return newDelegator;
3325: }
3326:
3327: public GenericDelegator cloneDelegator() {
3328: return this.cloneDelegator(this.delegatorName);
3329: }
3330: }
|