Package org.apache.tuscany.samples.sdo.advanced

Source Code of org.apache.tuscany.samples.sdo.advanced.PrintDataGraph

/**
*
*  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 recurse through the containment hierarchy of the\n"
              + "data graph in a depth first fashion, and create a text representaation 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 retunes 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 recurse 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 it's 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;
  }

}
TOP

Related Classes of org.apache.tuscany.samples.sdo.advanced.PrintDataGraph

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.