/** * INTERNAL: * A combination of readFromRowIntoObject and buildClone. * <p> * buildClone assumes the attribute value exists on the original and can * simply be copied. * <p> * readFromRowIntoObject assumes that one is building an original. * <p> * Both of the above assumptions are false in this method, and actually * attempts to do both at the same time. * <p> * Extract value from the row and set the attribute to this value in the * working copy clone. * In order to bypass the shared cache when in transaction a UnitOfWork must * be able to populate working copies directly from the row. */ public void buildCloneFromRow(AbstractRecord databaseRow, JoinedAttributeManager joinManager, Object clone, ObjectBuildingQuery sourceQuery, UnitOfWorkImpl unitOfWork, AbstractSession executionSession) { // This method is a combination of buildggregateFromRow and // buildClonePart on the super class. // none of buildClonePart used, as not an orignal new object, nor // do we worry about creating heavy clones for aggregate objects. Object clonedAttributeValue = buildAggregateFromRow(databaseRow, clone, joinManager, false, executionSession); ClassDescriptor descriptor = getReferenceDescriptor(clonedAttributeValue, unitOfWork); descriptor.getObjectChangePolicy().setAggregateChangeListener(clone, clonedAttributeValue, unitOfWork, descriptor, getAttributeName()); setAttributeValueInObject(clone, clonedAttributeValue); return; }
/** * INTERNAL: * Clone the attribute from the original and assign it to the clone. */ public void buildClone(Object original, Object clone, UnitOfWorkImpl unitOfWork) { Object attributeValue = getAttributeValueFromObject(original); Object aggregateClone = buildClonePart(original, attributeValue, unitOfWork); if (aggregateClone != null) { ClassDescriptor descriptor = getReferenceDescriptor(aggregateClone, unitOfWork); descriptor.getObjectChangePolicy().setAggregateChangeListener(clone, aggregateClone, unitOfWork, descriptor, getAttributeName()); } setAttributeValueInObject(clone, aggregateClone); }
/** * INTERNAL: * Get the attribute value from the object and add the appropriate * values to the specified database row. */ public void writeFromObjectIntoRow(Object object, AbstractRecord databaseRow, AbstractSession session) throws DescriptorException { if (isReadOnly()) { return; } AbstractRecord targetRow = buildRowFromAggregate(object, getAttributeValueFromObject(object), session); for (Enumeration stream = targetRow.keys(); stream.hasMoreElements();) { DatabaseField field = (DatabaseField)stream.nextElement(); Object value = targetRow.get(field); databaseRow.add(field, value); } }
/** * INTERNAL: * Builds a shallow original object. Only direct attributes and primary * keys are populated. In this way the minimum original required for * instantiating a working copy clone can be built without placing it in * the shared cache (no concern over cycles). */ public void buildShallowOriginalFromRow(AbstractRecord databaseRow, Object original, JoinedAttributeManager joinManager, AbstractSession executionSession) { Object aggregate = buildAggregateFromRow(databaseRow, original, joinManager, true, executionSession);// shallow only. setAttributeValueInObject(original, aggregate); }
if (isNullAllowed() && allAggregateFieldsAreNull(databaseRow)) { return null; ClassDescriptor descriptor = getReferenceDescriptor(); boolean refreshing = true; if (descriptor.hasInheritance()) { Class newAggregateClass = descriptor.getInheritancePolicy().classFromRow(databaseRow, session); descriptor = getReferenceDescriptor(newAggregateClass, session); aggregate = getMatchingAttributeValueFromObject(databaseRow, targetObject, session, descriptor); if ((aggregate != null) && (aggregate.getClass() != newAggregateClass)) { aggregate = getMatchingAttributeValueFromObject(databaseRow, targetObject, session, descriptor); if (joinManager.isAttributeJoined(getDescriptor(), getAttributeName()) ){ ((ObjectLevelReadQuery)nestedQuery).getJoinedAttributeManager().setJoinedAttributeExpressions_(extractNestedExpressions(joinManager.getJoinedAttributeExpressions(), joinManager.getBaseExpressionBuilder(), false)); nestedQuery.setDescriptor(descriptor);
if (isNullAllowed()) { if (backupAttributeValueIsNull(query)) { return new DatabaseRecord(1);// both attributes are null - no update required } else { return buildNullReferenceRow(); } else if ((query.getBackupClone() != null) && ((getMatchingBackupAttributeValue(query, attributeValue) == null) || !(attributeValue.getClass().equals(getMatchingBackupAttributeValue(query, attributeValue).getClass())))) { return getObjectBuilder(attributeValue, query.getSession()).buildRow(attributeValue, query.getSession()); } else { if (query.getSession().isClassReadOnly(attributeValue.getClass())) { clonedQuery.setObject(attributeValue); if (query.getSession().isUnitOfWork()) { Object backupAttributeValue = getMatchingBackupAttributeValue(query, attributeValue); if (backupAttributeValue == null) { backupAttributeValue = getObjectBuilder(attributeValue, query.getSession()).buildNewInstance(); return getObjectBuilder(attributeValue, query.getSession()).buildRowForUpdate(clonedQuery);
} else { AggregateObjectMapping mapping = new AggregateObjectMapping(); mapping.setIsReadOnly(false); mapping.setIsNullAllowed(true); mapping.setReferenceClassName(getReferenceClassName()); mapping.setAttributeName(getAttributeName());
/** * INTERNAL: * Get the attribute value from the object and add the changed * values to the specified database row. */ public void writeFromObjectIntoRowForUpdate(WriteObjectQuery query, AbstractRecord databaseRow) throws DescriptorException { if (isReadOnly()) { return; } AbstractRecord targetRow = buildRowFromAggregateForUpdate(query, getAttributeValueFromObject(query.getObject())); for (Enumeration stream = targetRow.keys(); stream.hasMoreElements();) { DatabaseField field = (DatabaseField)stream.nextElement(); Object value = targetRow.get(field); databaseRow.add(field, value); } }
/** * INTERNAL: * Build and return a database row built with the values from * the specified attribute value. */ protected AbstractRecord buildRowFromAggregate(Object object, Object attributeValue, AbstractSession session, boolean forceWriteOfReadOnlyClasses) throws DescriptorException { if (attributeValue == null) { if (isNullAllowed()) { return buildNullReferenceRow(); } else { throw DescriptorException.nullForNonNullAggregate(object, this); } } else { if ((!forceWriteOfReadOnlyClasses) && (session.isClassReadOnly(attributeValue.getClass()))) { return new DatabaseRecord(1); } else { return getObjectBuilder(attributeValue, session).buildRow(attributeValue, session); } } }
/** * INTERNAL: * Build and return a database row built with the values from * the specified attribute value. */ protected AbstractRecord buildRowFromAggregateWithChangeRecord(ChangeRecord changeRecord, ObjectChangeSet objectChangeSet, AbstractSession session, boolean forceWriteOfReadOnlyClasses) throws DescriptorException { if (objectChangeSet == null) { if (isNullAllowed()) { return buildNullReferenceRow(); } else { Object object = ((ObjectChangeSet)changeRecord.getOwner()).getUnitOfWorkClone(); throw DescriptorException.nullForNonNullAggregate(object, this); } } else { if ((!forceWriteOfReadOnlyClasses) && (session.isClassReadOnly(objectChangeSet.getClassType(session)))) { return new DatabaseRecord(1); } else { return getReferenceDescriptor(objectChangeSet.getClassType(session), session).getObjectBuilder().buildRowWithChangeSet(objectChangeSet, session); } } }
/** * INTERNAL: (Overridden in EmbeddedIdAccessor) * * Process an @AttributeOverride or attribute-override element for an * embedded object, that is, an aggregate object mapping in TopLink. */ protected void processAttributeOverride(AggregateObjectMapping mapping, MetadataColumn column) { String attributeName = column.getAttributeName(); // Set the attribute name on the aggregate. DatabaseMapping aggregateMapping = getReferenceDescriptor().getMappingForAttributeName(attributeName); if (aggregateMapping == null) { m_validator.throwInvalidEmbeddableAttribute(getJavaClass(), mapping.getAttributeName(), getReferenceDescriptor().getJavaClass(), attributeName); } // A sub-class to a mapped superclass may override an embedded attribute // override. if (m_descriptor.hasAttributeOverrideFor(attributeName)) { // Update the field on this metadata column. We do that so that // an embedded id can associate the correct id fields. column.setDatabaseField(m_descriptor.getAttributeOverrideFor(attributeName).getDatabaseField()); } mapping.addFieldNameTranslation(column.getDatabaseField().getQualifiedName(), aggregateMapping.getField().getName()); }
/** * INTERNAL: * Build and return a database row built with the values from * the specified attribute value. */ protected AbstractRecord buildRowFromAggregate(Object object, Object attributeValue, AbstractSession session) throws DescriptorException { return buildRowFromAggregate(object, attributeValue, session, false); }
((AggregateObjectMapping) mapping).addPrimaryKeyJoinField(primaryKeyField, secondaryField);
aggregateMapping.addFieldNameTranslation(joinColumn.name(), fkField.getName());
/** * INTERNAL: * Build an aggregate object from the specified row and put it * in the specified target object. */ public Object readFromRowIntoObject(AbstractRecord databaseRow, JoinedAttributeManager joinManager, Object targetObject, ObjectBuildingQuery sourceQuery, AbstractSession executionSession) throws DatabaseException { Object aggregate = buildAggregateFromRow(databaseRow, targetObject, joinManager, false, executionSession);// don't just build a shallow original setAttributeValueInObject(targetObject, aggregate); return aggregate; }
/** * INTERNAL: * A subclass should implement this method if it wants different behaviour. * Write the foreign key values from the attribute to the row. */ public void writeFromAttributeIntoRow(Object attribute, AbstractRecord row, AbstractSession session) { AbstractRecord targetRow = buildRowFromAggregate(null, attribute, session); for (Enumeration stream = targetRow.keys(); stream.hasMoreElements(); ) { DatabaseField field = (DatabaseField) stream.nextElement(); Object value = targetRow.get(field); row.put(field, value); } }