diff options
author | lresende <lresende@13f79535-47bb-0310-9956-ffa450edef68> | 2009-11-10 19:19:55 +0000 |
---|---|---|
committer | lresende <lresende@13f79535-47bb-0310-9956-ffa450edef68> | 2009-11-10 19:19:55 +0000 |
commit | 2a444004802173fa97afbc389fc4a6600b6d3f88 (patch) | |
tree | b175a25dd02206218987ab4bc730ad8e77b7756a /sdo-java/branches/sdo-1.1-incubating/sample/src/main/java/org/apache/tuscany/samples/sdo/advanced/PrintDataGraph.java | |
parent | c993ba575bdd1530b7bbc0c6a19c32e66fce4b89 (diff) |
moving SDO branches
git-svn-id: http://svn.us.apache.org/repos/asf/tuscany@834614 13f79535-47bb-0310-9956-ffa450edef68
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.java | 498 |
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; + } + +} |