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 2016/01/25 16:07:30 UTC

[09/50] [abbrv] isis git commit: ISIS-993: metadata classes, facet factory, starting on the wicket component

http://git-wip-us.apache.org/repos/asf/isis/blob/ea9204f1/core/metamodel/src/main/java/org/apache/isis/core/metamodel/facets/object/layoutxml/LayoutXmlFacet.java
----------------------------------------------------------------------
diff --git a/core/metamodel/src/main/java/org/apache/isis/core/metamodel/facets/object/layoutxml/LayoutXmlFacet.java b/core/metamodel/src/main/java/org/apache/isis/core/metamodel/facets/object/layoutxml/LayoutXmlFacet.java
new file mode 100644
index 0000000..608abbe
--- /dev/null
+++ b/core/metamodel/src/main/java/org/apache/isis/core/metamodel/facets/object/layoutxml/LayoutXmlFacet.java
@@ -0,0 +1,32 @@
+/*
+ *  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.metamodel.facets.object.layoutxml;
+
+
+import org.apache.isis.core.metamodel.facetapi.Facet;
+import org.apache.isis.applib.layout.v1_0.DomainObject;
+
+/**
+ * Corresponds to providing a <code>.layout.xml</code> file for the domain object's class.
+ */
+public interface LayoutXmlFacet extends Facet {
+
+    public DomainObject getLayoutMetadata();
+
+}

http://git-wip-us.apache.org/repos/asf/isis/blob/ea9204f1/core/metamodel/src/main/java/org/apache/isis/core/metamodel/facets/object/layoutxml/LayoutXmlFacetDefault.java
----------------------------------------------------------------------
diff --git a/core/metamodel/src/main/java/org/apache/isis/core/metamodel/facets/object/layoutxml/LayoutXmlFacetDefault.java b/core/metamodel/src/main/java/org/apache/isis/core/metamodel/facets/object/layoutxml/LayoutXmlFacetDefault.java
new file mode 100644
index 0000000..3a391d7
--- /dev/null
+++ b/core/metamodel/src/main/java/org/apache/isis/core/metamodel/facets/object/layoutxml/LayoutXmlFacetDefault.java
@@ -0,0 +1,85 @@
+/*
+ *  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.metamodel.facets.object.layoutxml;
+
+
+import java.util.List;
+
+import org.apache.isis.core.metamodel.facetapi.Facet;
+import org.apache.isis.core.metamodel.facetapi.FacetAbstract;
+import org.apache.isis.core.metamodel.facetapi.FacetHolder;
+import org.apache.isis.applib.layout.v1_0.DomainObject;
+import org.apache.isis.applib.layout.v1_0.TabGroup;
+import org.apache.isis.core.metamodel.spec.ObjectSpecification;
+import org.apache.isis.core.metamodel.spec.feature.Contributed;
+import org.apache.isis.core.metamodel.spec.feature.OneToOneAssociation;
+
+public class LayoutXmlFacetDefault
+            extends FacetAbstract
+            implements LayoutXmlFacet {
+
+    private final DomainObject metadata;
+
+    public static Class<? extends Facet> type() {
+        return LayoutXmlFacet.class;
+    }
+
+
+    public static LayoutXmlFacet create(
+            final FacetHolder facetHolder,
+            final DomainObject domainObject) {
+        if(domainObject == null) {
+            return null;
+        }
+        return new LayoutXmlFacetDefault(facetHolder, domainObject);
+    }
+
+    private LayoutXmlFacetDefault(
+            final FacetHolder facetHolder,
+            final DomainObject metadata) {
+        super(LayoutXmlFacetDefault.type(), facetHolder, Derivation.NOT_DERIVED);
+        this.metadata = metadata;
+    }
+
+
+    private boolean fleshedOut;
+
+    public DomainObject getLayoutMetadata() {
+        return fleshedOut? metadata : fleshOut(metadata);
+    }
+
+    private  DomainObject fleshOut(final DomainObject metadata) {
+        synchronized (metadata) {
+            doFleshOut(metadata);
+            fleshedOut = true;
+        }
+        return metadata;
+    }
+
+    private void doFleshOut(final DomainObject metadata) {
+        ObjectSpecification objectSpec = (ObjectSpecification) getFacetHolder();
+        List<OneToOneAssociation> properties = getProperties(objectSpec);
+        List<TabGroup> tabGroups = metadata.getTabGroups();
+    }
+
+    private List getProperties(final ObjectSpecification objectSpec) {
+        return objectSpec
+                .getAssociations(Contributed.INCLUDED, OneToOneAssociation.Filters.PROPERTIES);
+    }
+}

http://git-wip-us.apache.org/repos/asf/isis/blob/ea9204f1/core/metamodel/src/main/java/org/apache/isis/core/metamodel/facets/object/layoutxml/LayoutXmlFacetFactory.java
----------------------------------------------------------------------
diff --git a/core/metamodel/src/main/java/org/apache/isis/core/metamodel/facets/object/layoutxml/LayoutXmlFacetFactory.java b/core/metamodel/src/main/java/org/apache/isis/core/metamodel/facets/object/layoutxml/LayoutXmlFacetFactory.java
new file mode 100644
index 0000000..17d4063
--- /dev/null
+++ b/core/metamodel/src/main/java/org/apache/isis/core/metamodel/facets/object/layoutxml/LayoutXmlFacetFactory.java
@@ -0,0 +1,98 @@
+/* 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.metamodel.facets.object.layoutxml;
+
+import java.io.IOException;
+import java.util.Set;
+
+import com.google.common.collect.Sets;
+
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import org.apache.isis.applib.services.jaxb.JaxbService;
+import org.apache.isis.core.commons.lang.ClassExtensions;
+import org.apache.isis.core.metamodel.facetapi.FacetHolder;
+import org.apache.isis.core.metamodel.facetapi.FacetUtil;
+import org.apache.isis.core.metamodel.facetapi.FeatureType;
+import org.apache.isis.core.metamodel.facets.FacetFactoryAbstract;
+import org.apache.isis.applib.layout.v1_0.DomainObject;
+import org.apache.isis.core.metamodel.runtimecontext.ServicesInjector;
+import org.apache.isis.core.metamodel.runtimecontext.ServicesInjectorAware;
+
+public class LayoutXmlFacetFactory extends FacetFactoryAbstract implements ServicesInjectorAware {
+
+    private static final Logger LOG = LoggerFactory.getLogger(LayoutXmlFacetFactory.class);
+
+    public LayoutXmlFacetFactory() {
+        super(FeatureType.OBJECTS_ONLY);
+    }
+
+    @Override
+    public void process(final ProcessClassContext processClassContext) {
+        final Class<?> cls = processClassContext.getCls();
+        final FacetHolder facetHolder = processClassContext.getFacetHolder();
+
+        FacetUtil.addFacet(LayoutXmlFacetDefault.create(facetHolder, readMetadata(cls)));
+    }
+
+    private final Set<Class<?>> blacklisted = Sets.newConcurrentHashSet();
+
+    private DomainObject readMetadata(final Class<?> domainClass) {
+
+        if(blacklisted.contains(domainClass)) {
+            return null;
+        }
+        final String xml;
+
+        final String resourceName = domainClass.getSimpleName() + ".layout.xml";
+        try {
+            xml = ClassExtensions.resourceContentOf(domainClass, resourceName);
+        } catch (IOException | IllegalArgumentException ex) {
+
+            blacklisted.add(domainClass);
+            final String message = String .format(
+                    "Failed to locate file %s (relative to %s.class); ex: %s)",
+                    resourceName, domainClass.getName(), ex.getMessage());
+
+            LOG.debug(message);
+            return null;
+        }
+
+        try {
+            final JaxbService jaxbService = servicesInjector.lookupService(JaxbService.class);
+            final DomainObject metadata = jaxbService.fromXml(DomainObject.class, xml);
+            return metadata;
+        } catch(Exception ex) {
+
+            // note that we don't blacklist if the file exists but couldn't be parsed;
+            // the developer might fix so we will want to retry.
+            final String message = "Failed to parse " + resourceName + " file (" + ex.getMessage() + ")";
+            LOG.warn(message);
+
+            return null;
+        }
+    }
+
+    private ServicesInjector servicesInjector;
+
+    @Override
+    public void setServicesInjector(final ServicesInjector servicesInjector) {
+        this.servicesInjector = servicesInjector;
+    }
+
+}

http://git-wip-us.apache.org/repos/asf/isis/blob/ea9204f1/core/metamodel/src/main/java/org/apache/isis/progmodels/dflt/ProgrammingModelFacetsJava5.java
----------------------------------------------------------------------
diff --git a/core/metamodel/src/main/java/org/apache/isis/progmodels/dflt/ProgrammingModelFacetsJava5.java b/core/metamodel/src/main/java/org/apache/isis/progmodels/dflt/ProgrammingModelFacetsJava5.java
index 621b75b..9fc19be 100644
--- a/core/metamodel/src/main/java/org/apache/isis/progmodels/dflt/ProgrammingModelFacetsJava5.java
+++ b/core/metamodel/src/main/java/org/apache/isis/progmodels/dflt/ProgrammingModelFacetsJava5.java
@@ -82,7 +82,7 @@ import org.apache.isis.core.metamodel.facets.object.disabled.method.DisabledObje
 import org.apache.isis.core.metamodel.facets.object.domainobject.DomainObjectAnnotationFacetFactory;
 import org.apache.isis.core.metamodel.facets.object.domainobjectlayout.DomainObjectLayoutFacetFactory;
 import org.apache.isis.core.metamodel.facets.object.domainservice.annotation.DomainServiceFacetAnnotationFactory;
-import org.apache.isis.core.metamodel.facets.object.domainservicelayout.DomainServiceLayoutFactory;
+import org.apache.isis.core.metamodel.facets.object.domainservicelayout.DomainServiceLayoutFacetFactory;
 import org.apache.isis.core.metamodel.facets.object.encodeable.annotcfg.EncodableFacetAnnotationElseConfigurationFactory;
 import org.apache.isis.core.metamodel.facets.object.facets.annotation.FacetsFacetAnnotationFactory;
 import org.apache.isis.core.metamodel.facets.object.fieldorder.annotation.FieldOrderFacetAnnotationFactory;
@@ -108,6 +108,7 @@ import org.apache.isis.core.metamodel.facets.object.ignore.jdo.RemoveJdoEnhancem
 import org.apache.isis.core.metamodel.facets.object.ignore.jdo.RemoveJdoPrefixedMethodsFacetFactory;
 import org.apache.isis.core.metamodel.facets.object.immutable.immutableannot.CopyImmutableFacetOntoMembersFactory;
 import org.apache.isis.core.metamodel.facets.object.immutable.immutablemarkerifc.ImmutableFacetMarkerInterfaceFactory;
+import org.apache.isis.core.metamodel.facets.object.layoutxml.LayoutXmlFacetFactory;
 import org.apache.isis.core.metamodel.facets.object.mask.annotation.MaskFacetOnTypeAnnotationFactory;
 import org.apache.isis.core.metamodel.facets.object.maxlen.annotation.MaxLengthFacetOnTypeAnnotationFactory;
 import org.apache.isis.core.metamodel.facets.object.membergroups.annotprop.MemberGroupLayoutFacetFactory;
@@ -390,7 +391,9 @@ public final class ProgrammingModelFacetsJava5 extends ProgrammingModelAbstract
         // must come after DomainObjectAnnotationFacetFactory & MixinFacetFactory
         addFactory(NotContributedFacetDerivedFromMixinFacetFactory.class);
 
-        addFactory(DomainServiceLayoutFactory.class);
+        addFactory(LayoutXmlFacetFactory.class);
+
+        addFactory(DomainServiceLayoutFacetFactory.class);
         addFactory(DomainObjectLayoutFacetFactory.class);
         // must come after MultiLine
         addFactory(PropertyLayoutFacetFactory.class);

http://git-wip-us.apache.org/repos/asf/isis/blob/ea9204f1/core/metamodel/src/test/java/org/apache/isis/core/metamodel/facets/object/domainservicelayout/annotation/DomainServiceLayoutFacetFactoryTest.java
----------------------------------------------------------------------
diff --git a/core/metamodel/src/test/java/org/apache/isis/core/metamodel/facets/object/domainservicelayout/annotation/DomainServiceLayoutFacetFactoryTest.java b/core/metamodel/src/test/java/org/apache/isis/core/metamodel/facets/object/domainservicelayout/annotation/DomainServiceLayoutFacetFactoryTest.java
new file mode 100644
index 0000000..4460313
--- /dev/null
+++ b/core/metamodel/src/test/java/org/apache/isis/core/metamodel/facets/object/domainservicelayout/annotation/DomainServiceLayoutFacetFactoryTest.java
@@ -0,0 +1,129 @@
+/*
+ *  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.metamodel.facets.object.domainservicelayout.annotation;
+
+import org.junit.Assert;
+import org.apache.isis.applib.annotation.DomainService;
+import org.apache.isis.applib.annotation.DomainServiceLayout;
+import org.apache.isis.core.metamodel.facetapi.Facet;
+import org.apache.isis.core.metamodel.facets.AbstractFacetFactoryTest;
+import org.apache.isis.core.metamodel.facets.FacetFactory.ProcessClassContext;
+import org.apache.isis.core.metamodel.facets.object.domainservicelayout.DomainServiceLayoutFacet;
+import org.apache.isis.core.metamodel.facets.object.domainservicelayout.DomainServiceLayoutFacetFactory;
+
+import static org.hamcrest.Matchers.is;
+
+public class DomainServiceLayoutFacetFactoryTest extends AbstractFacetFactoryTest {
+
+    private DomainServiceLayoutFacetFactory facetFactory;
+
+    @Override
+    protected void setUp() throws Exception {
+        super.setUp();
+
+        facetFactory = new DomainServiceLayoutFacetFactory();
+    }
+
+    @Override
+    protected void tearDown() throws Exception {
+        facetFactory = null;
+        super.tearDown();
+    }
+
+    public void testAnnotationPickedUpOnClass() {
+        class Customer {
+        }
+        @DomainServiceLayout(menuOrder = "123" ,menuBar = DomainServiceLayout.MenuBar.SECONDARY)
+        class Customers {
+        }
+
+        facetFactory.process(new ProcessClassContext(Customers.class, null, methodRemover, facetHolder));
+
+        final Facet facet = facetHolder.getFacet(DomainServiceLayoutFacet.class);
+        assertNotNull(facet);
+        assertTrue(facet instanceof DomainServiceLayoutFacetAnnotation);
+        DomainServiceLayoutFacetAnnotation domainServiceLayoutFacet = (DomainServiceLayoutFacetAnnotation) facet;
+        Assert.assertThat(domainServiceLayoutFacet.getMenuOrder(), is("123"));
+        Assert.assertThat(domainServiceLayoutFacet.getMenuBar(), is(DomainServiceLayout.MenuBar.SECONDARY));
+
+        assertNoMethodsRemoved();
+    }
+
+
+    public void testDomainServiceMenuOrderAnnotationPickedUpOnClass() {
+        class Customer {
+        }
+        @DomainService(menuOrder = "123")
+        class Customers {
+        }
+
+        facetFactory.process(new ProcessClassContext(Customers.class, null, methodRemover, facetHolder));
+
+        final Facet facet = facetHolder.getFacet(DomainServiceLayoutFacet.class);
+        assertNotNull(facet);
+        assertTrue(facet instanceof DomainServiceLayoutFacetAnnotation);
+        DomainServiceLayoutFacetAnnotation domainServiceLayoutFacet = (DomainServiceLayoutFacetAnnotation) facet;
+        Assert.assertThat(domainServiceLayoutFacet.getMenuOrder(), is("123"));
+
+        assertNoMethodsRemoved();
+    }
+
+    public void testDomainServiceAndDomainServiceLayoutAnnotationWhenCompatiblePickedUpOnClass() {
+        class Customer {
+        }
+        @DomainService(menuOrder = "123")
+        @DomainServiceLayout(menuBar = DomainServiceLayout.MenuBar.SECONDARY)
+        class Customers {
+        }
+
+        facetFactory.process(new ProcessClassContext(Customers.class, null, methodRemover, facetHolder));
+
+        final Facet facet = facetHolder.getFacet(DomainServiceLayoutFacet.class);
+        assertNotNull(facet);
+        assertTrue(facet instanceof DomainServiceLayoutFacetAnnotation);
+        DomainServiceLayoutFacetAnnotation domainServiceLayoutFacet = (DomainServiceLayoutFacetAnnotation) facet;
+        Assert.assertThat(domainServiceLayoutFacet.getMenuOrder(), is("123"));
+        Assert.assertThat(domainServiceLayoutFacet.getMenuBar(), is(DomainServiceLayout.MenuBar.SECONDARY));
+
+        assertNoMethodsRemoved();
+    }
+
+    public void testDomainServiceAndDomainServiceLayoutAnnotationWhenIncompatiblePickedUpOnClass() {
+        class Customer {
+        }
+        @DomainService(menuOrder = "1")
+        @DomainServiceLayout(menuOrder = "123", menuBar = DomainServiceLayout.MenuBar.SECONDARY)
+        class Customers {
+        }
+
+        facetFactory.process(new ProcessClassContext(Customers.class, null, methodRemover, facetHolder));
+
+        final Facet facet = facetHolder.getFacet(DomainServiceLayoutFacet.class);
+        assertNotNull(facet);
+        assertTrue(facet instanceof DomainServiceLayoutFacetAnnotation);
+        DomainServiceLayoutFacetAnnotation domainServiceLayoutFacet = (DomainServiceLayoutFacetAnnotation) facet;
+        Assert.assertThat(domainServiceLayoutFacet.getMenuOrder(), is("123"));
+        Assert.assertThat(domainServiceLayoutFacet.getMenuBar(), is(DomainServiceLayout.MenuBar.SECONDARY));
+
+        assertNoMethodsRemoved();
+    }
+
+
+}

http://git-wip-us.apache.org/repos/asf/isis/blob/ea9204f1/core/metamodel/src/test/java/org/apache/isis/core/metamodel/facets/object/domainservicelayout/annotation/DomainServiceLayoutFactoryTest.java
----------------------------------------------------------------------
diff --git a/core/metamodel/src/test/java/org/apache/isis/core/metamodel/facets/object/domainservicelayout/annotation/DomainServiceLayoutFactoryTest.java b/core/metamodel/src/test/java/org/apache/isis/core/metamodel/facets/object/domainservicelayout/annotation/DomainServiceLayoutFactoryTest.java
deleted file mode 100644
index 6a65145..0000000
--- a/core/metamodel/src/test/java/org/apache/isis/core/metamodel/facets/object/domainservicelayout/annotation/DomainServiceLayoutFactoryTest.java
+++ /dev/null
@@ -1,129 +0,0 @@
-/*
- *  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.metamodel.facets.object.domainservicelayout.annotation;
-
-import org.junit.Assert;
-import org.apache.isis.applib.annotation.DomainService;
-import org.apache.isis.applib.annotation.DomainServiceLayout;
-import org.apache.isis.core.metamodel.facetapi.Facet;
-import org.apache.isis.core.metamodel.facets.AbstractFacetFactoryTest;
-import org.apache.isis.core.metamodel.facets.FacetFactory.ProcessClassContext;
-import org.apache.isis.core.metamodel.facets.object.domainservicelayout.DomainServiceLayoutFacet;
-import org.apache.isis.core.metamodel.facets.object.domainservicelayout.DomainServiceLayoutFactory;
-
-import static org.hamcrest.Matchers.is;
-
-public class DomainServiceLayoutFactoryTest extends AbstractFacetFactoryTest {
-
-    private DomainServiceLayoutFactory facetFactory;
-
-    @Override
-    protected void setUp() throws Exception {
-        super.setUp();
-
-        facetFactory = new DomainServiceLayoutFactory();
-    }
-
-    @Override
-    protected void tearDown() throws Exception {
-        facetFactory = null;
-        super.tearDown();
-    }
-
-    public void testAnnotationPickedUpOnClass() {
-        class Customer {
-        }
-        @DomainServiceLayout(menuOrder = "123" ,menuBar = DomainServiceLayout.MenuBar.SECONDARY)
-        class Customers {
-        }
-
-        facetFactory.process(new ProcessClassContext(Customers.class, null, methodRemover, facetHolder));
-
-        final Facet facet = facetHolder.getFacet(DomainServiceLayoutFacet.class);
-        assertNotNull(facet);
-        assertTrue(facet instanceof DomainServiceLayoutFacetAnnotation);
-        DomainServiceLayoutFacetAnnotation domainServiceLayoutFacet = (DomainServiceLayoutFacetAnnotation) facet;
-        Assert.assertThat(domainServiceLayoutFacet.getMenuOrder(), is("123"));
-        Assert.assertThat(domainServiceLayoutFacet.getMenuBar(), is(DomainServiceLayout.MenuBar.SECONDARY));
-
-        assertNoMethodsRemoved();
-    }
-
-
-    public void testDomainServiceMenuOrderAnnotationPickedUpOnClass() {
-        class Customer {
-        }
-        @DomainService(menuOrder = "123")
-        class Customers {
-        }
-
-        facetFactory.process(new ProcessClassContext(Customers.class, null, methodRemover, facetHolder));
-
-        final Facet facet = facetHolder.getFacet(DomainServiceLayoutFacet.class);
-        assertNotNull(facet);
-        assertTrue(facet instanceof DomainServiceLayoutFacetAnnotation);
-        DomainServiceLayoutFacetAnnotation domainServiceLayoutFacet = (DomainServiceLayoutFacetAnnotation) facet;
-        Assert.assertThat(domainServiceLayoutFacet.getMenuOrder(), is("123"));
-
-        assertNoMethodsRemoved();
-    }
-
-    public void testDomainServiceAndDomainServiceLayoutAnnotationWhenCompatiblePickedUpOnClass() {
-        class Customer {
-        }
-        @DomainService(menuOrder = "123")
-        @DomainServiceLayout(menuBar = DomainServiceLayout.MenuBar.SECONDARY)
-        class Customers {
-        }
-
-        facetFactory.process(new ProcessClassContext(Customers.class, null, methodRemover, facetHolder));
-
-        final Facet facet = facetHolder.getFacet(DomainServiceLayoutFacet.class);
-        assertNotNull(facet);
-        assertTrue(facet instanceof DomainServiceLayoutFacetAnnotation);
-        DomainServiceLayoutFacetAnnotation domainServiceLayoutFacet = (DomainServiceLayoutFacetAnnotation) facet;
-        Assert.assertThat(domainServiceLayoutFacet.getMenuOrder(), is("123"));
-        Assert.assertThat(domainServiceLayoutFacet.getMenuBar(), is(DomainServiceLayout.MenuBar.SECONDARY));
-
-        assertNoMethodsRemoved();
-    }
-
-    public void testDomainServiceAndDomainServiceLayoutAnnotationWhenIncompatiblePickedUpOnClass() {
-        class Customer {
-        }
-        @DomainService(menuOrder = "1")
-        @DomainServiceLayout(menuOrder = "123", menuBar = DomainServiceLayout.MenuBar.SECONDARY)
-        class Customers {
-        }
-
-        facetFactory.process(new ProcessClassContext(Customers.class, null, methodRemover, facetHolder));
-
-        final Facet facet = facetHolder.getFacet(DomainServiceLayoutFacet.class);
-        assertNotNull(facet);
-        assertTrue(facet instanceof DomainServiceLayoutFacetAnnotation);
-        DomainServiceLayoutFacetAnnotation domainServiceLayoutFacet = (DomainServiceLayoutFacetAnnotation) facet;
-        Assert.assertThat(domainServiceLayoutFacet.getMenuOrder(), is("123"));
-        Assert.assertThat(domainServiceLayoutFacet.getMenuBar(), is(DomainServiceLayout.MenuBar.SECONDARY));
-
-        assertNoMethodsRemoved();
-    }
-
-
-}

http://git-wip-us.apache.org/repos/asf/isis/blob/ea9204f1/core/metamodel/src/test/java/org/apache/isis/core/metamodel/layoutxml/v1_0/DomainObjectTest.java
----------------------------------------------------------------------
diff --git a/core/metamodel/src/test/java/org/apache/isis/core/metamodel/layoutxml/v1_0/DomainObjectTest.java b/core/metamodel/src/test/java/org/apache/isis/core/metamodel/layoutxml/v1_0/DomainObjectTest.java
new file mode 100644
index 0000000..070f094
--- /dev/null
+++ b/core/metamodel/src/test/java/org/apache/isis/core/metamodel/layoutxml/v1_0/DomainObjectTest.java
@@ -0,0 +1,101 @@
+/*
+ *  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.metamodel.layoutxml.v1_0;
+
+import java.util.Map;
+
+import javax.xml.bind.Marshaller;
+
+import com.google.common.collect.ImmutableMap;
+
+import org.junit.After;
+import org.junit.Before;
+import org.junit.Test;
+
+import org.apache.isis.applib.layout.v1_0.Action;
+import org.apache.isis.applib.layout.v1_0.Column;
+import org.apache.isis.applib.layout.v1_0.DomainObject;
+import org.apache.isis.applib.layout.v1_0.Property;
+import org.apache.isis.applib.layout.v1_0.PropertyGroup;
+import org.apache.isis.applib.layout.v1_0.Tab;
+import org.apache.isis.applib.layout.v1_0.TabGroup;
+import org.apache.isis.applib.services.jaxb.JaxbService;
+
+public class DomainObjectTest {
+
+    private JaxbService jaxbService;
+
+    @Before
+    public void setUp() throws Exception {
+        jaxbService = new JaxbService.Simple();
+    }
+
+    @After
+    public void tearDown() throws Exception {
+
+    }
+
+    @Test
+    public void xxx() throws Exception {
+
+        final DomainObject domainObject = new DomainObject();
+
+        TabGroup tabGroup = domainObject.getTabGroups().get(0);
+        Tab tab = tabGroup.getTabs().get(0);
+        Column left = tab.getLeft();
+
+        PropertyGroup leftPropGroup = new PropertyGroup();
+        left.getPropertyGroups().add(leftPropGroup);
+
+        leftPropGroup.setName("General");
+
+        Property nameProperty = leftPropGroup.getProperties().get(0);
+
+        nameProperty.setIdentifier("name");
+
+        Action updateNameAction = new Action();
+        updateNameAction.setIdentifier("updateName");
+        nameProperty.getActions().add(updateNameAction);
+
+        Action deleteAction = new Action();
+        deleteAction.setIdentifier("delete");
+        domainObject.getActions().add(deleteAction);
+
+        String xml = jaxbService.toXml(domainObject,
+                ImmutableMap.<String,Object>of(
+                        Marshaller.JAXB_SCHEMA_LOCATION,
+                        "http://isis.apache.org/schema/applib/layout http://isis.apache.org/schema/applib/layout/layout-1.0.xsd"
+                ));
+        System.out.println(xml);
+
+        jaxbService.fromXml(DomainObject.class, xml);
+
+        System.out.println("==========");
+
+        dumpXsd(domainObject);
+    }
+
+    protected void dumpXsd(final DomainObject domainObject) {
+        Map<String, String> schemas = jaxbService.toXsd(domainObject, JaxbService.IsisSchemas.INCLUDE);
+        for (Map.Entry<String, String> entry : schemas.entrySet()) {
+            System.out.println(entry.getKey() + ":");
+            System.out.println(entry.getValue());
+        }
+    }
+}
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/isis/blob/ea9204f1/core/schema/src/main/java/org/apache/isis/schema/services/jaxb/CatalogingSchemaOutputResolver.java
----------------------------------------------------------------------
diff --git a/core/schema/src/main/java/org/apache/isis/schema/services/jaxb/CatalogingSchemaOutputResolver.java b/core/schema/src/main/java/org/apache/isis/schema/services/jaxb/CatalogingSchemaOutputResolver.java
deleted file mode 100644
index aac43d7..0000000
--- a/core/schema/src/main/java/org/apache/isis/schema/services/jaxb/CatalogingSchemaOutputResolver.java
+++ /dev/null
@@ -1,85 +0,0 @@
-/**
- *  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.schema.services.jaxb;
-
-import java.io.IOException;
-import java.util.Collections;
-import java.util.List;
-import java.util.Map;
-
-import javax.xml.bind.SchemaOutputResolver;
-import javax.xml.transform.Result;
-import javax.xml.transform.stream.StreamResult;
-
-import com.google.common.collect.Lists;
-import com.google.common.collect.Maps;
-
-import org.apache.isis.applib.services.jaxb.JaxbService;
-
-/**
- * An implementation of {@link SchemaOutputResolver} that keeps track of all the schemas for which it has
- * {@link #createOutput(String, String) created} an output {@link StreamResult} containing the content of the schema.
- */
-class CatalogingSchemaOutputResolver extends SchemaOutputResolver
-{
-    private final JaxbService.IsisSchemas isisSchemas;
-    private List<String> namespaceUris = Lists.newArrayList();
-
-    public CatalogingSchemaOutputResolver(final JaxbService.IsisSchemas isisSchemas) {
-        this.isisSchemas = isisSchemas;
-    }
-
-    public List<String> getNamespaceUris() {
-        return namespaceUris;
-    }
-
-    private Map<String, StreamResultWithWriter> schemaResultByNamespaceUri = Maps.newLinkedHashMap();
-
-    public String getSchemaTextFor(final String namespaceUri) {
-        final StreamResultWithWriter streamResult = schemaResultByNamespaceUri.get(namespaceUri);
-        return streamResult != null? streamResult.asString(): null;
-    }
-
-    @Override
-    public Result createOutput(
-            final String namespaceUri, final String suggestedFileName) throws IOException {
-
-        final StreamResultWithWriter result = new StreamResultWithWriter();
-
-        result.setSystemId(namespaceUri);
-
-        if (isisSchemas.shouldIgnore(namespaceUri)) {
-            // skip
-        } else {
-            namespaceUris.add(namespaceUri);
-            schemaResultByNamespaceUri.put(namespaceUri, result);
-        }
-
-        return result;
-    }
-
-    public Map<String, String> asMap() {
-        final Map<String,String> map = Maps.newLinkedHashMap();
-        final List<String> namespaceUris = getNamespaceUris();
-
-        for (String namespaceUri : namespaceUris) {
-            map.put(namespaceUri, getSchemaTextFor(namespaceUri));
-        }
-
-        return Collections.unmodifiableMap(map);
-    }
-}

http://git-wip-us.apache.org/repos/asf/isis/blob/ea9204f1/core/schema/src/main/java/org/apache/isis/schema/services/jaxb/JaxbServiceDefault.java
----------------------------------------------------------------------
diff --git a/core/schema/src/main/java/org/apache/isis/schema/services/jaxb/JaxbServiceDefault.java b/core/schema/src/main/java/org/apache/isis/schema/services/jaxb/JaxbServiceDefault.java
index 2d2bf79..3679fdb 100644
--- a/core/schema/src/main/java/org/apache/isis/schema/services/jaxb/JaxbServiceDefault.java
+++ b/core/schema/src/main/java/org/apache/isis/schema/services/jaxb/JaxbServiceDefault.java
@@ -16,26 +16,11 @@
  */
 package org.apache.isis.schema.services.jaxb;
 
-import java.io.IOException;
-import java.io.StringReader;
-import java.io.StringWriter;
-import java.lang.reflect.Method;
-import java.util.List;
-import java.util.Map;
-
 import javax.inject.Inject;
-import javax.xml.bind.JAXBContext;
-import javax.xml.bind.JAXBException;
 import javax.xml.bind.Marshaller;
 import javax.xml.bind.Unmarshaller;
 
-import com.google.common.base.Function;
-import com.google.common.base.Joiner;
-import com.google.common.collect.Iterables;
-
-import org.apache.isis.applib.ApplicationException;
 import org.apache.isis.applib.DomainObjectContainer;
-import org.apache.isis.applib.NonRecoverableException;
 import org.apache.isis.applib.annotation.DomainService;
 import org.apache.isis.applib.annotation.NatureOfService;
 import org.apache.isis.applib.services.jaxb.JaxbService;
@@ -44,98 +29,20 @@ import org.apache.isis.schema.utils.jaxbadapters.PersistentEntityAdapter;
 @DomainService(
         nature = NatureOfService.DOMAIN
 )
-public class JaxbServiceDefault implements JaxbService {
-
-    @Override
-    public <T> T fromXml(final Class<T> domainClass, final String xml) {
-        try {
-            final JAXBContext context = JAXBContext.newInstance(domainClass);
-
-            final PersistentEntityAdapter adapter = new PersistentEntityAdapter();
-            container.injectServicesInto(adapter);
-
-            final Unmarshaller unmarshaller = context.createUnmarshaller();
-            unmarshaller.setAdapter(PersistentEntityAdapter.class, adapter);
-
-            final Object unmarshal = unmarshaller.unmarshal(new StringReader(xml));
-            return (T) unmarshal;
-
-        } catch (final JAXBException ex) {
-            throw new NonRecoverableException("Error unmarshalling domain object from XML; domain object class is '" + domainClass.getName() + "'", ex);
-        }
-    }
-
-    @Override
-    public String toXml(final Object domainObject)  {
-
-        final Class<?> domainClass = domainObject.getClass();
-        try {
-            final JAXBContext context = JAXBContext.newInstance(domainClass);
+public class JaxbServiceDefault extends JaxbService.Simple {
 
-            final PersistentEntityAdapter adapter = new PersistentEntityAdapter();
-            container.injectServicesInto(adapter);
-
-            final Marshaller marshaller = context.createMarshaller();
-            marshaller.setAdapter(PersistentEntityAdapter.class, adapter);
-            marshaller.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT, true);
-
-            final StringWriter sw = new StringWriter();
-            marshaller.marshal(domainObject, sw);
-            final String xml = sw.toString();
-
-            return xml;
-
-        } catch (final JAXBException ex) {
-            final Class<? extends JAXBException> exClass = ex.getClass();
-
-            final String name = exClass.getName();
-            if(name.equals("com.sun.xml.bind.v2.runtime.IllegalAnnotationsException")) {
-                // report a better error if possible
-                // this is done reflectively so as to not have to bring in a new Maven dependency
-                List<? extends Exception> errors = null;
-                String annotationExceptionMessages = null;
-                try {
-                    final Method getErrorsMethod = exClass.getMethod("getErrors");
-                    errors = (List<? extends Exception>) getErrorsMethod.invoke(ex);
-                    annotationExceptionMessages = ": " + Joiner.on("; ").join(
-                            Iterables.transform(errors, new Function<Exception, String>() {
-                                @Override public String apply(final Exception e) {
-                                    return e.getMessage();
-                                }
-                            }));
-                } catch (Exception e) {
-                    // fall through if we hit any snags, and instead throw the more generic error message.
-                }
-                if(errors != null) {
-                    throw new NonRecoverableException(
-                            "Error marshalling domain object to XML, due to illegal annotations on domain object class '"
-                                    + domainClass.getName() + "'; " + errors.size() + " error"
-                                    + (errors.size() == 1? "": "s")
-                                    + " reported" + (!errors
-                                    .isEmpty() ? annotationExceptionMessages : ""), ex);
-                }
-            }
-
-            throw new NonRecoverableException("Error marshalling domain object to XML; domain object class is '" + domainClass.getName() + "'", ex);
-        }
+    protected void configure(final Unmarshaller unmarshaller) {
+        final PersistentEntityAdapter adapter = new PersistentEntityAdapter();
+        container.injectServicesInto(adapter);
+        unmarshaller.setAdapter(PersistentEntityAdapter.class, adapter);
     }
 
-    public Map<String,String> toXsd(final Object domainObject, final IsisSchemas isisSchemas) {
-
-        try {
-            final Class<?> domainClass = domainObject.getClass();
-            final JAXBContext context = JAXBContext.newInstance(domainClass);
-
-            final CatalogingSchemaOutputResolver outputResolver = new CatalogingSchemaOutputResolver(isisSchemas);
-            context.generateSchema(outputResolver);
-
-            return outputResolver.asMap();
-        } catch (final JAXBException | IOException ex) {
-            throw new ApplicationException(ex);
-        }
+    protected void configure(final Marshaller marshaller) {
+        final PersistentEntityAdapter adapter = new PersistentEntityAdapter();
+        container.injectServicesInto(adapter);
+        marshaller.setAdapter(PersistentEntityAdapter.class, adapter);
     }
 
-
     @Inject
     DomainObjectContainer container;
 }

http://git-wip-us.apache.org/repos/asf/isis/blob/ea9204f1/core/schema/src/main/java/org/apache/isis/schema/services/jaxb/StreamResultWithWriter.java
----------------------------------------------------------------------
diff --git a/core/schema/src/main/java/org/apache/isis/schema/services/jaxb/StreamResultWithWriter.java b/core/schema/src/main/java/org/apache/isis/schema/services/jaxb/StreamResultWithWriter.java
deleted file mode 100644
index c07b49b..0000000
--- a/core/schema/src/main/java/org/apache/isis/schema/services/jaxb/StreamResultWithWriter.java
+++ /dev/null
@@ -1,45 +0,0 @@
-/**
- *  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.schema.services.jaxb;
-
-import java.io.StringWriter;
-
-import javax.xml.transform.stream.StreamResult;
-
-/**
- * A {@link StreamResult} that contains its own writer.
- *
- * <p>
- *     The point is that the writer is only ever queried lazily AFTER the result has been generated.
- * </p>
- */
-class StreamResultWithWriter extends StreamResult {
-    private final StringWriter writer;
-
-    public StreamResultWithWriter() {
-        this(new StringWriter());
-    }
-
-    private StreamResultWithWriter(StringWriter writer) {
-        super(writer);
-        this.writer = writer;
-    }
-
-    public String asString() {
-        return writer.toString();
-    }
-}

http://git-wip-us.apache.org/repos/asf/isis/blob/ea9204f1/core/viewer-wicket-impl/src/main/java/org/apache/isis/viewer/wicket/viewer/registries/components/ComponentFactoryRegistrarDefault.java
----------------------------------------------------------------------
diff --git a/core/viewer-wicket-impl/src/main/java/org/apache/isis/viewer/wicket/viewer/registries/components/ComponentFactoryRegistrarDefault.java b/core/viewer-wicket-impl/src/main/java/org/apache/isis/viewer/wicket/viewer/registries/components/ComponentFactoryRegistrarDefault.java
index 479b474..f82698f 100644
--- a/core/viewer-wicket-impl/src/main/java/org/apache/isis/viewer/wicket/viewer/registries/components/ComponentFactoryRegistrarDefault.java
+++ b/core/viewer-wicket-impl/src/main/java/org/apache/isis/viewer/wicket/viewer/registries/components/ComponentFactoryRegistrarDefault.java
@@ -20,16 +20,18 @@
 package org.apache.isis.viewer.wicket.viewer.registries.components;
 
 import java.util.ServiceLoader;
+
 import com.google.inject.Singleton;
+
 import org.apache.isis.viewer.wicket.ui.ComponentFactory;
 import org.apache.isis.viewer.wicket.ui.app.registry.ComponentFactoryRegistrar;
 import org.apache.isis.viewer.wicket.ui.components.about.AboutPanelFactory;
 import org.apache.isis.viewer.wicket.ui.components.actionlink.ActionLinkPanelFactory;
+import org.apache.isis.viewer.wicket.ui.components.actionmenu.serviceactions.ServiceActionsPanelFactory;
 import org.apache.isis.viewer.wicket.ui.components.actionmenu.serviceactions.TertiaryMenuPanelFactory;
 import org.apache.isis.viewer.wicket.ui.components.actions.ActionInfoPanelFactory;
 import org.apache.isis.viewer.wicket.ui.components.actions.ActionPanelFactory;
 import org.apache.isis.viewer.wicket.ui.components.actions.ActionParametersFormPanelFactory;
-import org.apache.isis.viewer.wicket.ui.components.actionmenu.serviceactions.ServiceActionsPanelFactory;
 import org.apache.isis.viewer.wicket.ui.components.bookmarkedpages.BookmarkedPagesPanelFactory;
 import org.apache.isis.viewer.wicket.ui.components.collection.CollectionPanelFactory;
 import org.apache.isis.viewer.wicket.ui.components.collectioncontents.ajaxtable.CollectionContentsAsAjaxTablePanelFactory;
@@ -44,9 +46,19 @@ import org.apache.isis.viewer.wicket.ui.components.entity.icontitle.EntityIconAn
 import org.apache.isis.viewer.wicket.ui.components.entity.icontitle.EntityIconTitleAndCopyLinkPanelFactory;
 import org.apache.isis.viewer.wicket.ui.components.entity.properties.EntityPropertiesPanelFactory;
 import org.apache.isis.viewer.wicket.ui.components.entity.selector.links.EntityLinksSelectorPanelFactory;
+import org.apache.isis.viewer.wicket.ui.components.entity.tabbed.EntityTabbedPanelFactory;
 import org.apache.isis.viewer.wicket.ui.components.footer.FooterPanelFactory;
 import org.apache.isis.viewer.wicket.ui.components.header.HeaderPanelFactory;
-import org.apache.isis.viewer.wicket.ui.components.scalars.isisapplib.*;
+import org.apache.isis.viewer.wicket.ui.components.scalars.isisapplib.IsisBlobPanelFactory;
+import org.apache.isis.viewer.wicket.ui.components.scalars.isisapplib.IsisClobPanelFactory;
+import org.apache.isis.viewer.wicket.ui.components.scalars.isisapplib.IsisColorPanelFactory;
+import org.apache.isis.viewer.wicket.ui.components.scalars.isisapplib.IsisDatePanelFactory;
+import org.apache.isis.viewer.wicket.ui.components.scalars.isisapplib.IsisDateTimePanelFactory;
+import org.apache.isis.viewer.wicket.ui.components.scalars.isisapplib.IsisMoneyPanelFactory;
+import org.apache.isis.viewer.wicket.ui.components.scalars.isisapplib.IsisPasswordPanelFactory;
+import org.apache.isis.viewer.wicket.ui.components.scalars.isisapplib.IsisPercentagePanelFactory;
+import org.apache.isis.viewer.wicket.ui.components.scalars.isisapplib.IsisTimePanelFactory;
+import org.apache.isis.viewer.wicket.ui.components.scalars.isisapplib.IsisTimeStampPanelFactory;
 import org.apache.isis.viewer.wicket.ui.components.scalars.jdkdates.JavaSqlDatePanelFactory;
 import org.apache.isis.viewer.wicket.ui.components.scalars.jdkdates.JavaSqlTimePanelFactory;
 import org.apache.isis.viewer.wicket.ui.components.scalars.jdkdates.JavaSqlTimestampPanelFactory;
@@ -56,7 +68,14 @@ import org.apache.isis.viewer.wicket.ui.components.scalars.jdkmath.JavaMathBigIn
 import org.apache.isis.viewer.wicket.ui.components.scalars.jodatime.JodaDateTimePanelFactory;
 import org.apache.isis.viewer.wicket.ui.components.scalars.jodatime.JodaLocalDatePanelFactory;
 import org.apache.isis.viewer.wicket.ui.components.scalars.jodatime.JodaLocalDateTimePanelFactory;
-import org.apache.isis.viewer.wicket.ui.components.scalars.primitive.*;
+import org.apache.isis.viewer.wicket.ui.components.scalars.primitive.BooleanPanelFactory;
+import org.apache.isis.viewer.wicket.ui.components.scalars.primitive.BytePanelFactory;
+import org.apache.isis.viewer.wicket.ui.components.scalars.primitive.CharacterPanelFactory;
+import org.apache.isis.viewer.wicket.ui.components.scalars.primitive.DoublePanelFactory;
+import org.apache.isis.viewer.wicket.ui.components.scalars.primitive.FloatPanelFactory;
+import org.apache.isis.viewer.wicket.ui.components.scalars.primitive.IntegerPanelFactory;
+import org.apache.isis.viewer.wicket.ui.components.scalars.primitive.LongPanelFactory;
+import org.apache.isis.viewer.wicket.ui.components.scalars.primitive.ShortPanelFactory;
 import org.apache.isis.viewer.wicket.ui.components.scalars.reference.ReferencePanelFactory;
 import org.apache.isis.viewer.wicket.ui.components.scalars.string.StringPanelFactory;
 import org.apache.isis.viewer.wicket.ui.components.scalars.value.ValuePanelFactory;
@@ -149,7 +168,8 @@ public class ComponentFactoryRegistrarDefault implements ComponentFactoryRegistr
 
         // top-level
         componentFactories.add(new EntityCombinedPanelFactory());
-        
+        componentFactories.add(new EntityTabbedPanelFactory()); // last one wins, apparently.
+
         // lower-level
         componentFactories.add(new EntityIconAndTitlePanelFactory());
         componentFactories.add(new EntityIconTitleAndCopyLinkPanelFactory());

http://git-wip-us.apache.org/repos/asf/isis/blob/ea9204f1/core/viewer-wicket-ui/src/main/java/org/apache/isis/viewer/wicket/ui/components/entity/EntityComponentFactoryAbstract.java
----------------------------------------------------------------------
diff --git a/core/viewer-wicket-ui/src/main/java/org/apache/isis/viewer/wicket/ui/components/entity/EntityComponentFactoryAbstract.java b/core/viewer-wicket-ui/src/main/java/org/apache/isis/viewer/wicket/ui/components/entity/EntityComponentFactoryAbstract.java
index 6f7fa36..53ed51d 100644
--- a/core/viewer-wicket-ui/src/main/java/org/apache/isis/viewer/wicket/ui/components/entity/EntityComponentFactoryAbstract.java
+++ b/core/viewer-wicket-ui/src/main/java/org/apache/isis/viewer/wicket/ui/components/entity/EntityComponentFactoryAbstract.java
@@ -65,7 +65,19 @@ public abstract class EntityComponentFactoryAbstract extends ComponentFactoryAbs
         final ObjectSpecification specification = entityModel.getTypeOfSpecification();
         final boolean isObject = specification.isNotCollection();
         final boolean isValue = specification.containsFacet(ValueFacet.class);
-        return appliesIf(isObject && !isValue);
+        boolean b = isObject && !isValue;
+        if (!b) {
+            return ApplicationAdvice.DOES_NOT_APPLY;
+        }
+
+        return doAppliesTo(entityModel);
+    }
+
+    /**
+     * optional hook.
+     */
+    protected ApplicationAdvice doAppliesTo(final EntityModel entityModel) {
+        return ApplicationAdvice.APPLIES;
     }
 
 }

http://git-wip-us.apache.org/repos/asf/isis/blob/ea9204f1/core/viewer-wicket-ui/src/main/java/org/apache/isis/viewer/wicket/ui/components/entity/tabbed/EntityTabbedPanel.html
----------------------------------------------------------------------
diff --git a/core/viewer-wicket-ui/src/main/java/org/apache/isis/viewer/wicket/ui/components/entity/tabbed/EntityTabbedPanel.html b/core/viewer-wicket-ui/src/main/java/org/apache/isis/viewer/wicket/ui/components/entity/tabbed/EntityTabbedPanel.html
new file mode 100644
index 0000000..add01ab
--- /dev/null
+++ b/core/viewer-wicket-ui/src/main/java/org/apache/isis/viewer/wicket/ui/components/entity/tabbed/EntityTabbedPanel.html
@@ -0,0 +1,27 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+  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.
+-->
+<html xmlns:wicket="http://wicket.apache.org">
+<body>
+<wicket:panel>
+	<div class="entityTabbed">
+	</div>
+</wicket:panel>
+</body>
+</html>

http://git-wip-us.apache.org/repos/asf/isis/blob/ea9204f1/core/viewer-wicket-ui/src/main/java/org/apache/isis/viewer/wicket/ui/components/entity/tabbed/EntityTabbedPanel.java
----------------------------------------------------------------------
diff --git a/core/viewer-wicket-ui/src/main/java/org/apache/isis/viewer/wicket/ui/components/entity/tabbed/EntityTabbedPanel.java b/core/viewer-wicket-ui/src/main/java/org/apache/isis/viewer/wicket/ui/components/entity/tabbed/EntityTabbedPanel.java
new file mode 100644
index 0000000..0f23e3b
--- /dev/null
+++ b/core/viewer-wicket-ui/src/main/java/org/apache/isis/viewer/wicket/ui/components/entity/tabbed/EntityTabbedPanel.java
@@ -0,0 +1,59 @@
+/*
+ *  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.viewer.wicket.ui.components.entity.tabbed;
+
+import org.apache.isis.core.metamodel.adapter.ObjectAdapter;
+import org.apache.isis.core.metamodel.facets.members.cssclass.CssClassFacet;
+import org.apache.isis.viewer.wicket.model.models.EntityModel;
+import org.apache.isis.viewer.wicket.ui.panels.PanelAbstract;
+import org.apache.isis.viewer.wicket.ui.util.CssClassAppender;
+
+/**
+ * {@link PanelAbstract Panel} to represent an entity on a single page made up
+ * of several &lt;div&gt; regions.
+ */
+public class EntityTabbedPanel extends PanelAbstract<EntityModel> {
+
+    private static final long serialVersionUID = 1L;
+
+    private static final String ID_ENTITY_PROPERTIES_AND_COLLECTIONS = "entityPropertiesAndCollections";
+
+    
+    public EntityTabbedPanel(final String id, final EntityModel entityModel) {
+        super(id, entityModel);
+        buildGui();
+    }
+
+    private void buildGui() {
+        final EntityModel model = getModel();
+        final ObjectAdapter objectAdapter = model.getObject();
+        final CssClassFacet facet = objectAdapter.getSpecification().getFacet(CssClassFacet.class);
+        if(facet != null) {
+            final String cssClass = facet.cssClass(objectAdapter);
+            CssClassAppender.appendCssClassTo(this, cssClass);
+        }
+
+//        addOrReplace(ComponentType.ENTITY_SUMMARY, model);
+//
+//        getComponentFactoryRegistry().addOrReplaceComponent(this, ID_ENTITY_PROPERTIES_AND_COLLECTIONS, ComponentType.ENTITY_PROPERTIES, model);
+    }
+
+
+}

http://git-wip-us.apache.org/repos/asf/isis/blob/ea9204f1/core/viewer-wicket-ui/src/main/java/org/apache/isis/viewer/wicket/ui/components/entity/tabbed/EntityTabbedPanelFactory.java
----------------------------------------------------------------------
diff --git a/core/viewer-wicket-ui/src/main/java/org/apache/isis/viewer/wicket/ui/components/entity/tabbed/EntityTabbedPanelFactory.java b/core/viewer-wicket-ui/src/main/java/org/apache/isis/viewer/wicket/ui/components/entity/tabbed/EntityTabbedPanelFactory.java
new file mode 100644
index 0000000..db69e65
--- /dev/null
+++ b/core/viewer-wicket-ui/src/main/java/org/apache/isis/viewer/wicket/ui/components/entity/tabbed/EntityTabbedPanelFactory.java
@@ -0,0 +1,56 @@
+/*
+ *  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.viewer.wicket.ui.components.entity.tabbed;
+
+import org.apache.wicket.Component;
+import org.apache.wicket.model.IModel;
+
+import org.apache.isis.core.metamodel.facets.object.layoutxml.LayoutXmlFacet;
+import org.apache.isis.core.metamodel.spec.ObjectSpecification;
+import org.apache.isis.viewer.wicket.model.models.EntityModel;
+import org.apache.isis.viewer.wicket.ui.ComponentFactory;
+import org.apache.isis.viewer.wicket.ui.ComponentType;
+import org.apache.isis.viewer.wicket.ui.components.entity.EntityComponentFactoryAbstract;
+
+/**
+ * {@link ComponentFactory} for {@link EntityTabbedPanel}.
+ */
+public class EntityTabbedPanelFactory extends EntityComponentFactoryAbstract {
+
+    private static final long serialVersionUID = 1L;
+
+    private static final String NAME = "combined";
+
+    public EntityTabbedPanelFactory() {
+        super(ComponentType.ENTITY, NAME, EntityTabbedPanel.class);
+    }
+
+    @Override
+    protected ApplicationAdvice doAppliesTo(final EntityModel entityModel) {
+        final ObjectSpecification specification = entityModel.getTypeOfSpecification();
+        return appliesExclusivelyIf(specification.containsDoOpFacet(LayoutXmlFacet.class));
+    }
+
+    @Override
+    public Component createComponent(final String id, final IModel<?> model) {
+        final EntityModel entityModel = (EntityModel) model;
+        return new EntityTabbedPanel(id, entityModel);
+    }
+}

http://git-wip-us.apache.org/repos/asf/isis/blob/ea9204f1/example/application/simpleapp/dom/src/main/java/domainapp/dom/simple/SimpleObject.layout.xml
----------------------------------------------------------------------
diff --git a/example/application/simpleapp/dom/src/main/java/domainapp/dom/simple/SimpleObject.layout.xml b/example/application/simpleapp/dom/src/main/java/domainapp/dom/simple/SimpleObject.layout.xml
new file mode 100644
index 0000000..6cf4984
--- /dev/null
+++ b/example/application/simpleapp/dom/src/main/java/domainapp/dom/simple/SimpleObject.layout.xml
@@ -0,0 +1,44 @@
+<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
+<domainObject xsi:schemaLocation="http://isis.apache.org/schema/applib/layout http://isis.apache.org/schema/applib/layout/layout-1.0.xsd" xmlns="http://isis.apache.org/schema/applib/layout" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
+    <actions>
+        <action identifier="delete">
+            <layout>
+                <bookmarking>NEVER</bookmarking>
+                <position>BELOW</position>
+            </layout>
+        </action>
+    </actions>
+    <tabGroups>
+        <tabGroup>
+            <tabs>
+                <tab>
+                    <left>
+                        <span>4</span>
+                        <propertyGroups>
+                            <propertyGroup name="General">
+                                <actions/>
+                                <properties>
+                                    <property identifier="name">
+                                        <layout>
+                                            <labelPosition>LEFT</labelPosition>
+                                            <typicalLength>-1</typicalLength>
+                                        </layout>
+                                        <actions>
+                                            <action identifier="updateName">
+                                                <layout>
+                                                    <bookmarking>NEVER</bookmarking>
+                                                    <position>BELOW</position>
+                                                </layout>
+                                            </action>
+                                        </actions>
+                                    </property>
+                                </properties>
+                            </propertyGroup>
+                        </propertyGroups>
+                        <collections/>
+                    </left>
+                </tab>
+            </tabs>
+        </tabGroup>
+    </tabGroups>
+</domainObject>