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]