incubator-isis-commits mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From danhayw...@apache.org
Subject svn commit: r1085690 [3/11] - in /incubator/isis/trunk: ./ applib/ core/ core/commons/ core/commons/src/main/java/org/apache/isis/core/commons/authentication/ core/commons/src/site/ core/metamodel/ core/metamodel/src/main/java/org/apache/isis/core/meta...
Date Sat, 26 Mar 2011 11:07:17 GMT
Added: incubator/isis/trunk/core/runtime/src/main/java/org/apache/isis/core/runtime/snapshot/XmlSnapshot.java
URL: http://svn.apache.org/viewvc/incubator/isis/trunk/core/runtime/src/main/java/org/apache/isis/core/runtime/snapshot/XmlSnapshot.java?rev=1085690&view=auto
==============================================================================
--- incubator/isis/trunk/core/runtime/src/main/java/org/apache/isis/core/runtime/snapshot/XmlSnapshot.java
(added)
+++ incubator/isis/trunk/core/runtime/src/main/java/org/apache/isis/core/runtime/snapshot/XmlSnapshot.java
Sat Mar 26 11:07:04 2011
@@ -0,0 +1,741 @@
+/*
+ *  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.isis.core.runtime.snapshot;
+
+import java.util.Collections;
+import java.util.Enumeration;
+import java.util.List;
+import java.util.StringTokenizer;
+import java.util.Vector;
+
+import javax.xml.parsers.DocumentBuilder;
+import javax.xml.parsers.DocumentBuilderFactory;
+import javax.xml.parsers.ParserConfigurationException;
+
+import org.apache.isis.applib.snapshot.SnapshottableWithInclusions;
+import org.apache.isis.core.commons.exceptions.IsisException;
+import org.apache.isis.core.metamodel.adapter.ObjectAdapter;
+import org.apache.isis.core.metamodel.adapter.oid.Oid;
+import org.apache.isis.core.metamodel.adapter.oid.stringable.directly.DirectlyStringableOid;
+import org.apache.isis.core.metamodel.facetapi.FacetUtil;
+import org.apache.isis.core.metamodel.facets.collections.modify.CollectionFacet;
+import org.apache.isis.core.metamodel.facets.object.encodeable.EncodableFacet;
+import org.apache.isis.core.metamodel.facets.object.parseable.ParseableFacet;
+import org.apache.isis.core.metamodel.facets.object.value.ValueFacet;
+import org.apache.isis.core.metamodel.spec.ObjectSpecification;
+import org.apache.isis.core.metamodel.spec.ObjectSpecificationException;
+import org.apache.isis.core.metamodel.spec.feature.ObjectAssociation;
+import org.apache.isis.core.metamodel.spec.feature.OneToManyAssociation;
+import org.apache.isis.core.metamodel.spec.feature.OneToOneAssociation;
+import org.apache.log4j.Logger;
+import org.w3c.dom.Document;
+import org.w3c.dom.Element;
+import org.w3c.dom.Node;
+import org.w3c.dom.NodeList;
+
+
+/**
+ * Traverses object graph from specified root, so that an XML representation of the graph
can be returned.
+ *
+ * <p>
+ * Initially designed to allow snapshots to be easily created.
+ * 
+ * <p>
+ * Typical use:
+ * <pre>
+ * XmlSnapshot snapshot = new XmlSnapshot(customer); // where customer is a reference to
an ObjectAdapter
+ * Element customerAsXml = snapshot.toXml(); // returns customer's fields, titles of simple
references, number of items in collections
+ * snapshot.include(&quot;placeOfBirth&quot;); // navigates to another object represented
by simple reference &quot;placeOfBirth&quot;
+ * snapshot.include(&quot;orders/product&quot;); // navigates to all <tt>Order</tt>s
of <tt>Customer</tt>, and from them for their <tt>Product</tt>s 
+ * </pre>
+ */
+public class XmlSnapshot {
+
+    private static final Logger LOG = Logger.getLogger(XmlSnapshot.class);
+
+    private final IsisMetaModel isisMetaModel;
+
+    private final Place rootPlace;
+
+    private final XmlSchema schema;
+
+    /**
+     * the suggested location for the schema (xsi:schemaLocation attribute)
+     */
+    private String schemaLocationFileName;
+    private boolean topLevelElementWritten = false;
+
+    private final Document xmlDocument;
+
+    /**
+     * root element of {@link #xmlDocument}
+     */
+    private Element xmlElement;
+    private final Document xsdDocument;
+    /**
+     * root element of {@link #xsdDocument}
+     */
+    private final Element xsdElement;
+
+    private final XsMetaModel xsMeta;
+
+    /**
+     * Start a snapshot at the root object, using own namespace manager.
+     */
+    public XmlSnapshot(final ObjectAdapter rootAdapter) {
+        this(rootAdapter, new XmlSchema());
+    }
+
+    /**
+     * Start a snapshot at the root object, using supplied namespace manager.
+     */
+    public XmlSnapshot(final ObjectAdapter rootAdapter, final XmlSchema schema) {
+
+        LOG.debug(".ctor(" + log("rootObj", rootAdapter) + andlog("schema", schema) + andlog("addOids",
"" + true) + ")");
+
+        this.isisMetaModel = new IsisMetaModel();
+        this.xsMeta = new XsMetaModel();
+
+        this.schema = schema;
+
+        final DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance();
+        dbf.setNamespaceAware(true);
+        DocumentBuilder db;
+        try {
+            db = dbf.newDocumentBuilder();
+            this.xmlDocument = db.newDocument();
+            this.xsdDocument = db.newDocument();
+
+            xsdElement = xsMeta.createXsSchemaElement(xsdDocument);
+
+            this.rootPlace = appendXml(rootAdapter);
+
+        } catch (final ParserConfigurationException e) {
+            LOG.error("unable to build snapshot", e);
+            throw new IsisException(e);
+        }
+
+		for(String path: getPathsFor(rootAdapter.getObject())) {
+			include(path);
+		}
+
+    }
+
+	private List<String> getPathsFor(Object object) {
+		if (!(object instanceof SnapshottableWithInclusions)) {
+			return Collections.emptyList();
+		}
+		List<String> paths = 
+			((SnapshottableWithInclusions) object).snapshotInclusions();
+		if (paths == null) {
+			return Collections.emptyList();
+		}
+		return paths;
+	}
+	
+
+    private String andlog(final String label, final ObjectAdapter object) {
+        return ", " + log(label, object);
+    }
+
+    private String andlog(final String label, final Object object) {
+        return ", " + log(label, object);
+    }
+
+    /**
+     * Creates an Element representing this object, and appends it as the root element of
the Document.
+     * 
+     * The Document must not yet have a root element Additionally, the supplied schemaManager
must be
+     * populated with any application-level namespaces referenced in the document that the
parentElement
+     * resides within. (Normally this is achieved simply by using appendXml passing in a
new schemaManager -
+     * see {@link #toXml()}or {@link XmlSnapshot}).
+     */
+    private Place appendXml(final ObjectAdapter object) {
+
+        LOG.debug("appendXml(" + log("obj", object) + "')");
+
+        final String fullyQualifiedClassName = object.getSpecification().getFullIdentifier();
+
+        schema.setUri(fullyQualifiedClassName); // derive
+        // URI
+        // from
+        // fully
+        // qualified
+        // name
+
+        final Place place = objectToElement(object);
+
+        final Element element = place.getXmlElement();
+        final Element xsElementElement = place.getXsdElement();
+
+        LOG.debug("appendXml(NO): add as element to XML doc");
+        getXmlDocument().appendChild(element);
+
+        LOG.debug("appendXml(NO): add as xs:element to xs:schema of the XSD document");
+        getXsdElement().appendChild(xsElementElement);
+
+        LOG.debug("appendXml(NO): set target name in XSD, derived from FQCN of obj");
+        schema.setTargetNamespace(getXsdDocument(), fullyQualifiedClassName);
+
+        LOG.debug("appendXml(NO): set schema location file name to XSD, derived from FQCN
of obj");
+        final String schemaLocationFileName = fullyQualifiedClassName + ".xsd";
+        schema.assignSchema(getXmlDocument(), fullyQualifiedClassName, schemaLocationFileName);
+
+        LOG.debug("appendXml(NO): copy into snapshot obj");
+        setXmlElement(element);
+        setSchemaLocationFileName(schemaLocationFileName);
+
+        return place;
+    }
+
+    /**
+     * Creates an Element representing this object, and appends it to the supplied parentElement,
provided
+     * that an element for the object is not already appended.
+     * 
+     * The method uses the OID to determine if an object's element is already present. If
the object is not
+     * yet persistent, then the hashCode is used instead.
+     * 
+     * The parentElement must have an owner document, and should define the nof namespace.
Additionally, the
+     * supplied schemaManager must be populated with any application-level namespaces referenced
in the
+     * document that the parentElement resides within. (Normally this is achieved simply
by using appendXml
+     * passing in a rootElement and a new schemaManager - see {@link #toXml()}or {@link XmlSnapshot}).
+     */
+    private Element appendXml(final Place parentPlace, final ObjectAdapter childObject) {
+
+        LOG.debug("appendXml(" + log("parentPlace", parentPlace) + andlog("childObj", childObject)
+ ")");
+
+        final Element parentElement = parentPlace.getXmlElement();
+        final Element parentXsElement = parentPlace.getXsdElement();
+
+        if (parentElement.getOwnerDocument() != getXmlDocument()) {
+            throw new IllegalArgumentException("parent XML Element must have snapshot's XML
document as its owner");
+        }
+
+        LOG.debug("appendXml(Pl, NO): invoking objectToElement() for " + log("childObj",
childObject));
+        final Place childPlace = objectToElement(childObject);
+        Element childElement = childPlace.getXmlElement();
+        final Element childXsElement = childPlace.getXsdElement();
+
+        LOG.debug("appendXml(Pl, NO): invoking mergeTree of parent with child");
+        childElement = mergeTree(parentElement, childElement);
+
+        LOG.debug("appendXml(Pl, NO): adding XS Element to schema if required");
+        schema.addXsElementIfNotPresent(parentXsElement, childXsElement);
+
+        return childElement;
+    }
+
+    private boolean appendXmlThenIncludeRemaining(
+            final Place parentPlace,
+            final ObjectAdapter referencedObject,
+            final Vector fieldNames,
+            final String annotation) {
+
+        LOG.debug("appendXmlThenIncludeRemaining(: " + log("parentPlace", parentPlace)
+                + andlog("referencedObj", referencedObject) + andlog("fieldNames", fieldNames)
+ andlog("annotation", annotation)
+                + ")");
+
+        LOG.debug("appendXmlThenIncludeRemaining(..): invoking appendXml(parentPlace, referencedObject)");
+
+        final Element referencedElement = appendXml(parentPlace, referencedObject);
+        final Place referencedPlace = new Place(referencedObject, referencedElement);
+
+        final boolean includedField = includeField(referencedPlace, fieldNames, annotation);
+
+        LOG.debug("appendXmlThenIncludeRemaining(..): invoked includeField(referencedPlace,
fieldNames)"
+                + andlog("returned", "" + includedField));
+
+        return includedField;
+    }
+
+    private Vector elementsUnder(final Element parentElement, final String localName) {
+        final Vector v = new Vector();
+        final NodeList existingNodes = parentElement.getChildNodes();
+        for (int i = 0; i < existingNodes.getLength(); i++) {
+            final Node node = existingNodes.item(i);
+            if (!(node instanceof Element)) {
+                continue;
+            }
+            final Element element = (Element) node;
+            if (localName.equals("*") || element.getLocalName().equals(localName)) {
+                v.addElement(element);
+            }
+        }
+        return v;
+    }
+
+    public ObjectAdapter getObject() {
+        return rootPlace.getObject();
+    }
+
+    public XmlSchema getSchema() {
+        return schema;
+    }
+
+    /**
+     * The name of the <code>xsi:schemaLocation</code> in the XML document.
+     * 
+     * Taken from the <code>fullyQualifiedClassName</code> (which also is used
as the basis for the
+     * <code>targetNamespace</code>.
+     * 
+     * Populated in {@link #appendXml(ObjectAdapter)}.
+     */
+    public String getSchemaLocationFileName() {
+        return schemaLocationFileName;
+    }
+
+    public Document getXmlDocument() {
+        return xmlDocument;
+    }
+
+    /**
+     * The root element of {@link #getXmlDocument()}. Returns <code>null</code>
until the snapshot has
+     * actually been built.
+     */
+    public Element getXmlElement() {
+        return xmlElement;
+    }
+
+    public Document getXsdDocument() {
+        return xsdDocument;
+    }
+
+    /**
+     * The root element of {@link #getXsdDocument()}. Returns <code>null</code>
until the snapshot has
+     * actually been built.
+     */
+    public Element getXsdElement() {
+        return xsdElement;
+    }
+
+    public void include(final String path) {
+        include(path, null);
+    }
+
+    public void include(final String path, final String annotation) {
+
+        // tokenize into successive fields
+        final Vector fieldNames = new Vector();
+        for (final StringTokenizer tok = new StringTokenizer(path, "/"); tok.hasMoreTokens();)
{
+            final String token = tok.nextToken();
+
+            LOG.debug("include(..): " + log("token", token));
+            fieldNames.addElement(token);
+        }
+
+        LOG.debug("include(..): " + log("fieldNames", fieldNames));
+
+        // navigate first field, from the root.
+        LOG.debug("include(..): invoking includeField");
+        includeField(rootPlace, fieldNames, annotation);
+    }
+
+    /**
+     * @return true if able to navigate the complete vector of field names successfully;
false if a field
+     *         could not be located or it turned out to be a value.
+     */
+    private boolean includeField(final Place place, final Vector fieldNames, final String
annotation) {
+
+        LOG.debug("includeField(: " + log("place", place) + andlog("fieldNames", fieldNames)
+ andlog("annotation", annotation)
+                + ")");
+
+        final ObjectAdapter object = place.getObject();
+        final Element xmlElement = place.getXmlElement();
+
+        // we use a copy of the path so that we can safely traverse collections
+        // without side-effects
+        final Vector originalNames = fieldNames;
+        final Vector names = new Vector();
+        for (final java.util.Enumeration e = originalNames.elements(); e.hasMoreElements();)
{
+            names.addElement(e.nextElement());
+        }
+
+        // see if we have any fields to process
+        if (names.size() == 0) {
+            return true;
+        }
+
+        // take the first field name from the list, and remove
+        final String fieldName = (String) names.elementAt(0);
+        names.removeElementAt(0);
+
+        LOG.debug("includeField(Pl, Vec, Str):" + log("processing field", fieldName) + andlog("left",
"" + names.size()));
+
+        // locate the field in the object's class
+        final ObjectSpecification nos = object.getSpecification();
+        ObjectAssociation field = null;
+        try {
+            // HACK: really want a ObjectSpecification.hasField method to
+            // check first.
+            field = nos.getAssociation(fieldName);
+        } catch (final ObjectSpecificationException ex) {
+            LOG.info("includeField(Pl, Vec, Str): could not locate field, skipping");
+            return false;
+        }
+
+        // locate the corresponding XML element
+        // (the corresponding XSD element will later be attached to xmlElement
+        // as its userData)
+        LOG.debug("includeField(Pl, Vec, Str): locating corresponding XML element");
+        final Vector xmlFieldElements = elementsUnder(xmlElement, field.getId());
+        if (xmlFieldElements.size() != 1) {
+            LOG.info("includeField(Pl, Vec, Str): could not locate " + log("field", field.getId())
+                    + andlog("xmlFieldElements.size", "" + xmlFieldElements.size()));
+            return false;
+        }
+        final Element xmlFieldElement = (Element) xmlFieldElements.elementAt(0);
+
+        if (names.size() == 0 && annotation != null) {
+            // nothing left in the path, so we will apply the annotation now
+            isisMetaModel.setAnnotationAttribute(xmlFieldElement, annotation);
+        }
+
+        final Place fieldPlace = new Place(object, xmlFieldElement);
+
+        if (field instanceof OneToOneAssociation) {
+            if (field.getSpecification().getAssociations().size() == 0) {
+                LOG.debug("includeField(Pl, Vec, Str): field is value; done");
+                return false;
+            }
+
+            LOG.debug("includeField(Pl, Vec, Str): field is 1->1");
+
+            final OneToOneAssociation oneToOneAssociation = ((OneToOneAssociation) field);
+            final ObjectAdapter referencedObject = oneToOneAssociation.get(fieldPlace.getObject());
+
+            if (referencedObject == null) {
+                return true; // not a failure if the reference was null
+            }
+
+            final boolean appendedXml = appendXmlThenIncludeRemaining(fieldPlace, referencedObject,
names,
+                    annotation);
+            LOG.debug("includeField(Pl, Vec, Str): 1->1: invoked appendXmlThenIncludeRemaining
for "
+                    + log("referencedObj", referencedObject) + andlog("returned", "" + appendedXml));
+
+            return appendedXml;
+
+        } else if (field instanceof OneToManyAssociation) {
+            LOG.debug("includeField(Pl, Vec, Str): field is 1->M");
+
+            final OneToManyAssociation oneToManyAssociation = (OneToManyAssociation) field;
+            final ObjectAdapter collection = oneToManyAssociation.get(fieldPlace.getObject());
+            final CollectionFacet facet = collection.getSpecification().getFacet(CollectionFacet.class);
+
+            LOG.debug("includeField(Pl, Vec, Str): 1->M: " + log("collection.size", ""
+ facet.size(collection)));
+            boolean allFieldsNavigated = true;
+            final Enumeration elements = facet.elements(collection);
+            while (elements.hasMoreElements()) {
+                final ObjectAdapter referencedObject = (ObjectAdapter) elements.nextElement();
+                final boolean appendedXml = appendXmlThenIncludeRemaining(fieldPlace, referencedObject,
names, annotation);
+                LOG.debug("includeField(Pl, Vec, Str): 1->M: + invoked appendXmlThenIncludeRemaining
for "
+                        + log("referencedObj", referencedObject) + andlog("returned", ""
+ appendedXml));
+                allFieldsNavigated = allFieldsNavigated && appendedXml;
+            }
+            LOG.debug("includeField(Pl, Vec, Str): " + log("returning", "" + allFieldsNavigated));
+            return allFieldsNavigated;
+        }
+
+        return false; // fall through, shouldn't get here but just in
+        // case.
+    }
+
+    private String log(final String label, final ObjectAdapter object) {
+        return log(label, (object == null ? "(null)" : object.titleString() + "[" + oidOrHashCode(object)
+ "]"));
+    }
+
+    private String log(final String label, final Object object) {
+        return (label == null ? "?" : label) + "='" + (object == null ? "(null)" : object.toString())
+ "'";
+    }
+
+    /**
+     * Merges the tree of Elements whose root is <code>childElement</code> underneath
the
+     * <code>parentElement</code>.
+     * 
+     * If the <code>parentElement</code> already has an element that matches
the <code>childElement</code>,
+     * then recursively attaches the grandchildren instead.
+     * 
+     * The element returned will be either the supplied <code>childElement</code>,
or an existing child
+     * element if one already existed under <code>parentElement</code>.
+     */
+    private Element mergeTree(final Element parentElement, final Element childElement) {
+
+        LOG.debug("mergeTree(" + log("parent", parentElement) + andlog("child", childElement));
+
+        final String childElementOid = isisMetaModel.getAttribute(childElement, "oid");
+
+        LOG.debug("mergeTree(El,El): " + log("childOid", childElementOid));
+        if (childElementOid != null) {
+
+            // before we add the child element, check to see if it is already
+            // there
+            LOG.debug("mergeTree(El,El): check if child already there");
+            final Vector existingChildElements = elementsUnder(parentElement, childElement.getLocalName());
+            for (final Enumeration childEnum = existingChildElements.elements(); childEnum.hasMoreElements();)
{
+                final Element possibleMatchingElement = (Element) childEnum.nextElement();
+
+                final String possibleMatchOid = isisMetaModel.getAttribute(possibleMatchingElement,
"oid");
+                if (possibleMatchOid == null || !possibleMatchOid.equals(childElementOid))
{
+                    continue;
+                }
+
+                LOG.debug("mergeTree(El,El): child already there; merging grandchildren");
+
+                // match: transfer the children of the child (grandchildren) to
+                // the
+                // already existing matching child
+                final Element existingChildElement = possibleMatchingElement;
+                final Vector grandchildrenElements = elementsUnder(childElement, "*");
+                for (final Enumeration grandchildEnum = grandchildrenElements.elements();
grandchildEnum.hasMoreElements();) {
+                    final Element grandchildElement = (Element) grandchildEnum.nextElement();
+                    childElement.removeChild(grandchildElement);
+
+                    LOG.debug("mergeTree(El,El): merging " + log("grandchild", grandchildElement));
+
+                    mergeTree(existingChildElement, grandchildElement);
+                }
+                return existingChildElement;
+            }
+        }
+
+        parentElement.appendChild(childElement);
+        return childElement;
+    }
+
+    Place objectToElement(final ObjectAdapter object) {
+
+        LOG.debug("objectToElement(" + log("object", object) + ")");
+
+        final ObjectSpecification nos = object.getSpecification();
+
+        LOG.debug("objectToElement(NO): create element and nof:title");
+        final Element element = schema.createElement(getXmlDocument(), nos.getShortIdentifier(),
nos.getFullIdentifier(), nos
+                .getSingularName(), nos.getPluralName());
+        isisMetaModel.appendNofTitle(element, object.titleString());
+
+        LOG.debug("objectToElement(NO): create XS element for NOF class");
+        final Element xsElement = schema.createXsElementForNofClass(getXsdDocument(), element,
topLevelElementWritten, FacetUtil
+                .getFacetsByType(nos));
+
+        // hack: every element in the XSD schema apart from first needs minimum cardinality
setting.
+        topLevelElementWritten = true;
+
+        final Place place = new Place(object, element);
+
+        isisMetaModel.setAttributesForClass(element, oidOrHashCode(object).toString());
+
+        final List<ObjectAssociation> fields = nos.getAssociations();
+        LOG.debug("objectToElement(NO): processing fields");
+        eachField: for (int i = 0; i < fields.size(); i++) {
+            final ObjectAssociation field = fields.get(i);
+            final String fieldName = field.getId();
+
+            LOG.debug("objectToElement(NO): " + log("field", fieldName));
+
+            // Skip field if we have seen the name already
+            // This is a workaround for getLastActivity(). This method exists
+            // in AbstractObjectAdapter, but is not (at some level) being picked
+            // up
+            // by the dot-net reflector as a property. On the other hand it does
+            // exist as a field in the meta model (ObjectSpecification).
+            //
+            // Now, to re-expose the lastactivity field for .Net, a
+            // deriveLastActivity()
+            // has been added to BusinessObject. This caused another field of
+            // the
+            // same name, ultimately breaking the XSD.
+            for (int j = 0; j < i; j++) {
+                if (fieldName.equals(fields.get(i).getName())) {
+                    LOG.debug("objectToElement(NO): " + log("field", fieldName) + " SKIPPED");
+                    continue eachField;
+                }
+            }
+
+            Element xmlFieldElement = getXmlDocument().createElementNS(schema.getUri(), //
scoped by namespace
+                    // of class of
+                    // containing object
+                    schema.getPrefix() + ":" + fieldName);
+
+            Element xsdFieldElement = null;
+
+            if (field.getSpecification().containsFacet(ValueFacet.class)) {
+                LOG.debug("objectToElement(NO): " + log("field", fieldName) + " is value");
+
+                final ObjectSpecification fieldNos = field.getSpecification();
+                // skip fields of type XmlValue
+                if (fieldNos == null) {
+                    continue eachField;
+                }
+                if (fieldNos.getFullIdentifier() != null && fieldNos.getFullIdentifier().endsWith("XmlValue"))
{
+                    continue eachField;
+                }
+
+                final OneToOneAssociation valueAssociation = ((OneToOneAssociation) field);
+                final Element xmlValueElement = xmlFieldElement; // more meaningful locally
scoped name
+
+                ObjectAdapter value;
+                try {
+                    value = valueAssociation.get(object);
+
+                    final ObjectSpecification valueNos = value.getSpecification();
+
+                    // XML
+                    isisMetaModel.setAttributesForValue(xmlValueElement, valueNos.getShortIdentifier());
+
+                    // return parsed string, else encoded string, else title.
+                    String valueStr;
+                    ParseableFacet parseableFacet = fieldNos.getFacet(ParseableFacet.class);
+                    EncodableFacet encodeableFacet = fieldNos.getFacet(EncodableFacet.class);
+                    if(parseableFacet != null) {
+                    	valueStr = parseableFacet.parseableTitle(value);
+                    } else if(encodeableFacet != null) {
+                    	valueStr = encodeableFacet.toEncodedString(value);
+                    } else {
+                    	valueStr = value.titleString();
+                    }
+                    
+					final boolean notEmpty = (valueStr.length() > 0);
+                    if (notEmpty) {
+                        xmlValueElement.appendChild(getXmlDocument().createTextNode(valueStr));
+                    } else {
+                        isisMetaModel.setIsEmptyAttribute(xmlValueElement, true);
+                    }
+
+                } catch (final Exception ex) {
+                    LOG.warn("objectToElement(NO): " + log("field", fieldName)
+                            + ": getField() threw exception - skipping XML generation");
+                }
+
+                // XSD
+                xsdFieldElement = schema.createXsElementForNofValue(xsElement, xmlValueElement,
FacetUtil
+                        .getFacetsByType(valueAssociation));
+
+            } else if (field instanceof OneToOneAssociation) {
+
+                LOG.debug("objectToElement(NO): " + log("field", fieldName) + " is OneToOneAssociation");
+
+                final OneToOneAssociation oneToOneAssociation = ((OneToOneAssociation) field);
+                final String fullyQualifiedClassName = nos.getFullIdentifier();
+                final Element xmlReferenceElement = xmlFieldElement; // more meaningful locally
scoped name
+
+                ObjectAdapter referencedObjectAdapter;
+
+                try {
+                    referencedObjectAdapter = oneToOneAssociation.get(object);
+
+                    // XML
+                    isisMetaModel.setAttributesForReference(xmlReferenceElement, schema.getPrefix(),
fullyQualifiedClassName);
+
+                    if (referencedObjectAdapter != null) {
+                        isisMetaModel.appendNofTitle(xmlReferenceElement, referencedObjectAdapter.titleString());
+                    } else {
+                        isisMetaModel.setIsEmptyAttribute(xmlReferenceElement, true);
+                    }
+
+                } catch (final Exception ex) {
+                    LOG.warn("objectToElement(NO): " + log("field", fieldName)
+                            + ": getAssociation() threw exception - skipping XML generation");
+                }
+
+                // XSD
+                xsdFieldElement = schema.createXsElementForNofReference(xsElement, xmlReferenceElement,
oneToOneAssociation
+                        .getSpecification().getFullIdentifier(), FacetUtil.getFacetsByType(oneToOneAssociation));
+
+            } else if (field instanceof OneToManyAssociation) {
+
+                LOG.debug("objectToElement(NO): " + log("field", fieldName) + " is OneToManyAssociation");
+
+                final OneToManyAssociation oneToManyAssociation = (OneToManyAssociation)
field;
+                final Element xmlCollectionElement = xmlFieldElement; // more meaningful
locally scoped name
+
+                ObjectAdapter collection;
+                try {
+                    collection = oneToManyAssociation.get(object);
+                    final ObjectSpecification referencedTypeNos = oneToManyAssociation.getSpecification();
+                    final String fullyQualifiedClassName = referencedTypeNos.getFullIdentifier();
+
+                    // XML
+                    isisMetaModel.setNofCollection(xmlCollectionElement, schema.getPrefix(),
fullyQualifiedClassName, collection);
+                } catch (final Exception ex) {
+                    LOG.warn("objectToElement(NO): " + log("field", fieldName)
+                            + ": get(obj) threw exception - skipping XML generation");
+                }
+
+                // XSD
+                xsdFieldElement = schema.createXsElementForNofCollection(xsElement, xmlCollectionElement,
oneToManyAssociation
+                        .getSpecification().getFullIdentifier(), FacetUtil.getFacetsByType(oneToManyAssociation));
+
+            } else {
+                LOG.info("objectToElement(NO): " + log("field", fieldName) + " is unknown
type; ignored");
+                continue;
+            }
+
+            if (xsdFieldElement != null) {
+                Place.setXsdElement(xmlFieldElement, xsdFieldElement);
+            }
+
+            // XML
+            LOG.debug("objectToElement(NO): invoking mergeTree for field");
+            xmlFieldElement = mergeTree(element, xmlFieldElement);
+
+            // XSD
+            if (xsdFieldElement != null) {
+                LOG.debug("objectToElement(NO): adding XS element for field to schema");
+                schema.addFieldXsElement(xsElement, xsdFieldElement);
+            }
+        }
+
+        return place;
+    }
+
+    private String oidOrHashCode(final ObjectAdapter object) {
+        final Oid oid = object.getOid();
+        /*
+         * if (oid == null) { return "" + object.hashCode(); }
+         */
+        if (oid instanceof DirectlyStringableOid) {
+			DirectlyStringableOid directlyStringableOid = (DirectlyStringableOid) oid;
+        	return directlyStringableOid.enString();
+        } else {
+        	return oid.toString();
+        }
+        /*
+         * InlineTransferableWriter itw = new InlineTransferableWriter(); oid.writeData(itw);
itw.close();
+         * return itw.toString();
+         */
+    }
+
+    /**
+     * @param schemaLocationFileName
+     *            The schemaLocationFileName to set.
+     */
+    private void setSchemaLocationFileName(final String schemaLocationFileName) {
+        this.schemaLocationFileName = schemaLocationFileName;
+    }
+
+    /**
+     * @param xmlElement
+     *            The xmlElement to set.
+     */
+    private void setXmlElement(final Element xmlElement) {
+        this.xmlElement = xmlElement;
+    }
+    
+}

Copied: incubator/isis/trunk/core/runtime/src/main/java/org/apache/isis/core/runtime/snapshot/XsMetaModel.java
(from r1083695, incubator/isis/trunk/runtimes/dflt/runtime/src/main/java/org/apache/isis/runtimes/dflt/runtime/snapshot/XsMetaModel.java)
URL: http://svn.apache.org/viewvc/incubator/isis/trunk/core/runtime/src/main/java/org/apache/isis/core/runtime/snapshot/XsMetaModel.java?p2=incubator/isis/trunk/core/runtime/src/main/java/org/apache/isis/core/runtime/snapshot/XsMetaModel.java&p1=incubator/isis/trunk/runtimes/dflt/runtime/src/main/java/org/apache/isis/runtimes/dflt/runtime/snapshot/XsMetaModel.java&r1=1083695&r2=1085690&rev=1085690&view=diff
==============================================================================
--- incubator/isis/trunk/runtimes/dflt/runtime/src/main/java/org/apache/isis/runtimes/dflt/runtime/snapshot/XsMetaModel.java
(original)
+++ incubator/isis/trunk/core/runtime/src/main/java/org/apache/isis/core/runtime/snapshot/XsMetaModel.java
Sat Mar 26 11:07:04 2011
@@ -18,7 +18,7 @@
  */
 
 
-package org.apache.isis.runtimes.dflt.runtime.snapshot;
+package org.apache.isis.core.runtime.snapshot;
 
 import org.w3c.dom.Document;
 import org.w3c.dom.Element;

Modified: incubator/isis/trunk/core/runtime/src/site/apt/index.apt
URL: http://svn.apache.org/viewvc/incubator/isis/trunk/core/runtime/src/site/apt/index.apt?rev=1085690&r1=1085689&r2=1085690&view=diff
==============================================================================
--- incubator/isis/trunk/core/runtime/src/site/apt/index.apt (original)
+++ incubator/isis/trunk/core/runtime/src/site/apt/index.apt Sat Mar 26 11:07:04 2011
@@ -17,16 +17,10 @@
 
 
 
-ProgModel
+Runtime
 
- The <core progmodel> provides a set of reusable elements (implementations of
- the <<<FacetFactory>>> API) that can be reused to make up a programming
model.
- 
- Most of those within <this> module are in fact used in the
- default programming model, defined by the 
- {{{../../defaults/progmodel/index.html}default progmodel}} module.  They are
- defined within core, however, to allow custom programming models (perhaps
- extending or trimming back the default programming model) to be defined.
+ The <core runtime> module defines a set of APIs common across
+ all runtime implementations.
  
 Documentation
 

Modified: incubator/isis/trunk/core/runtime/src/site/site.xml
URL: http://svn.apache.org/viewvc/incubator/isis/trunk/core/runtime/src/site/site.xml?rev=1085690&r1=1085689&r2=1085690&view=diff
==============================================================================
--- incubator/isis/trunk/core/runtime/src/site/site.xml (original)
+++ incubator/isis/trunk/core/runtime/src/site/site.xml Sat Mar 26 11:07:04 2011
@@ -3,10 +3,10 @@
 
 	<body>
 		<breadcrumbs>
-			<item name="Profile Store" href="index.html"/>
+			<item name="Runtime" href="index.html"/>
 		</breadcrumbs>
 
-		<menu name="ProfileStore">
+		<menu name="Runtime">
 			<item name="About" href="index.html" />
             <item name="Jottings" href="jottings.html" />
 		</menu>
@@ -14,9 +14,10 @@
         <menu name="Core Modules">
             <item name="Core Test Support" href="../testsupport/index.html" />
             <item name="Core Commons" href="../commons/index.html" />
-            <item name="Core MetaModel" href="../metamodel/index.html" />
-            <item name="Core ProgModel" href="../progmodel/index.html" />
-            <item name="Core Profilestore" href="../profilestore/index.html" />
+            <item name="Core Metamodel" href="../metamodel/index.html" />
+            <item name="Core Progmodel" href="../progmodel/index.html" />
+            <item name="Core Runtime" href="../runtime/index.html" />
+            <item name="Core Webapp" href="../webapp/index.html" />
         </menu>
         
 		<menu name="Maven Reports" ref="reports"/>



Mime
View raw message