Author: lresende
Date: Fri May  2 13:34:32 2008
New Revision: 652897

URL: http://svn.apache.org/viewvc?rev=652897&view=rev
Log:
TUSCANY-2288 - Patch from Florian Pinal with updates to  
MappingWrapper.getInsertOrder() algorithm

Modified:
    
incubator/tuscany/java/das/rdb/src/main/java/org/apache/tuscany/das/rdb/config/wrapper/MappingWrapper.java

Modified: 
incubator/tuscany/java/das/rdb/src/main/java/org/apache/tuscany/das/rdb/config/wrapper/MappingWrapper.java
URL: 
http://svn.apache.org/viewvc/incubator/tuscany/java/das/rdb/src/main/java/org/apache/tuscany/das/rdb/config/wrapper/MappingWrapper.java?rev=652897&r1=652896&r2=652897&view=diff
==============================================================================
--- 
incubator/tuscany/java/das/rdb/src/main/java/org/apache/tuscany/das/rdb/config/wrapper/MappingWrapper.java
 (original)
+++ 
incubator/tuscany/java/das/rdb/src/main/java/org/apache/tuscany/das/rdb/config/wrapper/MappingWrapper.java
 Fri May  2 13:34:32 2008
@@ -22,9 +22,11 @@
 import java.util.Collection;
 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;
 import java.util.Vector;
 
 import org.apache.log4j.Logger;
@@ -51,6 +53,12 @@
     private final Logger logger = Logger.getLogger(MappingWrapper.class);
 
     private Config config;
+    
+       // TUSCANY-2288
+       private List insertOrder;
+       private List deleteOrder;
+       // --
+
 
     public MappingWrapper() {
         config = FACTORY.createConfig();
@@ -600,57 +608,143 @@
         return results;
     }
 
-    // TODO optimize
-    public List getInsertOrder() {
-        if (this.logger.isDebugEnabled()) {
-            this.logger.debug("Getting insert order");
-        }
-
-        List inserts = new ArrayList();
-        Map parentToChild = new HashMap();
-
-        List parents = new ArrayList();
-        List children = new ArrayList();
-        if (config != null) {
-            Iterator i = getConfig().getRelationship().iterator();
-            while (i.hasNext()) {
-                Relationship r = (Relationship) i.next();
-                parents.add(r.getPrimaryKeyTable());
-                children.add(r.getForeignKeyTable());
-                parentToChild.put(r.getPrimaryKeyTable(), 
r.getForeignKeyTable());
-            }
-            while (parents.size() > 0) {
-                String parent = (String) parents.get(0);
-                if (!children.contains(parent)) {
-                    if (!inserts.contains(parent)) {
-                        inserts.add(parent);
-                    }
-                    String child = (String) parentToChild.get(parent);
-                    if (!inserts.contains(child)) {
-                        inserts.add(child);
-                    }
-                    parents.remove(parent);
-                    children.remove(child);
-                } else {
-                    parents.add(parents.remove(0));
-                }
-            }
-            inserts.addAll(children);
-        }
-
-        if (this.logger.isDebugEnabled()) {
-            this.logger.debug(inserts);
-        }
+       // TUSCANY-2288
+       public List getInsertOrder() {
+               if (this.logger.isDebugEnabled()) {
+                       this.logger.debug("Getting insert order");
+               }
+               if (insertOrder == null) {
+                       insertOrder = new ArrayList();
+                       if (config == null) return insertOrder;
+                       // correct insert order: tables sorted by ascending 
depth
+                       // parse all relationships
+                       Set allParents = new HashSet();
+                       Set allChildren = new HashSet();
+                       Map parentToChild = new HashMap();
+                       Iterator i = getConfig().getRelationship().iterator();
+                       while (i.hasNext()) {
+                               Relationship r = (Relationship) i.next();
+                               String parent = r.getPrimaryKeyTable();
+                               String child = r.getForeignKeyTable();
+                               if (parent.equals(child)) {
+                                       // self-relationship
+                                       // do not add to parent to child map to 
avoid loops
+                                       // do not add to all children list to 
allow root detection
+                                       allParents.add(parent);
+                               } else {
+                                       allParents.add(parent);
+                                       allChildren.add(child);
+                                       Set children = (Set) 
parentToChild.get(parent);
+                                       if (children == null) {
+                                               children = new HashSet();
+                                               parentToChild.put(parent, 
children);
+                                       }
+                                       children.add(child);
+                               }
+                       }
+                       // build list of tables ordered by depth
+                       List depthList = new ArrayList();
+                       // find roots (depth 0)
+                       // roots are tables that are present in the parents 
set, but not in the children set
+                       Set roots = new HashSet();
+                       for (Iterator itParents = allParents.iterator(); 
itParents.hasNext(); ) {
+                               String parent = (String) itParents.next();
+                               if (!allChildren.contains(parent)) {
+                                       roots.add(parent);
+                               }
+                       }
+                       // traverse table graph to populate depth list
+                       traverseTableGraph(roots, 0, parentToChild, depthList, 
new ArrayList());
+                       // build insert order from depth list
+                       for (Iterator itDepths = depthList.iterator(); 
itDepths.hasNext(); ) {
+                               Set tables = (Set) itDepths.next();
+                               insertOrder.addAll(tables);
+                       }
+               }
+               if (this.logger.isDebugEnabled()) {
+                       this.logger.debug(insertOrder);
+               }
+               return insertOrder;
+       }
+
+       private void traverseTableGraph(Set parents, int parentDepth, Map 
parentToChild, List depthList, List branch) {
+               int childDepth = parentDepth + 1;
+               // expand depth list if necessary
+               for (int i = depthList.size() - 1; i < parentDepth; i++) {
+                       Set tables = new HashSet();
+                       depthList.add(tables);
+               }
+               // loop thru parents
+               for (Iterator itParents = parents.iterator(); 
itParents.hasNext(); ) {
+                       String parent = (String) itParents.next();
+                       if (branch.contains(parent)) {
+                               // we found a cycle
+                               // we don't handle cycles
+                               // stop traversing branch to avoid infinite loop
+                               break;
+                       }
+                       // add parent to depth list
+                       addTableToDepthList(parent, parentDepth, depthList);
+                       // make recursive call on children
+                       Set children = (Set) parentToChild.get(parent);
+                       if (children != null && children.size() > 0) {
+                               List parentBranch = new ArrayList();
+                               parentBranch.addAll(branch);
+                               parentBranch.add(parent);
+                               traverseTableGraph(children, childDepth, 
parentToChild, depthList, parentBranch);
+                       }
+               }
+       }
+
+       private void addTableToDepthList(String table, int depth, List 
depthList) {
+               // in this method, keep in mind that the same table can appear 
multiple times at multiple depths inside the table graph
+               // check if table is already somewhere in depth list
+               int currentDepth = getTableDepth(table, depthList);
+               if (currentDepth == -1) {
+                       // table not in depth list
+                       // add it
+                       Set tables = (Set) depthList.get(depth);
+                       tables.add(table);
+               } else if (currentDepth < depth) {
+                       // table already in depth list, at a lower depth
+                       // the table should only be present once, at the 
greatest possible depth
+                       // replace table at the new depth
+                       Set tables = (Set) depthList.get(currentDepth);
+                       tables.remove(table);
+                       tables = (Set) depthList.get(depth);
+                       tables.add(table);
+               } else {
+                       // table already in depth list, at a greater or same 
depth
+                       // nothing to do, since the table should only be 
present once, at the greatest possible depth
+               }
+       }
+
+       private int getTableDepth(String table, List depthList) {
+               int depth = -1;
+               // loop thru depth list
+               int count = depthList.size();
+               for (int i = 0; i < count; i++) {
+                       Set tables = (Set) depthList.get(i);
+                       if (tables != null && tables.contains(table)) {
+                               depth = i;
+                               break;
+                       }
+               }
+               return depth;
+       }
+
+
+       public List getDeleteOrder() {
+               if (deleteOrder == null) {
+                       deleteOrder = new ArrayList();
+                       deleteOrder.addAll(getInsertOrder());
+                       Collections.reverse(deleteOrder);
+               }
+               return deleteOrder;
+       }
 
-        return inserts;
-    }
+       // --
 
-    public List getDeleteOrder() {
-        List deleteOrder = new ArrayList();
-        deleteOrder.addAll(getInsertOrder());
-        Collections.reverse(deleteOrder);
-        return deleteOrder;
-    }
 
     //JIRA-952
     public void addConverter(String name, String converter) {


Reply via email to