Search in sources :

Example 1 with ObjAttribute

use of org.apache.cayenne.map.ObjAttribute 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 ObjAttribute

use of org.apache.cayenne.map.ObjAttribute 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)

Example 3 with ObjAttribute

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

the class DataRowUtils method refreshObjectWithSnapshot.

/**
 * Replaces all object attribute values with snapshot values. Sets object state to
 * COMMITTED, unless the snapshot is partial in which case the state is set to HOLLOW
 */
static void refreshObjectWithSnapshot(ClassDescriptor descriptor, final Persistent object, final DataRow snapshot, final boolean invalidateToManyRelationships) {
    final boolean[] isPartialSnapshot = new boolean[1];
    descriptor.visitProperties(new PropertyVisitor() {

        public boolean visitAttribute(AttributeProperty property) {
            ObjAttribute attr = property.getAttribute();
            String dbAttrPath = attr.getDbAttributePath();
            Object value = snapshot.get(dbAttrPath);
            property.writePropertyDirectly(object, null, value);
            // checking for the null value first
            if (value == null && !snapshot.containsKey(dbAttrPath)) {
                isPartialSnapshot[0] = true;
            }
            return true;
        }

        public boolean visitToMany(ToManyProperty property) {
            // snapshot
            if (invalidateToManyRelationships) {
                property.invalidate(object);
            }
            return true;
        }

        public boolean visitToOne(ToOneProperty property) {
            property.invalidate(object);
            return true;
        }
    });
    object.setPersistenceState(isPartialSnapshot[0] ? PersistenceState.HOLLOW : PersistenceState.COMMITTED);
}
Also used : ObjAttribute(org.apache.cayenne.map.ObjAttribute) ToManyProperty(org.apache.cayenne.reflect.ToManyProperty) AttributeProperty(org.apache.cayenne.reflect.AttributeProperty) PropertyVisitor(org.apache.cayenne.reflect.PropertyVisitor) ToOneProperty(org.apache.cayenne.reflect.ToOneProperty)

Example 4 with ObjAttribute

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

the class PrefetchProcessorJointNode method buildRowMapping.

/**
 * Configures row columns mapping for this node entity.
 */
private void buildRowMapping() {
    final Map<String, ColumnDescriptor> targetSource = new TreeMap<>();
    // build a DB path .. find parent node that terminates the joint group...
    PrefetchTreeNode jointRoot = this;
    while (jointRoot.getParent() != null && !jointRoot.isDisjointPrefetch() && !jointRoot.isDisjointByIdPrefetch()) {
        jointRoot = jointRoot.getParent();
    }
    final String prefix;
    if (jointRoot != this) {
        Expression objectPath = ExpressionFactory.exp(getPath(jointRoot));
        ASTPath translated = (ASTPath) ((PrefetchProcessorNode) jointRoot).getResolver().getEntity().translateToDbPath(objectPath);
        // make sure we do not include "db:" prefix
        prefix = translated.getOperand(0) + ".";
    } else {
        prefix = "";
    }
    if (getParent() != null && !getParent().isPhantom() && getIncoming() != null && !getIncoming().getRelationship().isFlattened()) {
        DbRelationship r = getIncoming().getRelationship().getDbRelationships().get(0);
        for (final DbJoin join : r.getJoins()) {
            appendColumn(targetSource, join.getTargetName(), prefix + join.getTargetName());
        }
    }
    ClassDescriptor descriptor = resolver.getDescriptor();
    descriptor.visitAllProperties(new PropertyVisitor() {

        public boolean visitAttribute(AttributeProperty property) {
            String target = property.getAttribute().getDbAttributePath();
            appendColumn(targetSource, target, prefix + target);
            return true;
        }

        public boolean visitToMany(ToManyProperty property) {
            return visitRelationship(property);
        }

        public boolean visitToOne(ToOneProperty property) {
            return visitRelationship(property);
        }

        private boolean visitRelationship(ArcProperty arc) {
            DbRelationship dbRel = arc.getRelationship().getDbRelationships().get(0);
            for (DbAttribute attribute : dbRel.getSourceAttributes()) {
                String target = attribute.getName();
                appendColumn(targetSource, target, prefix + target);
            }
            return true;
        }
    });
    // append id columns ... (some may have been appended already via relationships)
    for (String pkName : descriptor.getEntity().getPrimaryKeyNames()) {
        appendColumn(targetSource, pkName, prefix + pkName);
    }
    // append inheritance discriminator columns...
    for (ObjAttribute column : descriptor.getDiscriminatorColumns()) {
        String target = column.getDbAttributePath();
        appendColumn(targetSource, target, prefix + target);
    }
    int size = targetSource.size();
    this.rowCapacity = (int) Math.ceil(size / 0.75);
    this.columns = new ColumnDescriptor[size];
    targetSource.values().toArray(columns);
}
Also used : ArcProperty(org.apache.cayenne.reflect.ArcProperty) ClassDescriptor(org.apache.cayenne.reflect.ClassDescriptor) ObjAttribute(org.apache.cayenne.map.ObjAttribute) ColumnDescriptor(org.apache.cayenne.access.jdbc.ColumnDescriptor) DbAttribute(org.apache.cayenne.map.DbAttribute) TreeMap(java.util.TreeMap) AttributeProperty(org.apache.cayenne.reflect.AttributeProperty) ToOneProperty(org.apache.cayenne.reflect.ToOneProperty) ToManyProperty(org.apache.cayenne.reflect.ToManyProperty) Expression(org.apache.cayenne.exp.Expression) PrefetchTreeNode(org.apache.cayenne.query.PrefetchTreeNode) DbRelationship(org.apache.cayenne.map.DbRelationship) DbJoin(org.apache.cayenne.map.DbJoin) ASTPath(org.apache.cayenne.exp.parser.ASTPath) PropertyVisitor(org.apache.cayenne.reflect.PropertyVisitor)

Example 5 with ObjAttribute

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

the class EJBQLIdColumnsTranslator method visitIdentifier.

@Override
public boolean visitIdentifier(EJBQLExpression expression) {
    Map<String, String> fields = null;
    if (context.isAppendingResultColumns()) {
        fields = context.nextEntityResult().getFields();
    }
    String idVar = expression.getText();
    ClassDescriptor descriptor = context.getEntityDescriptor(idVar);
    ObjEntity oe = descriptor.getEntity();
    for (ObjAttribute oa : oe.getPrimaryKeys()) {
        DbAttribute t = oe.getDbEntity().getAttribute(oa.getDbAttributeName());
        appendColumn(idVar, oa, t, fields, oa.getType());
    }
    return false;
}
Also used : ObjEntity(org.apache.cayenne.map.ObjEntity) ClassDescriptor(org.apache.cayenne.reflect.ClassDescriptor) ObjAttribute(org.apache.cayenne.map.ObjAttribute) DbAttribute(org.apache.cayenne.map.DbAttribute)

Aggregations

ObjAttribute (org.apache.cayenne.map.ObjAttribute)81 ObjEntity (org.apache.cayenne.map.ObjEntity)57 DbAttribute (org.apache.cayenne.map.DbAttribute)31 ObjRelationship (org.apache.cayenne.map.ObjRelationship)27 DbEntity (org.apache.cayenne.map.DbEntity)26 Test (org.junit.Test)26 DbRelationship (org.apache.cayenne.map.DbRelationship)19 DbJoin (org.apache.cayenne.map.DbJoin)12 DataMap (org.apache.cayenne.map.DataMap)9 ClassDescriptor (org.apache.cayenne.reflect.ClassDescriptor)9 HashMap (java.util.HashMap)8 CayenneRuntimeException (org.apache.cayenne.CayenneRuntimeException)8 AttributeProperty (org.apache.cayenne.reflect.AttributeProperty)8 PropertyVisitor (org.apache.cayenne.reflect.PropertyVisitor)8 ToManyProperty (org.apache.cayenne.reflect.ToManyProperty)8 ToOneProperty (org.apache.cayenne.reflect.ToOneProperty)8 ArrayList (java.util.ArrayList)7 DataChannelDescriptor (org.apache.cayenne.configuration.DataChannelDescriptor)7 HashSet (java.util.HashSet)6 Expression (org.apache.cayenne.exp.Expression)6