0001: /*
0002: * $Id: GenericDelegator.java,v 1.15 2004/01/20 17:10:49 ajzeneski Exp $
0003: *
0004: * Copyright (c) 2001, 2002 The Open For Business Project - www.ofbiz.org
0005: *
0006: * Permission is hereby granted, free of charge, to any person obtaining a
0007: * copy of this software and associated documentation files (the "Software"),
0008: * to deal in the Software without restriction, including without limitation
0009: * the rights to use, copy, modify, merge, publish, distribute, sublicense,
0010: * and/or sell copies of the Software, and to permit persons to whom the
0011: * Software is furnished to do so, subject to the following conditions:
0012: *
0013: * The above copyright notice and this permission notice shall be included
0014: * in all copies or substantial portions of the Software.
0015: *
0016: * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
0017: * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
0018: * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
0019: * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
0020: * CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT
0021: * OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR
0022: * THE USE OR OTHER DEALINGS IN THE SOFTWARE.
0023: *
0024: */
0025: package org.ofbiz.entity;
0026:
0027: import java.io.FileNotFoundException;
0028: import java.io.IOException;
0029: import java.net.URL;
0030: import java.util.Collection;
0031: import java.util.Collections;
0032: import java.util.HashMap;
0033: import java.util.HashSet;
0034: import java.util.Iterator;
0035: import java.util.LinkedList;
0036: import java.util.List;
0037: import java.util.Map;
0038: import java.util.Set;
0039: import java.util.TreeSet;
0040:
0041: import javax.xml.parsers.ParserConfigurationException;
0042:
0043: import org.ofbiz.base.util.Debug;
0044: import org.ofbiz.base.util.UtilCache;
0045: import org.ofbiz.base.util.UtilMisc;
0046: import org.ofbiz.base.util.UtilXml;
0047: import org.ofbiz.entity.condition.*;
0048: import org.ofbiz.entity.config.EntityConfigUtil;
0049: import org.ofbiz.entity.datasource.GenericHelper;
0050: import org.ofbiz.entity.datasource.GenericHelperFactory;
0051: import org.ofbiz.entity.eca.EntityEcaHandler;
0052: import org.ofbiz.entity.model.DynamicViewEntity;
0053: import org.ofbiz.entity.model.ModelEntity;
0054: import org.ofbiz.entity.model.ModelField;
0055: import org.ofbiz.entity.model.ModelFieldType;
0056: import org.ofbiz.entity.model.ModelFieldTypeReader;
0057: import org.ofbiz.entity.model.ModelGroupReader;
0058: import org.ofbiz.entity.model.ModelKeyMap;
0059: import org.ofbiz.entity.model.ModelReader;
0060: import org.ofbiz.entity.model.ModelRelation;
0061: import org.ofbiz.entity.model.ModelViewEntity;
0062: import org.ofbiz.entity.serialize.SerializeException;
0063: import org.ofbiz.entity.serialize.XmlSerializer;
0064: import org.ofbiz.entity.transaction.TransactionUtil;
0065: import org.ofbiz.entity.util.DistributedCacheClear;
0066: import org.ofbiz.entity.util.EntityFindOptions;
0067: import org.ofbiz.entity.util.EntityListIterator;
0068: import org.ofbiz.entity.util.EntityUtil;
0069: import org.ofbiz.entity.util.SequenceUtil;
0070: import org.w3c.dom.Document;
0071: import org.w3c.dom.Element;
0072: import org.w3c.dom.Node;
0073: import org.xml.sax.SAXException;
0074:
0075: /**
0076: * Generic Data Source Delegator Class
0077: *
0078: * @author <a href="mailto:jonesde@ofbiz.org">David E. Jones</a>
0079: * @author <a href="mailto:chris_maurer@altavista.com">Chris Maurer</a>
0080: * @author <a href="mailto:jaz@ofbiz.org">Andy Zeneski</a
0081: * @version $Revision: 1.15 $
0082: * @since 1.0
0083: */
0084: public class GenericDelegator implements DelegatorInterface {
0085:
0086: public static final String module = GenericDelegator.class
0087: .getName();
0088:
0089: /** the delegatorCache will now be a HashMap, allowing reload of definitions,
0090: * but the delegator will always be the same object for the given name */
0091: protected static Map delegatorCache = new HashMap();
0092: protected String delegatorName;
0093: protected EntityConfigUtil.DelegatorInfo delegatorInfo = null;
0094:
0095: /** set this to true for better performance; set to false to be able to reload definitions at runtime throught the cache manager */
0096: public static final boolean keepLocalReaders = true;
0097: protected ModelReader modelReader = null;
0098: protected ModelGroupReader modelGroupReader = null;
0099:
0100: protected UtilCache primaryKeyCache = null;
0101: protected UtilCache allCache = null;
0102: protected UtilCache andCache = null;
0103:
0104: // keeps a list of field key sets used in the by and cache, a Set (of Sets of fieldNames) for each entityName
0105: protected Map andCacheFieldSets = new HashMap();
0106:
0107: protected DistributedCacheClear distributedCacheClear = null;
0108:
0109: protected EntityEcaHandler entityEcaHandler = null;
0110: public static final String ECA_HANDLER_CLASS_NAME = "org.ofbiz.entityext.eca.DelegatorEcaHandler";
0111:
0112: protected SequenceUtil sequencer = null;
0113:
0114: public static GenericDelegator getGenericDelegator(
0115: String delegatorName) {
0116: GenericDelegator delegator = (GenericDelegator) delegatorCache
0117: .get(delegatorName);
0118:
0119: if (delegator == null) {
0120: synchronized (GenericDelegator.class) {
0121: // must check if null again as one of the blocked threads can still enter
0122: delegator = (GenericDelegator) delegatorCache
0123: .get(delegatorName);
0124: if (delegator == null) {
0125: try {
0126: delegator = new GenericDelegator(delegatorName);
0127: } catch (GenericEntityException e) {
0128: Debug.logError(e, "Error creating delegator",
0129: module);
0130: }
0131: if (delegator != null) {
0132: delegatorCache.put(delegatorName, delegator);
0133: }
0134: }
0135: }
0136: }
0137: return delegator;
0138: }
0139:
0140: /** Only allow creation through the factory method */
0141: protected GenericDelegator() {
0142: }
0143:
0144: /** Only allow creation through the factory method */
0145: protected GenericDelegator(String delegatorName)
0146: throws GenericEntityException {
0147: if (Debug.infoOn())
0148: Debug.logInfo("Creating new Delegator with name \""
0149: + delegatorName + "\".", module);
0150:
0151: this .delegatorName = delegatorName;
0152: if (keepLocalReaders) {
0153: modelReader = ModelReader.getModelReader(delegatorName);
0154: modelGroupReader = ModelGroupReader
0155: .getModelGroupReader(delegatorName);
0156: }
0157:
0158: primaryKeyCache = new UtilCache("entity.FindByPrimaryKey."
0159: + delegatorName, 0, 0, true);
0160: allCache = new UtilCache("entity.FindAll." + delegatorName, 0,
0161: 0, true);
0162: andCache = new UtilCache("entity.FindByAnd." + delegatorName,
0163: 0, 0, true);
0164:
0165: // initialize helpers by group
0166: Iterator groups = UtilMisc.toIterator(getModelGroupReader()
0167: .getGroupNames());
0168:
0169: while (groups != null && groups.hasNext()) {
0170: String groupName = (String) groups.next();
0171: String helperName = this .getGroupHelperName(groupName);
0172:
0173: if (Debug.infoOn())
0174: Debug.logInfo("Delegator \"" + delegatorName
0175: + "\" initializing helper \"" + helperName
0176: + "\" for entity group \"" + groupName + "\".",
0177: module);
0178: TreeSet helpersDone = new TreeSet();
0179:
0180: if (helperName != null && helperName.length() > 0) {
0181: // make sure each helper is only loaded once
0182: if (helpersDone.contains(helperName)) {
0183: if (Debug.infoOn())
0184: Debug
0185: .logInfo(
0186: "Helper \""
0187: + helperName
0188: + "\" already initialized, not re-initializing.",
0189: module);
0190: continue;
0191: }
0192: helpersDone.add(helperName);
0193: // pre-load field type defs, the return value is ignored
0194: ModelFieldTypeReader
0195: .getModelFieldTypeReader(helperName);
0196: // get the helper and if configured, do the datasource check
0197: GenericHelper helper = GenericHelperFactory
0198: .getHelper(helperName);
0199:
0200: EntityConfigUtil.DatasourceInfo datasourceInfo = EntityConfigUtil
0201: .getDatasourceInfo(helperName);
0202:
0203: if (datasourceInfo.checkOnStart) {
0204: if (Debug.infoOn())
0205: Debug
0206: .logInfo(
0207: "Doing database check as requested in entityengine.xml with addMissing="
0208: + datasourceInfo.addMissingOnStart,
0209: module);
0210: try {
0211: helper.checkDataSource(this
0212: .getModelEntityMapByGroup(groupName),
0213: null, datasourceInfo.addMissingOnStart);
0214: } catch (GenericEntityException e) {
0215: Debug.logWarning(e.getMessage(), module);
0216: }
0217: }
0218: }
0219: }
0220:
0221: //time to do some tricks with manual class loading that resolves circular dependencies, like calling services...
0222: ClassLoader loader = Thread.currentThread()
0223: .getContextClassLoader();
0224:
0225: // if useDistributedCacheClear is false do nothing since the
0226: // distributedCacheClear member field with a null value will cause the
0227: // dcc code to do nothing
0228: if (getDelegatorInfo().useDistributedCacheClear) {
0229: // initialize the distributedCacheClear mechanism
0230: String distributedCacheClearClassName = getDelegatorInfo().distributedCacheClearClassName;
0231:
0232: try {
0233: Class dccClass = loader
0234: .loadClass(distributedCacheClearClassName);
0235: this .distributedCacheClear = (DistributedCacheClear) dccClass
0236: .newInstance();
0237: this .distributedCacheClear
0238: .setDelegator(
0239: this ,
0240: getDelegatorInfo().distributedCacheClearUserLoginId);
0241: } catch (ClassNotFoundException e) {
0242: Debug
0243: .logWarning(
0244: e,
0245: "DistributedCacheClear class with name "
0246: + distributedCacheClearClassName
0247: + " was not found, distributed cache clearing will be disabled",
0248: module);
0249: } catch (InstantiationException e) {
0250: Debug
0251: .logWarning(
0252: e,
0253: "DistributedCacheClear class with name "
0254: + distributedCacheClearClassName
0255: + " could not be instantiated, distributed cache clearing will be disabled",
0256: module);
0257: } catch (IllegalAccessException e) {
0258: Debug
0259: .logWarning(
0260: e,
0261: "DistributedCacheClear class with name "
0262: + distributedCacheClearClassName
0263: + " could not be accessed (illegal), distributed cache clearing will be disabled",
0264: module);
0265: } catch (ClassCastException e) {
0266: Debug
0267: .logWarning(
0268: e,
0269: "DistributedCacheClear class with name "
0270: + distributedCacheClearClassName
0271: + " does not implement the DistributedCacheClear interface, distributed cache clearing will be disabled",
0272: module);
0273: }
0274: }
0275:
0276: // setup the Entity ECA Handler
0277: try {
0278: Class eecahClass = loader.loadClass(ECA_HANDLER_CLASS_NAME);
0279: this .entityEcaHandler = (EntityEcaHandler) eecahClass
0280: .newInstance();
0281: this .entityEcaHandler.setDelegator(this );
0282: } catch (ClassNotFoundException e) {
0283: Debug
0284: .logWarning(
0285: e,
0286: "EntityEcaHandler class with name "
0287: + ECA_HANDLER_CLASS_NAME
0288: + " was not found, Entity ECA Rules will be disabled",
0289: module);
0290: } catch (InstantiationException e) {
0291: Debug
0292: .logWarning(
0293: e,
0294: "EntityEcaHandler class with name "
0295: + ECA_HANDLER_CLASS_NAME
0296: + " could not be instantiated, Entity ECA Rules will be disabled",
0297: module);
0298: } catch (IllegalAccessException e) {
0299: Debug
0300: .logWarning(
0301: e,
0302: "EntityEcaHandler class with name "
0303: + ECA_HANDLER_CLASS_NAME
0304: + " could not be accessed (illegal), Entity ECA Rules will be disabled",
0305: module);
0306: } catch (ClassCastException e) {
0307: Debug
0308: .logWarning(
0309: e,
0310: "EntityEcaHandler class with name "
0311: + ECA_HANDLER_CLASS_NAME
0312: + " does not implement the EntityEcaHandler interface, Entity ECA Rules will be disabled",
0313: module);
0314: }
0315: }
0316:
0317: /** Gets the name of the server configuration that corresponds to this delegator
0318: * @return server configuration name
0319: */
0320: public String getDelegatorName() {
0321: return this .delegatorName;
0322: }
0323:
0324: protected EntityConfigUtil.DelegatorInfo getDelegatorInfo() {
0325: if (delegatorInfo == null) {
0326: delegatorInfo = EntityConfigUtil
0327: .getDelegatorInfo(this .delegatorName);
0328: }
0329: return delegatorInfo;
0330: }
0331:
0332: /** Gets the instance of ModelReader that corresponds to this delegator
0333: *@return ModelReader that corresponds to this delegator
0334: */
0335: public ModelReader getModelReader() {
0336: if (keepLocalReaders) {
0337: return this .modelReader;
0338: } else {
0339: try {
0340: return ModelReader.getModelReader(delegatorName);
0341: } catch (GenericEntityException e) {
0342: Debug.logError(e, "Error loading entity model", module);
0343: return null;
0344: }
0345: }
0346: }
0347:
0348: /** Gets the instance of ModelGroupReader that corresponds to this delegator
0349: *@return ModelGroupReader that corresponds to this delegator
0350: */
0351: public ModelGroupReader getModelGroupReader() {
0352: if (keepLocalReaders) {
0353: return this .modelGroupReader;
0354: } else {
0355: try {
0356: return ModelGroupReader
0357: .getModelGroupReader(delegatorName);
0358: } catch (GenericEntityException e) {
0359: Debug.logError(e, "Error loading entity group model",
0360: module);
0361: return null;
0362: }
0363: }
0364: }
0365:
0366: /** Gets the instance of ModelEntity that corresponds to this delegator and the specified entityName
0367: *@param entityName The name of the entity to get
0368: *@return ModelEntity that corresponds to this delegator and the specified entityName
0369: */
0370: public ModelEntity getModelEntity(String entityName) {
0371: try {
0372: return getModelReader().getModelEntity(entityName);
0373: } catch (GenericEntityException e) {
0374: Debug.logError(e,
0375: "Error getting entity definition from model",
0376: module);
0377: return null;
0378: }
0379: }
0380:
0381: /** Gets the helper name that corresponds to this delegator and the specified entityName
0382: *@param entityName The name of the entity to get the helper for
0383: *@return String with the helper name that corresponds to this delegator and the specified entityName
0384: */
0385: public String getEntityGroupName(String entityName) {
0386: String groupName = getModelGroupReader().getEntityGroupName(
0387: entityName);
0388:
0389: return groupName;
0390: }
0391:
0392: /** Gets a list of entity models that are in a group corresponding to the specified group name
0393: *@param groupName The name of the group
0394: *@return List of ModelEntity instances
0395: */
0396: public List getModelEntitiesByGroup(String groupName) {
0397: Iterator enames = UtilMisc.toIterator(getModelGroupReader()
0398: .getEntityNamesByGroup(groupName));
0399: List entities = new LinkedList();
0400:
0401: if (enames == null || !enames.hasNext())
0402: return entities;
0403: while (enames.hasNext()) {
0404: String ename = (String) enames.next();
0405: ModelEntity entity = this .getModelEntity(ename);
0406:
0407: if (entity != null)
0408: entities.add(entity);
0409: }
0410: return entities;
0411: }
0412:
0413: /** Gets a Map of entity name & entity model pairs that are in the named group
0414: *@param groupName The name of the group
0415: *@return Map of entityName String keys and ModelEntity instance values
0416: */
0417: public Map getModelEntityMapByGroup(String groupName) {
0418: Iterator enames = UtilMisc.toIterator(getModelGroupReader()
0419: .getEntityNamesByGroup(groupName));
0420: Map entities = new HashMap();
0421:
0422: if (enames == null || !enames.hasNext()) {
0423: return entities;
0424: }
0425:
0426: int errorCount = 0;
0427: while (enames.hasNext()) {
0428: String ename = (String) enames.next();
0429: try {
0430: ModelEntity entity = getModelReader().getModelEntity(
0431: ename);
0432: if (entity != null) {
0433: entities.put(entity.getEntityName(), entity);
0434: } else {
0435: throw new IllegalStateException(
0436: "Could not find entity with name " + ename);
0437: }
0438: } catch (GenericEntityException ex) {
0439: errorCount++;
0440: Debug
0441: .logError(
0442: "Entity "
0443: + ename
0444: + " named in Entity Group with name "
0445: + groupName
0446: + " are not defined in any Entity Definition file",
0447: module);
0448: }
0449: }
0450:
0451: if (errorCount > 0) {
0452: Debug
0453: .logError(
0454: errorCount
0455: + " entities were named in ModelGroup but not defined in any EntityModel",
0456: module);
0457: }
0458:
0459: return entities;
0460: }
0461:
0462: /** Gets the helper name that corresponds to this delegator and the specified entityName
0463: *@param groupName The name of the group to get the helper name for
0464: *@return String with the helper name that corresponds to this delegator and the specified entityName
0465: */
0466: public String getGroupHelperName(String groupName) {
0467: return (String) this .getDelegatorInfo().groupMap.get(groupName);
0468: }
0469:
0470: /** Gets the helper name that corresponds to this delegator and the specified entityName
0471: *@param entityName The name of the entity to get the helper name for
0472: *@return String with the helper name that corresponds to this delegator and the specified entityName
0473: */
0474: public String getEntityHelperName(String entityName) {
0475: String groupName = getModelGroupReader().getEntityGroupName(
0476: entityName);
0477:
0478: return this .getGroupHelperName(groupName);
0479: }
0480:
0481: /** Gets the helper name that corresponds to this delegator and the specified entity
0482: *@param entity The entity to get the helper for
0483: *@return String with the helper name that corresponds to this delegator and the specified entity
0484: */
0485: public String getEntityHelperName(ModelEntity entity) {
0486: if (entity == null)
0487: return null;
0488: return getEntityHelperName(entity.getEntityName());
0489: }
0490:
0491: /** Gets the an instance of helper that corresponds to this delegator and the specified entityName
0492: *@param entityName The name of the entity to get the helper for
0493: *@return GenericHelper that corresponds to this delegator and the specified entityName
0494: */
0495: public GenericHelper getEntityHelper(String entityName)
0496: throws GenericEntityException {
0497: String helperName = getEntityHelperName(entityName);
0498:
0499: if (helperName != null && helperName.length() > 0)
0500: return GenericHelperFactory.getHelper(helperName);
0501: else
0502: throw new GenericEntityException(
0503: "Helper name not found for entity " + entityName);
0504: }
0505:
0506: /** Gets the an instance of helper that corresponds to this delegator and the specified entity
0507: *@param entity The entity to get the helper for
0508: *@return GenericHelper that corresponds to this delegator and the specified entity
0509: */
0510: public GenericHelper getEntityHelper(ModelEntity entity)
0511: throws GenericEntityException {
0512: return getEntityHelper(entity.getEntityName());
0513: }
0514:
0515: /** Gets a field type instance by name from the helper that corresponds to the specified entity
0516: *@param entity The entity
0517: *@param type The name of the type
0518: *@return ModelFieldType instance for the named type from the helper that corresponds to the specified entity
0519: */
0520: public ModelFieldType getEntityFieldType(ModelEntity entity,
0521: String type) throws GenericEntityException {
0522: String helperName = getEntityHelperName(entity);
0523:
0524: if (helperName == null || helperName.length() <= 0)
0525: return null;
0526: ModelFieldTypeReader modelFieldTypeReader = ModelFieldTypeReader
0527: .getModelFieldTypeReader(helperName);
0528:
0529: if (modelFieldTypeReader == null) {
0530: throw new GenericEntityException(
0531: "ModelFieldTypeReader not found for entity "
0532: + entity.getEntityName()
0533: + " with helper name " + helperName);
0534: }
0535: return modelFieldTypeReader.getModelFieldType(type);
0536: }
0537:
0538: /** Gets field type names from the helper that corresponds to the specified entity
0539: *@param entity The entity
0540: *@return Collection of field type names from the helper that corresponds to the specified entity
0541: */
0542: public Collection getEntityFieldTypeNames(ModelEntity entity)
0543: throws GenericEntityException {
0544: String helperName = getEntityHelperName(entity);
0545:
0546: if (helperName == null || helperName.length() <= 0)
0547: return null;
0548: ModelFieldTypeReader modelFieldTypeReader = ModelFieldTypeReader
0549: .getModelFieldTypeReader(helperName);
0550:
0551: if (modelFieldTypeReader == null) {
0552: throw new GenericEntityException(
0553: "ModelFieldTypeReader not found for entity "
0554: + entity.getEntityName()
0555: + " with helper name " + helperName);
0556: }
0557: return modelFieldTypeReader.getFieldTypeNames();
0558: }
0559:
0560: /** Creates a Entity in the form of a GenericValue without persisting it */
0561: public GenericValue makeValue(String entityName, Map fields) {
0562: ModelEntity entity = this .getModelEntity(entityName);
0563: if (entity == null) {
0564: throw new IllegalArgumentException(
0565: "[GenericDelegator.makeValue] could not find entity for entityName: "
0566: + entityName);
0567: }
0568: GenericValue value = new GenericValue(entity, fields);
0569: value.setDelegator(this );
0570: return value;
0571: }
0572:
0573: /** Creates a Entity in the form of a GenericValue without persisting it; only valid fields will be pulled from the fields Map */
0574: public GenericValue makeValidValue(String entityName, Map fields) {
0575: ModelEntity entity = this .getModelEntity(entityName);
0576: if (entity == null) {
0577: throw new IllegalArgumentException(
0578: "[GenericDelegator.makeValidValue] could not find entity for entityName: "
0579: + entityName);
0580: }
0581: GenericValue value = new GenericValue(entity, null);
0582: value.setPKFields(fields, true);
0583: value.setNonPKFields(fields, true);
0584: value.setDelegator(this );
0585: return value;
0586: }
0587:
0588: /** Creates a Primary Key in the form of a GenericPK without persisting it */
0589: public GenericPK makePK(String entityName, Map fields) {
0590: ModelEntity entity = this .getModelEntity(entityName);
0591:
0592: if (entity == null) {
0593: throw new IllegalArgumentException(
0594: "[GenericDelegator.makePK] could not find entity for entityName: "
0595: + entityName);
0596: }
0597: GenericPK pk = new GenericPK(entity, fields);
0598:
0599: pk.setDelegator(this );
0600: return pk;
0601: }
0602:
0603: /** Creates a Entity in the form of a GenericValue and write it to the database
0604: *@return GenericValue instance containing the new instance
0605: */
0606: public GenericValue create(String entityName, Map fields)
0607: throws GenericEntityException {
0608: if (entityName == null || fields == null) {
0609: return null;
0610: }
0611: ModelEntity entity = this .getModelReader().getModelEntity(
0612: entityName);
0613: GenericValue genericValue = new GenericValue(entity, fields);
0614:
0615: return this .create(genericValue, true);
0616: }
0617:
0618: /** Creates a Entity in the form of a GenericValue and write it to the datasource
0619: *@param value The GenericValue to create a value in the datasource from
0620: *@return GenericValue instance containing the new instance
0621: */
0622: public GenericValue create(GenericValue value)
0623: throws GenericEntityException {
0624: return this .create(value, true);
0625: }
0626:
0627: /** Creates a Entity in the form of a GenericValue and write it to the datasource
0628: *@param value The GenericValue to create a value in the datasource from
0629: *@param doCacheClear boolean that specifies whether or not to automatically clear cache entries related to this operation
0630: *@return GenericValue instance containing the new instance
0631: */
0632: public GenericValue create(GenericValue value, boolean doCacheClear)
0633: throws GenericEntityException {
0634: Map ecaEventMap = this .getEcaEntityEventMap(value
0635: .getEntityName());
0636: this .evalEcaRules(EntityEcaHandler.EV_VALIDATE,
0637: EntityEcaHandler.OP_CREATE, value, ecaEventMap,
0638: (ecaEventMap == null), false);
0639:
0640: if (value == null) {
0641: throw new GenericEntityException(
0642: "Cannot create a null value");
0643: }
0644: GenericHelper helper = getEntityHelper(value.getEntityName());
0645:
0646: this .evalEcaRules(EntityEcaHandler.EV_RUN,
0647: EntityEcaHandler.OP_CREATE, value, ecaEventMap,
0648: (ecaEventMap == null), false);
0649:
0650: value.setDelegator(this );
0651: value = helper.create(value);
0652:
0653: if (value != null) {
0654: value.setDelegator(this );
0655: if (value.lockEnabled()) {
0656: refresh(value, doCacheClear);
0657: } else {
0658: if (doCacheClear) {
0659: this .evalEcaRules(EntityEcaHandler.EV_CACHE_CLEAR,
0660: EntityEcaHandler.OP_CREATE, value,
0661: ecaEventMap, (ecaEventMap == null), false);
0662: this .clearCacheLine(value);
0663: }
0664: }
0665: }
0666: this .evalEcaRules(EntityEcaHandler.EV_RETURN,
0667: EntityEcaHandler.OP_CREATE, value, ecaEventMap,
0668: (ecaEventMap == null), false);
0669: return value;
0670: }
0671:
0672: /** Creates a Entity in the form of a GenericValue and write it to the datasource
0673: *@param primaryKey The GenericPK to create a value in the datasource from
0674: *@return GenericValue instance containing the new instance
0675: */
0676: public GenericValue create(GenericPK primaryKey)
0677: throws GenericEntityException {
0678: return this .create(primaryKey, true);
0679: }
0680:
0681: /** Creates a Entity in the form of a GenericValue and write it to the datasource
0682: *@param primaryKey The GenericPK to create a value in the datasource from
0683: *@param doCacheClear boolean that specifies whether to clear related cache entries for this primaryKey to be created
0684: *@return GenericValue instance containing the new instance
0685: */
0686: public GenericValue create(GenericPK primaryKey,
0687: boolean doCacheClear) throws GenericEntityException {
0688: if (primaryKey == null) {
0689: throw new GenericEntityException(
0690: "Cannot create from a null primaryKey");
0691: }
0692:
0693: return this .create(new GenericValue(primaryKey), doCacheClear);
0694: }
0695:
0696: /** Creates or stores an Entity
0697: *@param value The GenericValue instance containing the new or existing instance
0698: *@param doCacheClear boolean that specifies whether or not to automatically clear cache entries related to this operation
0699: *@return GenericValue instance containing the new or updated instance
0700: */
0701: public GenericValue createOrStore(GenericValue value,
0702: boolean doCacheClear) throws GenericEntityException {
0703: GenericValue checkValue = this .findByPrimaryKey(value
0704: .getPrimaryKey());
0705: if (checkValue != null) {
0706: this .store(value, doCacheClear);
0707: } else {
0708: this .create(value, doCacheClear);
0709: }
0710: if (value.lockEnabled()) {
0711: this .refresh(value);
0712: }
0713: return value;
0714: }
0715:
0716: /** Creates or stores an Entity
0717: *@param value The GenericValue instance containing the new or existing instance
0718: *@return GenericValue instance containing the new or updated instance
0719: */
0720: public GenericValue createOrStore(GenericValue value)
0721: throws GenericEntityException {
0722: return createOrStore(value, true);
0723: }
0724:
0725: /** Find a Generic Entity by its Primary Key
0726: *@param primaryKey The primary key to find by.
0727: *@return The GenericValue corresponding to the primaryKey
0728: */
0729: public GenericValue findByPrimaryKey(GenericPK primaryKey)
0730: throws GenericEntityException {
0731: Map ecaEventMap = this .getEcaEntityEventMap(primaryKey
0732: .getEntityName());
0733: this .evalEcaRules(EntityEcaHandler.EV_VALIDATE,
0734: EntityEcaHandler.OP_FIND, primaryKey, ecaEventMap,
0735: (ecaEventMap == null), false);
0736:
0737: GenericHelper helper = getEntityHelper(primaryKey
0738: .getEntityName());
0739: GenericValue value = null;
0740:
0741: if (!primaryKey.isPrimaryKey()) {
0742: throw new GenericModelException(
0743: "[GenericDelegator.findByPrimaryKey] Passed primary key is not a valid primary key: "
0744: + primaryKey);
0745: }
0746: this .evalEcaRules(EntityEcaHandler.EV_RUN,
0747: EntityEcaHandler.OP_FIND, primaryKey, ecaEventMap,
0748: (ecaEventMap == null), false);
0749: try {
0750: value = helper.findByPrimaryKey(primaryKey);
0751: } catch (GenericEntityNotFoundException e) {
0752: value = null;
0753: }
0754: if (value != null)
0755: value.setDelegator(this );
0756:
0757: this .evalEcaRules(EntityEcaHandler.EV_RETURN,
0758: EntityEcaHandler.OP_FIND, primaryKey, ecaEventMap,
0759: (ecaEventMap == null), false);
0760: return value;
0761: }
0762:
0763: /** Find a CACHED Generic Entity by its Primary Key
0764: *@param primaryKey The primary key to find by.
0765: *@return The GenericValue corresponding to the primaryKey
0766: */
0767: public GenericValue findByPrimaryKeyCache(GenericPK primaryKey)
0768: throws GenericEntityException {
0769: Map ecaEventMap = this .getEcaEntityEventMap(primaryKey
0770: .getEntityName());
0771: this .evalEcaRules(EntityEcaHandler.EV_CACHE_CHECK,
0772: EntityEcaHandler.OP_FIND, primaryKey, ecaEventMap,
0773: (ecaEventMap == null), false);
0774:
0775: GenericValue value = this .getFromPrimaryKeyCache(primaryKey);
0776: if (value == null) {
0777: value = findByPrimaryKey(primaryKey);
0778: if (value != null) {
0779: this .evalEcaRules(EntityEcaHandler.EV_CACHE_PUT,
0780: EntityEcaHandler.OP_FIND, primaryKey,
0781: ecaEventMap, (ecaEventMap == null), false);
0782: this .putInPrimaryKeyCache(primaryKey, value);
0783: }
0784: }
0785: return value;
0786: }
0787:
0788: /** Find a Generic Entity by its Primary Key
0789: *@param entityName The Name of the Entity as defined in the entity XML file
0790: *@param fields The fields of the named entity to query by with their corresponging values
0791: *@return The GenericValue corresponding to the primaryKey
0792: */
0793: public GenericValue findByPrimaryKey(String entityName, Map fields)
0794: throws GenericEntityException {
0795: return findByPrimaryKey(makePK(entityName, fields));
0796: }
0797:
0798: /** Find a CACHED Generic Entity by its Primary Key
0799: *@param entityName The Name of the Entity as defined in the entity XML file
0800: *@param fields The fields of the named entity to query by with their corresponging values
0801: *@return The GenericValue corresponding to the primaryKey
0802: */
0803: public GenericValue findByPrimaryKeyCache(String entityName,
0804: Map fields) throws GenericEntityException {
0805: return findByPrimaryKeyCache(makePK(entityName, fields));
0806: }
0807:
0808: /** Find a Generic Entity by its Primary Key and only returns the values requested by the passed keys (names)
0809: *@param primaryKey The primary key to find by.
0810: *@param keys The keys, or names, of the values to retrieve; only these values will be retrieved
0811: *@return The GenericValue corresponding to the primaryKey
0812: */
0813: public GenericValue findByPrimaryKeyPartial(GenericPK primaryKey,
0814: Set keys) throws GenericEntityException {
0815: Map ecaEventMap = this .getEcaEntityEventMap(primaryKey
0816: .getEntityName());
0817: this .evalEcaRules(EntityEcaHandler.EV_VALIDATE,
0818: EntityEcaHandler.OP_FIND, primaryKey, ecaEventMap,
0819: (ecaEventMap == null), false);
0820:
0821: GenericHelper helper = getEntityHelper(primaryKey
0822: .getEntityName());
0823: GenericValue value = null;
0824:
0825: if (!primaryKey.isPrimaryKey()) {
0826: throw new GenericModelException(
0827: "[GenericDelegator.findByPrimaryKey] Passed primary key is not a valid primary key: "
0828: + primaryKey);
0829: }
0830:
0831: this .evalEcaRules(EntityEcaHandler.EV_RUN,
0832: EntityEcaHandler.OP_FIND, primaryKey, ecaEventMap,
0833: (ecaEventMap == null), false);
0834: try {
0835: value = helper.findByPrimaryKeyPartial(primaryKey, keys);
0836: } catch (GenericEntityNotFoundException e) {
0837: value = null;
0838: }
0839: if (value != null)
0840: value.setDelegator(this );
0841:
0842: this .evalEcaRules(EntityEcaHandler.EV_RETURN,
0843: EntityEcaHandler.OP_FIND, primaryKey, ecaEventMap,
0844: (ecaEventMap == null), false);
0845: return value;
0846: }
0847:
0848: /** Find a number of Generic Value objects by their Primary Keys, all at once
0849: *@param primaryKeys A Collection of primary keys to find by.
0850: *@return List of GenericValue objects corresponding to the passed primaryKey objects
0851: */
0852: public List findAllByPrimaryKeys(Collection primaryKeys)
0853: throws GenericEntityException {
0854: //TODO: add eca eval calls
0855: if (primaryKeys == null)
0856: return null;
0857: List results = new LinkedList();
0858:
0859: // from the delegator level this is complicated because different GenericPK
0860: // objects in the list may correspond to different helpers
0861: HashMap pksPerHelper = new HashMap();
0862: Iterator pkiter = primaryKeys.iterator();
0863:
0864: while (pkiter.hasNext()) {
0865: GenericPK curPK = (GenericPK) pkiter.next();
0866: String helperName = this .getEntityHelperName(curPK
0867: .getEntityName());
0868: List pks = (List) pksPerHelper.get(helperName);
0869:
0870: if (pks == null) {
0871: pks = new LinkedList();
0872: pksPerHelper.put(helperName, pks);
0873: }
0874: pks.add(curPK);
0875: }
0876:
0877: Iterator helperIter = pksPerHelper.entrySet().iterator();
0878:
0879: while (helperIter.hasNext()) {
0880: Map.Entry curEntry = (Map.Entry) helperIter.next();
0881: String helperName = (String) curEntry.getKey();
0882: GenericHelper helper = GenericHelperFactory
0883: .getHelper(helperName);
0884: List values = helper.findAllByPrimaryKeys((List) curEntry
0885: .getValue());
0886:
0887: results.addAll(values);
0888: }
0889: return results;
0890: }
0891:
0892: /** Find a number of Generic Value objects by their Primary Keys, all at once;
0893: * this first looks in the local cache for each PK and if there then it puts it
0894: * in the return list rather than putting it in the batch to send to
0895: * a given helper.
0896: *@param primaryKeys A Collection of primary keys to find by.
0897: *@return List of GenericValue objects corresponding to the passed primaryKey objects
0898: */
0899: public List findAllByPrimaryKeysCache(Collection primaryKeys)
0900: throws GenericEntityException {
0901: //TODO: add eca eval calls
0902: if (primaryKeys == null)
0903: return null;
0904: List results = new LinkedList();
0905:
0906: // from the delegator level this is complicated because different GenericPK
0907: // objects in the list may correspond to different helpers
0908: HashMap pksPerHelper = new HashMap();
0909: Iterator pkiter = primaryKeys.iterator();
0910:
0911: while (pkiter.hasNext()) {
0912: GenericPK curPK = (GenericPK) pkiter.next();
0913:
0914: GenericValue value = this .getFromPrimaryKeyCache(curPK);
0915:
0916: if (value != null) {
0917: // it is in the cache, so just put the cached value in the results
0918: results.add(value);
0919: } else {
0920: // is not in the cache, so put in a list for a call to the helper
0921: String helperName = this .getEntityHelperName(curPK
0922: .getEntityName());
0923: List pks = (List) pksPerHelper.get(helperName);
0924:
0925: if (pks == null) {
0926: pks = new LinkedList();
0927: pksPerHelper.put(helperName, pks);
0928: }
0929: pks.add(curPK);
0930: }
0931: }
0932:
0933: Iterator helperIter = pksPerHelper.entrySet().iterator();
0934:
0935: while (helperIter.hasNext()) {
0936: Map.Entry curEntry = (Map.Entry) helperIter.next();
0937: String helperName = (String) curEntry.getKey();
0938: GenericHelper helper = GenericHelperFactory
0939: .getHelper(helperName);
0940: List values = helper.findAllByPrimaryKeys((List) curEntry
0941: .getValue());
0942:
0943: this .putAllInPrimaryKeyCache(values);
0944: results.addAll(values);
0945: }
0946: return results;
0947: }
0948:
0949: /** Finds all Generic entities
0950: *@param entityName The Name of the Entity as defined in the entity XML file
0951: *@return List containing all Generic entities
0952: */
0953: public List findAll(String entityName)
0954: throws GenericEntityException {
0955: return this .findByAnd(entityName, new HashMap(), null);
0956: }
0957:
0958: /** Finds all Generic entities
0959: *@param entityName The Name of the Entity as defined in the entity XML file
0960: *@param orderBy The fields of the named entity to order the query by; optionally add a " ASC" for ascending or " DESC" for descending
0961: *@return List containing all Generic entities
0962: */
0963: public List findAll(String entityName, List orderBy)
0964: throws GenericEntityException {
0965: return this .findByAnd(entityName, new HashMap(), orderBy);
0966: }
0967:
0968: /** Finds all Generic entities, looking first in the cache
0969: *@param entityName The Name of the Entity as defined in the entity XML file
0970: *@return List containing all Generic entities
0971: */
0972: public List findAllCache(String entityName)
0973: throws GenericEntityException {
0974: return this .findAllCache(entityName, null);
0975: }
0976:
0977: /** Finds all Generic entities, looking first in the cache; uses orderBy for lookup, but only keys results on the entityName and fields
0978: *@param entityName The Name of the Entity as defined in the entity XML file
0979: *@param orderBy The fields of the named entity to order the query by; optionally add a " ASC" for ascending or " DESC" for descending
0980: *@return List containing all Generic entities
0981: */
0982: public List findAllCache(String entityName, List orderBy)
0983: throws GenericEntityException {
0984: GenericValue dummyValue = makeValue(entityName, null);
0985: Map ecaEventMap = this .getEcaEntityEventMap(entityName);
0986: this .evalEcaRules(EntityEcaHandler.EV_CACHE_CHECK,
0987: EntityEcaHandler.OP_FIND, dummyValue, ecaEventMap,
0988: (ecaEventMap == null), false);
0989:
0990: List lst = this .getFromAllCache(entityName);
0991:
0992: if (lst == null) {
0993: lst = findAll(entityName, orderBy);
0994: if (lst != null) {
0995: this .evalEcaRules(EntityEcaHandler.EV_CACHE_PUT,
0996: EntityEcaHandler.OP_FIND, dummyValue,
0997: ecaEventMap, (ecaEventMap == null), false);
0998: this .putInAllCache(entityName, lst);
0999: }
1000: return lst;
1001: } else {
1002: return EntityUtil.orderBy(lst, orderBy);
1003: }
1004: }
1005:
1006: /** Finds Generic Entity records by all of the specified fields (ie: combined using AND)
1007: * @param entityName The Name of the Entity as defined in the entity XML file
1008: * @param fields The fields of the named entity to query by with their corresponging values
1009: * @return List of GenericValue instances that match the query
1010: */
1011: public List findByAnd(String entityName, Map fields)
1012: throws GenericEntityException {
1013: return this .findByAnd(entityName, fields, null);
1014: }
1015:
1016: /** Finds Generic Entity records by all of the specified fields (ie: combined using OR)
1017: * @param entityName The Name of the Entity as defined in the entity XML file
1018: * @param fields The fields of the named entity to query by with their corresponging values
1019: * @return List of GenericValue instances that match the query
1020: */
1021: public List findByOr(String entityName, Map fields)
1022: throws GenericEntityException {
1023: return this .findByOr(entityName, fields, null);
1024: }
1025:
1026: /** Finds Generic Entity records by all of the specified fields (ie: combined using AND)
1027: * @param entityName The Name of the Entity as defined in the entity XML file
1028: * @param fields The fields of the named entity to query by with their corresponging values
1029: * @param orderBy The fields of the named entity to order the query by;
1030: * optionally add a " ASC" for ascending or " DESC" for descending
1031: * @return List of GenericValue instances that match the query
1032: */
1033: public List findByAnd(String entityName, Map fields, List orderBy)
1034: throws GenericEntityException {
1035: ModelEntity modelEntity = getModelReader().getModelEntity(
1036: entityName);
1037: GenericValue dummyValue = new GenericValue(modelEntity, fields);
1038: this .evalEcaRules(EntityEcaHandler.EV_VALIDATE,
1039: EntityEcaHandler.OP_FIND, dummyValue, null, false,
1040: false);
1041: return findByAnd(modelEntity, fields, orderBy);
1042: }
1043:
1044: public List findByAnd(ModelEntity modelEntity, Map fields,
1045: List orderBy) throws GenericEntityException {
1046: GenericValue dummyValue = new GenericValue(modelEntity);
1047: Map ecaEventMap = this .getEcaEntityEventMap(modelEntity
1048: .getEntityName());
1049:
1050: GenericHelper helper = getEntityHelper(modelEntity);
1051:
1052: if (fields != null && !modelEntity.areFields(fields.keySet())) {
1053: throw new GenericModelException(
1054: "At least one of the passed fields is not valid: "
1055: + fields.keySet().toString());
1056: }
1057:
1058: this .evalEcaRules(EntityEcaHandler.EV_RUN,
1059: EntityEcaHandler.OP_FIND, dummyValue, ecaEventMap,
1060: (ecaEventMap == null), false);
1061: List list = null;
1062: list = helper.findByAnd(modelEntity, fields, orderBy);
1063: absorbList(list);
1064:
1065: this .evalEcaRules(EntityEcaHandler.EV_RETURN,
1066: EntityEcaHandler.OP_FIND, dummyValue, ecaEventMap,
1067: (ecaEventMap == null), false);
1068: return list;
1069: }
1070:
1071: /** Finds Generic Entity records by all of the specified fields (ie: combined using OR)
1072: * @param entityName The Name of the Entity as defined in the entity XML file
1073: * @param fields The fields of the named entity to query by with their corresponging values
1074: * @param orderBy The fields of the named entity to order the query by;
1075: * optionally add a " ASC" for ascending or " DESC" for descending
1076: * @return List of GenericValue instances that match the query
1077: */
1078: public List findByOr(String entityName, Map fields, List orderBy)
1079: throws GenericEntityException {
1080: ModelEntity modelEntity = getModelReader().getModelEntity(
1081: entityName);
1082: GenericValue dummyValue = new GenericValue(modelEntity);
1083: Map ecaEventMap = this .getEcaEntityEventMap(modelEntity
1084: .getEntityName());
1085: this .evalEcaRules(EntityEcaHandler.EV_VALIDATE,
1086: EntityEcaHandler.OP_FIND, dummyValue, null, false,
1087: false);
1088:
1089: GenericHelper helper = getEntityHelper(entityName);
1090:
1091: if (fields != null && !modelEntity.areFields(fields.keySet())) {
1092: throw new GenericModelException(
1093: "[GenericDelegator.findByOr] At least of the passed fields is not valid: "
1094: + fields.keySet().toString());
1095: }
1096:
1097: this .evalEcaRules(EntityEcaHandler.EV_RUN,
1098: EntityEcaHandler.OP_FIND, dummyValue, ecaEventMap,
1099: (ecaEventMap == null), false);
1100: List list = null;
1101: list = helper.findByOr(modelEntity, fields, orderBy);
1102: absorbList(list);
1103:
1104: this .evalEcaRules(EntityEcaHandler.EV_RETURN,
1105: EntityEcaHandler.OP_FIND, dummyValue, ecaEventMap,
1106: (ecaEventMap == null), false);
1107: return list;
1108: }
1109:
1110: /** 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
1111: *@param entityName The Name of the Entity as defined in the entity XML file
1112: *@param fields The fields of the named entity to query by with their corresponging values
1113: *@return List of GenericValue instances that match the query
1114: */
1115: public List findByAndCache(String entityName, Map fields)
1116: throws GenericEntityException {
1117: return this .findByAndCache(entityName, fields, null);
1118: }
1119:
1120: /** 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
1121: *@param entityName The Name of the Entity as defined in the entity XML file
1122: *@param fields The fields of the named entity to query by with their corresponging values
1123: *@param orderBy The fields of the named entity to order the query by; optionally add a " ASC" for ascending or " DESC" for descending
1124: *@return List of GenericValue instances that match the query
1125: */
1126: public List findByAndCache(String entityName, Map fields,
1127: List orderBy) throws GenericEntityException {
1128: ModelEntity modelEntity = getModelReader().getModelEntity(
1129: entityName);
1130: GenericValue dummyValue = new GenericValue(modelEntity);
1131: Map ecaEventMap = this .getEcaEntityEventMap(modelEntity
1132: .getEntityName());
1133:
1134: this .evalEcaRules(EntityEcaHandler.EV_CACHE_CHECK,
1135: EntityEcaHandler.OP_FIND, dummyValue, ecaEventMap,
1136: (ecaEventMap == null), false);
1137: List lst = this .getFromAndCache(modelEntity, fields);
1138:
1139: if (lst == null) {
1140: lst = findByAnd(modelEntity, fields, orderBy);
1141: if (lst != null) {
1142: this .evalEcaRules(EntityEcaHandler.EV_CACHE_PUT,
1143: EntityEcaHandler.OP_FIND, dummyValue,
1144: ecaEventMap, (ecaEventMap == null), false);
1145: this .putInAndCache(modelEntity, fields, lst);
1146: }
1147: return lst;
1148: } else {
1149: // automatically re-order the elements if this didn't come from the datasource directly
1150: return EntityUtil.orderBy(lst, orderBy);
1151: }
1152: }
1153:
1154: /** Finds Generic Entity records by all of the specified expressions (ie: combined using AND)
1155: *@param entityName The Name of the Entity as defined in the entity XML file
1156: *@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
1157: *@return List of GenericValue instances that match the query
1158: */
1159: public List findByAnd(String entityName, List expressions)
1160: throws GenericEntityException {
1161: EntityConditionList ecl = new EntityConditionList(expressions,
1162: EntityOperator.AND);
1163: return findByCondition(entityName, ecl, null, null);
1164: }
1165:
1166: /** Finds Generic Entity records by all of the specified expressions (ie: combined using AND)
1167: *@param entityName The Name of the Entity as defined in the entity XML file
1168: *@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
1169: *@param orderBy The fields of the named entity to order the query by; optionally add a " ASC" for ascending or " DESC" for descending
1170: *@return List of GenericValue instances that match the query
1171: */
1172: public List findByAnd(String entityName, List expressions,
1173: List orderBy) throws GenericEntityException {
1174: EntityConditionList ecl = new EntityConditionList(expressions,
1175: EntityOperator.AND);
1176: return findByCondition(entityName, ecl, null, orderBy);
1177: }
1178:
1179: /** Finds Generic Entity records by all of the specified expressions (ie: combined using OR)
1180: *@param entityName The Name of the Entity as defined in the entity XML file
1181: *@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
1182: *@return List of GenericValue instances that match the query
1183: */
1184: public List findByOr(String entityName, List expressions)
1185: throws GenericEntityException {
1186: EntityConditionList ecl = new EntityConditionList(expressions,
1187: EntityOperator.OR);
1188: return findByCondition(entityName, ecl, null, null);
1189: }
1190:
1191: /** Finds Generic Entity records by all of the specified expressions (ie: combined using OR)
1192: *@param entityName The Name of the Entity as defined in the entity XML file
1193: *@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
1194: *@param orderBy The fields of the named entity to order the query by; optionally add a " ASC" for ascending or " DESC" for descending
1195: *@return List of GenericValue instances that match the query
1196: */
1197: public List findByOr(String entityName, List expressions,
1198: List orderBy) throws GenericEntityException {
1199: EntityConditionList ecl = new EntityConditionList(expressions,
1200: EntityOperator.OR);
1201: return findByCondition(entityName, ecl, null, orderBy);
1202: }
1203:
1204: public List findByLike(String entityName, Map fields)
1205: throws GenericEntityException {
1206: return findByLike(entityName, fields, null);
1207: }
1208:
1209: public List findByLike(String entityName, Map fields, List orderBy)
1210: throws GenericEntityException {
1211: List likeExpressions = new LinkedList();
1212: if (fields != null) {
1213: Iterator fieldEntries = fields.entrySet().iterator();
1214: while (fieldEntries.hasNext()) {
1215: Map.Entry fieldEntry = (Map.Entry) fieldEntries.next();
1216: likeExpressions.add(new EntityExpr(fieldEntry.getKey(),
1217: EntityOperator.LIKE, fieldEntry.getValue()));
1218: }
1219: }
1220: EntityConditionList ecl = new EntityConditionList(
1221: likeExpressions, EntityOperator.AND);
1222: return findByCondition(entityName, ecl, null, orderBy);
1223: }
1224:
1225: /** Finds GenericValues by the conditions specified in the EntityCondition object, the the EntityCondition javadoc for more details.
1226: *@param entityName The Name of the Entity as defined in the entity model XML file
1227: *@param entityCondition The EntityCondition object that specifies how to constrain this query
1228: *@param fieldsToSelect The fields of the named entity to get from the database; if empty or null all fields will be retreived
1229: *@param orderBy The fields of the named entity to order the query by; optionally add a " ASC" for ascending or " DESC" for descending
1230: *@return List of GenericValue objects representing the result
1231: */
1232: public List findByCondition(String entityName,
1233: EntityCondition entityCondition, Collection fieldsToSelect,
1234: List orderBy) throws GenericEntityException {
1235: ModelEntity modelEntity = getModelReader().getModelEntity(
1236: entityName);
1237: GenericValue dummyValue = new GenericValue(modelEntity);
1238: Map ecaEventMap = this .getEcaEntityEventMap(entityName);
1239:
1240: this .evalEcaRules(EntityEcaHandler.EV_VALIDATE,
1241: EntityEcaHandler.OP_FIND, dummyValue, ecaEventMap,
1242: (ecaEventMap == null), false);
1243: if (entityCondition != null)
1244: entityCondition.checkCondition(modelEntity);
1245:
1246: this .evalEcaRules(EntityEcaHandler.EV_RUN,
1247: EntityEcaHandler.OP_FIND, dummyValue, ecaEventMap,
1248: (ecaEventMap == null), false);
1249: GenericHelper helper = getEntityHelper(entityName);
1250: List list = null;
1251: list = helper.findByCondition(modelEntity, entityCondition,
1252: fieldsToSelect, orderBy);
1253:
1254: this .evalEcaRules(EntityEcaHandler.EV_RETURN,
1255: EntityEcaHandler.OP_FIND, dummyValue, ecaEventMap,
1256: (ecaEventMap == null), false);
1257: absorbList(list);
1258:
1259: return list;
1260: }
1261:
1262: /** Finds GenericValues by the conditions specified in the EntityCondition object, the the EntityCondition javadoc for more details.
1263: *@param entityName The Name of the Entity as defined in the entity model XML file
1264: *@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)
1265: *@param fieldsToSelect The fields of the named entity to get from the database; if empty or null all fields will be retreived
1266: *@param orderBy The fields of the named entity to order the query by; optionally add a " ASC" for ascending or " DESC" for descending
1267: *@return EntityListIterator representing the result of the query: NOTE THAT THIS MUST BE CLOSED WHEN YOU ARE
1268: * DONE WITH IT, AND DON'T LEAVE IT OPEN TOO LONG BEACUSE IT WILL MAINTAIN A DATABASE CONNECTION.
1269: */
1270: public EntityListIterator findListIteratorByCondition(
1271: String entityName, EntityCondition entityCondition,
1272: Collection fieldsToSelect, List orderBy)
1273: throws GenericEntityException {
1274: return this .findListIteratorByCondition(entityName,
1275: entityCondition, null, fieldsToSelect, orderBy, null);
1276: }
1277:
1278: /** Finds GenericValues by the conditions specified in the EntityCondition object, the the EntityCondition javadoc for more details.
1279: *@param entityName The name of the Entity as defined in the entity XML file
1280: *@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)
1281: *@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)
1282: *@param fieldsToSelect The fields of the named entity to get from the database; if empty or null all fields will be retreived
1283: *@param orderBy The fields of the named entity to order the query by; optionally add a " ASC" for ascending or " DESC" for descending
1284: *@param findOptions An instance of EntityFindOptions that specifies advanced query options. See the EntityFindOptions JavaDoc for more details.
1285: *@return EntityListIterator representing the result of the query: NOTE THAT THIS MUST BE CLOSED WHEN YOU ARE
1286: * DONE WITH IT, AND DON'T LEAVE IT OPEN TOO LONG BEACUSE IT WILL MAINTAIN A DATABASE CONNECTION.
1287: */
1288: public EntityListIterator findListIteratorByCondition(
1289: String entityName, EntityCondition whereEntityCondition,
1290: EntityCondition havingEntityCondition,
1291: Collection fieldsToSelect, List orderBy,
1292: EntityFindOptions findOptions)
1293: throws GenericEntityException {
1294:
1295: ModelEntity modelEntity = getModelReader().getModelEntity(
1296: entityName);
1297: GenericValue dummyValue = new GenericValue(modelEntity);
1298: Map ecaEventMap = this .getEcaEntityEventMap(modelEntity
1299: .getEntityName());
1300: this .evalEcaRules(EntityEcaHandler.EV_VALIDATE,
1301: EntityEcaHandler.OP_FIND, dummyValue, ecaEventMap,
1302: (ecaEventMap == null), false);
1303:
1304: if (whereEntityCondition != null)
1305: whereEntityCondition.checkCondition(modelEntity);
1306: if (havingEntityCondition != null)
1307: havingEntityCondition.checkCondition(modelEntity);
1308:
1309: this .evalEcaRules(EntityEcaHandler.EV_RUN,
1310: EntityEcaHandler.OP_FIND, dummyValue, ecaEventMap,
1311: (ecaEventMap == null), false);
1312: GenericHelper helper = getEntityHelper(modelEntity
1313: .getEntityName());
1314: EntityListIterator eli = helper.findListIteratorByCondition(
1315: modelEntity, whereEntityCondition,
1316: havingEntityCondition, fieldsToSelect, orderBy,
1317: findOptions);
1318: eli.setDelegator(this );
1319:
1320: this .evalEcaRules(EntityEcaHandler.EV_RETURN,
1321: EntityEcaHandler.OP_FIND, dummyValue, ecaEventMap,
1322: (ecaEventMap == null), false);
1323: return eli;
1324: }
1325:
1326: /** Finds GenericValues by the conditions specified in the EntityCondition object, the the EntityCondition javadoc for more details.
1327: *@param dynamicViewEntity The DynamicViewEntity to use for the entity model for this query; generally created on the fly for limited use
1328: *@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)
1329: *@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)
1330: *@param fieldsToSelect The fields of the named entity to get from the database; if empty or null all fields will be retreived
1331: *@param orderBy The fields of the named entity to order the query by; optionally add a " ASC" for ascending or " DESC" for descending
1332: *@param findOptions An instance of EntityFindOptions that specifies advanced query options. See the EntityFindOptions JavaDoc for more details.
1333: *@return EntityListIterator representing the result of the query: NOTE THAT THIS MUST BE CLOSED WHEN YOU ARE
1334: * DONE WITH IT, AND DON'T LEAVE IT OPEN TOO LONG BEACUSE IT WILL MAINTAIN A DATABASE CONNECTION.
1335: */
1336: public EntityListIterator findListIteratorByCondition(
1337: DynamicViewEntity dynamicViewEntity,
1338: EntityCondition whereEntityCondition,
1339: EntityCondition havingEntityCondition,
1340: Collection fieldsToSelect, List orderBy,
1341: EntityFindOptions findOptions)
1342: throws GenericEntityException {
1343:
1344: ModelViewEntity modelViewEntity = dynamicViewEntity
1345: .makeModelViewEntity(this );
1346: if (whereEntityCondition != null)
1347: whereEntityCondition.checkCondition(modelViewEntity);
1348: if (havingEntityCondition != null)
1349: havingEntityCondition.checkCondition(modelViewEntity);
1350:
1351: GenericHelper helper = getEntityHelper(dynamicViewEntity
1352: .getOneRealEntityName());
1353: EntityListIterator eli = helper.findListIteratorByCondition(
1354: modelViewEntity, whereEntityCondition,
1355: havingEntityCondition, fieldsToSelect, orderBy,
1356: findOptions);
1357: eli.setDelegator(this );
1358:
1359: return eli;
1360: }
1361:
1362: public long findCountByAnd(String entityName, Map fields)
1363: throws GenericEntityException {
1364: return findCountByCondition(entityName, new EntityFieldMap(
1365: fields, EntityOperator.AND), null);
1366: }
1367:
1368: public long findCountByCondition(String entityName,
1369: EntityCondition whereEntityCondition,
1370: EntityCondition havingEntityCondition)
1371: throws GenericEntityException {
1372: ModelEntity modelEntity = getModelReader().getModelEntity(
1373: entityName);
1374: GenericValue dummyValue = new GenericValue(modelEntity);
1375: Map ecaEventMap = this .getEcaEntityEventMap(modelEntity
1376: .getEntityName());
1377: this .evalEcaRules(EntityEcaHandler.EV_VALIDATE,
1378: EntityEcaHandler.OP_FIND, dummyValue, ecaEventMap,
1379: (ecaEventMap == null), false);
1380:
1381: if (whereEntityCondition != null)
1382: whereEntityCondition.checkCondition(modelEntity);
1383: if (havingEntityCondition != null)
1384: havingEntityCondition.checkCondition(modelEntity);
1385:
1386: this .evalEcaRules(EntityEcaHandler.EV_RUN,
1387: EntityEcaHandler.OP_FIND, dummyValue, ecaEventMap,
1388: (ecaEventMap == null), false);
1389: GenericHelper helper = getEntityHelper(modelEntity
1390: .getEntityName());
1391: long count = helper.findCountByCondition(modelEntity,
1392: whereEntityCondition, havingEntityCondition);
1393:
1394: this .evalEcaRules(EntityEcaHandler.EV_RETURN,
1395: EntityEcaHandler.OP_FIND, dummyValue, ecaEventMap,
1396: (ecaEventMap == null), false);
1397: return count;
1398: }
1399:
1400: protected void saveEntitySyncRemoveInfo(GenericEntity dummyPK)
1401: throws GenericEntityException {
1402: // don't store remove info on entities where it is disabled
1403: if (dummyPK.getModelEntity().getNoAutoStamp()) {
1404: return;
1405: }
1406:
1407: // don't store remove info on things removed on an entity sync
1408: if (dummyPK.getIsFromEntitySync()) {
1409: return;
1410: }
1411:
1412: String serializedPK = null;
1413: try {
1414: serializedPK = XmlSerializer.serialize(dummyPK);
1415: } catch (SerializeException e) {
1416: Debug
1417: .logError(
1418: e,
1419: "Could not serialize primary key to save EntitySyncRemove",
1420: module);
1421: } catch (FileNotFoundException e) {
1422: Debug
1423: .logError(
1424: e,
1425: "Could not serialize primary key to save EntitySyncRemove",
1426: module);
1427: } catch (IOException e) {
1428: Debug
1429: .logError(
1430: e,
1431: "Could not serialize primary key to save EntitySyncRemove",
1432: module);
1433: }
1434:
1435: if (serializedPK != null) {
1436: GenericValue entitySyncRemove = this .makeValue(
1437: "EntitySyncRemove", null);
1438: entitySyncRemove.set("entitySyncRemoveId", this
1439: .getNextSeqId("EntitySyncRemove"));
1440: entitySyncRemove.set("primaryKeyRemoved", serializedPK);
1441: entitySyncRemove.create();
1442: }
1443: }
1444:
1445: /** Remove a Generic Entity corresponding to the primaryKey
1446: *@param primaryKey The primary key of the entity to remove.
1447: *@return int representing number of rows effected by this operation
1448: */
1449: public int removeByPrimaryKey(GenericPK primaryKey)
1450: throws GenericEntityException {
1451: int retVal = this .removeByPrimaryKey(primaryKey, true);
1452: return retVal;
1453: }
1454:
1455: /** Remove a Generic Entity corresponding to the primaryKey
1456: *@param primaryKey The primary key of the entity to remove.
1457: *@param doCacheClear boolean that specifies whether to clear cache entries for this primaryKey to be removed
1458: *@return int representing number of rows effected by this operation
1459: */
1460: public int removeByPrimaryKey(GenericPK primaryKey,
1461: boolean doCacheClear) throws GenericEntityException {
1462: Map ecaEventMap = this .getEcaEntityEventMap(primaryKey
1463: .getEntityName());
1464: this .evalEcaRules(EntityEcaHandler.EV_VALIDATE,
1465: EntityEcaHandler.OP_REMOVE, primaryKey, ecaEventMap,
1466: (ecaEventMap == null), false);
1467:
1468: GenericHelper helper = getEntityHelper(primaryKey
1469: .getEntityName());
1470:
1471: if (doCacheClear) {
1472: // always clear cache before the operation
1473: this .evalEcaRules(EntityEcaHandler.EV_CACHE_CLEAR,
1474: EntityEcaHandler.OP_REMOVE, primaryKey,
1475: ecaEventMap, (ecaEventMap == null), false);
1476: this .clearCacheLine(primaryKey);
1477: }
1478:
1479: this .evalEcaRules(EntityEcaHandler.EV_RUN,
1480: EntityEcaHandler.OP_REMOVE, primaryKey, ecaEventMap,
1481: (ecaEventMap == null), false);
1482: int num = helper.removeByPrimaryKey(primaryKey);
1483: this .saveEntitySyncRemoveInfo(primaryKey);
1484:
1485: this .evalEcaRules(EntityEcaHandler.EV_RETURN,
1486: EntityEcaHandler.OP_REMOVE, primaryKey, ecaEventMap,
1487: (ecaEventMap == null), false);
1488: return num;
1489: }
1490:
1491: /** Remove a Generic Value from the database
1492: *@param value The GenericValue object of the entity to remove.
1493: *@return int representing number of rows effected by this operation
1494: */
1495: public int removeValue(GenericValue value)
1496: throws GenericEntityException {
1497: return this .removeValue(value, true);
1498: }
1499:
1500: /** Remove a Generic Value from the database
1501: *@param value The GenericValue object of the entity to remove.
1502: *@param doCacheClear boolean that specifies whether to clear cache entries for this value to be removed
1503: *@return int representing number of rows effected by this operation
1504: */
1505: public int removeValue(GenericValue value, boolean doCacheClear)
1506: throws GenericEntityException {
1507: Map ecaEventMap = this .getEcaEntityEventMap(value
1508: .getEntityName());
1509: this .evalEcaRules(EntityEcaHandler.EV_VALIDATE,
1510: EntityEcaHandler.OP_REMOVE, value, ecaEventMap,
1511: (ecaEventMap == null), false);
1512:
1513: GenericHelper helper = getEntityHelper(value.getEntityName());
1514:
1515: if (doCacheClear) {
1516: this .evalEcaRules(EntityEcaHandler.EV_CACHE_CLEAR,
1517: EntityEcaHandler.OP_REMOVE, value, ecaEventMap,
1518: (ecaEventMap == null), false);
1519: this .clearCacheLine(value);
1520: }
1521:
1522: this .evalEcaRules(EntityEcaHandler.EV_RUN,
1523: EntityEcaHandler.OP_REMOVE, value, ecaEventMap,
1524: (ecaEventMap == null), false);
1525: int num = helper.removeByPrimaryKey(value.getPrimaryKey());
1526: this .saveEntitySyncRemoveInfo(value.getPrimaryKey());
1527:
1528: this .evalEcaRules(EntityEcaHandler.EV_RETURN,
1529: EntityEcaHandler.OP_REMOVE, value, ecaEventMap,
1530: (ecaEventMap == null), false);
1531: return num;
1532: }
1533:
1534: /** Removes/deletes Generic Entity records found by all of the specified fields (ie: combined using AND)
1535: *@param entityName The Name of the Entity as defined in the entity XML file
1536: *@param fields The fields of the named entity to query by with their corresponging values
1537: *@return int representing number of rows effected by this operation
1538: */
1539: public int removeByAnd(String entityName, Map fields)
1540: throws GenericEntityException {
1541: return this .removeByAnd(entityName, fields, true);
1542: }
1543:
1544: /** Removes/deletes Generic Entity records found by all of the specified fields (ie: combined using AND)
1545: *@param entityName The Name of the Entity as defined in the entity XML file
1546: *@param fields The fields of the named entity to query by with their corresponging values
1547: *@param doCacheClear boolean that specifies whether to clear cache entries for this value to be removed
1548: *@return int representing number of rows effected by this operation
1549: */
1550: public int removeByAnd(String entityName, Map fields,
1551: boolean doCacheClear) throws GenericEntityException {
1552: GenericValue dummyPK = makeValue(entityName, null);
1553: dummyPK.setFields(fields);
1554:
1555: Map ecaEventMap = this .getEcaEntityEventMap(entityName);
1556: this .evalEcaRules(EntityEcaHandler.EV_VALIDATE,
1557: EntityEcaHandler.OP_REMOVE, dummyPK, ecaEventMap,
1558: (ecaEventMap == null), false);
1559:
1560: ModelEntity modelEntity = getModelReader().getModelEntity(
1561: entityName);
1562: GenericHelper helper = getEntityHelper(entityName);
1563:
1564: if (doCacheClear) {
1565: // always clear cache before the operation
1566: this .evalEcaRules(EntityEcaHandler.EV_CACHE_CLEAR,
1567: EntityEcaHandler.OP_REMOVE, dummyPK, ecaEventMap,
1568: (ecaEventMap == null), false);
1569: this .clearCacheLine(entityName, fields);
1570: }
1571:
1572: this .evalEcaRules(EntityEcaHandler.EV_RUN,
1573: EntityEcaHandler.OP_REMOVE, dummyPK, ecaEventMap,
1574: (ecaEventMap == null), false);
1575: int num = helper.removeByAnd(modelEntity, dummyPK
1576: .getAllFields());
1577: this .saveEntitySyncRemoveInfo(dummyPK);
1578:
1579: this .evalEcaRules(EntityEcaHandler.EV_RETURN,
1580: EntityEcaHandler.OP_REMOVE, dummyPK, ecaEventMap,
1581: (ecaEventMap == null), false);
1582: return num;
1583: }
1584:
1585: /**
1586: * Get the named Related Entity for the GenericValue from the persistent store across another Relation.
1587: * Helps to get related Values in a multi-to-multi relationship.
1588: * @param relationNameOne String containing the relation name which is the
1589: * combination of relation.title and relation.rel-entity-name as
1590: * specified in the entity XML definition file, for first relation
1591: * @param relationNameTwo String containing the relation name for second relation
1592: * @param value GenericValue instance containing the entity
1593: * @param orderBy The fields of the named entity to order the query by; may be null;
1594: * optionally add a " ASC" for ascending or " DESC" for descending
1595: * @return List of GenericValue instances as specified in the relation definition
1596: */
1597: public List getMultiRelation(GenericValue value,
1598: String relationNameOne, String relationNameTwo, List orderBy)
1599: throws GenericEntityException {
1600: //TODO: add eca eval calls
1601: // traverse the relationships
1602: ModelEntity modelEntity = value.getModelEntity();
1603: ModelRelation modelRelationOne = modelEntity
1604: .getRelation(relationNameOne);
1605: ModelEntity modelEntityOne = getModelEntity(modelRelationOne
1606: .getRelEntityName());
1607: ModelRelation modelRelationTwo = modelEntityOne
1608: .getRelation(relationNameTwo);
1609: ModelEntity modelEntityTwo = getModelEntity(modelRelationTwo
1610: .getRelEntityName());
1611:
1612: GenericHelper helper = getEntityHelper(modelEntity);
1613:
1614: return helper.findByMultiRelation(value, modelRelationOne,
1615: modelEntityOne, modelRelationTwo, modelEntityTwo,
1616: orderBy);
1617: }
1618:
1619: /**
1620: * Get the named Related Entity for the GenericValue from the persistent store across another Relation.
1621: * Helps to get related Values in a multi-to-multi relationship.
1622: * @param relationNameOne String containing the relation name which is the
1623: * combination of relation.title and relation.rel-entity-name as
1624: * specified in the entity XML definition file, for first relation
1625: * @param relationNameTwo String containing the relation name for second relation
1626: * @param value GenericValue instance containing the entity
1627: * @return List of GenericValue instances as specified in the relation definition
1628: */
1629: public List getMultiRelation(GenericValue value,
1630: String relationNameOne, String relationNameTwo)
1631: throws GenericEntityException {
1632: return getMultiRelation(value, relationNameOne,
1633: relationNameTwo, null);
1634: }
1635:
1636: /** Get the named Related Entity for the GenericValue from the persistent store
1637: * @param relationName String containing the relation name which is the
1638: * combination of relation.title and relation.rel-entity-name as
1639: * specified in the entity XML definition file
1640: * @param value GenericValue instance containing the entity
1641: * @return List of GenericValue instances as specified in the relation definition
1642: */
1643: public List getRelated(String relationName, GenericValue value)
1644: throws GenericEntityException {
1645: return getRelated(relationName, null, null, value);
1646: }
1647:
1648: /** Get the named Related Entity for the GenericValue from the persistent store
1649: * @param relationName String containing the relation name which is the
1650: * combination of relation.title and relation.rel-entity-name as
1651: * specified in the entity XML definition file
1652: * @param byAndFields the fields that must equal in order to keep; may be null
1653: * @param value GenericValue instance containing the entity
1654: * @return List of GenericValue instances as specified in the relation definition
1655: */
1656: public List getRelatedByAnd(String relationName, Map byAndFields,
1657: GenericValue value) throws GenericEntityException {
1658: return this .getRelated(relationName, byAndFields, null, value);
1659: }
1660:
1661: /** Get the named Related Entity for the GenericValue from the persistent store
1662: * @param relationName String containing the relation name which is the
1663: * combination of relation.title and relation.rel-entity-name as
1664: * specified in the entity XML definition file
1665: * @param orderBy The fields of the named entity to order the query by; may be null;
1666: * optionally add a " ASC" for ascending or " DESC" for descending
1667: * @param value GenericValue instance containing the entity
1668: * @return List of GenericValue instances as specified in the relation definition
1669: */
1670: public List getRelatedOrderBy(String relationName, List orderBy,
1671: GenericValue value) throws GenericEntityException {
1672: return this .getRelated(relationName, null, orderBy, value);
1673: }
1674:
1675: /** Get the named Related Entity for the GenericValue from the persistent store
1676: * @param relationName String containing the relation name which is the
1677: * combination of relation.title and relation.rel-entity-name as
1678: * specified in the entity XML definition file
1679: * @param byAndFields the fields that must equal in order to keep; may be null
1680: * @param orderBy The fields of the named entity to order the query by; may be null;
1681: * optionally add a " ASC" for ascending or " DESC" for descending
1682: * @param value GenericValue instance containing the entity
1683: * @return List of GenericValue instances as specified in the relation definition
1684: */
1685: public List getRelated(String relationName, Map byAndFields,
1686: List orderBy, GenericValue value)
1687: throws GenericEntityException {
1688: ModelEntity modelEntity = value.getModelEntity();
1689: ModelRelation relation = modelEntity.getRelation(relationName);
1690:
1691: if (relation == null) {
1692: throw new GenericModelException(
1693: "Could not find relation for relationName: "
1694: + relationName + " for value " + value);
1695: }
1696:
1697: // put the byAndFields (if not null) into the hash map first,
1698: // they will be overridden by value's fields if over-specified this is important for security and cleanliness
1699: Map fields = byAndFields == null ? new HashMap() : new HashMap(
1700: byAndFields);
1701: for (int i = 0; i < relation.getKeyMapsSize(); i++) {
1702: ModelKeyMap keyMap = relation.getKeyMap(i);
1703: fields.put(keyMap.getRelFieldName(), value.get(keyMap
1704: .getFieldName()));
1705: }
1706:
1707: return this .findByAnd(relation.getRelEntityName(), fields,
1708: orderBy);
1709: }
1710:
1711: /** Get a dummy primary key for the named Related Entity for the GenericValue
1712: * @param relationName String containing the relation name which is the
1713: * combination of relation.title and relation.rel-entity-name as
1714: * specified in the entity XML definition file
1715: * @param byAndFields the fields that must equal in order to keep; may be null
1716: * @param value GenericValue instance containing the entity
1717: * @return GenericPK containing a possibly incomplete PrimaryKey object representing the related entity or entities
1718: */
1719: public GenericPK getRelatedDummyPK(String relationName,
1720: Map byAndFields, GenericValue value)
1721: throws GenericEntityException {
1722: ModelEntity modelEntity = value.getModelEntity();
1723: ModelRelation relation = modelEntity.getRelation(relationName);
1724:
1725: if (relation == null) {
1726: throw new GenericModelException(
1727: "Could not find relation for relationName: "
1728: + relationName + " for value " + value);
1729: }
1730: ModelEntity relatedEntity = getModelReader().getModelEntity(
1731: relation.getRelEntityName());
1732:
1733: // put the byAndFields (if not null) into the hash map first,
1734: // they will be overridden by value's fields if over-specified this is important for security and cleanliness
1735: Map fields = byAndFields == null ? new HashMap() : new HashMap(
1736: byAndFields);
1737: for (int i = 0; i < relation.getKeyMapsSize(); i++) {
1738: ModelKeyMap keyMap = relation.getKeyMap(i);
1739: fields.put(keyMap.getRelFieldName(), value.get(keyMap
1740: .getFieldName()));
1741: }
1742:
1743: GenericPK dummyPK = new GenericPK(relatedEntity, fields);
1744: dummyPK.setDelegator(this );
1745: return dummyPK;
1746: }
1747:
1748: /** 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
1749: * @param relationName String containing the relation name which is the
1750: * combination of relation.title and relation.rel-entity-name as
1751: * specified in the entity XML definition file
1752: * @param value GenericValue instance containing the entity
1753: * @return List of GenericValue instances as specified in the relation definition
1754: */
1755: public List getRelatedCache(String relationName, GenericValue value)
1756: throws GenericEntityException {
1757: ModelEntity modelEntity = value.getModelEntity();
1758: ModelRelation relation = modelEntity.getRelation(relationName);
1759:
1760: if (relation == null) {
1761: throw new GenericModelException(
1762: "Could not find relation for relationName: "
1763: + relationName + " for value " + value);
1764: }
1765:
1766: Map fields = new HashMap();
1767: for (int i = 0; i < relation.getKeyMapsSize(); i++) {
1768: ModelKeyMap keyMap = relation.getKeyMap(i);
1769: fields.put(keyMap.getRelFieldName(), value.get(keyMap
1770: .getFieldName()));
1771: }
1772:
1773: return this .findByAndCache(relation.getRelEntityName(), fields,
1774: null);
1775: }
1776:
1777: /** Get related entity where relation is of type one, uses findByPrimaryKey
1778: * @throws IllegalArgumentException if the list found has more than one item
1779: */
1780: public GenericValue getRelatedOne(String relationName,
1781: GenericValue value) throws GenericEntityException {
1782: ModelRelation relation = value.getModelEntity().getRelation(
1783: relationName);
1784:
1785: if (relation == null) {
1786: throw new GenericModelException(
1787: "Could not find relation for relationName: "
1788: + relationName + " for value " + value);
1789: }
1790: if (!"one".equals(relation.getType())
1791: && !"one-nofk".equals(relation.getType())) {
1792: throw new GenericModelException(
1793: "Relation is not a 'one' or a 'one-nofk' relation: "
1794: + relationName + " of entity "
1795: + value.getEntityName());
1796: }
1797:
1798: Map fields = new HashMap();
1799: for (int i = 0; i < relation.getKeyMapsSize(); i++) {
1800: ModelKeyMap keyMap = relation.getKeyMap(i);
1801: fields.put(keyMap.getRelFieldName(), value.get(keyMap
1802: .getFieldName()));
1803: }
1804:
1805: return this .findByPrimaryKey(relation.getRelEntityName(),
1806: fields);
1807: }
1808:
1809: /** Get related entity where relation is of type one, uses findByPrimaryKey, checking first in the cache to see if the desired value is there
1810: * @throws IllegalArgumentException if the list found has more than one item
1811: */
1812: public GenericValue getRelatedOneCache(String relationName,
1813: GenericValue value) throws GenericEntityException {
1814: ModelEntity modelEntity = value.getModelEntity();
1815: ModelRelation relation = modelEntity.getRelation(relationName);
1816:
1817: if (relation == null) {
1818: throw new GenericModelException(
1819: "Could not find relation for relationName: "
1820: + relationName + " for value " + value);
1821: }
1822: if (!"one".equals(relation.getType())
1823: && !"one-nofk".equals(relation.getType())) {
1824: throw new GenericModelException(
1825: "Relation is not a 'one' or a 'one-nofk' relation: "
1826: + relationName + " of entity "
1827: + value.getEntityName());
1828: }
1829:
1830: Map fields = new HashMap();
1831: for (int i = 0; i < relation.getKeyMapsSize(); i++) {
1832: ModelKeyMap keyMap = relation.getKeyMap(i);
1833: fields.put(keyMap.getRelFieldName(), value.get(keyMap
1834: .getFieldName()));
1835: }
1836:
1837: return this .findByPrimaryKeyCache(relation.getRelEntityName(),
1838: fields);
1839: }
1840:
1841: /** Remove the named Related Entity for the GenericValue from the persistent store
1842: *@param relationName String containing the relation name which is the
1843: * combination of relation.title and relation.rel-entity-name as
1844: * specified in the entity XML definition file
1845: *@param value GenericValue instance containing the entity
1846: *@return int representing number of rows effected by this operation
1847: */
1848: public int removeRelated(String relationName, GenericValue value)
1849: throws GenericEntityException {
1850: return this .removeRelated(relationName, value, true);
1851: }
1852:
1853: /** Remove the named Related Entity for the GenericValue from the persistent store
1854: *@param relationName String containing the relation name which is the
1855: * combination of relation.title and relation.rel-entity-name as
1856: * specified in the entity XML definition file
1857: *@param value GenericValue instance containing the entity
1858: *@param doCacheClear boolean that specifies whether to clear cache entries for this value to be removed
1859: *@return int representing number of rows effected by this operation
1860: */
1861: public int removeRelated(String relationName, GenericValue value,
1862: boolean doCacheClear) throws GenericEntityException {
1863: ModelEntity modelEntity = value.getModelEntity();
1864: ModelRelation relation = modelEntity.getRelation(relationName);
1865:
1866: if (relation == null) {
1867: throw new GenericModelException(
1868: "Could not find relation for relationName: "
1869: + relationName + " for value " + value);
1870: }
1871:
1872: Map fields = new HashMap();
1873: for (int i = 0; i < relation.getKeyMapsSize(); i++) {
1874: ModelKeyMap keyMap = relation.getKeyMap(i);
1875: fields.put(keyMap.getRelFieldName(), value.get(keyMap
1876: .getFieldName()));
1877: }
1878:
1879: return this .removeByAnd(relation.getRelEntityName(), fields,
1880: doCacheClear);
1881: }
1882:
1883: /** Refresh the Entity for the GenericValue from the persistent store
1884: *@param value GenericValue instance containing the entity to refresh
1885: */
1886: public void refresh(GenericValue value)
1887: throws GenericEntityException {
1888: this .refresh(value, true);
1889: }
1890:
1891: /** Refresh the Entity for the GenericValue from the persistent store
1892: *@param value GenericValue instance containing the entity to refresh
1893: *@param doCacheClear boolean that specifies whether or not to automatically clear cache entries related to this operation
1894: */
1895: public void refresh(GenericValue value, boolean doCacheClear)
1896: throws GenericEntityException {
1897: if (doCacheClear) {
1898: // always clear cache before the operation
1899: clearCacheLine(value);
1900: }
1901: GenericPK pk = value.getPrimaryKey();
1902: GenericValue newValue = findByPrimaryKey(pk);
1903: value.refreshFromValue(newValue);
1904: }
1905:
1906: /** Store the Entity from the GenericValue to the persistent store
1907: *@param value GenericValue instance containing the entity
1908: *@return int representing number of rows effected by this operation
1909: */
1910: public int store(GenericValue value) throws GenericEntityException {
1911: return this .store(value, true);
1912: }
1913:
1914: /** Store the Entity from the GenericValue to the persistent store
1915: *@param value GenericValue instance containing the entity
1916: *@param doCacheClear boolean that specifies whether or not to automatically clear cache entries related to this operation
1917: *@return int representing number of rows effected by this operation
1918: */
1919: public int store(GenericValue value, boolean doCacheClear)
1920: throws GenericEntityException {
1921: Map ecaEventMap = this .getEcaEntityEventMap(value
1922: .getEntityName());
1923: this .evalEcaRules(EntityEcaHandler.EV_VALIDATE,
1924: EntityEcaHandler.OP_STORE, value, ecaEventMap,
1925: (ecaEventMap == null), false);
1926: GenericHelper helper = getEntityHelper(value.getEntityName());
1927:
1928: if (doCacheClear) {
1929: // always clear cache before the operation
1930: this .evalEcaRules(EntityEcaHandler.EV_CACHE_CLEAR,
1931: EntityEcaHandler.OP_STORE, value, ecaEventMap,
1932: (ecaEventMap == null), false);
1933: this .clearCacheLine(value);
1934: }
1935:
1936: this .evalEcaRules(EntityEcaHandler.EV_RUN,
1937: EntityEcaHandler.OP_STORE, value, ecaEventMap,
1938: (ecaEventMap == null), false);
1939: int retVal = helper.store(value);
1940:
1941: // refresh the valueObject to get the new version
1942: if (value.lockEnabled()) {
1943: refresh(value, doCacheClear);
1944: }
1945:
1946: this .evalEcaRules(EntityEcaHandler.EV_RETURN,
1947: EntityEcaHandler.OP_STORE, value, ecaEventMap,
1948: (ecaEventMap == null), false);
1949: return retVal;
1950: }
1951:
1952: /** Store the Entities from the List GenericValue instances to the persistent store.
1953: * <br>This is different than the normal store method in that the store method only does
1954: * an update, while the storeAll method checks to see if each entity exists, then
1955: * either does an insert or an update as appropriate.
1956: * <br>These updates all happen in one transaction, so they will either all succeed or all fail,
1957: * if the data source supports transactions. This is just like to othersToStore feature
1958: * of the GenericEntity on a create or store.
1959: *@param values List of GenericValue instances containing the entities to store
1960: *@return int representing number of rows effected by this operation
1961: */
1962: public int storeAll(List values) throws GenericEntityException {
1963: return this .storeAll(values, true);
1964: }
1965:
1966: /** Store the Entities from the List GenericValue instances to the persistent store.
1967: * <br>This is different than the normal store method in that the store method only does
1968: * an update, while the storeAll method checks to see if each entity exists, then
1969: * either does an insert or an update as appropriate.
1970: * <br>These updates all happen in one transaction, so they will either all succeed or all fail,
1971: * if the data source supports transactions. This is just like to othersToStore feature
1972: * of the GenericEntity on a create or store.
1973: *@param values List of GenericValue instances containing the entities to store
1974: *@param doCacheClear boolean that specifies whether or not to automatically clear cache entries related to this operation
1975: *@return int representing number of rows effected by this operation
1976: */
1977: public int storeAll(List values, boolean doCacheClear)
1978: throws GenericEntityException {
1979: //TODO: add eca eval calls
1980: if (values == null) {
1981: return 0;
1982: }
1983:
1984: // from the delegator level this is complicated because different GenericValue
1985: // objects in the list may correspond to different helpers
1986: HashMap valuesPerHelper = new HashMap();
1987: Iterator viter = values.iterator();
1988:
1989: while (viter.hasNext()) {
1990: GenericValue value = (GenericValue) viter.next();
1991: String helperName = this .getEntityHelperName(value
1992: .getEntityName());
1993: List helperValues = (List) valuesPerHelper.get(helperName);
1994: if (helperValues == null) {
1995: helperValues = new LinkedList();
1996: valuesPerHelper.put(helperName, helperValues);
1997: }
1998: helperValues.add(value);
1999: }
2000:
2001: boolean beganTransaction = false;
2002: int numberChanged = 0;
2003:
2004: try {
2005: // if there are multiple helpers and no transaction is active, begin one
2006: if (valuesPerHelper.size() > 1) {
2007: beganTransaction = TransactionUtil.begin();
2008: }
2009:
2010: Iterator helperIter = valuesPerHelper.entrySet().iterator();
2011: while (helperIter.hasNext()) {
2012: Map.Entry curEntry = (Map.Entry) helperIter.next();
2013: String helperName = (String) curEntry.getKey();
2014: GenericHelper helper = GenericHelperFactory
2015: .getHelper(helperName);
2016:
2017: if (doCacheClear) {
2018: this .clearAllCacheLinesByValue((List) curEntry
2019: .getValue());
2020: }
2021: numberChanged += helper.storeAll((List) curEntry
2022: .getValue());
2023: }
2024:
2025: // only commit the transaction if we started one...
2026: TransactionUtil.commit(beganTransaction);
2027: } catch (GenericEntityException e) {
2028: try {
2029: // only rollback the transaction if we started one...
2030: TransactionUtil.rollback(beganTransaction);
2031: } catch (GenericEntityException e2) {
2032: Debug
2033: .logError(
2034: "[GenericDelegator.storeAll] Could not rollback transaction: ",
2035: module);
2036: Debug.logError(e2, module);
2037: }
2038: // after rolling back, rethrow the exception
2039: throw e;
2040: }
2041:
2042: // Refresh the valueObjects to get the new version
2043: viter = values.iterator();
2044: while (viter.hasNext()) {
2045: GenericValue value = (GenericValue) viter.next();
2046: if (value.lockEnabled()) {
2047: refresh(value);
2048: }
2049: }
2050:
2051: return numberChanged;
2052: }
2053:
2054: /** Remove the Entities from the List from the persistent store.
2055: * <br>The List contains GenericEntity objects, can be either GenericPK or GenericValue.
2056: * <br>If a certain entity contains a complete primary key, the entity in the datasource corresponding
2057: * to that primary key will be removed, this is like a removeByPrimary Key.
2058: * <br>On the other hand, if a certain entity is an incomplete or non primary key,
2059: * if will behave like the removeByAnd method.
2060: * <br>These updates all happen in one transaction, so they will either all succeed or all fail,
2061: * if the data source supports transactions.
2062: *@param dummyPKs Collection of GenericEntity instances containing the entities or by and fields to remove
2063: *@return int representing number of rows effected by this operation
2064: */
2065: public int removeAll(List dummyPKs) throws GenericEntityException {
2066: return this .removeAll(dummyPKs, true);
2067: }
2068:
2069: /** Remove the Entities from the List from the persistent store.
2070: * <br>The List contains GenericEntity objects, can be either GenericPK or GenericValue.
2071: * <br>If a certain entity contains a complete primary key, the entity in the datasource corresponding
2072: * to that primary key will be removed, this is like a removeByPrimary Key.
2073: * <br>On the other hand, if a certain entity is an incomplete or non primary key,
2074: * if will behave like the removeByAnd method.
2075: * <br>These updates all happen in one transaction, so they will either all succeed or all fail,
2076: * if the data source supports transactions.
2077: *@param dummyPKs Collection of GenericEntity instances containing the entities or by and fields to remove
2078: *@param doCacheClear boolean that specifies whether or not to automatically clear cache entries related to this operation
2079: *@return int representing number of rows effected by this operation
2080: */
2081: public int removeAll(List dummyPKs, boolean doCacheClear)
2082: throws GenericEntityException {
2083: //TODO: add eca eval calls
2084: if (dummyPKs == null) {
2085: return 0;
2086: }
2087:
2088: // from the delegator level this is complicated because different GenericValue
2089: // objects in the list may correspond to different helpers
2090: HashMap valuesPerHelper = new HashMap();
2091: Iterator viter = dummyPKs.iterator();
2092:
2093: while (viter.hasNext()) {
2094: GenericEntity entity = (GenericEntity) viter.next();
2095: String helperName = this .getEntityHelperName(entity
2096: .getEntityName());
2097: Collection helperValues = (Collection) valuesPerHelper
2098: .get(helperName);
2099:
2100: if (helperValues == null) {
2101: helperValues = new LinkedList();
2102: valuesPerHelper.put(helperName, helperValues);
2103: }
2104: helperValues.add(entity);
2105: }
2106:
2107: boolean beganTransaction = false;
2108: int numRemoved = 0;
2109:
2110: try {
2111: // if there are multiple helpers and no transaction is active, begin one
2112: if (valuesPerHelper.size() > 1) {
2113: beganTransaction = TransactionUtil.begin();
2114: }
2115:
2116: Iterator helperIter = valuesPerHelper.entrySet().iterator();
2117: while (helperIter.hasNext()) {
2118: Map.Entry curEntry = (Map.Entry) helperIter.next();
2119: String helperName = (String) curEntry.getKey();
2120: GenericHelper helper = GenericHelperFactory
2121: .getHelper(helperName);
2122:
2123: if (doCacheClear) {
2124: this .clearAllCacheLinesByDummyPK((List) curEntry
2125: .getValue());
2126: }
2127:
2128: List helperDummyPKs = (List) curEntry.getValue();
2129: numRemoved += helper.removeAll(helperDummyPKs);
2130:
2131: // TODO: iterate through and store fact that it was removed
2132: Iterator helperDummyPKIter = helperDummyPKs.iterator();
2133: while (helperDummyPKIter.hasNext()) {
2134: GenericEntity dummyPK = (GenericEntity) helperDummyPKIter
2135: .next();
2136: this .saveEntitySyncRemoveInfo(dummyPK);
2137: }
2138: }
2139:
2140: // only commit the transaction if we started one...
2141: TransactionUtil.commit(beganTransaction);
2142: } catch (GenericEntityException e) {
2143: try {
2144: // only rollback the transaction if we started one...
2145: TransactionUtil.rollback(beganTransaction);
2146: } catch (GenericEntityException e2) {
2147: Debug
2148: .logError(
2149: "[GenericDelegator.removeAll] Could not rollback transaction: ",
2150: module);
2151: Debug.logError(e2, module);
2152: }
2153: // after rolling back, rethrow the exception
2154: throw e;
2155: }
2156:
2157: return numRemoved;
2158: }
2159:
2160: // ======================================
2161: // ======= Cache Related Methods ========
2162:
2163: /** This method is a shortcut to completely clear all entity engine caches.
2164: * For performance reasons this should not be called very often.
2165: */
2166: public void clearAllCaches() {
2167: this .clearAllCaches(true);
2168: }
2169:
2170: public void clearAllCaches(boolean distribute) {
2171: if (this .allCache != null)
2172: this .allCache.clear();
2173: if (this .andCache != null)
2174: this .andCache.clear();
2175: if (this .andCacheFieldSets != null)
2176: this .andCacheFieldSets.clear();
2177: if (this .primaryKeyCache != null)
2178: this .primaryKeyCache.clear();
2179:
2180: if (distribute && this .distributedCacheClear != null) {
2181: this .distributedCacheClear.clearAllCaches();
2182: }
2183: }
2184:
2185: /** Remove a CACHED Generic Entity (List) from the cache, either a PK, ByAnd, or All
2186: *@param entityName The Name of the Entity as defined in the entity XML file
2187: *@param fields The fields of the named entity to query by with their corresponging values
2188: */
2189: public void clearCacheLine(String entityName, Map fields) {
2190: // if no fields passed, do the all cache quickly and return
2191: if (fields == null && allCache != null) {
2192: allCache.remove(entityName);
2193: return;
2194: }
2195:
2196: ModelEntity entity = this .getModelEntity(entityName);
2197: if (entity == null) {
2198: throw new IllegalArgumentException(
2199: "[GenericDelegator.clearCacheLine] could not find entity for entityName: "
2200: + entityName);
2201: }
2202: //if never cached, then don't bother clearing
2203: if (entity.getNeverCache())
2204: return;
2205:
2206: GenericPK dummyPK = new GenericPK(entity, fields);
2207: this .clearCacheLineFlexible(dummyPK);
2208: }
2209:
2210: /** Remove a CACHED Generic Entity from the cache by its primary key.
2211: * Checks to see if the passed GenericPK is a complete primary key, if
2212: * it is then the cache line will be removed from the primaryKeyCache; if it
2213: * is NOT a complete primary key it will remove the cache line from the andCache.
2214: * If the fields map is empty, then the allCache for the entity will be cleared.
2215: *@param dummyPK The dummy primary key to clear by.
2216: */
2217: public void clearCacheLineFlexible(GenericEntity dummyPK) {
2218: this .clearCacheLineFlexible(dummyPK, true);
2219: }
2220:
2221: public void clearCacheLineFlexible(GenericEntity dummyPK,
2222: boolean distribute) {
2223: if (dummyPK != null) {
2224: //if never cached, then don't bother clearing
2225: if (dummyPK.getModelEntity().getNeverCache())
2226: return;
2227:
2228: // always auto clear the all cache too, since we know it's messed up in any case
2229: if (allCache != null) {
2230: allCache.remove(dummyPK.getEntityName());
2231: }
2232:
2233: // check to see if passed fields names exactly make the primary key...
2234: if (dummyPK.isPrimaryKey()) {
2235: // findByPrimaryKey
2236: if (primaryKeyCache != null) {
2237: primaryKeyCache.remove(dummyPK);
2238: }
2239: } else {
2240: if (dummyPK.size() > 0) {
2241: // findByAnd
2242: if (andCache != null) {
2243: andCache.remove(dummyPK);
2244: }
2245: }
2246: }
2247:
2248: if (distribute && this .distributedCacheClear != null) {
2249: this .distributedCacheClear
2250: .distributedClearCacheLineFlexible(dummyPK);
2251: }
2252: }
2253: }
2254:
2255: /** Remove a CACHED Generic Entity from the cache by its primary key, does NOT
2256: * check to see if the passed GenericPK is a complete primary key.
2257: * Also tries to clear the corresponding all cache entry.
2258: *@param primaryKey The primary key to clear by.
2259: */
2260: public void clearCacheLine(GenericPK primaryKey) {
2261: this .clearCacheLine(primaryKey, true);
2262: }
2263:
2264: public void clearCacheLine(GenericPK primaryKey, boolean distribute) {
2265: if (primaryKey == null)
2266: return;
2267:
2268: //if never cached, then don't bother clearing
2269: if (primaryKey.getModelEntity().getNeverCache())
2270: return;
2271:
2272: // always auto clear the all cache too, since we know it's messed up in any case
2273: if (allCache != null) {
2274: allCache.remove(primaryKey.getEntityName());
2275: }
2276:
2277: if (primaryKeyCache != null) {
2278: primaryKeyCache.remove(primaryKey);
2279: }
2280:
2281: if (distribute && this .distributedCacheClear != null) {
2282: this .distributedCacheClear
2283: .distributedClearCacheLine(primaryKey);
2284: }
2285: }
2286:
2287: /** Remove a CACHED GenericValue from as many caches as it can. Automatically
2288: * tries to remove entries from the all cache, the by primary key cache, and
2289: * the by and cache. This is the ONLY method that tries to clear automatically
2290: * from the by and cache.
2291: *@param value The GenericValue to clear by.
2292: */
2293: public void clearCacheLine(GenericValue value) {
2294: this .clearCacheLine(value, true);
2295: }
2296:
2297: public void clearCacheLine(GenericValue value, boolean distribute) {
2298: // 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...
2299: // for instance:
2300: // on create don't clear by primary cache (and won't clear original values because there won't be any)
2301: // on remove don't clear by and for new values, but do for original values
2302:
2303: // Debug.logInfo("running clearCacheLine for value: " + value + ", distribute: " + distribute, module);
2304: if (value == null)
2305: return;
2306:
2307: //if never cached, then don't bother clearing
2308: if (value.getModelEntity().getNeverCache())
2309: return;
2310:
2311: // always auto clear the all cache too, since we know it's messed up in any case
2312: if (allCache != null) {
2313: allCache.remove(value.getEntityName());
2314: }
2315:
2316: if (primaryKeyCache != null) {
2317: primaryKeyCache.remove(value.getPrimaryKey());
2318: }
2319:
2320: // now for the tricky part, automatically clearing from the by and cache
2321:
2322: // get a set of all field combination sets used in the by and cache for this entity
2323: Set fieldNameSets = (Set) andCacheFieldSets.get(value
2324: .getEntityName());
2325:
2326: if (fieldNameSets != null) {
2327: // note that if fieldNameSets is null then no by and caches have been
2328: // stored for this entity, so do nothing; ie only run this if not null
2329:
2330: // iterate through the list of field combination sets and do a cache clear
2331: // for each one using field values from this entity value object
2332: Iterator fieldNameSetIter = fieldNameSets.iterator();
2333:
2334: while (fieldNameSetIter.hasNext()) {
2335: Set fieldNameSet = (Set) fieldNameSetIter.next();
2336:
2337: // In this loop get the original values in addition to the
2338: // current values and clear the cache line with those values
2339: // too... This is necessary so that by and lists that currently
2340: // have the entity will be cleared in addition to the by and
2341: // lists that will have the entity
2342: // For this we will need to have the GenericValue object keep a
2343: // map of original values in addition to the "current" values.
2344: // That may have to be done when an entity is read from the
2345: // database and not when a put/set is done because a null value
2346: // is a perfectly valid original value. NOTE: the original value
2347: // map should be clear by default to denote that there was no
2348: // original value. When a GenericValue is created from a read
2349: // from the database only THEN should the original value map
2350: // be created and set to the same values that are put in the
2351: // normal field value map.
2352:
2353: Map originalFieldValues = null;
2354:
2355: if (value.isModified()
2356: && value.originalDbValuesAvailable()) {
2357: originalFieldValues = new HashMap();
2358: }
2359: Map fieldValues = new HashMap();
2360: Iterator fieldNameIter = fieldNameSet.iterator();
2361:
2362: while (fieldNameIter.hasNext()) {
2363: String fieldName = (String) fieldNameIter.next();
2364:
2365: fieldValues.put(fieldName, value.get(fieldName));
2366: if (originalFieldValues != null) {
2367: originalFieldValues.put(fieldName, value
2368: .getOriginalDbValue(fieldName));
2369: }
2370: }
2371:
2372: // now we have a map of values for this field set for this entity, so clear the by and line...
2373: GenericPK dummyPK = new GenericPK(value
2374: .getModelEntity(), fieldValues);
2375:
2376: andCache.remove(dummyPK);
2377:
2378: if (originalFieldValues != null
2379: && !originalFieldValues.equals(fieldValues)) {
2380: GenericPK dummyPKOriginal = new GenericPK(value
2381: .getModelEntity(), originalFieldValues);
2382:
2383: andCache.remove(dummyPKOriginal);
2384: }
2385: }
2386: }
2387:
2388: if (distribute && this .distributedCacheClear != null) {
2389: this .distributedCacheClear.distributedClearCacheLine(value);
2390: }
2391: }
2392:
2393: /** Gets a Set of Sets of fieldNames used in the by and cache for the given entityName */
2394: public Set getFieldNameSetsCopy(String entityName) {
2395: Set fieldNameSets = (Set) andCacheFieldSets.get(entityName);
2396:
2397: if (fieldNameSets == null)
2398: return null;
2399:
2400: // create a new container set and a copy of each entry set
2401: Set setsCopy = new TreeSet();
2402: Iterator fieldNameSetIter = fieldNameSets.iterator();
2403:
2404: while (fieldNameSetIter.hasNext()) {
2405: Set fieldNameSet = (Set) fieldNameSetIter.next();
2406:
2407: setsCopy.add(new TreeSet(fieldNameSet));
2408: }
2409: return setsCopy;
2410: }
2411:
2412: public void clearAllCacheLinesByDummyPK(Collection dummyPKs) {
2413: if (dummyPKs == null)
2414: return;
2415: Iterator iter = dummyPKs.iterator();
2416:
2417: while (iter.hasNext()) {
2418: GenericEntity entity = (GenericEntity) iter.next();
2419:
2420: this .clearCacheLineFlexible(entity);
2421: }
2422: }
2423:
2424: public void clearAllCacheLinesByValue(Collection values) {
2425: if (values == null)
2426: return;
2427: Iterator iter = values.iterator();
2428:
2429: while (iter.hasNext()) {
2430: GenericValue value = (GenericValue) iter.next();
2431:
2432: this .clearCacheLine(value);
2433: }
2434: }
2435:
2436: public GenericValue getFromPrimaryKeyCache(GenericPK primaryKey) {
2437: if (primaryKey == null)
2438: return null;
2439: return (GenericValue) primaryKeyCache.get(primaryKey);
2440: }
2441:
2442: public List getFromAllCache(String entityName) {
2443: if (entityName == null)
2444: return null;
2445: return (List) allCache.get(entityName);
2446: }
2447:
2448: public List getFromAndCache(String entityName, Map fields) {
2449: if (entityName == null || fields == null)
2450: return null;
2451: ModelEntity entity = this .getModelEntity(entityName);
2452:
2453: return getFromAndCache(entity, fields);
2454: }
2455:
2456: public List getFromAndCache(ModelEntity entity, Map fields) {
2457: if (entity == null || fields == null)
2458: return null;
2459: GenericPK tempPK = new GenericPK(entity, fields);
2460:
2461: if (tempPK == null)
2462: return null;
2463: return (List) andCache.get(tempPK);
2464: }
2465:
2466: public void putInPrimaryKeyCache(GenericPK primaryKey,
2467: GenericValue value) {
2468: if (primaryKey == null || value == null)
2469: return;
2470:
2471: if (value.getModelEntity().getNeverCache()) {
2472: Debug
2473: .logWarning(
2474: "Tried to put a value of the "
2475: + value.getEntityName()
2476: + " entity in the BY PRIMARY KEY cache but this entity has never-cache set to true, not caching.",
2477: module);
2478: return;
2479: }
2480:
2481: // before going into the cache, make this value immutable
2482: value.setImmutable();
2483: primaryKeyCache.put(primaryKey, value);
2484: }
2485:
2486: public void putAllInPrimaryKeyCache(List values) {
2487: if (values == null)
2488: return;
2489: Iterator iter = values.iterator();
2490: while (iter.hasNext()) {
2491: GenericValue value = (GenericValue) iter.next();
2492: this .putInPrimaryKeyCache(value.getPrimaryKey(), value);
2493: }
2494: }
2495:
2496: public void putInAllCache(String entityName, List values) {
2497: if (entityName == null || values == null)
2498: return;
2499: ModelEntity entity = this .getModelEntity(entityName);
2500: this .putInAllCache(entity, values);
2501: }
2502:
2503: public void putInAllCache(ModelEntity entity, List values) {
2504: if (entity == null || values == null)
2505: return;
2506:
2507: if (entity.getNeverCache()) {
2508: Debug
2509: .logWarning(
2510: "Tried to put values of the "
2511: + entity.getEntityName()
2512: + " entity in the ALL cache but this entity has never-cache set to true, not caching.",
2513: module);
2514: return;
2515: }
2516:
2517: // make the List and the values immutable so that the list can be returned directly from the cache without copying and still be safe
2518: Iterator valueIter = values.iterator();
2519: while (valueIter.hasNext()) {
2520: GenericEntity genericEntity = (GenericEntity) valueIter
2521: .next();
2522: genericEntity.setImmutable();
2523: }
2524: allCache.put(entity.getEntityName(), Collections
2525: .unmodifiableList(values));
2526: }
2527:
2528: public void putInAndCache(String entityName, Map fields, List values) {
2529: if (entityName == null || fields == null || values == null)
2530: return;
2531: ModelEntity entity = this .getModelEntity(entityName);
2532: putInAndCache(entity, fields, values);
2533: }
2534:
2535: public void putInAndCache(ModelEntity entity, Map fields,
2536: List values) {
2537: if (entity == null || fields == null || values == null)
2538: return;
2539:
2540: if (entity.getNeverCache()) {
2541: Debug
2542: .logWarning(
2543: "Tried to put values of the "
2544: + entity.getEntityName()
2545: + " entity in the BY AND cache but this entity has never-cache set to true, not caching.",
2546: module);
2547: return;
2548: }
2549:
2550: GenericPK tempPK = new GenericPK(entity, fields);
2551:
2552: if (tempPK == null)
2553: return;
2554:
2555: // make the List and the values immutable so that the list can be returned directly from the cache without copying and still be safe
2556: Iterator valueIter = values.iterator();
2557: while (valueIter.hasNext()) {
2558: GenericEntity genericEntity = (GenericEntity) valueIter
2559: .next();
2560: genericEntity.setImmutable();
2561: }
2562: andCache.put(tempPK, Collections.unmodifiableList(values));
2563:
2564: // now make sure the fieldName set used for this entry is in the
2565: // andCacheFieldSets Map which contains a Set of Sets of fieldNames for each entityName
2566: Set fieldNameSets = (Set) andCacheFieldSets.get(entity
2567: .getEntityName());
2568:
2569: if (fieldNameSets == null) {
2570: synchronized (this ) {
2571: fieldNameSets = (Set) andCacheFieldSets.get(entity
2572: .getEntityName());
2573: if (fieldNameSets == null) {
2574: // using a HashSet for both the individual fieldNameSets and
2575: // the set of fieldNameSets; this appears to be necessary
2576: // because TreeSet has bugs, or does not support, the compare
2577: // operation which is necessary when inserted a TreeSet
2578: // into a TreeSet.
2579: fieldNameSets = new HashSet();
2580: andCacheFieldSets.put(entity.getEntityName(),
2581: fieldNameSets);
2582: }
2583: }
2584: }
2585: fieldNameSets.add(new HashSet(fields.keySet()));
2586: }
2587:
2588: // ======= XML Related Methods ========
2589: public List readXmlDocument(URL url) throws SAXException,
2590: ParserConfigurationException, java.io.IOException {
2591: if (url == null)
2592: return null;
2593: return this .makeValues(UtilXml.readXmlDocument(url, false));
2594: }
2595:
2596: public List makeValues(Document document) {
2597: if (document == null)
2598: return null;
2599: List values = new LinkedList();
2600:
2601: Element docElement = document.getDocumentElement();
2602:
2603: if (docElement == null)
2604: return null;
2605: if (!"entity-engine-xml".equals(docElement.getTagName())) {
2606: Debug
2607: .logError(
2608: "[GenericDelegator.makeValues] Root node was not <entity-engine-xml>",
2609: module);
2610: throw new java.lang.IllegalArgumentException(
2611: "Root node was not <entity-engine-xml>");
2612: }
2613: docElement.normalize();
2614: Node curChild = docElement.getFirstChild();
2615:
2616: if (curChild != null) {
2617: do {
2618: if (curChild.getNodeType() == Node.ELEMENT_NODE) {
2619: Element element = (Element) curChild;
2620: GenericValue value = this .makeValue(element);
2621:
2622: if (value != null)
2623: values.add(value);
2624: }
2625: } while ((curChild = curChild.getNextSibling()) != null);
2626: } else {
2627: Debug
2628: .logWarning(
2629: "[GenericDelegator.makeValues] No child nodes found in document.",
2630: module);
2631: }
2632:
2633: return values;
2634: }
2635:
2636: public GenericPK makePK(Element element) {
2637: GenericValue value = makeValue(element);
2638:
2639: return value.getPrimaryKey();
2640: }
2641:
2642: public GenericValue makeValue(Element element) {
2643: if (element == null)
2644: return null;
2645: String entityName = element.getTagName();
2646:
2647: // if a dash or colon is in the tag name, grab what is after it
2648: if (entityName.indexOf('-') > 0)
2649: entityName = entityName
2650: .substring(entityName.indexOf('-') + 1);
2651: if (entityName.indexOf(':') > 0)
2652: entityName = entityName
2653: .substring(entityName.indexOf(':') + 1);
2654: GenericValue value = this .makeValue(entityName, null);
2655:
2656: ModelEntity modelEntity = value.getModelEntity();
2657:
2658: Iterator modelFields = modelEntity.getFieldsIterator();
2659:
2660: while (modelFields.hasNext()) {
2661: ModelField modelField = (ModelField) modelFields.next();
2662: String name = modelField.getName();
2663: String attr = element.getAttribute(name);
2664:
2665: if (attr != null && attr.length() > 0) {
2666: value.setString(name, attr);
2667: } else {
2668: // if no attribute try a subelement
2669: Element subElement = UtilXml.firstChildElement(element,
2670: name);
2671:
2672: if (subElement != null) {
2673: value.setString(name, UtilXml
2674: .elementValue(subElement));
2675: }
2676: }
2677: }
2678:
2679: return value;
2680: }
2681:
2682: // ======= Misc Methods ========
2683:
2684: protected Map getEcaEntityEventMap(String entityName) {
2685: if (this .entityEcaHandler == null)
2686: return null;
2687: Map ecaEventMap = this .entityEcaHandler
2688: .getEntityEventMap(entityName);
2689: //Debug.logWarning("for entityName " + entityName + " got ecaEventMap: " + ecaEventMap, module);
2690: return ecaEventMap;
2691: }
2692:
2693: protected void evalEcaRules(String event, String currentOperation,
2694: GenericEntity value, Map eventMap, boolean noEventMapFound,
2695: boolean isError) throws GenericEntityException {
2696: // if this is true then it means that the caller had looked for an event map but found none for this entity
2697: if (noEventMapFound)
2698: return;
2699: if (this .entityEcaHandler == null)
2700: return;
2701: //if (!"find".equals(currentOperation)) Debug.logWarning("evalRules for entity " + value.getEntityName() + ", currentOperation " + currentOperation + ", event " + event, module);
2702: this .entityEcaHandler.evalRules(currentOperation, eventMap,
2703: event, value, isError);
2704: }
2705:
2706: /** Get the next guaranteed unique seq id from the sequence with the given sequence name;
2707: * if the named sequence doesn't exist, it will be created
2708: *@param seqName The name of the sequence to get the next seq id from
2709: *@return Long with the next seq id for the given sequence name
2710: */
2711: public Long getNextSeqId(String seqName) {
2712: return this .getNextSeqId(seqName, 1);
2713: }
2714:
2715: /** Get the next guaranteed unique seq id from the sequence with the given sequence name;
2716: * if the named sequence doesn't exist, it will be created
2717: *@param seqName The name of the sequence to get the next seq id from
2718: *@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
2719: *@return Long with the next seq id for the given sequence name
2720: */
2721: public Long getNextSeqId(String seqName, long staggerMax) {
2722: if (sequencer == null) {
2723: synchronized (this ) {
2724: if (sequencer == null) {
2725: String helperName = this
2726: .getEntityHelperName("SequenceValueItem");
2727: ModelEntity seqEntity = this
2728: .getModelEntity("SequenceValueItem");
2729: sequencer = new SequenceUtil(helperName, seqEntity,
2730: "seqName", "seqId");
2731: }
2732: }
2733: }
2734: if (sequencer != null) {
2735: return sequencer.getNextSeqId(seqName, staggerMax);
2736: } else {
2737: return null;
2738: }
2739: }
2740:
2741: /** Allows you to pass a SequenceUtil class (possibly one that overrides the getNextSeqId method);
2742: * if null is passed will effectively refresh the sequencer. */
2743: public void setSequencer(SequenceUtil sequencer) {
2744: this .sequencer = sequencer;
2745: }
2746:
2747: /** Refreshes the ID sequencer clearing all cached bank values. */
2748: public void refreshSequencer() {
2749: this .sequencer = null;
2750: }
2751:
2752: protected void absorbList(List lst) {
2753: if (lst == null)
2754: return;
2755: Iterator iter = lst.iterator();
2756:
2757: while (iter.hasNext()) {
2758: GenericValue value = (GenericValue) iter.next();
2759:
2760: value.setDelegator(this );
2761: }
2762: }
2763:
2764: public UtilCache getPrimaryKeyCache() {
2765: return primaryKeyCache;
2766: }
2767:
2768: public UtilCache getAndCache() {
2769: return andCache;
2770: }
2771:
2772: public UtilCache getAllCache() {
2773: return allCache;
2774: }
2775: }
|