Search in sources :

Example 1 with IndegreeTopologicalSort

use of org.apache.cayenne.ashwood.graph.IndegreeTopologicalSort 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 2 with IndegreeTopologicalSort

use of org.apache.cayenne.ashwood.graph.IndegreeTopologicalSort in project cayenne by apache.

the class AshwoodEntitySorter method doIndexSorter.

/**
 * Reindexes internal sorter without synchronization.
 */
protected void doIndexSorter() {
    Map<DbEntity, List<DbRelationship>> reflexiveDbEntities = new HashMap<>();
    Digraph<DbEntity, List<DbAttribute>> referentialDigraph = new MapDigraph<>();
    if (entityResolver != null) {
        for (DbEntity entity : entityResolver.getDbEntities()) {
            referentialDigraph.addVertex(entity);
        }
    }
    for (DbEntity destination : entityResolver.getDbEntities()) {
        for (DbRelationship candidate : destination.getRelationships()) {
            if ((!candidate.isToMany() && !candidate.isToDependentPK()) || candidate.isToMasterPK()) {
                DbEntity origin = candidate.getTargetEntity();
                boolean newReflexive = destination.equals(origin);
                for (DbJoin join : candidate.getJoins()) {
                    DbAttribute targetAttribute = join.getTarget();
                    if (targetAttribute.isPrimaryKey()) {
                        if (newReflexive) {
                            List<DbRelationship> reflexiveRels = reflexiveDbEntities.get(destination);
                            if (reflexiveRels == null) {
                                reflexiveRels = new ArrayList<>(1);
                                reflexiveDbEntities.put(destination, reflexiveRels);
                            }
                            reflexiveRels.add(candidate);
                            newReflexive = false;
                        }
                        List<DbAttribute> fks = referentialDigraph.getArc(origin, destination);
                        if (fks == null) {
                            fks = new ArrayList<>();
                            referentialDigraph.putArc(origin, destination, fks);
                        }
                        fks.add(targetAttribute);
                    }
                }
            }
        }
    }
    StrongConnection<DbEntity, List<DbAttribute>> contractor = new StrongConnection<>(referentialDigraph);
    Digraph<Collection<DbEntity>, Collection<List<DbAttribute>>> contractedReferentialDigraph = new MapDigraph<>();
    contractor.contract(contractedReferentialDigraph);
    IndegreeTopologicalSort<Collection<DbEntity>> sorter = new IndegreeTopologicalSort<>(contractedReferentialDigraph);
    Map<DbEntity, ComponentRecord> components = new HashMap<>(contractedReferentialDigraph.order());
    int componentIndex = 0;
    while (sorter.hasNext()) {
        Collection<DbEntity> component = sorter.next();
        ComponentRecord rec = new ComponentRecord(componentIndex++, component);
        for (DbEntity table : component) {
            components.put(table, rec);
        }
    }
    this.reflexiveDbEntities = reflexiveDbEntities;
    this.components = components;
}
Also used : HashMap(java.util.HashMap) DbAttribute(org.apache.cayenne.map.DbAttribute) StrongConnection(org.apache.cayenne.ashwood.graph.StrongConnection) 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) DbJoin(org.apache.cayenne.map.DbJoin) Collection(java.util.Collection) ArrayList(java.util.ArrayList) List(java.util.List)

Aggregations

ArrayList (java.util.ArrayList)2 List (java.util.List)2 IndegreeTopologicalSort (org.apache.cayenne.ashwood.graph.IndegreeTopologicalSort)2 MapDigraph (org.apache.cayenne.ashwood.graph.MapDigraph)2 DbEntity (org.apache.cayenne.map.DbEntity)2 DbRelationship (org.apache.cayenne.map.DbRelationship)2 Collection (java.util.Collection)1 HashMap (java.util.HashMap)1 CayenneRuntimeException (org.apache.cayenne.CayenneRuntimeException)1 Persistent (org.apache.cayenne.Persistent)1 StrongConnection (org.apache.cayenne.ashwood.graph.StrongConnection)1 DbAttribute (org.apache.cayenne.map.DbAttribute)1 DbJoin (org.apache.cayenne.map.DbJoin)1 EntityResolver (org.apache.cayenne.map.EntityResolver)1 ObjRelationship (org.apache.cayenne.map.ObjRelationship)1 ClassDescriptor (org.apache.cayenne.reflect.ClassDescriptor)1