Search in sources :

Example 66 with DbRelationship

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

the class DbRelationshipValidator method checkForDuplicates.

/**
 * Per CAY-1813, make sure two (or more) DbRelationships do not map to the
 * same database path.
 */
private void checkForDuplicates(DbRelationship relationship, ValidationResult validationResult) {
    if (relationship != null && relationship.getName() != null && relationship.getTargetEntityName() != null) {
        String dbRelationshipPath = relationship.getTargetEntityName() + "." + getJoins(relationship);
        DbEntity entity = relationship.getSourceEntity();
        for (DbRelationship comparisonRelationship : entity.getRelationships()) {
            if (relationship != comparisonRelationship) {
                String comparisonDbRelationshipPath = comparisonRelationship.getTargetEntityName() + "." + getJoins(comparisonRelationship);
                if (dbRelationshipPath.equals(comparisonDbRelationshipPath)) {
                    addFailure(validationResult, relationship, "DbEntity '%s' contains a duplicate DbRelationship mapping ('%s' -> '%s')", entity.getName(), relationship.getName(), dbRelationshipPath);
                    // Duplicate found, stop.
                    return;
                }
            }
        }
    }
}
Also used : DbEntity(org.apache.cayenne.map.DbEntity) DbRelationship(org.apache.cayenne.map.DbRelationship)

Example 67 with DbRelationship

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

the class ObjRelationshipValidator method validate.

void validate(ObjRelationship relationship, ValidationResult validationResult) {
    if (Util.isEmptyString(relationship.getName())) {
        addFailure(validationResult, relationship, "Unnamed ObjRelationship");
    } else if (relationship.getSourceEntity().getAttribute(relationship.getName()) != null) {
        // check if there are attributes having the same name
        addFailure(validationResult, relationship, "ObjRelationship '%s' has the same name as one of ObjAttributes", toString(relationship));
    } else {
        NameValidationHelper helper = NameValidationHelper.getInstance();
        String invalidChars = helper.invalidCharsInObjPathComponent(relationship.getName());
        if (invalidChars != null) {
            addFailure(validationResult, relationship, "ObjRelationship name '%s' contains invalid characters: %s", toString(relationship), invalidChars);
        } else if (helper.invalidDataObjectProperty(relationship.getName())) {
            addFailure(validationResult, relationship, "ObjRelationship name '%s' is a reserved word", toString(relationship));
        }
    }
    if (relationship.getTargetEntity() == null) {
        addFailure(validationResult, relationship, "ObjRelationship '%s' has no target entity", toString(relationship));
    } else {
        // check for missing DbRelationship mappings
        List<DbRelationship> dbRels = relationship.getDbRelationships();
        if (dbRels.isEmpty()) {
            addFailure(validationResult, relationship, "ObjRelationship '%s' has no DbRelationship mapping", toString(relationship));
        } else {
            DbEntity expectedSrc = relationship.getSourceEntity().getDbEntity();
            DbEntity expectedTarget = relationship.getTargetEntity().getDbEntity();
            if ((dbRels.get(0)).getSourceEntity() != expectedSrc || (dbRels.get(dbRels.size() - 1)).getTargetEntity() != expectedTarget) {
                addFailure(validationResult, relationship, "ObjRelationship '%s' has incomplete DbRelationship mapping", toString(relationship));
            }
        }
    }
    // foreign key attributes are mandatory.
    if (relationship.isToMany() && !relationship.isFlattened() && (relationship.getDeleteRule() == DeleteRule.NULLIFY)) {
        ObjRelationship inverse = relationship.getReverseRelationship();
        if (inverse != null) {
            DbRelationship firstRel = inverse.getDbRelationships().get(0);
            Iterator<DbJoin> attributePairIterator = firstRel.getJoins().iterator();
            // by default, the relation will be check for mandatory.
            boolean check = true;
            while (attributePairIterator.hasNext()) {
                DbJoin pair = attributePairIterator.next();
                if (!pair.getSource().isMandatory()) {
                    // a field of the fk can be nullable, cancel the check.
                    check = false;
                    break;
                }
            }
            if (check) {
                addFailure(validationResult, relationship, "ObjRelationship '%s' has a Nullify delete rule and a mandatory reverse relationship", toString(relationship));
            }
        }
    }
    // check for relationships with same source and target entities
    ObjEntity entity = relationship.getSourceEntity();
    for (ObjRelationship rel : entity.getRelationships()) {
        if (relationship.getDbRelationshipPath() != null && relationship.getDbRelationshipPath().equals(rel.getDbRelationshipPath())) {
            if (relationship != rel && relationship.getTargetEntity() == rel.getTargetEntity() && relationship.getSourceEntity() == rel.getSourceEntity()) {
                addFailure(validationResult, relationship, "ObjectRelationship '%s' duplicates relationship '%s'", toString(relationship), toString(rel));
            }
        }
    }
    // check for invalid relationships in inherited entities
    if (relationship.getReverseRelationship() != null) {
        ObjRelationship revRel = relationship.getReverseRelationship();
        if (relationship.getSourceEntity() != revRel.getTargetEntity() || relationship.getTargetEntity() != revRel.getSourceEntity()) {
            addFailure(validationResult, revRel, "Usage of super entity's relationships '%s' as reversed relationships for sub entity is discouraged", toString(revRel));
        }
    }
    checkForDuplicates(relationship, validationResult);
}
Also used : ObjRelationship(org.apache.cayenne.map.ObjRelationship) ObjEntity(org.apache.cayenne.map.ObjEntity) DbEntity(org.apache.cayenne.map.DbEntity) DbRelationship(org.apache.cayenne.map.DbRelationship) DbJoin(org.apache.cayenne.map.DbJoin)

Example 68 with DbRelationship

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

the class QualifierTranslator method appendObjectMatch.

protected void appendObjectMatch() throws IOException {
    if (!matchingObject || objectMatchTranslator == null) {
        throw new IllegalStateException("An invalid attempt to append object match.");
    }
    // turn off special handling, so that all the methods behave as a
    // superclass's
    // impl.
    matchingObject = false;
    boolean first = true;
    DbRelationship relationship = objectMatchTranslator.getRelationship();
    if (!relationship.isToMany() && !relationship.isToPK()) {
        queryAssembler.dbRelationshipAdded(relationship, JoinType.INNER, objectMatchTranslator.getJoinSplitAlias());
    }
    Iterator<String> it = objectMatchTranslator.keys();
    while (it.hasNext()) {
        if (first) {
            first = false;
        } else {
            out.append(" AND ");
        }
        String key = it.next();
        DbAttribute attr = objectMatchTranslator.getAttribute(key);
        Object val = objectMatchTranslator.getValue(key);
        processColumn(attr);
        out.append(objectMatchTranslator.getOperation());
        appendLiteral(val, attr, objectMatchTranslator.getExpression());
    }
    objectMatchTranslator.reset();
}
Also used : DbRelationship(org.apache.cayenne.map.DbRelationship) DbAttribute(org.apache.cayenne.map.DbAttribute)

Example 69 with DbRelationship

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

the class AshwoodEntitySorter method sortObjectsForEntity.

@Override
public void sortObjectsForEntity(ObjEntity objEntity, List<?> objects, boolean deleteOrder) {
    indexSorter();
    List<Persistent> persistent = (List<Persistent>) objects;
    DbEntity dbEntity = objEntity.getDbEntity();
    // if no sorting is required
    if (!isReflexive(dbEntity)) {
        return;
    }
    int size = persistent.size();
    if (size == 0) {
        return;
    }
    EntityResolver resolver = persistent.get(0).getObjectContext().getEntityResolver();
    ClassDescriptor descriptor = resolver.getClassDescriptor(objEntity.getName());
    List<DbRelationship> reflexiveRels = reflexiveDbEntities.get(dbEntity);
    String[] reflexiveRelNames = new String[reflexiveRels.size()];
    for (int i = 0; i < reflexiveRelNames.length; i++) {
        DbRelationship dbRel = reflexiveRels.get(i);
        ObjRelationship objRel = (dbRel != null ? objEntity.getRelationshipForDbRelationship(dbRel) : null);
        reflexiveRelNames[i] = (objRel != null ? objRel.getName() : null);
    }
    List<Persistent> sorted = new ArrayList<>(size);
    Digraph<Persistent, Boolean> objectDependencyGraph = new MapDigraph<>();
    Object[] masters = new Object[reflexiveRelNames.length];
    for (int i = 0; i < size; i++) {
        Persistent current = (Persistent) objects.get(i);
        objectDependencyGraph.addVertex(current);
        int actualMasterCount = 0;
        for (int k = 0; k < reflexiveRelNames.length; k++) {
            String reflexiveRelName = reflexiveRelNames[k];
            if (reflexiveRelName == null) {
                continue;
            }
            masters[k] = descriptor.getProperty(reflexiveRelName).readProperty(current);
            if (masters[k] == null) {
                masters[k] = findReflexiveMaster(current, objEntity.getRelationship(reflexiveRelName), current.getObjectId().getEntityName());
            }
            if (masters[k] != null) {
                actualMasterCount++;
            }
        }
        int mastersFound = 0;
        for (int j = 0; j < size && mastersFound < actualMasterCount; j++) {
            if (i == j) {
                continue;
            }
            Persistent masterCandidate = persistent.get(j);
            for (Object master : masters) {
                if (masterCandidate == master) {
                    objectDependencyGraph.putArc(masterCandidate, current, Boolean.TRUE);
                    mastersFound++;
                }
            }
        }
    }
    IndegreeTopologicalSort<Persistent> sorter = new IndegreeTopologicalSort<>(objectDependencyGraph);
    while (sorter.hasNext()) {
        Persistent o = sorter.next();
        if (o == null) {
            throw new CayenneRuntimeException("Sorting objects for %s failed. Cycles found.", objEntity.getClassName());
        }
        sorted.add(o);
    }
    // since API requires sorting within the same array,
    // simply replace all objects with objects in the right order...
    // may come up with something cleaner later
    persistent.clear();
    persistent.addAll(sorted);
    if (deleteOrder) {
        Collections.reverse(persistent);
    }
}
Also used : ObjRelationship(org.apache.cayenne.map.ObjRelationship) ClassDescriptor(org.apache.cayenne.reflect.ClassDescriptor) ArrayList(java.util.ArrayList) CayenneRuntimeException(org.apache.cayenne.CayenneRuntimeException) Persistent(org.apache.cayenne.Persistent) EntityResolver(org.apache.cayenne.map.EntityResolver) IndegreeTopologicalSort(org.apache.cayenne.ashwood.graph.IndegreeTopologicalSort) MapDigraph(org.apache.cayenne.ashwood.graph.MapDigraph) DbEntity(org.apache.cayenne.map.DbEntity) DbRelationship(org.apache.cayenne.map.DbRelationship) ArrayList(java.util.ArrayList) List(java.util.List)

Example 70 with DbRelationship

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

the class AshwoodEntitySorter method findReflexiveMaster.

protected Object findReflexiveMaster(Persistent object, ObjRelationship toOneRel, String targetEntityName) {
    DbRelationship finalRel = toOneRel.getDbRelationships().get(0);
    ObjectContext context = object.getObjectContext();
    // the method
    if (object.getObjectId().isTemporary()) {
        return null;
    }
    ObjectIdQuery query = new ObjectIdQuery(object.getObjectId(), true, ObjectIdQuery.CACHE);
    QueryResponse response = context.getChannel().onQuery(null, query);
    List<?> result = response.firstList();
    if (result == null || result.size() == 0) {
        return null;
    }
    DataRow snapshot = (DataRow) result.get(0);
    ObjectId id = snapshot.createTargetObjectId(targetEntityName, finalRel);
    // hollow objects
    return (id != null) ? context.getGraphManager().getNode(id) : null;
}
Also used : ObjectId(org.apache.cayenne.ObjectId) DbRelationship(org.apache.cayenne.map.DbRelationship) QueryResponse(org.apache.cayenne.QueryResponse) ObjectContext(org.apache.cayenne.ObjectContext) ObjectIdQuery(org.apache.cayenne.query.ObjectIdQuery) DataRow(org.apache.cayenne.DataRow)

Aggregations

DbRelationship (org.apache.cayenne.map.DbRelationship)106 DbEntity (org.apache.cayenne.map.DbEntity)59 DbAttribute (org.apache.cayenne.map.DbAttribute)35 DbJoin (org.apache.cayenne.map.DbJoin)35 ObjEntity (org.apache.cayenne.map.ObjEntity)30 ObjRelationship (org.apache.cayenne.map.ObjRelationship)28 ObjAttribute (org.apache.cayenne.map.ObjAttribute)20 Test (org.junit.Test)15 ClassDescriptor (org.apache.cayenne.reflect.ClassDescriptor)13 ArrayList (java.util.ArrayList)11 CayenneRuntimeException (org.apache.cayenne.CayenneRuntimeException)10 EJBQLException (org.apache.cayenne.ejbql.EJBQLException)9 DataMap (org.apache.cayenne.map.DataMap)9 Entity (org.apache.cayenne.map.Entity)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 HashMap (java.util.HashMap)6 ObjectId (org.apache.cayenne.ObjectId)6