/** * INTERNAL: Return the value for in memory comparison. This is only valid for valueable * expressions. */ public Object valueFromObject( Object object, AbstractSession session, AbstractRecord translationRow, int valueHolderPolicy, boolean isObjectUnregistered) { // The expression may be across a relationship, in which case it must be traversed. if ((!getBaseExpression().isExpressionBuilder()) && getBaseExpression().isQueryKeyExpression()) { object = getBaseExpression() .valueFromObject( object, session, translationRow, valueHolderPolicy, isObjectUnregistered); // toDo: Null means the join filters out the row, returning null is not correct if an inner // join, // outer/inner joins need to be fixed to filter correctly. if (object == null) { return null; } // If from an anyof the object will be a collection of values, // A new vector must union the object values and the values extracted from it. if (object instanceof Vector) { Vector comparisonVector = new Vector(((Vector) object).size() + 2); for (Enumeration valuesToIterate = ((Vector) object).elements(); valuesToIterate.hasMoreElements(); ) { Object vectorObject = valuesToIterate.nextElement(); if (vectorObject == null) { comparisonVector.addElement(vectorObject); } else { Object valueOrValues = valuesFromCollection( vectorObject, session, valueHolderPolicy, isObjectUnregistered); // If a collection of values were extracted union them. if (valueOrValues instanceof Vector) { for (Enumeration nestedValuesToIterate = ((Vector) valueOrValues).elements(); nestedValuesToIterate.hasMoreElements(); ) { comparisonVector.addElement(nestedValuesToIterate.nextElement()); } } else { comparisonVector.addElement(valueOrValues); } } } return comparisonVector; } } return valuesFromCollection(object, session, valueHolderPolicy, isObjectUnregistered); }
/** * INTERNAL: This methods clones all the fields and ensures that each collection refers to the * same clones. */ @Override public Object clone() { VariableOneToOneMapping clone = (VariableOneToOneMapping) super.clone(); Map setOfKeys = new HashMap(getSourceToTargetQueryKeyNames().size()); Map sourceToTarget = new HashMap(getSourceToTargetQueryKeyNames().size()); Vector foreignKeys = org.eclipse.persistence.internal.helper.NonSynchronizedVector.newInstance( getForeignKeyFields().size()); if (getTypeField() != null) { clone.setTypeField((DatabaseField) this.getTypeField().clone()); } for (Iterator enumtr = getSourceToTargetQueryKeyNames().keySet().iterator(); enumtr.hasNext(); ) { // Clone the SourceKeyFields DatabaseField field = (DatabaseField) enumtr.next(); DatabaseField clonedField = (DatabaseField) field.clone(); setOfKeys.put(field, clonedField); // on the next line I'm cloning the query key names sourceToTarget.put(clonedField, getSourceToTargetQueryKeyNames().get(field)); } for (Enumeration enumtr = getForeignKeyFields().elements(); enumtr.hasMoreElements(); ) { DatabaseField field = (DatabaseField) enumtr.nextElement(); foreignKeys.addElement(setOfKeys.get(field)); } clone.setSourceToTargetQueryKeyFields(sourceToTarget); clone.setForeignKeyFields(foreignKeys); clone.setTypeIndicatorTranslation(new HashMap(this.getTypeIndicatorTranslation())); return clone; }
/** * INTERNAL: Return the value of the field from the row or a value holder on the query to obtain * the object. Check for batch + aggregation reading. */ @Override public Object valueFromRow( AbstractRecord row, JoinedAttributeManager joinManager, ObjectBuildingQuery sourceQuery, AbstractSession executionSession) throws DatabaseException { // If any field in the foreign key is null then it means there are no referenced objects for (Enumeration enumeration = getFields().elements(); enumeration.hasMoreElements(); ) { DatabaseField field = (DatabaseField) enumeration.nextElement(); if (row.get(field) == null) { return getIndirectionPolicy().nullValueFromRow(); } } if (getTypeField() != null) { // If the query used batched reading, return a special value holder, // or retrieve the object from the query property. if (sourceQuery.isReadAllQuery() && (((ReadAllQuery) sourceQuery).isAttributeBatchRead(getDescriptor(), getAttributeName()) || shouldUseBatchReading())) { return batchedValueFromRow(row, ((ReadAllQuery) sourceQuery)); } // If the field is empty we cannot load the object because we do not know what class it will // be if (row.get(getTypeField()) == null) { return getIndirectionPolicy().nullValueFromRow(); } Class implementerClass = (Class) getImplementorForType(row.get(getTypeField()), executionSession); ReadObjectQuery query = (ReadObjectQuery) getSelectionQuery().clone(); query.setReferenceClass(implementerClass); query.setSelectionCriteria(getSelectionCriteria()); query.setDescriptor(null); // Must set to null so the right descriptor is used if (sourceQuery.isObjectLevelReadQuery() && (sourceQuery.shouldCascadeAllParts() || (sourceQuery.shouldCascadePrivateParts() && isPrivateOwned()) || (sourceQuery.shouldCascadeByMapping() && this.cascadeRefresh))) { query.setShouldRefreshIdentityMapResult(sourceQuery.shouldRefreshIdentityMapResult()); query.setCascadePolicy(sourceQuery.getCascadePolicy()); query.setShouldMaintainCache(sourceQuery.shouldMaintainCache()); // For flashback. if (((ObjectLevelReadQuery) sourceQuery).hasAsOfClause()) { query.setAsOfClause(((ObjectLevelReadQuery) sourceQuery).getAsOfClause()); } // CR #4365 - used to prevent infinit recursion on refresh object cascade all query.setQueryId(sourceQuery.getQueryId()); } return getIndirectionPolicy().valueFromQuery(query, row, executionSession); } else { return super.valueFromRow(row, joinManager, sourceQuery, executionSession); } }
/** * PUBLIC: Return the foreign key field names associated with the mapping. These are only the * source fields that are writable. */ public Vector getForeignKeyFieldNames() { Vector fieldNames = new Vector(getForeignKeyFields().size()); for (Enumeration fieldsEnum = getForeignKeyFields().elements(); fieldsEnum.hasMoreElements(); ) { fieldNames.addElement(((DatabaseField) fieldsEnum.nextElement()).getQualifiedName()); } return fieldNames; }
/** PUBLIC: Set a collection of the source to target query key/field associations. */ public void setSourceToTargetQueryKeyFieldAssociations( Vector sourceToTargetQueryKeyFieldAssociations) { setSourceToTargetQueryKeyFields( new HashMap(sourceToTargetQueryKeyFieldAssociations.size() + 1)); for (Enumeration associationsEnum = sourceToTargetQueryKeyFieldAssociations.elements(); associationsEnum.hasMoreElements(); ) { Association association = (Association) associationsEnum.nextElement(); Object sourceField = new DatabaseField((String) association.getKey()); String targetQueryKey = (String) association.getValue(); getSourceToTargetQueryKeyNames().put(sourceField, targetQueryKey); } }
/** * PUBLIC: Return the foreign key field names associated with the mapping. These are only the * source fields that are writable. */ public void setForeignKeyFieldNames(Vector fieldNames) { Vector fields = org.eclipse.persistence.internal.helper.NonSynchronizedVector.newInstance( fieldNames.size()); for (Enumeration fieldNamesEnum = fieldNames.elements(); fieldNamesEnum.hasMoreElements(); ) { fields.addElement(new DatabaseField((String) fieldNamesEnum.nextElement())); } setForeignKeyFields(fields); if (!fields.isEmpty()) { setIsForeignKeyRelationship(true); } }
/** INTERNAL: Get a value from the object and set that in the respective field of the row. */ protected void writeFromNullObjectIntoRow(AbstractRecord record) { if (isReadOnly()) { return; } if (isForeignKeyRelationship()) { Enumeration foreignKeys = getForeignKeyFields().elements(); while (foreignKeys.hasMoreElements()) { record.put((DatabaseField) foreignKeys.nextElement(), null); } } if (getTypeField() != null) { record.put(getTypeField(), null); } }
/** PUBLIC: Set the class indicator associations. */ public void setClassIndicatorAssociations(Vector classIndicatorAssociations) { setTypeIndicatorNameTranslation(new HashMap(classIndicatorAssociations.size() + 1)); setTypeIndicatorTranslation(new HashMap((classIndicatorAssociations.size() * 2) + 1)); for (Enumeration associationsEnum = classIndicatorAssociations.elements(); associationsEnum.hasMoreElements(); ) { Association association = (Association) associationsEnum.nextElement(); Object classValue = association.getKey(); if (classValue instanceof Class) { // 904 projects will be a class type. addClassIndicator((Class) association.getKey(), association.getValue()); } else { addClassNameIndicator((String) association.getKey(), association.getValue()); } } }
/** INTERNAL: Get a value from the object and set that in the respective field of the row. */ @Override public void writeFromObjectIntoRowForWhereClause( ObjectLevelModifyQuery query, AbstractRecord record) { if (isReadOnly()) { return; } Object object; if (query.isDeleteObjectQuery()) { object = query.getObject(); } else { object = query.getBackupClone(); } Object referenceObject = getRealAttributeValueFromObject(object, query.getSession()); if (referenceObject == null) { writeFromNullObjectIntoRow(record); } else { if (isForeignKeyRelationship()) { Enumeration sourceFields = getForeignKeyFields().elements(); ClassDescriptor descriptor = query.getSession().getDescriptor(referenceObject.getClass()); while (sourceFields.hasMoreElements()) { DatabaseField sourceKey = (DatabaseField) sourceFields.nextElement(); String targetQueryKey = (String) getSourceToTargetQueryKeyNames().get(sourceKey); DatabaseField targetKeyField = descriptor.getObjectBuilder().getFieldForQueryKeyName(targetQueryKey); if (targetKeyField == null) { throw DescriptorException.variableOneToOneMappingIsNotDefinedProperly( this, descriptor, targetQueryKey); } Object referenceValue = descriptor .getObjectBuilder() .extractValueFromObjectForField( referenceObject, targetKeyField, query.getSession()); record.put(sourceKey, referenceValue); } } if (getTypeField() != null) { record.put(getTypeField(), getTypeForImplementor(referenceObject.getClass())); } } }
/** * INTERNAL: Get a value from the object and set that in the respective field of the row. If the * mapping id target foreign key, you must only write the type into the roe, the rest will be * updated when the object itself is written */ @Override public void writeFromObjectIntoRowWithChangeRecord( ChangeRecord changeRecord, AbstractRecord record, AbstractSession session) { if (isReadOnly()) { return; } ObjectChangeSet changeSet = (ObjectChangeSet) ((ObjectReferenceChangeRecord) changeRecord).getNewValue(); if (changeSet == null) { writeFromNullObjectIntoRow(record); } else { Object referenceObject = changeSet.getUnitOfWorkClone(); if (isForeignKeyRelationship()) { Enumeration sourceFields = getForeignKeyFields().elements(); ClassDescriptor descriptor = session.getDescriptor(referenceObject.getClass()); while (sourceFields.hasMoreElements()) { DatabaseField sourceKey = (DatabaseField) sourceFields.nextElement(); String targetQueryKey = (String) getSourceToTargetQueryKeyNames().get(sourceKey); DatabaseField targetKeyField = descriptor.getObjectBuilder().getFieldForQueryKeyName(targetQueryKey); if (targetKeyField == null) { throw DescriptorException.variableOneToOneMappingIsNotDefinedProperly( this, descriptor, targetQueryKey); } Object referenceValue = descriptor .getObjectBuilder() .extractValueFromObjectForField(referenceObject, targetKeyField, session); record.put(sourceKey, referenceValue); } } if (getTypeField() != null) { record.put(getTypeField(), getTypeForImplementor(referenceObject.getClass())); } } }