Author: amita
Date: Thu Oct 25 01:06:16 2007
New Revision: 588159

URL: http://svn.apache.org/viewvc?rev=588159&view=rev
Log:
TUSCANY-1815 Graph Merger improvement to allow secondary DataObjects without 
ChangeSummary to be treated for CREATE

Added:
    incubator/tuscany/java/das/rdb/src/test/resources/SINGER.xsd
Modified:
    incubator/tuscany/java/das/rdb/pom.xml
    
incubator/tuscany/java/das/rdb/src/main/java/org/apache/tuscany/das/rdb/graphbuilder/impl/MultiTableRegistry.java
    
incubator/tuscany/java/das/rdb/src/main/java/org/apache/tuscany/das/rdb/graphbuilder/impl/SingleTableRegistry.java
    
incubator/tuscany/java/das/rdb/src/main/java/org/apache/tuscany/das/rdb/graphbuilder/impl/TableRegistry.java
    
incubator/tuscany/java/das/rdb/src/main/java/org/apache/tuscany/das/rdb/merge/impl/GraphMerger.java
    
incubator/tuscany/java/das/rdb/src/test/java/org/apache/tuscany/das/rdb/test/GraphMergeTests.java
    
incubator/tuscany/java/das/rdb/src/test/java/org/apache/tuscany/das/rdb/test/RelationshipTests.java
    
incubator/tuscany/java/das/rdb/src/test/resources/customerOrderRelationshipMapping.xml

Modified: incubator/tuscany/java/das/rdb/pom.xml
URL: 
http://svn.apache.org/viewvc/incubator/tuscany/java/das/rdb/pom.xml?rev=588159&r1=588158&r2=588159&view=diff
==============================================================================
--- incubator/tuscany/java/das/rdb/pom.xml (original)
+++ incubator/tuscany/java/das/rdb/pom.xml Thu Oct 25 01:06:16 2007
@@ -135,6 +135,16 @@
                                    <goal>generate</goal>
                                </goals>
                            </execution>
+                           <execution>
+                               <id>singer</id>
+                               <configuration>
+                                   
<schemaFile>${basedir}/src/test/resources/SINGER.xsd</schemaFile>
+                                   <noUnsettable>true</noUnsettable>
+                               </configuration>
+                               <goals>
+                                   <goal>generate</goal>
+                               </goals>
+                           </execution>                            
                        </executions>
                    </plugin>
 

Modified: 
incubator/tuscany/java/das/rdb/src/main/java/org/apache/tuscany/das/rdb/graphbuilder/impl/MultiTableRegistry.java
URL: 
http://svn.apache.org/viewvc/incubator/tuscany/java/das/rdb/src/main/java/org/apache/tuscany/das/rdb/graphbuilder/impl/MultiTableRegistry.java?rev=588159&r1=588158&r2=588159&view=diff
==============================================================================
--- 
incubator/tuscany/java/das/rdb/src/main/java/org/apache/tuscany/das/rdb/graphbuilder/impl/MultiTableRegistry.java
 (original)
+++ 
incubator/tuscany/java/das/rdb/src/main/java/org/apache/tuscany/das/rdb/graphbuilder/impl/MultiTableRegistry.java
 Thu Oct 25 01:06:16 2007
@@ -101,4 +101,16 @@
 
     }
 
+    public void remove(String tableName, List primaryKey) {
+       getPkMap(tableName).get(primaryKey);
+       Map pkMap = (HashMap) tableNameMap.get(tableName);
+       
+       if(pkMap.get(primaryKey) != null) {
+               pkMap.remove(primaryKey);       
+       }
+       
+       if(pkMap.size() == 0) {
+               tableNameMap.remove(tableName);
+       }
+    }    
 }

Modified: 
incubator/tuscany/java/das/rdb/src/main/java/org/apache/tuscany/das/rdb/graphbuilder/impl/SingleTableRegistry.java
URL: 
http://svn.apache.org/viewvc/incubator/tuscany/java/das/rdb/src/main/java/org/apache/tuscany/das/rdb/graphbuilder/impl/SingleTableRegistry.java?rev=588159&r1=588158&r2=588159&view=diff
==============================================================================
--- 
incubator/tuscany/java/das/rdb/src/main/java/org/apache/tuscany/das/rdb/graphbuilder/impl/SingleTableRegistry.java
 (original)
+++ 
incubator/tuscany/java/das/rdb/src/main/java/org/apache/tuscany/das/rdb/graphbuilder/impl/SingleTableRegistry.java
 Thu Oct 25 01:06:16 2007
@@ -43,4 +43,7 @@
         return false;
     }
 
+    public void remove(String tableName, List primaryKey) {
+       
+    }    
 }

Modified: 
incubator/tuscany/java/das/rdb/src/main/java/org/apache/tuscany/das/rdb/graphbuilder/impl/TableRegistry.java
URL: 
http://svn.apache.org/viewvc/incubator/tuscany/java/das/rdb/src/main/java/org/apache/tuscany/das/rdb/graphbuilder/impl/TableRegistry.java?rev=588159&r1=588158&r2=588159&view=diff
==============================================================================
--- 
incubator/tuscany/java/das/rdb/src/main/java/org/apache/tuscany/das/rdb/graphbuilder/impl/TableRegistry.java
 (original)
+++ 
incubator/tuscany/java/das/rdb/src/main/java/org/apache/tuscany/das/rdb/graphbuilder/impl/TableRegistry.java
 Thu Oct 25 01:06:16 2007
@@ -42,4 +42,6 @@
     void put(String tableName, List primaryKey, DataObject value);
 
     boolean contains(String name, List list);
+    
+    void remove(String tableName, List primaryKey);
 }

Modified: 
incubator/tuscany/java/das/rdb/src/main/java/org/apache/tuscany/das/rdb/merge/impl/GraphMerger.java
URL: 
http://svn.apache.org/viewvc/incubator/tuscany/java/das/rdb/src/main/java/org/apache/tuscany/das/rdb/merge/impl/GraphMerger.java?rev=588159&r1=588158&r2=588159&view=diff
==============================================================================
--- 
incubator/tuscany/java/das/rdb/src/main/java/org/apache/tuscany/das/rdb/merge/impl/GraphMerger.java
 (original)
+++ 
incubator/tuscany/java/das/rdb/src/main/java/org/apache/tuscany/das/rdb/merge/impl/GraphMerger.java
 Thu Oct 25 01:06:16 2007
@@ -26,12 +26,10 @@
 import org.apache.log4j.Logger;
 
 import org.apache.tuscany.das.rdb.config.Config;
-import org.apache.tuscany.das.rdb.config.Table;
 import org.apache.tuscany.das.rdb.config.wrapper.MappingWrapper;
 import org.apache.tuscany.das.rdb.config.wrapper.QualifiedColumn;
 import org.apache.tuscany.das.rdb.graphbuilder.impl.MultiTableRegistry;
 import org.apache.tuscany.das.rdb.graphbuilder.impl.TableRegistry;
-import org.apache.tuscany.sdo.impl.ChangeSummaryImpl;
 import org.apache.tuscany.sdo.api.SDOUtil;
 
 import commonj.sdo.ChangeSummary;
@@ -77,16 +75,7 @@
             throw new RuntimeException("DataObjectModel must be specified in 
the Config");
         }
 
-        String uri = "http:///org.apache.tuscany.das.rdb/das";;
-        TypeHelper typeHelper = 
HelperProvider.getDefaultContext().getTypeHelper();
-        Type rootType = null;
-        rootType = typeHelper.getType(uri + "/DataGraphRoot", "DataGraphRoot");
-        if(rootType == null){
-               rootType = 
SDOUtil.createType(HelperProvider.getDefaultContext(), uri + "/DataGraphRoot", 
"DataGraphRoot", false);
-               if (logger.isDebugEnabled()) {
-                       logger.debug("GraphMerger.emptyGraph():creating type 
for "+uri);
-               }               
-        }
+        Type rootType = createDataGraphRoot();
         
         List types = SDOUtil.getTypes(HelperProvider.getDefaultContext(), 
config.getDataObjectModel());
         if (types == null) {
@@ -96,15 +85,7 @@
         Iterator i = types.iterator();
         while (i.hasNext()) {
             Type type = (Type) i.next();
-            Property property = rootType.getProperty(type.getName());
-            if( !(property != null && 
-               (property.getType().isDataType()== type.isDataType()) &&
-               (property.isContainment() == true) &&
-               (property.isMany() == true)) ){
-                   property = SDOUtil.createProperty(rootType, type.getName(), 
type);
-                   SDOUtil.setContainment(property, true);
-                   SDOUtil.setMany(property, true);
-            }
+            Property property = getOrCreateProperty(rootType, type);
         }
 
         // Create the DataGraph
@@ -119,81 +100,231 @@
         return g.getRootObject();
     }
 
-    public DataObject merge(List graphs) {
-        DataObject primaryGraph = (DataObject) graphs.get(0);
+    private Type createDataGraphRoot() {
+           String uri = "http:///org.apache.tuscany.das.rdb/das";;
+           TypeHelper typeHelper = 
HelperProvider.getDefaultContext().getTypeHelper();
+           Type rootType = null;
+           rootType = typeHelper.getType(uri+ "/DataGraphRoot", 
"DataGraphRoot");
+           if(rootType == null){
+               rootType = 
SDOUtil.createType(HelperProvider.getDefaultContext(), uri+ "/DataGraphRoot", 
"DataGraphRoot", false);
+               if (logger.isDebugEnabled()) {
+                       
logger.debug("GraphMerger.createDataGraphRoot():creating type for "+uri);
+               }               
+           }
+           return rootType;
+    }
 
-        Iterator i = graphs.iterator();
-        if (i.hasNext()) {
-            i.next();
+    private Property getOrCreateProperty(Type rootType, Type type) {
+        Property property = rootType.getProperty(type.getName());
+        if( !(property != null && 
+           (property.getType().isDataType()== type.isDataType()) &&
+           (property.isContainment() == true) &&
+           (property.isMany() == true)) ){
+            property = SDOUtil.createProperty(rootType, type.getName(), type);
+            SDOUtil.setContainment(property, true);
+            SDOUtil.setMany(property, true);
+            property = rootType.getProperty(type.getName());
+        }
+        return property;
+     }
+    
+    private boolean isContainedWithChangeSummary(DataObject object) {
+       if(!object.getType().getName().equals("DataGraphRoot") || 
object.getChangeSummary() == null) {
+               return false;
+       }
+       return true;
+    }
+    
+    private DataObject containWithChangeSummary(Type rootType, DataObject 
object) {
+       Property property = rootType.getProperty(object.getType().getName());
+        
+        if( property == null) {
+            property = SDOUtil.createProperty(rootType, 
object.getType().getName(), object.getType());
+            SDOUtil.setContainment(property, true);
+            SDOUtil.setMany(property, true);
+            property = rootType.getProperty(object.getType().getName());
+        }
+        
+        DataGraph dataGraph = SDOUtil.createDataGraph();
+        DataObject root = dataGraph.createRootObject(rootType);
+        root.getDataGraph().getChangeSummary().beginLogging();
+        createObjectWithSubtree(root, property, object);
+        
+        if(root.getDataGraph().getChangeSummary().getChangedDataObjects() != 
null) {
+               List cos = 
root.getDataGraph().getChangeSummary().getChangedDataObjects();
+               for(int i=0; i<cos.size(); i++) {
+                       DataObject changedDO = (DataObject)cos.get(i);
+               }
         }
+        //as we are just wrapping individual DOs in DataGraphRoot, and later 
during merge we will merge all such DOs, no need to have registry entry
+        //right now.
+        registry.remove(object.getType().getName(), 
Collections.singletonList(getPrimaryKey(object)));
+        return root;
+    }
+    
+    /**
+     * If list contains at least one with DG and CS, select it, if none, 
return -1, if more than one, select the first one matching condition
+     * @param graphs
+     * @return
+     */
+    private int getPrimaryFromList(List graphs) {
+       //select primary
+       Iterator itr = graphs.iterator();
+       int index = -1;
+       int primaryIndex = -1;
+       while(itr.hasNext()) {
+               index++;
+               DataObject currentGraph = (DataObject)itr.next();
+               if(isContainedWithChangeSummary(currentGraph) && 
currentGraph.getChangeSummary() != null) {
+                       primaryIndex = index;
+               }
+       }
+       return primaryIndex;
+    }
+    
+    //JIRA-1815
+    //preservePrimaryChangeSummary - default true - primary CS is preserved, 
secondary DOs are added without alteration to CS of primary - old behavior
+    //preservePrimaryChangeSummary - false - secondaries are treated as CREATE 
and primary CS is altered for merges - way to INSERT with adhoc SDOs.
+    public DataObject merge(List graphs, boolean preservePrimaryChangeSummary) 
{
+       DataObject primaryGraph = null;
+       int primaryIndex = getPrimaryFromList(graphs);
+
+       if(primaryIndex > -1) {
+               primaryGraph = (DataObject)graphs.remove(primaryIndex);
+       }
+
+       Iterator i = graphs.iterator();         
+       if(primaryGraph == null) {
+            if (i.hasNext()) {
+               primaryGraph = (DataObject)i.next();
+            }                  
+       }
+       
         while (i.hasNext()) {
-            primaryGraph = merge(primaryGraph, (DataObject) i.next());
+            primaryGraph = merge(primaryGraph, (DataObject) i.next(), 
preservePrimaryChangeSummary);
         }
 
-        return primaryGraph;
+        return primaryGraph;           
+    }
+    
+    public DataObject merge(List graphs) {
+       return merge(graphs, true);
     }
 
+    public DataObject merge(DataObject primary, DataObject secondary, boolean 
preservePrimaryChangeSummary) {
+       Type rootType = createDataGraphRoot();
+       DataObject root1 = null;
+       DataObject root2 = null;
+
+       if(!isContainedWithChangeSummary(primary) && 
isContainedWithChangeSummary(secondary)) {
+       //swap as secondary has change history
+               DataObject temp = primary;
+               primary = secondary;
+               secondary = temp;
+       }
+       
+        //if primary top type name is not DataGraphRoot , add it
+       if(!isContainedWithChangeSummary(primary)) {
+               root1 = containWithChangeSummary(rootType, primary);
+       } else {
+               root1 = primary;
+       }
+
+        //if secondary top type name is not DataGraphRoot , add it
+       if(!isContainedWithChangeSummary(secondary)) {
+               root2 = containWithChangeSummary(rootType, secondary);
+       } else {
+               root2 = secondary;
+       }
+              
+        return mergeContained(root1, root2, preservePrimaryChangeSummary);     
+    }
+    
     public DataObject merge(DataObject primary, DataObject secondary) {
+       return merge(primary, secondary, true);
+    }
+    
+    public DataObject mergeContained(DataObject primary, DataObject secondary, 
boolean preservePrimaryChangeSummary) {         
         addGraphToRegistry(primary);
 
-        ChangeSummary summary = primary.getDataGraph().getChangeSummary();
-        summary.endLogging();
         Iterator i = secondary.getType().getProperties().iterator();
+        ChangeSummary summary = primary.getDataGraph().getChangeSummary();
+
+        if(preservePrimaryChangeSummary && summary.isLogging()) {
+               summary.endLogging();
+        }
 
         while (i.hasNext()) {
             Property p = (Property) i.next();
 
-            Iterator objects = secondary.getList(p.getName()).iterator();
+            Iterator objects = secondary.getList(p.getName()).iterator();      
      
             while (objects.hasNext()) {
                 DataObject object = (DataObject) objects.next();
                 createObjectWithSubtree(primary, p, object);
             }
         }
-        ((ChangeSummaryImpl) summary).resumeLogging();
+
+        if(preservePrimaryChangeSummary && !summary.isLogging()) {
+               summary.beginLogging();
+        }
+        
         return primary;
     }
 
     private void createObjectWithSubtree(DataObject root, Property p, 
DataObject object) {
         Object pk = getPrimaryKey(object);
 
-        if (!registry.contains(object.getType().getName(), 
Collections.singletonList(pk))) {
-            DataObject newObject = root.createDataObject(p.getName());
-            Iterator attrs = object.getType().getProperties().iterator();
-            while (attrs.hasNext()) {
-                Property attr = (Property) attrs.next();
-                if (attr.getType().isDataType()) {
-                    newObject.set(attr.getName(), object.get(attr));
-                }
-            }
+        if (!registry.contains(object.getType().getName(), 
Collections.singletonList(pk))) {           
+               Iterator attrs = object.getType().getProperties().iterator();
+           DataObject newObject = root.createDataObject(p.getName());
+           
+           createDataProperties(attrs, newObject, object);
             registry.put(object.getType().getName(), 
Collections.singletonList(pk), newObject);
-            Iterator refs = object.getType().getProperties().iterator();
-            while (refs.hasNext()) {
-                Property ref = (Property) refs.next();
-                if (!ref.getType().isDataType()) {
-                    List refObjects;
-                    if (!ref.isMany()) {
-                        refObjects = 
Collections.singletonList(object.get(ref));
+            createReferenceProperties(root, newObject, object);            
+        }
+
+    }
+
+    private void createDataProperties(Iterator attrs, DataObject newObject, 
DataObject object) {
+           while (attrs.hasNext()) {
+               Property attr = (Property) attrs.next();
+               if (attr.getType().isDataType()) {
+                       try {
+                               newObject.set(attr.getName(), object.get(attr));
+                       } catch(Exception e) {
+                               throw new RuntimeException("Graph structures do 
not match, can not merge! " + attr.getName());
+                       }
+               }
+           }
+    }
+    
+    private void createReferenceProperties(DataObject root, DataObject 
newObject, DataObject object) {
+        Iterator refs = object.getType().getProperties().iterator();
+        while (refs.hasNext()) {
+            Property ref = (Property) refs.next();
+            if (!ref.getType().isDataType()) {
+                List refObjects;
+                if (!ref.isMany()) {
+                    refObjects = Collections.singletonList(object.get(ref));
+                } else {
+                    refObjects = (List) object.get(ref);
+                }
+                Iterator iter = refObjects.iterator();
+                while (iter.hasNext()) {
+                    DataObject refObject = (DataObject) iter.next();
+                    createObjectWithSubtree(root, 
refObject.getContainmentProperty(), refObject);
+                    refObject = registry.get(refObject.getType().getName(), 
+                            
Collections.singletonList(getPrimaryKey(refObject)));
+                    if (ref.isMany()) {
+                        
newObject.getList(newObject.getType().getProperty(ref.getName())).add(refObject);
                     } else {
-                        refObjects = (List) object.get(ref);
-                    }
-                    Iterator iter = refObjects.iterator();
-                    while (iter.hasNext()) {
-                        DataObject refObject = (DataObject) iter.next();
-                        createObjectWithSubtree(root, 
refObject.getContainmentProperty(), refObject);
-                        refObject = 
registry.get(refObject.getType().getName(), 
-                                
Collections.singletonList(getPrimaryKey(refObject)));
-                        if (ref.isMany()) {
-                            
newObject.getList(newObject.getType().getProperty(ref.getName())).add(refObject);
-                        } else {
-                            
newObject.set(newObject.getType().getProperty(ref.getName()), refObject);
-                        }
+                        
newObject.set(newObject.getType().getProperty(ref.getName()), refObject);
                     }
                 }
             }
-        }
-
+        }      
     }
-
+    
     private void addGraphToRegistry(DataObject graph1) {
         Iterator i = graph1.getType().getProperties().iterator();
         while (i.hasNext()) {

Modified: 
incubator/tuscany/java/das/rdb/src/test/java/org/apache/tuscany/das/rdb/test/GraphMergeTests.java
URL: 
http://svn.apache.org/viewvc/incubator/tuscany/java/das/rdb/src/test/java/org/apache/tuscany/das/rdb/test/GraphMergeTests.java?rev=588159&r1=588158&r2=588159&view=diff
==============================================================================
--- 
incubator/tuscany/java/das/rdb/src/test/java/org/apache/tuscany/das/rdb/test/GraphMergeTests.java
 (original)
+++ 
incubator/tuscany/java/das/rdb/src/test/java/org/apache/tuscany/das/rdb/test/GraphMergeTests.java
 Thu Oct 25 01:06:16 2007
@@ -24,15 +24,26 @@
 import org.apache.tuscany.das.rdb.Command;
 import org.apache.tuscany.das.rdb.ConfigHelper;
 import org.apache.tuscany.das.rdb.DAS;
+import org.apache.tuscany.das.rdb.config.wrapper.MappingWrapper;
 import org.apache.tuscany.das.rdb.merge.impl.GraphMerger;
+import org.apache.tuscany.das.rdb.test.customer.AnOrder;
 import org.apache.tuscany.das.rdb.test.customer.Customer;
 import org.apache.tuscany.das.rdb.test.customer.CustomerFactory;
+import org.apache.tuscany.das.rdb.test.customer.impl.CustomerFactoryImpl;
+import org.apache.tuscany.das.rdb.test.singer.impl.SingerFactoryImpl;
+import org.apache.tuscany.das.rdb.test.singer.SINGER;
 import org.apache.tuscany.das.rdb.test.data.CustomerData;
+import org.apache.tuscany.das.rdb.test.data.SingerData;
 import org.apache.tuscany.das.rdb.test.data.OrderData;
 import org.apache.tuscany.das.rdb.test.framework.DasTest;
+import org.apache.tuscany.sdo.api.SDOUtil;
 
 import commonj.sdo.DataObject;
+import commonj.sdo.Type;
+import commonj.sdo.helper.DataFactory;
 import commonj.sdo.helper.HelperContext;
+import commonj.sdo.helper.TypeHelper;
+import commonj.sdo.helper.XMLHelper;
 import commonj.sdo.impl.HelperProvider;
 
 public class GraphMergeTests extends DasTest {
@@ -42,6 +53,7 @@
 
         new CustomerData(getAutoConnection()).refresh();
         new OrderData(getAutoConnection()).refresh();
+        new SingerData(getAutoConnection()).refresh();
 
     }
 
@@ -97,10 +109,35 @@
         GraphMerger merger = new GraphMerger();
         merger.addPrimaryKey("CUSTOMER.ID");
         DataObject mergedGraph = merger.merge(graph1, graph2);
-
+        List custList = mergedGraph.getList("CUSTOMER");
+        for(int i=0; i<custList.size(); i++) {
+               DataObject currCust = (DataObject)custList.get(i);
+        }
         assertEquals(5, mergedGraph.getList("CUSTOMER").size());
     }
 
+    public void testSingleTableMerge2() throws Exception {
+        DAS das = DAS.FACTORY.createDAS(getConnection());
+        Command select = das.createCommand("Select ID, LASTNAME, ADDRESS from 
CUSTOMER where ID <= ?");
+        select.setParameter(1, "3");
+        DataObject graph1 = select.executeQuery();
+        assertEquals(3, graph1.getList("CUSTOMER").size());
+
+        Command select2 = das.createCommand("Select ID, LASTNAME, ADDRESS from 
CUSTOMER where ID > ?");
+        select2.setParameter(1, "3");
+        DataObject graph2 = select2.executeQuery();
+        assertEquals(2, graph2.getList("CUSTOMER").size());
+
+        GraphMerger merger = new GraphMerger();
+        merger.addPrimaryKey("CUSTOMER.ID");
+        DataObject mergedGraph = merger.merge(graph1, graph2);
+        List custList = mergedGraph.getList("CUSTOMER");
+        for(int i=0; i<custList.size(); i++) {
+               DataObject currCust = (DataObject)custList.get(i);
+        }
+        assertEquals(5, mergedGraph.getList("CUSTOMER").size());
+    }
+    
     public void testSingleTableMergeThreeGraphs() throws Exception {
         DAS das = DAS.FACTORY.createDAS(getConnection());
         Command select = das.createCommand("Select ID, LASTNAME, ADDRESS from 
CUSTOMER where ID <= ?");
@@ -223,5 +260,361 @@
         
         DataObject root1 = gm.merge(root, ((DataObject)c).getRootObject());    
   
         das.applyChanges(root1);
+    }
+    
+    /**
+     * Support merge(StaticDO1, StaticDO2, noChangeSummary) when both are not 
contained in "DataGraphRoot" and DataGraph (and not have changeSummary). When
+     * no existing change summary, will be used for INSERT
+     * @throws Exception
+     */
+    public void testMergeStaticDOs() throws Exception {
+        // Populate the meta data for the test (SINGER) model xsd - WAY ONE
+        /*String TEST_MODEL = "/SINGER.xsd";
+                String TEST_NAMESPACE = 
"http:///org.apache.tuscany.das.rdb.test/SINGER.xsd";;
+
+        URL url = getClass().getResource(TEST_MODEL);
+        InputStream inputStream = url.openStream();
+        XSDHelper.INSTANCE.define(inputStream, url.toString());
+        inputStream.close();
+           
+        Type singerType = TypeHelper.INSTANCE.getType(TEST_NAMESPACE, 
"SINGER");
+        DataObject SINGER = DataFactory.INSTANCE.create(singerType);
+        SINGER.set("ID", new Integer(100));
+        SINGER.set("NAME", "Singer100"); */
+                
+       // Populate the meta data for the test (SINGER) using generated classes 
- WAY TWO
+        SINGER singerStaticDO1 = SingerFactoryImpl.INSTANCE.createSINGER();
+        singerStaticDO1.setID(100);
+        singerStaticDO1.setNAME("Singer100");
+                        
+        SINGER singerStaticDO2 = SingerFactoryImpl.INSTANCE.createSINGER();
+        singerStaticDO2.setID(200);
+        singerStaticDO2.setNAME("Singer200");
+        
+        GraphMerger gm = new GraphMerger();
+        gm.addPrimaryKey("SINGER.ID");
+        
+        DataObject songs = gm.merge((DataObject)singerStaticDO1, 
(DataObject)singerStaticDO2, false);
+ 
+        DAS das = DAS.FACTORY.createDAS(getConnection());
+        das.applyChanges(songs);
+        //printSingerData();
+        Command cmd = das.createCommand("SELECT ID, NAME FROM SINGER");
+       DataObject root = cmd.executeQuery();
+       assertNotNull(root.getDataObject("SINGER[ID=100]"));
+       assertEquals("Singer100", 
root.getDataObject("SINGER[ID=100]").getString("NAME"));
+       assertNotNull(root.getDataObject("SINGER[ID=200]"));
+       assertEquals("Singer200", 
root.getDataObject("SINGER[ID=200]").getString("NAME"));
+   }  
+
+    /*Internal utility to create a property in a dynamic DO*/
+    private void specifyProperty(DataObject containingTypeDO, String 
nameString, Type type, boolean isMany) {
+        DataObject subordinateProperty = 
containingTypeDO.createDataObject("property");
+        subordinateProperty.set("name", nameString);
+        subordinateProperty.set("type", type);
+        subordinateProperty.setBoolean("many", isMany);
+    }
+    
+    /*Internal utility to form Dynamic DO*/
+    private DataObject formDynamicDO(String dynamicRootType) {
+       String DYNAMIC_TYPES_URI = 
"http://www.example.com/dynamicTypesFromSchemaSimple";;
+       String DYNAMIC_ROOT_TYPE_0 = dynamicRootType;
+       String COMMONJ_SDO = "commonj.sdo";
+       
+       HelperContext hcDO = SDOUtil.createHelperContext();
+
+        TypeHelper thDO = hcDO.getTypeHelper();
+        DataFactory dfDO = hcDO.getDataFactory();
+
+        // create a container object type
+        DataObject containerTypeDO = dfDO.create("commonj.sdo", "Type");
+        containerTypeDO.set("uri", DYNAMIC_TYPES_URI);
+        containerTypeDO.set("name", DYNAMIC_ROOT_TYPE_0);
+        containerTypeDO.set("sequenced", Boolean.TRUE);
+
+        specifyProperty(containerTypeDO, "NAME", thDO.getType(COMMONJ_SDO, 
"String"), false);
+        specifyProperty(containerTypeDO, "ID", thDO.getType(COMMONJ_SDO, 
"Int"), false);
+
+        Type containerType = thDO.define(containerTypeDO);
+        assertNotNull(containerType);
+
+        DataObject doFromApiAndDynTyp = dfDO.create(containerType);
+        return doFromApiAndDynTyp;
+    }
+    
+    /**merge(DynamicDO1, DynamicDO2, noChangeSummary). When no change summary 
associated in a DataGraph, treated for INSERT
+     * 
+     * @throws Exception
+     */
+    public void testMergeDynamicDOs() throws Exception {
+       DataObject doFromApiAndDynTyp1 = formDynamicDO("SINGER");
+        assertNotNull(doFromApiAndDynTyp1);
+        doFromApiAndDynTyp1.setString("NAME", "DynamicSinger1");
+        doFromApiAndDynTyp1.setInt("ID", 100);
+        
+        DataObject doFromApiAndDynTyp2 = formDynamicDO("SINGER");
+        assertNotNull(doFromApiAndDynTyp2);
+        doFromApiAndDynTyp2.setString("NAME", "DynamicSinger2");
+        doFromApiAndDynTyp2.setInt("ID", 200);
+        
+        GraphMerger gm = new GraphMerger();
+        gm.addPrimaryKey("SINGER.ID");
+        
+        DataObject dos = gm.merge(doFromApiAndDynTyp1, doFromApiAndDynTyp2, 
false);
+        
+        DAS das = DAS.FACTORY.createDAS(getConnection());
+        das.applyChanges(dos);
+        //printSingerData();
+        Command cmd = das.createCommand("SELECT ID, NAME FROM SINGER");
+       DataObject root = cmd.executeQuery();
+       assertNotNull(root.getDataObject("SINGER[ID=100]"));
+       assertEquals("DynamicSinger1", 
root.getDataObject("SINGER[ID=100]").getString("NAME"));
+       assertNotNull(root.getDataObject("SINGER[ID=200]"));
+       assertEquals("DynamicSinger2", 
root.getDataObject("SINGER[ID=200]").getString("NAME"));        
+    }
+    
+    /**
+     * merge(StaticDO, DynamicDO, noChangeSummary). As no change summary, used 
for INSERT
+     * @throws Exception
+     */
+    public void testMergeStaticAndDynamicDOs() throws Exception {
+       DataObject singerDynamicDO1 = formDynamicDO("SINGER");
+        assertNotNull(singerDynamicDO1);
+        singerDynamicDO1.setString("NAME", "Singer100");
+        singerDynamicDO1.setInt("ID", 100);
+        
+       SINGER singerStaticDO1 = SingerFactoryImpl.INSTANCE.createSINGER();
+        singerStaticDO1.setID(200);
+        singerStaticDO1.setNAME("Singer200");
+                        
+        GraphMerger gm = new GraphMerger();
+        gm.addPrimaryKey("SINGER.ID");
+        
+        DataObject singers = gm.merge((DataObject)singerStaticDO1, 
singerDynamicDO1, false);
+ 
+        DAS das = DAS.FACTORY.createDAS(getConnection());
+        das.applyChanges(singers);
+        //printSingerData();
+        Command cmd = das.createCommand("SELECT ID, NAME FROM SINGER");
+       DataObject root = cmd.executeQuery();
+       assertNotNull(root.getDataObject("SINGER[ID=100]"));
+       assertEquals("Singer100", 
root.getDataObject("SINGER[ID=100]").getString("NAME"));
+       assertNotNull(root.getDataObject("SINGER[ID=200]"));
+       assertEquals("Singer200", 
root.getDataObject("SINGER[ID=200]").getString("NAME"));        
+    }
+
+    /** 
+     * Query result can carry ChangeSummary of CUD, Dynamic DO will be a new 
Object (CREATE)
+     * @throws Exception
+     */
+    public void testMergeQueryResultAndDynamicDOs() throws Exception {
+       DataObject singerDynamicDO1 = formDynamicDO("SINGER");
+        assertNotNull(singerDynamicDO1);
+        singerDynamicDO1.setString("NAME", "Singer100");
+        singerDynamicDO1.setInt("ID", 100);
+        
+        DAS das = DAS.FACTORY.createDAS(getConnection());
+        Command cmd = das.createCommand("SELECT ID, NAME FROM SINGER");
+        DataObject root = cmd.executeQuery();
+        
+        DataObject secondSinger = root.getDataObject("SINGER[ID=2]");
+        secondSinger.setString("NAME", "JaneSecond");//change summary 
registers Update change
+        
+        DataObject thirdSinger = root.getDataObject("SINGER[ID=3]");
+        thirdSinger.delete();//change summary registers Delete change
+        
+        GraphMerger gm = new GraphMerger();
+        gm.addPrimaryKey("SINGER.ID");
+        
+        DataObject singers = gm.merge(root, singerDynamicDO1, false);//merge 
with primary DO having change summary and secondary DO without one.
+        //as false is passed, secondary DO will be treated as INSERT in 
primaryChangeSummary
+ 
+        das.applyChanges(singers);
+        //printSingerData();
+       root = cmd.executeQuery();
+       assertNotNull(root.getDataObject("SINGER[ID=100]"));
+       assertEquals("Singer100", 
root.getDataObject("SINGER[ID=100]").getString("NAME"));
+       assertNotNull(root.getDataObject("SINGER[ID=2]"));
+       assertEquals("JaneSecond", 
root.getDataObject("SINGER[ID=2]").getString("NAME"));
+       assertNull(root.getDataObject("SINGER[ID=3]"));
+    }
+    
+    /** 
+     * Query result can carry ChangeSummary of CUD, Static DO will be a new 
Object (CREATE)
+     * @throws Exception
+     */
+    public void testMergeQueryResultAndStaticDOs() throws Exception {
+       SINGER singerStaticDO1 = SingerFactoryImpl.INSTANCE.createSINGER();
+        singerStaticDO1.setID(100);
+        singerStaticDO1.setNAME("Singer100");
+                        
+        GraphMerger gm = new GraphMerger();
+        gm.addPrimaryKey("SINGER.ID");
+
+        DAS das = DAS.FACTORY.createDAS(getConnection());
+        Command cmd = das.createCommand("SELECT ID, NAME FROM SINGER");
+        DataObject root = cmd.executeQuery();
+
+        DataObject secondSinger = root.getDataObject("SINGER[ID=2]");
+        secondSinger.setString("NAME", "JaneSecond");//Change summary will 
register Update
+        
+        DataObject thirdSinger = root.getDataObject("SINGER[ID=3]");
+        thirdSinger.delete();//change summary will register Delete
+
+        DataObject singers = gm.merge(root, (DataObject)singerStaticDO1, 
false);//due to false, secondary DO will be treated as INSERT in primary change 
summary
+        
+        das.applyChanges(singers);
+        //printSingerData();
+       root = cmd.executeQuery();
+       assertNotNull(root.getDataObject("SINGER[ID=100]"));
+       assertEquals("Singer100", 
root.getDataObject("SINGER[ID=100]").getString("NAME"));
+       assertNotNull(root.getDataObject("SINGER[ID=2]"));
+       assertEquals("JaneSecond", 
root.getDataObject("SINGER[ID=2]").getString("NAME"));
+       assertNull(root.getDataObject("SINGER[ID=3]"));        
+    }    
+    
+    private void printSongData() throws Exception {
+       DAS das = DAS.FACTORY.createDAS(getConnection());
+       Command cmd = das.createCommand("SELECT ID, TITLE, SINGERID FROM SONG");
+       DataObject root = cmd.executeQuery();
+       System.out.println("**********SONG*************************");
+       System.out.println(XMLHelper.INSTANCE.save(root, "song", "song"));
+       System.out.println("**********************************************");
+    }
+    
+    private void printSingerData() throws Exception {
+       DAS das = DAS.FACTORY.createDAS(getConnection());
+       Command cmd = das.createCommand("SELECT ID, NAME FROM SINGER");
+       DataObject root = cmd.executeQuery();
+       System.out.println("**************SINGER************************");
+       System.out.println(XMLHelper.INSTANCE.save(root, "singer", "singer"));
+       System.out.println("**********************************************");
+    }
+    
+    /**
+     * Mix all 3 - query result carrying change summary, static and dynamic DO
+     * @throws Exception
+     */
+    public void testMergeListQueryResultStaticAndDynamic() throws Exception {
+       SINGER singerStaticDO1 = SingerFactoryImpl.INSTANCE.createSINGER();
+        singerStaticDO1.setID(200);
+        singerStaticDO1.setNAME("Singer200");
+        
+        GraphMerger gm = new GraphMerger();
+        gm.addPrimaryKey("SINGER.ID");
+        
+        DAS das = DAS.FACTORY.createDAS(getConnection());
+        Command cmd = das.createCommand("SELECT ID, NAME FROM SINGER");
+        DataObject root = cmd.executeQuery();
+        DataObject firstSinger = root.getDataObject("SINGER[ID=1]");
+        firstSinger.setString("NAME", "JohnNew");//change summary will 
register Update
+        
+        DataObject secondSinger = root.getDataObject("SINGER[ID=2]");
+        secondSinger.delete();//change summary will register Delete
+        
+        DataObject singerDynamicDO1 = formDynamicDO("SINGER");
+        assertNotNull(singerDynamicDO1);
+        singerDynamicDO1.setString("NAME", "Singer100");
+        singerDynamicDO1.setInt("ID", 100);
+        
+        ArrayList singersToMerge = new ArrayList();        
+        singersToMerge.add((DataObject)singerStaticDO1);
+        singersToMerge.add(root);
+        singersToMerge.add(singerDynamicDO1);
+        
+        //merge will internally shuffle DOs to detect primary having change 
summary. so root will be designated as Primary
+        DataObject singers = gm.merge(singersToMerge, false);
+        
+       das.applyChanges(singers);
+        //printSingerData();
+       root = cmd.executeQuery();
+       assertNotNull(root.getDataObject("SINGER[ID=100]"));
+       assertEquals("Singer100", 
root.getDataObject("SINGER[ID=100]").getString("NAME"));
+       assertNotNull(root.getDataObject("SINGER[ID=200]"));
+       assertEquals("Singer200", 
root.getDataObject("SINGER[ID=200]").getString("NAME"));
+       assertNotNull(root.getDataObject("SINGER[ID=1]"));
+       assertEquals("JohnNew", 
root.getDataObject("SINGER[ID=1]").getString("NAME"));
+       assertNull(root.getDataObject("SINGER[ID=2]"));
+    }
+
+    /**
+     * There is no much meaning to nested merges as the secondary DOs are at 
most treated for INSERTs. 
+     * @throws Exception
+     */
+    public void testMergePrimaryQuerySecondaryStaticNested() throws Exception {
+       String typeUri = "http:///org.apache.tuscany.das.rdb.test/customer.xsd";;
+        HelperContext context = HelperProvider.getDefaultContext();
+        CustomerFactory.INSTANCE.register(context);  
+       
+       AnOrder anOrderStaticDO1 = CustomerFactoryImpl.INSTANCE.createAnOrder();
+       anOrderStaticDO1.setID(100);
+       anOrderStaticDO1.setProduct("100 prods");
+       anOrderStaticDO1.setQuantity(100);
+       anOrderStaticDO1.setCustomer_ID(1);
+        
+        GraphMerger gm = new GraphMerger();
+        gm.addPrimaryKey("Customer.ID");
+        gm.addPrimaryKey("AnOrder.ID");
+        
+        ConfigHelper helper = new ConfigHelper();
+        helper.setDataObjectModel(typeUri);
+        helper.addTable("CUSTOMER", "Customer");
+        helper.addTable("ANORDER", "AnOrder");
+        MappingWrapper mappingWrapper = new MappingWrapper(helper.getConfig());
+        
+        helper.addColumn(mappingWrapper.getTable("CUSTOMER"), "ID", "ID");
+        helper.addColumn(mappingWrapper.getTable("CUSTOMER"), "LASTNAME", 
"lastName");
+        helper.addColumn(mappingWrapper.getTable("CUSTOMER"), "ADDRESS", 
"address");
+
+        helper.addColumn(mappingWrapper.getTable("ANORDER"), "ID", "ID");
+        helper.addColumn(mappingWrapper.getTable("ANORDER"), "PRODUCT", 
"Product");
+        helper.addColumn(mappingWrapper.getTable("ANORDER"), "QUANTITY", 
"Quantity");
+        helper.addColumn(mappingWrapper.getTable("ANORDER"), "CUSTOMER_ID", 
"Customer_ID");
+
+        helper.addRelationship("CUSTOMER.ID", "ANORDER.CUSTOMER_ID", "orders");
+        
+        DAS das = DAS.FACTORY.createDAS(helper.getConfig(), getConnection());
+        
+        Command cmd = das.createCommand("SELECT * FROM CUSTOMER LEFT JOIN 
ANORDER ON " 
+                + "CUSTOMER.ID = ANORDER.CUSTOMER_ID");
+        DataObject root = cmd.executeQuery();
+
+        DataObject result = gm.merge(root, (DataObject)anOrderStaticDO1, 
false);
+        assertEquals(2, 
result.getDataObject("Customer[ID=1]").getList("orders").size()); //because 
only CREATE part
+        //is considered for AnOrder, update part for relationship is not 
considered
+        das.applyChanges(result);
+        
+        context = HelperProvider.getDefaultContext();
+        CustomerFactory.INSTANCE.register(context);
+        
+        root = cmd.executeQuery();
+        DataObject firstCustomer = root.getDataObject("Customer[ID=1]");
+        List firstCustOrders = firstCustomer.getList("orders");
+        assertEquals(3, 
root.getDataObject("Customer[ID=1]").getList("orders").size());//as now 
snapshot from DB
+    }
+    
+    /**
+     * Show that when structure coming from Query is partial and the secondary 
is complete DO structure based on model xsd,
+     * on-the-fly changes to structure are not allowed and merge does not 
happen
+     * @throws Exception
+     */
+    public void testMergePartialQueryAndStatic() throws Exception {
+       SINGER singerStaticDO1 = SingerFactoryImpl.INSTANCE.createSINGER();
+       singerStaticDO1.setID(100);
+       singerStaticDO1.setNAME("Singer100");
+                        
+        GraphMerger gm = new GraphMerger();
+        gm.addPrimaryKey("SINGER.ID");
+
+        DAS das = DAS.FACTORY.createDAS(getConnection());
+        Command cmd = das.createCommand("SELECT ID FROM SINGER WHERE ID=1");
+        DataObject root = cmd.executeQuery();
+
+        try {
+               gm.merge(root, (DataObject)singerStaticDO1);
+               fail("Expected exception!");
+        } catch(RuntimeException e) {          
+               assertEquals("Graph structures do not match,", 
e.getMessage().substring(0, 30));
+        }        
     }    
 }

Modified: 
incubator/tuscany/java/das/rdb/src/test/java/org/apache/tuscany/das/rdb/test/RelationshipTests.java
URL: 
http://svn.apache.org/viewvc/incubator/tuscany/java/das/rdb/src/test/java/org/apache/tuscany/das/rdb/test/RelationshipTests.java?rev=588159&r1=588158&r2=588159&view=diff
==============================================================================
--- 
incubator/tuscany/java/das/rdb/src/test/java/org/apache/tuscany/das/rdb/test/RelationshipTests.java
 (original)
+++ 
incubator/tuscany/java/das/rdb/src/test/java/org/apache/tuscany/das/rdb/test/RelationshipTests.java
 Thu Oct 25 01:06:16 2007
@@ -41,6 +41,7 @@
 import org.apache.tuscany.das.rdb.test.framework.DasTest;
 
 import commonj.sdo.DataObject;
+import commonj.sdo.helper.XMLHelper;
 
 public class RelationshipTests extends DasTest {
 
@@ -74,8 +75,7 @@
         Command select = das.createCommand(statement);
 
         DataObject root = select.executeQuery();
-        DataObject customer = root.getDataObject("CUSTOMER[1]");
-
+        DataObject customer = root.getDataObject("Customer[1]");
         assertEquals(2, customer.getList("orders").size());
 
     }

Added: incubator/tuscany/java/das/rdb/src/test/resources/SINGER.xsd
URL: 
http://svn.apache.org/viewvc/incubator/tuscany/java/das/rdb/src/test/resources/SINGER.xsd?rev=588159&view=auto
==============================================================================
--- incubator/tuscany/java/das/rdb/src/test/resources/SINGER.xsd (added)
+++ incubator/tuscany/java/das/rdb/src/test/resources/SINGER.xsd Thu Oct 25 
01:06:16 2007
@@ -0,0 +1,39 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+  Licensed to the Apache Software Foundation (ASF) under one
+  or more contributor license agreements.  See the NOTICE file
+  distributed with this work for additional information
+  regarding copyright ownership.  The ASF licenses this file
+  to you under the Apache License, Version 2.0 (the
+  "License"); you may not use this file except in compliance
+  with the License.  You may obtain a copy of the License at
+
+  http://www.apache.org/licenses/LICENSE-2.0
+
+  Unless required by applicable law or agreed to in writing,
+  software distributed under the License is distributed on an
+  "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+  KIND, either express or implied.  See the License for the
+  specific language governing permissions and limitations
+  under the License.
+ -->
+<xsd:schema xmlns:xsd="http://www.w3.org/2001/XMLSchema"; 
xmlns:this="http:///org.apache.tuscany.das.rdb.test/SINGER.xsd"; 
targetNamespace="http:///org.apache.tuscany.das.rdb.test/SINGER.xsd";>
+       <!-- A Singer -->
+         <xsd:complexType name="SINGER">
+       <xsd:sequence>
+          <xsd:element name="ID" nillable="false" type="xsd:int"/>
+          <xsd:element name="NAME" type="xsd:string"/>
+          <xsd:element maxOccurs="unbounded" name="sings" type="this:SONG"/> 
+       </xsd:sequence>
+        </xsd:complexType>   
+   
+   <!-- A Song -->
+       <xsd:complexType name="SONG">
+               <xsd:sequence>
+                       <xsd:element name="ID" nillable="false" type="xsd:int"/>
+                       <xsd:element name="TITLE" type="xsd:string"/>
+                       <xsd:element name="SINGERID" type="xsd:int"/>
+               </xsd:sequence>
+       </xsd:complexType>
+          
+</xsd:schema>

Modified: 
incubator/tuscany/java/das/rdb/src/test/resources/customerOrderRelationshipMapping.xml
URL: 
http://svn.apache.org/viewvc/incubator/tuscany/java/das/rdb/src/test/resources/customerOrderRelationshipMapping.xml?rev=588159&r1=588158&r2=588159&view=diff
==============================================================================
--- 
incubator/tuscany/java/das/rdb/src/test/resources/customerOrderRelationshipMapping.xml
 (original)
+++ 
incubator/tuscany/java/das/rdb/src/test/resources/customerOrderRelationshipMapping.xml
 Thu Oct 25 01:06:16 2007
@@ -19,10 +19,10 @@
  -->
 <Config xmlns="http:///org.apache.tuscany.das.rdb/config.xsd";> 
   
-  <Table tableName="CUSTOMER">
+  <Table tableName="CUSTOMER" typeName="Customer">
        <Column columnName="ID" primaryKey="true"/>
   </Table>
-  <Table tableName="ANORDER">
+  <Table tableName="ANORDER" typeName="AnOrder">
        <Column columnName="ID" primaryKey="true"/>
   </Table>
   



---------------------------------------------------------------------
To unsubscribe, e-mail: [EMAIL PROTECTED]
For additional commands, e-mail: [EMAIL PROTECTED]

Reply via email to