Search in sources :

Example 66 with ObjRelationship

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

the class DropRelationshipToModelIT method testForeignKey.

@Test
public void testForeignKey() throws Exception {
    dropTableIfPresent("NEW_TABLE");
    dropTableIfPresent("NEW_TABLE2");
    assertTokensAndExecute(0, 0);
    DbEntity dbEntity1 = new DbEntity("NEW_TABLE");
    DbAttribute e1col1 = new DbAttribute("ID", Types.INTEGER, dbEntity1);
    e1col1.setMandatory(true);
    e1col1.setPrimaryKey(true);
    dbEntity1.addAttribute(e1col1);
    DbAttribute e1col2 = new DbAttribute("NAME", Types.VARCHAR, dbEntity1);
    e1col2.setMaxLength(10);
    e1col2.setMandatory(false);
    dbEntity1.addAttribute(e1col2);
    map.addDbEntity(dbEntity1);
    DbEntity dbEntity2 = new DbEntity("NEW_TABLE2");
    DbAttribute e2col1 = new DbAttribute("ID", Types.INTEGER, dbEntity2);
    e2col1.setMandatory(true);
    e2col1.setPrimaryKey(true);
    dbEntity2.addAttribute(e2col1);
    DbAttribute e2col2 = new DbAttribute("FK", Types.INTEGER, dbEntity2);
    dbEntity2.addAttribute(e2col2);
    DbAttribute e2col3 = new DbAttribute("NAME", Types.VARCHAR, dbEntity2);
    e2col3.setMaxLength(10);
    dbEntity2.addAttribute(e2col3);
    map.addDbEntity(dbEntity2);
    // create db relationships
    DbRelationship rel1To2 = new DbRelationship("rel1To2");
    rel1To2.setSourceEntity(dbEntity1);
    rel1To2.setTargetEntityName(dbEntity2);
    rel1To2.setToMany(true);
    rel1To2.addJoin(new DbJoin(rel1To2, e1col1.getName(), e2col2.getName()));
    dbEntity1.addRelationship(rel1To2);
    DbRelationship rel2To1 = new DbRelationship("rel2To1");
    rel2To1.setSourceEntity(dbEntity2);
    rel2To1.setTargetEntityName(dbEntity1);
    rel2To1.setToMany(false);
    rel2To1.addJoin(new DbJoin(rel2To1, e2col2.getName(), e1col1.getName()));
    dbEntity2.addRelationship(rel2To1);
    assertSame(rel1To2, rel2To1.getReverseRelationship());
    assertSame(rel2To1, rel1To2.getReverseRelationship());
    assertTokensAndExecute(3, 0);
    assertTokensAndExecute(0, 0);
    // create ObjEntities
    ObjEntity objEntity1 = new ObjEntity("NewTable");
    objEntity1.setDbEntity(dbEntity1);
    ObjAttribute oatr1 = new ObjAttribute("name");
    oatr1.setDbAttributePath(e1col2.getName());
    oatr1.setType("java.lang.String");
    objEntity1.addAttribute(oatr1);
    map.addObjEntity(objEntity1);
    ObjEntity objEntity2 = new ObjEntity("NewTable2");
    objEntity2.setDbEntity(dbEntity2);
    ObjAttribute o2a1 = new ObjAttribute("name");
    o2a1.setDbAttributePath(e2col3.getName());
    o2a1.setType("java.lang.String");
    objEntity2.addAttribute(o2a1);
    map.addObjEntity(objEntity2);
    // create ObjRelationships
    assertEquals(0, objEntity1.getRelationships().size());
    assertEquals(0, objEntity2.getRelationships().size());
    ObjRelationship objRel1To2 = new ObjRelationship("objRel1To2");
    objRel1To2.addDbRelationship(rel1To2);
    objRel1To2.setSourceEntity(objEntity1);
    objRel1To2.setTargetEntityName(objEntity2);
    objEntity1.addRelationship(objRel1To2);
    ObjRelationship objRel2To1 = new ObjRelationship("objRel2To1");
    objRel2To1.addDbRelationship(rel2To1);
    objRel2To1.setSourceEntity(objEntity2);
    objRel2To1.setTargetEntityName(objEntity1);
    objEntity2.addRelationship(objRel2To1);
    assertEquals(1, objEntity1.getRelationships().size());
    assertEquals(1, objEntity2.getRelationships().size());
    assertSame(objRel1To2, objRel2To1.getReverseRelationship());
    assertSame(objRel2To1, objRel1To2.getReverseRelationship());
    // remove relationship and fk from model, merge to db and read to model
    dbEntity2.removeRelationship(rel2To1.getName());
    dbEntity1.removeRelationship(rel1To2.getName());
    dbEntity2.removeAttribute(e2col2.getName());
    List<MergerToken> tokens = createMergeTokens();
    /**
     * Drop Relationship NEW_TABLE2->NEW_TABLE To DB
     * Drop Column NEW_TABLE2.FK To DB
     */
    assertTokens(tokens, 2, 0);
    for (MergerToken token : tokens) {
        if (token.getDirection().isToDb()) {
            execute(token);
        }
    }
    assertTokensAndExecute(0, 0);
    dbEntity2.addRelationship(rel2To1);
    dbEntity1.addRelationship(rel1To2);
    dbEntity2.addAttribute(e2col2);
    // try do use the merger to remove the relationship in the model
    tokens = createMergeTokens();
    assertTokens(tokens, 2, 0);
    // TODO: reversing the following two tokens should also reverse the
    // order
    MergerToken token0 = tokens.get(0).createReverse(mergerFactory());
    MergerToken token1 = tokens.get(1).createReverse(mergerFactory());
    if (!(token0 instanceof DropRelationshipToModel && token1 instanceof DropColumnToModel || token1 instanceof DropRelationshipToModel && token0 instanceof DropColumnToModel)) {
        fail();
    }
    execute(token0);
    execute(token1);
    // check after merging
    assertNull(dbEntity2.getAttribute(e2col2.getName()));
    assertEquals(0, dbEntity1.getRelationships().size());
    assertEquals(0, dbEntity2.getRelationships().size());
    assertEquals(0, objEntity1.getRelationships().size());
    assertEquals(0, objEntity2.getRelationships().size());
    // clear up
    dbEntity1.removeRelationship(rel1To2.getName());
    dbEntity2.removeRelationship(rel2To1.getName());
    map.removeObjEntity(objEntity1.getName(), true);
    map.removeDbEntity(dbEntity1.getName(), true);
    map.removeObjEntity(objEntity2.getName(), true);
    map.removeDbEntity(dbEntity2.getName(), true);
    resolver.refreshMappingCache();
    assertNull(map.getObjEntity(objEntity1.getName()));
    assertNull(map.getDbEntity(dbEntity1.getName()));
    assertNull(map.getObjEntity(objEntity2.getName()));
    assertNull(map.getDbEntity(dbEntity2.getName()));
    assertFalse(map.getDbEntities().contains(dbEntity1));
    assertFalse(map.getDbEntities().contains(dbEntity2));
    assertTokensAndExecute(2, 0);
    assertTokensAndExecute(0, 0);
}
Also used : ObjEntity(org.apache.cayenne.map.ObjEntity) ObjRelationship(org.apache.cayenne.map.ObjRelationship) DbEntity(org.apache.cayenne.map.DbEntity) ObjAttribute(org.apache.cayenne.map.ObjAttribute) DbRelationship(org.apache.cayenne.map.DbRelationship) DbAttribute(org.apache.cayenne.map.DbAttribute) MergerToken(org.apache.cayenne.dbsync.merge.token.MergerToken) DbJoin(org.apache.cayenne.map.DbJoin) Test(org.junit.Test)

Example 67 with ObjRelationship

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

the class NameBuilderTest method testName_ObjEntityContext.

@Test
public void testName_ObjEntityContext() {
    ObjEntity entity = new ObjEntity();
    entity.getCallbackMap().getPostAdd().addCallbackMethod("getMe");
    ObjAttribute a0 = new ObjAttribute();
    String na0 = NameBuilder.builder(a0).in(entity).name();
    assertEquals("untitledAttr", na0);
    a0.setName(na0);
    entity.addAttribute(a0);
    ObjAttribute a1 = new ObjAttribute();
    String na1 = NameBuilder.builder(a1).in(entity).name();
    assertEquals("untitledAttr1", na1);
    a1.setName(na1);
    entity.addAttribute(a1);
    ObjAttribute a2 = new ObjAttribute();
    String na2 = NameBuilder.builder(a2).in(entity).baseName("me").name();
    assertEquals("Conflict with callback method was not detected", "me1", na2);
    a2.setName(na2);
    entity.addAttribute(a2);
    ObjRelationship r0 = new ObjRelationship();
    String nr0 = NameBuilder.builder(r0).in(entity).name();
    assertEquals("untitledRel", nr0);
    r0.setName(nr0);
    entity.addRelationship(r0);
    ObjRelationship r1 = new ObjRelationship();
    String nr1 = NameBuilder.builder(r1).in(entity).name();
    assertEquals("untitledRel1", nr1);
    r1.setName(nr1);
    entity.addRelationship(r1);
}
Also used : ObjEntity(org.apache.cayenne.map.ObjEntity) ObjRelationship(org.apache.cayenne.map.ObjRelationship) ObjAttribute(org.apache.cayenne.map.ObjAttribute) Test(org.junit.Test)

Example 68 with ObjRelationship

use of org.apache.cayenne.map.ObjRelationship 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 69 with ObjRelationship

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

the class BaseDataObject method setReverseRelationship.

/**
 * Initializes reverse relationship from object <code>val</code> to this
 * object.
 *
 * @param relName
 *            name of relationship from this object to <code>val</code>.
 */
protected void setReverseRelationship(String relName, DataObject val) {
    ObjRelationship rel = objectContext.getEntityResolver().getObjEntity(objectId.getEntityName()).getRelationship(relName);
    ObjRelationship revRel = rel.getReverseRelationship();
    if (revRel != null) {
        if (revRel.isToMany()) {
            val.addToManyTarget(revRel.getName(), this, false);
        } else {
            val.setToOneTarget(revRel.getName(), this, false);
        }
    }
}
Also used : ObjRelationship(org.apache.cayenne.map.ObjRelationship)

Example 70 with ObjRelationship

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

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