summaryrefslogtreecommitdiffstats
path: root/sdo-java/branches/sdo-1.1.1-incubating/sample/src/main/java/org/apache/tuscany/samples/sdo/advanced
diff options
context:
space:
mode:
Diffstat (limited to 'sdo-java/branches/sdo-1.1.1-incubating/sample/src/main/java/org/apache/tuscany/samples/sdo/advanced')
-rw-r--r--sdo-java/branches/sdo-1.1.1-incubating/sample/src/main/java/org/apache/tuscany/samples/sdo/advanced/MedicalScenario.java424
-rw-r--r--sdo-java/branches/sdo-1.1.1-incubating/sample/src/main/java/org/apache/tuscany/samples/sdo/advanced/MedicalScenarioWithChangeMonitoring.java449
-rw-r--r--sdo-java/branches/sdo-1.1.1-incubating/sample/src/main/java/org/apache/tuscany/samples/sdo/advanced/ObtainingDataGraphFromXml.java201
-rw-r--r--sdo-java/branches/sdo-1.1.1-incubating/sample/src/main/java/org/apache/tuscany/samples/sdo/advanced/PrintDataGraph.java498
-rw-r--r--sdo-java/branches/sdo-1.1.1-incubating/sample/src/main/java/org/apache/tuscany/samples/sdo/advanced/package.html31
5 files changed, 1603 insertions, 0 deletions
diff --git a/sdo-java/branches/sdo-1.1.1-incubating/sample/src/main/java/org/apache/tuscany/samples/sdo/advanced/MedicalScenario.java b/sdo-java/branches/sdo-1.1.1-incubating/sample/src/main/java/org/apache/tuscany/samples/sdo/advanced/MedicalScenario.java
new file mode 100644
index 0000000000..916fe9405c
--- /dev/null
+++ b/sdo-java/branches/sdo-1.1.1-incubating/sample/src/main/java/org/apache/tuscany/samples/sdo/advanced/MedicalScenario.java
@@ -0,0 +1,424 @@
+/**
+ * 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.
+ */
+package org.apache.tuscany.samples.sdo.advanced;
+
+import java.io.FileNotFoundException;
+import java.util.ArrayList;
+import java.util.List;
+
+import org.apache.tuscany.samples.sdo.SampleBase;
+import org.apache.tuscany.sdo.api.SDOUtil;
+
+import commonj.sdo.DataObject;
+import commonj.sdo.Property;
+import commonj.sdo.Type;
+import commonj.sdo.helper.DataFactory;
+import commonj.sdo.helper.HelperContext;
+import commonj.sdo.helper.TypeHelper;
+
+/**
+ * This sample is based on a 2 part article by Kelvin Goodson and Geoffrey Winn.
+ * See <A href="http://soa.sys-con.com/read/313547.htm">Part1</A> and <A
+ * href="http://soa.sys-con.com/read/358059.htm">Part 2</A> of the article.
+ * <p>
+ * <h3>Running this Sample</h3> See <A HREF="../../../../../../index.html"
+ * target="_top">the main overview</A> for instructions on how to run this
+ * sample.
+ */
+public class MedicalScenario extends SampleBase {
+
+ private static final String sdoApiUri = "commonj.sdo";
+
+ private static final String peopleURI = "www.example.org/people";
+
+ private static final String medicalURI = "www.example.org/MedicalTest";
+
+ boolean typesViaAPI = false;
+
+ private static final String usage = " [-api |-xsd]\n"
+ + " -api : define the types using the SDO API\n"
+ + " -xsd : define the types using an XML schema file";
+
+ public MedicalScenario(String[] args, Integer userLevel) {
+
+ super(userLevel, SAMPLE_LEVEL_ADVANCED);
+
+ if (args.length > 1) {
+ printUsage(args);
+ System.exit(-1);
+ }
+ if (args.length == 1) {
+ if (args[0].equals("-xsd")) {
+ typesViaAPI = false;
+ } else if (args[0].equals("-api")) {
+ typesViaAPI = true;
+ } else {
+ printUsage(args);
+ System.exit(-1);
+ }
+ }
+ }
+
+ public MedicalScenario(Integer userLevel) {
+ super(userLevel, SAMPLE_LEVEL_ADVANCED);
+ }
+
+
+ private void printUsage(String[] args) {
+ System.out.println("Usage: " + this.getClass().getName() + usage);
+ }
+
+ /**
+ * @param args
+ * @throws Exception
+ */
+ public static void main(String[] args) throws Exception {
+
+ MedicalScenario s = new MedicalScenario(args, COMMENTARY_FOR_NOVICE);
+ s.run();
+
+ }
+
+ /*
+ * metadata for the sample documenting the areas of SDO that are explored
+ */
+ public static int [] CORE_FUNCTION = {
+ SDOFacets.CONTAINMENT,
+ SDOFacets.CREATE_TYPES_USING_THE_SDO_API,
+ SDOFacets.CREATE_TYPES_USING_XML_SCHEMA,
+ SDOFacets.OPEN_CONTENT,
+ SDOFacets.NON_CONTAINMENT
+ };
+
+ public static int [] SIGNIFICANT_FUNCTION = {
+ SDOFacets.CREATE_DATAOBJECTS_BY_NAME,
+ SDOFacets.ISMANY_PROPERTIES,
+ SDOFacets.GENERIC_DATA_GRAPH_TRAVERSAL,
+ SDOFacets.SAVING_DATA_TO_XML
+ };
+
+ public void runSample() throws Exception {
+
+ HelperContext scope = SDOUtil.createHelperContext();
+
+ if (typesViaAPI) {
+
+ commentary("In this execution of the sample we use Types created\n"
+ + "using the SDO API");
+
+ createTypesViaAPI(scope);
+
+ } else {
+
+ commentary("In this execution of the sample we use Types created\n"
+ + "by loading an XMLSchema");
+
+ loadTypesFromXMLSchemaFile(scope, "MedicalTest.xsd");
+
+ }
+
+ commentary(
+ COMMENTARY_FOR_NOVICE,
+ "The DataFactory associated with the scope that the types were created within\n"
+ + "can be used to create an instance of the Person Type\n\n"
+ + "DataFactory dataFactory = scope.getDataFactory();\n"
+ + "DataObject person1 = dataFactory.create(\"www.example.org/people\", \"Person\");");
+
+ DataFactory dataFactory = scope.getDataFactory();
+ DataObject person1 = dataFactory.create("www.example.org/people", "Person");
+
+ commentary("The setString() of dataObject method is used to set the properties of the\n"
+ + "new Person DataObject, including a unique identifier reference value\n"
+ + "for the Person instance.\n\n"
+ + "person1.setString(\"id\", \"1\");\n"
+ + "person1.setString(\"name\", \"Joe Johnson Snr.\");\n"
+ + "person1.setString(\"gender\", \"male\"););");
+
+ person1.setString("id", "1");
+ person1.setString("name", "Joe Johnson Snr.");
+ person1.setString("gender", "male");
+
+ commentary("An alternative approach to using the DataFactory directly to create\n"
+ + "all DataObjects is to use a top-down approach, where we create the\n"
+ + "root object for a data graph, and then use the createDataObject(String propertyName)\n"
+ + "method to create the contained DataObjects. Here we create the overall\n"
+ + "medical test DataObject, and then create the contained \"referrals\" DataObject\n\n"
+ + "DataObject test = dataFactory.create(\"www.example.org/MedicalTest\", \"Test\");\n"
+ + "DataObject referrals = test.createDataObject(\"referrals\");");
+
+ DataObject test = dataFactory.create("www.example.org/MedicalTest", "Test");
+ DataObject referrals = test.createDataObject("referrals");
+
+ commentary("Now we can add the person we created earlier into the set of people who have\n"
+ + "been referred for this medical test.\n\n"
+ + "test.set(\"referrals\", referrals);\n"
+ + "referrals.getList(\"person\").add(person1);");
+
+ test.set("referrals", referrals);
+ referrals.getList("person").add(person1);
+
+ commentary("Let's take a look at how the current state of the data"
+ + "graph is rendered in XML ...");
+
+ System.out.println(scope.getXMLHelper().save(test,
+ "www.example.org/MedicalTest", "test"));
+
+ commentary("The scenario unfolds and the Joe Johnson Snr. becomes a patient\n\n"
+ + "DataObject patients = test.createDataObject(\"patients\");\n"
+ + "patients.getList(\"person\").add(person1);");
+
+ DataObject patients = test.createDataObject("patients");
+
+ patients.getList("person").add(person1);
+
+ commentary("Having added Joe Johnson Snr. to the set of patients we can see\n"
+ + "the way that SDO preserves a single containment hierarchy within a\n"
+ + "datagraph. If we look at the XML rendering of the graph again, we will\n"
+ + "see that by adding him to the set of patients he has been removed from the\n"
+ + "containment property associated with the referrals set ...");
+
+ System.out.println(scope.getXMLHelper().save(test,
+ "www.example.org/MedicalTest", "test"));
+
+ commentary("The 'Person' Type we are making use of here has been designed to be\n"
+ + "multi-purpose, in that the type has been declared to be 'Open'.\n"
+ + "That means that we can make use of 'Open Content' Properties\n"
+ + "(If the type system has been defined using an XML schema\n"
+ + "then these properties will derive from global elements)\n"
+ + "We can look up open content Properties using the TypeHelper\n\n"
+ + "Property conditionProperty = scope.getTypeHelper().getOpenContentProperty(\n"
+ + " \"www.example.org/MedicalTest\", \"condition\");");
+
+ Property conditionProperty = scope.getTypeHelper().getOpenContentProperty(
+ "www.example.org/MedicalTest", "condition");
+
+ commentary("We can create a value of the appropriate Type for this open\n"
+ + "content Property\n\n"
+ + "DataObject condition = dataFactory.create(conditionProperty.getType());\n"
+ + "condition.setString(\"name\", \"Panar Syndrome\");");
+
+ DataObject condition = dataFactory.create(conditionProperty.getType());
+ condition.setString("name", "Panar Syndrome");
+
+ commentary("If you ask a DataObject that has an 'Open' Type for its list of\n"
+ + "values associated with an open content Property, and the DataObject\n"
+ + "doesn't currently have any values for the Property, it will return\n"
+ + "an empty list. We can use the list to add values for the Property\n\n"
+ + "List conditions = person1.getList(conditionProperty);\n"
+ + "conditions.add(condition);");
+
+ List conditions = person1.getList(conditionProperty);
+ conditions.add(condition);
+
+ commentary("A further look at the data graph in XML form shows\n"
+ + "the presence of the new condition Property's value ...");
+
+ System.out.println(scope.getXMLHelper().save(test,
+ "www.example.org/MedicalTest", "test"));
+
+ commentary("Having looked at the way SDO handles Open content\n"
+ + "We now turn our attention to 'non-containment' relationships.\n"
+ + "To do this we first create the set of people in the test that\n"
+ + "constitute the blood relatives of patients -- 'relatives'\n"
+ + "and define a new person to be Joe Johnson Snr's child.\n\n"
+ + "DataObject relatives = test.createDataObject(\"relatives\");\n"
+ + "DataObject person2 = relatives.createDataObject(\"person\");\n"
+ + "person2.setString(\"id\", \"2\");\n"
+ + "person2.setString(\"name\", \"Joe Johnson Jnr.\");\n"
+ + "person2.setString(\"gender\", \"male\");");
+
+ DataObject relatives = test.createDataObject("relatives");
+ DataObject person2 = relatives.createDataObject("person");
+
+ person2.setString("id", "2");
+ person2.setString("name", "Joe Johnson Jnr.");
+ person2.setString("gender", "male");
+
+ commentary("Another quick look at the XML rendering of the graph confirms that\n"
+ + "the set of relatives now includes Joe Johnson Jnr, but we haven't yet\n"
+ + "defined who he is related to, or how.");
+
+ System.out.println(scope.getXMLHelper().save(test,
+ "www.example.org/MedicalTest", "test"));
+
+ commentary("The Person type has a Property 'relative'\n"
+ + "so we create a relative for Joe Johnson Snr.\n\n"
+ + "DataObject relation = person1.createDataObject(\"relative\");\n"
+ + "relation.set(\"target\", person2);\n"
+ + "relation.set(\"relationship\", \"child\");");
+
+ DataObject relation = person1.createDataObject("relative");
+ relation.set("target", person2);
+ relation.set("relationship", "child");
+
+ commentary("Now when we look at the XML rendering of the data graph\n"
+ + "we can see that the action of setting the 'target' of the\n"
+ + "relationship to Joe Johnson Jnr didn't displace him from the\n"
+ + "set of 'relatives', because the 'target' Property is a\n"
+ + "non-containment Property. This non-containment relationship\n"
+ + "is reflected in the XML by a reference to the Person DataObject\n"
+ + "describing Joe Johnson Jnr, \"2\" ...\n"
+ + "If the Type system has been created from an XML schema then the\n"
+ + "unique ID of the target can be used in the serialization.\n"
+ + "If however the type system was defined dynamically, then the reference\n"
+ + "will be represented as an XPath from the root of the data graph.");
+
+ System.out.println(scope.getXMLHelper().save(test,
+ "www.example.org/MedicalTest", "test"));
+
+ commentary("Now that the graph is complete we can use the PrintDataGraph sample utility\n" +
+ "to reveal the full SDO nature of the final data graph\n\n" +
+ "");
+
+ PrintDataGraph printer = new PrintDataGraph(COMMENTARY_FOR_ADVANCED);
+ printer.printDataObject(test);
+ System.out.println(printer.getBuf());
+ }
+
+ /**
+ * @throws Exception
+ * @throws FileNotFoundException
+ */
+ private void createTypesViaAPI(HelperContext scope) throws Exception {
+
+ List typeDeclarations = new ArrayList();
+
+ TypeHelper typeHelper = scope.getTypeHelper();
+
+ Type stringType = typeHelper.getType(sdoApiUri, "String");
+ Type dateType = typeHelper.getType(sdoApiUri, "Date");
+ Type booleanType = typeHelper.getType(sdoApiUri, "Boolean");
+
+ // <complexType name="Person">
+ // <sequence>
+ // <element name="dob" type="date"/>
+ // <element name="relative" maxOccurs="unbounded" type="tns:Relative"/>
+ // <any namespace="##other" processContents="lax" maxOccurs="unbounded"/>
+ // </sequence>
+ // <attribute name="id" type="ID"/>
+ // <attribute name="name" type="string"/>
+ // <attribute name="gender" type = "tns:Gender"/>
+ // </complexType>
+
+ DataObject personTypeDesc = createTypeDescription(scope, peopleURI,
+ "Person");
+ typeDeclarations.add(personTypeDesc);
+
+ addPropertyDescription(personTypeDesc, stringType, "name");
+ addPropertyDescription(personTypeDesc, dateType, "dob");
+ addPropertyDescription(personTypeDesc, stringType, "id"); // set to unique
+ // identifier?
+ addPropertyDescription(personTypeDesc, stringType, "gender"); // restrict?
+
+ DataObject relativeType = createTypeDescription(scope, peopleURI,
+ "Relative"); // forward declare the Relative type
+ typeDeclarations.add(relativeType);
+
+ DataObject rp = addPropertyDescription(personTypeDesc, relativeType,
+ "relative");
+ rp.setBoolean("many", true);
+ personTypeDesc.set("open", Boolean.TRUE);
+
+ // <complexType name="Relative">
+ // <attribute name="target" type="IDREF" sdoxml:propertyType="tns:Person"
+ // use="required"/>
+ // <attribute name="relationship" type="string" />
+ // <attribute name="genetic" use="optional" type="boolean"/>
+ // </complexType>
+
+ addPropertyDescription(relativeType, stringType, "relationship");
+ addPropertyDescription(relativeType, booleanType, "genetic");
+ DataObject targetPersonProp = addPropertyDescription(relativeType,
+ personTypeDesc, "target");
+ targetPersonProp.setBoolean("containment", false);
+
+ // <complexType name="PersonSet">
+ // <sequence>
+ // <element name="person" type="tns:Person" maxOccurs="unbounded"/>
+ // </sequence>
+ // </complexType>
+
+ DataObject pSet = createTypeDescription(scope, peopleURI, "PersonSet");
+ typeDeclarations.add(pSet);
+ DataObject pSetProperty = addPropertyDescription(pSet, personTypeDesc,
+ "person");
+ pSetProperty.setBoolean("many", true);
+
+ // <complexType name="Condition">
+ // <sequence>
+ // <element name="diagnosed" type="date" />
+ // </sequence>
+ // <attribute name="name" type="tns:ConditionName" />
+ // </complexType>
+
+ DataObject condition = createTypeDescription(scope, medicalURI, "Condition");
+ typeDeclarations.add(condition);
+ addPropertyDescription(condition, booleanType, "diagnosed");
+ addPropertyDescription(condition, stringType, "name"); // constrain?
+
+ // <complexType name="Test">
+ // <sequence>
+ // <element name="referrals" type="people:PersonSet" />
+ // <element name="patients" type="people:PersonSet" />
+ // <element name="relatives" type="people:PersonSet" />
+ // </sequence>
+ // </complexType>
+
+ DataObject testType = createTypeDescription(scope, medicalURI, "Test");
+ typeDeclarations.add(testType);
+ addPropertyDescription(testType, pSet, "referrals");
+ addPropertyDescription(testType, pSet, "patients");
+ addPropertyDescription(testType, pSet, "relatives");
+
+ List types = typeHelper.define(typeDeclarations);
+
+ DataObject p = scope.getDataFactory().create("commonj.sdo", "Property");
+ p.set("type", typeHelper.getType(medicalURI, "Condition"));
+ p.set("name", "condition");
+ p.setBoolean("many", true);
+ p.setBoolean("containment", true); // why is this not the default?
+
+ typeHelper.defineOpenContentProperty(medicalURI, p);
+
+ }
+
+ /**
+ * @param uri
+ * @param name
+ * @return
+ */
+ private DataObject createTypeDescription(HelperContext scope, String uri,
+ String name) {
+ DataObject typeDesc = scope.getDataFactory().create(sdoApiUri, "Type");
+ typeDesc.set("name", name);
+ typeDesc.set("uri", uri);
+ return typeDesc;
+ }
+
+ private DataObject addPropertyDescription(
+ DataObject containerTypeDescription, Object propertyType,
+ String propertyName) {
+ DataObject property = containerTypeDescription.createDataObject("property");
+ property.set("type", propertyType);
+ property.setString("name", propertyName);
+ property.setBoolean("containment", true);
+ return property;
+ }
+
+}
diff --git a/sdo-java/branches/sdo-1.1.1-incubating/sample/src/main/java/org/apache/tuscany/samples/sdo/advanced/MedicalScenarioWithChangeMonitoring.java b/sdo-java/branches/sdo-1.1.1-incubating/sample/src/main/java/org/apache/tuscany/samples/sdo/advanced/MedicalScenarioWithChangeMonitoring.java
new file mode 100644
index 0000000000..32d63f4335
--- /dev/null
+++ b/sdo-java/branches/sdo-1.1.1-incubating/sample/src/main/java/org/apache/tuscany/samples/sdo/advanced/MedicalScenarioWithChangeMonitoring.java
@@ -0,0 +1,449 @@
+/**
+ * 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.
+ */
+package org.apache.tuscany.samples.sdo.advanced;
+
+import java.io.FileNotFoundException;
+import java.util.ArrayList;
+import java.util.List;
+
+import org.apache.tuscany.samples.sdo.SampleBase;
+import org.apache.tuscany.sdo.api.SDOUtil;
+
+import commonj.sdo.DataObject;
+import commonj.sdo.Property;
+import commonj.sdo.Type;
+import commonj.sdo.helper.DataFactory;
+import commonj.sdo.helper.HelperContext;
+import commonj.sdo.helper.TypeHelper;
+
+/**
+ * This sample is based on a 2 part article by Kelvin Goodson and Geoffrey Winn.
+ * In this variant of the sample the model for the test includes change monitoring.
+ * The facility for undoing changes on the basis of the change monitoring is
+ * demonstrated.
+ * See <A href="http://soa.sys-con.com/read/313547.htm">Part1</A> and <A
+ * href="http://soa.sys-con.com/read/358059.htm">Part 2</A> of the article.
+ * <p>
+ * <h3>Running this Sample</h3> See <A HREF="../../../../../../index.html"
+ * target="_top">the main overview</A> for instructions on how to run this
+ * sample.
+ */
+public class MedicalScenarioWithChangeMonitoring extends SampleBase {
+
+ private static final String sdoApiUri = "commonj.sdo";
+
+ private static final String peopleURI = "www.example.org/people";
+
+ private static final String medicalURI = "www.example.org/MedicalTest";
+
+ boolean typesViaAPI = false;
+
+ private static final String usage = " [-api |-xsd]\n"
+ + " -api : define the types using the SDO API\n"
+ + " -xsd : define the types using an XML schema file";
+
+ public MedicalScenarioWithChangeMonitoring(String[] args, Integer userLevel) {
+
+ super(userLevel, SAMPLE_LEVEL_ADVANCED);
+
+ if (args.length > 1) {
+ printUsage(args);
+ System.exit(-1);
+ }
+ if (args.length == 1) {
+ if (args[0].equals("-xsd")) {
+ typesViaAPI = false;
+ } else if (args[0].equals("-api")) {
+ typesViaAPI = true;
+ } else {
+ printUsage(args);
+ System.exit(-1);
+ }
+ }
+ }
+
+ public MedicalScenarioWithChangeMonitoring(Integer userLevel) {
+ super(userLevel, SAMPLE_LEVEL_ADVANCED);
+ }
+
+
+ private void printUsage(String[] args) {
+ System.out.println("Usage: " + this.getClass().getName() + usage);
+ }
+
+ /**
+ * @param args
+ * @throws Exception
+ */
+ public static void main(String[] args) throws Exception {
+
+ MedicalScenarioWithChangeMonitoring s = new MedicalScenarioWithChangeMonitoring(args, COMMENTARY_FOR_NOVICE);
+ s.run();
+
+ }
+
+ /*
+ * metadata for the sample documenting the areas of SDO that are explored
+ */
+ public static int [] CORE_FUNCTION = {
+ SDOFacets.CONTAINMENT,
+ SDOFacets.CREATE_TYPES_USING_THE_SDO_API,
+ SDOFacets.CREATE_TYPES_USING_XML_SCHEMA,
+ SDOFacets.OPEN_CONTENT,
+ SDOFacets.NON_CONTAINMENT,
+ SDOFacets.CHANGE_MONITORING_USING_A_CHANGESUMMARY_PROPERTY_ON_A_DATAOBJECT
+ };
+
+ public static int [] SIGNIFICANT_FUNCTION = {
+ SDOFacets.CREATE_DATAOBJECTS_BY_NAME,
+ SDOFacets.ISMANY_PROPERTIES,
+ SDOFacets.GENERIC_DATA_GRAPH_TRAVERSAL,
+ SDOFacets.SAVING_DATA_TO_XML
+ };
+
+ public void runSample() throws Exception {
+
+ HelperContext scope = SDOUtil.createHelperContext();
+
+ if (typesViaAPI) {
+
+ commentary("In this execution of the sample we use Types created\n"
+ + "using the SDO API");
+
+ createTypesViaAPI(scope);
+
+ } else {
+
+ commentary("In this execution of the sample we use Types created\n"
+ + "by loading a variant of the XMLSchema that includes a change summary Property");
+
+ loadTypesFromXMLSchemaFile(scope, "MedicalTest_CS.xsd");
+
+ }
+
+ commentary(
+ COMMENTARY_FOR_NOVICE,
+ "The DataFactory associated with the scope that the types were created within\n"
+ + "can be used to create an instance of the Person Type\n\n"
+ + "DataFactory dataFactory = scope.getDataFactory();\n"
+ + "DataObject person1 = dataFactory.create(\"www.example.org/people\", \"Person\");");
+
+ DataFactory dataFactory = scope.getDataFactory();
+ DataObject person1 = dataFactory.create("www.example.org/people", "Person");
+
+ commentary("The setString() of dataObject method is used to set the properties of the\n"
+ + "new Person DataObject, including a unique identifier reference value\n"
+ + "for the Person instance.\n\n"
+ + "person1.setString(\"id\", \"1\");\n"
+ + "person1.setString(\"name\", \"Joe Johnson Snr.\");\n"
+ + "person1.setString(\"gender\", \"male\"););");
+
+ person1.setString("id", "1");
+ person1.setString("name", "Joe Johnson Snr.");
+ person1.setString("gender", "male");
+
+ commentary("An alternative approach to using the DataFactory directly to create\n"
+ + "all DataObjects is to use a top-down approach, where we create the\n"
+ + "root object for a data graph, and then use the createDataObject(String propertyName)\n"
+ + "method to create the contained DataObjects. Here we create the overall\n"
+ + "medical test DataObject, and then create the contained \"referrals\" DataObject\n\n"
+ + "DataObject test = dataFactory.create(\"www.example.org/MedicalTest\", \"Test\");\n"
+ + "DataObject referrals = test.createDataObject(\"referrals\");");
+
+ DataObject test = dataFactory.create("www.example.org/MedicalTest", "Test");
+
+ DataObject referrals = test.createDataObject("referrals");
+
+ commentary("The default state for monitoring changes for the DataObject when created in this\n" +
+ "way is the monitoring is switched off, so we switch it on. (Note that if you\n" +
+ "get your data graphs from a data Access Service then this service may turn on\n" +
+ "change monitoring be default\n\n" +
+ "test.getChangeSummary().beginLogging();");
+ test.getChangeSummary().beginLogging();
+
+ commentary("We'll repeat the whole of the MedicalScenario sample, but then at the \n" +
+ "last minute we'll decide it was all wrong and roll back the changes......");
+
+ commentary("Now we can add the person we created earlier into the set of people who have\n"
+ + "been referred for this medical test.\n\n"
+ + "test.set(\"referrals\", referrals);\n"
+ + "referrals.getList(\"person\").add(person1);");
+
+ test.set("referrals", referrals);
+ referrals.getList("person").add(person1);
+
+ commentary("Let's take a look at how the current state of the data"
+ + "graph is rendered in XML ...");
+
+ System.out.println(scope.getXMLHelper().save(test,
+ "www.example.org/MedicalTest", "test"));
+
+ commentary("The scenario unfolds and the Joe Johnson Snr. becomes a patient\n\n"
+ + "DataObject patients = test.createDataObject(\"patients\");\n"
+ + "patients.getList(\"person\").add(person1);");
+
+ DataObject patients = test.createDataObject("patients");
+
+ patients.getList("person").add(person1);
+
+ commentary("Having added Joe Johnson Snr. to the set of patients we can see\n"
+ + "the way that SDO preserves a single containment hierarchy within a\n"
+ + "datagraph. If we look at the XML rendering of the graph again, we will\n"
+ + "see that by adding him to the set of patients he has been removed from the\n"
+ + "containment property associated with the referrals set ...");
+
+ System.out.println(scope.getXMLHelper().save(test,
+ "www.example.org/MedicalTest", "test"));
+
+ commentary("The 'Person' Type we are making use of here has been designed to be\n"
+ + "multi-purpose, in that the type has been declared to be 'Open'.\n"
+ + "That means that we can make use of 'Open Content' Properties\n"
+ + "(If the type system has been defined using an XML schema\n"
+ + "then these properties will derive from global elements)\n"
+ + "We can look up open content Properties using the TypeHelper\n\n"
+ + "Property conditionProperty = scope.getTypeHelper().getOpenContentProperty(\n"
+ + " \"www.example.org/MedicalTest\", \"condition\");");
+
+ Property conditionProperty = scope.getTypeHelper().getOpenContentProperty(
+ "www.example.org/MedicalTest", "condition");
+
+ commentary("We can create a value of the appropriate Type for this open\n"
+ + "content Property\n\n"
+ + "DataObject condition = dataFactory.create(conditionProperty.getType());\n"
+ + "condition.setString(\"name\", \"Panar Syndrome\");");
+
+ DataObject condition = dataFactory.create(conditionProperty.getType());
+ condition.setString("name", "Panar Syndrome");
+
+ commentary("If you ask a DataObject that has an 'Open' Type for its list of\n"
+ + "values associated with an open content Property, and the DataObject\n"
+ + "doesn't currently have any values for the Property, it will return\n"
+ + "an empty list. We can use the list to add values for the Property\n\n"
+ + "List conditions = person1.getList(conditionProperty);\n"
+ + "conditions.add(condition);");
+
+ List conditions = person1.getList(conditionProperty);
+ conditions.add(condition);
+
+ commentary("A further look at the data graph in XML form shows\n"
+ + "the presence of the new condition Property's value ...");
+
+ System.out.println(scope.getXMLHelper().save(test,
+ "www.example.org/MedicalTest", "test"));
+
+ commentary("Having looked at the way SDO handles Open content\n"
+ + "We now turn our attention to 'non-containment' relationships.\n"
+ + "To do this we first create the set of people in the test that\n"
+ + "constitute the blood relatives of patients -- 'relatives'\n"
+ + "and define a new person to be Joe Johnson Snr's child.\n\n"
+ + "DataObject relatives = test.createDataObject(\"relatives\");\n"
+ + "DataObject person2 = relatives.createDataObject(\"person\");\n"
+ + "person2.setString(\"id\", \"2\");\n"
+ + "person2.setString(\"name\", \"Joe Johnson Jnr.\");\n"
+ + "person2.setString(\"gender\", \"male\");");
+
+ DataObject relatives = test.createDataObject("relatives");
+ DataObject person2 = relatives.createDataObject("person");
+
+ person2.setString("id", "2");
+ person2.setString("name", "Joe Johnson Jnr.");
+ person2.setString("gender", "male");
+
+ commentary("Another quick look at the XML rendering of the graph confirms that\n"
+ + "the set of relatives now includes Joe Johnson Jnr, but we haven't yet\n"
+ + "defined who he is related to, or how.");
+
+ System.out.println(scope.getXMLHelper().save(test,
+ "www.example.org/MedicalTest", "test"));
+
+ commentary("The Person type has a Property 'relative'\n"
+ + "so we create a relative for Joe Johnson Snr.\n\n"
+ + "DataObject relation = person1.createDataObject(\"relative\");\n"
+ + "relation.set(\"target\", person2);\n"
+ + "relation.set(\"relationship\", \"child\");");
+
+ DataObject relation = person1.createDataObject("relative");
+ relation.set("target", person2);
+ relation.set("relationship", "child");
+
+ commentary("Now when we look at the XML rendering of the data graph\n"
+ + "we can see that the action of setting the 'target' of the\n"
+ + "relationship to Joe Johnson Jnr didn't displace him from the\n"
+ + "set of 'relatives', because the 'target' Property is a\n"
+ + "non-containment Property. This non-containment relationship\n"
+ + "is reflected in the XML by a reference to the Person DataObject\n"
+ + "describing Joe Johnson Jnr, \"2\" ...\n"
+ + "If the Type system has been created from an XML schema then the\n"
+ + "unique ID of the target can be used in the serialization.\n"
+ + "If however the type system was defined dynamically, then the reference\n"
+ + "will be represented as an XPath from the root of the data graph.");
+
+ System.out.println(scope.getXMLHelper().save(test,
+ "www.example.org/MedicalTest", "test"));
+
+ commentary("Now that the graph is complete we can use the PrintDataGraph sample utility\n" +
+ "to reveal the full SDO nature of the final data graph\n\n" +
+ "");
+
+ PrintDataGraph printer = new PrintDataGraph(COMMENTARY_FOR_ADVANCED);
+ printer.printDataObject(test);
+ System.out.println(printer.getBuf());
+
+ commentary("But Wait! it's all wrong. Let's go back to our checkpoint where we started monitoring changes\n\n" +
+ "test.getChangeSummary().undoChanges();");
+
+ test.getChangeSummary().undoChanges();
+
+ printer.reset();
+ printer.printDataObject(test);
+ System.out.println(printer.getBuf());
+
+ }
+
+ /**
+ * @throws Exception
+ * @throws FileNotFoundException
+ */
+ private void createTypesViaAPI(HelperContext scope) throws Exception {
+
+ List typeDeclarations = new ArrayList();
+
+ TypeHelper typeHelper = scope.getTypeHelper();
+
+ Type stringType = typeHelper.getType(sdoApiUri, "String");
+ Type dateType = typeHelper.getType(sdoApiUri, "Date");
+ Type booleanType = typeHelper.getType(sdoApiUri, "Boolean");
+
+ // <complexType name="Person">
+ // <sequence>
+ // <element name="dob" type="date"/>
+ // <element name="relative" maxOccurs="unbounded" type="tns:Relative"/>
+ // <any namespace="##other" processContents="lax" maxOccurs="unbounded"/>
+ // </sequence>
+ // <attribute name="id" type="ID"/>
+ // <attribute name="name" type="string"/>
+ // <attribute name="gender" type = "tns:Gender"/>
+ // </complexType>
+
+ DataObject personTypeDesc = createTypeDescription(scope, peopleURI,
+ "Person");
+ typeDeclarations.add(personTypeDesc);
+
+ addPropertyDescription(personTypeDesc, stringType, "name");
+ addPropertyDescription(personTypeDesc, dateType, "dob");
+ addPropertyDescription(personTypeDesc, stringType, "id"); // set to unique
+ // identifier?
+ addPropertyDescription(personTypeDesc, stringType, "gender"); // restrict?
+
+ DataObject relativeType = createTypeDescription(scope, peopleURI,
+ "Relative"); // forward declare the Relative type
+ typeDeclarations.add(relativeType);
+
+ DataObject rp = addPropertyDescription(personTypeDesc, relativeType,
+ "relative");
+ rp.setBoolean("many", true);
+ personTypeDesc.set("open", Boolean.TRUE);
+
+ // <complexType name="Relative">
+ // <attribute name="target" type="IDREF" sdoxml:propertyType="tns:Person"
+ // use="required"/>
+ // <attribute name="relationship" type="string" />
+ // <attribute name="genetic" use="optional" type="boolean"/>
+ // </complexType>
+
+ addPropertyDescription(relativeType, stringType, "relationship");
+ addPropertyDescription(relativeType, booleanType, "genetic");
+ DataObject targetPersonProp = addPropertyDescription(relativeType,
+ personTypeDesc, "target");
+ targetPersonProp.setBoolean("containment", false);
+
+ // <complexType name="PersonSet">
+ // <sequence>
+ // <element name="person" type="tns:Person" maxOccurs="unbounded"/>
+ // </sequence>
+ // </complexType>
+
+ DataObject pSet = createTypeDescription(scope, peopleURI, "PersonSet");
+ typeDeclarations.add(pSet);
+ DataObject pSetProperty = addPropertyDescription(pSet, personTypeDesc,
+ "person");
+ pSetProperty.setBoolean("many", true);
+
+ // <complexType name="Condition">
+ // <sequence>
+ // <element name="diagnosed" type="date" />
+ // </sequence>
+ // <attribute name="name" type="tns:ConditionName" />
+ // </complexType>
+
+ DataObject condition = createTypeDescription(scope, medicalURI, "Condition");
+ typeDeclarations.add(condition);
+ addPropertyDescription(condition, booleanType, "diagnosed");
+ addPropertyDescription(condition, stringType, "name"); // constrain?
+
+ // <complexType name="Test">
+ // <sequence>
+ // <element name="referrals" type="people:PersonSet" />
+ // <element name="patients" type="people:PersonSet" />
+ // <element name="relatives" type="people:PersonSet" />
+ // </sequence>
+ // </complexType>
+
+ DataObject testType = createTypeDescription(scope, medicalURI, "Test");
+ typeDeclarations.add(testType);
+ addPropertyDescription(testType, pSet, "referrals");
+ addPropertyDescription(testType, pSet, "patients");
+ addPropertyDescription(testType, pSet, "relatives");
+
+ List types = typeHelper.define(typeDeclarations);
+
+ DataObject p = scope.getDataFactory().create("commonj.sdo", "Property");
+ p.set("type", typeHelper.getType(medicalURI, "Condition"));
+ p.set("name", "condition");
+ p.setBoolean("many", true);
+ p.setBoolean("containment", true); // why is this not the default?
+
+ typeHelper.defineOpenContentProperty(medicalURI, p);
+
+ }
+
+ /**
+ * @param uri
+ * @param name
+ * @return
+ */
+ private DataObject createTypeDescription(HelperContext scope, String uri,
+ String name) {
+ DataObject typeDesc = scope.getDataFactory().create(sdoApiUri, "Type");
+ typeDesc.set("name", name);
+ typeDesc.set("uri", uri);
+ return typeDesc;
+ }
+
+ private DataObject addPropertyDescription(
+ DataObject containerTypeDescription, Object propertyType,
+ String propertyName) {
+ DataObject property = containerTypeDescription.createDataObject("property");
+ property.set("type", propertyType);
+ property.setString("name", propertyName);
+ property.setBoolean("containment", true);
+ return property;
+ }
+
+}
diff --git a/sdo-java/branches/sdo-1.1.1-incubating/sample/src/main/java/org/apache/tuscany/samples/sdo/advanced/ObtainingDataGraphFromXml.java b/sdo-java/branches/sdo-1.1.1-incubating/sample/src/main/java/org/apache/tuscany/samples/sdo/advanced/ObtainingDataGraphFromXml.java
new file mode 100644
index 0000000000..6d8ac0ab31
--- /dev/null
+++ b/sdo-java/branches/sdo-1.1.1-incubating/sample/src/main/java/org/apache/tuscany/samples/sdo/advanced/ObtainingDataGraphFromXml.java
@@ -0,0 +1,201 @@
+/**
+ *
+ * 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.
+ */
+
+package org.apache.tuscany.samples.sdo.advanced;
+
+import java.io.InputStream;
+
+import org.apache.tuscany.samples.sdo.SampleBase;
+import org.apache.tuscany.samples.sdo.internal.SampleInfrastructure;
+import org.apache.tuscany.sdo.api.SDOUtil;
+
+import commonj.sdo.DataGraph;
+import commonj.sdo.DataObject;
+import commonj.sdo.helper.HelperContext;
+import commonj.sdo.helper.XMLDocument;
+
+/**
+ * This sample program demonstrates a variety of methods available to obtain the root DataObject
+ * contained within an xml representation of a DataGraph. This is currently a grey
+ * area of the specification and this sample demonstrates spec compliant methods, as
+ * well as utility methods that have been added to Tuscany to address issues within
+ * the specification.
+ *
+ * The following sample is from the <a href="http://incubator.apache.org/tuscany"
+ * target="_blank"> Apache Tuscany</a> project. It was written to help users
+ * understand and experiment with SDO. It is based upon example code contained
+ * within, and is meant for use with, and reference to the <a
+ * href="http://osoa.org/download/attachments/36/Java-SDO-Spec-v2.1.0-FINAL.pdf?version=1"
+ * target="_bank">SDO Specification</a>. This sample attempts to clarify aspects of
+ * the the AccessDataObjectsUsingXPath example from the Examples section of the SDO
+ * specification.<br>
+ * <br>
+ * To define the correct Types for each DataObject ( CompanyType, DepartmentType etc )
+ * this sample relies upon
+ * {@link org.apache.tuscany.samples.sdo.internal.SampleInfrastructure#COMPANY_XSD} which is
+ * provided in the resources directory of these samples. The xml file
+ * {@link org.apache.tuscany.samples.sdo.internal.SampleInfrastructure#COMPANY_DATAGRAPH_XML} is
+ * used to load the DataGraph and is also located in this resources directory. <br>
+ * <p>
+ * <h3>Running this Sample</h3> See <A HREF="../../../../../../index.html"
+ * target="_top">the main overview</A> for instructions on how to run this
+ * sample.
+ */
+
+public class ObtainingDataGraphFromXml extends SampleBase {
+
+ HelperContext scope;
+
+
+
+ public ObtainingDataGraphFromXml(Integer userLevel) {
+ super(userLevel, SAMPLE_LEVEL_ADVANCED);
+ }
+
+ public static void main(String[] args) {
+
+ /*
+ * Create an instance of the sample program. Edit the "commentaryLevel" argument to suit
+ * your experience, COMMENTARY_FOR_NOVICE, COMMENTARY_FOR_INTERMEDIATE or COMMENTARY_FOR_ADVANCED
+ */
+ ObtainingDataGraphFromXml sample =
+ new ObtainingDataGraphFromXml(COMMENTARY_FOR_ADVANCED);
+ sample.run();
+
+ }
+
+ /*
+ * metadata for the sample documenting the areas of SDO that are explored
+ */
+ public static int [] CORE_FUNCTION = {
+ SDOFacets.WRAPPING_DATA_GRAPH_IN_A_DATAGRAPH_INSTANCE
+ };
+
+ public static int [] SIGNIFICANT_FUNCTION = {
+ SDOFacets.USING_BUILT_IN_TYPES
+ };
+
+
+ public void runSample () {
+ banner('*',
+ "SDO Sample " + this.getClass().getName() + "\n\n" +
+
+ "This sample touches an area of the SDO API where the emphasis has changed over the various\n"+
+ "version of the specification, and so it's important to be clear what's going on\n"+
+ "First off lets be sure of our terminology ...\n"+
+ "1) A \"data graph\" is a just collection of DataObjects, all contained within a single\n"+
+ "containment hierarchy, with a single root object, and possibly having some non-containment\n"+
+ "references\n"+
+ "2) A \"DataGraph\" is an instance of the SDO DataGraph class, used as a container for the root\n"+
+ "DataObject of a data graph, and providing a means to access a change summary for the data graph.\n\n"+
+ "More recent versions of the SDO specification have provided alternative means of containment\n"+
+ "of a data graph ...\n"+
+ "3) The graph can be contained in a DataObject of a built-in SDO Type with namespace URI \"commonj.sdo\"\n" +
+ "and name \"DataGraph\": so this is a modeled version of the special DataGraph class.\n"+
+ "4) The Graph can be contained in an XMLDocument instance, which provides for things such as\n"+
+ "naming the root element of an XML instance document"
+ );
+
+ scope = useDefaultScopeForTypes();
+ loadTypesFromXMLSchemaFile(scope, SampleInfrastructure.COMPANY_XSD);
+
+
+
+ try {
+
+
+
+
+ DataObject company = null;
+
+ commentary(
+ "Here we see the specification's example for obtaining dealing with\n"+
+ "loading a data graph which uses a method, XMLHelper.load(). This loads an XML instance document\n"+
+ "into an instance of XMLDocument ...\n\n"+
+ "XMLDocument doc = scope.getXMLHelper().load(\n"+
+ "ClassLoader.getSystemResourceAsStream(SampleInfrastructure.COMPANY_DATAGRAPH_XML));"
+ );
+
+ InputStream is = ClassLoader.getSystemResourceAsStream(SampleInfrastructure.COMPANY_DATAGRAPH_XML);
+ int x= is.available();
+ byte b[]= new byte[x];
+ is.read(b);
+ String instanceDoc = new String(b);
+
+ System.out.println(instanceDoc);
+
+ XMLDocument doc = scope.getXMLHelper().load(
+ ClassLoader.getSystemResourceAsStream(SampleInfrastructure.COMPANY_DATAGRAPH_XML));
+
+ commentary(
+ "Now we can get the wrapper for the data graph, which in this case is the DataObject\n"+
+ "of type commonj.sdo#DataGraph. Note how there's no magic here; no special class for\n"+
+ "DataGraph, no special handling, this is just a standard pattern of using a built in SDO Type.\n"+
+ "The wrapper is there purely because it was serialized\n"+
+ "into the XML document, using the standard serialization technique.\n\n" +
+ "DataObject dataObjectRepresentingDataGraph = doc.getRootObject();");
+
+ DataObject dataObjectRepresentingDataGraph = doc.getRootObject();
+
+ System.out.println(dataObjectRepresentingDataGraph);
+
+ commentary(
+ "If you are confused by the fact that what we really get is an instance of DataGraphTypeImpl\n"+
+ "This really is a DataObject, but it is a generated class extending DataObjectImpl\n+"+
+ "representing the DataGraph model.");
+
+ company = dataObjectRepresentingDataGraph.getDataObject("company");
+
+ commentary(
+ "We've obtained a DataObject representing the data graph, and from that we have obtained\n"+
+ "the true root object of the business data");
+
+ System.out.println(company);
+ System.out.println();
+
+ commentary(
+ "Using an instance of DataGraph can perhaps be seen as an older style pattern of wrapping a data graph\n"+
+ "and the first approach is likely to get more emphasis and attention in future revisions of the spec.\n"+
+ "The SDO API has some limitations in the area of saving and loading instances of the\n"+
+ "Java DataGraph type, so Tuscany has an API for doing this ...\n\n"+
+ "DataGraph datagraph = SDOUtil.loadDataGraph(\n"+
+ " ClassLoader.getSystemResourceAsStream(SampleInfrastructure.COMPANY_DATAGRAPH_XML), null);"
+
+ );
+
+ DataGraph datagraph = SDOUtil.loadDataGraph(ClassLoader.getSystemResourceAsStream(SampleInfrastructure.COMPANY_DATAGRAPH_XML), null);
+
+ System.out.println(datagraph);
+
+ commentary(
+ "In this case we directly receive an instance of DataGraph and can retrieve the root\n"+
+ "business object from the DataGraph\n\n"+
+ "DataObject company = datagraph.getRootObject();");
+
+ company = datagraph.getRootObject();
+ System.out.println(company);
+ System.out.println();
+
+ } catch (Exception e) {
+ somethingUnexpectedHasHappened(e);
+ }
+
+ }
+}
diff --git a/sdo-java/branches/sdo-1.1.1-incubating/sample/src/main/java/org/apache/tuscany/samples/sdo/advanced/PrintDataGraph.java b/sdo-java/branches/sdo-1.1.1-incubating/sample/src/main/java/org/apache/tuscany/samples/sdo/advanced/PrintDataGraph.java
new file mode 100644
index 0000000000..7458eef76c
--- /dev/null
+++ b/sdo-java/branches/sdo-1.1.1-incubating/sample/src/main/java/org/apache/tuscany/samples/sdo/advanced/PrintDataGraph.java
@@ -0,0 +1,498 @@
+/**
+ *
+ * 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.
+ */
+package org.apache.tuscany.samples.sdo.advanced;
+
+import java.util.ArrayList;
+import java.util.Iterator;
+import java.util.List;
+import java.util.ListIterator;
+
+import org.apache.tuscany.samples.sdo.SampleBase;
+import org.apache.tuscany.samples.sdo.internal.SampleInfrastructure;
+
+import commonj.sdo.DataObject;
+import commonj.sdo.Property;
+import commonj.sdo.Sequence;
+import commonj.sdo.Type;
+import commonj.sdo.helper.HelperContext;
+import commonj.sdo.helper.XMLDocument;
+import commonj.sdo.helper.XSDHelper;
+import commonj.sdo.impl.HelperProvider;
+
+/**
+ *
+ * This sample program traverses data graphs and builds up a text representation of the
+ * data graph. As it traverses a graph it outputs commentary to the console
+ * about what it has encountered and how it intends to process what it finds. At
+ * the end of each traversal the text representation of the graph is printed to
+ * the console.
+ * <p>
+ * <h3>Running this Sample</h3> See <A HREF="../../../../../../index.html"
+ * target="_top">the main overview</A> for instructions on how to run this
+ * sample.
+ */
+public class PrintDataGraph extends SampleBase {
+
+ StringBuffer buf = null;
+ HelperContext scope = HelperProvider.getDefaultContext();
+
+ private int indent;
+
+ private int indentIncrement = 2;
+
+ public PrintDataGraph(Integer userLevel) {
+ super(userLevel, SAMPLE_LEVEL_ADVANCED);
+ buf = new StringBuffer();
+ }
+
+ public static void main(String[] args) {
+ PrintDataGraph sample = new PrintDataGraph(COMMENTARY_FOR_NOVICE);
+ sample.run();
+ }
+
+ /*
+ * metadata for the sample documenting the areas of SDO that are explored
+ */
+ public static int [] CORE_FUNCTION = {
+ SDOFacets.GENERIC_DATA_GRAPH_TRAVERSAL
+ };
+
+ public static int [] SIGNIFICANT_FUNCTION = {
+ SDOFacets.GET_SET_PROPERTIES_BY_INSTANCE_PROPERTIES,
+ SDOFacets.ISMANY_PROPERTIES,
+ SDOFacets.CREATE_TYPES_USING_THE_SDO_API,
+ SDOFacets.ACCESSING_VALUES_IN_A_SEQUENCE,
+ SDOFacets.NON_CONTAINMENT
+ };
+
+ public void runSample() throws Exception {
+ commentary("This sample demonstrates a common pattern of traversing a data graph\n"
+ + "and printing the values of its Properties. As the sample traverses a couple of\n"
+ + "graphs it provides commentary about what it has found and what actions it\n"
+ + "is taking, whilst building up a text representation of the graph. It then\n"
+ + "shows you the results of its labours.");
+
+ HelperContext scope = createScopeForTypes();
+
+ commentary(
+ COMMENTARY_ALWAYS,
+ "First we look at a data graph of a Purchase Order which has a fairly simple XML schema\n"
+ + "and the graph's containment hierarchy has a couple of levels of depth");
+
+ loadTypesFromXMLSchemaFile(scope, SampleInfrastructure.PO_XSD_RESOURCE);
+
+ XMLDocument purchaseOrder = getXMLDocumentFromFile(scope,
+ SampleInfrastructure.PO_XML_RESOURCE);
+
+ printXMLDocument(purchaseOrder);
+
+ commentary(COMMENTARY_ALWAYS,
+ "And here is the resultant view of the data graph\n\n");
+ System.out.println(getBuf().toString());
+
+ commentary(COMMENTARY_ALWAYS,
+ "Next we look at a graph representing a form letter, where the Type of the\n"
+ + "root data object is 'Sequenced'");
+
+ loadTypesFromXMLSchemaFile(scope, "letter.xsd");
+ DataObject letter = getDataObjectFromFile(scope, "letter.xml");
+
+ reset();
+ print(letter);
+
+ commentary(COMMENTARY_ALWAYS,
+ "And here is the resultant view of the data graph\n\n");
+
+ System.out.println(getBuf().toString());
+
+ }
+
+ public void reset() {
+ indent = 0;
+ buf = new StringBuffer();
+ }
+
+ /*
+ * a convenience method allowing untyped access to the print function for
+ * selected SDO artifacts
+ */
+ public void print(Object sdoObject) throws Exception {
+
+ if (sdoObject instanceof XMLDocument) {
+ printXMLDocument((XMLDocument) sdoObject);
+ } else if (sdoObject instanceof DataObject) {
+ printDataObject((DataObject) sdoObject);
+ }
+
+ }
+
+ public void printXMLDocument(XMLDocument xmlDocument) {
+
+ commentary(
+ COMMENTARY_FOR_NOVICE,
+ "We are going to traverse a data graph that has been wrapped in an instance of XMLDocument\n"
+ + "Amongst other things, the XMLDocument instance provides access to the root element name\n"
+ + "and the root DataObject of the data graph.\n\n"
+ + "xmlDocument.getRootElementName();\n"
+ + "xmlDocument.getRootObject();",
+
+ "Accessing another graph via an XMLDocument instance as we saw previously ...\n"
+ + "xmlDocument.getRootElementName();\n"
+ + "xmlDocument.getRootObject();");
+
+ buf.append("XMLDocument: ").append(xmlDocument.getRootElementName());
+ lineBreak();
+ incrementIndent();
+ printDataObject(xmlDocument.getRootObject());
+ decrementIndent();
+ }
+
+ public void printDataObject(DataObject dataObject) {
+
+ if (dataObject.getContainer() == null) {
+ commentary(
+ COMMENTARY_FOR_NOVICE,
+ "We begin traversing the data graph by examining the root object of the graph's containment hierarchy,\n"
+ + "making a record of the values of its Properties. As we inspect the values of the Properties of this object\n"
+ + "if we encounter contained DataObjects, then we will recurs through the containment hierarchy of the\n"
+ + "data graph in a depth first fashion, and create a text representation of the graph that we'll print\n"
+ + "out after the graph traversal has been completed.",
+
+ "We are beginning to traverse another data graph from its root object, in the same way that we saw previously");
+ } else {
+ commentary(
+ COMMENTARY_FOR_NOVICE,
+ "We have arrived at a contained dataObject in the graph, and will inspect its Property values,\n"
+ + "recursing deeper if necessary",
+
+ "Inspecting another contained dataObject");
+ }
+
+ lineBreak();
+ indent();
+ buf.append("DataObject: ");
+ Type type = dataObject.getType();
+ buf.append("Type: ").append(type.getURI()).append('#').append(
+ type.getName());
+ lineBreak();
+
+ if (dataObject.getType().isSequenced()) {
+
+ commentary(
+ COMMENTARY_FOR_INTERMEDIATE,
+ "We've encountered a DataObject in the graph for which the Type is 'Sequenced'\n"
+ + "That is to say that the order of addition of Property values to the DataObject instance\n"
+ + "is important, and is preserved by the DataObject\n\n"
+ + "dataObject.getType().isSequenced();",
+
+ "We've encountered another sequenced DataObject instance, and so will traverse the Property\n"
+ + "values in the order preerved by the instance, as we saw before\n\n"
+ + "dataObject.getType().isSequenced();");
+
+ commentary(
+ "There's a subtlety here which we must deal with if this sample code is to\n" +
+ "handle both Type systems that derive from XML schema, and those that come from elsewhere,\n" +
+ "e.g. using the SDO API. If a Sequenced DataObject has a Type that comes from XML schema\n" +
+ "then its Properties that derive from XML attributes are not ordered, whereas those that\n" +
+ "derive from XML elements are ordered. The SDO specification doesn't say whether\n" +
+ "the attribute related Properties should appear at the start of a Sequence or not.\n" +
+ "Currently in Tuscany we leave them out of the Sequence; other SDO implementations may\n" +
+ "include the XML attributes in the Sequence. This sample code is written to deal with\n" +
+ "either approach\n." +
+ "We use the XSDHelper.isAttribute(Property) and isElement(Property) methods to distinguish\n" +
+ "between the two kinds of Property",
+
+ "Examining the xml attributes and elements of a Sequenced DataObject again."
+ );
+
+ XSDHelper xsdHelper = getScope().getXSDHelper();
+ incrementIndent();
+ for(Iterator it=dataObject.getInstanceProperties().iterator(); it.hasNext();) {
+ Property property = (Property)it.next();
+ if (xsdHelper.isAttribute(property)) {
+ indent();
+ buf.append("Property (XML Attribute): ").append(property.getName()).append(" - ").append(dataObject.get(property));
+ lineBreak();
+ }
+
+ }
+ decrementIndent();
+ Sequence seq = dataObject.getSequence();
+
+ commentary(
+ "The Property/Value pairs of a Sequence can be accessed via the getProperty(int) and getValue(int)\n"
+ + "accessor methods of the Sequence interface. The size() method of the Sequence tells us how many there are.\n"
+ + "If the getProperty(int) method returns null, then the value is text. These text values may be encountered\n"
+ + "when the DataObject's type is 'mixed' (dataObject.getType().isMixed() == true). A typical example of this\n"
+ + "is when the data graph represents a form letter.",
+
+ "Inspecting the Property/Value pairs of another Sequence");
+
+ incrementIndent();
+ indent();
+ buf.append("Sequence: {\n");
+
+ incrementIndent();
+ for (int i = 0; i < seq.size(); i++) {
+ Property p = seq.getProperty(i);
+ if (p == null) {
+ indent();
+ buf.append("text: ").append(seq.getValue(i));
+ lineBreak();
+ } else if(!xsdHelper.isAttribute(p)){
+ printPropertyValuePair(p, seq.getValue(i));
+ }
+ }
+ decrementIndent();
+
+ indent();
+ buf.append("}\n");
+ decrementIndent();
+
+ } else {
+ incrementIndent();
+
+ commentary(
+ COMMENTARY_FOR_INTERMEDIATE,
+ "We access the Property values of this DataObject by first getting the list of 'Instance Properties'\n"
+ + "from the DataObject. For many DataObjects, this will be the same set of Properties that are defined\n"
+ + "by the DataObject's Type. However, if the DataObject's type is 'Open' then an instance of that Type\n"
+ + "may contain more Properties than the type itself. The list of Instance Properties will always include\n"
+ + "the Properties defined in the Type, but will also include any Properties that the instance has values for\n"
+ + "by virtue of it's type being 'Open'\n\n"
+ + "for (int i = 0; i < dataObject.getInstanceProperties().size(); i++) {\n"
+ + " Property p = (Property) dataObject.getInstanceProperties().get(i);",
+
+ "Traversing the instance Properties of this DataObject\n"
+ + "for (int i = 0; i < dataObject.getInstanceProperties().size(); i++) {\n"
+ + " Property p = (Property) dataObject.getInstanceProperties().get(i);"
+
+ );
+
+ for (int i = 0; i < dataObject.getInstanceProperties().size(); i++) {
+ Property p = (Property) dataObject.getInstanceProperties().get(i);
+ indent();
+ printValueOfProperty(dataObject, p);
+ }
+
+ decrementIndent();
+ }
+
+ }
+
+
+
+
+
+ private void printPropertyValuePair(Property p, Object value) {
+
+ indent();
+ buf.append("Property: ").append(p.getName()).append(": ");
+ if(p.getType().isDataType()) {
+ printSimpleValue(value);
+ lineBreak();
+ } else {
+ if(p.isContainment()) {
+ incrementIndent();
+ printDataObject((DataObject)value);
+ decrementIndent();
+ } else {
+ printReferencedDataObject((DataObject)value);
+ }
+ }
+
+
+ }
+
+ private void printValueOfProperty(DataObject dataObject, Property p) {
+
+ commentary(
+ COMMENTARY_FOR_INTERMEDIATE,
+ "We are about to inspect the value of a Property, but we must\n"
+ + "consider the nature of that Property in order to deal with it appropriately.\n"
+ + "Firstly we see if the Property value has been set (dataObject.isSet(property))\n"
+ + "Then we see if the Property is simple valued (property.isDataType() == true)\n"
+ + "--if not then we know it's a DataObject and we must recurs deeper into the graph's\n"
+ + "containment hierarchy\n"
+ + "Whether or not the property value is a DataObject, is may be single or multi-valued\n"
+ + "so we must either use one of the DataObject's get*(Property) accessors for single\n"
+ + "valued Properties or the getList() method for multi-valued properties.\n"
+ + "Another thing we must deal with when the Property is a DataObject, is whether or not the\n"
+ + "Property is a 'containment' Property. If it isn't, then here we simply record the fact that\n"
+ + "we have encountered this non-containment relationship, and move on to the next Property",
+
+ "Inspecting another property to determine how to access its value, as we saw before");
+
+ // TODO deal with nullable
+
+ buf.append("Property ").append(p.getName()).append(": ").append(" - ");
+
+ if (dataObject.isSet(p)) {
+ if (p.getType().isDataType()) {
+ if (p.isMany()) {
+ printSimpleValues(dataObject.getList(p));
+ } else {
+ printSimpleValue(dataObject.get(p));
+ }
+ } else {
+ if (p.isContainment()) {
+ incrementIndent();
+ if (p.isMany()) {
+ printDataObjects(dataObject.getList(p));
+ } else {
+ printDataObject(dataObject.getDataObject(p));
+ }
+ decrementIndent();
+ } else {
+ if (p.isMany()) {
+ printReferencedDataObjects(dataObject.getList(p));
+ } else {
+ printReferencedDataObject(dataObject.getDataObject(p));
+ }
+ }
+ }
+ } else {
+ buf.append(" is not set");
+ }
+
+ lineBreak();
+
+ }
+
+ private void printReferencedDataObject(DataObject dataObject) {
+
+ commentary(
+ COMMENTARY_FOR_INTERMEDIATE,
+ "We have encounted a non-containment reference to a DataObject, and so\n"
+ + "we know that this DataObject will be fully inspected when encountered by the\n"
+ + "traversal of the data graph's containment hierarchy.\n"
+ + "We therefore record the fact that this association has been encountered by\n"
+ + "establishing the path from the root object of the data graph to the referenced\n"
+ + "DataObject",
+
+ "Recording the fact that we have encountered another non-containment reference");
+
+ List path = new ArrayList();
+ DataObject current = dataObject;
+ while (current != null) {
+ Property containmentProperty = current.getContainmentProperty();
+ if(containmentProperty != null) {
+ if(containmentProperty.isMany()) {
+ List pValues = current.getContainer().getList(containmentProperty);
+ int index = pValues.indexOf(current)+1;
+ path.add("["+index+"]");
+ }
+ path.add("/"+current.getContainmentProperty().getName());
+ }
+ current = current.getContainer();
+ }
+ buf.append("reference to: ");
+ for (ListIterator i = path.listIterator(path.size()); i.hasPrevious();) {
+ buf.append(i.previous());
+ }
+ }
+
+ private void printReferencedDataObjects(List list) {
+
+ commentary(
+ COMMENTARY_FOR_NOVICE,
+ "Traversing a list of DataObjects which represent the values of a multi-valued non-containment Property");
+
+ indent();
+ buf.append('[');
+ for (Iterator i = list.iterator(); i.hasNext();) {
+ printReferencedDataObject((DataObject) i.next());
+ }
+ indent();
+ buf.append(']');
+ }
+
+ private void printDataObjects(List list) {
+
+ commentary(
+ COMMENTARY_FOR_NOVICE,
+ "Traversing a list of DataObjects which represent the values of a multi-valued containment Property");
+
+
+ lineBreak();
+ indent();
+ buf.append("[");
+ incrementIndent();
+ for (Iterator i = list.iterator(); i.hasNext();) {
+ printDataObject((DataObject) i.next());
+ }
+ decrementIndent();
+ indent();
+ buf.append(']');
+ }
+
+ private void printSimpleValue(Object object) {
+ buf.append(object);
+ }
+
+ private void printSimpleValues(List values) {
+ buf.append('[');
+ for (Iterator i = values.iterator(); i.hasNext();) {
+ printSimpleValue(i.next());
+ if (i.hasNext()) {
+ buf.append(',');
+ }
+ }
+ buf.append(']');
+
+ }
+
+ private void decrementIndent() {
+ indent -= indentIncrement;
+
+ }
+
+ private void incrementIndent() {
+ indent += indentIncrement;
+
+ }
+
+ private void indent() {
+ for (int i = 0; i < indent; i++) {
+ buf.append(' ');
+ }
+ }
+
+ private void lineBreak() {
+ buf.append('\n');
+ }
+
+ public StringBuffer getBuf() {
+ return buf;
+ }
+
+ public void setBuf(StringBuffer b) {
+ buf = b;
+ }
+
+ public HelperContext getScope() {
+ return scope;
+ }
+
+ public void setScope(HelperContext scope) {
+ this.scope = scope;
+ }
+
+}
diff --git a/sdo-java/branches/sdo-1.1.1-incubating/sample/src/main/java/org/apache/tuscany/samples/sdo/advanced/package.html b/sdo-java/branches/sdo-1.1.1-incubating/sample/src/main/java/org/apache/tuscany/samples/sdo/advanced/package.html
new file mode 100644
index 0000000000..4a375228f8
--- /dev/null
+++ b/sdo-java/branches/sdo-1.1.1-incubating/sample/src/main/java/org/apache/tuscany/samples/sdo/advanced/package.html
@@ -0,0 +1,31 @@
+<html>
+<!--
+ *
+ * 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.
+ * -->
+<head>
+ <title>Advanced SDO Samples</title>
+</head>
+<BODY>
+<h1>Advanced Service Data Object (SDO) Sample Programs</h1>
+
+<h3>Running the Samples</h3> See <A HREF="../../../../../../index.html"
+target="_top">the main overview</A> for instructions on how to run these
+samples.
+</BODY>
+</HTML>