Author: aadamchik
Date: Mon Aug 30 16:49:58 2010
New Revision: 990859
URL: http://svn.apache.org/viewvc?rev=990859&view=rev
Log:
CAY-1479 EntitySorter refactoring: make it DI-based, internalize Ashowood lib
* more generics cleanup
* removing synchronized blocks from AshwoodEntitySorter. It is using double
check locking now instead
Modified:
cayenne/main/trunk/framework/cayenne-jdk1.5-unpublished/src/main/java/org/apache/cayenne/ashwood/AshwoodEntitySorter.java
cayenne/main/trunk/framework/cayenne-jdk1.5-unpublished/src/main/java/org/apache/cayenne/ashwood/graph/IndegreeTopologicalSort.java
cayenne/main/trunk/framework/cayenne-jdk1.5-unpublished/src/main/java/org/apache/cayenne/ashwood/graph/StrongConnection.java
Modified:
cayenne/main/trunk/framework/cayenne-jdk1.5-unpublished/src/main/java/org/apache/cayenne/ashwood/AshwoodEntitySorter.java
URL:
http://svn.apache.org/viewvc/cayenne/main/trunk/framework/cayenne-jdk1.5-unpublished/src/main/java/org/apache/cayenne/ashwood/AshwoodEntitySorter.java?rev=990859&r1=990858&r2=990859&view=diff
==============================================================================
---
cayenne/main/trunk/framework/cayenne-jdk1.5-unpublished/src/main/java/org/apache/cayenne/ashwood/AshwoodEntitySorter.java
(original)
+++
cayenne/main/trunk/framework/cayenne-jdk1.5-unpublished/src/main/java/org/apache/cayenne/ashwood/AshwoodEntitySorter.java
Mon Aug 30 16:49:58 2010
@@ -63,7 +63,6 @@ public class AshwoodEntitySorter impleme
protected Collection<DataMap> dataMaps;
protected Map<DbEntity, Table> dbEntityToTableMap;
- protected Digraph<Collection<Table>, List<ForeignKey>>
contractedReferentialDigraph;
protected Map<Table, ComponentRecord> components;
protected Map<DbEntity, List<DbRelationship>> reflexiveDbEntities;
@@ -71,8 +70,7 @@ public class AshwoodEntitySorter impleme
protected DbEntityComparator dbEntityComparator;
protected ObjEntityComparator objEntityComparator;
- // used for lazy initialization
- protected boolean dirty;
+ private volatile boolean dirty;
public AshwoodEntitySorter() {
tableComparator = new TableComparator();
@@ -88,12 +86,28 @@ public class AshwoodEntitySorter impleme
}
/**
- * Reindexes internal sorter.
+ * Reindexes internal sorter in a thread-safe manner.
*/
- protected synchronized void _indexSorter() {
- if (!dirty) {
- return;
+ protected void indexSorter() {
+
+ // correct double check locking per Joshua Bloch
+ //
http://java.sun.com/developer/technicalArticles/Interviews/bloch_effective_08_qa.html
+ // (maybe we should use something like CountDownLatch or a Cyclic
barrier
+ // instead?)
+
+ boolean localDirty = dirty;
+ if (localDirty) {
+ synchronized (this) {
+ localDirty = dirty;
+ if (localDirty) {
+ doIndexSorter();
+ dirty = false;
+ }
+ }
}
+ }
+
+ private void doIndexSorter() {
Collection<Table> tables = new ArrayList<Table>(64);
dbEntityToTableMap = new HashMap<DbEntity, Table>(64);
@@ -112,15 +126,17 @@ public class AshwoodEntitySorter impleme
Digraph<Table, List<ForeignKey>> referentialDigraph = new
MapDigraph<Table, List<ForeignKey>>();
DbUtils.buildReferentialDigraph(referentialDigraph, tables);
- StrongConnection contractor = new StrongConnection(referentialDigraph);
+ StrongConnection<Table, List<ForeignKey>> contractor = new
StrongConnection<Table, List<ForeignKey>>(
+ referentialDigraph);
- contractedReferentialDigraph = new MapDigraph<Collection<Table>,
List<ForeignKey>>();
+ Digraph<Collection<Table>, Collection<List<ForeignKey>>>
contractedReferentialDigraph = new MapDigraph<Collection<Table>,
Collection<List<ForeignKey>>>();
contractor.contract(contractedReferentialDigraph);
- IndegreeTopologicalSort<Collection<Table>, List<ForeignKey>> sorter =
new IndegreeTopologicalSort<Collection<Table>, List<ForeignKey>>(
+ IndegreeTopologicalSort<Collection<Table>> sorter = new
IndegreeTopologicalSort<Collection<Table>>(
contractedReferentialDigraph);
- components = new HashMap(contractedReferentialDigraph.order());
+ components = new HashMap<Table,
ComponentRecord>(contractedReferentialDigraph
+ .order());
int componentIndex = 0;
while (sorter.hasNext()) {
Collection<Table> component = sorter.next();
@@ -130,36 +146,34 @@ public class AshwoodEntitySorter impleme
components.put(table, rec);
}
}
-
- // clear dirty flag
- this.dirty = false;
}
/**
* @since 1.1
*/
- public synchronized void setDataMaps(Collection<DataMap> dataMaps) {
- this.dirty = true;
+ public void setDataMaps(Collection<DataMap> dataMaps) {
this.dataMaps = dataMaps != null ? dataMaps : Collections.EMPTY_LIST;
+ this.dirty = true;
}
public void sortDbEntities(List<DbEntity> dbEntities, boolean deleteOrder)
{
- _indexSorter();
+ indexSorter();
Collections.sort(dbEntities, getDbEntityComparator(deleteOrder));
}
public void sortObjEntities(List<ObjEntity> objEntities, boolean
deleteOrder) {
- _indexSorter();
+ indexSorter();
Collections.sort(objEntities, getObjEntityComparator(deleteOrder));
}
public void sortObjectsForEntity(
ObjEntity objEntity,
- List objects,
+ List<?> objects,
boolean deleteOrder) {
- // don't forget to index the sorter
- _indexSorter();
+ indexSorter();
+
+ List<Persistent> persistent = (List<Persistent>) objects;
DbEntity dbEntity = objEntity.getDbEntity();
@@ -168,12 +182,13 @@ public class AshwoodEntitySorter impleme
return;
}
- int size = objects.size();
+ int size = persistent.size();
if (size == 0) {
return;
}
- EntityResolver resolver = ((Persistent) objects.get(0))
+ EntityResolver resolver = persistent
+ .get(0)
.getObjectContext()
.getEntityResolver();
ClassDescriptor descriptor =
resolver.getClassDescriptor(objEntity.getName());
@@ -187,9 +202,9 @@ public class AshwoodEntitySorter impleme
reflexiveRelNames[i] = (objRel != null ? objRel.getName() : null);
}
- List<Object> sorted = new ArrayList<Object>(size);
+ List<Persistent> sorted = new ArrayList<Persistent>(size);
- Digraph objectDependencyGraph = new MapDigraph();
+ Digraph<Persistent, Boolean> objectDependencyGraph = new
MapDigraph<Persistent, Boolean>();
Object[] masters = new Object[reflexiveRelNames.length];
for (int i = 0; i < size; i++) {
Persistent current = (Persistent) objects.get(i);
@@ -224,7 +239,7 @@ public class AshwoodEntitySorter impleme
continue;
}
- Object masterCandidate = objects.get(j);
+ Persistent masterCandidate = persistent.get(j);
for (Object master : masters) {
if (masterCandidate.equals(master)) {
objectDependencyGraph.putArc(
@@ -237,11 +252,11 @@ public class AshwoodEntitySorter impleme
}
}
- IndegreeTopologicalSort sorter = new IndegreeTopologicalSort(
+ IndegreeTopologicalSort<Persistent> sorter = new
IndegreeTopologicalSort<Persistent>(
objectDependencyGraph);
while (sorter.hasNext()) {
- Object o = sorter.next();
+ Persistent o = sorter.next();
if (o == null)
throw new CayenneRuntimeException("Sorting objects for "
+ objEntity.getClassName()
@@ -252,11 +267,11 @@ public class AshwoodEntitySorter impleme
// 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
- objects.clear();
- objects.addAll(sorted);
+ persistent.clear();
+ persistent.addAll(sorted);
if (deleteOrder) {
- Collections.reverse(objects);
+ Collections.reverse(persistent);
}
}
@@ -330,8 +345,8 @@ public class AshwoodEntitySorter impleme
return (id != null) ? context.localObject(id, null) : null;
}
- protected Comparator getDbEntityComparator(boolean dependantFirst) {
- Comparator c = dbEntityComparator;
+ protected Comparator<DbEntity> getDbEntityComparator(boolean
dependantFirst) {
+ Comparator<DbEntity> c = dbEntityComparator;
if (dependantFirst) {
c = new ReverseComparator(c);
}
@@ -392,8 +407,8 @@ public class AshwoodEntitySorter impleme
else if (t2 == null)
result = 1;
else {
- ComponentRecord rec1 = (ComponentRecord) components.get(t1);
- ComponentRecord rec2 = (ComponentRecord) components.get(t2);
+ ComponentRecord rec1 = components.get(t1);
+ ComponentRecord rec2 = components.get(t2);
int index1 = rec1.index;
int index2 = rec2.index;
result = (index1 > index2 ? 1 : (index1 < index2 ? -1 : 0));
Modified:
cayenne/main/trunk/framework/cayenne-jdk1.5-unpublished/src/main/java/org/apache/cayenne/ashwood/graph/IndegreeTopologicalSort.java
URL:
http://svn.apache.org/viewvc/cayenne/main/trunk/framework/cayenne-jdk1.5-unpublished/src/main/java/org/apache/cayenne/ashwood/graph/IndegreeTopologicalSort.java?rev=990859&r1=990858&r2=990859&view=diff
==============================================================================
---
cayenne/main/trunk/framework/cayenne-jdk1.5-unpublished/src/main/java/org/apache/cayenne/ashwood/graph/IndegreeTopologicalSort.java
(original)
+++
cayenne/main/trunk/framework/cayenne-jdk1.5-unpublished/src/main/java/org/apache/cayenne/ashwood/graph/IndegreeTopologicalSort.java
Mon Aug 30 16:49:58 2010
@@ -66,14 +66,14 @@ import java.util.List;
import java.util.ListIterator;
import java.util.Map;
-public class IndegreeTopologicalSort<E, V> extends Algorithm<E> {
+public class IndegreeTopologicalSort<E> extends Algorithm<E> {
- private Digraph<E, V> digraph;
+ private Digraph<E, ?> digraph;
private List<E> vertices = new LinkedList<E>();
private Map<E, InDegree> inDegrees = new HashMap<E, InDegree>();
private ListIterator<E> current;
- public IndegreeTopologicalSort(Digraph<E, V> digraph) {
+ public IndegreeTopologicalSort(Digraph<E, ?> digraph) {
this.digraph = digraph;
for (Iterator<E> i = digraph.vertexIterator(); i.hasNext();) {
E vertex = i.next();
@@ -110,7 +110,7 @@ public class IndegreeTopologicalSort<E,
}
private void removeVertex(E vertex) {
- for (ArcIterator<E, V> i = digraph.outgoingIterator(vertex);
i.hasNext();) {
+ for (ArcIterator<E, ?> i = digraph.outgoingIterator(vertex);
i.hasNext();) {
i.next();
E dst = i.getDestination();
InDegree indegree = inDegrees.get(dst);
Modified:
cayenne/main/trunk/framework/cayenne-jdk1.5-unpublished/src/main/java/org/apache/cayenne/ashwood/graph/StrongConnection.java
URL:
http://svn.apache.org/viewvc/cayenne/main/trunk/framework/cayenne-jdk1.5-unpublished/src/main/java/org/apache/cayenne/ashwood/graph/StrongConnection.java?rev=990859&r1=990858&r2=990859&view=diff
==============================================================================
---
cayenne/main/trunk/framework/cayenne-jdk1.5-unpublished/src/main/java/org/apache/cayenne/ashwood/graph/StrongConnection.java
(original)
+++
cayenne/main/trunk/framework/cayenne-jdk1.5-unpublished/src/main/java/org/apache/cayenne/ashwood/graph/StrongConnection.java
Mon Aug 30 16:49:58 2010
@@ -65,7 +65,6 @@ import java.util.Collections;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Iterator;
-import java.util.List;
import java.util.Map;
import java.util.Set;
@@ -74,11 +73,11 @@ import org.apache.commons.collections.Co
import org.apache.commons.collections.Predicate;
import org.apache.commons.collections.functors.TruePredicate;
-public class StrongConnection<E> extends Algorithm<Collection<E>> {
+public class StrongConnection<E, V> extends Algorithm<Collection<E>> {
- private DigraphIteration digraph;
- private DigraphIteration reverseDigraph;
- private DigraphIteration filteredDigraph;
+ private DigraphIteration<E, V> digraph;
+ private DigraphIteration<E, V> reverseDigraph;
+ private DigraphIteration<E, V> filteredDigraph;
private DepthFirstStampSearch directDfs;
private DepthFirstSearch reverseDfs;
private Set seen = new HashSet();
@@ -86,7 +85,7 @@ public class StrongConnection<E> extends
private ArrayStack dfsStack = new ArrayStack();
private DFSSeenVerticesPredicate reverseDFSFilter = new
DFSSeenVerticesPredicate();
- public StrongConnection(DigraphIteration digraph) {
+ public StrongConnection(DigraphIteration<E, V> digraph) {
this.digraph = digraph;
filteredDigraph = new FilterIteration(
digraph,
@@ -100,10 +99,12 @@ public class StrongConnection<E> extends
runDirectDFS();
}
+ @Override
public boolean hasNext() {
return !dfsStack.isEmpty();
}
+ @Override
public Collection<E> next() {
Collection component = buildStronglyConnectedComponent();
if (dfsStack.isEmpty())
@@ -111,38 +112,41 @@ public class StrongConnection<E> extends
return component;
}
- public Digraph contract(Digraph contractedDigraph) {
- List components = new ArrayList();
+ public Digraph<Collection<E>, Collection<V>>
contract(Digraph<Collection<E>, Collection<V>> contractedDigraph) {
+
+ Collection<Collection<E>> components = new ArrayList<Collection<E>>();
CollectionUtils.addAll(components, this);
- Map memberToComponent = new HashMap();
- for (Iterator i = components.iterator(); i.hasNext();) {
- Collection c = (Collection) i.next();
- for (Iterator j = c.iterator(); j.hasNext();)
- memberToComponent.put(j.next(), c);
+
+ Map<E, Collection<E>> memberToComponent = new HashMap<E,
Collection<E>>();
+
+ for (Collection<E> c : components) {
+ for (E e : c) {
+ memberToComponent.put(e, c);
+ }
}
- for (Iterator i = components.iterator(); i.hasNext();) {
- Collection origin = (Collection) i.next();
+
+ for (Collection<E> origin : components) {
+
contractedDigraph.addVertex(origin);
- for (Iterator j = origin.iterator(); j.hasNext();) {
- Object member = j.next();
- for (ArcIterator k = digraph.outgoingIterator(member);
k.hasNext();) {
- Object arc = k.next();
- Object dst = k.getDestination();
+
+ for (E member : origin) {
+
+ for (ArcIterator<E, V> k = digraph.outgoingIterator(member);
k.hasNext();) {
+ V arc = k.next();
+ E dst = k.getDestination();
if (origin.contains(dst))
continue;
- Collection destination = (Collection)
memberToComponent.get(dst);
+ Collection<E> destination = memberToComponent.get(dst);
- Collection contractedArc = (Collection)
contractedDigraph.getArc(
- origin,
- destination);
+ Collection<V> contractedArc =
contractedDigraph.getArc(origin, destination);
if (contractedArc == null) {
contractedArc = Collections.singletonList(arc);
contractedDigraph.putArc(origin, destination,
contractedArc);
}
else {
if (contractedArc.size() == 1) {
- Collection tmp = contractedArc;
- contractedArc = new ArrayList<E>();
+ Collection<V> tmp = contractedArc;
+ contractedArc = new ArrayList<V>();
contractedArc.addAll(tmp);
contractedDigraph.putArc(origin, destination,
contractedArc);
}
@@ -156,10 +160,6 @@ public class StrongConnection<E> extends
}
private Object nextDFSRoot() {
- /*
- * while (vertexIterator.hasNext()) { Object vertex =
vertexIterator.next(); if
- * (!seen.contains(vertex)) return vertex; } return null;
- */
return (vertexIterator.hasNext() ? vertexIterator.next() : null);
}