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/02/08 14:16:19 UTC

[7/24] ISIS-323: lots more refactoring of RO

http://git-wip-us.apache.org/repos/asf/isis/blob/75f41b75/component/viewer/restfulobjects/rendering/src/main/java/org/apache/isis/viewer/restfulobjects/rendering/domainobjects/ObjectAndProperty.java
----------------------------------------------------------------------
diff --git a/component/viewer/restfulobjects/rendering/src/main/java/org/apache/isis/viewer/restfulobjects/rendering/domainobjects/ObjectAndProperty.java b/component/viewer/restfulobjects/rendering/src/main/java/org/apache/isis/viewer/restfulobjects/rendering/domainobjects/ObjectAndProperty.java
new file mode 100644
index 0000000..0b9a236
--- /dev/null
+++ b/component/viewer/restfulobjects/rendering/src/main/java/org/apache/isis/viewer/restfulobjects/rendering/domainobjects/ObjectAndProperty.java
@@ -0,0 +1,30 @@
+/*
+ *  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.restfulobjects.rendering.domainobjects;
+
+import org.apache.isis.core.metamodel.adapter.ObjectAdapter;
+import org.apache.isis.core.metamodel.spec.feature.OneToOneAssociation;
+
+public class ObjectAndProperty extends ObjectAndMember<OneToOneAssociation> {
+
+    public ObjectAndProperty(final ObjectAdapter objectAdapter, final OneToOneAssociation property) {
+        super(objectAdapter, property);
+    }
+
+}
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/isis/blob/75f41b75/component/viewer/restfulobjects/rendering/src/main/java/org/apache/isis/viewer/restfulobjects/rendering/domainobjects/ObjectCollectionReprRenderer.java
----------------------------------------------------------------------
diff --git a/component/viewer/restfulobjects/rendering/src/main/java/org/apache/isis/viewer/restfulobjects/rendering/domainobjects/ObjectCollectionReprRenderer.java b/component/viewer/restfulobjects/rendering/src/main/java/org/apache/isis/viewer/restfulobjects/rendering/domainobjects/ObjectCollectionReprRenderer.java
new file mode 100644
index 0000000..8dd36c9
--- /dev/null
+++ b/component/viewer/restfulobjects/rendering/src/main/java/org/apache/isis/viewer/restfulobjects/rendering/domainobjects/ObjectCollectionReprRenderer.java
@@ -0,0 +1,157 @@
+/**
+ *  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.restfulobjects.rendering.domainobjects;
+
+import java.util.List;
+import java.util.Map;
+
+import org.apache.isis.applib.annotation.Where;
+import org.apache.isis.core.metamodel.adapter.ObjectAdapter;
+import org.apache.isis.core.metamodel.facets.collections.modify.CollectionFacet;
+import org.apache.isis.core.metamodel.facets.collections.modify.CollectionFacetUtils;
+import org.apache.isis.core.metamodel.spec.feature.OneToManyAssociation;
+import org.apache.isis.viewer.restfulobjects.applib.JsonRepresentation;
+import org.apache.isis.viewer.restfulobjects.applib.RepresentationType;
+import org.apache.isis.viewer.restfulobjects.applib.links.Rel;
+import org.apache.isis.viewer.restfulobjects.rendering.LinkBuilder;
+import org.apache.isis.viewer.restfulobjects.rendering.LinkFollower;
+import org.apache.isis.viewer.restfulobjects.rendering.RendererContext;
+import org.apache.isis.viewer.restfulobjects.rendering.RendererFactory;
+import org.apache.isis.viewer.restfulobjects.rendering.RendererFactoryRegistry;
+import org.apache.isis.viewer.restfulobjects.rendering.ReprRenderer;
+import org.apache.isis.viewer.restfulobjects.rendering.ReprRendererFactoryAbstract;
+import org.apache.isis.viewer.restfulobjects.rendering.domaintypes.CollectionDescriptionReprRenderer;
+
+import com.google.common.collect.Lists;
+
+public class ObjectCollectionReprRenderer extends AbstractObjectMemberReprRenderer<ObjectCollectionReprRenderer, OneToManyAssociation> {
+
+    public static class Factory extends ReprRendererFactoryAbstract {
+
+        public Factory() {
+            super(RepresentationType.OBJECT_COLLECTION);
+        }
+
+        @Override
+        public ReprRenderer<?, ?> newRenderer(final RendererContext resourceContext, final LinkFollower linkFollower, final JsonRepresentation representation) {
+            return new ObjectCollectionReprRenderer(resourceContext, linkFollower, getRepresentationType(), representation);
+        }
+    }
+
+    private ObjectCollectionReprRenderer(final RendererContext resourceContext, final LinkFollower linkFollower, final RepresentationType representationType, final JsonRepresentation representation) {
+        super(resourceContext, linkFollower, representationType, representation, Where.PARENTED_TABLES);
+    }
+
+    @Override
+    public JsonRepresentation render() {
+        // id and memberType are rendered eagerly
+
+        renderMemberContent();
+        if (mode.isStandalone() || mode.isMutated() || !objectAdapter.representsPersistent()) {
+            addValue();
+        }
+        putDisabledReasonIfDisabled();
+
+        if (mode.isStandalone() || mode.isMutated()) {
+            addExtensionsIsisProprietaryChangedObjects();
+        }
+
+        return representation;
+    }
+
+    // ///////////////////////////////////////////////////
+    // value
+    // ///////////////////////////////////////////////////
+
+    private void addValue() {
+        final ObjectAdapter valueAdapter = objectMember.get(objectAdapter);
+        if (valueAdapter == null) {
+            return;
+        }
+
+        final CollectionFacet facet = CollectionFacetUtils.getCollectionFacetFromSpec(valueAdapter);
+        final List<JsonRepresentation> list = Lists.newArrayList();
+        for (final ObjectAdapter elementAdapter : facet.iterable(valueAdapter)) {
+
+            final LinkBuilder newBuilder = DomainObjectReprRenderer.newLinkToBuilder(resourceContext, Rel.OBJECT, elementAdapter);
+
+            list.add(newBuilder.build());
+        }
+
+        representation.mapPut("value", list);
+    }
+
+    // ///////////////////////////////////////////////////
+    // details link
+    // ///////////////////////////////////////////////////
+
+    /**
+     * Mandatory hook method to support x-ro-follow-links
+     */
+    @Override
+    protected void followDetailsLink(final JsonRepresentation detailsLink) {
+        final RendererFactory factory = RendererFactoryRegistry.instance.find(RepresentationType.OBJECT_COLLECTION);
+        final ObjectCollectionReprRenderer renderer = (ObjectCollectionReprRenderer) factory.newRenderer(getResourceContext(), getLinkFollower(), JsonRepresentation.newMap());
+        renderer.with(new ObjectAndCollection(objectAdapter, objectMember)).asFollowed();
+        detailsLink.mapPut("value", renderer.render());
+    }
+
+    // ///////////////////////////////////////////////////
+    // mutators
+    // ///////////////////////////////////////////////////
+
+    @Override
+    protected void addMutatorsIfEnabled() {
+        if (usability().isVetoed()) {
+            return;
+        }
+
+        final CollectionSemantics semantics = CollectionSemantics.determine(objectMember);
+        addMutatorLink(semantics.getAddToKey());
+        addMutatorLink(semantics.getRemoveFromKey());
+
+        return;
+    }
+
+    private void addMutatorLink(final String key) {
+        final Map<String, MutatorSpec> mutators = memberType.getMutators();
+        final MutatorSpec mutatorSpec = mutators.get(key);
+        addLinkFor(mutatorSpec);
+    }
+
+    // ///////////////////////////////////////////////////
+    // extensions and links
+    // ///////////////////////////////////////////////////
+
+    @Override
+    protected void addLinksToFormalDomainModel() {
+        final LinkBuilder linkBuilder = CollectionDescriptionReprRenderer.newLinkToBuilder(resourceContext, Rel.DESCRIBEDBY, objectAdapter.getSpecification(), objectMember);
+        getLinks().arrayAdd(linkBuilder.build());
+    }
+
+    @Override
+    protected void addLinksIsisProprietary() {
+        // none
+    }
+
+    @Override
+    protected void putExtensionsIsisProprietary() {
+        final CollectionSemantics semantics = CollectionSemantics.determine(objectMember);
+        getExtensions().mapPut("collectionSemantics", semantics.name().toLowerCase());
+    }
+
+}
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/isis/blob/75f41b75/component/viewer/restfulobjects/rendering/src/main/java/org/apache/isis/viewer/restfulobjects/rendering/domainobjects/ObjectPropertyReprRenderer.java
----------------------------------------------------------------------
diff --git a/component/viewer/restfulobjects/rendering/src/main/java/org/apache/isis/viewer/restfulobjects/rendering/domainobjects/ObjectPropertyReprRenderer.java b/component/viewer/restfulobjects/rendering/src/main/java/org/apache/isis/viewer/restfulobjects/rendering/domainobjects/ObjectPropertyReprRenderer.java
new file mode 100644
index 0000000..2c1c6c1
--- /dev/null
+++ b/component/viewer/restfulobjects/rendering/src/main/java/org/apache/isis/viewer/restfulobjects/rendering/domainobjects/ObjectPropertyReprRenderer.java
@@ -0,0 +1,167 @@
+/**
+ *  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.restfulobjects.rendering.domainobjects;
+
+import java.util.List;
+import java.util.Map;
+
+import org.apache.isis.applib.annotation.Where;
+import org.apache.isis.core.metamodel.adapter.ObjectAdapter;
+import org.apache.isis.core.metamodel.spec.ObjectSpecification;
+import org.apache.isis.core.metamodel.spec.feature.OneToOneAssociation;
+import org.apache.isis.viewer.restfulobjects.applib.JsonRepresentation;
+import org.apache.isis.viewer.restfulobjects.applib.RepresentationType;
+import org.apache.isis.viewer.restfulobjects.applib.links.Rel;
+import org.apache.isis.viewer.restfulobjects.rendering.LinkFollower;
+import org.apache.isis.viewer.restfulobjects.rendering.RendererContext;
+import org.apache.isis.viewer.restfulobjects.rendering.RendererFactory;
+import org.apache.isis.viewer.restfulobjects.rendering.RendererFactoryRegistry;
+import org.apache.isis.viewer.restfulobjects.rendering.ReprRenderer;
+import org.apache.isis.viewer.restfulobjects.rendering.ReprRendererFactoryAbstract;
+import org.apache.isis.viewer.restfulobjects.rendering.domaintypes.PropertyDescriptionReprRenderer;
+import org.codehaus.jackson.node.NullNode;
+
+import com.google.common.collect.Lists;
+
+public class ObjectPropertyReprRenderer extends AbstractObjectMemberReprRenderer<ObjectPropertyReprRenderer, OneToOneAssociation> {
+
+    public static class Factory extends ReprRendererFactoryAbstract {
+
+        public Factory() {
+            super(RepresentationType.OBJECT_PROPERTY);
+        }
+
+        @Override
+        public ReprRenderer<?, ?> newRenderer(final RendererContext resourceContext, final LinkFollower linkFollower, final JsonRepresentation representation) {
+            return new ObjectPropertyReprRenderer(resourceContext, linkFollower, getRepresentationType(), representation);
+        }
+    }
+
+    private ObjectPropertyReprRenderer(final RendererContext resourceContext, final LinkFollower linkFollower, final RepresentationType representationType, final JsonRepresentation representation) {
+        super(resourceContext, linkFollower, representationType, representation, Where.OBJECT_FORMS);
+    }
+
+    @Override
+    public JsonRepresentation render() {
+        // id and memberType are rendered eagerly
+
+        renderMemberContent();
+        addValue();
+
+        putDisabledReasonIfDisabled();
+
+        if (mode.isStandalone() || mode.isMutated()) {
+            addChoices();
+            addExtensionsIsisProprietaryChangedObjects();
+        }
+
+        return representation;
+    }
+
+    // ///////////////////////////////////////////////////
+    // value
+    // ///////////////////////////////////////////////////
+
+    private void addValue() {
+        representation.mapPut("value", valueRep());
+    }
+
+    private Object valueRep() {
+        final ObjectAdapter valueAdapter = objectMember.get(objectAdapter);
+        if (valueAdapter == null) {
+            return NullNode.getInstance();
+        }
+        return DomainObjectReprRenderer.valueOrRef(resourceContext, valueAdapter, objectMember.getSpecification());
+    }
+
+    // ///////////////////////////////////////////////////
+    // details link
+    // ///////////////////////////////////////////////////
+
+    /**
+     * Mandatory hook method to support x-ro-follow-links
+     */
+    @Override
+    protected void followDetailsLink(final JsonRepresentation detailsLink) {
+        final RendererFactory factory = RendererFactoryRegistry.instance.find(RepresentationType.OBJECT_PROPERTY);
+        final ObjectPropertyReprRenderer renderer = (ObjectPropertyReprRenderer) factory.newRenderer(getResourceContext(), getLinkFollower(), JsonRepresentation.newMap());
+        renderer.with(new ObjectAndProperty(objectAdapter, objectMember)).asFollowed();
+        detailsLink.mapPut("value", renderer.render());
+    }
+
+    // ///////////////////////////////////////////////////
+    // mutators
+    // ///////////////////////////////////////////////////
+
+    @Override
+    protected void addMutatorsIfEnabled() {
+        if (usability().isVetoed()) {
+            return;
+        }
+        final Map<String, MutatorSpec> mutators = memberType.getMutators();
+        for (final String mutator : mutators.keySet()) {
+            final MutatorSpec mutatorSpec = mutators.get(mutator);
+            addLinkFor(mutatorSpec);
+        }
+        return;
+    }
+
+    // ///////////////////////////////////////////////////
+    // choices
+    // ///////////////////////////////////////////////////
+
+    private ObjectPropertyReprRenderer addChoices() {
+        final Object propertyChoices = propertyChoices();
+        if (propertyChoices != null) {
+            representation.mapPut("choices", propertyChoices);
+        }
+        return this;
+    }
+
+    private Object propertyChoices() {
+        final ObjectAdapter[] choiceAdapters = objectMember.getChoices(objectAdapter);
+        if (choiceAdapters == null || choiceAdapters.length == 0) {
+            return null;
+        }
+        final List<Object> list = Lists.newArrayList();
+        for (final ObjectAdapter choiceAdapter : choiceAdapters) {
+            final ObjectSpecification objectSpec = objectMember.getSpecification();
+            list.add(DomainObjectReprRenderer.valueOrRef(resourceContext, choiceAdapter, objectSpec));
+        }
+        return list;
+    }
+
+    // ///////////////////////////////////////////////////
+    // extensions and links
+    // ///////////////////////////////////////////////////
+
+    @Override
+    protected void addLinksToFormalDomainModel() {
+        getLinks().arrayAdd(PropertyDescriptionReprRenderer.newLinkToBuilder(getResourceContext(), Rel.DESCRIBEDBY, objectAdapter.getSpecification(), objectMember).build());
+    }
+
+    @Override
+    protected void addLinksIsisProprietary() {
+        // none
+    }
+
+    @Override
+    protected void putExtensionsIsisProprietary() {
+        // none
+    }
+
+}
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/isis/blob/75f41b75/component/viewer/restfulobjects/rendering/src/main/java/org/apache/isis/viewer/restfulobjects/rendering/domainobjects/ScalarValueReprRenderer.java
----------------------------------------------------------------------
diff --git a/component/viewer/restfulobjects/rendering/src/main/java/org/apache/isis/viewer/restfulobjects/rendering/domainobjects/ScalarValueReprRenderer.java b/component/viewer/restfulobjects/rendering/src/main/java/org/apache/isis/viewer/restfulobjects/rendering/domainobjects/ScalarValueReprRenderer.java
new file mode 100644
index 0000000..b81d48d
--- /dev/null
+++ b/component/viewer/restfulobjects/rendering/src/main/java/org/apache/isis/viewer/restfulobjects/rendering/domainobjects/ScalarValueReprRenderer.java
@@ -0,0 +1,83 @@
+/**
+ *  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.restfulobjects.rendering.domainobjects;
+
+import org.apache.isis.core.metamodel.adapter.ObjectAdapter;
+import org.apache.isis.core.metamodel.facets.object.encodeable.EncodableFacet;
+import org.apache.isis.core.metamodel.spec.ObjectSpecification;
+import org.apache.isis.viewer.restfulobjects.applib.JsonRepresentation;
+import org.apache.isis.viewer.restfulobjects.applib.RepresentationType;
+import org.apache.isis.viewer.restfulobjects.applib.links.Rel;
+import org.apache.isis.viewer.restfulobjects.rendering.LinkFollower;
+import org.apache.isis.viewer.restfulobjects.rendering.RendererContext;
+import org.apache.isis.viewer.restfulobjects.rendering.ReprRenderer;
+import org.apache.isis.viewer.restfulobjects.rendering.ReprRendererAbstract;
+import org.apache.isis.viewer.restfulobjects.rendering.ReprRendererException;
+import org.apache.isis.viewer.restfulobjects.rendering.ReprRendererFactoryAbstract;
+
+public class ScalarValueReprRenderer extends ReprRendererAbstract<ScalarValueReprRenderer, ObjectAdapter> {
+
+    private final JsonValueEncoder jsonValueEncoder = new JsonValueEncoder();
+    private ObjectSpecification returnType;
+
+    public static class Factory extends ReprRendererFactoryAbstract {
+        public Factory() {
+            super(RepresentationType.SCALAR_VALUE);
+        }
+
+        @Override
+        public ReprRenderer<?, ?> newRenderer(final RendererContext resourceContext, final LinkFollower linkFollower, final JsonRepresentation representation) {
+            return new ScalarValueReprRenderer(resourceContext, linkFollower, getRepresentationType(), representation);
+        }
+    }
+
+    private ScalarValueReprRenderer(final RendererContext resourceContext, final LinkFollower linkFollower, final RepresentationType representationType, final JsonRepresentation representation) {
+        super(resourceContext, linkFollower, representationType, representation);
+    }
+
+    @Override
+    public ScalarValueReprRenderer with(final ObjectAdapter objectAdapter) {
+        final EncodableFacet facet = objectAdapter.getSpecification().getFacet(EncodableFacet.class);
+        if (facet == null) {
+            throw ReprRendererException.create("Not an (encodable) value", objectAdapter.titleString());
+        }
+        final Object value = jsonValueEncoder.asObject(objectAdapter);
+
+        representation.mapPut("value", value);
+        return this;
+    }
+
+    @Override
+    public JsonRepresentation render() {
+
+        addLinkToReturnType();
+
+        getExtensions();
+
+        return representation;
+    }
+
+    public ScalarValueReprRenderer withReturnType(final ObjectSpecification returnType) {
+        this.returnType = returnType;
+        return this;
+    }
+
+    private void addLinkToReturnType() {
+        addLink(Rel.RETURN_TYPE, returnType);
+    }
+
+}
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/isis/blob/75f41b75/component/viewer/restfulobjects/rendering/src/main/java/org/apache/isis/viewer/restfulobjects/rendering/domaintypes/AbstractTypeFeatureReprRenderer.java
----------------------------------------------------------------------
diff --git a/component/viewer/restfulobjects/rendering/src/main/java/org/apache/isis/viewer/restfulobjects/rendering/domaintypes/AbstractTypeFeatureReprRenderer.java b/component/viewer/restfulobjects/rendering/src/main/java/org/apache/isis/viewer/restfulobjects/rendering/domaintypes/AbstractTypeFeatureReprRenderer.java
new file mode 100644
index 0000000..9101ec8
--- /dev/null
+++ b/component/viewer/restfulobjects/rendering/src/main/java/org/apache/isis/viewer/restfulobjects/rendering/domaintypes/AbstractTypeFeatureReprRenderer.java
@@ -0,0 +1,107 @@
+/**
+ *  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.restfulobjects.rendering.domaintypes;
+
+import org.apache.isis.core.metamodel.spec.ObjectSpecification;
+import org.apache.isis.core.metamodel.spec.feature.ObjectFeature;
+import org.apache.isis.viewer.restfulobjects.applib.JsonRepresentation;
+import org.apache.isis.viewer.restfulobjects.applib.RepresentationType;
+import org.apache.isis.viewer.restfulobjects.rendering.LinkFollower;
+import org.apache.isis.viewer.restfulobjects.rendering.RendererContext;
+import org.apache.isis.viewer.restfulobjects.rendering.ReprRendererAbstract;
+
+import com.google.common.base.Strings;
+
+public abstract class AbstractTypeFeatureReprRenderer<R extends ReprRendererAbstract<R, ParentSpecAndFeature<T>>, T extends ObjectFeature> extends ReprRendererAbstract<R, ParentSpecAndFeature<T>> {
+
+    protected ObjectSpecification objectSpecification;
+    protected T objectFeature;
+
+    public AbstractTypeFeatureReprRenderer(final RendererContext resourceContext, final LinkFollower linkFollower, final RepresentationType representationType, final JsonRepresentation representation) {
+        super(resourceContext, linkFollower, representationType, representation);
+    }
+
+    public ObjectSpecification getParentSpecification() {
+        return objectSpecification;
+    }
+
+    public T getObjectFeature() {
+        return objectFeature;
+    }
+
+    @Override
+    public R with(final ParentSpecAndFeature<T> specAndFeature) {
+        objectSpecification = specAndFeature.getParentSpec();
+        objectFeature = specAndFeature.getObjectFeature();
+
+        return cast(this);
+    }
+
+    @Override
+    public JsonRepresentation render() {
+
+        addLinkSelfIfRequired();
+        addLinkUpToParent();
+
+        addPropertiesSpecificToFeature();
+
+        addLinksSpecificToFeature();
+        putExtensionsSpecificToFeature();
+
+        return representation;
+    }
+
+    /**
+     * Optional hook method.
+     */
+    protected void addPropertiesSpecificToFeature() {
+    }
+
+    /**
+     * Mandatory hook method.
+     */
+    protected abstract void addLinkSelfIfRequired();
+
+    /**
+     * Mandatory hook method.
+     */
+    protected abstract void addLinkUpToParent();
+
+    /**
+     * Optional hook method.
+     */
+    protected void addLinksSpecificToFeature() {
+    }
+
+    /**
+     * Mandatory hook method.
+     */
+    protected abstract void putExtensionsSpecificToFeature();
+
+    protected void putExtensionsName() {
+        final String friendlyName = getObjectFeature().getName();
+        getExtensions().mapPut("friendlyName", friendlyName);
+    }
+
+    protected void putExtensionsDescriptionIfAvailable() {
+        final String description = getObjectFeature().getDescription();
+        if (!Strings.isNullOrEmpty(description)) {
+            getExtensions().mapPut("description", description);
+        }
+    }
+
+}
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/isis/blob/75f41b75/component/viewer/restfulobjects/rendering/src/main/java/org/apache/isis/viewer/restfulobjects/rendering/domaintypes/AbstractTypeMemberReprRenderer.java
----------------------------------------------------------------------
diff --git a/component/viewer/restfulobjects/rendering/src/main/java/org/apache/isis/viewer/restfulobjects/rendering/domaintypes/AbstractTypeMemberReprRenderer.java b/component/viewer/restfulobjects/rendering/src/main/java/org/apache/isis/viewer/restfulobjects/rendering/domaintypes/AbstractTypeMemberReprRenderer.java
new file mode 100644
index 0000000..3f4dd53
--- /dev/null
+++ b/component/viewer/restfulobjects/rendering/src/main/java/org/apache/isis/viewer/restfulobjects/rendering/domaintypes/AbstractTypeMemberReprRenderer.java
@@ -0,0 +1,75 @@
+/**
+ *  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.restfulobjects.rendering.domaintypes;
+
+import org.apache.isis.core.metamodel.spec.feature.ObjectMember;
+import org.apache.isis.viewer.restfulobjects.applib.JsonRepresentation;
+import org.apache.isis.viewer.restfulobjects.applib.RepresentationType;
+import org.apache.isis.viewer.restfulobjects.applib.links.Rel;
+import org.apache.isis.viewer.restfulobjects.rendering.LinkBuilder;
+import org.apache.isis.viewer.restfulobjects.rendering.LinkFollower;
+import org.apache.isis.viewer.restfulobjects.rendering.RendererContext;
+import org.apache.isis.viewer.restfulobjects.rendering.ReprRendererAbstract;
+import org.apache.isis.viewer.restfulobjects.rendering.domainobjects.MemberType;
+
+public abstract class AbstractTypeMemberReprRenderer<R extends ReprRendererAbstract<R, ParentSpecAndFeature<T>>, T extends ObjectMember> extends AbstractTypeFeatureReprRenderer<R, T> {
+
+    protected MemberType memberType;
+
+    public AbstractTypeMemberReprRenderer(final RendererContext resourceContext, final LinkFollower linkFollower, final RepresentationType representationType, final JsonRepresentation representation) {
+        super(resourceContext, linkFollower, representationType, representation);
+    }
+
+    /**
+     * null if the feature is an object action param.
+     * 
+     * @return
+     */
+    public MemberType getMemberType() {
+        return memberType;
+    }
+
+    @Override
+    public R with(final ParentSpecAndFeature<T> specAndFeature) {
+        super.with(specAndFeature);
+        memberType = MemberType.determineFrom(objectFeature);
+
+        // done eagerly so can use as criteria for x-ro-follow-links
+        representation.mapPut(memberType.getJsProp(), objectFeature.getId());
+        representation.mapPut("memberType", memberType.getName());
+
+        return cast(this);
+    }
+
+    @Override
+    protected void addLinkUpToParent() {
+        final LinkBuilder parentLinkBuilder = DomainTypeReprRenderer.newLinkToBuilder(resourceContext, Rel.UP, objectSpecification);
+        getLinks().arrayAdd(parentLinkBuilder.build());
+    }
+
+    @Override
+    protected void addLinkSelfIfRequired() {
+        if (!includesSelf) {
+            return;
+        }
+
+        final ObjectMember objectMember = getObjectFeature();
+        final LinkBuilder linkBuilder = LinkBuilder.newBuilder(getResourceContext(), Rel.SELF, getRepresentationType(), "domainTypes/%s/%s%s", getParentSpecification().getFullIdentifier(), getMemberType().getUrlPart(), objectMember.getId());
+        getLinks().arrayAdd(linkBuilder.build());
+    }
+
+}
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/isis/blob/75f41b75/component/viewer/restfulobjects/rendering/src/main/java/org/apache/isis/viewer/restfulobjects/rendering/domaintypes/ActionDescriptionReprRenderer.java
----------------------------------------------------------------------
diff --git a/component/viewer/restfulobjects/rendering/src/main/java/org/apache/isis/viewer/restfulobjects/rendering/domaintypes/ActionDescriptionReprRenderer.java b/component/viewer/restfulobjects/rendering/src/main/java/org/apache/isis/viewer/restfulobjects/rendering/domaintypes/ActionDescriptionReprRenderer.java
new file mode 100644
index 0000000..7f3c08a
--- /dev/null
+++ b/component/viewer/restfulobjects/rendering/src/main/java/org/apache/isis/viewer/restfulobjects/rendering/domaintypes/ActionDescriptionReprRenderer.java
@@ -0,0 +1,102 @@
+/**
+ *  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.restfulobjects.rendering.domaintypes;
+
+import java.util.List;
+
+import org.apache.isis.core.metamodel.facets.typeof.TypeOfFacet;
+import org.apache.isis.core.metamodel.spec.ObjectSpecification;
+import org.apache.isis.core.metamodel.spec.feature.ObjectAction;
+import org.apache.isis.core.metamodel.spec.feature.ObjectActionParameter;
+import org.apache.isis.viewer.restfulobjects.applib.JsonRepresentation;
+import org.apache.isis.viewer.restfulobjects.applib.RepresentationType;
+import org.apache.isis.viewer.restfulobjects.applib.links.Rel;
+import org.apache.isis.viewer.restfulobjects.rendering.LinkBuilder;
+import org.apache.isis.viewer.restfulobjects.rendering.LinkFollower;
+import org.apache.isis.viewer.restfulobjects.rendering.RendererContext;
+import org.apache.isis.viewer.restfulobjects.rendering.ReprRenderer;
+import org.apache.isis.viewer.restfulobjects.rendering.ReprRendererFactoryAbstract;
+
+public class ActionDescriptionReprRenderer extends AbstractTypeMemberReprRenderer<ActionDescriptionReprRenderer, ObjectAction> {
+
+    public static class Factory extends ReprRendererFactoryAbstract {
+
+        public Factory() {
+            super(RepresentationType.ACTION_DESCRIPTION);
+        }
+
+        @Override
+        public ReprRenderer<?, ?> newRenderer(final RendererContext resourceContext, final LinkFollower linkFollower, final JsonRepresentation representation) {
+            return new ActionDescriptionReprRenderer(resourceContext, linkFollower, getRepresentationType(), representation);
+        }
+    }
+
+    public static LinkBuilder newLinkToBuilder(final RendererContext resourceContext, final Rel rel, final ObjectSpecification objectSpecification, final ObjectAction objectAction) {
+        final String typeFullName = objectSpecification.getFullIdentifier();
+        final String actionId = objectAction.getId();
+        final String url = "domainTypes/" + typeFullName + "/actions/" + actionId;
+        return LinkBuilder.newBuilder(resourceContext, rel, RepresentationType.ACTION_DESCRIPTION, url);
+    }
+
+    public ActionDescriptionReprRenderer(final RendererContext resourceContext, final LinkFollower linkFollower, final RepresentationType representationType, final JsonRepresentation representation) {
+        super(resourceContext, linkFollower, representationType, representation);
+    }
+
+    @Override
+    protected void addLinksSpecificToFeature() {
+        addParameters();
+        addLinkToReturnTypeIfAny();
+        addLinkToElementTypeIfAny();
+    }
+
+    private void addParameters() {
+        final JsonRepresentation parameterList = JsonRepresentation.newArray();
+        final List<ObjectActionParameter> parameters = getObjectFeature().getParameters();
+        for (final ObjectActionParameter parameter : parameters) {
+            final LinkBuilder linkBuilder = ActionParameterDescriptionReprRenderer.newLinkToBuilder(getResourceContext(), Rel.ACTION_PARAM, objectSpecification, parameter);
+            parameterList.arrayAdd(linkBuilder.build());
+        }
+
+        representation.mapPut("parameters", parameterList);
+    }
+
+    protected void addLinkToElementTypeIfAny() {
+        final TypeOfFacet facet = getObjectFeature().getFacet(TypeOfFacet.class);
+        if (facet == null) {
+            return;
+        }
+        final ObjectSpecification typeOfSpec = facet.valueSpec();
+        final LinkBuilder linkBuilder = DomainTypeReprRenderer.newLinkToBuilder(getResourceContext(), Rel.ELEMENT_TYPE, typeOfSpec);
+        getLinks().arrayAdd(linkBuilder.build());
+    }
+
+    private void addLinkToReturnTypeIfAny() {
+        final ObjectSpecification returnType = getObjectFeature().getReturnType();
+        if (returnType == null) {
+            return;
+        }
+        final LinkBuilder linkBuilder = DomainTypeReprRenderer.newLinkToBuilder(getResourceContext(), Rel.RETURN_TYPE, returnType);
+        getLinks().arrayAdd(linkBuilder.build());
+    }
+
+    @Override
+    protected void putExtensionsSpecificToFeature() {
+        putExtensionsName();
+        putExtensionsDescriptionIfAvailable();
+    }
+
+}
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/isis/blob/75f41b75/component/viewer/restfulobjects/rendering/src/main/java/org/apache/isis/viewer/restfulobjects/rendering/domaintypes/ActionParameterDescriptionReprRenderer.java
----------------------------------------------------------------------
diff --git a/component/viewer/restfulobjects/rendering/src/main/java/org/apache/isis/viewer/restfulobjects/rendering/domaintypes/ActionParameterDescriptionReprRenderer.java b/component/viewer/restfulobjects/rendering/src/main/java/org/apache/isis/viewer/restfulobjects/rendering/domaintypes/ActionParameterDescriptionReprRenderer.java
new file mode 100644
index 0000000..fcdf4ca
--- /dev/null
+++ b/component/viewer/restfulobjects/rendering/src/main/java/org/apache/isis/viewer/restfulobjects/rendering/domaintypes/ActionParameterDescriptionReprRenderer.java
@@ -0,0 +1,116 @@
+/**
+ *  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.restfulobjects.rendering.domaintypes;
+
+import org.apache.isis.core.metamodel.facets.maxlen.MaxLengthFacet;
+import org.apache.isis.core.metamodel.spec.ObjectSpecification;
+import org.apache.isis.core.metamodel.spec.feature.ObjectAction;
+import org.apache.isis.core.metamodel.spec.feature.ObjectActionParameter;
+import org.apache.isis.viewer.restfulobjects.applib.JsonRepresentation;
+import org.apache.isis.viewer.restfulobjects.applib.RepresentationType;
+import org.apache.isis.viewer.restfulobjects.applib.links.Rel;
+import org.apache.isis.viewer.restfulobjects.rendering.LinkBuilder;
+import org.apache.isis.viewer.restfulobjects.rendering.LinkFollower;
+import org.apache.isis.viewer.restfulobjects.rendering.RendererContext;
+import org.apache.isis.viewer.restfulobjects.rendering.ReprRenderer;
+import org.apache.isis.viewer.restfulobjects.rendering.ReprRendererFactoryAbstract;
+
+public class ActionParameterDescriptionReprRenderer extends AbstractTypeFeatureReprRenderer<ActionParameterDescriptionReprRenderer, ObjectActionParameter> {
+
+    public static class Factory extends ReprRendererFactoryAbstract {
+
+        public Factory() {
+            super(RepresentationType.ACTION_PARAMETER_DESCRIPTION);
+        }
+
+        @Override
+        public ReprRenderer<?, ?> newRenderer(final RendererContext resourceContext, final LinkFollower linkFollower, final JsonRepresentation representation) {
+            return new ActionParameterDescriptionReprRenderer(resourceContext, linkFollower, getRepresentationType(), representation);
+        }
+    }
+
+    public static LinkBuilder newLinkToBuilder(final RendererContext resourceContext, final Rel rel, final ObjectSpecification objectSpecification, final ObjectActionParameter objectActionParameter) {
+        final String typeFullName = objectSpecification.getFullIdentifier();
+        final ObjectAction objectAction = objectActionParameter.getAction();
+        final String actionId = objectAction.getId();
+        final String paramName = objectActionParameter.getName();
+        final String url = String.format("domainTypes/%s/actions/%s/params/%s", typeFullName, actionId, paramName);
+        return LinkBuilder.newBuilder(resourceContext, rel, RepresentationType.ACTION_PARAMETER_DESCRIPTION, url).withId(deriveId(objectActionParameter));
+    }
+
+    public ActionParameterDescriptionReprRenderer(final RendererContext resourceContext, final LinkFollower linkFollower, final RepresentationType representationType, final JsonRepresentation representation) {
+        super(resourceContext, linkFollower, representationType, representation);
+    }
+
+    @Override
+    public ActionParameterDescriptionReprRenderer with(final ParentSpecAndFeature<ObjectActionParameter> specAndFeature) {
+        super.with(specAndFeature);
+
+        // done eagerly so can use as criteria for x-ro-follow-links
+        representation.mapPut("id", deriveId());
+
+        return this;
+    }
+
+    protected String deriveId() {
+        return deriveId(getObjectFeature());
+    }
+
+    private static String deriveId(final ObjectActionParameter objectActionParameter) {
+        return objectActionParameter.getAction().getId() + "-" + objectActionParameter.getName();
+    }
+
+    @Override
+    protected void addLinkSelfIfRequired() {
+        if (!includesSelf) {
+            return;
+        }
+        getLinks().arrayAdd(newLinkToBuilder(getResourceContext(), Rel.SELF, getParentSpecification(), getObjectFeature()).build());
+    }
+
+    @Override
+    protected void addLinkUpToParent() {
+        final ObjectAction parentAction = this.objectFeature.getAction();
+
+        final LinkBuilder parentLinkBuilder = ActionDescriptionReprRenderer.newLinkToBuilder(resourceContext, Rel.UP, objectSpecification, parentAction);
+        getLinks().arrayAdd(parentLinkBuilder.build());
+    }
+
+    @Override
+    protected void addPropertiesSpecificToFeature() {
+        representation.mapPut("name", getObjectFeature().getName());
+        representation.mapPut("number", getObjectFeature().getNumber());
+        representation.mapPut("optional", getObjectFeature().isOptional());
+        final MaxLengthFacet maxLength = getObjectFeature().getFacet(MaxLengthFacet.class);
+        if (maxLength != null && !maxLength.isNoop()) {
+            representation.mapPut("maxLength", maxLength.value());
+        }
+    }
+
+    @Override
+    protected void addLinksSpecificToFeature() {
+        final LinkBuilder linkBuilder = DomainTypeReprRenderer.newLinkToBuilder(resourceContext, Rel.RETURN_TYPE, objectFeature.getSpecification());
+        getLinks().arrayAdd(linkBuilder.build());
+    }
+
+    @Override
+    protected void putExtensionsSpecificToFeature() {
+        putExtensionsName();
+        putExtensionsDescriptionIfAvailable();
+    }
+
+}
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/isis/blob/75f41b75/component/viewer/restfulobjects/rendering/src/main/java/org/apache/isis/viewer/restfulobjects/rendering/domaintypes/CollectionDescriptionReprRenderer.java
----------------------------------------------------------------------
diff --git a/component/viewer/restfulobjects/rendering/src/main/java/org/apache/isis/viewer/restfulobjects/rendering/domaintypes/CollectionDescriptionReprRenderer.java b/component/viewer/restfulobjects/rendering/src/main/java/org/apache/isis/viewer/restfulobjects/rendering/domaintypes/CollectionDescriptionReprRenderer.java
new file mode 100644
index 0000000..0f008b9
--- /dev/null
+++ b/component/viewer/restfulobjects/rendering/src/main/java/org/apache/isis/viewer/restfulobjects/rendering/domaintypes/CollectionDescriptionReprRenderer.java
@@ -0,0 +1,75 @@
+/**
+ *  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.restfulobjects.rendering.domaintypes;
+
+import org.apache.isis.core.metamodel.spec.ObjectSpecification;
+import org.apache.isis.core.metamodel.spec.feature.OneToManyAssociation;
+import org.apache.isis.viewer.restfulobjects.applib.JsonRepresentation;
+import org.apache.isis.viewer.restfulobjects.applib.RepresentationType;
+import org.apache.isis.viewer.restfulobjects.applib.links.Rel;
+import org.apache.isis.viewer.restfulobjects.rendering.LinkBuilder;
+import org.apache.isis.viewer.restfulobjects.rendering.LinkFollower;
+import org.apache.isis.viewer.restfulobjects.rendering.RendererContext;
+import org.apache.isis.viewer.restfulobjects.rendering.ReprRenderer;
+import org.apache.isis.viewer.restfulobjects.rendering.ReprRendererFactoryAbstract;
+
+public class CollectionDescriptionReprRenderer extends AbstractTypeMemberReprRenderer<CollectionDescriptionReprRenderer, OneToManyAssociation> {
+
+    public static class Factory extends ReprRendererFactoryAbstract {
+
+        public Factory() {
+            super(RepresentationType.COLLECTION_DESCRIPTION);
+        }
+
+        @Override
+        public ReprRenderer<?, ?> newRenderer(final RendererContext resourceContext, final LinkFollower linkFollower, final JsonRepresentation representation) {
+            return new CollectionDescriptionReprRenderer(resourceContext, linkFollower, getRepresentationType(), representation);
+        }
+    }
+
+    public static LinkBuilder newLinkToBuilder(final RendererContext resourceContext, final Rel rel, final ObjectSpecification objectSpecification, final OneToManyAssociation collection) {
+        final String typeFullName = objectSpecification.getFullIdentifier();
+        final String collectionId = collection.getId();
+        final String url = "domainTypes/" + typeFullName + "/collections/" + collectionId;
+        return LinkBuilder.newBuilder(resourceContext, rel, RepresentationType.COLLECTION_DESCRIPTION, url);
+    }
+
+    public CollectionDescriptionReprRenderer(final RendererContext resourceContext, final LinkFollower linkFollower, final RepresentationType representationType, final JsonRepresentation representation) {
+        super(resourceContext, linkFollower, representationType, representation);
+    }
+
+    @Override
+    protected void addLinksSpecificToFeature() {
+        addLinkToElementTypeIfAny();
+    }
+
+    private void addLinkToElementTypeIfAny() {
+        final ObjectSpecification elementType = getObjectFeature().getSpecification();
+        if (elementType == null) {
+            return;
+        }
+        final LinkBuilder linkBuilder = DomainTypeReprRenderer.newLinkToBuilder(getResourceContext(), Rel.ELEMENT_TYPE, elementType);
+        getLinks().arrayAdd(linkBuilder.build());
+    }
+
+    @Override
+    protected void putExtensionsSpecificToFeature() {
+        putExtensionsName();
+        putExtensionsDescriptionIfAvailable();
+    }
+
+}
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/isis/blob/75f41b75/component/viewer/restfulobjects/rendering/src/main/java/org/apache/isis/viewer/restfulobjects/rendering/domaintypes/DomainTypeReprRenderer.java
----------------------------------------------------------------------
diff --git a/component/viewer/restfulobjects/rendering/src/main/java/org/apache/isis/viewer/restfulobjects/rendering/domaintypes/DomainTypeReprRenderer.java b/component/viewer/restfulobjects/rendering/src/main/java/org/apache/isis/viewer/restfulobjects/rendering/domaintypes/DomainTypeReprRenderer.java
new file mode 100644
index 0000000..2b2df40
--- /dev/null
+++ b/component/viewer/restfulobjects/rendering/src/main/java/org/apache/isis/viewer/restfulobjects/rendering/domaintypes/DomainTypeReprRenderer.java
@@ -0,0 +1,190 @@
+/**
+ *  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.restfulobjects.rendering.domaintypes;
+
+import java.util.List;
+
+import org.apache.isis.core.metamodel.spec.ObjectSpecification;
+import org.apache.isis.core.metamodel.spec.feature.ObjectAction;
+import org.apache.isis.core.metamodel.spec.feature.ObjectActionContainer.Contributed;
+import org.apache.isis.core.metamodel.spec.feature.ObjectAssociation;
+import org.apache.isis.core.metamodel.spec.feature.OneToManyAssociation;
+import org.apache.isis.core.metamodel.spec.feature.OneToOneAssociation;
+import org.apache.isis.viewer.restfulobjects.applib.JsonRepresentation;
+import org.apache.isis.viewer.restfulobjects.applib.RepresentationType;
+import org.apache.isis.viewer.restfulobjects.applib.links.Rel;
+import org.apache.isis.viewer.restfulobjects.rendering.LinkBuilder;
+import org.apache.isis.viewer.restfulobjects.rendering.LinkFollower;
+import org.apache.isis.viewer.restfulobjects.rendering.RendererContext;
+import org.apache.isis.viewer.restfulobjects.rendering.ReprRenderer;
+import org.apache.isis.viewer.restfulobjects.rendering.ReprRendererAbstract;
+import org.apache.isis.viewer.restfulobjects.rendering.ReprRendererFactoryAbstract;
+import org.codehaus.jackson.node.NullNode;
+
+import com.google.common.base.Strings;
+
+public class DomainTypeReprRenderer extends ReprRendererAbstract<DomainTypeReprRenderer, ObjectSpecification> {
+
+    public static class Factory extends ReprRendererFactoryAbstract {
+        public Factory() {
+            super(RepresentationType.DOMAIN_TYPE);
+        }
+
+        @Override
+        public ReprRenderer<?, ?> newRenderer(final RendererContext resourceContext, final LinkFollower linkFollower, final JsonRepresentation representation) {
+            return new DomainTypeReprRenderer(resourceContext, linkFollower, getRepresentationType(), representation);
+        }
+    }
+
+    public static LinkBuilder newLinkToBuilder(final RendererContext resourceContext, final Rel rel, final ObjectSpecification objectSpec) {
+        final String typeFullName = objectSpec.getFullIdentifier();
+        final String url = "domainTypes/" + typeFullName;
+        return LinkBuilder.newBuilder(resourceContext, rel, RepresentationType.DOMAIN_TYPE, url);
+    }
+
+    private ObjectSpecification objectSpecification;
+
+    public DomainTypeReprRenderer(final RendererContext resourceContext, final LinkFollower linkFollower, final RepresentationType representationType, final JsonRepresentation representation) {
+        super(resourceContext, linkFollower, representationType, representation);
+    }
+
+    @Override
+    public DomainTypeReprRenderer with(final ObjectSpecification objectSpecification) {
+        this.objectSpecification = objectSpecification;
+        return cast(this);
+    }
+
+    @Override
+    public JsonRepresentation render() {
+
+        if (objectSpecification == null) {
+            throw new IllegalStateException("ObjectSpecification not specified");
+        }
+
+        // self
+        if (includesSelf) {
+            final JsonRepresentation selfLink = newLinkToBuilder(getResourceContext(), Rel.SELF, objectSpecification).build();
+            getLinks().arrayAdd(selfLink);
+        }
+
+        representation.mapPut("canonicalName", objectSpecification.getFullIdentifier());
+        addMembers();
+
+        addTypeActions();
+
+        putExtensionsNames();
+        putExtensionsDescriptionIfAvailable();
+        putExtensionsIfService();
+
+        return representation;
+    }
+
+    private void addMembers() {
+        final JsonRepresentation membersList = JsonRepresentation.newArray();
+        representation.mapPut("members", membersList);
+        final List<ObjectAssociation> associations = objectSpecification.getAssociations();
+        for (final ObjectAssociation association : associations) {
+            if (association.isOneToOneAssociation()) {
+                final OneToOneAssociation property = (OneToOneAssociation) association;
+                final LinkBuilder linkBuilder = PropertyDescriptionReprRenderer.newLinkToBuilder(getResourceContext(), Rel.PROPERTY, objectSpecification, property);
+                membersList.arrayAdd(linkBuilder.build());
+            } else if (association.isOneToManyAssociation()) {
+                final OneToManyAssociation collection = (OneToManyAssociation) association;
+                final LinkBuilder linkBuilder = CollectionDescriptionReprRenderer.newLinkToBuilder(getResourceContext(), Rel.PROPERTY, objectSpecification, collection);
+                membersList.arrayAdd(linkBuilder.build());
+            }
+        }
+        final List<ObjectAction> actions = objectSpecification.getObjectActions(Contributed.INCLUDED);
+        for (final ObjectAction action : actions) {
+            final LinkBuilder linkBuilder = ActionDescriptionReprRenderer.newLinkToBuilder(getResourceContext(), Rel.ACTION, objectSpecification, action);
+            membersList.arrayAdd(linkBuilder.build());
+        }
+    }
+
+    private JsonRepresentation getTypeActions() {
+        JsonRepresentation typeActions = representation.getArray("typeActions");
+        if (typeActions == null) {
+            typeActions = JsonRepresentation.newArray();
+            representation.mapPut("typeActions", typeActions);
+        }
+        return typeActions;
+    }
+
+    private void addTypeActions() {
+        getTypeActions().arrayAdd(linkToIsSubtypeOf());
+        getTypeActions().arrayAdd(linkToIsSupertypeOf());
+        getTypeActions().arrayAdd(linkToNewTransientInstance());
+    }
+
+    private JsonRepresentation linkToIsSubtypeOf() {
+        final String url = "domainTypes/" + objectSpecification.getFullIdentifier() + "/typeactions/isSubtypeOf/invoke";
+
+        final LinkBuilder linkBuilder = LinkBuilder.newBuilder(getResourceContext(), Rel.TYPE_ACTION, RepresentationType.TYPE_ACTION_RESULT, url);
+        final JsonRepresentation arguments = argumentsTo(getResourceContext(), "supertype", null);
+        final JsonRepresentation link = linkBuilder.withArguments(arguments).withId("isSubtypeOf").build();
+        return link;
+    }
+
+    private JsonRepresentation linkToIsSupertypeOf() {
+        final String url = "domainTypes/" + objectSpecification.getFullIdentifier() + "/typeactions/isSupertypeOf/invoke";
+
+        final LinkBuilder linkBuilder = LinkBuilder.newBuilder(getResourceContext(), Rel.TYPE_ACTION, RepresentationType.TYPE_ACTION_RESULT, url);
+        final JsonRepresentation arguments = argumentsTo(getResourceContext(), "subtype", null);
+        final JsonRepresentation link = linkBuilder.withArguments(arguments).withId("isSupertypeOf").build();
+        return link;
+    }
+
+    private JsonRepresentation linkToNewTransientInstance() {
+        final String url = "domainTypes/" + objectSpecification.getFullIdentifier() + "/typeactions/newTransientInstance/invoke";
+
+        final LinkBuilder linkBuilder = LinkBuilder.newBuilder(getResourceContext(), Rel.TYPE_ACTION, RepresentationType.TYPE_ACTION_RESULT, url);
+        final JsonRepresentation link = linkBuilder.withId("newTransientInstance").build();
+        return link;
+    }
+
+    public static JsonRepresentation argumentsTo(final RendererContext resourceContext, final String paramName, final ObjectSpecification objectSpec) {
+        final JsonRepresentation arguments = JsonRepresentation.newMap();
+        final JsonRepresentation link = JsonRepresentation.newMap();
+        arguments.mapPut(paramName, link);
+        if (objectSpec != null) {
+            link.mapPut("href", resourceContext.urlFor("domainTypes/" + objectSpec.getFullIdentifier()));
+        } else {
+            link.mapPut("href", NullNode.instance);
+        }
+        return arguments;
+    }
+
+    protected void putExtensionsNames() {
+        final String singularName = objectSpecification.getSingularName();
+        getExtensions().mapPut("friendlyName", singularName);
+
+        final String pluralName = objectSpecification.getPluralName();
+        getExtensions().mapPut("pluralName", pluralName);
+    }
+
+    protected void putExtensionsDescriptionIfAvailable() {
+        final String description = objectSpecification.getDescription();
+        if (!Strings.isNullOrEmpty(description)) {
+            getExtensions().mapPut("description", description);
+        }
+    }
+
+    protected void putExtensionsIfService() {
+        getExtensions().mapPut("isService", objectSpecification.isService());
+    }
+
+}
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/isis/blob/75f41b75/component/viewer/restfulobjects/rendering/src/main/java/org/apache/isis/viewer/restfulobjects/rendering/domaintypes/ObjectSpecAndSuperSpec.java
----------------------------------------------------------------------
diff --git a/component/viewer/restfulobjects/rendering/src/main/java/org/apache/isis/viewer/restfulobjects/rendering/domaintypes/ObjectSpecAndSuperSpec.java b/component/viewer/restfulobjects/rendering/src/main/java/org/apache/isis/viewer/restfulobjects/rendering/domaintypes/ObjectSpecAndSuperSpec.java
new file mode 100644
index 0000000..98b989e
--- /dev/null
+++ b/component/viewer/restfulobjects/rendering/src/main/java/org/apache/isis/viewer/restfulobjects/rendering/domaintypes/ObjectSpecAndSuperSpec.java
@@ -0,0 +1,41 @@
+/*
+ *  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.restfulobjects.rendering.domaintypes;
+
+import org.apache.isis.core.metamodel.spec.ObjectSpecification;
+
+public class ObjectSpecAndSuperSpec {
+
+    private final ObjectSpecification objectSpecification;
+    private final ObjectSpecification superSpecification;
+
+    public ObjectSpecAndSuperSpec(final ObjectSpecification objectSpecification, final ObjectSpecification superSpecification) {
+        this.objectSpecification = objectSpecification;
+        this.superSpecification = superSpecification;
+    }
+
+    public ObjectSpecification getObjectSpecification() {
+        return objectSpecification;
+    }
+
+    public ObjectSpecification getSuperSpecification() {
+        return superSpecification;
+    }
+
+}
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/isis/blob/75f41b75/component/viewer/restfulobjects/rendering/src/main/java/org/apache/isis/viewer/restfulobjects/rendering/domaintypes/ParentSpecAndAction.java
----------------------------------------------------------------------
diff --git a/component/viewer/restfulobjects/rendering/src/main/java/org/apache/isis/viewer/restfulobjects/rendering/domaintypes/ParentSpecAndAction.java b/component/viewer/restfulobjects/rendering/src/main/java/org/apache/isis/viewer/restfulobjects/rendering/domaintypes/ParentSpecAndAction.java
new file mode 100644
index 0000000..5892ade
--- /dev/null
+++ b/component/viewer/restfulobjects/rendering/src/main/java/org/apache/isis/viewer/restfulobjects/rendering/domaintypes/ParentSpecAndAction.java
@@ -0,0 +1,30 @@
+/*
+ *  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.restfulobjects.rendering.domaintypes;
+
+import org.apache.isis.core.metamodel.spec.ObjectSpecification;
+import org.apache.isis.core.metamodel.spec.feature.ObjectAction;
+
+public class ParentSpecAndAction extends ParentSpecAndFeature<ObjectAction> {
+
+    public ParentSpecAndAction(final ObjectSpecification objectSpecification, final ObjectAction action) {
+        super(objectSpecification, action);
+    }
+
+}
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/isis/blob/75f41b75/component/viewer/restfulobjects/rendering/src/main/java/org/apache/isis/viewer/restfulobjects/rendering/domaintypes/ParentSpecAndActionParam.java
----------------------------------------------------------------------
diff --git a/component/viewer/restfulobjects/rendering/src/main/java/org/apache/isis/viewer/restfulobjects/rendering/domaintypes/ParentSpecAndActionParam.java b/component/viewer/restfulobjects/rendering/src/main/java/org/apache/isis/viewer/restfulobjects/rendering/domaintypes/ParentSpecAndActionParam.java
new file mode 100644
index 0000000..b2e180e
--- /dev/null
+++ b/component/viewer/restfulobjects/rendering/src/main/java/org/apache/isis/viewer/restfulobjects/rendering/domaintypes/ParentSpecAndActionParam.java
@@ -0,0 +1,30 @@
+/*
+ *  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.restfulobjects.rendering.domaintypes;
+
+import org.apache.isis.core.metamodel.spec.ObjectSpecification;
+import org.apache.isis.core.metamodel.spec.feature.ObjectActionParameter;
+
+public class ParentSpecAndActionParam extends ParentSpecAndFeature<ObjectActionParameter> {
+
+    public ParentSpecAndActionParam(final ObjectSpecification objectSpecification, final ObjectActionParameter actionParam) {
+        super(objectSpecification, actionParam);
+    }
+
+}
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/isis/blob/75f41b75/component/viewer/restfulobjects/rendering/src/main/java/org/apache/isis/viewer/restfulobjects/rendering/domaintypes/ParentSpecAndCollection.java
----------------------------------------------------------------------
diff --git a/component/viewer/restfulobjects/rendering/src/main/java/org/apache/isis/viewer/restfulobjects/rendering/domaintypes/ParentSpecAndCollection.java b/component/viewer/restfulobjects/rendering/src/main/java/org/apache/isis/viewer/restfulobjects/rendering/domaintypes/ParentSpecAndCollection.java
new file mode 100644
index 0000000..d2c6029
--- /dev/null
+++ b/component/viewer/restfulobjects/rendering/src/main/java/org/apache/isis/viewer/restfulobjects/rendering/domaintypes/ParentSpecAndCollection.java
@@ -0,0 +1,30 @@
+/*
+ *  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.restfulobjects.rendering.domaintypes;
+
+import org.apache.isis.core.metamodel.spec.ObjectSpecification;
+import org.apache.isis.core.metamodel.spec.feature.OneToManyAssociation;
+
+public class ParentSpecAndCollection extends ParentSpecAndFeature<OneToManyAssociation> {
+
+    public ParentSpecAndCollection(final ObjectSpecification objectSpecification, final OneToManyAssociation collection) {
+        super(objectSpecification, collection);
+    }
+
+}
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/isis/blob/75f41b75/component/viewer/restfulobjects/rendering/src/main/java/org/apache/isis/viewer/restfulobjects/rendering/domaintypes/ParentSpecAndFeature.java
----------------------------------------------------------------------
diff --git a/component/viewer/restfulobjects/rendering/src/main/java/org/apache/isis/viewer/restfulobjects/rendering/domaintypes/ParentSpecAndFeature.java b/component/viewer/restfulobjects/rendering/src/main/java/org/apache/isis/viewer/restfulobjects/rendering/domaintypes/ParentSpecAndFeature.java
new file mode 100644
index 0000000..d1ed13f
--- /dev/null
+++ b/component/viewer/restfulobjects/rendering/src/main/java/org/apache/isis/viewer/restfulobjects/rendering/domaintypes/ParentSpecAndFeature.java
@@ -0,0 +1,42 @@
+/*
+ *  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.restfulobjects.rendering.domaintypes;
+
+import org.apache.isis.core.metamodel.spec.ObjectSpecification;
+import org.apache.isis.core.metamodel.spec.feature.ObjectFeature;
+
+public abstract class ParentSpecAndFeature<T extends ObjectFeature> {
+
+    private final ObjectSpecification parentSpec;
+    private final T objectFeature;
+
+    public ParentSpecAndFeature(final ObjectSpecification objectSpecification, final T objectFeature) {
+        this.parentSpec = objectSpecification;
+        this.objectFeature = objectFeature;
+    }
+
+    public ObjectSpecification getParentSpec() {
+        return parentSpec;
+    }
+
+    public T getObjectFeature() {
+        return objectFeature;
+    }
+
+}
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/isis/blob/75f41b75/component/viewer/restfulobjects/rendering/src/main/java/org/apache/isis/viewer/restfulobjects/rendering/domaintypes/ParentSpecAndProperty.java
----------------------------------------------------------------------
diff --git a/component/viewer/restfulobjects/rendering/src/main/java/org/apache/isis/viewer/restfulobjects/rendering/domaintypes/ParentSpecAndProperty.java b/component/viewer/restfulobjects/rendering/src/main/java/org/apache/isis/viewer/restfulobjects/rendering/domaintypes/ParentSpecAndProperty.java
new file mode 100644
index 0000000..0ec418d
--- /dev/null
+++ b/component/viewer/restfulobjects/rendering/src/main/java/org/apache/isis/viewer/restfulobjects/rendering/domaintypes/ParentSpecAndProperty.java
@@ -0,0 +1,30 @@
+/*
+ *  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.restfulobjects.rendering.domaintypes;
+
+import org.apache.isis.core.metamodel.spec.ObjectSpecification;
+import org.apache.isis.core.metamodel.spec.feature.OneToOneAssociation;
+
+public class ParentSpecAndProperty extends ParentSpecAndFeature<OneToOneAssociation> {
+
+    public ParentSpecAndProperty(final ObjectSpecification objectSpecification, final OneToOneAssociation property) {
+        super(objectSpecification, property);
+    }
+
+}
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/isis/blob/75f41b75/component/viewer/restfulobjects/rendering/src/main/java/org/apache/isis/viewer/restfulobjects/rendering/domaintypes/PropertyDescriptionReprRenderer.java
----------------------------------------------------------------------
diff --git a/component/viewer/restfulobjects/rendering/src/main/java/org/apache/isis/viewer/restfulobjects/rendering/domaintypes/PropertyDescriptionReprRenderer.java b/component/viewer/restfulobjects/rendering/src/main/java/org/apache/isis/viewer/restfulobjects/rendering/domaintypes/PropertyDescriptionReprRenderer.java
new file mode 100644
index 0000000..b11d3fc
--- /dev/null
+++ b/component/viewer/restfulobjects/rendering/src/main/java/org/apache/isis/viewer/restfulobjects/rendering/domaintypes/PropertyDescriptionReprRenderer.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.viewer.restfulobjects.rendering.domaintypes;
+
+import org.apache.isis.core.metamodel.facets.maxlen.MaxLengthFacet;
+import org.apache.isis.core.metamodel.spec.ObjectSpecification;
+import org.apache.isis.core.metamodel.spec.feature.OneToOneAssociation;
+import org.apache.isis.viewer.restfulobjects.applib.JsonRepresentation;
+import org.apache.isis.viewer.restfulobjects.applib.RepresentationType;
+import org.apache.isis.viewer.restfulobjects.applib.links.Rel;
+import org.apache.isis.viewer.restfulobjects.rendering.LinkBuilder;
+import org.apache.isis.viewer.restfulobjects.rendering.LinkFollower;
+import org.apache.isis.viewer.restfulobjects.rendering.RendererContext;
+import org.apache.isis.viewer.restfulobjects.rendering.ReprRenderer;
+import org.apache.isis.viewer.restfulobjects.rendering.ReprRendererFactoryAbstract;
+
+public class PropertyDescriptionReprRenderer extends AbstractTypeMemberReprRenderer<PropertyDescriptionReprRenderer, OneToOneAssociation> {
+
+    public static class Factory extends ReprRendererFactoryAbstract {
+
+        public Factory() {
+            super(RepresentationType.PROPERTY_DESCRIPTION);
+        }
+
+        @Override
+        public ReprRenderer<?, ?> newRenderer(final RendererContext resourceContext, final LinkFollower linkFollower, final JsonRepresentation representation) {
+            return new PropertyDescriptionReprRenderer(resourceContext, linkFollower, getRepresentationType(), representation);
+        }
+    }
+
+    public static LinkBuilder newLinkToBuilder(final RendererContext resourceContext, final Rel rel, final ObjectSpecification objectSpecification, final OneToOneAssociation property) {
+        final String typeFullName = objectSpecification.getFullIdentifier();
+        final String propertyId = property.getId();
+        final String url = "domainTypes/" + typeFullName + "/properties/" + propertyId;
+        return LinkBuilder.newBuilder(resourceContext, rel, RepresentationType.PROPERTY_DESCRIPTION, url);
+    }
+
+    public PropertyDescriptionReprRenderer(final RendererContext resourceContext, final LinkFollower linkFollower, final RepresentationType representationType, final JsonRepresentation representation) {
+        super(resourceContext, linkFollower, representationType, representation);
+    }
+
+    @Override
+    protected void addLinksSpecificToFeature() {
+        addLinkToReturnTypeIfAny();
+    }
+
+    @Override
+    protected void addPropertiesSpecificToFeature() {
+        representation.mapPut("optional", !getObjectFeature().isMandatory());
+        final MaxLengthFacet maxLength = getObjectFeature().getFacet(MaxLengthFacet.class);
+        if (maxLength != null && !maxLength.isNoop()) {
+            representation.mapPut("maxLength", maxLength.value());
+        }
+    }
+
+    private void addLinkToReturnTypeIfAny() {
+        final ObjectSpecification returnType = getObjectFeature().getSpecification();
+        if (returnType == null) {
+            return;
+        }
+        final LinkBuilder linkBuilder = DomainTypeReprRenderer.newLinkToBuilder(getResourceContext(), Rel.RETURN_TYPE, returnType);
+        getLinks().arrayAdd(linkBuilder.build());
+    }
+
+    @Override
+    protected void putExtensionsSpecificToFeature() {
+        putExtensionsName();
+        putExtensionsDescriptionIfAvailable();
+    }
+
+}
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/isis/blob/75f41b75/component/viewer/restfulobjects/rendering/src/main/java/org/apache/isis/viewer/restfulobjects/rendering/domaintypes/TypeActionResultReprRenderer.java
----------------------------------------------------------------------
diff --git a/component/viewer/restfulobjects/rendering/src/main/java/org/apache/isis/viewer/restfulobjects/rendering/domaintypes/TypeActionResultReprRenderer.java b/component/viewer/restfulobjects/rendering/src/main/java/org/apache/isis/viewer/restfulobjects/rendering/domaintypes/TypeActionResultReprRenderer.java
new file mode 100644
index 0000000..83a258d
--- /dev/null
+++ b/component/viewer/restfulobjects/rendering/src/main/java/org/apache/isis/viewer/restfulobjects/rendering/domaintypes/TypeActionResultReprRenderer.java
@@ -0,0 +1,79 @@
+/**
+ *  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.restfulobjects.rendering.domaintypes;
+
+import org.apache.isis.core.metamodel.spec.ObjectSpecification;
+import org.apache.isis.viewer.restfulobjects.applib.JsonRepresentation;
+import org.apache.isis.viewer.restfulobjects.applib.RepresentationType;
+import org.apache.isis.viewer.restfulobjects.applib.links.LinkRepresentation;
+import org.apache.isis.viewer.restfulobjects.rendering.LinkFollower;
+import org.apache.isis.viewer.restfulobjects.rendering.RendererContext;
+import org.apache.isis.viewer.restfulobjects.rendering.ReprRenderer;
+import org.apache.isis.viewer.restfulobjects.rendering.ReprRendererAbstract;
+import org.apache.isis.viewer.restfulobjects.rendering.ReprRendererFactoryAbstract;
+
+public class TypeActionResultReprRenderer extends ReprRendererAbstract<TypeActionResultReprRenderer, ObjectSpecification> {
+
+    public static class Factory extends ReprRendererFactoryAbstract {
+        public Factory() {
+            super(RepresentationType.TYPE_ACTION_RESULT);
+        }
+
+        @Override
+        public ReprRenderer<?, ?> newRenderer(final RendererContext resourceContext, final LinkFollower linkFollower, final JsonRepresentation representation) {
+            return new TypeActionResultReprRenderer(resourceContext, linkFollower, getRepresentationType(), representation);
+        }
+    }
+
+    private ObjectSpecification objectSpecification;
+    private LinkRepresentation selfLink;
+    private Object value;
+
+    public TypeActionResultReprRenderer(final RendererContext resourceContext, final LinkFollower linkFollower, final RepresentationType representationType, final JsonRepresentation representation) {
+        super(resourceContext, linkFollower, representationType, representation);
+    }
+
+    @Override
+    public TypeActionResultReprRenderer with(final ObjectSpecification objectSpecification) {
+        this.objectSpecification = objectSpecification;
+        return cast(this);
+    }
+
+    public TypeActionResultReprRenderer withValue(final Object value) {
+        this.value = value;
+        return this;
+    }
+
+    @Override
+    public JsonRepresentation render() {
+        if (includesSelf && selfLink != null) {
+            getLinks().arrayAdd(selfLink);
+        }
+
+        if (value != null) {
+            representation.mapPut("value", value);
+        }
+        getExtensions();
+
+        return representation;
+    }
+
+    protected void putExtensionsIfService() {
+        getExtensions().mapPut("isService", objectSpecification.isService());
+    }
+
+}
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/isis/blob/75f41b75/component/viewer/restfulobjects/rendering/src/main/java/org/apache/isis/viewer/restfulobjects/rendering/domaintypes/TypeListReprRenderer.java
----------------------------------------------------------------------
diff --git a/component/viewer/restfulobjects/rendering/src/main/java/org/apache/isis/viewer/restfulobjects/rendering/domaintypes/TypeListReprRenderer.java b/component/viewer/restfulobjects/rendering/src/main/java/org/apache/isis/viewer/restfulobjects/rendering/domaintypes/TypeListReprRenderer.java
new file mode 100644
index 0000000..5536306
--- /dev/null
+++ b/component/viewer/restfulobjects/rendering/src/main/java/org/apache/isis/viewer/restfulobjects/rendering/domaintypes/TypeListReprRenderer.java
@@ -0,0 +1,80 @@
+/*
+ *  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.restfulobjects.rendering.domaintypes;
+
+import java.util.Collection;
+
+import org.apache.isis.core.metamodel.spec.ObjectSpecification;
+import org.apache.isis.viewer.restfulobjects.applib.JsonRepresentation;
+import org.apache.isis.viewer.restfulobjects.applib.RepresentationType;
+import org.apache.isis.viewer.restfulobjects.applib.links.Rel;
+import org.apache.isis.viewer.restfulobjects.rendering.LinkBuilder;
+import org.apache.isis.viewer.restfulobjects.rendering.LinkFollower;
+import org.apache.isis.viewer.restfulobjects.rendering.RendererContext;
+import org.apache.isis.viewer.restfulobjects.rendering.ReprRenderer;
+import org.apache.isis.viewer.restfulobjects.rendering.ReprRendererAbstract;
+import org.apache.isis.viewer.restfulobjects.rendering.ReprRendererFactoryAbstract;
+
+public class TypeListReprRenderer extends ReprRendererAbstract<TypeListReprRenderer, Collection<ObjectSpecification>> {
+
+    private Collection<ObjectSpecification> specifications;
+
+    public static class Factory extends ReprRendererFactoryAbstract {
+        public Factory() {
+            super(RepresentationType.TYPE_LIST);
+        }
+
+        @Override
+        public ReprRenderer<?, ?> newRenderer(final RendererContext resourceContext, final LinkFollower linkFollower, final JsonRepresentation representation) {
+            return new TypeListReprRenderer(resourceContext, linkFollower, getRepresentationType(), representation);
+        }
+    }
+
+    private TypeListReprRenderer(final RendererContext resourceContext, final LinkFollower linkFollower, final RepresentationType representationType, final JsonRepresentation representation) {
+        super(resourceContext, linkFollower, representationType, representation);
+    }
+
+    @Override
+    public TypeListReprRenderer with(final Collection<ObjectSpecification> specifications) {
+        this.specifications = specifications;
+        return this;
+    }
+
+    @Override
+    public JsonRepresentation render() {
+
+        // self
+        if (includesSelf) {
+            withSelf("domainTypes");
+        }
+
+        final JsonRepresentation specList = JsonRepresentation.newArray();
+        for (final ObjectSpecification objectSpec : specifications) {
+            final LinkBuilder linkBuilder = LinkBuilder.newBuilder(getResourceContext(), Rel.DOMAIN_TYPE, RepresentationType.DOMAIN_TYPE, "domainTypes/%s", objectSpec.getFullIdentifier());
+            specList.arrayAdd(linkBuilder.build());
+        }
+
+        representation.mapPut("values", specList);
+
+        getExtensions(); // empty
+
+        return representation;
+    }
+
+}
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/isis/blob/75f41b75/component/viewer/restfulobjects/rendering/src/main/java/org/apache/isis/viewer/restfulobjects/rendering/util/GraphUtil.java
----------------------------------------------------------------------
diff --git a/component/viewer/restfulobjects/rendering/src/main/java/org/apache/isis/viewer/restfulobjects/rendering/util/GraphUtil.java b/component/viewer/restfulobjects/rendering/src/main/java/org/apache/isis/viewer/restfulobjects/rendering/util/GraphUtil.java
new file mode 100644
index 0000000..c797b1f
--- /dev/null
+++ b/component/viewer/restfulobjects/rendering/src/main/java/org/apache/isis/viewer/restfulobjects/rendering/util/GraphUtil.java
@@ -0,0 +1,60 @@
+/*
+ *  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.restfulobjects.rendering.util;
+
+import java.util.Collections;
+import java.util.List;
+import java.util.Map;
+
+import org.apache.isis.viewer.restfulobjects.applib.util.PathNode;
+
+import com.google.common.collect.Maps;
+
+@SuppressWarnings({ "rawtypes", "unchecked" })
+public final class GraphUtil {
+
+    private GraphUtil() {
+    }
+
+    public final static Map<PathNode, Map> asGraph(final List<List<String>> links) {
+        if (links == null) {
+            return Collections.emptyMap();
+        }
+        final Map<PathNode, Map> map = Maps.newHashMap();
+        for (final List<String> link : links) {
+            GraphUtil.mergeInto(link, map);
+        }
+        return map;
+    }
+
+    private static void mergeInto(final List<String> list, final Map<PathNode, Map> map) {
+        if (list.size() == 0) {
+            return;
+        }
+        final String str = list.get(0);
+        final PathNode node = PathNode.parse(str);
+        Map<PathNode, Map> submap = map.get(node);
+        if (submap == null) {
+            submap = Maps.newHashMap();
+            map.put(node, submap);
+        }
+        mergeInto(list.subList(1, list.size()), submap);
+    }
+
+}