Search in sources :

Example 1 with ObjRelationship

use of org.apache.cayenne.map.ObjRelationship in project cayenne by apache.

the class BaseDataObject method validateForSave.

/**
 * Performs property validation of the object, appending any validation
 * failures to the provided validationResult object. This method is invoked
 * from "validateFor.." before committing a NEW or MODIFIED object to the
 * database. Validation includes checking for null values and value sizes.
 * CayenneDataObject subclasses may override this method, calling super.
 *
 * @since 1.1
 */
protected void validateForSave(ValidationResult validationResult) {
    ObjEntity objEntity = getObjectContext().getEntityResolver().getObjEntity(this);
    if (objEntity == null) {
        throw new CayenneRuntimeException("No ObjEntity mapping found for DataObject %s", getClass().getName());
    }
    // validate mandatory attributes
    Map<String, ValidationFailure> failedDbAttributes = null;
    for (ObjAttribute next : objEntity.getAttributes()) {
        // TODO: andrus, 2/20/2007 - handle embedded attribute
        if (next instanceof EmbeddedAttribute) {
            continue;
        }
        DbAttribute dbAttribute = next.getDbAttribute();
        if (dbAttribute == null) {
            throw new CayenneRuntimeException("ObjAttribute '%s" + "' does not have a corresponding DbAttribute", next.getName());
        }
        // pk may still be generated
        if (dbAttribute.isPrimaryKey()) {
            continue;
        }
        Object value = this.readPropertyDirectly(next.getName());
        if (dbAttribute.isMandatory()) {
            ValidationFailure failure = BeanValidationFailure.validateNotNull(this, next.getName(), value);
            if (failure != null) {
                if (failedDbAttributes == null) {
                    failedDbAttributes = new HashMap<>();
                }
                failedDbAttributes.put(dbAttribute.getName(), failure);
                continue;
            }
        }
        // validate length
        if (value != null && dbAttribute.getMaxLength() > 0) {
            if (value.getClass().isArray()) {
                int len = Array.getLength(value);
                if (len > dbAttribute.getMaxLength()) {
                    String message = "\"" + next.getName() + "\" exceeds maximum allowed length (" + dbAttribute.getMaxLength() + " bytes): " + len;
                    validationResult.addFailure(new BeanValidationFailure(this, next.getName(), message));
                }
            } else if (value instanceof CharSequence) {
                int len = ((CharSequence) value).length();
                if (len > dbAttribute.getMaxLength()) {
                    String message = "\"" + next.getName() + "\" exceeds maximum allowed length (" + dbAttribute.getMaxLength() + " chars): " + len;
                    validationResult.addFailure(new BeanValidationFailure(this, next.getName(), message));
                }
            }
        }
    }
    // validate mandatory relationships
    for (final ObjRelationship relationship : objEntity.getRelationships()) {
        List<DbRelationship> dbRels = relationship.getDbRelationships();
        if (dbRels.isEmpty()) {
            continue;
        }
        // see ObjRelationship.recalculateReadOnlyValue() for more info
        if (relationship.isSourceIndependentFromTargetChange()) {
            continue;
        }
        // if db relationship is not based on a PK and is based on mandatory
        // attributes, see if we have a target object set
        // relationship will be validated only if all db path has mandatory
        // db relationships
        boolean validate = true;
        for (DbRelationship dbRelationship : dbRels) {
            for (DbJoin join : dbRelationship.getJoins()) {
                DbAttribute source = join.getSource();
                if (source.isMandatory()) {
                    // clear attribute failures...
                    if (failedDbAttributes != null && !failedDbAttributes.isEmpty()) {
                        failedDbAttributes.remove(source.getName());
                    }
                } else {
                    // do not validate if the relation is based on
                    // multiple keys with some that can be nullable.
                    validate = false;
                }
            }
        }
        if (validate) {
            Object value = this.readPropertyDirectly(relationship.getName());
            ValidationFailure failure = BeanValidationFailure.validateNotNull(this, relationship.getName(), value);
            if (failure != null) {
                validationResult.addFailure(failure);
            }
        }
    }
    // deal with previously found attribute failures...
    if (failedDbAttributes != null && !failedDbAttributes.isEmpty()) {
        for (ValidationFailure failure : failedDbAttributes.values()) {
            validationResult.addFailure(failure);
        }
    }
}
Also used : ObjRelationship(org.apache.cayenne.map.ObjRelationship) ObjAttribute(org.apache.cayenne.map.ObjAttribute) BeanValidationFailure(org.apache.cayenne.validation.BeanValidationFailure) DbAttribute(org.apache.cayenne.map.DbAttribute) EmbeddedAttribute(org.apache.cayenne.map.EmbeddedAttribute) ValidationFailure(org.apache.cayenne.validation.ValidationFailure) BeanValidationFailure(org.apache.cayenne.validation.BeanValidationFailure) ObjEntity(org.apache.cayenne.map.ObjEntity) DbRelationship(org.apache.cayenne.map.DbRelationship) DbJoin(org.apache.cayenne.map.DbJoin)

Example 2 with ObjRelationship

use of org.apache.cayenne.map.ObjRelationship in project cayenne by apache.

the class BaseDataObject method unsetReverseRelationship.

/**
 * Removes current object from reverse relationship of object
 * <code>val</code> to this object.
 */
protected void unsetReverseRelationship(String relName, DataObject val) {
    EntityResolver resolver = objectContext.getEntityResolver();
    ObjEntity entity = resolver.getObjEntity(objectId.getEntityName());
    if (entity == null) {
        throw new IllegalStateException("DataObject's entity is unmapped, objectId: " + objectId);
    }
    ObjRelationship rel = entity.getRelationship(relName);
    ObjRelationship revRel = rel.getReverseRelationship();
    if (revRel != null) {
        if (revRel.isToMany()) {
            val.removeToManyTarget(revRel.getName(), this, false);
        } else {
            val.setToOneTarget(revRel.getName(), null, false);
        }
    }
}
Also used : ObjEntity(org.apache.cayenne.map.ObjEntity) ObjRelationship(org.apache.cayenne.map.ObjRelationship) EntityResolver(org.apache.cayenne.map.EntityResolver)

Example 3 with ObjRelationship

use of org.apache.cayenne.map.ObjRelationship in project cayenne by apache.

the class DataDomainIndirectDiffBuilder method arcCreated.

@Override
public void arcCreated(Object nodeId, Object targetNodeId, Object arcId) {
    ObjEntity entity = resolver.getObjEntity(((ObjectId) nodeId).getEntityName());
    ObjRelationship relationship = entity.getRelationship(arcId.toString());
    if (relationship.isSourceIndependentFromTargetChange()) {
        ObjectId nodeObjectId = (ObjectId) nodeId;
        if (!nodeObjectId.isTemporary()) {
            indirectModifications.add(nodeObjectId);
        }
        if (relationship.isFlattened()) {
            if (relationship.isReadOnly()) {
                throw new CayenneRuntimeException("Cannot set the read-only flattened relationship '%s' in ObjEntity '%s'.", relationship.getName(), relationship.getSourceEntity().getName());
            }
            // Register this combination (so we can remove it later if an insert occurs before commit)
            FlattenedArcKey key = new FlattenedArcKey((ObjectId) nodeId, (ObjectId) targetNodeId, relationship);
            // If this combination has already been deleted, simply undelete it.
            if (!flattenedDeletes.remove(key)) {
                flattenedInserts.add(key);
            }
        }
    }
}
Also used : ObjEntity(org.apache.cayenne.map.ObjEntity) ObjRelationship(org.apache.cayenne.map.ObjRelationship) ObjectId(org.apache.cayenne.ObjectId) CayenneRuntimeException(org.apache.cayenne.CayenneRuntimeException)

Example 4 with ObjRelationship

use of org.apache.cayenne.map.ObjRelationship in project cayenne by apache.

the class DataDomainQueryAction method interceptRelationshipQuery.

private boolean interceptRelationshipQuery() {
    if (query instanceof RelationshipQuery) {
        RelationshipQuery relationshipQuery = (RelationshipQuery) query;
        if (relationshipQuery.isRefreshing()) {
            return !DONE;
        }
        ObjRelationship relationship = relationshipQuery.getRelationship(domain.getEntityResolver());
        // check if we can derive target PK from FK...
        if (relationship.isSourceIndependentFromTargetChange()) {
            return !DONE;
        }
        // we can assume that there is one and only one DbRelationship as
        // we previously checked that "!isSourceIndependentFromTargetChange"
        DbRelationship dbRelationship = relationship.getDbRelationships().get(0);
        // FK pointing to a unique field that is a 'fake' PK (CAY-1755)...
        // It is not sufficient to generate target ObjectId.
        DbEntity targetEntity = dbRelationship.getTargetEntity();
        if (dbRelationship.getJoins().size() < targetEntity.getPrimaryKeys().size()) {
            return !DONE;
        }
        if (cache == null) {
            return !DONE;
        }
        DataRow sourceRow = cache.getCachedSnapshot(relationshipQuery.getObjectId());
        if (sourceRow == null) {
            return !DONE;
        }
        ObjectId targetId = sourceRow.createTargetObjectId(relationship.getTargetEntityName(), dbRelationship);
        // null id means that FK is null...
        if (targetId == null) {
            this.response = new GenericResponse(Collections.EMPTY_LIST);
            return DONE;
        }
        // target id resolution (unlike source) should be polymorphic
        DataRow targetRow = polymorphicRowFromCache(targetId);
        if (targetRow != null) {
            this.response = new GenericResponse(Collections.singletonList(targetRow));
            return DONE;
        }
        // create a fault
        if (context != null && relationship.isSourceDefiningTargetPrecenseAndType(domain.getEntityResolver())) {
            // prevent passing partial snapshots to ObjectResolver per
            // CAY-724.
            // Create a hollow object right here and skip object conversion
            // downstream
            this.noObjectConversion = true;
            Object object = context.findOrCreateObject(targetId);
            this.response = new GenericResponse(Collections.singletonList(object));
            return DONE;
        }
    }
    return !DONE;
}
Also used : ObjRelationship(org.apache.cayenne.map.ObjRelationship) DbEntity(org.apache.cayenne.map.DbEntity) RelationshipQuery(org.apache.cayenne.query.RelationshipQuery) ObjectId(org.apache.cayenne.ObjectId) GenericResponse(org.apache.cayenne.util.GenericResponse) DbRelationship(org.apache.cayenne.map.DbRelationship) DataRow(org.apache.cayenne.DataRow)

Example 5 with ObjRelationship

use of org.apache.cayenne.map.ObjRelationship in project cayenne by apache.

the class DataNodeSyncQualifierDescriptor method reset.

void reset(DbEntityClassDescriptor descriptor) {
    attributes = new ArrayList<>(3);
    valueTransformers = new ArrayList<>(3);
    usingOptimisticLocking = descriptor.getEntity().getLockType() == ObjEntity.LOCK_TYPE_OPTIMISTIC;
    // master PK columns
    if (descriptor.isMaster()) {
        for (final DbAttribute attribute : descriptor.getDbEntity().getPrimaryKeys()) {
            attributes.add(attribute);
            valueTransformers.add(input -> {
                ObjectId id = (ObjectId) input.getNodeId();
                return id.getIdSnapshot().get(attribute.getName());
            });
        }
    } else {
        // TODO: andrus 12/23/2007 - only one step relationship is supported...
        if (descriptor.getPathFromMaster().size() != 1) {
            throw new CayenneRuntimeException("Only single step dependent relationships are currently supported. Actual path length: %d", descriptor.getPathFromMaster().size());
        }
        DbRelationship masterDependentDbRel = descriptor.getPathFromMaster().get(0);
        if (masterDependentDbRel != null) {
            for (final DbJoin dbAttrPair : masterDependentDbRel.getJoins()) {
                DbAttribute dbAttribute = dbAttrPair.getTarget();
                if (!attributes.contains(dbAttribute)) {
                    attributes.add(dbAttribute);
                    valueTransformers.add(input -> {
                        ObjectId id = (ObjectId) input.getNodeId();
                        return id.getIdSnapshot().get(dbAttrPair.getSourceName());
                    });
                }
            }
        }
    }
    if (usingOptimisticLocking) {
        for (final ObjAttribute attribute : descriptor.getEntity().getAttributes()) {
            if (attribute.isUsedForLocking()) {
                // only care about first step in a flattened attribute
                DbAttribute dbAttribute = (DbAttribute) attribute.getDbPathIterator().next();
                // only use qualifier if dbEntities match
                if (dbAttribute.getEntity().equals(descriptor.getDbEntity()) && !attributes.contains(dbAttribute)) {
                    attributes.add(dbAttribute);
                    valueTransformers.add(input -> input.getSnapshotValue(attribute.getName()));
                }
            }
        }
        for (final ObjRelationship relationship : descriptor.getEntity().getRelationships()) {
            if (relationship.isUsedForLocking()) {
                // only care about the first DbRelationship
                DbRelationship dbRelationship = relationship.getDbRelationships().get(0);
                for (final DbJoin dbAttrPair : dbRelationship.getJoins()) {
                    DbAttribute dbAttribute = dbAttrPair.getSource();
                    // relationship transformers override attribute transformers for meaningful FK's...
                    // why meaningful FKs can go out of sync is another story (CAY-595)
                    int index = attributes.indexOf(dbAttribute);
                    if (index >= 0 && !dbAttribute.isForeignKey()) {
                        continue;
                    }
                    Function<ObjectDiff, Object> transformer = input -> {
                        ObjectId targetId = input.getArcSnapshotValue(relationship.getName());
                        return targetId != null ? targetId.getIdSnapshot().get(dbAttrPair.getTargetName()) : null;
                    };
                    if (index < 0) {
                        attributes.add(dbAttribute);
                        valueTransformers.add(transformer);
                    } else {
                        valueTransformers.set(index, transformer);
                    }
                }
            }
        }
    }
}
Also used : ObjEntity(org.apache.cayenne.map.ObjEntity) ObjAttribute(org.apache.cayenne.map.ObjAttribute) HashMap(java.util.HashMap) Function(java.util.function.Function) DbAttribute(org.apache.cayenne.map.DbAttribute) ArrayList(java.util.ArrayList) List(java.util.List) ObjectId(org.apache.cayenne.ObjectId) DbJoin(org.apache.cayenne.map.DbJoin) ObjRelationship(org.apache.cayenne.map.ObjRelationship) Map(java.util.Map) CayenneRuntimeException(org.apache.cayenne.CayenneRuntimeException) DbRelationship(org.apache.cayenne.map.DbRelationship) ObjRelationship(org.apache.cayenne.map.ObjRelationship) ObjAttribute(org.apache.cayenne.map.ObjAttribute) ObjectId(org.apache.cayenne.ObjectId) DbAttribute(org.apache.cayenne.map.DbAttribute) CayenneRuntimeException(org.apache.cayenne.CayenneRuntimeException) DbRelationship(org.apache.cayenne.map.DbRelationship) DbJoin(org.apache.cayenne.map.DbJoin)

Aggregations

ObjRelationship (org.apache.cayenne.map.ObjRelationship)84 ObjEntity (org.apache.cayenne.map.ObjEntity)48 ObjAttribute (org.apache.cayenne.map.ObjAttribute)27 DbRelationship (org.apache.cayenne.map.DbRelationship)26 Test (org.junit.Test)24 DbEntity (org.apache.cayenne.map.DbEntity)18 DbAttribute (org.apache.cayenne.map.DbAttribute)15 DbJoin (org.apache.cayenne.map.DbJoin)14 CayenneRuntimeException (org.apache.cayenne.CayenneRuntimeException)12 ClassDescriptor (org.apache.cayenne.reflect.ClassDescriptor)12 ObjectId (org.apache.cayenne.ObjectId)10 ToManyProperty (org.apache.cayenne.reflect.ToManyProperty)9 ToOneProperty (org.apache.cayenne.reflect.ToOneProperty)9 ArrayList (java.util.ArrayList)8 AttributeProperty (org.apache.cayenne.reflect.AttributeProperty)8 PropertyVisitor (org.apache.cayenne.reflect.PropertyVisitor)8 List (java.util.List)7 EJBQLException (org.apache.cayenne.ejbql.EJBQLException)7 DataMap (org.apache.cayenne.map.DataMap)7 HashMap (java.util.HashMap)6