I am having problems creating data objects with the SDO API to match data objects created by loading an XML document.
The problems occur for elements that have maxOccurs greater than one. The SDO implementation maps each such attribute to a List-valued property. However, the Lists that are used behave differently. Is there a way I can use the SDO API to dynamically create objects with the same properties as those created by loading an XML document? For example, the test case shown at the end of this note produces this output: ------------------------------------------------------------- for 'aString' property: XML & reference type value was: [This is a repeated string., This is a repeated string.] API & dynamic type value was: [This is a repeated string.] API & reference type value was: [This is a repeated string.] for 'aBoolean' property: XML & reference type value was: [true, false, true, true, false] API & dynamic type value was: [true, false] API & reference type value was: [true, false] for 'aFloat' property: XML & reference type value was: [0.0, 12.5, 0.0] API & dynamic type value was: [0.0, 12.5] API & reference type value was: [0.0, 12.5] object from XML & reference type sequence has size=21 This is a repeated string. This is a repeated string. true false true true false 0.0 12.5 0.0 object from API & dynamic type sequence has size=5 This is a repeated string. true false 0.0 12.5 object from API & reference type sequence has size=10 This is a repeated string. This is a repeated string. true false true true false 0.0 12.5 0.0 ------------------------------------------------------------- This is the test case that can be put in the Tuscany\java\sdo\impl\src\test\java\org\apache\tuscany\sdo\test directory and run as a JUnit test: ------------------------------------------------------------- package org.apache.tuscany.sdo.test; import java.io.FileOutputStream; import java.io.IOException; import java.io.PrintStream; import java.util.List; import junit.framework.TestCase; import org.apache.tuscany.sdo.util.SDOUtil; import commonj.sdo.DataObject; import commonj.sdo.Sequence; import commonj.sdo.Type; import commonj.sdo.helper.DataFactory; import commonj.sdo.helper.HelperContext; import commonj.sdo.helper.TypeHelper; import commonj.sdo.helper.XMLDocument; import commonj.sdo.helper.XMLHelper; import commonj.sdo.helper.XSDHelper; /** * Tests dynamic creation of SDO types from specifications in DataObject */ public class DynamicTypesFromDataObjectSimpleTestCase extends TestCase { private final String COMMONJ_SDO = "commonj.sdo"; private final String DYNAMIC_ROOT_TYPE_0 = "TestType0"; private final String DYNAMIC_TYPES_SCHEMA_STRING = "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n"+ "<xsd:schema\n"+ " targetNamespace=\"http://www.example.com/dynamicTypesFromSchemaSimple\"\n"+ " xmlns:dtfs=\"http://www.example.com/dynamicTypesFromSchemaSimple\"\n"+ " xmlns:xsd=\"http://www.w3.org/2001/XMLSchema\">\n"+ " \n"+ " <xsd:complexType name=\"TestType0\" mixed=\"true\">\n"+ " <xsd:sequence>\n"+ " <xsd:element name=\"aString\" minOccurs=\"0\" maxOccurs=\"unbounded\" type=\"xsd:string\"/>\n"+ " <xsd:element name=\"aBoolean\" minOccurs=\"0\" maxOccurs=\"unbounded\" type=\"xsd:boolean\"/>\n"+ " <xsd:element name=\"aFloat\" minOccurs=\"0\" maxOccurs=\"unbounded\" type=\"xsd:float\"/>\n"+ " </xsd:sequence>\n"+ " </xsd:complexType>\n"+ " \n"+ " <xsd:element name=\"testElement0\" type=\"dtfs:TestType0\"/>\n"+ " \n"+ "</xsd:schema>\n"; private final String DYNAMIC_TYPES_URI = "http://www.example.com/dynamicTypesFromSchemaSimple"; private final String TEST_XML_DOC_0_STRING = "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n"+ "<dtfs:testElement0 xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\"\n"+ " xmlns:dtfs=\"http://www.example.com/dynamicTypesFromSchemaSimple\">\n"+ " <aString>This is a repeated string.</aString>\n"+ " <aString>This is a repeated string.</aString>\n"+ " <aBoolean>true</aBoolean>\n"+ " <aBoolean>false</aBoolean>\n"+ " <aBoolean>true</aBoolean>\n"+ " <aBoolean>1</aBoolean>\n"+ " <aBoolean>0</aBoolean>\n"+ " <aFloat>0</aFloat>\n"+ " <aFloat>12.5</aFloat>\n"+ " <aFloat>0</aFloat>\n"+ "</dtfs:testElement0>\n"; protected void setUp() throws Exception { super.setUp(); } private void specifyProperty(DataObject containingTypeDO, String nameString, Type typ, boolean isMany) { DataObject subordinateProperty = containingTypeDO.createDataObject("property"); subordinateProperty.set("name", nameString); subordinateProperty.set("type", typ); subordinateProperty.setBoolean("many", isMany); } /** * test #0 of Data Object primitive datatypes */ public void testDynamicTypesGroup0DO() throws IOException { 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, "aString", thDO.getType(COMMONJ_SDO, "String"), true); specifyProperty(containerTypeDO, "aBoolean", thDO.getType(COMMONJ_SDO, "Boolean"), true); specifyProperty(containerTypeDO, "aFloat", thDO.getType(COMMONJ_SDO, "Float"), true); Type containerType = thDO.define(containerTypeDO); assertNotNull(containerType); DataObject doFromApiAndDynTyp = dfDO.create(containerType); assertNotNull(doFromApiAndDynTyp); doFromApiAndDynTyp.getList("aString").add("This is a repeated string."); doFromApiAndDynTyp.getList("aString").add("This is a repeated string."); doFromApiAndDynTyp.getList("aBoolean").add(new Boolean(true)); doFromApiAndDynTyp.getList("aBoolean").add(new Boolean(false)); doFromApiAndDynTyp.getList("aBoolean").add(new Boolean(true)); doFromApiAndDynTyp.getList("aBoolean").add(new Boolean(true)); doFromApiAndDynTyp.getList("aBoolean").add(new Boolean(false)); doFromApiAndDynTyp.getList("aFloat").add(new Float(0)); doFromApiAndDynTyp.getList("aFloat").add(new Float(12.5)); doFromApiAndDynTyp.getList("aFloat").add(new Float(0)); Type rootType = thDO.getType(DYNAMIC_TYPES_URI, DYNAMIC_ROOT_TYPE_0); assertNotNull(rootType); assertSame(containerType, rootType); // now load xml to get a reference data object using schema HelperContext hcRef = SDOUtil.createHelperContext(); XSDHelper xsdHelper = hcRef.getXSDHelper(); List typeList = xsdHelper.define(DYNAMIC_TYPES_SCHEMA_STRING); assertNotNull(typeList); TypeHelper thRef = hcRef.getTypeHelper(); Type rootTypeRef = thRef.getType(DYNAMIC_TYPES_URI, DYNAMIC_ROOT_TYPE_0); assertNotNull(rootTypeRef); XMLHelper xhRef = hcRef.getXMLHelper(); //XMLDocument docRef = xhRef.load(getClass().getResourceAsStream(TEST_XML_DOC_0)); XMLDocument docRef = xhRef.load(TEST_XML_DOC_0_STRING); DataObject doFromXmlAndRefTyp = docRef.getRootObject(); assertNotNull(doFromXmlAndRefTyp); // create a data object using dynamic API from reference type DataFactory dfRef = hcRef.getDataFactory(); DataObject doFromApiAndRefTyp = dfRef.create(rootTypeRef); assertNotNull(doFromApiAndRefTyp); doFromApiAndRefTyp.getList("aString").add("This is a repeated string."); doFromApiAndRefTyp.getList("aString").add("This is a repeated string."); doFromApiAndRefTyp.getList("aBoolean").add(new Boolean(true)); doFromApiAndRefTyp.getList("aBoolean").add(new Boolean(false)); doFromApiAndRefTyp.getList("aBoolean").add(new Boolean(true)); doFromApiAndRefTyp.getList("aBoolean").add(new Boolean(true)); doFromApiAndRefTyp.getList("aBoolean").add(new Boolean(false)); doFromApiAndRefTyp.getList("aFloat").add(new Float(0)); doFromApiAndRefTyp.getList("aFloat").add(new Float(12.5)); doFromApiAndRefTyp.getList("aFloat").add(new Float(0)); //PrintStream ps = new PrintStream(new FileOutputStream("C:\\temp\\testDynamicTypesSimple0cmp.txt")); // qqq PrintStream ps = System.out; printPropertiesForRefAndTest(ps, "aString", doFromXmlAndRefTyp, doFromApiAndDynTyp, doFromApiAndRefTyp); printPropertiesForRefAndTest(ps, "aBoolean", doFromXmlAndRefTyp, doFromApiAndDynTyp, doFromApiAndRefTyp); printPropertiesForRefAndTest(ps, "aFloat", doFromXmlAndRefTyp, doFromApiAndDynTyp, doFromApiAndRefTyp); printSequence(ps, "object from XML & reference type", doFromXmlAndRefTyp.getSequence()); printSequence(ps, "object from API & dynamic type ", doFromApiAndDynTyp.getSequence()); printSequence(ps, "object from API & reference type", doFromApiAndRefTyp.getSequence()); //ps.close(); } private void printPropertiesForRefAndTest(PrintStream ps, String propName, DataObject xmlAndRefTypDO, DataObject apiAndDynTypDO, DataObject apiAndRefTypDO) { Object refProperty = xmlAndRefTypDO.get(propName); Object tstProperty = apiAndDynTypDO.get(propName); ps.println("for '"+propName+"' property:"); ps.println(" XML & reference type value was: "+refProperty); ps.println(" API & dynamic type value was: "+tstProperty); ps.println(" API & reference type value was: "+tstProperty+"\n"); } private void printSequence(PrintStream ps, String header, Sequence sequence) { if (sequence == null) { ps.println(header + " sequence is null"); } else { ps.println(header + " sequence has size=" + sequence.size()); for (int i = 0; i < sequence.size(); i++) { ps.println(" " + sequence.getValue(i)); } } } } ------------------------------------------------------------- Regards, Paul Golick e-mail: [EMAIL PROTECTED]