use of org.apache.cayenne.ashwood.graph.MapDigraph 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);
}
}
use of org.apache.cayenne.ashwood.graph.MapDigraph 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;
}
Aggregations