summaryrefslogtreecommitdiffstats
path: root/sdo-java/branches/sdo-1.1-incubating/sample/src/main/java/org/apache/tuscany/samples/sdo/advanced/PrintDataGraph.java
diff options
context:
space:
mode:
Diffstat (limited to 'sdo-java/branches/sdo-1.1-incubating/sample/src/main/java/org/apache/tuscany/samples/sdo/advanced/PrintDataGraph.java')
-rw-r--r--sdo-java/branches/sdo-1.1-incubating/sample/src/main/java/org/apache/tuscany/samples/sdo/advanced/PrintDataGraph.java498
1 files changed, 498 insertions, 0 deletions
diff --git a/sdo-java/branches/sdo-1.1-incubating/sample/src/main/java/org/apache/tuscany/samples/sdo/advanced/PrintDataGraph.java b/sdo-java/branches/sdo-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-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;
+ }
+
+}