You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@isis.apache.org by da...@apache.org on 2013/11/18 17:43:39 UTC

git commit: ISIS-592: XmlSnapshotService

Updated Branches:
  refs/heads/master 62c91ddae -> fc773898e


ISIS-592: XmlSnapshotService

added to applib; core XmlSnapshot refactored to implement.


Project: http://git-wip-us.apache.org/repos/asf/isis/repo
Commit: http://git-wip-us.apache.org/repos/asf/isis/commit/fc773898
Tree: http://git-wip-us.apache.org/repos/asf/isis/tree/fc773898
Diff: http://git-wip-us.apache.org/repos/asf/isis/diff/fc773898

Branch: refs/heads/master
Commit: fc773898e7e9056e114e7b9c817a408b1b339956
Parents: 62c91dd
Author: Dan Haywood <da...@apache.org>
Authored: Mon Nov 18 16:43:23 2013 +0000
Committer: Dan Haywood <da...@apache.org>
Committed: Mon Nov 18 16:43:23 2013 +0000

----------------------------------------------------------------------
 .../persistence/FrameworkSynchronizer.java      |   5 +
 .../xmlsnapshot/XmlSnapshotService.java         |  95 +++++++++++++
 .../xmlsnapshot/XmlSnapshotServiceAbstract.java | 136 +++++++++++++++++++
 .../isis/applib/snapshot/Snapshottable.java     |  11 +-
 .../XmlSnapshotServiceAbstractTest.java         |  90 ++++++++++++
 .../isis/core/runtime/snapshot/IsisSchema.java  |  24 ++--
 .../isis/core/runtime/snapshot/XmlSchema.java   | 108 +++++++--------
 .../isis/core/runtime/snapshot/XmlSnapshot.java | 126 +++++++++++++----
 .../isis/core/runtime/snapshot/XsMetaModel.java |  38 +++---
 ...shingServiceWithDefaultPayloadFactories.java |   8 +-
 .../runtime/snapshot/XmlSnapshotBuilder.java    |   9 +-
 .../snapshot/XmlSnapshotServiceDefault.java     |  87 ++++++++++++
 .../dom/src/main/java/dom/todo/ToDoItem.java    |  13 ++
 .../src/main/webapp/WEB-INF/isis.properties     |   1 +
 .../src/main/webapp/WEB-INF/isis.properties     |   1 +
 15 files changed, 631 insertions(+), 121 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/isis/blob/fc773898/component/objectstore/jdo/jdo-datanucleus/src/main/java/org/apache/isis/objectstore/jdo/datanucleus/persistence/FrameworkSynchronizer.java
----------------------------------------------------------------------
diff --git a/component/objectstore/jdo/jdo-datanucleus/src/main/java/org/apache/isis/objectstore/jdo/datanucleus/persistence/FrameworkSynchronizer.java b/component/objectstore/jdo/jdo-datanucleus/src/main/java/org/apache/isis/objectstore/jdo/datanucleus/persistence/FrameworkSynchronizer.java
index 5ba8ba9..f675ed8 100644
--- a/component/objectstore/jdo/jdo-datanucleus/src/main/java/org/apache/isis/objectstore/jdo/datanucleus/persistence/FrameworkSynchronizer.java
+++ b/component/objectstore/jdo/jdo-datanucleus/src/main/java/org/apache/isis/objectstore/jdo/datanucleus/persistence/FrameworkSynchronizer.java
@@ -70,6 +70,11 @@ public class FrameworkSynchronizer {
             @Override
             public void run() {
                 final PersistenceCapable pc = pojo;
+                
+                // need to do eagerly, because (if a viewModel then) a
+                // viewModel's #viewModelMemento might need to use services 
+                getPersistenceSession().getServicesInjector().injectServicesInto(pojo);
+                
                 final Version datastoreVersion = getVersionIfAny(pc);
                 
                 final RootOid originalOid ;

http://git-wip-us.apache.org/repos/asf/isis/blob/fc773898/core/applib/src/main/java/org/apache/isis/applib/services/xmlsnapshot/XmlSnapshotService.java
----------------------------------------------------------------------
diff --git a/core/applib/src/main/java/org/apache/isis/applib/services/xmlsnapshot/XmlSnapshotService.java b/core/applib/src/main/java/org/apache/isis/applib/services/xmlsnapshot/XmlSnapshotService.java
new file mode 100644
index 0000000..9e26871
--- /dev/null
+++ b/core/applib/src/main/java/org/apache/isis/applib/services/xmlsnapshot/XmlSnapshotService.java
@@ -0,0 +1,95 @@
+/**
+ *  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.applib.services.xmlsnapshot;
+
+import org.w3c.dom.Document;
+import org.w3c.dom.Element;
+
+import org.apache.isis.applib.annotation.Programmatic;
+
+public interface XmlSnapshotService {
+
+    public interface Snapshot {
+        public Document getXmlDocument();
+        public Document getXsdDocument();
+        
+        public String getXmlDocumentAsString();    
+        public String getXsdDocumentAsString();    
+    }
+
+    public interface Builder {
+        public void includePath(final String path);
+        public void includePathAndAnnotation(final String path, final String annotation);
+    }
+    
+    public static class Exception extends RuntimeException {
+
+        private static final long serialVersionUID = 1L;
+
+        public Exception() {
+            super();
+        }
+
+        public Exception(String message, Throwable cause, boolean enableSuppression, boolean writableStackTrace) {
+            super(message, cause, enableSuppression, writableStackTrace);
+        }
+
+        public Exception(String message, Throwable cause) {
+            super(message, cause);
+        }
+
+        public Exception(String message) {
+            super(message);
+        }
+
+        public Exception(Throwable cause) {
+            super(cause);
+        }
+    }
+
+    @Programmatic
+    public XmlSnapshotService.Snapshot snapshotFor(final Object domainObject);
+
+    @Programmatic
+    public XmlSnapshotService.Builder builderFor(final Object domainObject);
+
+    /**
+     * Convenience to convert xml string (eg as obtained by {@link Snapshot#getXmlDocumentAsString()} or
+     * {@link Snapshot#getXsdDocumentAsString()}) back into a {@link Document W3C Document}.
+     */
+    @Programmatic
+    public Document asDocument(String xmlStr);
+
+    /**
+     * Convenience method to extract value of an XML element, based on its type.
+     */
+    @Programmatic
+    public <T> T getChildElementValue(final Element el, final String tagname, final Class<T> expectedCls);
+
+    /**
+     * Convenience method to walk XML document.
+     */
+    @Programmatic
+    public Element getChildElement(final Element el, final String tagname);
+    
+    /**
+     * Convenience method to obtain value of child text node.
+     */
+    @Programmatic
+    public String getChildTextValue(final Element el);
+
+}

http://git-wip-us.apache.org/repos/asf/isis/blob/fc773898/core/applib/src/main/java/org/apache/isis/applib/services/xmlsnapshot/XmlSnapshotServiceAbstract.java
----------------------------------------------------------------------
diff --git a/core/applib/src/main/java/org/apache/isis/applib/services/xmlsnapshot/XmlSnapshotServiceAbstract.java b/core/applib/src/main/java/org/apache/isis/applib/services/xmlsnapshot/XmlSnapshotServiceAbstract.java
new file mode 100644
index 0000000..4f3a5f8
--- /dev/null
+++ b/core/applib/src/main/java/org/apache/isis/applib/services/xmlsnapshot/XmlSnapshotServiceAbstract.java
@@ -0,0 +1,136 @@
+/**
+ *  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.applib.services.xmlsnapshot;
+
+import java.io.StringReader;
+import java.math.BigDecimal;
+import java.math.BigInteger;
+
+import javax.xml.transform.OutputKeys;
+import javax.xml.transform.Transformer;
+import javax.xml.transform.TransformerException;
+import javax.xml.transform.TransformerFactory;
+import javax.xml.transform.dom.DOMResult;
+import javax.xml.transform.stream.StreamSource;
+
+import org.joda.time.format.DateTimeFormat;
+import org.joda.time.format.DateTimeFormatter;
+import org.w3c.dom.Document;
+import org.w3c.dom.Element;
+import org.w3c.dom.Node;
+import org.w3c.dom.NodeList;
+import org.w3c.dom.Text;
+
+public abstract class XmlSnapshotServiceAbstract implements XmlSnapshotService {
+
+    @Override
+    public Document asDocument(String xmlStr) {
+        try {
+            final StringReader reader = new StringReader(xmlStr);
+            final StreamSource streamSource = new StreamSource(reader);
+            final DOMResult result = new DOMResult();
+            final TransformerFactory tf = TransformerFactory.newInstance();
+            final Transformer transformer = tf.newTransformer();
+            transformer.setOutputProperty(OutputKeys.OMIT_XML_DECLARATION, "no");
+            transformer.setOutputProperty(OutputKeys.METHOD, "xml");
+            transformer.setOutputProperty(OutputKeys.INDENT, "yes");
+            transformer.setOutputProperty(OutputKeys.ENCODING, "UTF-8");
+            transformer.setOutputProperty("{http://xml.apache.org/xslt}indent-amount", "2");
+            transformer.transform(streamSource, result);
+            
+            final Node node = result.getNode();
+            return (Document) node;
+        } catch (TransformerException e) {
+            throw new XmlSnapshotService.Exception(e);
+        }
+    }
+    
+    @SuppressWarnings("unchecked")
+    public <T> T getChildElementValue(final Element el, final String tagname, final Class<T> expectedCls) {
+        final Element chldEl = getChildElement(el, tagname);
+        final String dataType = chldEl.getAttribute("isis:datatype");
+        if(dataType == null) {
+            throw new IllegalArgumentException("unable to locate " + tagname + "/@datatype attribute");
+        }
+        if("isis:String".equals(dataType)) {
+            return (T)getChildTextValue(chldEl);
+        }
+        if("isis:LocalDate".equals(dataType)) {
+            final String str = getChildTextValue(chldEl);
+            final DateTimeFormatter forPattern = DateTimeFormat.forPattern("dd-MMM-yyyy");
+            return (T)forPattern.parseLocalDate(str);
+        }
+        if("isis:Byte".equals(dataType)) {
+            final String str = getChildTextValue(chldEl);
+            return (T)new Byte(str);
+        }
+        if("isis:Short".equals(dataType)) {
+            final String str = getChildTextValue(chldEl);
+            return (T)new Short(str);
+        }
+        if("isis:Integer".equals(dataType)) {
+            final String str = getChildTextValue(chldEl);
+            return (T)new Integer(str);
+        }
+        if("isis:Long".equals(dataType)) {
+            final String str = getChildTextValue(chldEl);
+            return (T)new Long(str);
+        }
+        if("isis:Float".equals(dataType)) {
+            final String str = getChildTextValue(chldEl);
+            return (T)new Float(str);
+        }
+        if("isis:Double".equals(dataType)) {
+            final String str = getChildTextValue(chldEl);
+            return (T)new Double(str);
+        }
+        if("isis:BigDecimal".equals(dataType)) {
+            final String str = getChildTextValue(chldEl);
+            return (T) new BigDecimal(str);
+        }
+        if("isis:BigInteger".equals(dataType)) {
+            final String str = getChildTextValue(chldEl);
+            return (T) new BigInteger(str);
+        }
+        if("isis:Boolean".equals(dataType)) {
+            final String str = getChildTextValue(chldEl);
+            return (T) new Boolean(str);
+        }
+        throw new IllegalArgumentException(
+                "Datatype of '" + dataType + "' for element '" + tagname + "' not recognized");
+    }
+
+    public Element getChildElement(final Element el, final String tagname) {
+        NodeList elementsByTagName = el.getElementsByTagName(tagname);
+        final int length = elementsByTagName.getLength();
+        if(length != 1 || !(elementsByTagName.item(0) instanceof Element)) {
+            throw new IllegalArgumentException("unable to locate " + tagname + " element");
+        }
+        final Element item = (Element) elementsByTagName.item(0);
+        return item;
+    }
+    
+    public String getChildTextValue(final Element el) {
+        final NodeList childNodes = el.getChildNodes();
+        if(childNodes.getLength() !=1 || !(childNodes.item(0) instanceof Text)) {
+            throw new IllegalArgumentException("unable to locate app:reference/text() node");
+        }
+        final Text referenceText = (Text) childNodes.item(0);
+        return referenceText.getData();
+    }
+
+}

http://git-wip-us.apache.org/repos/asf/isis/blob/fc773898/core/applib/src/main/java/org/apache/isis/applib/snapshot/Snapshottable.java
----------------------------------------------------------------------
diff --git a/core/applib/src/main/java/org/apache/isis/applib/snapshot/Snapshottable.java b/core/applib/src/main/java/org/apache/isis/applib/snapshot/Snapshottable.java
index 2445bd4..06c7eb0 100644
--- a/core/applib/src/main/java/org/apache/isis/applib/snapshot/Snapshottable.java
+++ b/core/applib/src/main/java/org/apache/isis/applib/snapshot/Snapshottable.java
@@ -20,9 +20,16 @@
 package org.apache.isis.applib.snapshot;
 
 /**
- * Marker interface for domain objects that can be snapshot using
- * <xx>XmlSnapshot</tt>.
+ * Unused.
+ * 
+ * <p>
+ * Previously it was necessary for domain objects to implement this marker interface
+ * in order to be used with <tt>XmlSnapshot</tt>.  The new {@link XmlSnapshotService} lifts
+ * this restriction.
+ * 
+ * @deprecated 
  */
+@Deprecated
 public interface Snapshottable {
 
 }

http://git-wip-us.apache.org/repos/asf/isis/blob/fc773898/core/applib/src/test/java/org/apache/isis/applib/services/xmlsnapshot/XmlSnapshotServiceAbstractTest.java
----------------------------------------------------------------------
diff --git a/core/applib/src/test/java/org/apache/isis/applib/services/xmlsnapshot/XmlSnapshotServiceAbstractTest.java b/core/applib/src/test/java/org/apache/isis/applib/services/xmlsnapshot/XmlSnapshotServiceAbstractTest.java
new file mode 100644
index 0000000..d1561f1
--- /dev/null
+++ b/core/applib/src/test/java/org/apache/isis/applib/services/xmlsnapshot/XmlSnapshotServiceAbstractTest.java
@@ -0,0 +1,90 @@
+/**
+ *  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.applib.services.xmlsnapshot;
+
+import static org.hamcrest.CoreMatchers.is;
+import static org.junit.Assert.assertThat;
+
+import java.math.BigDecimal;
+import java.math.BigInteger;
+import java.net.URL;
+import java.nio.charset.Charset;
+
+import com.google.common.io.Resources;
+
+import org.joda.time.LocalDate;
+import org.junit.Before;
+import org.junit.Test;
+import org.w3c.dom.Document;
+import org.w3c.dom.Element;
+
+public class XmlSnapshotServiceAbstractTest {
+
+    private XmlSnapshotServiceAbstract xmlSnapshotService;
+    private String xmlStr;
+
+    @Before
+    public void setUp() throws Exception {
+        URL resource = Resources.getResource(XmlSnapshotServiceAbstractTest.class, "XmlSnapshotServiceAbstractTest.xml");
+        xmlStr = Resources.toString(resource, Charset.forName("UTF-8"));
+        
+        xmlSnapshotService = new XmlSnapshotServiceForUnitTesting();
+    }
+
+    @Test
+    public void test() {
+
+        Document xmlDoc = xmlSnapshotService.asDocument(xmlStr);
+        Element rootEl = xmlDoc.getDocumentElement();
+        
+        assertThat(
+                xmlSnapshotService.getChildElementValue(rootEl, "app:someString", String.class), is("OXF"));
+        assertThat(
+                xmlSnapshotService.getChildElementValue(rootEl, "app:someLocalDate", LocalDate.class), is(new LocalDate(2013,4,1)));
+        assertThat(
+                xmlSnapshotService.getChildElementValue(rootEl, "app:someBigDecimal", BigDecimal.class), is(new BigDecimal("123456789012345678901234567890.12345678")));
+        assertThat(
+                xmlSnapshotService.getChildElementValue(rootEl, "app:someBigInteger", BigInteger.class), is(new BigInteger("12345678901234567890123456789012345678")));
+        assertThat(
+                xmlSnapshotService.getChildElementValue(rootEl, "app:someInteger", Integer.class), is(new Integer(123456789)));
+        assertThat(
+                xmlSnapshotService.getChildElementValue(rootEl, "app:someLong", Long.class), is(new Long(1234567890123456789L)));
+        assertThat(
+                xmlSnapshotService.getChildElementValue(rootEl, "app:someShort", Short.class), is(new Short((short)12345)));
+        assertThat(
+                xmlSnapshotService.getChildElementValue(rootEl, "app:someByte", Byte.class), is(new Byte((byte)123)));
+        assertThat(
+                xmlSnapshotService.getChildElementValue(rootEl, "app:someBoolean", Boolean.class), is(Boolean.TRUE));
+        assertThat(
+                xmlSnapshotService.getChildElementValue(rootEl, "app:someBoolean2", Boolean.class), is(Boolean.FALSE));
+    }
+
+    
+    static class XmlSnapshotServiceForUnitTesting extends XmlSnapshotServiceAbstract {
+
+        @Override
+        public Snapshot snapshotFor(Object domainObject) {
+            throw new RuntimeException();
+        }
+
+        @Override
+        public Builder builderFor(Object domainObject) {
+            throw new RuntimeException();
+        }
+    }
+
+}

http://git-wip-us.apache.org/repos/asf/isis/blob/fc773898/core/metamodel/src/main/java/org/apache/isis/core/runtime/snapshot/IsisSchema.java
----------------------------------------------------------------------
diff --git a/core/metamodel/src/main/java/org/apache/isis/core/runtime/snapshot/IsisSchema.java b/core/metamodel/src/main/java/org/apache/isis/core/runtime/snapshot/IsisSchema.java
index ff4fbaa..5c4aa85 100644
--- a/core/metamodel/src/main/java/org/apache/isis/core/runtime/snapshot/IsisSchema.java
+++ b/core/metamodel/src/main/java/org/apache/isis/core/runtime/snapshot/IsisSchema.java
@@ -65,7 +65,7 @@ final class IsisSchema {
      * 
      * The NamespaceManager will not allow any namespace to use this prefix.
      */
-    public static final String NS_PREFIX = "nof";
+    public static final String NS_PREFIX = "isis";
     /**
      * URI representing the namespace of ObjectAdapter framework's metamodel.
      * 
@@ -85,7 +85,7 @@ final class IsisSchema {
     }
 
     /**
-     * Creates an element in the NOF namespace, appends to parent, and adds NOF
+     * Creates an element in the &quot;isis&quot; namespace, appends to parent, and adds &quot;isis&quot;
      * namespace to the root element if required.
      */
     Element appendElement(final Element parentElement, final String localName) {
@@ -96,10 +96,10 @@ final class IsisSchema {
     }
 
     /**
-     * Appends an <code>nof:title</code> element with the supplied title string
+     * Appends an <code>isis:title</code> element with the supplied title string
      * to the provided element.
      */
-    public void appendNofTitle(final Element element, final String titleStr) {
+    public void appendIsisTitle(final Element element, final String titleStr) {
         final Document doc = helper.docFor(element);
         final Element titleElement = appendElement(element, "title");
         titleElement.appendChild(doc.createTextNode(titleStr));
@@ -139,8 +139,8 @@ final class IsisSchema {
     }
 
     /**
-     * Adds <code>nof:feature=&quot;reference&quot;</code> attribute and
-     * <code>nof:type=&quote;...&quot;</code> for the supplied element.
+     * Adds <code>isis:feature=&quot;reference&quot;</code> attribute and
+     * <code>isis:type=&quote;...&quot;</code> for the supplied element.
      */
     void setAttributesForReference(final Element element, final String prefix, final String fullyQualifiedClassName) {
         setAttribute(element, "feature", FEATURE_REFERENCE);
@@ -148,8 +148,8 @@ final class IsisSchema {
     }
 
     /**
-     * Adds <code>nof:feature=&quot;value&quot;</code> attribute and
-     * <code>nof:datatype=&quote;...&quot;</code> for the supplied element.
+     * Adds <code>isis:feature=&quot;value&quot;</code> attribute and
+     * <code>isis:datatype=&quote;...&quot;</code> for the supplied element.
      */
     void setAttributesForValue(final Element element, final String datatypeName) {
         setAttribute(element, "feature", FEATURE_VALUE);
@@ -157,7 +157,7 @@ final class IsisSchema {
     }
 
     /**
-     * Adds an <code>nof:isEmpty</code> attribute for the supplied class to the
+     * Adds an <code>isis:isEmpty</code> attribute for the supplied class to the
      * supplied element.
      */
     void setIsEmptyAttribute(final Element element, final boolean isEmpty) {
@@ -165,9 +165,9 @@ final class IsisSchema {
     }
 
     /**
-     * Adds <code>nof:feature=&quot;collection&quot;</code> attribute, the
-     * <code>nof:type=&quote;...&quot;</code> and the
-     * <code>nof:size=&quote;...&quot;</code> for the supplied element.
+     * Adds <code>isis:feature=&quot;collection&quot;</code> attribute, the
+     * <code>isis:type=&quote;...&quot;</code> and the
+     * <code>isis:size=&quote;...&quot;</code> for the supplied element.
      * 
      * Additionally, if the <code>addOids</code> parameter is set, also adds
      * <code>&lt;oids&gt;</code> child elements.

http://git-wip-us.apache.org/repos/asf/isis/blob/fc773898/core/metamodel/src/main/java/org/apache/isis/core/runtime/snapshot/XmlSchema.java
----------------------------------------------------------------------
diff --git a/core/metamodel/src/main/java/org/apache/isis/core/runtime/snapshot/XmlSchema.java b/core/metamodel/src/main/java/org/apache/isis/core/runtime/snapshot/XmlSchema.java
index 1bbab91..f5cc390 100644
--- a/core/metamodel/src/main/java/org/apache/isis/core/runtime/snapshot/XmlSchema.java
+++ b/core/metamodel/src/main/java/org/apache/isis/core/runtime/snapshot/XmlSchema.java
@@ -28,6 +28,8 @@ import org.w3c.dom.Element;
 import org.w3c.dom.NamedNodeMap;
 import org.w3c.dom.NodeList;
 
+import org.apache.isis.applib.services.xmlsnapshot.XmlSnapshotService.Snapshot;
+
 /**
  * Represents the schema for the derived snapshot.
  */
@@ -37,7 +39,7 @@ public final class XmlSchema {
     private final String uriBase;
     private String uri;
 
-    private final IsisSchema nofMeta;
+    private final IsisSchema isisMeta;
     private final XsMetaModel xsMeta;
     private final Helper helper;
 
@@ -58,7 +60,7 @@ public final class XmlSchema {
      *            the prefix for the application namespace's prefix
      */
     public XmlSchema(final String uriBase, final String prefix) {
-        this.nofMeta = new IsisSchema();
+        this.isisMeta = new IsisSchema();
         this.xsMeta = new XsMetaModel();
         this.helper = new Helper();
 
@@ -144,10 +146,10 @@ public final class XmlSchema {
      */
     Element createElement(final Document doc, final String localName, final String fullyQualifiedClassName, final String singularName, final String pluralName) {
         final Element element = doc.createElementNS(getUri(), getPrefix() + ":" + localName);
-        element.setAttributeNS(IsisSchema.NS_URI, "nof:fqn", fullyQualifiedClassName);
-        element.setAttributeNS(IsisSchema.NS_URI, "nof:singular", singularName);
-        element.setAttributeNS(IsisSchema.NS_URI, "nof:plural", pluralName);
-        nofMeta.addNamespace(element); // good a place as any
+        element.setAttributeNS(IsisSchema.NS_URI, IsisSchema.NS_PREFIX + ":fqn", fullyQualifiedClassName);
+        element.setAttributeNS(IsisSchema.NS_URI, IsisSchema.NS_PREFIX + ":singular", singularName);
+        element.setAttributeNS(IsisSchema.NS_URI, IsisSchema.NS_PREFIX + ":plural", pluralName);
+        isisMeta.addNamespace(element); // good a place as any
 
         addNamespace(element, getPrefix(), getUri());
         return element;
@@ -183,14 +185,14 @@ public final class XmlSchema {
         // <xs:element name="AO11ConfirmAnimalRegistration">
         // <xs:complexType>
         // <xs:sequence>
-        // <xs:element ref="nof:title"/>
+        // <xs:element ref="isis:title"/>
         // <!-- placeholder -->
         // </xs:sequence>
-        // <xs:attribute ref="nof:feature"
+        // <xs:attribute ref="isis:feature"
         // default="class"/>
-        // <xs:attribute ref="nof:oid"/>
-        // <xs:attribute ref="nof:annotation"/>
-        // <xs:attribute ref="nof:fqn"/>
+        // <xs:attribute ref="isis:oid"/>
+        // <xs:attribute ref="isis:annotation"/>
+        // <xs:attribute ref="isis:fqn"/>
         // </xs:complexType>
         // </xs:element>
 
@@ -203,7 +205,7 @@ public final class XmlSchema {
         final Element xsComplexTypeElement = xsMeta.complexTypeFor(xsElementForNofClassElement);
         final Element xsSequenceElement = xsMeta.sequenceFor(xsComplexTypeElement);
 
-        // xs:element/xs:complexType/xs:sequence/xs:element ref="nof:title"
+        // xs:element/xs:complexType/xs:sequence/xs:element ref="isis:title"
         final Element xsTitleElement = xsMeta.createXsElement(helper.docFor(xsSequenceElement), "element");
         xsTitleElement.setAttribute("ref", IsisSchema.NS_PREFIX + ":" + "title");
         xsSequenceElement.appendChild(xsTitleElement);
@@ -213,12 +215,12 @@ public final class XmlSchema {
         addXsElementForAppExtensions(xsSequenceElement, extensions);
 
         // xs:element/xs:complexType/xs:attribute ...
-        xsMeta.addXsNofFeatureAttributeElements(xsComplexTypeElement, "class");
-        xsMeta.addXsNofAttribute(xsComplexTypeElement, "oid");
-        xsMeta.addXsNofAttribute(xsComplexTypeElement, "fqn");
-        xsMeta.addXsNofAttribute(xsComplexTypeElement, "singular");
-        xsMeta.addXsNofAttribute(xsComplexTypeElement, "plural");
-        xsMeta.addXsNofAttribute(xsComplexTypeElement, "annotation");
+        xsMeta.addXsIsisFeatureAttributeElements(xsComplexTypeElement, "class");
+        xsMeta.addXsIsisAttribute(xsComplexTypeElement, "oid");
+        xsMeta.addXsIsisAttribute(xsComplexTypeElement, "fqn");
+        xsMeta.addXsIsisAttribute(xsComplexTypeElement, "singular");
+        xsMeta.addXsIsisAttribute(xsComplexTypeElement, "plural");
+        xsMeta.addXsIsisAttribute(xsComplexTypeElement, "annotation");
 
         Place.setXsdElement(element, xsElementForNofClassElement);
 
@@ -252,7 +254,7 @@ public final class XmlSchema {
         // </xs:complexType>
         // </xs:element>
 
-        // xs:element name="nof-extensions"
+        // xs:element name="isis-extensions"
         // xs:element/xs:complexType/xs:sequence
         final Element xsExtensionsSequenceElement = addExtensionsElement(parentXsElementElement);
 
@@ -262,14 +264,14 @@ public final class XmlSchema {
     }
 
     /**
-     * Adds an nof-extensions element and a complexType and sequence elements
+     * Adds an isis-extensions element and a complexType and sequence elements
      * underneath.
      * 
      * <p>
      * Returns the sequence element so that it can be appended to.
      */
     private Element addExtensionsElement(final Element parentXsElement) {
-        final Element xsExtensionsElementElement = xsMeta.createXsElementElement(helper.docFor(parentXsElement), "nof-extensions");
+        final Element xsExtensionsElementElement = xsMeta.createXsElementElement(helper.docFor(parentXsElement), "isis-extensions");
         parentXsElement.appendChild(xsExtensionsElementElement);
 
         // xs:element/xs:complexType/xs:sequence/xs:element/xs:complexType/xs:sequence
@@ -306,7 +308,7 @@ public final class XmlSchema {
         // <xs:element name="%%field object%%">
         // <xs:complexType>
         // <xs:sequence>
-        // <xs:element name="nof-extensions">
+        // <xs:element name="isis-extensions">
         // <xs:complexType>
         // <xs:sequence>
         // <xs:element name="%extensionClassShortName%"
@@ -320,10 +322,10 @@ public final class XmlSchema {
         // </xs:complexType>
         // </xs:element>
         // </xs:sequence>
-        // <xs:attribute ref="nof:feature" fixed="value"/>
-        // <xs:attribute ref="nof:datatype" fixed="nof:%datatype%"/>
-        // <xs:attribute ref="nof:isEmpty"/>
-        // <xs:attribute ref="nof:annotation"/>
+        // <xs:attribute ref="isis:feature" fixed="value"/>
+        // <xs:attribute ref="isis:datatype" fixed="isis:%datatype%"/>
+        // <xs:attribute ref="isis:isEmpty"/>
+        // <xs:attribute ref="isis:annotation"/>
         // </xs:complexType>
         // </xs:element>
         // </xs:sequence>
@@ -349,14 +351,14 @@ public final class XmlSchema {
         final Element xsFieldSequenceElement = xsMeta.sequenceFor(xsFieldComplexTypeElement);
 
         // xs:element/xs:complexType/xs:sequence/xs:element/xs:complexType/xs:sequence/xs:element
-        // name="nof-extensions"
+        // name="isis-extensions"
         // xs:element/xs:complexType/xs:sequence/xs:element/xs:complexType/xs:sequence/xs:element/xs:complexType/xs:sequence
         addXsElementForAppExtensions(xsFieldSequenceElement, extensions);
 
-        xsMeta.addXsNofFeatureAttributeElements(xsFieldComplexTypeElement, "value");
-        xsMeta.addXsNofAttribute(xsFieldComplexTypeElement, "datatype", datatype);
-        xsMeta.addXsNofAttribute(xsFieldComplexTypeElement, "isEmpty");
-        xsMeta.addXsNofAttribute(xsFieldComplexTypeElement, "annotation");
+        xsMeta.addXsIsisFeatureAttributeElements(xsFieldComplexTypeElement, "value");
+        xsMeta.addXsIsisAttribute(xsFieldComplexTypeElement, "datatype", datatype);
+        xsMeta.addXsIsisAttribute(xsFieldComplexTypeElement, "isEmpty");
+        xsMeta.addXsIsisAttribute(xsFieldComplexTypeElement, "annotation");
 
         return xsFieldElementElement;
     }
@@ -396,8 +398,8 @@ public final class XmlSchema {
         // <xs:element name="%%field object%%">
         // <xs:complexType>
         // <xs:sequence>
-        // <xs:element ref="nof:title" minOccurs="0"/>
-        // <xs:element name="nof-extensions">
+        // <xs:element ref="isis:title" minOccurs="0"/>
+        // <xs:element name="isis-extensions">
         // <xs:complexType>
         // <xs:sequence>
         // <xs:element name="app:%extension class short name%" minOccurs="0"
@@ -412,10 +414,10 @@ public final class XmlSchema {
         // </xs:element>
         // <xs:sequence minOccurs="0" maxOccurs="1"/>
         // </xs:sequence>
-        // <xs:attribute ref="nof:feature" fixed="reference"/>
-        // <xs:attribute ref="nof:type" default="%%appX%%:%%type%%"/>
-        // <xs:attribute ref="nof:isEmpty"/>
-        // <xs:attribute ref="nof:annotation"/>
+        // <xs:attribute ref="isis:feature" fixed="reference"/>
+        // <xs:attribute ref="isis:type" default="%%appX%%:%%type%%"/>
+        // <xs:attribute ref="isis:isEmpty"/>
+        // <xs:attribute ref="isis:annotation"/>
         // </xs:complexType>
         // </xs:element>
         // </xs:sequence>
@@ -436,14 +438,14 @@ public final class XmlSchema {
         final Element xsFieldSequenceElement = xsMeta.sequenceFor(xsFieldComplexTypeElement);
 
         // xs:element/xs:complexType/xs:sequence/xs:element/xs:complexType/xs:sequence/xs:element
-        // ref="nof:title"
+        // ref="isis:title"
         final Element xsFieldTitleElement = xsMeta.createXsElement(helper.docFor(xsFieldSequenceElement), "element");
         xsFieldTitleElement.setAttribute("ref", IsisSchema.NS_PREFIX + ":" + "title");
         xsFieldSequenceElement.appendChild(xsFieldTitleElement);
         xsMeta.setXsCardinality(xsFieldTitleElement, 0, 1);
 
         // xs:element/xs:complexType/xs:sequence/xs:element/xs:complexType/xs:sequence/xs:element
-        // name="nof-extensions"
+        // name="isis-extensions"
         addXsElementForAppExtensions(xsFieldSequenceElement, extensions);
 
         // xs:element/xs:complexType/xs:sequence/xs:element/xs:complexType/xs:sequence/xs:sequence
@@ -452,10 +454,10 @@ public final class XmlSchema {
         final Element xsReferencedElementSequenceElement = xsMeta.sequenceFor(xsFieldSequenceElement);
         xsMeta.setXsCardinality(xsReferencedElementSequenceElement, 0, 1);
 
-        xsMeta.addXsNofFeatureAttributeElements(xsFieldComplexTypeElement, "reference");
-        xsMeta.addXsNofAttribute(xsFieldComplexTypeElement, "type", "app:" + referencedClassName, false);
-        xsMeta.addXsNofAttribute(xsFieldComplexTypeElement, "isEmpty");
-        xsMeta.addXsNofAttribute(xsFieldComplexTypeElement, "annotation");
+        xsMeta.addXsIsisFeatureAttributeElements(xsFieldComplexTypeElement, "reference");
+        xsMeta.addXsIsisAttribute(xsFieldComplexTypeElement, "type", "app:" + referencedClassName, false);
+        xsMeta.addXsIsisAttribute(xsFieldComplexTypeElement, "isEmpty");
+        xsMeta.addXsIsisAttribute(xsFieldComplexTypeElement, "annotation");
 
         return xsFieldElementElement;
     }
@@ -476,13 +478,13 @@ public final class XmlSchema {
         // <xs:element name="%%field object%%">
         // <xs:complexType>
         // <xs:sequence>
-        // <xs:element ref="nof:oids" minOccurs="0" maxOccurs="1"/>
+        // <xs:element ref="isis:oids" minOccurs="0" maxOccurs="1"/>
         // <!-- nested element definitions go here -->
         // </xs:sequence>
-        // <xs:attribute ref="nof:feature" fixed="collection"/>
-        // <xs:attribute ref="nof:type" fixed="%%appX%%:%%type%%"/>
-        // <xs:attribute ref="nof:size"/>
-        // <xs:attribute ref="nof:annotation"/>
+        // <xs:attribute ref="isis:feature" fixed="collection"/>
+        // <xs:attribute ref="isis:type" fixed="%%appX%%:%%type%%"/>
+        // <xs:attribute ref="isis:size"/>
+        // <xs:attribute ref="isis:annotation"/>
         // </xs:complexType>
         // </xs:element>
         // </xs:sequence>
@@ -504,7 +506,7 @@ public final class XmlSchema {
         final Element xsFieldSequenceElement = xsMeta.sequenceFor(xsFieldComplexTypeElement);
 
         // xs:element/xs:complexType/xs:sequence/xs:element/xs:complexType/xs:sequence/xs:element
-        // ref="nof:oids"
+        // ref="isis:oids"
         final Element xsFieldOidsElement = xsMeta.createXsElement(helper.docFor(xsFieldSequenceElement), "element");
         xsFieldOidsElement.setAttribute("ref", IsisSchema.NS_PREFIX + ":" + "oids");
         xsFieldSequenceElement.appendChild(xsFieldOidsElement);
@@ -526,10 +528,10 @@ public final class XmlSchema {
         // sequenceFor(xsFieldSequenceElement);
         // setXsCardinality(xsReferencedElementSequenceElement, 0, 1);
 
-        xsMeta.addXsNofFeatureAttributeElements(xsFieldComplexTypeElement, "collection");
-        xsMeta.addXsNofAttribute(xsFieldComplexTypeElement, "type", "app:" + referencedClassName, false);
-        xsMeta.addXsNofAttribute(xsFieldComplexTypeElement, "size");
-        xsMeta.addXsNofAttribute(xsFieldComplexTypeElement, "annotation");
+        xsMeta.addXsIsisFeatureAttributeElements(xsFieldComplexTypeElement, "collection");
+        xsMeta.addXsIsisAttribute(xsFieldComplexTypeElement, "type", "app:" + referencedClassName, false);
+        xsMeta.addXsIsisAttribute(xsFieldComplexTypeElement, "size");
+        xsMeta.addXsIsisAttribute(xsFieldComplexTypeElement, "annotation");
 
         return xsFieldElementElement;
     }

http://git-wip-us.apache.org/repos/asf/isis/blob/fc773898/core/metamodel/src/main/java/org/apache/isis/core/runtime/snapshot/XmlSnapshot.java
----------------------------------------------------------------------
diff --git a/core/metamodel/src/main/java/org/apache/isis/core/runtime/snapshot/XmlSnapshot.java b/core/metamodel/src/main/java/org/apache/isis/core/runtime/snapshot/XmlSnapshot.java
index 5873cf2..d71b53e 100644
--- a/core/metamodel/src/main/java/org/apache/isis/core/runtime/snapshot/XmlSnapshot.java
+++ b/core/metamodel/src/main/java/org/apache/isis/core/runtime/snapshot/XmlSnapshot.java
@@ -19,15 +19,31 @@
 
 package org.apache.isis.core.runtime.snapshot;
 
+import java.io.StringReader;
+import java.io.StringWriter;
 import java.util.Collections;
 import java.util.Enumeration;
 import java.util.List;
+import java.util.Map;
 import java.util.StringTokenizer;
+import java.util.UUID;
 import java.util.Vector;
 
 import javax.xml.parsers.DocumentBuilder;
 import javax.xml.parsers.DocumentBuilderFactory;
 import javax.xml.parsers.ParserConfigurationException;
+import javax.xml.transform.OutputKeys;
+import javax.xml.transform.Transformer;
+import javax.xml.transform.TransformerConfigurationException;
+import javax.xml.transform.TransformerException;
+import javax.xml.transform.TransformerFactory;
+import javax.xml.transform.TransformerFactoryConfigurationError;
+import javax.xml.transform.dom.DOMResult;
+import javax.xml.transform.dom.DOMSource;
+import javax.xml.transform.stream.StreamResult;
+import javax.xml.transform.stream.StreamSource;
+
+import com.google.common.collect.Maps;
 
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
@@ -36,6 +52,8 @@ import org.w3c.dom.Element;
 import org.w3c.dom.Node;
 import org.w3c.dom.NodeList;
 
+import org.apache.isis.applib.ViewModel;
+import org.apache.isis.applib.services.xmlsnapshot.XmlSnapshotService.Snapshot;
 import org.apache.isis.applib.snapshot.SnapshottableWithInclusions;
 import org.apache.isis.core.commons.exceptions.IsisException;
 import org.apache.isis.core.metamodel.adapter.ObjectAdapter;
@@ -64,19 +82,19 @@ import org.apache.isis.core.metamodel.spec.feature.OneToOneAssociation;
  * 
  * <pre>
  * XmlSnapshot snapshot = new XmlSnapshot(customer); // where customer is a
- *                                                   // reference to an
- *                                                   // ObjectAdapter
+ * // reference to an
+ * // ObjectAdapter
  * Element customerAsXml = snapshot.toXml(); // returns customer's fields, titles
- *                                           // of simple references, number of
- *                                           // items in collections
+ * // of simple references, number of
+ * // items in collections
  * snapshot.include(&quot;placeOfBirth&quot;); // navigates to another object represented by
- *                                   // simple reference &quot;placeOfBirth&quot;
+ * // simple reference &quot;placeOfBirth&quot;
  * snapshot.include(&quot;orders/product&quot;); // navigates to all &lt;tt&gt;Order&lt;/tt&gt;s of
- *                                     // &lt;tt&gt;Customer&lt;/tt&gt;, and from them for
- *                                     // their &lt;tt&gt;Product&lt;/tt&gt;s
+ * // &lt;tt&gt;Customer&lt;/tt&gt;, and from them for
+ * // their &lt;tt&gt;Product&lt;/tt&gt;s
  * </pre>
  */
-public class XmlSnapshot {
+public class XmlSnapshot implements Snapshot {
 
     private static final Logger LOG = LoggerFactory.getLogger(XmlSnapshot.class);
 
@@ -110,7 +128,9 @@ public class XmlSnapshot {
 
     /**
      * Start a snapshot at the root object, using own namespace manager.
-     * @param oidMarshaller TODO
+     * 
+     * @param oidMarshaller
+     *            TODO
      */
     public XmlSnapshot(final ObjectAdapter rootAdapter, OidMarshaller oidMarshaller) {
         this(rootAdapter, new XmlSchema(), oidMarshaller);
@@ -118,7 +138,9 @@ public class XmlSnapshot {
 
     /**
      * Start a snapshot at the root object, using supplied namespace manager.
-     * @param oidMarshaller TODO
+     * 
+     * @param oidMarshaller
+     *            TODO
      */
     public XmlSnapshot(final ObjectAdapter rootAdapter, final XmlSchema schema, final OidMarshaller oidMarshaller) {
 
@@ -243,7 +265,7 @@ public class XmlSnapshot {
      * 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
+     * The parentElement must have an owner document, and should define the &quot;isis&quot;
      * 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
@@ -500,7 +522,7 @@ public class XmlSnapshot {
                 LOG.debug("includeField(Pl, Vec, Str): 1->M: " + log("collection.size", "" + facet.size(collection)));
             }
             boolean allFieldsNavigated = true;
-            for(final ObjectAdapter referencedObject: facet.iterable(collection)) {
+            for (final ObjectAdapter referencedObject : facet.iterable(collection)) {
                 final boolean appendedXml = appendXmlThenIncludeRemaining(fieldPlace, referencedObject, names, annotation);
                 if (LOG.isDebugEnabled()) {
                     LOG.debug("includeField(Pl, Vec, Str): 1->M: + invoked appendXmlThenIncludeRemaining for " + log("referencedObj", referencedObject) + andlog("returned", "" + appendedXml));
@@ -589,22 +611,22 @@ public class XmlSnapshot {
         return childElement;
     }
 
-    Place objectToElement(final ObjectAdapter object) {
+    Place objectToElement(final ObjectAdapter adapter) {
 
         if (LOG.isDebugEnabled()) {
-            LOG.debug("objectToElement(" + log("object", object) + ")");
+            LOG.debug("objectToElement(" + log("object", adapter) + ")");
         }
 
-        final ObjectSpecification nos = object.getSpecification();
+        final ObjectSpecification nos = adapter.getSpecification();
 
         if (LOG.isDebugEnabled()) {
-            LOG.debug("objectToElement(NO): create element and nof:title");
+            LOG.debug("objectToElement(NO): create element and isis:title");
         }
         final Element element = schema.createElement(getXmlDocument(), nos.getShortIdentifier(), nos.getFullIdentifier(), nos.getSingularName(), nos.getPluralName());
-        isisMetaModel.appendNofTitle(element, object.titleString());
+        isisMetaModel.appendIsisTitle(element, adapter.titleString());
 
         if (LOG.isDebugEnabled()) {
-            LOG.debug("objectToElement(NO): create XS element for NOF class");
+            LOG.debug("objectToElement(NO): create XS element for Isis class");
         }
         final Element xsElement = schema.createXsElementForNofClass(getXsdDocument(), element, topLevelElementWritten, FacetUtil.getFacetsByType(nos));
 
@@ -612,9 +634,9 @@ public class XmlSnapshot {
         // cardinality setting.
         topLevelElementWritten = true;
 
-        final Place place = new Place(object, element);
+        final Place place = new Place(adapter, element);
 
-        isisMetaModel.setAttributesForClass(element, oidAsString(object).toString());
+        isisMetaModel.setAttributesForClass(element, oidAsString(adapter).toString());
 
         final List<ObjectAssociation> fields = nos.getAssociations(Contributed.EXCLUDED);
         if (LOG.isDebugEnabled()) {
@@ -678,7 +700,7 @@ public class XmlSnapshot {
 
                 ObjectAdapter value;
                 try {
-                    value = valueAssociation.get(object);
+                    value = valueAssociation.get(adapter);
 
                     final ObjectSpecification valueNos = value.getSpecification();
 
@@ -728,13 +750,13 @@ public class XmlSnapshot {
                 ObjectAdapter referencedObjectAdapter;
 
                 try {
-                    referencedObjectAdapter = oneToOneAssociation.get(object);
+                    referencedObjectAdapter = oneToOneAssociation.get(adapter);
 
                     // XML
                     isisMetaModel.setAttributesForReference(xmlReferenceElement, schema.getPrefix(), fullyQualifiedClassName);
 
                     if (referencedObjectAdapter != null) {
-                        isisMetaModel.appendNofTitle(xmlReferenceElement, referencedObjectAdapter.titleString());
+                        isisMetaModel.appendIsisTitle(xmlReferenceElement, referencedObjectAdapter.titleString());
                     } else {
                         isisMetaModel.setIsEmptyAttribute(xmlReferenceElement, true);
                     }
@@ -753,11 +775,15 @@ public class XmlSnapshot {
                 }
 
                 final OneToManyAssociation oneToManyAssociation = (OneToManyAssociation) field;
-                final Element xmlCollectionElement = xmlFieldElement; // more meaningful locally scoped name
+                final Element xmlCollectionElement = xmlFieldElement; // more
+                                                                      // meaningful
+                                                                      // locally
+                                                                      // scoped
+                                                                      // name
 
                 ObjectAdapter collection;
                 try {
-                    collection = oneToManyAssociation.get(object);
+                    collection = oneToManyAssociation.get(adapter);
                     final ObjectSpecification referencedTypeNos = oneToManyAssociation.getSpecification();
                     final String fullyQualifiedClassName = referencedTypeNos.getFullIdentifier();
 
@@ -799,8 +825,22 @@ public class XmlSnapshot {
         return place;
     }
 
+    
+    private final Map<ObjectAdapter, String> viewModelFakeOids = Maps.newHashMap();
+    
     private String oidAsString(final ObjectAdapter adapter) {
-        return adapter.getOid().enString(oidMarshaller);
+        if(adapter.getObject() instanceof ViewModel) {
+            // return a fake oid for view models; 
+            // a snapshot may be being used to create the memento/OID 
+            String fakeOid = viewModelFakeOids.get(adapter);
+            if(fakeOid == null) {
+                fakeOid = "viewmodel-fakeoid-" + UUID.randomUUID().toString();
+                viewModelFakeOids.put(adapter, fakeOid);
+            }
+            return fakeOid;
+        } else {
+            return adapter.getOid().enString(oidMarshaller);
+        }
     }
 
     /**
@@ -819,5 +859,39 @@ public class XmlSnapshot {
         this.xmlElement = xmlElement;
     }
 
+    @Override
+    public String getXmlDocumentAsString() {
+        final Document doc = getXmlDocument();
+        return asString(doc);
+    }
+
+    @Override
+    public String getXsdDocumentAsString() {
+        final Document doc = getXsdDocument();
+        return asString(doc);
+    }
+    
+    private static String asString(final Document doc) {
+        try {
+            final DOMSource domSource = new DOMSource(doc);
+            final StringWriter writer = new StringWriter();
+            final StreamResult result = new StreamResult(writer);
+            final TransformerFactory tf = TransformerFactory.newInstance();
+            final Transformer transformer = tf.newTransformer();
+            transformer.setOutputProperty(OutputKeys.OMIT_XML_DECLARATION, "no");
+            transformer.setOutputProperty(OutputKeys.METHOD, "xml");
+            transformer.setOutputProperty(OutputKeys.INDENT, "yes");
+            transformer.setOutputProperty(OutputKeys.ENCODING, "UTF-8");
+            transformer.setOutputProperty("{http://xml.apache.org/xslt}indent-amount", "2");
+            transformer.transform(domSource, result);
+            
+            return writer.toString();
+        } catch (TransformerConfigurationException e) {
+            throw new IsisException(e);
+        } catch (TransformerException e) {
+            throw new IsisException(e);
+        }
+    }
+    
 
 }

http://git-wip-us.apache.org/repos/asf/isis/blob/fc773898/core/metamodel/src/main/java/org/apache/isis/core/runtime/snapshot/XsMetaModel.java
----------------------------------------------------------------------
diff --git a/core/metamodel/src/main/java/org/apache/isis/core/runtime/snapshot/XsMetaModel.java b/core/metamodel/src/main/java/org/apache/isis/core/runtime/snapshot/XsMetaModel.java
index 4d759e9..7936155 100644
--- a/core/metamodel/src/main/java/org/apache/isis/core/runtime/snapshot/XsMetaModel.java
+++ b/core/metamodel/src/main/java/org/apache/isis/core/runtime/snapshot/XsMetaModel.java
@@ -65,11 +65,11 @@ public final class XsMetaModel {
      */
     public static final String W3_ORG_XSI_PREFIX = "xsi";
 
-    private final IsisSchema nofMeta;
+    private final IsisSchema isisMeta;
 
     public XsMetaModel() {
         this.helper = new Helper();
-        this.nofMeta = new IsisSchema();
+        this.isisMeta = new IsisSchema();
     }
 
     /**
@@ -92,7 +92,7 @@ public final class XsMetaModel {
 
         xsSchemaElement.setAttribute("elementFormDefault", "qualified");
 
-        nofMeta.addNamespace(xsSchemaElement);
+        isisMeta.addNamespace(xsSchemaElement);
 
         xsdDoc.appendChild(xsSchemaElement);
         final Element xsImportElement = createXsElement(xsdDoc, "import");
@@ -140,50 +140,50 @@ public final class XsMetaModel {
     // }
 
     /**
-     * Creates an xs:attribute ref="nof:xxx" element, and appends to specified
+     * Creates an xs:attribute ref="isis:xxx" element, and appends to specified
      * owning element.
      */
-    Element addXsNofAttribute(final Element parentXsElement, final String nofAttributeRef) {
-        return addXsNofAttribute(parentXsElement, nofAttributeRef, null);
+    Element addXsIsisAttribute(final Element parentXsElement, final String isisAttributeRef) {
+        return addXsIsisAttribute(parentXsElement, isisAttributeRef, null);
     }
 
     /**
-     * Adds <code>xs:attribute ref="nof:xxx" fixed="yyy"</code> element, and
+     * Adds <code>xs:attribute ref="isis:xxx" fixed="yyy"</code> element, and
      * appends to specified parent XSD element.
      */
-    Element addXsNofAttribute(final Element parentXsElement, final String nofAttributeRef, final String fixedValue) {
-        return addXsNofAttribute(parentXsElement, nofAttributeRef, fixedValue, true);
+    Element addXsIsisAttribute(final Element parentXsElement, final String isisAttributeRef, final String fixedValue) {
+        return addXsIsisAttribute(parentXsElement, isisAttributeRef, fixedValue, true);
     }
 
     /**
-     * Adds <code>xs:attribute ref="nof:xxx" default="yyy"</code> element, and
+     * Adds <code>xs:attribute ref="isis:xxx" default="yyy"</code> element, and
      * appends to specified parent XSD element.
      * 
      * The last parameter determines whether to use <code>fixed="yyy"</code>
      * rather than <code>default="yyy"</code>.
      */
-    Element addXsNofAttribute(final Element parentXsElement, final String nofAttributeRef, final String value, final boolean useFixed) {
-        final Element xsNofAttributeElement = createXsElement(helper.docFor(parentXsElement), "attribute");
-        xsNofAttributeElement.setAttribute("ref", IsisSchema.NS_PREFIX + ":" + nofAttributeRef);
-        parentXsElement.appendChild(xsNofAttributeElement);
+    Element addXsIsisAttribute(final Element parentXsElement, final String isisAttributeRef, final String value, final boolean useFixed) {
+        final Element xsIsisAttributeElement = createXsElement(helper.docFor(parentXsElement), "attribute");
+        xsIsisAttributeElement.setAttribute("ref", IsisSchema.NS_PREFIX + ":" + isisAttributeRef);
+        parentXsElement.appendChild(xsIsisAttributeElement);
         if (value != null) {
             if (useFixed) {
-                xsNofAttributeElement.setAttribute("fixed", value);
+                xsIsisAttributeElement.setAttribute("fixed", value);
             } else {
-                xsNofAttributeElement.setAttribute("default", value);
+                xsIsisAttributeElement.setAttribute("default", value);
             }
         }
         return parentXsElement;
     }
 
     /**
-     * Adds <code>xs:attribute ref="nof:feature" fixed="(feature)"</code>
+     * Adds <code>xs:attribute ref="isis:feature" fixed="(feature)"</code>
      * element as child to supplied XSD element, presumed to be an
      * <xs:complexType</code>.
      */
-    Element addXsNofFeatureAttributeElements(final Element parentXsElement, final String feature) {
+    Element addXsIsisFeatureAttributeElements(final Element parentXsElement, final String feature) {
         final Element xsNofFeatureAttributeElement = createXsElement(helper.docFor(parentXsElement), "attribute");
-        xsNofFeatureAttributeElement.setAttribute("ref", "nof:feature");
+        xsNofFeatureAttributeElement.setAttribute("ref", IsisSchema.NS_PREFIX + ":feature");
         xsNofFeatureAttributeElement.setAttribute("fixed", feature);
         parentXsElement.appendChild(xsNofFeatureAttributeElement);
         return xsNofFeatureAttributeElement;

http://git-wip-us.apache.org/repos/asf/isis/blob/fc773898/core/runtime/src/main/java/org/apache/isis/core/runtime/persistence/objectstore/transaction/PublishingServiceWithDefaultPayloadFactories.java
----------------------------------------------------------------------
diff --git a/core/runtime/src/main/java/org/apache/isis/core/runtime/persistence/objectstore/transaction/PublishingServiceWithDefaultPayloadFactories.java b/core/runtime/src/main/java/org/apache/isis/core/runtime/persistence/objectstore/transaction/PublishingServiceWithDefaultPayloadFactories.java
index f066b59..19a975b 100644
--- a/core/runtime/src/main/java/org/apache/isis/core/runtime/persistence/objectstore/transaction/PublishingServiceWithDefaultPayloadFactories.java
+++ b/core/runtime/src/main/java/org/apache/isis/core/runtime/persistence/objectstore/transaction/PublishingServiceWithDefaultPayloadFactories.java
@@ -85,7 +85,7 @@ public class PublishingServiceWithDefaultPayloadFactories {
                 ? payloadFactoryIfAny
                 : defaultObjectPayloadFactory;
         final EventPayload payload = payloadFactoryToUse.payloadFor(
-                ObjectAdapterUtils.unwrapObject(undeletedElseEmpty(changedAdapter)), changeKind);
+                ObjectAdapter.Util.unwrap(undeletedElseEmpty(changedAdapter)), changeKind);
         payload.withStringifier(stringifier);
         publishingService.publish(metadata, payload);
     }
@@ -104,9 +104,9 @@ public class PublishingServiceWithDefaultPayloadFactories {
         List<ObjectAdapter> parameters = currentInvocation.getParameters();
         final EventPayload payload = payloadFactoryToUse.payloadFor(
                 currentInvocation.getAction().getIdentifier(),
-                ObjectAdapterUtils.unwrapObject(undeletedElseEmpty(target)), 
-                ObjectAdapterUtils.unwrapObjects(undeletedElseEmpty(parameters)), 
-                ObjectAdapterUtils.unwrapObject(undeletedElseEmpty(result)));
+                ObjectAdapter.Util.unwrap(undeletedElseEmpty(target)), 
+                ObjectAdapter.Util.unwrap(undeletedElseEmpty(parameters)), 
+                ObjectAdapter.Util.unwrap(undeletedElseEmpty(result)));
         payload.withStringifier(stringifier);
         publishingService.publish(metadata, payload);
     }

http://git-wip-us.apache.org/repos/asf/isis/blob/fc773898/core/runtime/src/main/java/org/apache/isis/core/runtime/snapshot/XmlSnapshotBuilder.java
----------------------------------------------------------------------
diff --git a/core/runtime/src/main/java/org/apache/isis/core/runtime/snapshot/XmlSnapshotBuilder.java b/core/runtime/src/main/java/org/apache/isis/core/runtime/snapshot/XmlSnapshotBuilder.java
index 43c6d93..88449f6 100644
--- a/core/runtime/src/main/java/org/apache/isis/core/runtime/snapshot/XmlSnapshotBuilder.java
+++ b/core/runtime/src/main/java/org/apache/isis/core/runtime/snapshot/XmlSnapshotBuilder.java
@@ -22,7 +22,6 @@ import java.util.List;
 
 import com.google.common.collect.Lists;
 
-import org.apache.isis.applib.snapshot.Snapshottable;
 import org.apache.isis.core.metamodel.adapter.ObjectAdapter;
 import org.apache.isis.core.metamodel.adapter.mgr.AdapterManager;
 import org.apache.isis.core.metamodel.adapter.oid.OidMarshaller;
@@ -39,7 +38,7 @@ import org.apache.isis.core.runtime.system.persistence.PersistenceSession;
  */
 public class XmlSnapshotBuilder {
 
-    private final Snapshottable snapshottable;
+    private final Object domainObject;
     private XmlSchema schema;
     private OidMarshaller oidMarshaller = new OidMarshaller();
 
@@ -55,8 +54,8 @@ public class XmlSnapshotBuilder {
 
     private final List<XmlSnapshotBuilder.PathAndAnnotation> paths = Lists.newArrayList();
 
-    public XmlSnapshotBuilder(final Snapshottable domainObject) {
-        this.snapshottable = domainObject;
+    public XmlSnapshotBuilder(final Object domainObject) {
+        this.domainObject = domainObject;
     }
 
     public XmlSnapshotBuilder usingSchema(final XmlSchema schema) {
@@ -79,7 +78,7 @@ public class XmlSnapshotBuilder {
     }
 
     public XmlSnapshot build() {
-        final ObjectAdapter adapter = getAdapterManager().adapterFor(snapshottable);
+        final ObjectAdapter adapter = getAdapterManager().adapterFor(domainObject);
         final XmlSnapshot snapshot = (schema != null) ? new XmlSnapshot(adapter, schema, oidMarshaller) : new XmlSnapshot(adapter, oidMarshaller);
         for (final XmlSnapshotBuilder.PathAndAnnotation paa : paths) {
             if (paa.annotation != null) {

http://git-wip-us.apache.org/repos/asf/isis/blob/fc773898/core/runtime/src/main/java/org/apache/isis/core/runtime/snapshot/XmlSnapshotServiceDefault.java
----------------------------------------------------------------------
diff --git a/core/runtime/src/main/java/org/apache/isis/core/runtime/snapshot/XmlSnapshotServiceDefault.java b/core/runtime/src/main/java/org/apache/isis/core/runtime/snapshot/XmlSnapshotServiceDefault.java
new file mode 100644
index 0000000..c90614d
--- /dev/null
+++ b/core/runtime/src/main/java/org/apache/isis/core/runtime/snapshot/XmlSnapshotServiceDefault.java
@@ -0,0 +1,87 @@
+/**
+ *  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 org.apache.isis.applib.services.xmlsnapshot.XmlSnapshotService;
+import org.apache.isis.applib.services.xmlsnapshot.XmlSnapshotServiceAbstract;
+import org.apache.isis.core.metamodel.adapter.ObjectAdapter;
+import org.apache.isis.core.metamodel.adapter.mgr.AdapterManager;
+import org.apache.isis.core.metamodel.adapter.oid.OidMarshaller;
+import org.apache.isis.core.runtime.system.context.IsisContext;
+import org.apache.isis.core.runtime.system.persistence.PersistenceSession;
+
+public class XmlSnapshotServiceDefault extends XmlSnapshotServiceAbstract {
+
+    static class XmlSnapshotServiceDefaultBuilder implements XmlSnapshotService.Builder{
+        
+        private final XmlSnapshotBuilder builder;
+        public XmlSnapshotServiceDefaultBuilder(final Object domainObject) {
+            builder = new XmlSnapshotBuilder(domainObject);
+        }
+        
+        @Override
+        public void includePath(String path) {
+            builder.includePath(path);
+        }
+
+        @Override
+        public void includePathAndAnnotation(String path, String annotation) {
+            builder.includePathAndAnnotation(path, annotation);
+        }
+
+        public XmlSnapshotService.Snapshot build() {
+            XmlSnapshot xmlSnapshot = builder.build();
+            return xmlSnapshot;
+        }
+    } 
+
+
+    /**
+     * Creates a simple snapshot of the domain object.
+     */
+    public XmlSnapshotService.Snapshot snapshotFor(final Object domainObject) {
+        final ObjectAdapter adapter = getAdapterManager().adapterFor(domainObject);
+        return new XmlSnapshot(adapter, getOidMarshaller());
+    }
+
+    /**
+     * Creates a builder that allows a custom snapshot - traversing additional associated
+     * properties or collections (using {@link Builder#includePath(String)} and 
+     * {@link Builder#includePathAndAnnotation(String, String)}) - to be created.
+     */
+    public Builder builderFor(final Object domainObject) {
+        return new XmlSnapshotServiceDefaultBuilder(domainObject);
+    }
+
+    
+    // //////////////////////////////////////
+    
+
+    protected AdapterManager getAdapterManager() {
+        return gerPersistenceSession().getAdapterManager();
+    }
+
+    protected PersistenceSession gerPersistenceSession() {
+        return IsisContext.getPersistenceSession();
+    }
+
+    protected OidMarshaller getOidMarshaller() {
+        return IsisContext.getOidMarshaller();
+    }
+
+
+}

http://git-wip-us.apache.org/repos/asf/isis/blob/fc773898/example/application/quickstart_wicket_restful_jdo/dom/src/main/java/dom/todo/ToDoItem.java
----------------------------------------------------------------------
diff --git a/example/application/quickstart_wicket_restful_jdo/dom/src/main/java/dom/todo/ToDoItem.java b/example/application/quickstart_wicket_restful_jdo/dom/src/main/java/dom/todo/ToDoItem.java
index 0fa748e..ee70c76 100644
--- a/example/application/quickstart_wicket_restful_jdo/dom/src/main/java/dom/todo/ToDoItem.java
+++ b/example/application/quickstart_wicket_restful_jdo/dom/src/main/java/dom/todo/ToDoItem.java
@@ -62,6 +62,7 @@ import org.apache.isis.applib.annotation.SortedBy;
 import org.apache.isis.applib.annotation.TypicalLength;
 import org.apache.isis.applib.annotation.Where;
 import org.apache.isis.applib.clock.Clock;
+import org.apache.isis.applib.services.xmlsnapshot.XmlSnapshotService;
 import org.apache.isis.applib.util.ObjectContracts;
 import org.apache.isis.applib.util.TitleBuffer;
 import org.apache.isis.applib.value.Blob;
@@ -737,4 +738,16 @@ public class ToDoItem implements Comparable<ToDoItem> /*, Locatable*/ { // GMAP3
 //        this.location = location;
 //    }
 
+    
+    
+    public String asSnapshot() {
+        final String str = xmlSnapshotService.snapshotFor(this).getXmlDocumentAsString();
+        return str;
+    }
+    
+    private XmlSnapshotService xmlSnapshotService;
+    public void injectXmlSnapshotService(XmlSnapshotService xmlSnapshotService) {
+        this.xmlSnapshotService = xmlSnapshotService;
+    }
+    
 }

http://git-wip-us.apache.org/repos/asf/isis/blob/fc773898/example/application/quickstart_wicket_restful_jdo/webapp/src/main/webapp/WEB-INF/isis.properties
----------------------------------------------------------------------
diff --git a/example/application/quickstart_wicket_restful_jdo/webapp/src/main/webapp/WEB-INF/isis.properties b/example/application/quickstart_wicket_restful_jdo/webapp/src/main/webapp/WEB-INF/isis.properties
index 1cf474d..98720d5 100644
--- a/example/application/quickstart_wicket_restful_jdo/webapp/src/main/webapp/WEB-INF/isis.properties
+++ b/example/application/quickstart_wicket_restful_jdo/webapp/src/main/webapp/WEB-INF/isis.properties
@@ -169,6 +169,7 @@ isis.services = \
                 30:webapp.prototyping.DeveloperUtilities,\
                 \
                 org.apache.isis.core.metamodel.services.bookmarks.BookmarkServiceDefault,\
+                org.apache.isis.core.runtime.snapshot.XmlSnapshotServiceDefault,\
                 org.apache.isis.objectstore.jdo.service.RegisterEntities,\
                 org.apache.isis.objectstore.jdo.datanucleus.service.support.IsisJdoSupportImpl,\
                 org.apache.isis.objectstore.jdo.applib.service.exceprecog.ExceptionRecognizerCompositeForJdoObjectStore,\

http://git-wip-us.apache.org/repos/asf/isis/blob/fc773898/example/application/simple_wicket_restful_jdo/webapp/src/main/webapp/WEB-INF/isis.properties
----------------------------------------------------------------------
diff --git a/example/application/simple_wicket_restful_jdo/webapp/src/main/webapp/WEB-INF/isis.properties b/example/application/simple_wicket_restful_jdo/webapp/src/main/webapp/WEB-INF/isis.properties
index 4dbac3c..8ed6c96 100644
--- a/example/application/simple_wicket_restful_jdo/webapp/src/main/webapp/WEB-INF/isis.properties
+++ b/example/application/simple_wicket_restful_jdo/webapp/src/main/webapp/WEB-INF/isis.properties
@@ -165,6 +165,7 @@ isis.services = \
                 30:webapp.prototyping.DeveloperUtilities,\
                 \
                 org.apache.isis.core.metamodel.services.bookmarks.BookmarkServiceDefault,\
+                org.apache.isis.core.runtime.snapshot.XmlSnapshotServiceDefault,\
                 org.apache.isis.objectstore.jdo.service.RegisterEntities,\
                 org.apache.isis.objectstore.jdo.datanucleus.service.support.IsisJdoSupportImpl,\
                 org.apache.isis.objectstore.jdo.applib.service.exceprecog.ExceptionRecognizerCompositeForJdoObjectStore,\