/** * INTERNAL: this returns a single expression to represent the join from the main table to all * child descriptor tables Only if outer joins should be printed in the where clause * * @return Expression */ public Expression getTreatCriteria() { if (getDescriptor() == null) { return null; } // need to build this using just the multiple tables on this descriptor not included in the // parent's join expression Expression criteria = null; if (getSession().getPlatform().shouldPrintOuterJoinInWhereClause()) { Vector tables = getDescriptor().getTables(); // This child's tables ClassDescriptor parentDescriptor = this.typeExpressionBase.getDescriptor(); int tablesSize = tables.size(); if (parentDescriptor.hasInheritance() && parentDescriptor.getInheritancePolicy().hasMultipleTableChild()) { // look up the joins from the parent descriptor to our tables. for (int i = 0; i < tablesSize; i++) { DatabaseTable table = (DatabaseTable) tables.elementAt(i); Expression joinExpression = parentDescriptor.getInheritancePolicy().getChildrenTablesJoinExpressions().get(table); // Some of our tables might be the in our parent as well, so ignore the lack of a // joinExpression if (joinExpression != null) { joinExpression = this.baseExpression.twist(joinExpression, this); if (shouldUseOuterJoin()) { joinExpression = joinExpression.convertToUseOuterJoin(); } criteria = joinExpression.and(criteria); } } } } return criteria; }
/** INTERNAL: */ @Override public List<DatabaseField> getSelectionFields(ReadQuery query) { if (getDescriptor() == null) { DatabaseMapping mapping = getMapping(); if (mapping != null) { return mapping.getSelectFields(); } return new ArrayList<DatabaseField>(0); } if (descriptor.hasInheritance() && descriptor.getInheritancePolicy().shouldReadSubclasses() && (!descriptor.getInheritancePolicy().hasMultipleTableChild()) || shouldUseOuterJoinForMultitableInheritance()) { // return all fields because we can. if (query != null && query.isObjectLevelReadQuery()) { return descriptor.getAllSelectionFields((ObjectLevelReadQuery) query); } else { return descriptor.getAllSelectionFields(); } } else { if (query != null && query.isObjectLevelReadQuery()) { return descriptor.getSelectionFields((ObjectLevelReadQuery) query); } else { return descriptor.getSelectionFields(); } } }
/** * INTERNAL Return the descriptor which contains this query key, look in the inheritance hierarchy * of rootDescriptor for the descriptor. */ public ClassDescriptor convertToCastDescriptor( ClassDescriptor rootDescriptor, AbstractSession session) { if (castClass == null || rootDescriptor == null || rootDescriptor.getJavaClass() == castClass) { return rootDescriptor; } ClassDescriptor castDescriptor = session.getClassDescriptor(castClass); if (castDescriptor == null) { throw QueryException.couldNotFindCastDescriptor(castClass, getBaseExpression()); } if (!castDescriptor.hasInheritance()) { throw QueryException.castMustUseInheritance(getBaseExpression()); } ClassDescriptor parentDescriptor = castDescriptor.getInheritancePolicy().getParentDescriptor(); while (parentDescriptor != null) { if (parentDescriptor == rootDescriptor) { return castDescriptor; } parentDescriptor = parentDescriptor.getInheritancePolicy().getParentDescriptor(); } ClassDescriptor childDescriptor = rootDescriptor; while (childDescriptor != null) { if (childDescriptor == castDescriptor) { return rootDescriptor; } childDescriptor = childDescriptor.getInheritancePolicy().getParentDescriptor(); } throw QueryException.couldNotFindCastDescriptor(castClass, getBaseExpression()); }
/** * INTERNAL - Return the descriptor which contains this query key, look in the inheritance * hierarchy of rootDescriptor for the descriptor. Does not set the descriptor, only returns it. */ public ClassDescriptor convertToCastDescriptor( ClassDescriptor rootDescriptor, AbstractSession session) { isDowncast = Boolean.FALSE; if (castClass == null || rootDescriptor == null || rootDescriptor.getJavaClass() == castClass) { return rootDescriptor; } ClassDescriptor castDescriptor = session.getClassDescriptor(castClass); if (castDescriptor == null) { throw QueryException.couldNotFindCastDescriptor(castClass, getBaseExpression()); } if (!castDescriptor.hasInheritance()) { throw QueryException.castMustUseInheritance(getBaseExpression()); } ClassDescriptor parentDescriptor = castDescriptor.getInheritancePolicy().getParentDescriptor(); while (parentDescriptor != null) { if (parentDescriptor == rootDescriptor) { isDowncast = Boolean.TRUE; return castDescriptor; } parentDescriptor = parentDescriptor.getInheritancePolicy().getParentDescriptor(); } // is there value casting an emp to person in a query? ClassDescriptor childDescriptor = rootDescriptor; while (childDescriptor != null) { if (childDescriptor == castDescriptor) { return rootDescriptor; } childDescriptor = childDescriptor.getInheritancePolicy().getParentDescriptor(); } throw QueryException.couldNotFindCastDescriptor(castClass, getBaseExpression()); }
/** * Return whether the reference objects must be deleted one by one, as opposed to with a single * DELETE statement. */ protected boolean mustDeleteReferenceObjectsOneByOne() { ClassDescriptor referenceDescriptor = this.getReferenceDescriptor(); return referenceDescriptor.hasDependencyOnParts() || referenceDescriptor.usesOptimisticLocking() || (referenceDescriptor.hasInheritance() && referenceDescriptor.getInheritancePolicy().shouldReadSubclasses()) || referenceDescriptor.hasMultipleTables(); }
/** * INTERNAL: much like getOwnedTables(), this gets the tables represented from the descriptor. * Difference is this only returns local tables for the child casted descriptor, and excludes * tables owned by the parent descriptor */ public List<DatabaseTable> getOwnedSubTables() { ClassDescriptor parentDescriptor = this.typeExpressionBase.getDescriptor(); Vector<DatabaseTable> childTables = new Vector(2); if (parentDescriptor.hasInheritance() && parentDescriptor.getInheritancePolicy().hasMultipleTableChild()) { List parentTables = typeExpressionBase.getOwnedTables(); // All tables for this child, including parent tables Vector<DatabaseTable> tables = getDescriptor().getTables(); for (DatabaseTable table : tables) { if (!parentTables.contains(table)) { childTables.add(table); } } } return childTables; }
/** * INTERNAL: Not to be confused with the public getField(String) This returns a collection of all * fields associated with this object. Really only applies to query keys representing an object or * to expression builders. */ @Override public Vector getFields() { if (getDescriptor() == null) { DatabaseMapping mapping = getMapping(); if (mapping != null) { return mapping.getSelectFields(); } return new NonSynchronizedVector(0); } if (descriptor.hasInheritance() && descriptor.getInheritancePolicy().shouldReadSubclasses() && (!descriptor.getInheritancePolicy().hasMultipleTableChild()) || shouldUseOuterJoinForMultitableInheritance()) { // return all fields because we can. return descriptor.getAllFields(); } else { return descriptor.getFields(); } }
/** * INTERNAL: Used in case outer joins should be printed in FROM clause. Each of the additional * tables mapped to expressions that joins it. */ public Map additionalTreatExpressionCriteriaMap() { if (getDescriptor() == null) { return null; } int tableSize = 0; HashMap tablesJoinExpressions = new HashMap(); ClassDescriptor parentDescriptor = this.typeExpressionBase.getDescriptor(); // outerjoin our parent->child tables if (parentDescriptor.hasInheritance() && parentDescriptor.getInheritancePolicy().hasMultipleTableChild()) { Vector tables = getDescriptor().getTables(); // All this child's tables tableSize = tables.size(); // look up the joins from the parent descriptor to our tables. for (int i = 0; i < tableSize; i++) { DatabaseTable table = (DatabaseTable) tables.elementAt(i); Expression joinExpression = parentDescriptor.getInheritancePolicy().getChildrenTablesJoinExpressions().get(table); // Some of our tables might be the in our parent as well, so ignore the lack of a // joinExpression if (joinExpression != null) { joinExpression = this.baseExpression.twist(joinExpression, this); tablesJoinExpressions.put(table, joinExpression); } } } if (isUsingOuterJoinForMultitableInheritance()) { List childrenTables = getDescriptor().getInheritancePolicy().getChildrenTables(); tableSize = childrenTables.size(); for (int i = 0; i < tableSize; i++) { DatabaseTable table = (DatabaseTable) childrenTables.get(i); Expression joinExpression = getDescriptor().getInheritancePolicy().getChildrenTablesJoinExpressions().get(table); joinExpression = this.baseExpression.twist(joinExpression, this); tablesJoinExpressions.put(table, joinExpression); } } return tablesJoinExpressions; }
public static Hashtable buildInheritanceHierarchyTree(Project project) { Map descriptors = project.getDescriptors(); Hashtable hierarchyTree = new Hashtable(descriptors.size()); for (Iterator descriptorIterator = descriptors.values().iterator(); descriptorIterator.hasNext(); ) { ClassDescriptor descriptor = (ClassDescriptor) descriptorIterator.next(); String className = descriptor.getJavaClassName(); if (className == null) { className = descriptor.getJavaClass().getName(); } HierarchyNode node = getNodeForClass(className, hierarchyTree); if (descriptor.hasInheritance() && (descriptor.getInheritancePolicy().getParentClassName() != null)) { HierarchyNode parentNode = getNodeForClass(descriptor.getInheritancePolicy().getParentClassName(), hierarchyTree); node.setParent(parentNode); } } return hierarchyTree; }
protected Object readObjectFromRow(Session session, ClassDescriptor desc, Record row) { if (desc.hasInheritance()) { Class newClass = desc.getInheritancePolicy().classFromRow((DatabaseRecord) row, (AbstractSession) session); desc = session.getClassDescriptor(newClass); } Object object = desc.getObjectBuilder().buildNewInstance(); ReadObjectQuery query = new ReadObjectQuery(); query.setSession((AbstractSession) session); for (Enumeration mappings = desc.getMappings().elements(); mappings.hasMoreElements(); ) { DatabaseMapping mapping = (DatabaseMapping) mappings.nextElement(); mapping.readFromRowIntoObject( (DatabaseRecord) row, query.getJoinedAttributeManager(), object, null, query, query.getSession(), true); } return object; }
/** * INTERNAL This method iterates through a collection and gets the values from the objects to * conform in an in-memory query. Creation date: (1/19/01 1:18:27 PM) */ public Object valuesFromCollection( Object object, AbstractSession session, int valueHolderPolicy, boolean isObjectUnregistered) { // in case the mapping is null - this can happen if a query key is being used // In this case, check for the query key and find it's mapping. boolean readMappingFromQueryKey = false; if (getMapping() == null) { getMappingFromQueryKey(); readMappingFromQueryKey = true; } // For bug 2780817 get the mapping directly from the object. In EJB 2.0 // inheritance, each child must override mappings defined in an abstract // class with its own. DatabaseMapping mapping = this.mapping; ClassDescriptor descriptor = mapping.getDescriptor(); if (descriptor.hasInheritance() && (descriptor.getJavaClass() != object.getClass())) { mapping = session .getDescriptor(object.getClass()) .getObjectBuilder() .getMappingForAttributeName(getName()); descriptor = mapping.getDescriptor(); } // fetch group support if (descriptor.hasFetchGroupManager()) { FetchGroupManager fetchGroupManager = descriptor.getFetchGroupManager(); if (fetchGroupManager.isPartialObject(object) && (!fetchGroupManager.isAttributeFetched(object, mapping.getAttributeName()))) { // the conforming attribute is not fetched, simply throw exception throw QueryException.cannotConformUnfetchedAttribute(mapping.getAttributeName()); } } if (mapping.isDirectToFieldMapping()) { return ((AbstractDirectMapping) mapping).valueFromObject(object, mapping.getField(), session); } else if (mapping.isForeignReferenceMapping()) { // CR 3677 integration of a ValueHolderPolicy Object valueFromMapping = mapping.getAttributeValueFromObject(object); if (!((ForeignReferenceMapping) mapping) .getIndirectionPolicy() .objectIsInstantiated(valueFromMapping)) { if (valueHolderPolicy != InMemoryQueryIndirectionPolicy.SHOULD_TRIGGER_INDIRECTION) { // If the client wishes us to trigger the indirection then we should do so, // Other wise throw the exception throw QueryException .mustInstantiateValueholders(); // you should instantiate the valueholder for this to // work } // maybe we should throw this exception from the start, to save time } Object valueToIterate = mapping.getRealAttributeValueFromObject(object, session); UnitOfWorkImpl uow = isObjectUnregistered ? (UnitOfWorkImpl) session : null; // First check that object in fact is unregistered. // toDo: ?? Why is this commented out? Why are we supporting the unregistered thing at all? // Does not seem to be any public API for this, nor every used internally? // if (isObjectUnregistered) { // isObjectUnregistered = !uow.getCloneMapping().containsKey(object); // } if (mapping.isCollectionMapping() && (valueToIterate != null)) { // For bug 2766379 must use the correct version of vectorFor to // unwrap the result same time. valueToIterate = mapping.getContainerPolicy().vectorFor(valueToIterate, session); // toDo: If the value is empty, need to support correct inner/outer join filtering // symantics. // For CR 2612601, try to partially replace the result with already // registered objects. if (isObjectUnregistered && (uow.getCloneMapping().get(object) == null)) { Vector objectValues = (Vector) valueToIterate; for (int i = 0; i < objectValues.size(); i++) { Object original = objectValues.elementAt(i); Object clone = uow.getIdentityMapAccessorInstance() .getIdentityMapManager() .getFromIdentityMap(original); if (clone != null) { objectValues.setElementAt(clone, i); } } } // For CR 2612601, conforming without registering, a query could be // bob.get("address").get("city").equal("Ottawa"); where the address // has been registered and modified in the UOW, but bob has not. Thus // even though bob does not point to the modified address now, it will // as soon as it is registered, so should point to it here. } else if (isObjectUnregistered && (uow.getCloneMapping().get(object) == null)) { Object clone = uow.getIdentityMapAccessorInstance() .getIdentityMapManager() .getFromIdentityMap(valueToIterate); if (clone != null) { valueToIterate = clone; } } return valueToIterate; } else if (mapping.isAggregateMapping()) { Object aggregateValue = mapping.getAttributeValueFromObject(object); // Bug 3995468 - if this query key is to a mapping in an aggregate object, get the object from // actual mapping rather than the aggregate mapping while (readMappingFromQueryKey && mapping.isAggregateObjectMapping() && !((AggregateObjectMapping) mapping) .getReferenceClass() .equals(queryKey.getDescriptor().getJavaClass())) { mapping = mapping .getReferenceDescriptor() .getObjectBuilder() .getMappingForField(((DirectQueryKey) queryKey).getField()); aggregateValue = mapping.getRealAttributeValueFromObject(aggregateValue, session); } return aggregateValue; } else { throw QueryException.cannotConformExpression(); } }
public Object buildObjectFromNestedRow( AbstractRecord nestedRow, JoinedAttributeManager joinManager, ObjectBuildingQuery sourceQuery, AbstractSession executionSession, boolean isTargetProtected) { Object objectToAdd = null; ClassDescriptor aDescriptor = getReferenceDescriptor((DOMRecord) nestedRow); if (aDescriptor == null) { if ((getKeepAsElementPolicy() == UnmarshalKeepAsElementPolicy.KEEP_UNKNOWN_AS_ELEMENT) || (getKeepAsElementPolicy() == UnmarshalKeepAsElementPolicy.KEEP_ALL_AS_ELEMENT)) { XMLPlatformFactory.getInstance() .getXMLPlatform() .namespaceQualifyFragment((Element) ((DOMRecord) nestedRow).getDOM()); objectToAdd = ((DOMRecord) nestedRow).getDOM(); convertDataValueToObjectValue( objectToAdd, executionSession, ((XMLRecord) nestedRow).getUnmarshaller()); // simple case objectToAdd = convertToSimpleTypeIfPresent(objectToAdd, nestedRow, executionSession); } else { NodeList children = ((Element) ((DOMRecord) nestedRow).getDOM()).getChildNodes(); for (int i = 0; i < children.getLength(); i++) { Node nextNode = children.item(i); if (nextNode.getNodeType() == nextNode.ELEMENT_NODE) { // complex child String type = ((Element) ((DOMRecord) nestedRow).getDOM()) .getAttributeNS( javax.xml.XMLConstants.W3C_XML_SCHEMA_INSTANCE_NS_URI, XMLConstants.SCHEMA_TYPE_ATTRIBUTE); if (type != null && type.length() > 0) { throw XMLMarshalException.unknownXsiTypeValue(type, (Mapping) this); } else { throw XMLMarshalException.noDescriptorFound((Mapping) this); } } } // simple case objectToAdd = convertToSimpleTypeIfPresent(objectToAdd, nestedRow, executionSession); } } else { if (aDescriptor.hasInheritance()) { Class newElementClass = aDescriptor.getInheritancePolicy().classFromRow(nestedRow, executionSession); if (newElementClass == null) { // no xsi:type attribute - look for type indicator on the field QName leafElementType = ((XMLField) getField()).getLeafElementType(); if (leafElementType != null) { XPathQName leafElementXPathQName = new XPathQName(leafElementType, ((XMLRecord) nestedRow).isNamespaceAware()); Object indicator = aDescriptor .getInheritancePolicy() .getClassIndicatorMapping() .get(leafElementXPathQName); if (indicator != null) { newElementClass = (Class) indicator; } } } if (newElementClass != null) { aDescriptor = this.getReferenceDescriptor(newElementClass, executionSession); } else { // since there is no xsi:type attribute or leaf element type set, // use the reference descriptor - make sure it is non-abstract if (Modifier.isAbstract(aDescriptor.getJavaClass().getModifiers())) { // throw an exception throw DescriptorException.missingClassIndicatorField( nestedRow, aDescriptor.getInheritancePolicy().getDescriptor()); } } } // Object element objectToAdd = buildCompositeObject( aDescriptor, nestedRow, sourceQuery, null, joinManager, executionSession); objectToAdd = convertDataValueToObjectValue( objectToAdd, executionSession, ((XMLRecord) nestedRow).getUnmarshaller()); } return objectToAdd; }
/** * INTERNAL: Build and return the nested rows from the specified field value. This method allows * the field value to be an ARRAY containing other structures such as arrays or Struct, or direct * values. */ public static Object buildContainerFromArray( Array fieldValue, ObjectRelationalDatabaseField arrayField, AbstractSession session) throws DatabaseException { if (arrayField.getType() == null) { return fieldValue; } Object[] objects = null; try { objects = (Object[]) fieldValue.getArray(); } catch (java.sql.SQLException ex) { throw DatabaseException.sqlException(ex, session, false); } if (objects == null) { return null; } boolean isNestedStructure = false; ObjectRelationalDataTypeDescriptor ord = null; DatabaseField nestedType = null; if (arrayField != null) { nestedType = arrayField.getNestedTypeField(); if ((nestedType != null) && nestedType.getSqlType() == Types.STRUCT) { ClassDescriptor descriptor = session.getDescriptor(nestedType.getType()); if ((descriptor != null) && (descriptor.isObjectRelationalDataTypeDescriptor())) { // this is used to convert non-null objects passed through stored procedures and custom // SQL to structs ord = (ObjectRelationalDataTypeDescriptor) descriptor; } } else if ((nestedType != null) && (nestedType instanceof ObjectRelationalDatabaseField)) { isNestedStructure = true; } } // handle ARRAY conversions ReadObjectQuery query = new ReadObjectQuery(); query.setSession(session); ContainerPolicy cp = ContainerPolicy.buildPolicyFor(arrayField.getType()); Object container = cp.containerInstance(objects.length); for (int i = 0; i < objects.length; i++) { Object arrayValue = objects[i]; if (arrayValue == null) { return null; } if (ord != null) { AbstractRecord nestedRow = ord.buildRowFromStructure((Struct) arrayValue); ClassDescriptor descriptor = ord; if (descriptor.hasInheritance()) { Class newElementClass = descriptor.getInheritancePolicy().classFromRow(nestedRow, session); if (!descriptor.getJavaClass().equals(newElementClass)) { descriptor = session.getDescriptor(newElementClass); if (descriptor == null) { descriptor = ord; } } } arrayValue = descriptor.getObjectBuilder().buildNewInstance(); descriptor .getObjectBuilder() .buildAttributesIntoObject(arrayValue, nestedRow, query, null, false); } else if (isNestedStructure && (arrayValue instanceof Array)) { arrayValue = buildContainerFromArray( (Array) arrayValue, (ObjectRelationalDatabaseField) nestedType, session); } cp.addInto(arrayValue, container, session); } return container; }