0001: /*
0002: Copyright (C) 2007 Mobixess Inc. http://www.java-objects-database.com
0003:
0004: This file is part of the JODB (Java Objects Database) open source project.
0005:
0006: JODB is free software; you can redistribute it and/or modify it under
0007: the terms of version 2 of the GNU General Public License as published
0008: by the Free Software Foundation.
0009:
0010: JODB is distributed in the hope that it will be useful, but WITHOUT ANY
0011: WARRANTY; without even the implied warranty of MERCHANTABILITY or
0012: FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
0013: for more details.
0014:
0015: You should have received a copy of the GNU General Public License along
0016: with this program; if not, write to the Free Software Foundation, Inc.,
0017: 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
0018: */
0019: package com.mobixess.jodb.core.query;
0020:
0021: import java.io.IOException;
0022: import java.io.ObjectStreamException;
0023: import java.io.Serializable;
0024: import java.lang.ref.WeakReference;
0025: import java.lang.reflect.Field;
0026: import java.util.Collection;
0027: import java.util.Enumeration;
0028: import java.util.HashMap;
0029: import java.util.HashSet;
0030: import java.util.Hashtable;
0031: import java.util.Iterator;
0032: import java.util.Vector;
0033:
0034: import com.mobixess.jodb.core.IllegalClassTypeException;
0035: import com.mobixess.jodb.core.JODBConfig;
0036: import com.mobixess.jodb.core.JodbIOException;
0037: import com.mobixess.jodb.core.JODBConstants.COMPARE_RESULT;
0038: import com.mobixess.jodb.core.index.IndexDataIterator;
0039: import com.mobixess.jodb.core.index.JODBIndexingAgent;
0040: import com.mobixess.jodb.core.index.JODBIndexingRootAgent;
0041: import com.mobixess.jodb.core.io.IOBase;
0042: import com.mobixess.jodb.core.io.IOTicket;
0043: import com.mobixess.jodb.core.io.JODBOperationContext;
0044: import com.mobixess.jodb.core.io.ObjectDataContainer;
0045: import com.mobixess.jodb.core.io.ObjectDataContainer.FIELD_CATEGORIES;
0046: import com.mobixess.jodb.core.io.ObjectDataContainer.FieldRecord;
0047: import com.mobixess.jodb.core.io.ObjectDataContainer.FieldsIterator;
0048: import com.mobixess.jodb.core.plugin.IClassProcessor;
0049: import com.mobixess.jodb.core.plugin.JODBPluginRegistry;
0050: import com.mobixess.jodb.core.query.SortDataCache.SortNodeRecord;
0051: import com.mobixess.jodb.core.transaction.JODBQueryList;
0052: import com.mobixess.jodb.core.transaction.JODBSession;
0053: import com.mobixess.jodb.core.transaction.TransactionUtils;
0054: import com.mobixess.jodb.core.transaction.JODBSession.ClassDescriptor;
0055: import com.mobixess.jodb.core.transaction.JODBSession.FieldAndIDRecord;
0056: import com.mobixess.jodb.core.transaction.TransactionUtils.DataContainersCache;
0057: import com.mobixess.jodb.soda.api.Constraint;
0058: import com.mobixess.jodb.soda.api.Constraints;
0059: import com.mobixess.jodb.soda.api.Evaluation;
0060: import com.mobixess.jodb.soda.api.ObjectSet;
0061: import com.mobixess.jodb.soda.api.Query;
0062: import com.mobixess.jodb.util.ArrayUtils;
0063: import com.mobixess.jodb.util.LongVector;
0064: import com.mobixess.jodb.util.PrimitiveJavaTypesUtil;
0065: import com.mobixess.jodb.util.PrimitiveJavaTypesUtil.PRIMITIVES_ENUMERATION;
0066:
0067: public class QueryNode implements Query, Serializable {
0068:
0069: /**
0070: *
0071: */
0072: private static final long serialVersionUID = 1L;
0073:
0074: private String _name;
0075: private transient JODBSession _session;
0076: private Hashtable<String, QueryNode> _descendants = new Hashtable<String, QueryNode>();//TODO HashMap???
0077:
0078: //private static enum CONSTRAINT_SUBJECT{CLASS_TYPE, EXAMPLE_OBJECT, COMPARISON_OBJECT, EVALUATION};
0079: private static enum QUERY_SORTING_TYPE {
0080: NONE, ASCENDING, DESCENDING
0081: };
0082:
0083: private static enum CONSTRAINT_EVALUATION_STATUS {
0084: UNKNOWN, ACCEPTED, REJECTED, EXCLUDED
0085: };
0086:
0087: private static enum CONSTRAINT_TYPE {
0088: CONTAINS, EQUAL, GREATER, SMALLER, NOT, LIKE, IDENTITY
0089: };
0090:
0091: private ConstraintsImpl _constraints = new ConstraintsImpl();
0092: private QueryNode _masterNode;
0093: private int _masterNodeSortCounter;
0094: private static HashSet<Object> _defaultByExampleIgnore;
0095:
0096: private transient ThreadLocal<ThreadLocalAuxDataHolder> _threadLocalAuxData;
0097:
0098: static {
0099: _defaultByExampleIgnore = new HashSet<Object>();
0100: PRIMITIVES_ENUMERATION[] primitivesEnum = PRIMITIVES_ENUMERATION
0101: .values();
0102: _defaultByExampleIgnore.add(null);
0103: for (int i = 0; i < primitivesEnum.length; i++) {
0104: try {
0105: Object wrapper = PrimitiveJavaTypesUtil
0106: .getDefaultWrapperInstance(primitivesEnum[i]);
0107: _defaultByExampleIgnore.add(wrapper);
0108: } catch (JodbIOException e) {
0109: throw new Error(e);
0110: }
0111: }
0112: }
0113:
0114: public QueryNode() {
0115: initThreadLocalData();
0116: }
0117:
0118: private void initThreadLocalData() {
0119: _threadLocalAuxData = new ThreadLocal<ThreadLocalAuxDataHolder>() {
0120: @Override
0121: protected ThreadLocalAuxDataHolder initialValue() {
0122: return new ThreadLocalAuxDataHolder();
0123: }
0124: };
0125: }
0126:
0127: public QueryNode(String name, JODBSession session,
0128: QueryNode masterNode) {
0129: this ();
0130: _name = name;
0131: _session = session;
0132: setMasterNode(masterNode);
0133: }
0134:
0135: public QueryNode(Object pattern, Collection defaultIgnoreValues,
0136: JODBSession session, QueryNode masterNode) {
0137: this ();
0138: _name = "";
0139: _session = session;
0140: assembleForPattern(pattern, defaultIgnoreValues);
0141: setMasterNode(masterNode);
0142: }
0143:
0144: public Object readResolve() throws ObjectStreamException {
0145: initThreadLocalData();
0146: return this ;
0147: }
0148:
0149: private void setMasterNode(QueryNode masterNode) {
0150: if (masterNode == null) {
0151: _masterNode = this ;
0152: } else {
0153: _masterNode = masterNode;
0154: }
0155: }
0156:
0157: public void setSession(JODBSession session) {
0158: _session = session;
0159: _constraints.updateSession(session);
0160: Iterator<QueryNode> iterator = _descendants.values().iterator();
0161: while (iterator.hasNext()) {
0162: QueryNode descendant = iterator.next();
0163: descendant.setSession(session);
0164: }
0165: }
0166:
0167: public JODBSession getSession() {
0168: return _session;
0169: }
0170:
0171: public Constraint constrain(Object constraint) {
0172: return _constraints.addConsraint(constraint);
0173: }
0174:
0175: public Constraints constraints() {
0176: return _constraints;
0177: }
0178:
0179: public Query descend(String fieldName) {
0180: synchronized (_descendants) {
0181: QueryNode descendant = _descendants.get(fieldName);
0182: if (descendant == null) {
0183: descendant = new QueryNode(fieldName, _session,
0184: _masterNode);
0185: }
0186: _descendants.put(fieldName, descendant);
0187: return descendant;
0188: }
0189: }
0190:
0191: public int getNextMasterNodeSortCounter() {
0192: return _masterNodeSortCounter++;
0193: }
0194:
0195: public ObjectSet execute() throws IOException,
0196: IllegalClassTypeException {
0197: IOBase base = _session.getBase();
0198: return base.executeQuery(this );
0199: }
0200:
0201: public JODBQueryList runQuery() throws IOException,
0202: IllegalClassTypeException {
0203: return runQuery(null, null);
0204: }
0205:
0206: public JODBQueryList runQuery(LongVector excludedObjects,
0207: LongVector dynamicLongArray) throws IOException,
0208: IllegalClassTypeException {
0209: IOBase base = _session.getBase();
0210: IOTicket ticket = base.getIOTicket(true, false);
0211: SortDataCache sortDataCache = new SortDataCache();
0212: initSortDataCache(sortDataCache, new StringBuffer());
0213: if (sortDataCache.getSortNodesCacheSize() > 0) {
0214: sortDataCache.setValuesAccumulationMode();
0215: } else {
0216: sortDataCache.clearAll();
0217: sortDataCache = null;
0218: }
0219: JODBOperationContext context = new JODBOperationContext(
0220: _session, ticket, sortDataCache, null, null,
0221: excludedObjects, true);
0222: IndexDataIterator indexIterator = null;
0223: boolean skipConventionalSorting = false;
0224:
0225: FieldRecord indexDataIteratorFieldRecord = null;//used for iteraion through indexed data
0226: QueryNode indexedNode = null;
0227: TypeConstraint typeConstraint = null;
0228: try {
0229:
0230: Vector<ConstraintBase> vectorOfConstraints = _constraints._constraints;
0231: for (int i = 0; i < vectorOfConstraints.size(); i++) {
0232: ConstraintBase nextCandidate = vectorOfConstraints
0233: .elementAt(i);
0234: if (nextCandidate instanceof TypeConstraint) {
0235: if (typeConstraint == null) {
0236: typeConstraint = (TypeConstraint) nextCandidate;
0237: } else {
0238: typeConstraint = null;//multiple type constraints
0239: break;
0240: }
0241: }
0242: }
0243:
0244: if (typeConstraint != null) {
0245: //boolean useIndexDataFromIterator = false;
0246: JODBIndexingRootAgent indexingRootAgent = _session
0247: .getIndexingRootAgent();
0248: try {
0249: ClassDescriptor classDescriptor = _session
0250: .getDescriptorForClass((Class) typeConstraint
0251: .getObject());
0252: JODBIndexingAgent indexingAgent = null;
0253: if (sortDataCache != null) {
0254: //lookup indexing data to optimize query
0255: SortNodeRecord[] sortRecords = sortDataCache
0256: .getSortNodes();
0257: int fieldId = classDescriptor
0258: .getFieldIDForName(sortRecords[0]._fullPath);
0259: if (fieldId != -1) {
0260: indexingAgent = indexingRootAgent
0261: .getIndexingAgent(fieldId, base);
0262: if (indexingAgent != null) {
0263: indexIterator = indexingAgent
0264: .getIndexIterator(sortRecords[0]._orderAscending);
0265: indexedNode = _descendants
0266: .get(sortRecords[0]._fullPath);
0267: skipConventionalSorting = sortRecords.length == 1;
0268: }
0269: }
0270: }
0271: if (indexIterator == null) {
0272: //search first index
0273: Iterator<String> descendants = _descendants
0274: .keySet().iterator();
0275: while (descendants.hasNext()
0276: && indexIterator == null) {
0277: String next = descendants.next();
0278: Field field = classDescriptor
0279: .getFieldForName(next);
0280: if (field == null) {
0281: continue;
0282: }
0283: indexingAgent = indexingRootAgent
0284: .getIndexingAgent(field, base);
0285: if (indexingAgent != null) {
0286: indexIterator = indexingAgent
0287: .getIndexIterator(true);
0288: indexedNode = _descendants.get(next);
0289: }
0290: }
0291: }
0292: if (indexingAgent != null && indexedNode != null) {
0293: Field field = classDescriptor.getFieldForID(
0294: indexingAgent.getFieldId(), null);
0295: Class fieldType = field.getType();
0296: if (fieldType.isPrimitive()) {
0297: indexDataIteratorFieldRecord = new FieldRecord();
0298: indexDataIteratorFieldRecord._fieldID = indexingAgent
0299: .getFieldId();
0300: indexDataIteratorFieldRecord._category = FIELD_CATEGORIES.PRIMITIVE;
0301: indexDataIteratorFieldRecord._fieldTypeID = base
0302: .getClassTypeSubstitutionID(fieldType
0303: .getName());
0304: }
0305: }
0306: } catch (IllegalClassTypeException e) {
0307: e.printStackTrace();
0308: }
0309: }
0310: if (indexIterator == null) {
0311: indexIterator = new LArrayIndexIterator(base
0312: .getForAllObjects(ticket));
0313: }
0314: //long[] allObjectIDs = base.getForAllObjects(ticket);
0315: Vector<long[]> acceptedIds = new Vector<long[]>();
0316: int totalAccepted = 0;
0317: final int acceptedChunkSize = 100;
0318: long[] currentChunk = new long[acceptedChunkSize];
0319: int indexInChunk = 0;
0320: while (indexIterator.hasNext()) {
0321: resetStateOfConstraints();
0322: CONSTRAINT_EVALUATION_STATUS status = CONSTRAINT_EVALUATION_STATUS.UNKNOWN;
0323: long nextObjectId;
0324: if (indexDataIteratorFieldRecord != null) {
0325: indexDataIteratorFieldRecord._primitiveRawDataBuffer
0326: .clear();
0327: nextObjectId = indexIterator
0328: .next(indexDataIteratorFieldRecord._primitiveRawDataBuffer);
0329: if (excludedObjects != null
0330: && excludedObjects
0331: .binarySearch(nextObjectId) >= 0) {
0332: continue;
0333: }
0334: if (_session.getObjectFromCache(nextObjectId) == null) {
0335: //do not analize active objects
0336: indexDataIteratorFieldRecord._primitiveRawDataBuffer
0337: .flip();
0338: if (sortDataCache != null) {
0339: sortDataCache.setCandidateID(nextObjectId);
0340: }
0341: indexedNode.analize(-1,
0342: indexDataIteratorFieldRecord, context);
0343: typeConstraint
0344: .setStatus(CONSTRAINT_EVALUATION_STATUS.ACCEPTED);
0345: _constraints.markExistanceConstrantAsAccepted();
0346: indexedNode._constraints
0347: .markExistanceConstrantAsAccepted();
0348: status = getCumulativeStatus();
0349: }
0350: } else {
0351: nextObjectId = indexIterator.next();
0352: if (excludedObjects != null
0353: && excludedObjects
0354: .binarySearch(nextObjectId) >= 0) {
0355: continue;
0356: }
0357: }
0358: if (status == CONSTRAINT_EVALUATION_STATUS.UNKNOWN) {
0359: if (sortDataCache != null) {
0360: sortDataCache.setCandidateID(nextObjectId);
0361: }
0362: status = analize(nextObjectId, context);
0363: }
0364: if (status == CONSTRAINT_EVALUATION_STATUS.EXCLUDED) {
0365: if (!context.isExcludedObjectId(nextObjectId)) {
0366: dynamicLongArray.addElement(nextObjectId);
0367: }
0368: continue;
0369: }
0370: if (status == CONSTRAINT_EVALUATION_STATUS.ACCEPTED) {
0371: if (indexInChunk == acceptedChunkSize) {
0372: acceptedIds.add(currentChunk);
0373: currentChunk = new long[acceptedChunkSize];
0374: indexInChunk = 0;
0375: }
0376: if (sortDataCache != null
0377: && JODBConfig.useCacheOnSortOperations()) {
0378: sortDataCache.acceptCandidate();
0379: }
0380: currentChunk[indexInChunk++] = nextObjectId;
0381: totalAccepted++;
0382: }
0383: }
0384: if (indexInChunk != 0) {
0385: acceptedIds.add(currentChunk);
0386: }
0387: long[] resultingOffsets = new long[totalAccepted];
0388: int remainingToCopy = totalAccepted;
0389: for (int i = 0; i < acceptedIds.size(); i++) {
0390: long[] chunk = acceptedIds.elementAt(i);
0391: int toCopy = Math.min(chunk.length, remainingToCopy);
0392: System.arraycopy(chunk, 0, resultingOffsets, i
0393: * acceptedChunkSize, toCopy);
0394: remainingToCopy -= toCopy;
0395: }
0396: if (!skipConventionalSorting) {
0397: handleSortInstructions(sortDataCache, context,
0398: resultingOffsets);
0399: }
0400: return new JODBQueryList(resultingOffsets, _session);
0401: } finally {
0402: if (sortDataCache != null) {
0403: sortDataCache.clearAll();
0404: }
0405: ticket.close();
0406: }
0407: }
0408:
0409: private void handleSortInstructions(SortDataCache sortDataCache,
0410: JODBOperationContext context, long[] items)
0411: throws IOException {
0412: if (sortDataCache == null) {
0413: return;
0414: }
0415: SortingDataProvider sortingDataProvider = new SortingDataProvider(
0416: sortDataCache, context, this );
0417: QueryUtils.quickQuerySort(items, sortingDataProvider,
0418: sortDataCache.getSortNodes());
0419: }
0420:
0421: private CONSTRAINT_EVALUATION_STATUS analize(long offset,
0422: JODBOperationContext context) throws IOException {
0423: Object activeObject = _session.getObjectFromCache(offset);
0424: if (activeObject != null && !context.isServerMode()) {
0425: return analize(activeObject, null, context);
0426: } else {
0427: return analize(offset, null, context);
0428: }
0429: }
0430:
0431: private CONSTRAINT_EVALUATION_STATUS analize(Object object,
0432: Field field, JODBOperationContext context)
0433: throws IOException {
0434: _constraints.evaluateActiveObject(object, field, context);
0435: if (field != null && field.getType().isPrimitive()) {
0436: return getCumulativeStatus();
0437: }
0438: if (field != null) {
0439: if (object != null) {
0440: try {
0441: object = field.get(object);
0442: } catch (Exception e) {
0443: e.printStackTrace();
0444: throw new JodbIOException(e);
0445: }
0446: }
0447: } else if (object == null) {
0448: return getCumulativeStatus();
0449: }
0450: ClassDescriptor classDescriptor;
0451: try {
0452: classDescriptor = _session
0453: .getDescriptorForClass(object != null ? object
0454: .getClass() : field.getType());
0455: } catch (IllegalClassTypeException e) {
0456: e.printStackTrace();//should never happen
0457: return CONSTRAINT_EVALUATION_STATUS.REJECTED;
0458: }
0459: Iterator<QueryNode> iterator = _descendants.values().iterator();
0460: while (iterator.hasNext()) {
0461: QueryNode descendant = iterator.next();
0462: Field descendantField = classDescriptor
0463: .getFieldForName(descendant._name);
0464: if (descendantField != null) {
0465: descendant.analize(object, descendantField, context);
0466: }
0467: }
0468: return getCumulativeStatus();
0469: }
0470:
0471: private CONSTRAINT_EVALUATION_STATUS analize(long objectOffset,
0472: FieldRecord fieldRecord, JODBOperationContext context)
0473: throws IOException {
0474: if (context.isServerMode()
0475: && context.isExcludedObjectId(objectOffset)) {
0476: _constraints
0477: .setStatus(CONSTRAINT_EVALUATION_STATUS.EXCLUDED);
0478: return CONSTRAINT_EVALUATION_STATUS.EXCLUDED;
0479: }
0480: ClassDescriptor classDescriptor = null;
0481: if (fieldRecord != null) {
0482: try {
0483: classDescriptor = _session
0484: .getDescriptorForClass(fieldRecord._fieldTypeID);
0485: } catch (Exception e) {
0486: e.printStackTrace();
0487: throw new JodbIOException(e);
0488: }
0489: if (fieldRecord._category == FIELD_CATEGORIES.PRIMITIVE) {
0490: _constraints.evaluatePersistentCopy(classDescriptor,
0491: null, fieldRecord, context);
0492: return getCumulativeStatus();
0493: }
0494: objectOffset = fieldRecord._objectOffset;
0495: } else {
0496: if (objectOffset <= 0) {
0497: throw new JodbIOException("illegal query state");
0498: }
0499: }
0500:
0501: if (objectOffset == 0) {
0502: _constraints.evaluatePersistentCopy(classDescriptor, null,
0503: null, context);
0504: return getCumulativeStatus();
0505: }
0506: DataContainersCache dataContainersCache = TransactionUtils
0507: .getObjectDataContainerCache();
0508: ObjectDataContainer dataContainer = dataContainersCache
0509: .pullObjectDataContainer();
0510: IOBase base = _session.getBase();
0511: IOTicket ticket = base.getIOTicket(true, true);
0512: try {//TODO need handling for arrays
0513: dataContainer.readObject(ticket.getRandomAccessBuffer(),
0514: base, context.getSession(), objectOffset, true);
0515: return analize(classDescriptor, dataContainer, context);
0516: } finally {
0517: TransactionUtils.getObjectDataContainerCache()
0518: .pushObjectDataContainer(dataContainer);
0519: ticket.close();
0520: }
0521: }
0522:
0523: private CONSTRAINT_EVALUATION_STATUS analize(
0524: ClassDescriptor classDescriptor,
0525: ObjectDataContainer dataContainer,
0526: JODBOperationContext context) throws IOException {
0527: FieldsIterator fieldsIterator = dataContainer
0528: .getActiveFieldsIterator();
0529: if (fieldsIterator == null) {
0530: return getCumulativeStatus();
0531: }
0532: //int[] hierarchy = dataContainer.getClassHierarchy();
0533: int typeID = dataContainer.getOriginalClassType();
0534: try {
0535: classDescriptor = _session.getDescriptorForClass(typeID);
0536: } catch (Exception e) {
0537: e.printStackTrace();
0538: throw new JodbIOException(e);
0539: }
0540: _constraints.evaluatePersistentCopy(classDescriptor,
0541: dataContainer, null, context);
0542: HashMap<String, Field> unProcessedDescendantFields = _threadLocalAuxData
0543: .get()._processedFieldsBuffer;
0544: unProcessedDescendantFields.clear();
0545: FieldAndIDRecord[] fields = classDescriptor.getFields();
0546: for (int i = 0; i < fields.length; i++) {
0547: String name = fields[i]._field.getName();
0548: if (_descendants.containsKey(name)) {
0549: unProcessedDescendantFields.put(name, fields[i]._field);
0550: }
0551: }
0552: FieldRecord record = dataContainer.getRecordCache();
0553: while (unProcessedDescendantFields.size() > 0
0554: && fieldsIterator.hasNext()) {
0555: fieldsIterator.next(record, context.getBase(), false);
0556: Field field = classDescriptor.getFieldForID(
0557: record._fieldID, null);
0558: String name = field.getName();
0559: QueryNode descendant = _descendants.get(name);
0560: if (descendant == null) {
0561: continue;
0562: }
0563: if (!unProcessedDescendantFields.containsKey(name)) {//TODO can only happen if private fields with same name exist
0564: continue;
0565: }
0566: descendant.analize(0, record, context);
0567: unProcessedDescendantFields.remove(name);
0568: }
0569:
0570: // TODO commented because iterrator now guarantee iterration through all field
0571: // Iterator<Field> remainingFields = unProcessedDescendantFields.values().iterator();
0572: // while(remainingFields.hasNext()){
0573: // Field field = remainingFields.next();
0574: // QueryNode descendant = _descendants.get(field.getName());
0575: // if(descendant == null){
0576: // continue;//TODO should never happen, print log???
0577: // }
0578: // descendant.analize(null,field, context);
0579: // }
0580:
0581: return getCumulativeStatus();
0582: }
0583:
0584: private void assembleForPattern(Object pattern,
0585: Collection defaultIgnoreValues) {
0586: ClassDescriptor classDescriptor;
0587: try {
0588: classDescriptor = _session.getDescriptorForClass(pattern
0589: .getClass());
0590: } catch (IllegalClassTypeException e) {
0591: //TODO print debug
0592: return;
0593: }
0594: constrain(pattern.getClass());
0595: FieldAndIDRecord[] fields = classDescriptor.getFields();
0596: for (int i = 0; i < fields.length; i++) {
0597: Field descendant = fields[i]._field;
0598: Object descendantValue;
0599: try {
0600: descendantValue = descendant.get(pattern);
0601: } catch (Exception e) {
0602: e.printStackTrace();
0603: continue;
0604: }
0605: if (defaultIgnoreValues.contains(descendantValue)) {
0606: continue;
0607: }
0608: Query descendantQuery = (QueryNode) descend(descendant
0609: .getName());
0610: descendantQuery.constrain(descendantValue);
0611: }
0612: return;
0613: }
0614:
0615: public CONSTRAINT_EVALUATION_STATUS getCumulativeStatus() {
0616: CONSTRAINT_EVALUATION_STATUS status = _constraints
0617: .getCumulativeStatus();
0618: if (status == CONSTRAINT_EVALUATION_STATUS.REJECTED) {
0619: return status;
0620: }
0621: int totalDescendants = _descendants.size();
0622: int totalAccepted = 0;
0623: Iterator<QueryNode> descendantsIterator = _descendants.values()
0624: .iterator();
0625: while (descendantsIterator.hasNext()) {
0626: CONSTRAINT_EVALUATION_STATUS descStatus = descendantsIterator
0627: .next().getCumulativeStatus();
0628: switch (descStatus) {
0629: case ACCEPTED:
0630: totalAccepted++;
0631: break;
0632: case REJECTED:
0633: case EXCLUDED:
0634: return descStatus;
0635: }
0636: }
0637: if (status == CONSTRAINT_EVALUATION_STATUS.ACCEPTED
0638: && totalDescendants == totalAccepted) {
0639: return CONSTRAINT_EVALUATION_STATUS.ACCEPTED;
0640: } else {
0641: return CONSTRAINT_EVALUATION_STATUS.UNKNOWN;
0642: }
0643: }
0644:
0645: public void markAsUnreachable() {
0646: _constraints.setStatus(CONSTRAINT_EVALUATION_STATUS.REJECTED);
0647: }
0648:
0649: public Query orderAscending() {
0650: _constraints.orderAscending();
0651: return this ;
0652: }
0653:
0654: public Query orderDescending() {
0655: _constraints.orderDescending();
0656: return this ;
0657: }
0658:
0659: public void resetStateOfConstraints() {
0660: _constraints.resetStatus();
0661: Iterator<QueryNode> iterator = _descendants.values().iterator();
0662: while (iterator.hasNext()) {
0663: QueryNode descendant = iterator.next();
0664: descendant.resetStateOfConstraints();
0665: }
0666: }
0667:
0668: public void refillSortData(long objectID,
0669: SortDataCache sortDataCache, JODBOperationContext context)
0670: throws IOException {
0671: sortDataCache.setCandidateID(objectID);
0672: if (!hasSortInstructions()) {
0673: return;
0674: }
0675: readSortData(objectID, sortDataCache, context);
0676: }
0677:
0678: private void readSortData(long objectID,
0679: SortDataCache sortDataCache, JODBOperationContext context)
0680: throws IOException {
0681: if (sortDataCache.isValuesAccumulationComplete()) {
0682: return;
0683: }
0684: Object activeObject = context.getSession().getObjectFromCache(
0685: objectID);
0686: if (activeObject != null) {
0687: readSortData(activeObject, null, sortDataCache, context);
0688: return;
0689: }
0690:
0691: IOBase base = context.getBase();
0692: DataContainersCache dataContainersCache = TransactionUtils
0693: .getObjectDataContainerCache();
0694: ObjectDataContainer dataContainer = dataContainersCache
0695: .pullObjectDataContainer();
0696: IOTicket ticket = context.getIoTicket();
0697: try {
0698: dataContainer.readObject(ticket.getRandomAccessBuffer(),
0699: base, context.getSession(), objectID, true);
0700: readSortData(dataContainer, (FieldRecord) null,
0701: sortDataCache, context);
0702: } finally {
0703: TransactionUtils.getObjectDataContainerCache()
0704: .pushObjectDataContainer(dataContainer);
0705: }
0706: }
0707:
0708: private void readSortData(Object activeObject, Field field,
0709: SortDataCache sortDataCache, JODBOperationContext context)
0710: throws JodbIOException {
0711: activeObject = _constraints.processSortValuesCache(
0712: activeObject, field, context);
0713: if (_descendants.isEmpty()
0714: && sortDataCache.isValuesAccumulationComplete()) {
0715: return;
0716: }
0717: if (activeObject != null) {
0718: Enumeration<QueryNode> descendants = _descendants
0719: .elements();
0720: while (descendants.hasMoreElements()) {
0721: QueryNode descendantQueryNode = descendants
0722: .nextElement();
0723: if (descendantQueryNode.hasSortInstructions()) {
0724: try {
0725: ClassDescriptor classDescriptor = context
0726: .getSession().getDescriptorForClass(
0727: activeObject.getClass());
0728: Field descendantField = classDescriptor
0729: .getFieldForName(descendantQueryNode._name);
0730: if (descendantField != null) {
0731: descendantQueryNode.readSortData(
0732: activeObject, descendantField,
0733: sortDataCache, context);
0734: }
0735: } catch (IllegalClassTypeException e) {
0736: // TODO Auto-generated catch block
0737: e.printStackTrace();
0738: }
0739: }
0740: }
0741: return;
0742: }
0743: }
0744:
0745: private void readSortData(ObjectDataContainer dataContainer,
0746: FieldRecord fieldRecord, SortDataCache sortDataCache,
0747: JODBOperationContext context) throws IOException {
0748: _constraints.processSortValuesCache(dataContainer, fieldRecord,
0749: context);
0750: if (_descendants.isEmpty()
0751: && sortDataCache.isValuesAccumulationComplete()) {
0752: return;
0753: }
0754: if (fieldRecord != null) {
0755: if (fieldRecord._category == FIELD_CATEGORIES.PRIMITIVE) {
0756: return;
0757: }
0758: long nextObjectID = fieldRecord._objectOffset;
0759: readSortData(nextObjectID, sortDataCache, context);
0760: return;
0761: } else {
0762: FieldsIterator fieldsIterator = dataContainer
0763: .getActiveFieldsIterator();
0764: if (fieldsIterator == null) {
0765: return;//TODO add warning?
0766: }
0767: FieldRecord iterratorFieldRecord = dataContainer
0768: .getRecordCache();
0769: IOBase base = context.getBase();
0770: while (fieldsIterator.hasNext()) {
0771: fieldsIterator.next(iterratorFieldRecord, context
0772: .getBase(), false);
0773: QueryNode descendant = _descendants
0774: .get(base
0775: .getSimpleFieldNameForID(iterratorFieldRecord._fieldID));
0776: if (descendant != null
0777: && descendant.hasSortInstructions()) {
0778: descendant.readSortData(null, iterratorFieldRecord,
0779: sortDataCache, context);
0780: }
0781: if (sortDataCache.isValuesAccumulationComplete()) {
0782: return;
0783: }
0784: }
0785: }
0786: }
0787:
0788: private boolean hasSortInstructions() {
0789: if (_constraints._sortingNodeId != -1) {
0790: return true;
0791: }
0792: return descendantsHaveSortInstructions();
0793: }
0794:
0795: private boolean descendantsHaveSortInstructions() {
0796: if (_descendants.isEmpty()) {
0797: return false;
0798: }
0799: Enumeration<QueryNode> descendants = _descendants.elements();
0800: while (descendants.hasMoreElements()) {
0801: QueryNode element = descendants.nextElement();
0802: if (element.hasSortInstructions()) {
0803: return true;
0804: }
0805: }
0806: return false;
0807: }
0808:
0809: public void initSortDataCache(SortDataCache sortDataCache,
0810: StringBuffer path) {
0811: _constraints.initSortDataCache(sortDataCache, path);
0812: Iterator<QueryNode> iterator = _descendants.values().iterator();
0813: int pathLen = path.length();
0814: while (iterator.hasNext()) {
0815: QueryNode descendant = iterator.next();
0816: if (path.length() != 0) {
0817: path.append('.');
0818: }
0819: path.append(descendant._name);
0820: descendant.initSortDataCache(sortDataCache, path);
0821: path.setLength(pathLen);
0822: }
0823: }
0824:
0825: private static class ThreadLocalAuxDataHolder {
0826: private HashMap<String, Field> _processedFieldsBuffer = new HashMap<String, Field>();
0827: }
0828:
0829: private class ConstraintsImpl extends ConstraintBase implements
0830: Constraints, Serializable {
0831: /**
0832: *
0833: */
0834: private static final long serialVersionUID = 1L;
0835: Vector<ConstraintBase> _constraints = new Vector<ConstraintBase>();
0836: QUERY_SORTING_TYPE _sortingType = QUERY_SORTING_TYPE.NONE;
0837: int _sortingNodeId = -1;
0838: private boolean _recursiveSatusRequest;
0839:
0840: public ConstraintsImpl() {
0841: _constraints.add(new ExistanceConstraint());
0842: }
0843:
0844: @Override
0845: public void resetStatus() {
0846: int len = _constraints.size();
0847: for (int i = 0; i < len; i++) {
0848: ConstraintBase constraint = _constraints.elementAt(i);
0849: if (constraint == this ) {
0850: continue;
0851: }
0852: constraint.resetStatus();
0853: }
0854: }
0855:
0856: @Override
0857: public void setStatus(CONSTRAINT_EVALUATION_STATUS newStatus) {
0858: int len = _constraints.size();
0859: for (int i = 0; i < len; i++) {
0860: ConstraintBase constraint = _constraints.elementAt(i);
0861: if (constraint == this ) {
0862: continue;
0863: }
0864: constraint.setStatus(newStatus);
0865: }
0866: }
0867:
0868: public void initSortDataCache(SortDataCache sortDataCache,
0869: StringBuffer path) {
0870: if (_sortingType != QUERY_SORTING_TYPE.NONE) {
0871: sortDataCache.addNode(_sortingNodeId, path.toString(),
0872: _sortingType == QUERY_SORTING_TYPE.ASCENDING);
0873: }
0874: }
0875:
0876: public void markExistanceConstrantAsAccepted() {
0877: int len = _constraints.size();
0878: for (int i = 0; i < len; i++) {
0879: ConstraintBase constraint = _constraints.elementAt(i);
0880: if (constraint == this ) {
0881: continue;
0882: }
0883: if (constraint instanceof ExistanceConstraint) {
0884: constraint
0885: .setStatus(CONSTRAINT_EVALUATION_STATUS.ACCEPTED);
0886: }
0887: }
0888: }
0889:
0890: public ConstraintBase addConsraint(Object constraint) {
0891: ConstraintBase result;
0892: if (constraint instanceof Class) {
0893: result = new TypeConstraint((Class) constraint);
0894: } else if (constraint instanceof Evaluation) {
0895: result = new EvaluationCallbackConstraint(
0896: (Evaluation) constraint);
0897: } else {
0898: Class constraintClass = constraint.getClass();
0899: if (constraint instanceof String
0900: || constraintClass.isArray()
0901: || PrimitiveJavaTypesUtil
0902: .isPrimitiveWrapper(constraintClass
0903: .getName())) {
0904: result = new ValueComparisonConstraint(constraint);
0905: } else {
0906: result = new QueryByExample(constraint,
0907: _defaultByExampleIgnore, _session);
0908: }
0909:
0910: }
0911: _constraints.add(result);
0912: return result;
0913: }
0914:
0915: @Override
0916: public CONSTRAINT_EVALUATION_STATUS getStatus() {
0917: return getCumulativeStatus();
0918: }
0919:
0920: @Override
0921: public CONSTRAINT_EVALUATION_STATUS getCumulativeStatus() {// statis calculated in accordance with AND operation for all contained constraints
0922: if (_recursiveSatusRequest || _constraints.size() == 0) {
0923: return CONSTRAINT_EVALUATION_STATUS.ACCEPTED;
0924: }
0925: _recursiveSatusRequest = true;
0926: try {
0927: int len = _constraints.size();
0928: int totalAccepted = 0;
0929: for (int i = 0; i < len; i++) {
0930: ConstraintBase constraint = _constraints
0931: .elementAt(i);
0932: if (constraint == this ) {
0933: continue;
0934: }
0935: if (constraint.getCumulativeStatus() == CONSTRAINT_EVALUATION_STATUS.REJECTED) {
0936: return CONSTRAINT_EVALUATION_STATUS.REJECTED;
0937: }
0938: if (constraint.getCumulativeStatus() == CONSTRAINT_EVALUATION_STATUS.ACCEPTED) {
0939: totalAccepted++;
0940: }
0941: }
0942: if (totalAccepted == len) {
0943: return CONSTRAINT_EVALUATION_STATUS.ACCEPTED;
0944: } else {
0945: return CONSTRAINT_EVALUATION_STATUS.UNKNOWN;
0946: }
0947: } finally {
0948: _recursiveSatusRequest = false;
0949: }
0950: }
0951:
0952: public Constraint[] toArray() {
0953: throw new RuntimeException("Not Implemented");
0954: //return null;
0955: }
0956:
0957: public Constraint and(Constraint with) {
0958: int len = _constraints.size();
0959: for (int i = 0; i < len; i++) {
0960: _constraints.elementAt(i).and(with);
0961: }
0962: return this ;
0963: }
0964:
0965: public Constraint contains() {
0966: int len = _constraints.size();
0967: for (int i = 0; i < len; i++) {
0968: _constraints.elementAt(i).contains();
0969: }
0970: return this ;
0971: }
0972:
0973: public Constraint equal() {
0974: int len = _constraints.size();
0975: for (int i = 0; i < len; i++) {
0976: _constraints.elementAt(i).equal();
0977: }
0978: return this ;
0979: }
0980:
0981: public Object getObject() {
0982: return null;//TODO check correctness
0983: }
0984:
0985: public Constraint greater() {
0986: int len = _constraints.size();
0987: for (int i = 0; i < len; i++) {
0988: _constraints.elementAt(i).greater();
0989: }
0990: return this ;
0991: }
0992:
0993: public Constraint identity() {
0994: int len = _constraints.size();
0995: for (int i = 0; i < len; i++) {
0996: _constraints.elementAt(i).identity();
0997: }
0998: return this ;
0999: }
1000:
1001: public Constraint like() {
1002: int len = _constraints.size();
1003: for (int i = 0; i < len; i++) {
1004: _constraints.elementAt(i).like();
1005: }
1006: return this ;
1007: }
1008:
1009: public Constraint not() {
1010: int len = _constraints.size();
1011: for (int i = 0; i < len; i++) {
1012: _constraints.elementAt(i).not();
1013: }
1014: return this ;
1015: }
1016:
1017: public Constraint or(Constraint with) {
1018: int len = _constraints.size();
1019: for (int i = 0; i < len; i++) {
1020: _constraints.elementAt(i).or(with);
1021: }
1022: return this ;
1023: }
1024:
1025: public Constraint smaller() {
1026: int len = _constraints.size();
1027: for (int i = 0; i < len; i++) {
1028: _constraints.elementAt(i).smaller();
1029: }
1030: return this ;
1031: }
1032:
1033: @Override
1034: void evaluateActiveObject(Object activeObject, Field field,
1035: JODBOperationContext context) throws IOException {
1036: int totalConstraints = _constraints.size();
1037: for (int i = 0; i < totalConstraints; i++) {
1038: _constraints.elementAt(i).evaluateActiveObject(
1039: activeObject, field, context);
1040: }
1041: if (JODBConfig.useCacheOnSortOperations()) {
1042: processSortValuesCache(activeObject, field, context);
1043: }
1044: }
1045:
1046: /**
1047: *
1048: * @param activeObject
1049: * @param field
1050: * @param context
1051: * @return active object for descendant analysis - can be result of extraction from 'field', original activeObject or null
1052: * @throws JodbIOException
1053: */
1054: private Object processSortValuesCache(Object activeObject,
1055: Field field, JODBOperationContext context)
1056: throws JodbIOException {
1057: if (_sortingNodeId == -1) {
1058: return activeObject;
1059: }
1060: if (field != null) {
1061: Class type = field.getType();
1062: if (type == String.class
1063: || type.isPrimitive()
1064: || PrimitiveJavaTypesUtil
1065: .isPrimitiveWrapper(type.getName())) {
1066: try {
1067: activeObject = field.get(activeObject);
1068: } catch (Exception e) {
1069: throw new JodbIOException(e);
1070: }
1071: } else {
1072: activeObject = null;
1073: }
1074: }
1075:
1076: if (activeObject != null
1077: && (activeObject instanceof String || PrimitiveJavaTypesUtil
1078: .isPrimitiveWrapper(activeObject.getClass()
1079: .getName()))) {
1080: SortDataCache sortDataCache = context
1081: .getSortDataCache();
1082: if (sortDataCache != null) {
1083: sortDataCache.addSortValue(_sortingNodeId,
1084: activeObject);
1085: }
1086: return null;
1087: }
1088: return activeObject;
1089: }
1090:
1091: @Override
1092: void evaluatePersistentCopy(ClassDescriptor classDescriptor,
1093: ObjectDataContainer dataContainer,
1094: FieldRecord primitiveRecord,
1095: JODBOperationContext context) throws IOException {
1096: int totalConstraints = _constraints.size();
1097: for (int i = 0; i < totalConstraints; i++) {
1098: _constraints.elementAt(i).evaluatePersistentCopy(
1099: classDescriptor, dataContainer,
1100: primitiveRecord, context);
1101: if (dataContainer != null && i < totalConstraints) {
1102: FieldsIterator fieldsIterator = dataContainer
1103: .getActiveFieldsIterator();
1104: if (fieldsIterator != null) {
1105: fieldsIterator.reset();
1106: }
1107: }
1108: }
1109: if (JODBConfig.useCacheOnSortOperations()) {
1110: processSortValuesCache(dataContainer, primitiveRecord,
1111: context);
1112: }
1113: }
1114:
1115: @Override
1116: void updateSession(JODBSession session) {
1117: int totalConstraints = _constraints.size();
1118: for (int i = 0; i < totalConstraints; i++) {
1119: _constraints.elementAt(i).updateSession(session);
1120: }
1121: }
1122:
1123: private void processSortValuesCache(
1124: ObjectDataContainer dataContainer,
1125: FieldRecord primitiveRecord,
1126: JODBOperationContext context) throws IOException {
1127: if (_sortingNodeId == -1) {
1128: return;
1129: }
1130: if (primitiveRecord != null) {
1131: SortDataCache sortDataCache = context
1132: .getSortDataCache();
1133: if (primitiveRecord._category == FIELD_CATEGORIES.PRIMITIVE) {
1134: if (sortDataCache != null) {
1135: PRIMITIVES_ENUMERATION fieldTypeEnum = PrimitiveJavaTypesUtil
1136: .getEnumeratedType(
1137: primitiveRecord._fieldTypeID,
1138: context.getBase());
1139: sortDataCache
1140: .addSortValue(
1141: _sortingNodeId,
1142: PrimitiveJavaTypesUtil
1143: .getAsWrappedPrimitive(
1144: fieldTypeEnum,
1145: primitiveRecord._primitiveRawDataBuffer));
1146: }
1147: } else if (primitiveRecord._fieldTypeName
1148: .equals(String.class.getName())) {
1149: Object value = TransactionUtils.launchObject(
1150: context.getSession(),
1151: primitiveRecord._objectOffset, null, 1);
1152: sortDataCache.addSortValue(_sortingNodeId, value);
1153: }
1154: return;
1155: }
1156: if (dataContainer != null) {
1157: Class persistentObjectClass;
1158: try {
1159: persistentObjectClass = context.getSession()
1160: .resolveClassForID(
1161: dataContainer
1162: .getOriginalClassType());
1163: } catch (ClassNotFoundException e) {
1164: //TODO debug output???
1165: throw new JodbIOException(e);
1166: }
1167:
1168: if (persistentObjectClass == String.class) {
1169: SortDataCache sortDataCache = context
1170: .getSortDataCache();
1171: if (sortDataCache != null) {
1172: Object value = TransactionUtils.launchObject(
1173: context.getSession(), dataContainer
1174: .getOffset(), null, 1);
1175: if (value != null && value instanceof String) {
1176: sortDataCache.addSortValue(_sortingNodeId,
1177: value);
1178: } else {
1179: System.err
1180: .println(" Warning internal state mismatch");//TODO add log
1181: }
1182: }
1183: }
1184: }
1185: }
1186:
1187: public void orderAscending() {
1188: _sortingType = QUERY_SORTING_TYPE.ASCENDING;
1189: setSortConstraintIndex();
1190: }
1191:
1192: public void orderDescending() {
1193: _sortingType = QUERY_SORTING_TYPE.DESCENDING;
1194: setSortConstraintIndex();
1195: }
1196:
1197: private void setSortConstraintIndex() {
1198: if (_sortingNodeId == -1) {
1199: _sortingNodeId = _masterNode
1200: .getNextMasterNodeSortCounter();
1201: }
1202: }
1203: }
1204:
1205: private static class ConstraintLink extends ConstraintBase {
1206: /**
1207: *
1208: */
1209: private static final long serialVersionUID = 1L;
1210: private boolean _linkTypeIsOr;
1211: private ConstraintBase _constraint1;
1212: private ConstraintBase _constraint2;
1213:
1214: /**
1215: * @param linkTypeIsOr
1216: * @param constraint1
1217: * @param constraint2
1218: */
1219: public ConstraintLink(boolean linkTypeIsOr,
1220: ConstraintBase constraint1, ConstraintBase constraint2) {
1221: _linkTypeIsOr = linkTypeIsOr;
1222: _constraint1 = constraint1;
1223: _constraint2 = constraint2;
1224: }
1225:
1226: @Override
1227: public CONSTRAINT_EVALUATION_STATUS getCumulativeStatus() {
1228: CONSTRAINT_EVALUATION_STATUS status1 = _constraint1
1229: .getStatus();
1230: CONSTRAINT_EVALUATION_STATUS status2 = _constraint2
1231: .getStatus();
1232: if (_linkTypeIsOr) {
1233: if (status1 == CONSTRAINT_EVALUATION_STATUS.ACCEPTED
1234: || status2 == CONSTRAINT_EVALUATION_STATUS.ACCEPTED) {
1235: return CONSTRAINT_EVALUATION_STATUS.ACCEPTED;
1236: }
1237: if (status1 == CONSTRAINT_EVALUATION_STATUS.UNKNOWN
1238: || status2 == CONSTRAINT_EVALUATION_STATUS.UNKNOWN) {
1239: return CONSTRAINT_EVALUATION_STATUS.UNKNOWN;
1240: }
1241: return CONSTRAINT_EVALUATION_STATUS.REJECTED;
1242: } else {
1243: if (status1 == CONSTRAINT_EVALUATION_STATUS.REJECTED
1244: || status2 == CONSTRAINT_EVALUATION_STATUS.REJECTED) {
1245: return CONSTRAINT_EVALUATION_STATUS.REJECTED;
1246: }
1247: if (status1 == CONSTRAINT_EVALUATION_STATUS.UNKNOWN
1248: || status2 == CONSTRAINT_EVALUATION_STATUS.UNKNOWN) {
1249: return CONSTRAINT_EVALUATION_STATUS.UNKNOWN;
1250: }
1251: return CONSTRAINT_EVALUATION_STATUS.ACCEPTED;
1252: }
1253: }
1254:
1255: public Constraint contains() {
1256: return this ;
1257: }
1258:
1259: public Constraint equal() {
1260: return this ;
1261: }
1262:
1263: public Object getObject() {
1264: return null;
1265: }
1266:
1267: public Constraint greater() {
1268: return this ;
1269: }
1270:
1271: public Constraint identity() {
1272: return this ;
1273: }
1274:
1275: public Constraint like() {
1276: return this ;
1277: }
1278:
1279: public Constraint not() {
1280: return this ;
1281: }
1282:
1283: public Constraint smaller() {
1284: return this ;
1285: }
1286:
1287: @Override
1288: void evaluateActiveObject(Object activeObject, Field field,
1289: JODBOperationContext context) {
1290: throw new RuntimeException("Not Implemented");
1291: //
1292: }
1293:
1294: @Override
1295: void evaluatePersistentCopy(ClassDescriptor classDescriptor,
1296: ObjectDataContainer dataContainer,
1297: FieldRecord primitiveRecord,
1298: JODBOperationContext context) {
1299: throw new RuntimeException("Not Implemented");
1300: //
1301: }
1302:
1303: }
1304:
1305: private class QueryByExample extends ValueComparisonConstraint {
1306:
1307: /**
1308: *
1309: */
1310: private static final long serialVersionUID = 1L;
1311: private QueryNode _queryNode;
1312:
1313: public QueryByExample(Object constraintOrigin,
1314: Collection defaultIgnoreValues, JODBSession session) {
1315: super (null);
1316: _queryNode = new QueryNode(constraintOrigin,
1317: defaultIgnoreValues, session, _masterNode);
1318: }
1319:
1320: @Override
1321: void evaluateActiveObject(Object activeObject, Field field,
1322: JODBOperationContext context) throws IOException {
1323: _queryNode.analize(activeObject, field, context);
1324: processEvaluationResult();
1325: }
1326:
1327: @Override
1328: void evaluatePersistentCopy(ClassDescriptor classDescriptor,
1329: ObjectDataContainer dataContainer, FieldRecord record,
1330: JODBOperationContext context) throws IOException {
1331: _queryNode.analize(classDescriptor, dataContainer, context);
1332: processEvaluationResult();
1333: }
1334:
1335: private void processEvaluationResult() {
1336: CONSTRAINT_EVALUATION_STATUS status = _queryNode
1337: .getCumulativeStatus();
1338: switch (_type) {
1339: case EQUAL:
1340: case LIKE:
1341: setStatus(status);
1342: break;
1343: case NOT:
1344: if (status == CONSTRAINT_EVALUATION_STATUS.ACCEPTED) {
1345: setStatus(CONSTRAINT_EVALUATION_STATUS.REJECTED);
1346: } else {
1347: setStatus(CONSTRAINT_EVALUATION_STATUS.ACCEPTED);
1348: }
1349: default:
1350: setStatus(CONSTRAINT_EVALUATION_STATUS.UNKNOWN);
1351: }
1352: }
1353:
1354: @Override
1355: public void resetStatus() {
1356: super .resetStatus();
1357: _queryNode._constraints.resetStatus();
1358: }
1359:
1360: @Override
1361: void updateSession(JODBSession session) {
1362: _queryNode.setSession(session);
1363: }
1364:
1365: // @Override
1366: // public CONSTRAINT_EVALUATION_STATUS getCumulativeStatus()
1367: // {
1368: // return _queryNode.getCumulativeStatus();
1369: // }
1370: //
1371: // @Override
1372: // public CONSTRAINT_EVALUATION_STATUS getStatus()
1373: // {
1374: // return getCumulativeStatus();
1375: // }
1376:
1377: }
1378:
1379: private static class ValueComparisonConstraint extends
1380: ConstraintBase {
1381:
1382: /**
1383: *
1384: */
1385: private static final long serialVersionUID = 1L;
1386: private Object _constraintOrigin;
1387: private transient WeakReference<Object> _translatedOrigin = new WeakReference<Object>(
1388: null);
1389: CONSTRAINT_TYPE _type = CONSTRAINT_TYPE.EQUAL;
1390:
1391: /**
1392: * @param constraintOrigin
1393: */
1394: public ValueComparisonConstraint(Object constraintOrigin) {
1395: super ();
1396: _constraintOrigin = constraintOrigin;
1397: }
1398:
1399: public Constraint contains() {
1400: _type = CONSTRAINT_TYPE.CONTAINS;
1401: return this ;
1402: }
1403:
1404: public Constraint equal() {
1405: _type = CONSTRAINT_TYPE.EQUAL;
1406: return this ;
1407: }
1408:
1409: public Object getObject() {
1410: return _constraintOrigin;
1411: }
1412:
1413: public Constraint greater() {
1414: _type = CONSTRAINT_TYPE.GREATER;
1415: return this ;
1416: }
1417:
1418: public Constraint identity() {
1419: _type = CONSTRAINT_TYPE.IDENTITY;
1420: return this ;
1421: }
1422:
1423: public Constraint like() {
1424: _type = CONSTRAINT_TYPE.LIKE;
1425: return this ;
1426: }
1427:
1428: public Constraint not() {
1429: _type = CONSTRAINT_TYPE.NOT;
1430: return this ;
1431: }
1432:
1433: public Constraint smaller() {
1434: _type = CONSTRAINT_TYPE.SMALLER;
1435: return this ;
1436: }
1437:
1438: Object getTranslatedOrigin() throws JodbIOException {
1439: Object result = null;
1440: if (_translatedOrigin != null) {
1441: result = _translatedOrigin.get();
1442: }
1443: if (result == null) {
1444: Class originClass = getObject().getClass();
1445: if (PrimitiveJavaTypesUtil
1446: .isPrimitiveWrapper(originClass.getName())) {
1447: return getObject();
1448: }
1449: IClassProcessor classProcessor = JODBPluginRegistry
1450: .getInstance().getClassProcessor(originClass);
1451: result = classProcessor.translate(getObject());
1452: _translatedOrigin = new WeakReference(result);
1453: }
1454: return result;
1455: }
1456:
1457: @Override
1458: void evaluateActiveObject(Object activeObject, Field field,
1459: JODBOperationContext context) throws IOException {
1460: Class originClass = getObject().getClass();
1461: if (field != null && field.getType().isPrimitive()) {
1462: COMPARE_RESULT compareResult;
1463: if (!PrimitiveJavaTypesUtil
1464: .isPrimitiveWrapper(originClass.getName())) {
1465: compareResult = COMPARE_RESULT.UNKNOWN;
1466: } else {
1467: compareResult = PrimitiveJavaTypesUtil.compare(
1468: _constraintOrigin, field, activeObject);
1469: }
1470: processCompareResult(compareResult);
1471: return;
1472: }
1473: if (field != null && activeObject != null) {
1474: try {
1475: activeObject = field.get(activeObject);
1476: } catch (Exception e) {
1477: e.printStackTrace();
1478: throw new JodbIOException(e);
1479: }
1480: }
1481: if (activeObject != null) {
1482: if (originClass != activeObject.getClass()) {
1483: processCompareResult(COMPARE_RESULT.UNKNOWN);
1484: return;
1485: }
1486: IClassProcessor processor = JODBPluginRegistry
1487: .getInstance().getClassProcessor(originClass);
1488: COMPARE_RESULT compareResult = processor.compare(
1489: getObject(), activeObject, context, null);
1490: processCompareResult(compareResult);
1491: return;
1492: }
1493: }
1494:
1495: /*package*/void processCompareResult(
1496: COMPARE_RESULT compareResult) throws JodbIOException {
1497: CONSTRAINT_EVALUATION_STATUS status = getStatusForCompareResult(
1498: compareResult, _type);
1499: setStatus(status);
1500: }
1501:
1502: private CONSTRAINT_EVALUATION_STATUS getStatusForCompareResult(
1503: COMPARE_RESULT compareResult, CONSTRAINT_TYPE type)
1504: throws JodbIOException {
1505: if (compareResult == COMPARE_RESULT.UNKNOWN) {
1506: return CONSTRAINT_EVALUATION_STATUS.REJECTED;
1507: }
1508: switch (type) {
1509: case EQUAL:
1510: case IDENTITY:
1511: case LIKE:
1512: if (compareResult == COMPARE_RESULT.EQUAL) {
1513: return CONSTRAINT_EVALUATION_STATUS.ACCEPTED;
1514: } else {
1515: return CONSTRAINT_EVALUATION_STATUS.REJECTED;
1516: }
1517: case GREATER:
1518: if (compareResult == COMPARE_RESULT.SMALLER) {
1519: return CONSTRAINT_EVALUATION_STATUS.ACCEPTED;
1520: } else {
1521: return CONSTRAINT_EVALUATION_STATUS.REJECTED;
1522: }
1523: case SMALLER:
1524: if (compareResult == COMPARE_RESULT.GREATER) {
1525: return CONSTRAINT_EVALUATION_STATUS.ACCEPTED;
1526: } else {
1527: return CONSTRAINT_EVALUATION_STATUS.REJECTED;
1528: }
1529: case NOT:
1530: if (compareResult != COMPARE_RESULT.EQUAL) {
1531: return CONSTRAINT_EVALUATION_STATUS.ACCEPTED;
1532: } else {
1533: return CONSTRAINT_EVALUATION_STATUS.REJECTED;
1534: }
1535: default:
1536: throw new JodbIOException();
1537: }
1538: }
1539:
1540: @Override
1541: void evaluatePersistentCopy(ClassDescriptor classDescriptor,
1542: ObjectDataContainer dataContainer, FieldRecord record,
1543: JODBOperationContext context) throws IOException {
1544: Class originClass = getObject().getClass();
1545: if (record != null
1546: && record._category == FIELD_CATEGORIES.PRIMITIVE) {
1547: COMPARE_RESULT compareResult;
1548: if (!PrimitiveJavaTypesUtil
1549: .isPrimitiveWrapper(originClass.getName())) {
1550: compareResult = COMPARE_RESULT.UNKNOWN;
1551: } else {
1552: PRIMITIVES_ENUMERATION fieldTypeEnum = PrimitiveJavaTypesUtil
1553: .getEnumeratedType(record._fieldTypeID,
1554: context.getBase());
1555: compareResult = PrimitiveJavaTypesUtil.compare(
1556: _constraintOrigin, record, fieldTypeEnum);
1557: }
1558: processCompareResult(compareResult);
1559: return;
1560: }
1561: if (dataContainer != null) {
1562: Class persistentObjectClass;
1563: try {
1564: persistentObjectClass = context.getSession()
1565: .resolveClassForID(
1566: dataContainer
1567: .getOriginalClassType());
1568: } catch (ClassNotFoundException e) {
1569: //TODO debug output???
1570: throw new JodbIOException(e);
1571: }
1572: if (originClass != persistentObjectClass) {
1573: processCompareResult(COMPARE_RESULT.UNKNOWN);
1574: return;
1575: }
1576: IClassProcessor processor = JODBPluginRegistry
1577: .getInstance().getClassProcessor(originClass);
1578: if (_type == CONSTRAINT_TYPE.EQUAL
1579: || _type == CONSTRAINT_TYPE.NOT) {//equals methods can be better optimized
1580: boolean equal = processor.equals(
1581: getTranslatedOrigin(), dataContainer,
1582: context, null);
1583: processCompareResult(equal ? COMPARE_RESULT.EQUAL
1584: : COMPARE_RESULT.SMALLER);
1585: return;
1586: } else {
1587: COMPARE_RESULT compareResult = processor.compare(
1588: getTranslatedOrigin(), dataContainer,
1589: context, null);
1590: processCompareResult(compareResult);
1591: return;
1592: }
1593:
1594: }
1595: }
1596: }
1597:
1598: private static class TypeConstraint extends
1599: ValueComparisonConstraint {
1600:
1601: /**
1602: *
1603: */
1604: private static final long serialVersionUID = 1L;
1605: int _constraintClassTypeID = -1;
1606:
1607: public TypeConstraint(Class constraintOrigin) {
1608: super (constraintOrigin);
1609: }
1610:
1611: @Override
1612: void evaluateActiveObject(Object activeObject, Field field,
1613: JODBOperationContext context) throws IOException {
1614: Class constaintClass = (Class) getObject();
1615: boolean isInstanceOf = false;
1616: if (field != null) {
1617: isInstanceOf = field.getType().isAssignableFrom(
1618: constaintClass);
1619: if (!isInstanceOf && activeObject != null) {
1620: try {
1621: activeObject = field.get(activeObject);
1622: } catch (Exception e) {
1623: e.printStackTrace();
1624: throw new JodbIOException(e);
1625: }
1626: }
1627: }
1628: if (!isInstanceOf) {
1629: if (activeObject != null) {
1630: isInstanceOf = constaintClass
1631: .isInstance(activeObject);
1632: } else {
1633: setStatus(CONSTRAINT_EVALUATION_STATUS.REJECTED);
1634: return;
1635: }
1636: }
1637:
1638: setStatus(evaluateObject(isInstanceOf, _type));
1639: }
1640:
1641: @Override
1642: public void resetStatus() {
1643: _constraintClassTypeID = -1;
1644: }
1645:
1646: private CONSTRAINT_EVALUATION_STATUS evaluateObject(
1647: boolean isInstanceOfConstraint, CONSTRAINT_TYPE type)
1648: throws JodbIOException {
1649: switch (type) {
1650: case EQUAL:
1651: case IDENTITY:
1652: case LIKE:
1653: if (isInstanceOfConstraint) {
1654: return CONSTRAINT_EVALUATION_STATUS.ACCEPTED;
1655: } else {
1656: return CONSTRAINT_EVALUATION_STATUS.REJECTED;
1657: }
1658: case GREATER:
1659: case SMALLER:
1660: return CONSTRAINT_EVALUATION_STATUS.REJECTED;
1661: case NOT:
1662: if (!isInstanceOfConstraint) {
1663: return CONSTRAINT_EVALUATION_STATUS.ACCEPTED;
1664: } else {
1665: return CONSTRAINT_EVALUATION_STATUS.REJECTED;
1666: }
1667: default:
1668: throw new JodbIOException();
1669: }
1670: }
1671:
1672: @Override
1673: void evaluatePersistentCopy(ClassDescriptor classDescriptor,
1674: ObjectDataContainer dataContainer, FieldRecord record,
1675: JODBOperationContext context) throws JodbIOException {
1676: setStatus(evaluatePersistentCopyForType(_type,
1677: classDescriptor, dataContainer, record, context
1678: .getSession()));
1679: }
1680:
1681: CONSTRAINT_EVALUATION_STATUS evaluatePersistentCopyForType(
1682: CONSTRAINT_TYPE type, ClassDescriptor classDescriptor,
1683: ObjectDataContainer dataContainer, FieldRecord record,
1684: JODBSession session) throws JodbIOException {
1685: boolean isInstanceOf;
1686: if (classDescriptor == null) {
1687: isInstanceOf = false;
1688: } else {
1689: String[] hierarchy = classDescriptor.getTypes();
1690: String className = ((Class) getObject()).getName();
1691: if (ArrayUtils.indexOf(hierarchy, className) == -1) {
1692: isInstanceOf = false;
1693: } else {
1694: isInstanceOf = true;
1695: }
1696: }
1697: return evaluateObject(isInstanceOf, type);
1698: }
1699:
1700: public int getConstraintClassTypeID(JODBSession session)
1701: throws JodbIOException {
1702: int result = _constraintClassTypeID;//precaution in case of multi threading
1703: if (result == -1) {
1704: result = session.getBase().getClassTypeSubstitutionID(
1705: ((Class) getObject()).getName());
1706: _constraintClassTypeID = result;
1707: }
1708: return result;
1709: }
1710: }
1711:
1712: /*private class ByExampleConstraint extends ValueComparisonConstraint{
1713:
1714: Field[] _fieldsToIgnore;
1715:
1716: public ByExampleConstraint(Object constraintOrigin) {
1717: super(constraintOrigin);
1718: Object translatedOrigin = getTranslatedOrigin();
1719: try {//TODO should have two copies of ignore fields for original object and translated
1720: ClassDescriptor classDescriptor = _session.getDescriptorForClass(translatedOrigin.getClass());
1721: Vector<Field> fieldsToIgnore = new Vector<Field>();
1722: Field[] fields = classDescriptor.getFields();
1723: for (int i = 0; i < fields.length; i++) {
1724: Field field = fields[i];
1725: Object val = field.get(translatedOrigin);
1726: if(val == null){
1727: fieldsToIgnore.add(field);
1728: continue;
1729: }
1730: Class type = field.getType();
1731: if(type.isPrimitive()){
1732: Object wrapperObj = PrimitiveJavaTypesUtil.getDefaultWrapperInstance(type.getName());
1733: if(val.equals( wrapperObj ) ){
1734: fieldsToIgnore.add(field);
1735: continue;
1736: }
1737: }
1738: }
1739: _fieldsToIgnore = new Field[fieldsToIgnore.size()];
1740: _fieldsToIgnore = fieldsToIgnore.toArray(_fieldsToIgnore);
1741: } catch (Exception e) {
1742: e.printStackTrace();
1743: _fieldsToIgnore = new Field[0];
1744: processCompareResult(COMPARE_RESULT.UNKNOWN);
1745: }
1746:
1747: }
1748:
1749: @Override
1750: void evaluateActiveObject(Object activeObject, Field field, JODBOperationContext context) throws IOException
1751: {
1752: if(field!=null && activeObject!=null){
1753: try {
1754: activeObject = field.get(activeObject);
1755: } catch (Exception e) {
1756: throw new IOException(e.getMessage());
1757: }
1758: }
1759: if(activeObject!=null){
1760: Object byExapleConstraint = getObject();
1761: if(activeObject.getClass()!=byExapleConstraint.getClass()){
1762: processCompareResult(COMPARE_RESULT.GREATER);
1763: return;
1764: }
1765: IClassProcessor processor = JODBPluginRegistry.getInstance().getClassProcessor(byExapleConstraint.getClass());
1766: COMPARE_RESULT compare_result = processor.compare(byExapleConstraint, activeObject, context, _fieldsToIgnore);
1767: processCompareResult(compare_result);
1768: }
1769: }
1770:
1771: @Override
1772: void evaluatePersistentCopy(ClassDescriptor classDescriptor, ObjectDataContainer dataContainer, FieldRecord record, JODBOperationContext context) throws IOException
1773: {
1774: if(record!=null){
1775: if(record._category == FIELD_CATEGORIES.PRIMITIVE){
1776: processCompareResult(COMPARE_RESULT.GREATER);
1777: return;
1778: }
1779: }
1780: if(dataContainer!=null){
1781: // Class originClass = getObject().getClass();
1782: // Class persistentObjectClass;
1783: // try {
1784: // persistentObjectClass = context.getSession().resolveClassForID(dataContainer.getOriginalClassType());
1785: // } catch (ClassNotFoundException e) {
1786: // //TODO debug output???
1787: // throw new IOException(e.getMessage());
1788: // }
1789: // if(originClass!=persistentObjectClass){
1790: // processCompareResult(COMPARE_RESULT.UNKNOWN);
1791: // return;
1792: // }
1793:
1794: Object byExapleConstraint = getObject();
1795: if(classDescriptor.getType()!=byExapleConstraint.getClass()){
1796: processCompareResult(COMPARE_RESULT.GREATER);
1797: return;
1798: }
1799:
1800: IClassProcessor processor = JODBPluginRegistry.getInstance().getClassProcessor(byExapleConstraint.getClass());
1801: if(_type == CONSTRAINT_TYPE.EQUAL || _type == CONSTRAINT_TYPE.NOT){//equals methods can be better optimized
1802: boolean equal = processor.equals(getTranslatedOrigin(), dataContainer, context, _fieldsToIgnore);
1803: processCompareResult(equal? COMPARE_RESULT.EQUAL : COMPARE_RESULT.SMALLER);
1804: return;
1805: }else{
1806: COMPARE_RESULT compareResult = processor.compare(getTranslatedOrigin(), dataContainer, context, _fieldsToIgnore);
1807: processCompareResult(compareResult);
1808: return;
1809: }
1810: }
1811: }
1812:
1813: }*/
1814:
1815: private static class EvaluationCallbackConstraint extends
1816: ValueComparisonConstraint {
1817:
1818: private ThreadLocal<CandidateImpl> _candidateImpl = new ThreadLocal<CandidateImpl>() {
1819: @Override
1820: protected CandidateImpl initialValue() {
1821: return new CandidateImpl();
1822: }
1823: };
1824:
1825: public EvaluationCallbackConstraint(Evaluation constraintOrigin) {
1826: super (constraintOrigin);
1827: }
1828:
1829: @Override
1830: void evaluateActiveObject(Object activeObject, Field field,
1831: JODBOperationContext context) throws IOException {
1832: if (field != null && activeObject != null) {
1833: try {
1834: activeObject = field.get(activeObject);
1835: } catch (Exception e) {
1836: throw new JodbIOException(e);
1837: }
1838: }
1839: if (activeObject != null) {
1840: Evaluation evaluation = (Evaluation) getObject();
1841: CandidateImpl candidateImpl = _candidateImpl.get();
1842: candidateImpl.init(activeObject);
1843: evaluation.evaluate(candidateImpl);
1844: if (candidateImpl.isInclude()) {
1845: processCompareResult(COMPARE_RESULT.EQUAL);
1846: } else {
1847: processCompareResult(COMPARE_RESULT.SMALLER);
1848: }
1849: }
1850: }
1851:
1852: @Override
1853: void evaluatePersistentCopy(ClassDescriptor classDescriptor,
1854: ObjectDataContainer dataContainer, FieldRecord record,
1855: JODBOperationContext context) throws IOException {
1856: if (record != null
1857: && record._category == FIELD_CATEGORIES.PRIMITIVE) {
1858: PRIMITIVES_ENUMERATION fieldTypeEnum = PrimitiveJavaTypesUtil
1859: .getEnumeratedType(record._fieldTypeID, context
1860: .getBase());
1861: Object obj = PrimitiveJavaTypesUtil
1862: .getAsWrappedPrimitive(fieldTypeEnum,
1863: record._primitiveRawDataBuffer);
1864: evaluateActiveObject(obj, null, context);
1865: return;
1866: }
1867: if (dataContainer != null) {
1868: Evaluation evaluation = (Evaluation) getObject();
1869: int activationDepth = evaluation.getActivationDepth() >= 0 ? evaluation
1870: .getActivationDepth()
1871: : JODBConfig.getDefaultActivationDepth();
1872: Object obj = context.getSession().getObjectForOffset(
1873: dataContainer.getOffset(), activationDepth);
1874: evaluateActiveObject(obj, null, context);
1875: return;
1876: }
1877: }
1878:
1879: }
1880:
1881: /**
1882: * Constraint to ensure that field actually exists
1883: *
1884: * @author Mobixess
1885: *
1886: */
1887: private static class ExistanceConstraint extends ConstraintBase {
1888:
1889: /**
1890: *
1891: */
1892: private static final long serialVersionUID = 1L;
1893:
1894: @Override
1895: void evaluateActiveObject(Object activeObject, Field field,
1896: JODBOperationContext context) throws IOException {
1897: setStatus(CONSTRAINT_EVALUATION_STATUS.ACCEPTED);
1898: }
1899:
1900: @Override
1901: void evaluatePersistentCopy(ClassDescriptor classDescriptor,
1902: ObjectDataContainer dataContainer,
1903: FieldRecord primitiveRecord,
1904: JODBOperationContext context) throws IOException {
1905: setStatus(CONSTRAINT_EVALUATION_STATUS.ACCEPTED);
1906: }
1907:
1908: public Constraint contains() {
1909: // TODO Auto-generated method stub
1910: throw new RuntimeException("Not Implemented");
1911: //return null;
1912: }
1913:
1914: public Constraint equal() {
1915: // TODO Auto-generated method stub
1916: throw new RuntimeException("Not Implemented");
1917: //return null;
1918: }
1919:
1920: public Object getObject() {
1921: // TODO Auto-generated method stub
1922: throw new RuntimeException("Not Implemented");
1923: //return null;
1924: }
1925:
1926: public Constraint greater() {
1927: // TODO Auto-generated method stub
1928: throw new RuntimeException("Not Implemented");
1929: //return null;
1930: }
1931:
1932: public Constraint identity() {
1933: // TODO Auto-generated method stub
1934: throw new RuntimeException("Not Implemented");
1935: //return null;
1936: }
1937:
1938: public Constraint like() {
1939: // TODO Auto-generated method stub
1940: throw new RuntimeException("Not Implemented");
1941: //return null;
1942: }
1943:
1944: public Constraint not() {
1945: // TODO Auto-generated method stub
1946: throw new RuntimeException("Not Implemented");
1947: //return null;
1948: }
1949:
1950: public Constraint smaller() {
1951: // TODO Auto-generated method stub
1952: throw new RuntimeException("Not Implemented");
1953: //return null;
1954: }
1955:
1956: }
1957:
1958: private abstract static class ConstraintBase implements Constraint,
1959: Serializable {
1960:
1961: private transient ThreadLocal<CONSTRAINT_EVALUATION_STATUS> _status;
1962:
1963: private Vector<ConstraintBase> _links = new Vector<ConstraintBase>(
1964: 2);
1965:
1966: public ConstraintBase() {
1967: initStatus();
1968: }
1969:
1970: void updateSession(JODBSession session) {
1971:
1972: }
1973:
1974: private void initStatus() {
1975: _status = new ThreadLocal<CONSTRAINT_EVALUATION_STATUS>() {
1976: @Override
1977: protected CONSTRAINT_EVALUATION_STATUS initialValue() {
1978: return CONSTRAINT_EVALUATION_STATUS.UNKNOWN;
1979: }
1980: };
1981: }
1982:
1983: public void resetStatus() {
1984: _status.set(CONSTRAINT_EVALUATION_STATUS.UNKNOWN);
1985: }
1986:
1987: public Object readResolve() throws ObjectStreamException {
1988: initStatus();
1989: return this ;
1990: }
1991:
1992: public void setStatus(CONSTRAINT_EVALUATION_STATUS newStatus) {
1993: _status.set(newStatus);
1994: }
1995:
1996: public Constraint and(Constraint with) {
1997: ConstraintBase withImpl = (ConstraintBase) with;
1998: ConstraintLink link = new ConstraintLink(false, this ,
1999: withImpl);
2000: _links.add(link);
2001: withImpl._links.add(link);
2002: return link;
2003: }
2004:
2005: public CONSTRAINT_EVALUATION_STATUS getStatus() {
2006: return _status.get();
2007: }
2008:
2009: public CONSTRAINT_EVALUATION_STATUS getCumulativeStatus() {
2010: synchronized (_links) {
2011: if (_links.size() == 0) {
2012: return _status.get();
2013: }
2014: int acceptedCount = 0;
2015: for (int i = 0; i < _links.size(); i++) {
2016: switch (_links.elementAt(i).getCumulativeStatus()) {
2017: case ACCEPTED:
2018: acceptedCount++;
2019: break;
2020: case REJECTED:
2021: return CONSTRAINT_EVALUATION_STATUS.REJECTED;
2022: }
2023: }
2024: if (acceptedCount == _links.size()) {
2025: return CONSTRAINT_EVALUATION_STATUS.ACCEPTED;
2026: } else {
2027: return CONSTRAINT_EVALUATION_STATUS.UNKNOWN;
2028: }
2029: }
2030: }
2031:
2032: abstract void evaluatePersistentCopy(
2033: ClassDescriptor classDescriptor,
2034: ObjectDataContainer dataContainer,
2035: FieldRecord primitiveRecord,
2036: JODBOperationContext context) throws IOException;
2037:
2038: abstract void evaluateActiveObject(Object activeObject,
2039: Field field, JODBOperationContext context)
2040: throws IOException;
2041:
2042: public Constraint or(Constraint with) {
2043: ConstraintBase withImpl = (ConstraintBase) with;
2044: ConstraintLink link = new ConstraintLink(true, this,
2045: withImpl);
2046: _links.add(link);
2047: withImpl._links.add(link);
2048: return link;
2049: }
2050:
2051: }
2052: }
|