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
[8/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/ActionResultReprRenderer.java
----------------------------------------------------------------------
diff --git a/component/viewer/restfulobjects/rendering/src/main/java/org/apache/isis/viewer/restfulobjects/rendering/domainobjects/ActionResultReprRenderer.java b/component/viewer/restfulobjects/rendering/src/main/java/org/apache/isis/viewer/restfulobjects/rendering/domainobjects/ActionResultReprRenderer.java
new file mode 100644
index 0000000..5109cb5
--- /dev/null
+++ b/component/viewer/restfulobjects/rendering/src/main/java/org/apache/isis/viewer/restfulobjects/rendering/domainobjects/ActionResultReprRenderer.java
@@ -0,0 +1,183 @@
+/**
+ * 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.Collection;
+import java.util.Map;
+
+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.object.encodeable.EncodableFacet;
+import org.apache.isis.core.metamodel.spec.ObjectSpecification;
+import org.apache.isis.core.metamodel.spec.feature.ObjectAction;
+import org.apache.isis.viewer.restfulobjects.applib.JsonRepresentation;
+import org.apache.isis.viewer.restfulobjects.applib.RepresentationType;
+import org.apache.isis.viewer.restfulobjects.applib.domainobjects.ActionResultRepresentation.ResultType;
+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.ReprRendererAbstract;
+import org.apache.isis.viewer.restfulobjects.rendering.ReprRendererFactoryAbstract;
+
+public class ActionResultReprRenderer extends ReprRendererAbstract<ActionResultReprRenderer, ObjectAndActionInvocation> {
+
+ private ObjectAdapterLinkTo adapterLinkTo = new DomainObjectLinkTo();
+
+ private ObjectAdapter objectAdapter;
+ private ObjectAction action;
+ private JsonRepresentation arguments;
+ private ObjectAdapter returnedAdapter;
+
+ public static class Factory extends ReprRendererFactoryAbstract {
+
+ public Factory() {
+ super(RepresentationType.ACTION_RESULT);
+ }
+
+ @Override
+ public ReprRenderer<?, ?> newRenderer(final RendererContext resourceContext, final LinkFollower linkFollower, final JsonRepresentation representation) {
+ return new ActionResultReprRenderer(resourceContext, linkFollower, getRepresentationType(), representation);
+ }
+ }
+
+ private ActionResultReprRenderer(final RendererContext resourceContext, final LinkFollower linkFollower, final RepresentationType representationType, final JsonRepresentation representation) {
+ super(resourceContext, linkFollower, representationType, representation);
+ }
+
+ @Override
+ public ActionResultReprRenderer with(final ObjectAndActionInvocation objectAndActionInvocation) {
+
+ objectAdapter = objectAndActionInvocation.getObjectAdapter();
+ action = objectAndActionInvocation.getAction();
+ arguments = objectAndActionInvocation.getArguments();
+ returnedAdapter = objectAndActionInvocation.getReturnedAdapter();
+
+ adapterLinkTo.with(returnedAdapter);
+
+ return this;
+ }
+
+ public void using(final ObjectAdapterLinkTo adapterLinkTo) {
+ this.adapterLinkTo = adapterLinkTo.with(objectAdapter);
+ }
+
+ @Override
+ public JsonRepresentation render() {
+
+ representationWithSelfFor(action, arguments);
+
+ addResult(representation);
+
+ addExtensionsIsisProprietaryChangedObjects();
+
+ return representation;
+ }
+
+ private void addResult(final JsonRepresentation representation) {
+ final JsonRepresentation result = JsonRepresentation.newMap();
+ final ResultType resultType = addResultTo(result);
+
+ if (!resultType.isVoid()) {
+ putResultType(representation, resultType);
+ representation.mapPut("result", result);
+ }
+ }
+
+ private ResultType addResultTo(final JsonRepresentation result) {
+
+ final ObjectSpecification returnType = this.action.getReturnType();
+
+ if (returnType.getCorrespondingClass() == void.class) {
+ // void
+ return ResultType.VOID;
+ }
+
+ final CollectionFacet collectionFacet = returnType.getFacet(CollectionFacet.class);
+ if (collectionFacet != null) {
+ // collection
+
+ final Collection<ObjectAdapter> collectionAdapters = collectionFacet.collection(returnedAdapter);
+
+ final RendererFactory factory = getRendererFactoryRegistry().find(RepresentationType.LIST);
+ final ListReprRenderer renderer = (ListReprRenderer) factory.newRenderer(resourceContext, null, result);
+ renderer.with(collectionAdapters).withReturnType(action.getReturnType()).withElementType(returnedAdapter.getElementSpecification());
+
+ renderer.render();
+ return ResultType.LIST;
+ }
+
+ final EncodableFacet encodableFacet = returnType.getFacet(EncodableFacet.class);
+ if (encodableFacet != null) {
+ // scalar
+
+ final RendererFactory factory = getRendererFactoryRegistry().find(RepresentationType.SCALAR_VALUE);
+
+ final ScalarValueReprRenderer renderer = (ScalarValueReprRenderer) factory.newRenderer(resourceContext, null, result);
+ renderer.with(returnedAdapter).withReturnType(action.getReturnType());
+
+ renderer.render();
+ return ResultType.SCALAR_VALUE;
+
+ }
+
+ {
+ // object
+ final RendererFactory factory = getRendererFactoryRegistry().find(RepresentationType.DOMAIN_OBJECT);
+ final DomainObjectReprRenderer renderer = (DomainObjectReprRenderer) factory.newRenderer(resourceContext, null, result);
+
+ renderer.with(returnedAdapter).includesSelf();
+
+ renderer.render();
+ return ResultType.DOMAIN_OBJECT;
+ }
+ }
+
+ private void putResultType(final JsonRepresentation representation, final ResultType resultType) {
+ representation.mapPut("resulttype", resultType.getValue());
+ }
+
+ private JsonRepresentation representationWithSelfFor(final ObjectAction action, final JsonRepresentation bodyArgs) {
+ final JsonRepresentation links = JsonRepresentation.newArray();
+ representation.mapPut("links", links);
+
+ final LinkBuilder selfLinkBuilder = adapterLinkTo.memberBuilder(Rel.SELF, MemberType.ACTION, action, RepresentationType.ACTION_RESULT, "invoke");
+
+ // TODO: remove duplication with AbstractObjectMember#addLinkTo
+ final MemberType memberType = MemberType.of(action);
+ final Map<String, MutatorSpec> mutators = memberType.getMutators();
+
+ final String mutator = InvokeKeys.getKeyFor(action.getSemantics());
+ final MutatorSpec mutatorSpec = mutators.get(mutator);
+ selfLinkBuilder.withHttpMethod(mutatorSpec.httpMethod);
+
+ final JsonRepresentation selfLink = selfLinkBuilder.build();
+
+ links.arrayAdd(selfLink);
+ selfLink.mapPut("args", bodyArgs);
+ return representation;
+ }
+
+ protected RendererFactoryRegistry getRendererFactoryRegistry() {
+ // TODO: yuck
+ return RendererFactoryRegistry.instance;
+ }
+
+}
\ 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/BodyArgs.java
----------------------------------------------------------------------
diff --git a/component/viewer/restfulobjects/rendering/src/main/java/org/apache/isis/viewer/restfulobjects/rendering/domainobjects/BodyArgs.java b/component/viewer/restfulobjects/rendering/src/main/java/org/apache/isis/viewer/restfulobjects/rendering/domainobjects/BodyArgs.java
new file mode 100644
index 0000000..2fc35b9
--- /dev/null
+++ b/component/viewer/restfulobjects/rendering/src/main/java/org/apache/isis/viewer/restfulobjects/rendering/domainobjects/BodyArgs.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.domainobjects;
+
+public enum BodyArgs {
+ /**
+ * eg property clear
+ */
+ NONE,
+ /**
+ * eg property modify, collection addto/remove
+ */
+ ONE,
+ /**
+ * eg action invoke
+ */
+ MANY;
+
+ public boolean isOne() {
+ return this == ONE;
+ }
+
+ public boolean isNone() {
+ return this == NONE;
+ }
+
+}
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/CollectionSemantics.java
----------------------------------------------------------------------
diff --git a/component/viewer/restfulobjects/rendering/src/main/java/org/apache/isis/viewer/restfulobjects/rendering/domainobjects/CollectionSemantics.java b/component/viewer/restfulobjects/rendering/src/main/java/org/apache/isis/viewer/restfulobjects/rendering/domainobjects/CollectionSemantics.java
new file mode 100644
index 0000000..4075016
--- /dev/null
+++ b/component/viewer/restfulobjects/rendering/src/main/java/org/apache/isis/viewer/restfulobjects/rendering/domainobjects/CollectionSemantics.java
@@ -0,0 +1,46 @@
+/*
+ * 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.spec.feature.OneToManyAssociation;
+
+public enum CollectionSemantics {
+
+ SET("addToSet"),
+ LIST("addToList");
+
+ private final String addToKey;
+
+ private CollectionSemantics(final String addToKey) {
+ this.addToKey = addToKey;
+ }
+
+ public String getAddToKey() {
+ return addToKey;
+ }
+
+ public String getRemoveFromKey() {
+ return "removeFrom";
+ }
+
+ public static CollectionSemantics determine(final OneToManyAssociation collection) {
+ return collection.getCollectionSemantics().isSet() ? CollectionSemantics.SET : CollectionSemantics.LIST;
+ }
+
+}
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/DomainObjectLinkTo.java
----------------------------------------------------------------------
diff --git a/component/viewer/restfulobjects/rendering/src/main/java/org/apache/isis/viewer/restfulobjects/rendering/domainobjects/DomainObjectLinkTo.java b/component/viewer/restfulobjects/rendering/src/main/java/org/apache/isis/viewer/restfulobjects/rendering/domainobjects/DomainObjectLinkTo.java
new file mode 100644
index 0000000..03a78c8
--- /dev/null
+++ b/component/viewer/restfulobjects/rendering/src/main/java/org/apache/isis/viewer/restfulobjects/rendering/domainobjects/DomainObjectLinkTo.java
@@ -0,0 +1,113 @@
+/**
+ * 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.adapter.oid.OidMarshaller;
+import org.apache.isis.core.metamodel.spec.feature.ObjectMember;
+import org.apache.isis.core.runtime.system.context.IsisContext;
+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.RendererContext;
+
+public class DomainObjectLinkTo implements ObjectAdapterLinkTo {
+
+ protected RendererContext resourceContext;
+ protected ObjectAdapter objectAdapter;
+
+ @Override
+ public final DomainObjectLinkTo usingUrlBase(final RendererContext resourceContext) {
+ this.resourceContext = resourceContext;
+ return this;
+ }
+
+ @Override
+ public ObjectAdapterLinkTo with(final ObjectAdapter objectAdapter) {
+ this.objectAdapter = objectAdapter;
+ return this;
+ }
+
+ @Override
+ public LinkBuilder builder() {
+ return builder(null);
+ }
+
+ @Override
+ public LinkBuilder builder(final Rel rel) {
+ final LinkBuilder linkBuilder = LinkBuilder.newBuilder(resourceContext, relElseDefault(rel), RepresentationType.DOMAIN_OBJECT, linkRef());
+ linkBuilder.withTitle(objectAdapter.titleString());
+ return linkBuilder;
+ }
+
+ /**
+ * hook method
+ */
+ protected String linkRef() {
+ if (resourceContext == null) {
+ throw new IllegalStateException("resourceContext not provided");
+ }
+ if (objectAdapter == null) {
+ throw new IllegalStateException("objectAdapter not provided");
+ }
+ final StringBuilder buf = new StringBuilder("objects/");
+ buf.append(objectAdapter.getOid().enString(getOidMarshaller()));
+ return buf.toString();
+ }
+
+ private Rel relElseDefault(final Rel rel) {
+ return rel != null ? rel : defaultRel();
+ }
+
+ /**
+ * hook method; used by {@link #builder(Rel)}.
+ */
+ protected Rel defaultRel() {
+ return Rel.OBJECT;
+ }
+
+ @Override
+ public final LinkBuilder memberBuilder(final Rel rel, final MemberType memberType, final ObjectMember objectMember, final String... parts) {
+ return memberBuilder(rel, memberType, objectMember, memberType.getRepresentationType(), parts);
+ }
+
+ @Override
+ public final LinkBuilder memberBuilder(final Rel rel, final MemberType memberType, final ObjectMember objectMember, final RepresentationType representationType, final String... parts) {
+ final StringBuilder buf = new StringBuilder(linkRef());
+ buf.append("/").append(memberType.getUrlPart()).append(objectMember.getId());
+ for (final String part : parts) {
+ if (part == null) {
+ continue;
+ }
+ buf.append("/").append(part);
+ }
+ final String url = buf.toString();
+ return LinkBuilder.newBuilder(resourceContext, rel, representationType, url);
+ }
+
+
+
+ //////////////////////////////////////////////////
+ // Dependencies (from context)
+ //////////////////////////////////////////////////
+
+ protected static OidMarshaller getOidMarshaller() {
+ return IsisContext.getOidMarshaller();
+ }
+
+
+}
\ 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/DomainObjectReprRenderer.java
----------------------------------------------------------------------
diff --git a/component/viewer/restfulobjects/rendering/src/main/java/org/apache/isis/viewer/restfulobjects/rendering/domainobjects/DomainObjectReprRenderer.java b/component/viewer/restfulobjects/rendering/src/main/java/org/apache/isis/viewer/restfulobjects/rendering/domainobjects/DomainObjectReprRenderer.java
new file mode 100644
index 0000000..192774e
--- /dev/null
+++ b/component/viewer/restfulobjects/rendering/src/main/java/org/apache/isis/viewer/restfulobjects/rendering/domainobjects/DomainObjectReprRenderer.java
@@ -0,0 +1,313 @@
+/**
+ * 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 org.apache.isis.core.metamodel.adapter.ObjectAdapter;
+import org.apache.isis.core.metamodel.adapter.oid.OidMarshaller;
+import org.apache.isis.core.metamodel.adapter.oid.RootOid;
+import org.apache.isis.core.metamodel.consent.Consent;
+import org.apache.isis.core.metamodel.facets.object.title.TitleFacet;
+import org.apache.isis.core.metamodel.facets.object.value.ValueFacet;
+import org.apache.isis.core.metamodel.services.ServiceUtil;
+import org.apache.isis.core.metamodel.spec.ObjectActionSet;
+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.core.runtime.system.context.IsisContext;
+import org.apache.isis.viewer.restfulobjects.applib.JsonRepresentation;
+import org.apache.isis.viewer.restfulobjects.applib.RepresentationType;
+import org.apache.isis.viewer.restfulobjects.applib.RoHttpMethod;
+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.ReprRendererAbstract;
+import org.apache.isis.viewer.restfulobjects.rendering.ReprRendererFactoryAbstract;
+import org.apache.isis.viewer.restfulobjects.rendering.domaintypes.DomainTypeReprRenderer;
+import org.apache.isis.viewer.restfulobjects.rendering.util.OidUtils;
+
+public class DomainObjectReprRenderer extends ReprRendererAbstract<DomainObjectReprRenderer, ObjectAdapter> {
+
+ public static class Factory extends ReprRendererFactoryAbstract {
+
+ public Factory() {
+ super(RepresentationType.DOMAIN_OBJECT);
+ }
+
+ @Override
+ public ReprRenderer<?, ?> newRenderer(final RendererContext resourceContext, final LinkFollower linkFollower, final JsonRepresentation representation) {
+ return new DomainObjectReprRenderer(resourceContext, linkFollower, getRepresentationType(), representation);
+ }
+ }
+
+ public static LinkBuilder newLinkToBuilder(final RendererContext resourceContext, final Rel rel, final ObjectAdapter elementAdapter) {
+ final String oidStr = ((RootOid) elementAdapter.getOid()).enString(getOidMarshaller());
+ final String url = "objects/" + oidStr;
+ final LinkBuilder builder = LinkBuilder.newBuilder(resourceContext, rel, RepresentationType.DOMAIN_OBJECT, url).withTitle(elementAdapter.titleString());
+ return builder;
+ }
+
+ private static enum Mode {
+ REGULAR(false, true), PERSIST_LINK_ARGUMENTS(true, true), MODIFY_PROPERTIES_LINK_ARGUMENTS(true, false);
+
+ private final boolean cutDown;
+ private final boolean describedBy;
+
+ private Mode(final boolean cutDown, final boolean describedBy) {
+ this.cutDown = cutDown;
+ this.describedBy = describedBy;
+ }
+
+ public boolean isCutDown() {
+ return cutDown;
+ }
+
+ public boolean includesDescribedBy() {
+ return describedBy;
+ }
+ }
+
+ private ObjectAdapterLinkTo linkToBuilder;
+ private ObjectAdapter objectAdapter;
+ private Mode mode = Mode.REGULAR;
+
+ private DomainObjectReprRenderer(final RendererContext resourceContext, final LinkFollower linkFollower, final RepresentationType representationType, final JsonRepresentation representation) {
+ super(resourceContext, linkFollower, representationType, representation);
+ usingLinkToBuilder(new DomainObjectLinkTo());
+ }
+
+ /**
+ * Override the default {@link ObjectAdapterLinkTo} (that is used for
+ * generating links in {@link #linkTo(ObjectAdapter)}).
+ */
+ public DomainObjectReprRenderer usingLinkToBuilder(final ObjectAdapterLinkTo objectAdapterLinkToBuilder) {
+ this.linkToBuilder = objectAdapterLinkToBuilder.usingUrlBase(resourceContext);
+ return this;
+ }
+
+ @Override
+ public DomainObjectReprRenderer with(final ObjectAdapter objectAdapter) {
+ this.objectAdapter = objectAdapter;
+ return this;
+ }
+
+ @Override
+ public JsonRepresentation render() {
+
+ // self, oid
+ if (!mode.isCutDown()) {
+ if (objectAdapter.representsPersistent()) {
+ if (includesSelf) {
+ final JsonRepresentation self = linkToBuilder.with(objectAdapter).builder(Rel.SELF).build();
+ getLinks().arrayAdd(self);
+ }
+ representation.mapPut("oid", getOidStr());
+ }
+ }
+
+ // title
+ if (!mode.isCutDown()) {
+ final String title = objectAdapter.titleString();
+ representation.mapPut("title", title);
+
+ }
+
+ // serviceId
+ if (!mode.isCutDown()) {
+ final boolean isService = objectAdapter.getSpecification().isService();
+ if (isService) {
+ representation.mapPut("serviceId", ServiceUtil.id(objectAdapter.getObject()));
+ }
+ }
+
+ // members
+ withMembers(objectAdapter);
+
+ // described by
+ if (mode.includesDescribedBy()) {
+ getLinks().arrayAdd(DomainTypeReprRenderer.newLinkToBuilder(getResourceContext(), Rel.DESCRIBEDBY, objectAdapter.getSpecification()).build());
+ }
+
+ if (!mode.isCutDown()) {
+ // update/persist
+ addPersistLinkIfTransient();
+ addUpdatePropertiesLinkIfPersistent();
+
+ // extensions
+ final boolean isService = objectAdapter.getSpecification().isService();
+ getExtensions().mapPut("isService", isService);
+ getExtensions().mapPut("isPersistent", objectAdapter.representsPersistent());
+ }
+
+ return representation;
+ }
+
+ private String getOidStr() {
+ return OidUtils.getOidStr(resourceContext, objectAdapter);
+ }
+
+ private DomainObjectReprRenderer withMembers(final ObjectAdapter objectAdapter) {
+ final JsonRepresentation members = JsonRepresentation.newArray();
+ final List<ObjectAssociation> associations = objectAdapter.getSpecification().getAssociations();
+ addAssociations(objectAdapter, members, associations);
+
+ if (!mode.isCutDown()) {
+ final List<ObjectAction> actions = objectAdapter.getSpecification().getObjectActions(Contributed.INCLUDED);
+ addActions(objectAdapter, actions, members);
+ }
+ representation.mapPut("members", members);
+ return this;
+ }
+
+ private void addAssociations(final ObjectAdapter objectAdapter, final JsonRepresentation members, final List<ObjectAssociation> associations) {
+ final LinkFollower linkFollower = getLinkFollower().follow("members");
+ for (final ObjectAssociation assoc : associations) {
+
+ if (!mode.isCutDown()) {
+ final Consent visibility = assoc.isVisible(getAuthenticationSession(), objectAdapter, resourceContext.getWhere());
+ if (!visibility.isAllowed()) {
+ continue;
+ }
+ }
+ if (assoc instanceof OneToOneAssociation) {
+ final OneToOneAssociation property = (OneToOneAssociation) assoc;
+
+ final RendererFactory factory = getRendererFactoryRegistry().find(RepresentationType.OBJECT_PROPERTY);
+ final ObjectPropertyReprRenderer renderer = (ObjectPropertyReprRenderer) factory.newRenderer(getResourceContext(), linkFollower, JsonRepresentation.newMap());
+
+ renderer.with(new ObjectAndProperty(objectAdapter, property)).usingLinkTo(linkToBuilder);
+
+ if (mode.isCutDown()) {
+ renderer.asArguments();
+ }
+
+ members.arrayAdd(renderer.render());
+ }
+
+ if (mode.isCutDown()) {
+ // don't include collections
+ continue;
+ }
+ if (assoc instanceof OneToManyAssociation) {
+ final OneToManyAssociation collection = (OneToManyAssociation) assoc;
+
+ final RendererFactory factory = getRendererFactoryRegistry().find(RepresentationType.OBJECT_COLLECTION);
+ final ObjectCollectionReprRenderer renderer = (ObjectCollectionReprRenderer) factory.newRenderer(getResourceContext(), linkFollower, JsonRepresentation.newMap());
+
+ renderer.with(new ObjectAndCollection(objectAdapter, collection)).usingLinkTo(linkToBuilder);
+
+ members.arrayAdd(renderer.render());
+ }
+ }
+ }
+
+ private void addActions(final ObjectAdapter objectAdapter, final List<ObjectAction> actions, final JsonRepresentation members) {
+ final LinkFollower linkFollower = getLinkFollower().follow("members");
+ for (final ObjectAction action : actions) {
+ final Consent visibility = action.isVisible(getAuthenticationSession(), objectAdapter, resourceContext.getWhere());
+ if (!visibility.isAllowed()) {
+ continue;
+ }
+ if (action.getType().isSet()) {
+ final ObjectActionSet objectActionSet = (ObjectActionSet) action;
+ final List<ObjectAction> subactions = objectActionSet.getActions();
+ addActions(objectAdapter, subactions, members);
+
+ } else {
+
+ final RendererFactory factory = getRendererFactoryRegistry().find(RepresentationType.OBJECT_ACTION);
+ final ObjectActionReprRenderer renderer = (ObjectActionReprRenderer) factory.newRenderer(getResourceContext(), linkFollower, JsonRepresentation.newMap());
+
+ renderer.with(new ObjectAndAction(objectAdapter, action)).usingLinkTo(linkToBuilder);
+
+ members.arrayAdd(renderer.render());
+ }
+ }
+ }
+
+ private void addPersistLinkIfTransient() {
+ if (objectAdapter.representsPersistent()) {
+ return;
+ }
+ final RendererFactory rendererFactory = getRendererFactoryRegistry().find(RepresentationType.DOMAIN_OBJECT);
+ final DomainObjectReprRenderer renderer = (DomainObjectReprRenderer) rendererFactory.newRenderer(getResourceContext(), null, JsonRepresentation.newMap());
+ final JsonRepresentation domainObjectRepr = renderer.with(objectAdapter).asPersistLinkArguments().render();
+
+ final LinkBuilder persistLinkBuilder = LinkBuilder.newBuilder(getResourceContext(), Rel.PERSIST, RepresentationType.DOMAIN_OBJECT, "objects/").withHttpMethod(RoHttpMethod.POST).withArguments(domainObjectRepr);
+ getLinks().arrayAdd(persistLinkBuilder.build());
+ }
+
+ private DomainObjectReprRenderer asPersistLinkArguments() {
+ this.mode = Mode.PERSIST_LINK_ARGUMENTS;
+ return this;
+ }
+
+ private DomainObjectReprRenderer asModifyPropertiesLinkArguments() {
+ this.mode = Mode.MODIFY_PROPERTIES_LINK_ARGUMENTS;
+ return this;
+ }
+
+ private void addUpdatePropertiesLinkIfPersistent() {
+ if (!objectAdapter.representsPersistent()) {
+ return;
+ }
+
+ final RendererFactory rendererFactory = getRendererFactoryRegistry().find(RepresentationType.DOMAIN_OBJECT);
+ final DomainObjectReprRenderer renderer = (DomainObjectReprRenderer) rendererFactory.newRenderer(getResourceContext(), null, JsonRepresentation.newMap());
+ final JsonRepresentation domainObjectRepr = renderer.with(objectAdapter).asModifyPropertiesLinkArguments().render();
+
+ final LinkBuilder persistLinkBuilder = LinkBuilder.newBuilder(getResourceContext(), Rel.MODIFY, RepresentationType.DOMAIN_OBJECT, "objects/%s", getOidStr()).withHttpMethod(RoHttpMethod.PUT).withArguments(domainObjectRepr);
+ getLinks().arrayAdd(persistLinkBuilder.build());
+ }
+
+ protected RendererFactoryRegistry getRendererFactoryRegistry() {
+ return RendererFactoryRegistry.instance;
+ }
+
+ // ///////////////////////////////////////////////////////////////////
+ //
+ // ///////////////////////////////////////////////////////////////////
+
+ public static Object valueOrRef(final RendererContext resourceContext, final ObjectAdapter objectAdapter, final ObjectSpecification objectSpec) {
+ final ValueFacet valueFacet = objectSpec.getFacet(ValueFacet.class);
+ if (valueFacet != null) {
+ return new JsonValueEncoder().asObject(objectAdapter);
+ }
+ final TitleFacet titleFacet = objectSpec.getFacet(TitleFacet.class);
+ final String title = titleFacet.title(objectAdapter, resourceContext.getLocalization());
+ return DomainObjectReprRenderer.newLinkToBuilder(resourceContext, Rel.OBJECT, objectAdapter).withTitle(title).build();
+ }
+
+
+
+ // ///////////////////////////////////////////////////////////////////
+ // dependencies (from context)
+ // ///////////////////////////////////////////////////////////////////
+
+ protected static OidMarshaller getOidMarshaller() {
+ return IsisContext.getOidMarshaller();
+ }
+
+}
\ 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/DomainServiceLinkTo.java
----------------------------------------------------------------------
diff --git a/component/viewer/restfulobjects/rendering/src/main/java/org/apache/isis/viewer/restfulobjects/rendering/domainobjects/DomainServiceLinkTo.java b/component/viewer/restfulobjects/rendering/src/main/java/org/apache/isis/viewer/restfulobjects/rendering/domainobjects/DomainServiceLinkTo.java
new file mode 100644
index 0000000..f3fce41
--- /dev/null
+++ b/component/viewer/restfulobjects/rendering/src/main/java/org/apache/isis/viewer/restfulobjects/rendering/domainobjects/DomainServiceLinkTo.java
@@ -0,0 +1,50 @@
+/**
+ * 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.services.ServiceUtil;
+import org.apache.isis.viewer.restfulobjects.applib.links.Rel;
+import org.apache.isis.viewer.restfulobjects.rendering.LinkBuilder;
+
+public class DomainServiceLinkTo extends DomainObjectLinkTo {
+ private String serviceId;
+
+ @Override
+ public ObjectAdapterLinkTo with(final ObjectAdapter objectAdapter) {
+ serviceId = ServiceUtil.id(objectAdapter.getObject());
+ return super.with(objectAdapter);
+ }
+
+ @Override
+ protected String linkRef() {
+ final StringBuilder buf = new StringBuilder("services/");
+ buf.append(serviceId);
+ return buf.toString();
+ }
+
+ @Override
+ protected Rel defaultRel() {
+ return Rel.SERVICE;
+ }
+
+ @Override
+ public LinkBuilder builder(final Rel rel) {
+ return super.builder(rel).withId(serviceId);
+ }
+
+}
\ 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/InvokeKeys.java
----------------------------------------------------------------------
diff --git a/component/viewer/restfulobjects/rendering/src/main/java/org/apache/isis/viewer/restfulobjects/rendering/domainobjects/InvokeKeys.java b/component/viewer/restfulobjects/rendering/src/main/java/org/apache/isis/viewer/restfulobjects/rendering/domainobjects/InvokeKeys.java
new file mode 100644
index 0000000..bf116e9
--- /dev/null
+++ b/component/viewer/restfulobjects/rendering/src/main/java/org/apache/isis/viewer/restfulobjects/rendering/domainobjects/InvokeKeys.java
@@ -0,0 +1,40 @@
+/*
+ * 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.EnumMap;
+
+import org.apache.isis.applib.annotation.ActionSemantics;
+
+public final class InvokeKeys {
+
+ private final static EnumMap<ActionSemantics.Of, String> map = new EnumMap<ActionSemantics.Of, String>(ActionSemantics.Of.class);
+ static {
+ map.put(ActionSemantics.Of.SAFE, "invokeQueryOnly");
+ map.put(ActionSemantics.Of.IDEMPOTENT, "invokeIdempotent");
+ map.put(ActionSemantics.Of.NON_IDEMPOTENT, "invoke");
+ }
+
+ private InvokeKeys() {
+ }
+
+ public static String getKeyFor(ActionSemantics.Of actionSemantics) {
+ return map.get(actionSemantics);
+ }
+}
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/JsonValueEncoder.java
----------------------------------------------------------------------
diff --git a/component/viewer/restfulobjects/rendering/src/main/java/org/apache/isis/viewer/restfulobjects/rendering/domainobjects/JsonValueEncoder.java b/component/viewer/restfulobjects/rendering/src/main/java/org/apache/isis/viewer/restfulobjects/rendering/domainobjects/JsonValueEncoder.java
new file mode 100644
index 0000000..957aa67
--- /dev/null
+++ b/component/viewer/restfulobjects/rendering/src/main/java/org/apache/isis/viewer/restfulobjects/rendering/domainobjects/JsonValueEncoder.java
@@ -0,0 +1,224 @@
+/*
+ * 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.math.BigDecimal;
+import java.math.BigInteger;
+
+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;
+
+/**
+ * Similar to Isis' value encoding, but with additional support for JSON
+ * primitives.
+ */
+public final class JsonValueEncoder {
+
+ public static class ExpectedStringRepresentingValueException extends IllegalArgumentException {
+ private static final long serialVersionUID = 1L;
+ }
+
+ public ObjectAdapter asAdapter(final ObjectSpecification objectSpec, final JsonRepresentation representation) {
+ if (objectSpec == null) {
+ throw new IllegalArgumentException("objectSpec cannot be null");
+ }
+ final EncodableFacet encodableFacet = objectSpec.getFacet(EncodableFacet.class);
+ if (encodableFacet == null) {
+ throw new IllegalArgumentException("objectSpec expected to have EncodableFacet");
+ }
+ if (representation == null) {
+ throw new IllegalArgumentException("representation cannot be null");
+ }
+ if (!representation.isValue()) {
+ throw new IllegalArgumentException("representation must be of a value");
+ }
+
+ // special case handling for JSON built-ins
+ if (isBoolean(objectSpec)) {
+ if (!representation.isBoolean()) {
+ throwIncompatibleException(objectSpec, representation);
+ }
+ final String argStr = "" + representation.asBoolean();
+ return encodableFacet.fromEncodedString(argStr);
+ }
+
+ if (isInteger(objectSpec)) {
+ if (representation.isInt()) {
+ final String argStr = "" + representation.asInt();
+ return encodableFacet.fromEncodedString(argStr);
+ }
+ // best effort
+ if (representation.isString()) {
+ final String argStr = representation.asString();
+ return encodableFacet.fromEncodedString(argStr);
+ }
+ // give up
+ throwIncompatibleException(objectSpec, representation);
+ }
+
+ if (isLong(objectSpec)) {
+ if (!representation.isLong()) {
+ throwIncompatibleException(objectSpec, representation);
+ }
+ final String argStr = "" + representation.asLong();
+ return encodableFacet.fromEncodedString(argStr);
+ }
+
+ if (isBigInteger(objectSpec)) {
+ if (representation.isBigInteger()) {
+ final String argStr = "" + representation.asBigInteger();
+ return encodableFacet.fromEncodedString(argStr);
+ }
+ // best effort
+ if (representation.isLong()) {
+ final String argStr = "" + representation.asLong();
+ return encodableFacet.fromEncodedString(argStr);
+ }
+ if (representation.isInt()) {
+ final String argStr = "" + representation.asInt();
+ return encodableFacet.fromEncodedString(argStr);
+ }
+ if (representation.isString()) {
+ final String argStr = representation.asString();
+ return encodableFacet.fromEncodedString(argStr);
+ }
+ // give up
+ throwIncompatibleException(objectSpec, representation);
+ }
+
+ if (isBigDecimal(objectSpec)) {
+ if (representation.isBigDecimal()) {
+ final String argStr = "" + representation.asBigDecimal();
+ return encodableFacet.fromEncodedString(argStr);
+ }
+ // best effort
+ if (representation.isBigInteger()) {
+ final String argStr = "" + representation.asBigInteger();
+ return encodableFacet.fromEncodedString(argStr);
+ }
+ if (representation.isDouble()) {
+ final String argStr = "" + representation.asDouble();
+ return encodableFacet.fromEncodedString(argStr);
+ }
+ if (representation.isLong()) {
+ final String argStr = "" + representation.asLong();
+ return encodableFacet.fromEncodedString(argStr);
+ }
+ if (representation.isInt()) {
+ final String argStr = "" + representation.asInt();
+ return encodableFacet.fromEncodedString(argStr);
+ }
+ if (representation.isString()) {
+ final String argStr = representation.asString();
+ return encodableFacet.fromEncodedString(argStr);
+ }
+ // give up
+ throwIncompatibleException(objectSpec, representation);
+ }
+
+ if (isDouble(objectSpec)) {
+ if (representation.isDouble()) {
+ final String argStr = "" + representation.asDouble();
+ return encodableFacet.fromEncodedString(argStr);
+ }
+ // best effort
+ if (representation.isLong()) {
+ final String argStr = "" + representation.asLong();
+ return encodableFacet.fromEncodedString(argStr);
+ }
+ if (representation.isInt()) {
+ final String argStr = "" + representation.asInt();
+ return encodableFacet.fromEncodedString(argStr);
+ }
+ if (representation.isString()) {
+ final String argStr = representation.asString();
+ return encodableFacet.fromEncodedString(argStr);
+ }
+ // give up
+ throwIncompatibleException(objectSpec, representation);
+ }
+
+ if (!representation.isString()) {
+ throw new ExpectedStringRepresentingValueException();
+ }
+ final String argStr = representation.asString();
+ return encodableFacet.fromEncodedString(argStr);
+ }
+
+ public Object asObject(final ObjectAdapter objectAdapter) {
+ if (objectAdapter == null) {
+ throw new IllegalArgumentException("objectAdapter cannot be null");
+ }
+ final ObjectSpecification objectSpec = objectAdapter.getSpecification();
+
+ // special case handling for JSON built-ins (at least so far as json.org
+ // defines them).
+ if (isBoolean(objectSpec) || isInteger(objectSpec) || isLong(objectSpec) || isBigInteger(objectSpec) || isDouble(objectSpec) || isBigDecimal(objectSpec)) {
+ // simply return
+ return objectAdapter.getObject();
+ }
+
+ final EncodableFacet encodableFacet = objectSpec.getFacet(EncodableFacet.class);
+ if (encodableFacet == null) {
+ throw new IllegalArgumentException("objectSpec expected to have EncodableFacet");
+ }
+ return encodableFacet.toEncodedString(objectAdapter);
+ }
+
+ private boolean isBoolean(final ObjectSpecification objectSpec) {
+ return hasCorrespondingClass(objectSpec, boolean.class, Boolean.class);
+ }
+
+ private boolean isInteger(final ObjectSpecification objectSpec) {
+ return hasCorrespondingClass(objectSpec, int.class, Integer.class);
+ }
+
+ private boolean isLong(final ObjectSpecification objectSpec) {
+ return hasCorrespondingClass(objectSpec, long.class, Long.class);
+ }
+
+ private boolean isBigInteger(final ObjectSpecification objectSpec) {
+ return hasCorrespondingClass(objectSpec, BigInteger.class);
+ }
+
+ private boolean isDouble(final ObjectSpecification objectSpec) {
+ return hasCorrespondingClass(objectSpec, double.class, Double.class);
+ }
+
+ private boolean isBigDecimal(final ObjectSpecification objectSpec) {
+ return hasCorrespondingClass(objectSpec, BigDecimal.class);
+ }
+
+ private boolean hasCorrespondingClass(final ObjectSpecification objectSpec, final Class<?>... candidates) {
+ final Class<?> specClass = objectSpec.getCorrespondingClass();
+ for (final Class<?> candidate : candidates) {
+ if (specClass == candidate) {
+ return true;
+ }
+ }
+ return false;
+ }
+
+ private void throwIncompatibleException(final ObjectSpecification objectSpec, final JsonRepresentation representation) {
+ throw new IllegalArgumentException(String.format("representation '%s' incompatible with objectSpec '%s'", representation.toString(), objectSpec.getCorrespondingClass().getName()));
+ }
+
+}
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/ListReprRenderer.java
----------------------------------------------------------------------
diff --git a/component/viewer/restfulobjects/rendering/src/main/java/org/apache/isis/viewer/restfulobjects/rendering/domainobjects/ListReprRenderer.java b/component/viewer/restfulobjects/rendering/src/main/java/org/apache/isis/viewer/restfulobjects/rendering/domainobjects/ListReprRenderer.java
new file mode 100644
index 0000000..32269f4
--- /dev/null
+++ b/component/viewer/restfulobjects/rendering/src/main/java/org/apache/isis/viewer/restfulobjects/rendering/domainobjects/ListReprRenderer.java
@@ -0,0 +1,115 @@
+/**
+ * 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.Collection;
+
+import org.apache.isis.core.metamodel.adapter.ObjectAdapter;
+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.RendererFactory;
+import org.apache.isis.viewer.restfulobjects.rendering.RendererFactoryRegistry;
+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 ListReprRenderer extends ReprRendererAbstract<ListReprRenderer, Collection<ObjectAdapter>> {
+
+ public static class Factory extends ReprRendererFactoryAbstract {
+ public Factory() {
+ super(RepresentationType.LIST);
+ }
+
+ @Override
+ public ReprRenderer<?, ?> newRenderer(final RendererContext resourceContext, final LinkFollower linkFollower, final JsonRepresentation representation) {
+ return new ListReprRenderer(resourceContext, linkFollower, getRepresentationType(), representation);
+ }
+ }
+
+ private ObjectAdapterLinkTo linkTo;
+ private Collection<ObjectAdapter> objectAdapters;
+ private ObjectSpecification elementType;
+ private ObjectSpecification returnType;
+
+ private ListReprRenderer(final RendererContext resourceContext, final LinkFollower linkFollower, final RepresentationType representationType, final JsonRepresentation representation) {
+ super(resourceContext, linkFollower, representationType, representation);
+ usingLinkToBuilder(new DomainObjectLinkTo());
+ }
+
+ public ListReprRenderer usingLinkToBuilder(final ObjectAdapterLinkTo objectAdapterLinkToBuilder) {
+ this.linkTo = objectAdapterLinkToBuilder.usingUrlBase(resourceContext);
+ return this;
+ }
+
+ @Override
+ public ListReprRenderer with(final Collection<ObjectAdapter> objectAdapters) {
+ this.objectAdapters = objectAdapters;
+ return this;
+ }
+
+ public ListReprRenderer withReturnType(final ObjectSpecification returnType) {
+ this.returnType = returnType;
+ return this;
+ }
+
+ public ListReprRenderer withElementType(final ObjectSpecification elementType) {
+ this.elementType = elementType;
+ return this;
+ }
+
+ @Override
+ public JsonRepresentation render() {
+ addValue();
+
+ addLink(Rel.RETURN_TYPE, returnType);
+ addLink(Rel.ELEMENT_TYPE, elementType);
+
+ getExtensions();
+
+ return representation;
+ }
+
+ private void addValue() {
+ if (objectAdapters == null) {
+ return;
+ }
+
+ final JsonRepresentation values = JsonRepresentation.newArray();
+ final LinkFollower linkFollower = getLinkFollower().follow("value");
+
+ for (final ObjectAdapter adapter : objectAdapters) {
+ if (adapter.getSpecification().isHidden()) {
+ continue;
+ }
+ final JsonRepresentation linkToObject = linkTo.with(adapter).builder().build();
+ values.arrayAdd(linkToObject);
+
+ if (linkFollower.matches(linkToObject)) {
+ final RendererFactory factory = RendererFactoryRegistry.instance.find(RepresentationType.DOMAIN_OBJECT);
+ final DomainObjectReprRenderer renderer = (DomainObjectReprRenderer) factory.newRenderer(getResourceContext(), linkFollower, JsonRepresentation.newMap());
+ final JsonRepresentation domainObject = renderer.with(adapter).render();
+ linkToObject.mapPut("value", domainObject);
+ }
+ }
+ representation.mapPut("value", values);
+ }
+
+}
\ 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/MemberType.java
----------------------------------------------------------------------
diff --git a/component/viewer/restfulobjects/rendering/src/main/java/org/apache/isis/viewer/restfulobjects/rendering/domainobjects/MemberType.java b/component/viewer/restfulobjects/rendering/src/main/java/org/apache/isis/viewer/restfulobjects/rendering/domainobjects/MemberType.java
new file mode 100644
index 0000000..d4005a0
--- /dev/null
+++ b/component/viewer/restfulobjects/rendering/src/main/java/org/apache/isis/viewer/restfulobjects/rendering/domainobjects/MemberType.java
@@ -0,0 +1,152 @@
+/**
+ * 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.Map;
+
+import org.apache.isis.applib.annotation.ActionSemantics;
+import org.apache.isis.applib.util.Enums;
+import org.apache.isis.core.metamodel.facets.actions.invoke.ActionInvocationFacet;
+import org.apache.isis.core.metamodel.facets.collections.modify.CollectionAddToFacet;
+import org.apache.isis.core.metamodel.facets.collections.modify.CollectionRemoveFromFacet;
+import org.apache.isis.core.metamodel.facets.properties.modify.PropertyClearFacet;
+import org.apache.isis.core.metamodel.facets.properties.modify.PropertySetterFacet;
+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.ObjectFeature;
+import org.apache.isis.core.metamodel.spec.feature.ObjectMember;
+import org.apache.isis.core.metamodel.spec.feature.OneToManyAssociation;
+import org.apache.isis.core.metamodel.spec.feature.OneToOneAssociation;
+import org.apache.isis.core.progmodel.facets.actions.validate.ActionValidationFacet;
+import org.apache.isis.core.progmodel.facets.collections.validate.CollectionValidateAddToFacet;
+import org.apache.isis.core.progmodel.facets.collections.validate.CollectionValidateRemoveFromFacet;
+import org.apache.isis.core.progmodel.facets.properties.validate.PropertyValidateFacet;
+import org.apache.isis.viewer.restfulobjects.applib.RepresentationType;
+import org.apache.isis.viewer.restfulobjects.applib.RoHttpMethod;
+import org.apache.isis.viewer.restfulobjects.applib.links.Rel;
+
+import com.google.common.collect.ImmutableMap;
+
+public enum MemberType {
+
+ PROPERTY("properties/", "id", RepresentationType.OBJECT_PROPERTY, ImmutableMap.of("modify", MutatorSpec.of(Rel.MODIFY, PropertyValidateFacet.class, PropertySetterFacet.class, RoHttpMethod.PUT, BodyArgs.ONE), "clear",
+ MutatorSpec.of(Rel.CLEAR, PropertyValidateFacet.class, PropertyClearFacet.class, RoHttpMethod.DELETE, BodyArgs.NONE))) {
+ @Override
+ public ObjectSpecification specFor(final ObjectMember objectMember) {
+ return objectMember.getSpecification();
+ }
+ },
+ /**
+ * {@link #getMutators()} are keyed by
+ * {@link CollectionSemantics#getAddToKey()}
+ */
+ COLLECTION("collections/", "id", RepresentationType.OBJECT_COLLECTION, ImmutableMap.of("addToSet", MutatorSpec.of(Rel.ADD_TO, CollectionValidateAddToFacet.class, CollectionAddToFacet.class, RoHttpMethod.PUT, BodyArgs.ONE), "addToList",
+ MutatorSpec.of(Rel.ADD_TO, CollectionValidateAddToFacet.class, CollectionAddToFacet.class, RoHttpMethod.POST, BodyArgs.ONE), "removeFrom", MutatorSpec.of(Rel.REMOVE_FROM, CollectionValidateRemoveFromFacet.class, CollectionRemoveFromFacet.class, RoHttpMethod.DELETE, BodyArgs.ONE))) {
+ @Override
+ public ObjectSpecification specFor(final ObjectMember objectMember) {
+ return objectMember.getSpecification();
+ }
+ },
+ /**
+ * {@link #getMutators()} are keyed by
+ * {@link ActionSemantics#getInvokeKey()}
+ */
+ ACTION("actions/", "id", RepresentationType.ACTION_RESULT, ImmutableMap.of("invokeQueryOnly", MutatorSpec.of(Rel.INVOKE, ActionValidationFacet.class, ActionInvocationFacet.class, RoHttpMethod.GET, BodyArgs.MANY, "invoke"), "invokeIdempotent",
+ MutatorSpec.of(Rel.INVOKE, ActionValidationFacet.class, ActionInvocationFacet.class, RoHttpMethod.PUT, BodyArgs.MANY, "invoke"), "invoke", MutatorSpec.of(Rel.INVOKE, ActionValidationFacet.class, ActionInvocationFacet.class, RoHttpMethod.POST, BodyArgs.MANY, "invoke"))) {
+ @Override
+ public ObjectSpecification specFor(final ObjectMember objectMember) {
+ final ObjectAction objectAction = (ObjectAction) objectMember;
+ return objectAction.getReturnType();
+ }
+ };
+
+ private final String urlPart;
+ private final String jsProp;
+ private final String name;
+ private final RepresentationType representationType;
+
+ private final Map<String, MutatorSpec> mutators;
+
+ private MemberType(final String urlPart, final String jsProp, final RepresentationType representationType, final Map<String, MutatorSpec> mutators) {
+ this.urlPart = urlPart;
+ this.jsProp = jsProp;
+ this.representationType = representationType;
+ this.mutators = mutators;
+ name = Enums.enumToCamelCase(this);
+ }
+
+ public String getJsProp() {
+ return jsProp;
+ }
+
+ public String getUrlPart() {
+ return urlPart;
+ }
+
+ public Map<String, MutatorSpec> getMutators() {
+ return mutators;
+ }
+
+ public abstract ObjectSpecification specFor(ObjectMember objectMember);
+
+ public boolean isProperty() {
+ return this == MemberType.PROPERTY;
+ }
+
+ public boolean isCollection() {
+ return this == MemberType.COLLECTION;
+ }
+
+ public boolean isAction() {
+ return this == MemberType.ACTION;
+ }
+
+ public static MemberType lookup(final String memberTypeName) {
+ for (final MemberType memberType : values()) {
+ if (memberType.getName().equals(memberTypeName)) {
+ return memberType;
+ }
+ }
+ return null;
+ }
+
+ public static MemberType of(final ObjectMember objectMember) {
+ return objectMember.isAction() ? ACTION : objectMember.isOneToOneAssociation() ? PROPERTY : COLLECTION;
+ }
+
+ public RepresentationType getRepresentationType() {
+ return representationType;
+ }
+
+ public String getName() {
+ return name;
+ }
+
+ public static MemberType determineFrom(final ObjectFeature objectFeature) {
+ if (objectFeature instanceof ObjectAction) {
+ return MemberType.ACTION;
+ }
+ if (objectFeature instanceof OneToOneAssociation) {
+ return MemberType.PROPERTY;
+ }
+ if (objectFeature instanceof OneToManyAssociation) {
+ return MemberType.COLLECTION;
+ }
+ return null;
+ }
+
+}
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/MutatorSpec.java
----------------------------------------------------------------------
diff --git a/component/viewer/restfulobjects/rendering/src/main/java/org/apache/isis/viewer/restfulobjects/rendering/domainobjects/MutatorSpec.java b/component/viewer/restfulobjects/rendering/src/main/java/org/apache/isis/viewer/restfulobjects/rendering/domainobjects/MutatorSpec.java
new file mode 100644
index 0000000..f44f3ea
--- /dev/null
+++ b/component/viewer/restfulobjects/rendering/src/main/java/org/apache/isis/viewer/restfulobjects/rendering/domainobjects/MutatorSpec.java
@@ -0,0 +1,49 @@
+/**
+ * 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.facetapi.Facet;
+import org.apache.isis.viewer.restfulobjects.applib.RoHttpMethod;
+import org.apache.isis.viewer.restfulobjects.applib.links.Rel;
+
+public class MutatorSpec {
+
+ public static MutatorSpec of(final Rel rel, final Class<? extends Facet> validationFacetType, final Class<? extends Facet> mutatorFacetType, final RoHttpMethod httpMethod, final BodyArgs argSpec) {
+ return of(rel, validationFacetType, mutatorFacetType, httpMethod, argSpec, null);
+ }
+
+ public static MutatorSpec of(final Rel rel, final Class<? extends Facet> validationFacetType, final Class<? extends Facet> mutatorFacetType, final RoHttpMethod httpMethod, final BodyArgs argSpec, final String suffix) {
+ return new MutatorSpec(rel, validationFacetType, mutatorFacetType, httpMethod, argSpec, suffix);
+ }
+
+ public final Rel rel;
+ public final Class<? extends Facet> validationFacetType;
+ public final Class<? extends Facet> mutatorFacetType;
+ public final RoHttpMethod httpMethod;
+ public final String suffix;
+ public final BodyArgs arguments;
+
+ private MutatorSpec(final Rel rel, final Class<? extends Facet> validationFacetType, final Class<? extends Facet> mutatorFacetType, final RoHttpMethod httpMethod, final BodyArgs bodyArgs, final String suffix) {
+ this.rel = rel;
+ this.validationFacetType = validationFacetType;
+ this.mutatorFacetType = mutatorFacetType;
+ this.httpMethod = httpMethod;
+ this.arguments = bodyArgs;
+ this.suffix = suffix;
+ }
+
+}
\ 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/ObjectActionReprRenderer.java
----------------------------------------------------------------------
diff --git a/component/viewer/restfulobjects/rendering/src/main/java/org/apache/isis/viewer/restfulobjects/rendering/domainobjects/ObjectActionReprRenderer.java b/component/viewer/restfulobjects/rendering/src/main/java/org/apache/isis/viewer/restfulobjects/rendering/domainobjects/ObjectActionReprRenderer.java
new file mode 100644
index 0000000..c180f3f
--- /dev/null
+++ b/component/viewer/restfulobjects/rendering/src/main/java/org/apache/isis/viewer/restfulobjects/rendering/domainobjects/ObjectActionReprRenderer.java
@@ -0,0 +1,228 @@
+/**
+ * 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.ActionSemantics;
+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.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.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.ActionDescriptionReprRenderer;
+import org.codehaus.jackson.node.NullNode;
+
+import com.google.common.collect.Lists;
+
+public class ObjectActionReprRenderer extends AbstractObjectMemberReprRenderer<ObjectActionReprRenderer, ObjectAction> {
+
+ public static class Factory extends ReprRendererFactoryAbstract {
+
+ public Factory() {
+ super(RepresentationType.OBJECT_ACTION);
+ }
+
+ @Override
+ public ReprRenderer<?, ?> newRenderer(final RendererContext resourceContext, final LinkFollower linkFollower, final JsonRepresentation representation) {
+ return new ObjectActionReprRenderer(resourceContext, linkFollower, getRepresentationType(), representation);
+ }
+ }
+
+ private ObjectActionReprRenderer(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();
+ putDisabledReasonIfDisabled();
+
+ if (mode.isStandalone() || mode.isMutated()) {
+ addParameterDetails();
+ }
+
+ return representation;
+ }
+
+ // ///////////////////////////////////////////////////
+ // 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_ACTION);
+ final ObjectActionReprRenderer renderer = (ObjectActionReprRenderer) factory.newRenderer(getResourceContext(), getLinkFollower(), JsonRepresentation.newMap());
+ renderer.with(new ObjectAndAction(objectAdapter, objectMember)).usingLinkTo(linkTo).asFollowed();
+ detailsLink.mapPut("value", renderer.render());
+ }
+
+ // ///////////////////////////////////////////////////
+ // mutators
+ // ///////////////////////////////////////////////////
+
+ @Override
+ protected void addMutatorsIfEnabled() {
+ if (usability().isVetoed()) {
+ return;
+ }
+ final Map<String, MutatorSpec> mutators = memberType.getMutators();
+
+ final ActionSemantics.Of actionSemantics = objectMember.getSemantics();
+ final String mutator = InvokeKeys.getKeyFor(actionSemantics);
+ final MutatorSpec mutatorSpec = mutators.get(mutator);
+
+ addLinkFor(mutatorSpec);
+ }
+
+ @Override
+ protected ObjectAdapterLinkTo linkToForMutatorInvoke() {
+ if (!objectMember.isContributed()) {
+ return super.linkToForMutatorInvoke();
+ }
+ final DomainServiceLinkTo linkTo = new DomainServiceLinkTo();
+ return linkTo.usingUrlBase(getResourceContext()).with(contributingServiceAdapter());
+ }
+
+ private ObjectAdapter contributingServiceAdapter() {
+ final ObjectSpecification serviceType = objectMember.getOnType();
+ final List<ObjectAdapter> serviceAdapters = getServiceAdapters();
+ for (final ObjectAdapter serviceAdapter : serviceAdapters) {
+ if (serviceAdapter.getSpecification() == serviceType) {
+ return serviceAdapter;
+ }
+ }
+ // fail fast
+ throw new IllegalStateException("Unable to locate contributing service");
+ }
+
+ @Override
+ protected JsonRepresentation mutatorArgs(final MutatorSpec mutatorSpec) {
+ final JsonRepresentation argMap = JsonRepresentation.newMap();
+ final List<ObjectActionParameter> parameters = objectMember.getParameters();
+ for (int i = 0; i < objectMember.getParameterCount(); i++) {
+ argMap.mapPut(parameters.get(i).getId(), argValueFor(i));
+ }
+ return argMap;
+ }
+
+ private Object argValueFor(final int i) {
+ if (objectMember.isContributed()) {
+ final ObjectActionParameter actionParameter = objectMember.getParameters().get(i);
+ if (actionParameter.getSpecification().isOfType(objectAdapter.getSpecification())) {
+ return DomainObjectReprRenderer.newLinkToBuilder(resourceContext, Rel.OBJECT, objectAdapter).build();
+ }
+ }
+ // force a null into the map
+ return NullNode.getInstance();
+ }
+
+ // ///////////////////////////////////////////////////
+ // parameter details
+ // ///////////////////////////////////////////////////
+
+ private ObjectActionReprRenderer addParameterDetails() {
+ final List<Object> parameters = Lists.newArrayList();
+ for (int i = 0; i < objectMember.getParameterCount(); i++) {
+ final ObjectActionParameter param = objectMember.getParameters().get(i);
+ parameters.add(paramDetails(param));
+ }
+ representation.mapPut("parameters", parameters);
+ return this;
+ }
+
+ private Object paramDetails(final ObjectActionParameter param) {
+ final JsonRepresentation paramRep = JsonRepresentation.newMap();
+ paramRep.mapPut("num", param.getNumber());
+ paramRep.mapPut("id", param.getId());
+ paramRep.mapPut("name", param.getName());
+ paramRep.mapPut("description", param.getDescription());
+ final Object paramChoices = choicesFor(param);
+ if (paramChoices != null) {
+ paramRep.mapPut("choices", paramChoices);
+ }
+ final Object paramDefault = defaultFor(param);
+ if (paramDefault != null) {
+ paramRep.mapPut("default", paramDefault);
+ }
+ return paramRep;
+ }
+
+ private Object choicesFor(final ObjectActionParameter param) {
+ final ObjectAdapter[] choiceAdapters = param.getChoices(objectAdapter);
+ if (choiceAdapters == null || choiceAdapters.length == 0) {
+ return null;
+ }
+ final List<Object> list = Lists.newArrayList();
+ for (final ObjectAdapter choiceAdapter : choiceAdapters) {
+ final ObjectSpecification objectSpec = param.getSpecification();
+ list.add(DomainObjectReprRenderer.valueOrRef(resourceContext, choiceAdapter, objectSpec));
+ }
+ return list;
+ }
+
+ private Object defaultFor(final ObjectActionParameter param) {
+ final ObjectAdapter defaultAdapter = param.getDefault(objectAdapter);
+ if (defaultAdapter == null) {
+ return null;
+ }
+ final ObjectSpecification objectSpec = param.getSpecification();
+ return DomainObjectReprRenderer.valueOrRef(resourceContext, defaultAdapter, objectSpec);
+ }
+
+ // ///////////////////////////////////////////////////
+ // extensions and links
+ // ///////////////////////////////////////////////////
+
+ @Override
+ protected void addLinksToFormalDomainModel() {
+ getLinks().arrayAdd(ActionDescriptionReprRenderer.newLinkToBuilder(resourceContext, Rel.DESCRIBEDBY, objectAdapter.getSpecification(), objectMember).build());
+ }
+
+ @Override
+ protected void addLinksIsisProprietary() {
+ if (objectMember.isContributed()) {
+ final ObjectAdapter serviceAdapter = contributingServiceAdapter();
+ final JsonRepresentation contributedByLink = DomainObjectReprRenderer.newLinkToBuilder(resourceContext, Rel.CONTRIBUTED_BY, serviceAdapter).build();
+ getLinks().arrayAdd(contributedByLink);
+ }
+ }
+
+ @Override
+ protected void putExtensionsIsisProprietary() {
+ getExtensions().mapPut("actionType", objectMember.getType().name().toLowerCase());
+
+ final ActionSemantics.Of semantics = objectMember.getSemantics();
+ getExtensions().mapPut("actionSemantics", semantics.getCamelCaseName());
+ }
+
+}
\ 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/ObjectAdapterLinkTo.java
----------------------------------------------------------------------
diff --git a/component/viewer/restfulobjects/rendering/src/main/java/org/apache/isis/viewer/restfulobjects/rendering/domainobjects/ObjectAdapterLinkTo.java b/component/viewer/restfulobjects/rendering/src/main/java/org/apache/isis/viewer/restfulobjects/rendering/domainobjects/ObjectAdapterLinkTo.java
new file mode 100644
index 0000000..afeda55
--- /dev/null
+++ b/component/viewer/restfulobjects/rendering/src/main/java/org/apache/isis/viewer/restfulobjects/rendering/domainobjects/ObjectAdapterLinkTo.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.domainobjects;
+
+import org.apache.isis.core.metamodel.adapter.ObjectAdapter;
+import org.apache.isis.core.metamodel.spec.feature.ObjectMember;
+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.RendererContext;
+
+public interface ObjectAdapterLinkTo {
+
+ ObjectAdapterLinkTo usingUrlBase(RendererContext resourceContext);
+
+ ObjectAdapterLinkTo with(ObjectAdapter objectAdapter);
+
+ LinkBuilder builder();
+
+ LinkBuilder builder(Rel rel);
+
+ LinkBuilder memberBuilder(Rel rel, MemberType memberType, ObjectMember objectMember, String... parts);
+
+ LinkBuilder memberBuilder(Rel rel, MemberType memberType, ObjectMember objectMember, RepresentationType representationType, String... parts);
+
+}
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/ObjectAndAction.java
----------------------------------------------------------------------
diff --git a/component/viewer/restfulobjects/rendering/src/main/java/org/apache/isis/viewer/restfulobjects/rendering/domainobjects/ObjectAndAction.java b/component/viewer/restfulobjects/rendering/src/main/java/org/apache/isis/viewer/restfulobjects/rendering/domainobjects/ObjectAndAction.java
new file mode 100644
index 0000000..dc7c546
--- /dev/null
+++ b/component/viewer/restfulobjects/rendering/src/main/java/org/apache/isis/viewer/restfulobjects/rendering/domainobjects/ObjectAndAction.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.ObjectAction;
+
+public class ObjectAndAction extends ObjectAndMember<ObjectAction> {
+
+ public ObjectAndAction(final ObjectAdapter objectAdapter, final ObjectAction action) {
+ super(objectAdapter, 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/domainobjects/ObjectAndActionInvocation.java
----------------------------------------------------------------------
diff --git a/component/viewer/restfulobjects/rendering/src/main/java/org/apache/isis/viewer/restfulobjects/rendering/domainobjects/ObjectAndActionInvocation.java b/component/viewer/restfulobjects/rendering/src/main/java/org/apache/isis/viewer/restfulobjects/rendering/domainobjects/ObjectAndActionInvocation.java
new file mode 100644
index 0000000..10795a2
--- /dev/null
+++ b/component/viewer/restfulobjects/rendering/src/main/java/org/apache/isis/viewer/restfulobjects/rendering/domainobjects/ObjectAndActionInvocation.java
@@ -0,0 +1,55 @@
+/*
+ * 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.ObjectAction;
+import org.apache.isis.viewer.restfulobjects.applib.JsonRepresentation;
+
+public class ObjectAndActionInvocation {
+
+ private final ObjectAdapter objectAdapter;
+ private final ObjectAction action;
+ private final JsonRepresentation arguments;
+ private final ObjectAdapter returnedAdapter;
+
+ public ObjectAndActionInvocation(final ObjectAdapter objectAdapter, final ObjectAction action, final JsonRepresentation arguments, final ObjectAdapter returnedAdapter) {
+ this.objectAdapter = objectAdapter;
+ this.action = action;
+ this.arguments = arguments;
+ this.returnedAdapter = returnedAdapter;
+ }
+
+ public ObjectAdapter getObjectAdapter() {
+ return objectAdapter;
+ }
+
+ public ObjectAction getAction() {
+ return action;
+ }
+
+ public JsonRepresentation getArguments() {
+ return arguments;
+ }
+
+ public ObjectAdapter getReturnedAdapter() {
+ return returnedAdapter;
+ }
+
+}
\ 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/ObjectAndCollection.java
----------------------------------------------------------------------
diff --git a/component/viewer/restfulobjects/rendering/src/main/java/org/apache/isis/viewer/restfulobjects/rendering/domainobjects/ObjectAndCollection.java b/component/viewer/restfulobjects/rendering/src/main/java/org/apache/isis/viewer/restfulobjects/rendering/domainobjects/ObjectAndCollection.java
new file mode 100644
index 0000000..3bb3189
--- /dev/null
+++ b/component/viewer/restfulobjects/rendering/src/main/java/org/apache/isis/viewer/restfulobjects/rendering/domainobjects/ObjectAndCollection.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.OneToManyAssociation;
+
+public class ObjectAndCollection extends ObjectAndMember<OneToManyAssociation> {
+
+ public ObjectAndCollection(final ObjectAdapter objectAdapter, final OneToManyAssociation collection) {
+ super(objectAdapter, 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/domainobjects/ObjectAndMember.java
----------------------------------------------------------------------
diff --git a/component/viewer/restfulobjects/rendering/src/main/java/org/apache/isis/viewer/restfulobjects/rendering/domainobjects/ObjectAndMember.java b/component/viewer/restfulobjects/rendering/src/main/java/org/apache/isis/viewer/restfulobjects/rendering/domainobjects/ObjectAndMember.java
new file mode 100644
index 0000000..675f884
--- /dev/null
+++ b/component/viewer/restfulobjects/rendering/src/main/java/org/apache/isis/viewer/restfulobjects/rendering/domainobjects/ObjectAndMember.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.domainobjects;
+
+import org.apache.isis.core.metamodel.adapter.ObjectAdapter;
+import org.apache.isis.core.metamodel.spec.feature.ObjectMember;
+
+public abstract class ObjectAndMember<T extends ObjectMember> {
+
+ private final ObjectAdapter objectAdapter;
+ private final T objectMember;
+
+ public ObjectAndMember(final ObjectAdapter objectAdapter, final T objectMember) {
+ this.objectAdapter = objectAdapter;
+ this.objectMember = objectMember;
+ }
+
+ public ObjectAdapter getObjectAdapter() {
+ return objectAdapter;
+ }
+
+ public T getMember() {
+ return objectMember;
+ }
+}
\ No newline at end of file