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
[9/24] ISIS-323: lots more refactoring of RO
http://git-wip-us.apache.org/repos/asf/isis/blob/75f41b75/component/viewer/restfulobjects/impl/src/test/java/org/apache/isis/viewer/restfulobjects/viewer/resources/domainobjects/JsonValueEncoderTest_asAdapter.java
----------------------------------------------------------------------
diff --git a/component/viewer/restfulobjects/impl/src/test/java/org/apache/isis/viewer/restfulobjects/viewer/resources/domainobjects/JsonValueEncoderTest_asAdapter.java b/component/viewer/restfulobjects/impl/src/test/java/org/apache/isis/viewer/restfulobjects/viewer/resources/domainobjects/JsonValueEncoderTest_asAdapter.java
deleted file mode 100644
index 042b1a1..0000000
--- a/component/viewer/restfulobjects/impl/src/test/java/org/apache/isis/viewer/restfulobjects/viewer/resources/domainobjects/JsonValueEncoderTest_asAdapter.java
+++ /dev/null
@@ -1,370 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements. See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership. The ASF licenses this file
- * to you under the Apache License, Version 2.0 (the
- * "License"); you may not use this file except in compliance
- * with the License. You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing,
- * software distributed under the License is distributed on an
- * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- * KIND, either express or implied. See the License for the
- * specific language governing permissions and limitations
- * under the License.
- */
-package org.apache.isis.viewer.restfulobjects.viewer.resources.domainobjects;
-
-import static org.junit.Assert.assertNull;
-import static org.junit.Assert.assertSame;
-
-import java.math.BigDecimal;
-import java.math.BigInteger;
-
-import org.codehaus.jackson.node.BigIntegerNode;
-import org.codehaus.jackson.node.BooleanNode;
-import org.codehaus.jackson.node.DecimalNode;
-import org.codehaus.jackson.node.DoubleNode;
-import org.codehaus.jackson.node.IntNode;
-import org.codehaus.jackson.node.LongNode;
-import org.codehaus.jackson.node.TextNode;
-import org.jmock.Expectations;
-import org.jmock.Mockery;
-import org.jmock.integration.junit4.JMock;
-import org.jmock.integration.junit4.JUnit4Mockery;
-import org.junit.Before;
-import org.junit.Test;
-import org.junit.runner.RunWith;
-
-import org.apache.isis.core.metamodel.adapter.ObjectAdapter;
-import org.apache.isis.core.metamodel.facetapi.Facet;
-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.viewer.resources.domainobjects.JsonValueEncoder;
-
-@RunWith(JMock.class)
-public class JsonValueEncoderTest_asAdapter {
-
- private final Mockery context = new JUnit4Mockery();
-
- private JsonValueEncoder jsonValueEncoder;
- private JsonRepresentation representation;
- private ObjectSpecification objectSpec;
-
- private EncodableFacet encodableFacet;
- private ObjectAdapter objectAdapter;
-
- @Before
- public void setUp() throws Exception {
- objectSpec = context.mock(ObjectSpecification.class);
- encodableFacet = context.mock(EncodableFacet.class);
- objectAdapter = context.mock(ObjectAdapter.class);
-
- representation = new JsonRepresentation(TextNode.valueOf("aString"));
- jsonValueEncoder = new JsonValueEncoder();
- }
-
- @Test(expected = IllegalArgumentException.class)
- public void whenSpecIsNull() throws Exception {
- jsonValueEncoder.asAdapter(null, representation);
- }
-
- @Test(expected = IllegalArgumentException.class)
- public void whenReprIsNull() throws Exception {
- allowingObjectSpecHas(EncodableFacet.class, encodableFacet);
- jsonValueEncoder.asAdapter(objectSpec, null);
- }
-
- @Test(expected = IllegalArgumentException.class)
- public void whenReprIsAnArray() throws Exception {
- allowingObjectSpecHas(EncodableFacet.class, encodableFacet);
- jsonValueEncoder.asAdapter(objectSpec, JsonRepresentation.newArray());
- }
-
- @Test(expected = IllegalArgumentException.class)
- public void whenReprIsAMap() throws Exception {
- allowingObjectSpecHas(EncodableFacet.class, encodableFacet);
- assertNull(jsonValueEncoder.asAdapter(objectSpec, JsonRepresentation.newMap()));
- }
-
- @Test(expected = IllegalArgumentException.class)
- public void whenSpecDoesNotHaveAnEncodableFacet() throws Exception {
- allowingObjectSpecHas(EncodableFacet.class, null);
-
- assertNull(jsonValueEncoder.asAdapter(objectSpec, representation));
- }
-
- @Test
- public void whenReprIsBooleanPrimitive() throws Exception {
- whenReprIsBoolean(boolean.class);
- }
-
- @Test
- public void whenReprIsBooleanWrapper() throws Exception {
- whenReprIsBoolean(Boolean.class);
- }
-
- private void whenReprIsBoolean(final Class<?> correspondingClass) {
- // given
- allowingObjectSpecHas(EncodableFacet.class, encodableFacet);
- allowingObjectSpecCorrespondingClassIs(correspondingClass);
- final boolean value = true;
- representation = new JsonRepresentation(BooleanNode.valueOf(value));
- context.checking(new Expectations() {
- {
- one(encodableFacet).fromEncodedString("" + value);
- will(returnValue(objectAdapter));
- }
- });
-
- // when
- final ObjectAdapter adapter = jsonValueEncoder.asAdapter(objectSpec, representation);
-
- // then
- assertSame(objectAdapter, adapter);
- }
-
- @Test(expected = IllegalArgumentException.class)
- public void whenObjectSpecIsBooleanButReprIsNot() throws Exception {
- // given
- allowingObjectSpecHas(EncodableFacet.class, encodableFacet);
- allowingObjectSpecCorrespondingClassIs(boolean.class);
-
- // when
- jsonValueEncoder.asAdapter(objectSpec, representation);
- }
-
- @Test
- public void whenReprIsIntegerPrimitive() throws Exception {
- whenReprIsInteger(int.class);
- }
-
- @Test
- public void whenReprIsIntegerWrapper() throws Exception {
- whenReprIsInteger(Integer.class);
- }
-
- private void whenReprIsInteger(final Class<?> correspondingClass) {
- // given
- allowingObjectSpecHas(EncodableFacet.class, encodableFacet);
- allowingObjectSpecCorrespondingClassIs(correspondingClass);
- final int value = 123;
- representation = new JsonRepresentation(IntNode.valueOf(value));
- context.checking(new Expectations() {
- {
- one(encodableFacet).fromEncodedString("" + value);
- will(returnValue(objectAdapter));
- }
- });
-
- // when
- final ObjectAdapter adapter = jsonValueEncoder.asAdapter(objectSpec, representation);
-
- // then
- assertSame(objectAdapter, adapter);
- }
-
- @Test(expected = IllegalArgumentException.class)
- public void whenObjectSpecIsIntegerButReprIsNot() throws Exception {
- // given
- allowingObjectSpecHas(EncodableFacet.class, encodableFacet);
- allowingObjectSpecCorrespondingClassIs(int.class);
-
- representation = JsonRepresentation.newMap("foo", "bar");
-
- // when
- jsonValueEncoder.asAdapter(objectSpec, representation);
- }
-
- @Test
- public void whenReprIsLongPrimitive() throws Exception {
- whenReprIsLong(long.class);
- }
-
- @Test
- public void whenReprIsLongWrapper() throws Exception {
- whenReprIsLong(Long.class);
- }
-
- private void whenReprIsLong(final Class<?> correspondingClass) {
- // given
- allowingObjectSpecHas(EncodableFacet.class, encodableFacet);
- allowingObjectSpecCorrespondingClassIs(correspondingClass);
- final long value = 1234567890L;
- representation = new JsonRepresentation(LongNode.valueOf(value));
- context.checking(new Expectations() {
- {
- one(encodableFacet).fromEncodedString("" + value);
- will(returnValue(objectAdapter));
- }
- });
-
- // when
- final ObjectAdapter adapter = jsonValueEncoder.asAdapter(objectSpec, representation);
-
- // then
- assertSame(objectAdapter, adapter);
- }
-
- @Test(expected = IllegalArgumentException.class)
- public void whenObjectSpecIsLongButReprIsNot() throws Exception {
- // given
- allowingObjectSpecHas(EncodableFacet.class, encodableFacet);
- allowingObjectSpecCorrespondingClassIs(long.class);
-
- // when
- jsonValueEncoder.asAdapter(objectSpec, representation);
- }
-
- @Test
- public void whenReprIsDoublePrimitive() throws Exception {
- whenReprIsDouble(double.class);
- }
-
- @Test
- public void whenReprIsDoubleWrapper() throws Exception {
- whenReprIsDouble(Double.class);
- }
-
- private void whenReprIsDouble(final Class<?> correspondingClass) {
- // given
- allowingObjectSpecHas(EncodableFacet.class, encodableFacet);
- allowingObjectSpecCorrespondingClassIs(correspondingClass);
- final double value = 123.45;
- representation = new JsonRepresentation(DoubleNode.valueOf(value));
- context.checking(new Expectations() {
- {
- one(encodableFacet).fromEncodedString("" + value);
- will(returnValue(objectAdapter));
- }
- });
-
- // when
- final ObjectAdapter adapter = jsonValueEncoder.asAdapter(objectSpec, representation);
-
- // then
- assertSame(objectAdapter, adapter);
- }
-
- @Test(expected = IllegalArgumentException.class)
- public void whenObjectSpecIsDoubleButReprIsNot() throws Exception {
- // given
- allowingObjectSpecHas(EncodableFacet.class, encodableFacet);
- allowingObjectSpecCorrespondingClassIs(double.class);
-
- representation = JsonRepresentation.newMap("foo", "bar");
-
- // when
- jsonValueEncoder.asAdapter(objectSpec, representation);
- }
-
- @Test
- public void whenReprIsBigInteger() throws Exception {
- // given
- allowingObjectSpecHas(EncodableFacet.class, encodableFacet);
- allowingObjectSpecCorrespondingClassIs(BigInteger.class);
- final BigInteger value = BigInteger.valueOf(123);
- representation = new JsonRepresentation(BigIntegerNode.valueOf(value));
- context.checking(new Expectations() {
- {
- one(encodableFacet).fromEncodedString("" + value);
- will(returnValue(objectAdapter));
- }
- });
-
- // when
- final ObjectAdapter adapter = jsonValueEncoder.asAdapter(objectSpec, representation);
-
- // then
- assertSame(objectAdapter, adapter);
- }
-
- @Test(expected = IllegalArgumentException.class)
- public void whenObjectSpecIsBigIntegerButReprIsNot() throws Exception {
- // given
- allowingObjectSpecHas(EncodableFacet.class, encodableFacet);
- allowingObjectSpecCorrespondingClassIs(BigInteger.class);
-
- representation = JsonRepresentation.newMap("foo", "bar");
-
- // when
- jsonValueEncoder.asAdapter(objectSpec, representation);
- }
-
- @Test
- public void whenReprIsBigDecimal() throws Exception {
- // given
- allowingObjectSpecHas(EncodableFacet.class, encodableFacet);
- allowingObjectSpecCorrespondingClassIs(BigDecimal.class);
- final BigDecimal value = new BigDecimal("123234234.45612312343535");
- representation = new JsonRepresentation(DecimalNode.valueOf(value));
- context.checking(new Expectations() {
- {
- one(encodableFacet).fromEncodedString("" + value);
- will(returnValue(objectAdapter));
- }
- });
-
- // when
- final ObjectAdapter adapter = jsonValueEncoder.asAdapter(objectSpec, representation);
-
- // then
- assertSame(objectAdapter, adapter);
- }
-
- @Test(expected = IllegalArgumentException.class)
- public void whenObjectSpecIsBigDecimalButReprIsNot() throws Exception {
- // given
- allowingObjectSpecHas(EncodableFacet.class, encodableFacet);
- allowingObjectSpecCorrespondingClassIs(BigDecimal.class);
-
- representation = JsonRepresentation.newMap("foo", "bar");
-
- // when
- jsonValueEncoder.asAdapter(objectSpec, representation);
- }
-
- @Test
- public void whenReprIsString() throws Exception {
- // given
- allowingObjectSpecHas(EncodableFacet.class, encodableFacet);
- allowingObjectSpecCorrespondingClassIs(String.class);
- representation = new JsonRepresentation(TextNode.valueOf("aString"));
-
- context.checking(new Expectations() {
- {
- one(encodableFacet).fromEncodedString("aString");
- will(returnValue(objectAdapter));
- }
- });
-
- // when
- final ObjectAdapter adapter = jsonValueEncoder.asAdapter(objectSpec, representation);
-
- // then
- assertSame(objectAdapter, adapter);
- }
-
- private <T extends Facet> void allowingObjectSpecHas(final Class<T> facetClass, final T encodableFacet) {
- context.checking(new Expectations() {
- {
- allowing(objectSpec).getFacet(facetClass);
- will(returnValue(encodableFacet));
- }
- });
- }
-
- private void allowingObjectSpecCorrespondingClassIs(final Class<?> result) {
- context.checking(new Expectations() {
- {
- allowing(objectSpec).getCorrespondingClass();
- will(returnValue(result));
- }
- });
- }
-
-}
http://git-wip-us.apache.org/repos/asf/isis/blob/75f41b75/component/viewer/restfulobjects/impl/src/test/java/org/apache/isis/viewer/restfulobjects/viewer/resources/domainobjects/JsonValueEncoderTest_asObject.java
----------------------------------------------------------------------
diff --git a/component/viewer/restfulobjects/impl/src/test/java/org/apache/isis/viewer/restfulobjects/viewer/resources/domainobjects/JsonValueEncoderTest_asObject.java b/component/viewer/restfulobjects/impl/src/test/java/org/apache/isis/viewer/restfulobjects/viewer/resources/domainobjects/JsonValueEncoderTest_asObject.java
deleted file mode 100644
index 38f5841..0000000
--- a/component/viewer/restfulobjects/impl/src/test/java/org/apache/isis/viewer/restfulobjects/viewer/resources/domainobjects/JsonValueEncoderTest_asObject.java
+++ /dev/null
@@ -1,248 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements. See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership. The ASF licenses this file
- * to you under the Apache License, Version 2.0 (the
- * "License"); you may not use this file except in compliance
- * with the License. You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing,
- * software distributed under the License is distributed on an
- * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- * KIND, either express or implied. See the License for the
- * specific language governing permissions and limitations
- * under the License.
- */
-package org.apache.isis.viewer.restfulobjects.viewer.resources.domainobjects;
-
-import static org.junit.Assert.assertEquals;
-import static org.junit.Assert.assertSame;
-
-import java.math.BigDecimal;
-import java.math.BigInteger;
-
-import org.jmock.Expectations;
-import org.jmock.Mockery;
-import org.jmock.integration.junit4.JMock;
-import org.jmock.integration.junit4.JUnit4Mockery;
-import org.junit.Before;
-import org.junit.Test;
-import org.junit.runner.RunWith;
-
-import org.apache.isis.core.metamodel.adapter.ObjectAdapter;
-import org.apache.isis.core.metamodel.facetapi.Facet;
-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.viewer.resources.domainobjects.JsonValueEncoder;
-
-@RunWith(JMock.class)
-public class JsonValueEncoderTest_asObject {
-
- private final Mockery context = new JUnit4Mockery();
-
- private JsonValueEncoder jsonValueEncoder;
- private JsonRepresentation representation;
- private ObjectAdapter objectAdapter;
- private ObjectSpecification objectSpec;
-
- private EncodableFacet encodableFacet;
- private Object encoded;
-
- @Before
- public void setUp() throws Exception {
- objectAdapter = context.mock(ObjectAdapter.class);
- objectSpec = context.mock(ObjectSpecification.class);
-
- context.checking(new Expectations() {
- {
- allowing(objectAdapter).getSpecification();
- will(returnValue(objectSpec));
- }
- });
- encodableFacet = context.mock(EncodableFacet.class);
-
- encoded = new Object();
-
- jsonValueEncoder = new JsonValueEncoder();
- }
-
- @Test(expected = IllegalArgumentException.class)
- public void whenAdapterIsNull() throws Exception {
- jsonValueEncoder.asObject(null);
- }
-
- @Test(expected = IllegalArgumentException.class)
- public void whenObjectAdapterIsNotSpecialCaseAndSpecIsNotEncodable() throws Exception {
- allowingObjectSpecCorrespondingClassIs(String.class);
- allowingObjectSpecHas(EncodableFacet.class, null);
- jsonValueEncoder.asObject(objectAdapter);
- }
-
- @Test
- public void whenBooleanPrimitive() throws Exception {
- whenBoolean(boolean.class);
- }
-
- @Test
- public void whenBooleanWrapper() throws Exception {
- whenBoolean(Boolean.class);
- }
-
- private void whenBoolean(final Class<?> cls) {
- allowingObjectSpecCorrespondingClassIs(cls);
- allowingObjectSpecHas(EncodableFacet.class, encodableFacet);
- never(encodableFacet);
- context.checking(new Expectations() {
- {
- one(objectAdapter).getObject();
- will(returnValue(true));
- }
- });
- assertEquals(true, jsonValueEncoder.asObject(objectAdapter));
- }
-
- @Test
- public void whenIntegerPrimitive() throws Exception {
- whenInteger(int.class);
- }
-
- @Test
- public void whenIntegerWrapper() throws Exception {
- whenInteger(Integer.class);
- }
-
- private void whenInteger(final Class<?> cls) {
- allowingObjectSpecCorrespondingClassIs(cls);
- allowingObjectSpecHas(EncodableFacet.class, encodableFacet);
- never(encodableFacet);
- context.checking(new Expectations() {
- {
- one(objectAdapter).getObject();
- will(returnValue(123));
- }
- });
- assertEquals(123, jsonValueEncoder.asObject(objectAdapter));
- }
-
- @Test
- public void whenLongPrimitive() throws Exception {
- whenLong(long.class);
- }
-
- @Test
- public void whenLongWrapper() throws Exception {
- whenLong(Long.class);
- }
-
- private void whenLong(final Class<?> cls) {
- allowingObjectSpecCorrespondingClassIs(cls);
- allowingObjectSpecHas(EncodableFacet.class, encodableFacet);
- never(encodableFacet);
- context.checking(new Expectations() {
- {
- one(objectAdapter).getObject();
- will(returnValue(123456789L));
- }
- });
- assertEquals(123456789L, jsonValueEncoder.asObject(objectAdapter));
- }
-
- @Test
- public void whenDoublePrimitive() throws Exception {
- whenDouble(double.class);
- }
-
- @Test
- public void whenDoubleWrapper() throws Exception {
- whenDouble(Double.class);
- }
-
- private void whenDouble(final Class<?> cls) {
- allowingObjectSpecCorrespondingClassIs(cls);
- allowingObjectSpecHas(EncodableFacet.class, encodableFacet);
- never(encodableFacet);
- context.checking(new Expectations() {
- {
- one(objectAdapter).getObject();
- will(returnValue(12345.6789));
- }
- });
- assertEquals(12345.6789, jsonValueEncoder.asObject(objectAdapter));
- }
-
- @Test
- public void whenBigInteger() throws Exception {
- allowingObjectSpecCorrespondingClassIs(BigInteger.class);
- allowingObjectSpecHas(EncodableFacet.class, encodableFacet);
- never(encodableFacet);
- final BigInteger value = new BigInteger("123456789012345");
- context.checking(new Expectations() {
-
- {
- one(objectAdapter).getObject();
- will(returnValue(value));
- }
- });
- assertEquals(value, jsonValueEncoder.asObject(objectAdapter));
- }
-
- @Test
- public void whenBigDecimal() throws Exception {
- allowingObjectSpecCorrespondingClassIs(BigDecimal.class);
- allowingObjectSpecHas(EncodableFacet.class, encodableFacet);
- never(encodableFacet);
- final BigDecimal value = new BigDecimal("1234567890.1234567890");
- context.checking(new Expectations() {
-
- {
- one(objectAdapter).getObject();
- will(returnValue(value));
- }
- });
- assertEquals(value, jsonValueEncoder.asObject(objectAdapter));
- }
-
- @Test
- public void whenString() throws Exception {
- allowingObjectSpecCorrespondingClassIs(String.class);
- allowingObjectSpecHas(EncodableFacet.class, encodableFacet);
- context.checking(new Expectations() {
- {
- one(encodableFacet).toEncodedString(objectAdapter);
- will(returnValue("encodedString"));
- }
- });
- assertSame("encodedString", jsonValueEncoder.asObject(objectAdapter));
- }
-
- private void allowingObjectSpecCorrespondingClassIs(final Class<?> result) {
- context.checking(new Expectations() {
- {
- allowing(objectSpec).getCorrespondingClass();
- will(returnValue(result));
- }
- });
- }
-
- private <T extends Facet> void allowingObjectSpecHas(final Class<T> facetClass, final T encodableFacet) {
- context.checking(new Expectations() {
- {
- allowing(objectSpec).getFacet(facetClass);
- will(returnValue(encodableFacet));
- }
- });
- }
-
- private void never(final EncodableFacet encodableFacet2) {
- context.checking(new Expectations() {
- {
- never(encodableFacet2);
- }
- });
- }
-
-}
http://git-wip-us.apache.org/repos/asf/isis/blob/75f41b75/component/viewer/restfulobjects/impl/src/test/java/org/apache/isis/viewer/restfulobjects/viewer/util/MapUtilsTest.java
----------------------------------------------------------------------
diff --git a/component/viewer/restfulobjects/impl/src/test/java/org/apache/isis/viewer/restfulobjects/viewer/util/MapUtilsTest.java b/component/viewer/restfulobjects/impl/src/test/java/org/apache/isis/viewer/restfulobjects/viewer/util/MapUtilsTest.java
deleted file mode 100644
index 705c7e9..0000000
--- a/component/viewer/restfulobjects/impl/src/test/java/org/apache/isis/viewer/restfulobjects/viewer/util/MapUtilsTest.java
+++ /dev/null
@@ -1,51 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements. See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership. The ASF licenses this file
- * to you under the Apache License, Version 2.0 (the
- * "License"); you may not use this file except in compliance
- * with the License. You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing,
- * software distributed under the License is distributed on an
- * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- * KIND, either express or implied. See the License for the
- * specific language governing permissions and limitations
- * under the License.
- */
-package org.apache.isis.viewer.restfulobjects.viewer.util;
-
-import static org.hamcrest.CoreMatchers.is;
-import static org.junit.Assert.assertThat;
-
-import java.util.Map;
-
-import org.junit.Test;
-
-import org.apache.isis.viewer.restfulobjects.viewer.util.MapUtils;
-
-public class MapUtilsTest {
-
- @Test
- public void happyCase() throws Exception {
- final Map<String, String> map = MapUtils.mapOf("foo", "bar", "foz", "boz");
- assertThat(map.get("foo"), is("bar"));
- assertThat(map.get("foz"), is("boz"));
- assertThat(map.size(), is(2));
- }
-
- @Test
- public void emptyList() throws Exception {
- final Map<String, String> map = MapUtils.mapOf();
- assertThat(map.size(), is(0));
- }
-
- @Test(expected = IllegalArgumentException.class)
- public void uneven() throws Exception {
- MapUtils.mapOf("foo");
- }
-
-}
http://git-wip-us.apache.org/repos/asf/isis/blob/75f41b75/component/viewer/restfulobjects/impl/src/test/java/org/apache/isis/viewer/restfulobjects/viewer/util/UrlParserUtilsTest.java
----------------------------------------------------------------------
diff --git a/component/viewer/restfulobjects/impl/src/test/java/org/apache/isis/viewer/restfulobjects/viewer/util/UrlParserUtilsTest.java b/component/viewer/restfulobjects/impl/src/test/java/org/apache/isis/viewer/restfulobjects/viewer/util/UrlParserUtilsTest.java
deleted file mode 100644
index 912f18a..0000000
--- a/component/viewer/restfulobjects/impl/src/test/java/org/apache/isis/viewer/restfulobjects/viewer/util/UrlParserUtilsTest.java
+++ /dev/null
@@ -1,62 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements. See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership. The ASF licenses this file
- * to you under the Apache License, Version 2.0 (the
- * "License"); you may not use this file except in compliance
- * with the License. You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing,
- * software distributed under the License is distributed on an
- * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- * KIND, either express or implied. See the License for the
- * specific language governing permissions and limitations
- * under the License.
- */
-package org.apache.isis.viewer.restfulobjects.viewer.util;
-
-import static org.junit.Assert.assertEquals;
-
-import org.junit.Test;
-
-import org.apache.isis.viewer.restfulobjects.applib.JsonRepresentation;
-import org.apache.isis.viewer.restfulobjects.viewer.util.UrlParserUtils;
-
-public class UrlParserUtilsTest {
-
- @Test
- public void oidFromLink() throws Exception {
- final JsonRepresentation link = JsonRepresentation.newMap();
- link.mapPut("href", "http://localhost/objects/OID:1");
- final String oidFromHref = UrlParserUtils.oidFromLink(link);
- assertEquals("OID:1", oidFromHref);
- }
-
- @Test
- public void domainTypeFromLink() throws Exception {
- final JsonRepresentation link = JsonRepresentation.newMap();
- link.mapPut("href", "http://localhost/domainTypes/com.mycompany.myapp.Customer");
- final String oidFromHref = UrlParserUtils.domainTypeFrom(link);
- assertEquals("com.mycompany.myapp.Customer", oidFromHref);
- }
-
- @Test
- public void domainTypeFromLinkTrailingSlash() throws Exception {
- final JsonRepresentation link = JsonRepresentation.newMap();
- link.mapPut("href", "http://localhost/domainTypes/com.mycompany.myapp.Customer/");
- final String oidFromHref = UrlParserUtils.domainTypeFrom(link);
- assertEquals("com.mycompany.myapp.Customer", oidFromHref);
- }
-
- @Test
- public void domainTypeFromLinkFollowingStuff() throws Exception {
- final JsonRepresentation link = JsonRepresentation.newMap();
- link.mapPut("href", "http://localhost/domainTypes/com.mycompany.myapp.Customer/otherStuffHere");
- final String oidFromHref = UrlParserUtils.domainTypeFrom(link);
- assertEquals("com.mycompany.myapp.Customer", oidFromHref);
- }
-
-}
http://git-wip-us.apache.org/repos/asf/isis/blob/75f41b75/component/viewer/restfulobjects/jaxrs/pom.xml
----------------------------------------------------------------------
diff --git a/component/viewer/restfulobjects/jaxrs/pom.xml b/component/viewer/restfulobjects/jaxrs/pom.xml
new file mode 100644
index 0000000..e3b5e8d
--- /dev/null
+++ b/component/viewer/restfulobjects/jaxrs/pom.xml
@@ -0,0 +1,85 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+ Licensed to the Apache Software Foundation (ASF) under one
+ or more contributor license agreements. See the NOTICE file
+ distributed with this work for additional information
+ regarding copyright ownership. The ASF licenses this file
+ to you under the Apache License, Version 2.0 (the
+ "License"); you may not use this file except in compliance
+ with the License. You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing,
+ software distributed under the License is distributed on an
+ "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ KIND, either express or implied. See the License for the
+ specific language governing permissions and limitations
+ under the License.
+-->
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
+ <modelVersion>4.0.0</modelVersion>
+
+ <parent>
+ <groupId>org.apache.isis.viewer</groupId>
+ <artifactId>isis-viewer-restfulobjects</artifactId>
+ <version>2.0.0-SNAPSHOT</version>
+ </parent>
+
+ <artifactId>isis-viewer-restfulobjects-jaxrs</artifactId>
+ <name>Isis RestfulObjects Viewer jax-rs Resources</name>
+
+ <properties>
+ <siteBaseDir>..</siteBaseDir>
+ <relativeUrl>applib/</relativeUrl>
+ </properties>
+
+ <!-- used in Site generation for relative references. -->
+ <url>http://isis.apache.org/${relativeUrl}</url>
+
+ <dependencies>
+ <dependency>
+ <groupId>org.apache.isis.viewer</groupId>
+ <artifactId>isis-viewer-restfulobjects-applib</artifactId>
+ </dependency>
+
+ <dependency>
+ <groupId>org.jboss.resteasy</groupId>
+ <artifactId>resteasy-jaxrs</artifactId>
+ </dependency>
+ <dependency>
+ <groupId>org.codehaus.jackson</groupId>
+ <artifactId>jackson-core-asl</artifactId>
+ </dependency>
+ <dependency>
+ <groupId>org.codehaus.jackson</groupId>
+ <artifactId>jackson-mapper-asl</artifactId>
+ </dependency>
+
+ <dependency>
+ <groupId>org.apache.isis.core</groupId>
+ <artifactId>isis-core-metamodel</artifactId>
+ <scope>test</scope>
+ </dependency>
+
+ <dependency>
+ <groupId>org.apache.isis.core</groupId>
+ <artifactId>isis-core-unittestsupport</artifactId>
+ <scope>test</scope>
+ </dependency>
+
+ </dependencies>
+
+
+ <repositories>
+ <!-- The artifact in the maven repository has been moved and causes a build failure. Using this setting gets the artifact allowing the build to work. This fix should hopefully be temporary -->
+ <repository>
+ <id>java.net</id>
+ <url>http://repo1.maven.org/maven2</url>
+ <snapshots>
+ <enabled>false</enabled>
+ </snapshots>
+ </repository>
+ </repositories>
+
+</project>
http://git-wip-us.apache.org/repos/asf/isis/blob/75f41b75/component/viewer/restfulobjects/pom.xml
----------------------------------------------------------------------
diff --git a/component/viewer/restfulobjects/pom.xml b/component/viewer/restfulobjects/pom.xml
index e6d286e..93d7744 100644
--- a/component/viewer/restfulobjects/pom.xml
+++ b/component/viewer/restfulobjects/pom.xml
@@ -30,7 +30,7 @@
<groupId>org.apache.isis.viewer</groupId>
<artifactId>isis-viewer-restfulobjects</artifactId>
- <version>1.0.1-SNAPSHOT</version>
+ <version>2.0.0-SNAPSHOT</version>
<name>Isis RestfulObjects Viewer</name>
@@ -119,24 +119,36 @@
<dependency>
<groupId>org.apache.isis.viewer</groupId>
<artifactId>isis-viewer-restfulobjects-applib</artifactId>
- <version>1.0.1-SNAPSHOT</version>
+ <version>2.0.0-SNAPSHOT</version>
</dependency>
<dependency>
<groupId>org.apache.isis.viewer</groupId>
<artifactId>isis-viewer-restfulobjects-applib</artifactId>
- <version>1.0.1-SNAPSHOT</version>
+ <version>2.0.0-SNAPSHOT</version>
<type>test-jar</type>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.apache.isis.viewer</groupId>
- <artifactId>isis-viewer-restfulobjects-impl</artifactId>
- <version>1.0.1-SNAPSHOT</version>
+ <artifactId>isis-viewer-restfulobjects-rendering</artifactId>
+ <version>2.0.0-SNAPSHOT</version>
</dependency>
<dependency>
<groupId>org.apache.isis.viewer</groupId>
- <artifactId>isis-viewer-restfulobjects-impl</artifactId>
- <version>1.0.1-SNAPSHOT</version>
+ <artifactId>isis-viewer-restfulobjects-rendering</artifactId>
+ <version>2.0.0-SNAPSHOT</version>
+ <type>test-jar</type>
+ <scope>test</scope>
+ </dependency>
+ <dependency>
+ <groupId>org.apache.isis.viewer</groupId>
+ <artifactId>isis-viewer-restfulobjects-server</artifactId>
+ <version>2.0.0-SNAPSHOT</version>
+ </dependency>
+ <dependency>
+ <groupId>org.apache.isis.viewer</groupId>
+ <artifactId>isis-viewer-restfulobjects-server</artifactId>
+ <version>2.0.0-SNAPSHOT</version>
<type>test-jar</type>
<scope>test</scope>
</dependency>
@@ -147,7 +159,9 @@
<modules>
<module>applib</module>
- <module>impl</module>
+ <module>jaxrs</module>
+ <module>rendering</module>
+ <module>server</module>
<module>tck</module>
</modules>
</project>
http://git-wip-us.apache.org/repos/asf/isis/blob/75f41b75/component/viewer/restfulobjects/rendering/pom.xml
----------------------------------------------------------------------
diff --git a/component/viewer/restfulobjects/rendering/pom.xml b/component/viewer/restfulobjects/rendering/pom.xml
new file mode 100644
index 0000000..9e5b3e2
--- /dev/null
+++ b/component/viewer/restfulobjects/rendering/pom.xml
@@ -0,0 +1,62 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+ Licensed to the Apache Software Foundation (ASF) under one
+ or more contributor license agreements. See the NOTICE file
+ distributed with this work for additional information
+ regarding copyright ownership. The ASF licenses this file
+ to you under the Apache License, Version 2.0 (the
+ "License"); you may not use this file except in compliance
+ with the License. You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing,
+ software distributed under the License is distributed on an
+ "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ KIND, either express or implied. See the License for the
+ specific language governing permissions and limitations
+ under the License.
+-->
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
+ <modelVersion>4.0.0</modelVersion>
+
+ <parent>
+ <groupId>org.apache.isis.viewer</groupId>
+ <artifactId>isis-viewer-restfulobjects</artifactId>
+ <version>2.0.0-SNAPSHOT</version>
+ </parent>
+
+ <artifactId>isis-viewer-restfulobjects-rendering</artifactId>
+ <name>Isis RestfulObjects Viewer Rendering</name>
+
+ <properties>
+ <siteBaseDir>..</siteBaseDir>
+ <relativeUrl>viewer/</relativeUrl>
+ </properties>
+
+ <!-- used in Site generation for relative references. -->
+ <url>http://isis.apache.org/${relativeUrl}</url>
+
+ <dependencies>
+
+ <dependency>
+ <groupId>org.apache.isis.core</groupId>
+ <artifactId>isis-core-unittestsupport</artifactId>
+ <scope>test</scope>
+ </dependency>
+
+ <dependency>
+ <groupId>org.apache.isis.core</groupId>
+ <artifactId>isis-core-metamodel</artifactId>
+ </dependency>
+ <dependency>
+ <groupId>org.apache.isis.core</groupId>
+ <artifactId>isis-core-runtime</artifactId>
+ </dependency>
+ <dependency>
+ <groupId>org.apache.isis.viewer</groupId>
+ <artifactId>isis-viewer-restfulobjects-applib</artifactId>
+ </dependency>
+
+ </dependencies>
+</project>
http://git-wip-us.apache.org/repos/asf/isis/blob/75f41b75/component/viewer/restfulobjects/rendering/src/main/java/org/apache/isis/viewer/restfulobjects/rendering/LinkBuilder.java
----------------------------------------------------------------------
diff --git a/component/viewer/restfulobjects/rendering/src/main/java/org/apache/isis/viewer/restfulobjects/rendering/LinkBuilder.java b/component/viewer/restfulobjects/rendering/src/main/java/org/apache/isis/viewer/restfulobjects/rendering/LinkBuilder.java
new file mode 100644
index 0000000..a120f59
--- /dev/null
+++ b/component/viewer/restfulobjects/rendering/src/main/java/org/apache/isis/viewer/restfulobjects/rendering/LinkBuilder.java
@@ -0,0 +1,94 @@
+/**
+ * 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;
+
+
+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 com.google.common.net.MediaType;
+
+public final class LinkBuilder {
+
+ public static LinkBuilder newBuilder(final RendererContext resourceContext, final Rel rel, final RepresentationType representationType, final String hrefFormat, final Object... hrefArgs) {
+ return newBuilder(resourceContext, rel, representationType.getMediaType(), hrefFormat, hrefArgs);
+ }
+
+ public static LinkBuilder newBuilder(final RendererContext resourceContext, final Rel rel, final MediaType mediaType, final String hrefFormat, final Object... hrefArgs) {
+ return new LinkBuilder(resourceContext, rel, String.format(hrefFormat, hrefArgs), mediaType);
+ }
+
+ private final RendererContext resourceContext;
+ private final JsonRepresentation representation = JsonRepresentation.newMap();
+
+ private final Rel rel;
+ private final String href;
+ private final MediaType mediaType;
+
+ private RoHttpMethod method = RoHttpMethod.GET;
+ private String title;
+ private JsonRepresentation arguments;
+ private JsonRepresentation value;
+ private String id;
+
+ protected LinkBuilder(final RendererContext resourceContext, final Rel rel, final String href, final MediaType mediaType) {
+ this.resourceContext = resourceContext;
+ this.rel = rel;
+ this.href = href;
+ this.mediaType = mediaType;
+ }
+
+ public LinkBuilder withHttpMethod(final RoHttpMethod method) {
+ this.method = method;
+ return this;
+ }
+
+ public LinkBuilder withTitle(final String title) {
+ this.title = title;
+ return this;
+ }
+
+ public LinkBuilder withArguments(final JsonRepresentation arguments) {
+ this.arguments = arguments;
+ return this;
+ }
+
+ public LinkBuilder withId(final String id) {
+ this.id = id;
+ return this;
+ }
+
+ public LinkBuilder withValue(final JsonRepresentation value) {
+ this.value = value;
+ return this;
+ }
+
+ public JsonRepresentation build() {
+ representation.mapPut("id", id);
+ representation.mapPut("rel", rel.getName());
+ representation.mapPut("href", resourceContext.urlFor(href));
+ representation.mapPut("method", method);
+ representation.mapPut("type", mediaType.toString());
+ representation.mapPut("title", title);
+ representation.mapPut("arguments", arguments);
+ representation.mapPut("value", value);
+ 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/LinkFollower.java
----------------------------------------------------------------------
diff --git a/component/viewer/restfulobjects/rendering/src/main/java/org/apache/isis/viewer/restfulobjects/rendering/LinkFollower.java b/component/viewer/restfulobjects/rendering/src/main/java/org/apache/isis/viewer/restfulobjects/rendering/LinkFollower.java
new file mode 100644
index 0000000..3818ff8
--- /dev/null
+++ b/component/viewer/restfulobjects/rendering/src/main/java/org/apache/isis/viewer/restfulobjects/rendering/LinkFollower.java
@@ -0,0 +1,125 @@
+/*
+ * 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;
+
+import java.util.Collections;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+
+import org.apache.isis.viewer.restfulobjects.applib.JsonRepresentation;
+import org.apache.isis.viewer.restfulobjects.applib.util.PathNode;
+import org.apache.isis.viewer.restfulobjects.rendering.util.GraphUtil;
+
+@SuppressWarnings({ "rawtypes", "unchecked" })
+public final class LinkFollower {
+
+ public final static LinkFollower create(final List<List<String>> links) {
+ final Map<PathNode, Map> graph = GraphUtil.asGraph(links);
+ return new LinkFollower(graph, Mode.FOLLOWING, PathNode.NULL);
+ }
+
+ private enum Mode {
+ FOLLOWING, TERMINATED;
+ }
+
+ private final Map<PathNode, Map> graph;
+ private final Mode mode;
+ private final PathNode root;
+
+ private LinkFollower(final Map<PathNode, Map> graph, final Mode mode, final PathNode root) {
+ this.graph = graph;
+ this.mode = mode;
+ this.root = root;
+ }
+
+ /**
+ * A little algebra...
+ */
+ public LinkFollower follow(final String pathTemplate, final Object... args) {
+ final String path = String.format(pathTemplate, args);
+ if (path == null) {
+ return terminated(PathNode.NULL);
+ }
+ if (mode == Mode.TERMINATED) {
+ return terminated(this.root);
+ }
+ final PathNode node = PathNode.parse(path);
+ if (mode == Mode.FOLLOWING) {
+ final Map<PathNode, Map> remaining = graph.get(node);
+ if (remaining != null) {
+ final PathNode key = findKey(node);
+ return new LinkFollower(remaining, Mode.FOLLOWING, key);
+ } else {
+ return terminated(node);
+ }
+ }
+ return terminated(node);
+ }
+
+ /**
+ * somewhat bizarre, but we have to find the actual node that is in the
+ * graph; the one we matching on doesn't match on the
+ * {@link PathNode#getCriteria()} map.
+ */
+ private PathNode findKey(final PathNode node) {
+ final Set<PathNode> keySet = graph.keySet();
+ for (final PathNode key : keySet) {
+ if (key.equals(node)) {
+ return key;
+ }
+ }
+ // shouldn't happen
+ return node;
+ }
+
+ private static LinkFollower terminated(final PathNode node) {
+ return new LinkFollower(null, Mode.TERMINATED, node);
+ }
+
+ /**
+ * Not public API; use {@link #matches(JsonRepresentation)}.
+ */
+ boolean isFollowing() {
+ return mode == Mode.FOLLOWING;
+ }
+
+ public boolean isTerminated() {
+ return mode == Mode.TERMINATED;
+ }
+
+ public Map<String, String> criteria() {
+ return Collections.unmodifiableMap(root.getCriteria());
+ }
+
+ /**
+ * Ensure that every key present in the provided map matches the criterium.
+ *
+ * <p>
+ * Any keys in the criterium that are not present in the map will be
+ * ignored.
+ */
+ public boolean matches(final JsonRepresentation link) {
+ if (!isFollowing()) {
+ return false;
+ }
+ return root == null || root.matches(link);
+ }
+
+}
http://git-wip-us.apache.org/repos/asf/isis/blob/75f41b75/component/viewer/restfulobjects/rendering/src/main/java/org/apache/isis/viewer/restfulobjects/rendering/NOTUSED_WellKnownType.java
----------------------------------------------------------------------
diff --git a/component/viewer/restfulobjects/rendering/src/main/java/org/apache/isis/viewer/restfulobjects/rendering/NOTUSED_WellKnownType.java b/component/viewer/restfulobjects/rendering/src/main/java/org/apache/isis/viewer/restfulobjects/rendering/NOTUSED_WellKnownType.java
new file mode 100644
index 0000000..131c265
--- /dev/null
+++ b/component/viewer/restfulobjects/rendering/src/main/java/org/apache/isis/viewer/restfulobjects/rendering/NOTUSED_WellKnownType.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;
+
+// TODO: remove, not used?
+enum NOTUSED_WellKnownType {
+
+ STRING(java.lang.String.class),
+ BYTE(java.lang.Byte.class),
+ SHORT(java.lang.Short.class),
+ INT(java.lang.Integer.class),
+ LONG(java.lang.Long.class),
+ BOOLEAN(java.lang.Boolean.class),
+ FLOAT(java.lang.Float.class),
+ DOUBLE(java.lang.Double.class),
+ BIGINT(java.math.BigInteger.class),
+ BIGDEC(java.math.BigDecimal.class),
+ OBJECT(java.lang.Object.class),
+ LIST(java.util.List.class),
+ SET(java.util.Set.class);
+
+ private final Class<?> cls;
+ private final String className;
+
+ private NOTUSED_WellKnownType(final Class<?> cls) {
+ this.cls = cls;
+ this.className = cls.getName();
+ }
+
+ private String getName() {
+ return name().toLowerCase();
+ }
+
+ private static NOTUSED_WellKnownType lookup(final Class<?> cls) {
+ for (final NOTUSED_WellKnownType wellKnownType : values()) {
+ if (wellKnownType.cls.equals(cls)) {
+ return wellKnownType;
+ }
+ }
+ return null;
+ }
+
+ private static NOTUSED_WellKnownType lookup(final String className) {
+ for (final NOTUSED_WellKnownType wellKnownType : values()) {
+ if (wellKnownType.className.equals(className)) {
+ return wellKnownType;
+ }
+ }
+ return null;
+ }
+
+ @SuppressWarnings("unused")
+ private static String canonical(final String className) {
+ final NOTUSED_WellKnownType wellKnownType = NOTUSED_WellKnownType.lookup(className);
+ return wellKnownType != null ? wellKnownType.getName() : className;
+ }
+
+ @SuppressWarnings("unused")
+ private static String canonical(final Class<?> cls) {
+ final NOTUSED_WellKnownType wellKnownType = NOTUSED_WellKnownType.lookup(cls);
+ return wellKnownType != null ? wellKnownType.getName() : cls.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/RendererContext.java
----------------------------------------------------------------------
diff --git a/component/viewer/restfulobjects/rendering/src/main/java/org/apache/isis/viewer/restfulobjects/rendering/RendererContext.java b/component/viewer/restfulobjects/rendering/src/main/java/org/apache/isis/viewer/restfulobjects/rendering/RendererContext.java
new file mode 100644
index 0000000..22d702d
--- /dev/null
+++ b/component/viewer/restfulobjects/rendering/src/main/java/org/apache/isis/viewer/restfulobjects/rendering/RendererContext.java
@@ -0,0 +1,23 @@
+package org.apache.isis.viewer.restfulobjects.rendering;
+
+import java.util.List;
+
+import org.apache.isis.applib.annotation.Where;
+import org.apache.isis.applib.profiles.Localization;
+import org.apache.isis.core.commons.authentication.AuthenticationSession;
+import org.apache.isis.core.metamodel.adapter.mgr.AdapterManager;
+
+public interface RendererContext {
+
+ public String urlFor(final String url);
+
+ public AuthenticationSession getAuthenticationSession();
+
+ public AdapterManager getAdapterManager();
+
+ public List<List<String>> getFollowLinks();
+
+ public Where getWhere();
+
+ public Localization getLocalization();
+}
http://git-wip-us.apache.org/repos/asf/isis/blob/75f41b75/component/viewer/restfulobjects/rendering/src/main/java/org/apache/isis/viewer/restfulobjects/rendering/RendererFactory.java
----------------------------------------------------------------------
diff --git a/component/viewer/restfulobjects/rendering/src/main/java/org/apache/isis/viewer/restfulobjects/rendering/RendererFactory.java b/component/viewer/restfulobjects/rendering/src/main/java/org/apache/isis/viewer/restfulobjects/rendering/RendererFactory.java
new file mode 100644
index 0000000..d05d712
--- /dev/null
+++ b/component/viewer/restfulobjects/rendering/src/main/java/org/apache/isis/viewer/restfulobjects/rendering/RendererFactory.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;
+
+import org.apache.isis.viewer.restfulobjects.applib.JsonRepresentation;
+import org.apache.isis.viewer.restfulobjects.applib.RepresentationType;
+
+public interface RendererFactory {
+
+ RepresentationType getRepresentationType();
+
+ ReprRenderer<?, ?> newRenderer(RendererContext resourceContext, LinkFollower linkFollower, JsonRepresentation 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/RendererFactoryRegistry.java
----------------------------------------------------------------------
diff --git a/component/viewer/restfulobjects/rendering/src/main/java/org/apache/isis/viewer/restfulobjects/rendering/RendererFactoryRegistry.java b/component/viewer/restfulobjects/rendering/src/main/java/org/apache/isis/viewer/restfulobjects/rendering/RendererFactoryRegistry.java
new file mode 100644
index 0000000..7799e52
--- /dev/null
+++ b/component/viewer/restfulobjects/rendering/src/main/java/org/apache/isis/viewer/restfulobjects/rendering/RendererFactoryRegistry.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;
+
+import java.util.Map;
+
+import org.apache.isis.viewer.restfulobjects.applib.RepresentationType;
+import org.apache.isis.viewer.restfulobjects.rendering.domainobjects.ActionResultReprRenderer;
+import org.apache.isis.viewer.restfulobjects.rendering.domainobjects.DomainObjectReprRenderer;
+import org.apache.isis.viewer.restfulobjects.rendering.domainobjects.ListReprRenderer;
+import org.apache.isis.viewer.restfulobjects.rendering.domainobjects.ObjectActionReprRenderer;
+import org.apache.isis.viewer.restfulobjects.rendering.domainobjects.ObjectCollectionReprRenderer;
+import org.apache.isis.viewer.restfulobjects.rendering.domainobjects.ObjectPropertyReprRenderer;
+import org.apache.isis.viewer.restfulobjects.rendering.domainobjects.ScalarValueReprRenderer;
+import org.apache.isis.viewer.restfulobjects.rendering.domaintypes.ActionDescriptionReprRenderer;
+import org.apache.isis.viewer.restfulobjects.rendering.domaintypes.ActionParameterDescriptionReprRenderer;
+import org.apache.isis.viewer.restfulobjects.rendering.domaintypes.CollectionDescriptionReprRenderer;
+import org.apache.isis.viewer.restfulobjects.rendering.domaintypes.DomainTypeReprRenderer;
+import org.apache.isis.viewer.restfulobjects.rendering.domaintypes.PropertyDescriptionReprRenderer;
+import org.apache.isis.viewer.restfulobjects.rendering.domaintypes.TypeActionResultReprRenderer;
+import org.apache.isis.viewer.restfulobjects.rendering.domaintypes.TypeListReprRenderer;
+
+import com.google.common.collect.Maps;
+import com.google.common.net.MediaType;
+
+public class RendererFactoryRegistry {
+
+ // TODO: get rid of this horrible singleton
+ public final static RendererFactoryRegistry instance = new RendererFactoryRegistry();
+
+ private final Map<MediaType, RendererFactory> factoryByReprType = Maps.newHashMap();
+
+ RendererFactoryRegistry() {
+ registerDefaults();
+ }
+
+ private void registerDefaults() {
+ register(new DomainObjectReprRenderer.Factory());
+ register(new ObjectPropertyReprRenderer.Factory());
+ register(new ObjectCollectionReprRenderer.Factory());
+ register(new ObjectActionReprRenderer.Factory());
+ register(new ActionResultReprRenderer.Factory());
+ register(new ListReprRenderer.Factory());
+ register(new ScalarValueReprRenderer.Factory());
+ register(new TypeListReprRenderer.Factory());
+ register(new DomainTypeReprRenderer.Factory());
+ register(new PropertyDescriptionReprRenderer.Factory());
+ register(new CollectionDescriptionReprRenderer.Factory());
+ register(new ActionDescriptionReprRenderer.Factory());
+ register(new ActionParameterDescriptionReprRenderer.Factory());
+ register(new TypeActionResultReprRenderer.Factory());
+ }
+
+ public void register(final RendererFactory factory) {
+ final RepresentationType representationType = factory.getRepresentationType();
+ factoryByReprType.put(representationType.getMediaType(), factory);
+ }
+
+ public RendererFactory find(final MediaType mediaType) {
+ return factoryByReprType.get(mediaType);
+ }
+
+ public RendererFactory find(final RepresentationType representationType) {
+ return find(representationType.getMediaType());
+ }
+
+}
http://git-wip-us.apache.org/repos/asf/isis/blob/75f41b75/component/viewer/restfulobjects/rendering/src/main/java/org/apache/isis/viewer/restfulobjects/rendering/ReprRenderer.java
----------------------------------------------------------------------
diff --git a/component/viewer/restfulobjects/rendering/src/main/java/org/apache/isis/viewer/restfulobjects/rendering/ReprRenderer.java b/component/viewer/restfulobjects/rendering/src/main/java/org/apache/isis/viewer/restfulobjects/rendering/ReprRenderer.java
new file mode 100644
index 0000000..81a03da
--- /dev/null
+++ b/component/viewer/restfulobjects/rendering/src/main/java/org/apache/isis/viewer/restfulobjects/rendering/ReprRenderer.java
@@ -0,0 +1,32 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.isis.viewer.restfulobjects.rendering;
+
+import org.apache.isis.viewer.restfulobjects.applib.JsonRepresentation;
+import org.apache.isis.viewer.restfulobjects.applib.RepresentationType;
+
+public interface ReprRenderer<R extends ReprRenderer<R, T>, T> {
+
+ RepresentationType getRepresentationType();
+
+ R with(T t);
+
+ public JsonRepresentation render();
+
+}
http://git-wip-us.apache.org/repos/asf/isis/blob/75f41b75/component/viewer/restfulobjects/rendering/src/main/java/org/apache/isis/viewer/restfulobjects/rendering/ReprRendererAbstract.java
----------------------------------------------------------------------
diff --git a/component/viewer/restfulobjects/rendering/src/main/java/org/apache/isis/viewer/restfulobjects/rendering/ReprRendererAbstract.java b/component/viewer/restfulobjects/rendering/src/main/java/org/apache/isis/viewer/restfulobjects/rendering/ReprRendererAbstract.java
new file mode 100644
index 0000000..0a68617
--- /dev/null
+++ b/component/viewer/restfulobjects/rendering/src/main/java/org/apache/isis/viewer/restfulobjects/rendering/ReprRendererAbstract.java
@@ -0,0 +1,173 @@
+/*
+ * 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;
+
+import java.util.List;
+
+import org.apache.isis.core.commons.authentication.AuthenticationSession;
+import org.apache.isis.core.metamodel.adapter.ObjectAdapter;
+import org.apache.isis.core.metamodel.spec.ObjectSpecification;
+import org.apache.isis.core.runtime.system.context.IsisContext;
+import org.apache.isis.core.runtime.system.transaction.UpdateNotifier;
+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.domainobjects.DomainObjectReprRenderer;
+import org.apache.isis.viewer.restfulobjects.rendering.domaintypes.DomainTypeReprRenderer;
+
+public abstract class ReprRendererAbstract<R extends ReprRendererAbstract<R, T>, T> implements ReprRenderer<R, T> {
+
+ protected final RendererContext resourceContext;
+ private final LinkFollower linkFollower;
+ private final RepresentationType representationType;
+ protected final JsonRepresentation representation;
+
+ protected boolean includesSelf;
+
+ public ReprRendererAbstract(final RendererContext resourceContext, final LinkFollower linkFollower, final RepresentationType representationType, final JsonRepresentation representation) {
+ this.resourceContext = resourceContext;
+ this.linkFollower = asProvidedElseCreate(linkFollower);
+ this.representationType = representationType;
+ this.representation = representation;
+ }
+
+ public RendererContext getResourceContext() {
+ return resourceContext;
+ }
+
+ public LinkFollower getLinkFollower() {
+ return linkFollower;
+ }
+
+ private LinkFollower asProvidedElseCreate(final LinkFollower linkFollower) {
+ if (linkFollower != null) {
+ return linkFollower;
+ }
+ return LinkFollower.create(resourceContext.getFollowLinks());
+ }
+
+ @Override
+ public RepresentationType getRepresentationType() {
+ return representationType;
+ }
+
+ @SuppressWarnings("unchecked")
+ public R includesSelf() {
+ this.includesSelf = true;
+ return (R) this;
+ }
+
+ public R withSelf(final String href) {
+ if (href != null) {
+ getLinks().arrayAdd(LinkBuilder.newBuilder(resourceContext, Rel.SELF, representationType, href).build());
+ }
+ return cast(this);
+ }
+
+ public R withSelf(final JsonRepresentation link) {
+ final String rel = link.getString("rel");
+ if (rel == null || !rel.equals(Rel.SELF.getName())) {
+ throw new IllegalArgumentException("Provided link does not have a 'rel' of 'self'; was: " + link);
+ }
+ if (link != null) {
+ getLinks().arrayAdd(link);
+ }
+ return cast(this);
+ }
+
+ /**
+ * Will lazily create links array as required
+ */
+ protected JsonRepresentation getLinks() {
+ JsonRepresentation links = representation.getArray("links");
+ if (links == null) {
+ links = JsonRepresentation.newArray();
+ representation.mapPut("links", links);
+ }
+ return links;
+ }
+
+ protected void addLink(final Rel rel, final ObjectSpecification objectSpec) {
+ if (objectSpec == null) {
+ return;
+ }
+ final LinkBuilder linkBuilder = DomainTypeReprRenderer.newLinkToBuilder(getResourceContext(), rel, objectSpec);
+ getLinks().arrayAdd(linkBuilder.build());
+ }
+
+ /**
+ * Will lazily create extensions map as required
+ */
+ protected JsonRepresentation getExtensions() {
+ JsonRepresentation extensions = representation.getMap("extensions");
+ if (extensions == null) {
+ extensions = JsonRepresentation.newMap();
+ representation.mapPut("extensions", extensions);
+ }
+ return extensions;
+ }
+
+ public R withExtensions(final JsonRepresentation extensions) {
+ if (!extensions.isMap()) {
+ throw new IllegalArgumentException("extensions must be a map");
+ }
+ representation.mapPut("extensions", extensions);
+ return cast(this);
+ }
+
+ @SuppressWarnings("unchecked")
+ protected static <R extends ReprRendererAbstract<R, T>, T> R cast(final ReprRendererAbstract<R, T> builder) {
+ return (R) builder;
+ }
+
+ @Override
+ public abstract JsonRepresentation render();
+
+ /**
+ * Convenience for representations that are returned from objects that
+ * mutate state.
+ */
+ protected final void addExtensionsIsisProprietaryChangedObjects() {
+ final UpdateNotifier updateNotifier = getUpdateNotifier();
+
+ addToExtensions("changed", updateNotifier.getChangedObjects());
+ addToExtensions("disposed", updateNotifier.getDisposedObjects());
+ }
+
+ private void addToExtensions(final String key, final List<ObjectAdapter> adapters) {
+ final JsonRepresentation adapterList = JsonRepresentation.newArray();
+ getExtensions().mapPut(key, adapterList);
+ for (final ObjectAdapter adapter : adapters) {
+ adapterList.arrayAdd(DomainObjectReprRenderer.newLinkToBuilder(getResourceContext(), Rel.OBJECT, adapter).build());
+ }
+ }
+
+ protected List<ObjectAdapter> getServiceAdapters() {
+ return IsisContext.getPersistenceSession().getServices();
+ }
+
+ protected AuthenticationSession getAuthenticationSession() {
+ return IsisContext.getAuthenticationSession();
+ }
+
+ protected UpdateNotifier getUpdateNotifier() {
+ return IsisContext.getCurrentTransaction().getUpdateNotifier();
+ }
+
+}
http://git-wip-us.apache.org/repos/asf/isis/blob/75f41b75/component/viewer/restfulobjects/rendering/src/main/java/org/apache/isis/viewer/restfulobjects/rendering/ReprRendererException.java
----------------------------------------------------------------------
diff --git a/component/viewer/restfulobjects/rendering/src/main/java/org/apache/isis/viewer/restfulobjects/rendering/ReprRendererException.java b/component/viewer/restfulobjects/rendering/src/main/java/org/apache/isis/viewer/restfulobjects/rendering/ReprRendererException.java
new file mode 100644
index 0000000..b8cbfca
--- /dev/null
+++ b/component/viewer/restfulobjects/rendering/src/main/java/org/apache/isis/viewer/restfulobjects/rendering/ReprRendererException.java
@@ -0,0 +1,57 @@
+/*
+ * 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;
+
+import org.apache.isis.viewer.restfulobjects.applib.JsonRepresentation;
+
+public class ReprRendererException extends RuntimeException {
+
+ public static ReprRendererException create(final String message, final Object... args) {
+ return create((Exception) null, message, args);
+ }
+
+ public static ReprRendererException create(final Exception cause) {
+ return create(cause, null);
+ }
+
+ public static ReprRendererException create(final Exception cause, final String message, final Object... args) {
+ return new ReprRendererException(formatString(message, args), cause, null);
+ }
+
+ public static ReprRendererException create(final JsonRepresentation repr, final String message, final Object... args) {
+ return new ReprRendererException(formatString(message, args), null, repr);
+ }
+
+ private static String formatString(final String formatStr, final Object... args) {
+ return formatStr != null ? String.format(formatStr, args) : null;
+ }
+
+ private static final long serialVersionUID = 1L;
+ private final JsonRepresentation jsonRepresentation;
+
+ private ReprRendererException(final String message, final Throwable ex, final JsonRepresentation jsonRepresentation) {
+ super(message, ex);
+ this.jsonRepresentation = jsonRepresentation;
+ }
+
+ public JsonRepresentation getJsonRepresentation() {
+ return jsonRepresentation;
+ }
+
+}
http://git-wip-us.apache.org/repos/asf/isis/blob/75f41b75/component/viewer/restfulobjects/rendering/src/main/java/org/apache/isis/viewer/restfulobjects/rendering/ReprRendererFactoryAbstract.java
----------------------------------------------------------------------
diff --git a/component/viewer/restfulobjects/rendering/src/main/java/org/apache/isis/viewer/restfulobjects/rendering/ReprRendererFactoryAbstract.java b/component/viewer/restfulobjects/rendering/src/main/java/org/apache/isis/viewer/restfulobjects/rendering/ReprRendererFactoryAbstract.java
new file mode 100644
index 0000000..69477db
--- /dev/null
+++ b/component/viewer/restfulobjects/rendering/src/main/java/org/apache/isis/viewer/restfulobjects/rendering/ReprRendererFactoryAbstract.java
@@ -0,0 +1,36 @@
+/*
+ * 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;
+
+import org.apache.isis.viewer.restfulobjects.applib.RepresentationType;
+
+public abstract class ReprRendererFactoryAbstract implements RendererFactory {
+
+ private final RepresentationType representationType;
+
+ public ReprRendererFactoryAbstract(final RepresentationType representationType) {
+ this.representationType = representationType;
+ }
+
+ @Override
+ public RepresentationType getRepresentationType() {
+ return representationType;
+ }
+
+}
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/AbstractObjectMemberReprRenderer.java
----------------------------------------------------------------------
diff --git a/component/viewer/restfulobjects/rendering/src/main/java/org/apache/isis/viewer/restfulobjects/rendering/domainobjects/AbstractObjectMemberReprRenderer.java b/component/viewer/restfulobjects/rendering/src/main/java/org/apache/isis/viewer/restfulobjects/rendering/domainobjects/AbstractObjectMemberReprRenderer.java
new file mode 100644
index 0000000..73c91b9
--- /dev/null
+++ b/component/viewer/restfulobjects/rendering/src/main/java/org/apache/isis/viewer/restfulobjects/rendering/domainobjects/AbstractObjectMemberReprRenderer.java
@@ -0,0 +1,257 @@
+/**
+ * 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.applib.annotation.Where;
+import org.apache.isis.core.metamodel.adapter.ObjectAdapter;
+import org.apache.isis.core.metamodel.consent.Consent;
+import org.apache.isis.core.metamodel.facetapi.Facet;
+import org.apache.isis.core.metamodel.spec.ObjectSpecification;
+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.LinkFollower;
+import org.apache.isis.viewer.restfulobjects.rendering.RendererContext;
+import org.apache.isis.viewer.restfulobjects.rendering.ReprRendererAbstract;
+import org.codehaus.jackson.node.NullNode;
+
+public abstract class AbstractObjectMemberReprRenderer<R extends ReprRendererAbstract<R, ObjectAndMember<T>>, T extends ObjectMember> extends ReprRendererAbstract<R, ObjectAndMember<T>> {
+
+ protected enum Mode {
+ INLINE, FOLLOWED, STANDALONE, MUTATED, ARGUMENTS;
+
+ public boolean isInline() {
+ return this == INLINE;
+ }
+
+ public boolean isFollowed() {
+ return this == FOLLOWED;
+ }
+
+ public boolean isStandalone() {
+ return this == STANDALONE;
+ }
+
+ public boolean isMutated() {
+ return this == MUTATED;
+ }
+
+ public boolean isArguments() {
+ return this == ARGUMENTS;
+ }
+ }
+
+ protected ObjectAdapterLinkTo linkTo;
+
+ protected ObjectAdapter objectAdapter;
+ protected MemberType memberType;
+ protected T objectMember;
+ protected Mode mode = Mode.INLINE; // unless we determine otherwise
+
+ private final Where where;
+
+ public AbstractObjectMemberReprRenderer(final RendererContext resourceContext, final LinkFollower linkFollower, final RepresentationType representationType, final JsonRepresentation representation, Where where) {
+ super(resourceContext, linkFollower, representationType, representation);
+ this.where = where;
+ }
+
+ @Override
+ public R with(final ObjectAndMember<T> objectAndMember) {
+ this.objectAdapter = objectAndMember.getObjectAdapter();
+ this.objectMember = objectAndMember.getMember();
+ this.memberType = MemberType.determineFrom(objectMember);
+ usingLinkTo(new DomainObjectLinkTo());
+
+ // done eagerly so can use as criteria for x-ro-follow-links
+ representation.mapPut(memberType.getJsProp(), objectMember.getId());
+ representation.mapPut("memberType", memberType.getName());
+
+ return cast(this);
+ }
+
+ /**
+ * Must be called after {@link #with(ObjectAndMember)} (which provides the
+ * {@link #objectAdapter}).
+ */
+ public R usingLinkTo(final ObjectAdapterLinkTo linkTo) {
+ this.linkTo = linkTo.usingUrlBase(resourceContext).with(objectAdapter);
+ return cast(this);
+ }
+
+ /**
+ * Indicate that this is a standalone representation.
+ */
+ public R asStandalone() {
+ mode = Mode.STANDALONE;
+ return cast(this);
+ }
+
+ /**
+ * Indicate that this is a representation to include as the result of a
+ * followed link.
+ */
+ public R asFollowed() {
+ mode = Mode.FOLLOWED;
+ return cast(this);
+ }
+
+ /**
+ * Indicates that the representation was produced as the result of a
+ * resource that mutated the state.
+ *
+ * <p>
+ * The effect of this is to suppress the link to self.
+ */
+ public R asMutated() {
+ mode = Mode.MUTATED;
+ return cast(this);
+ }
+
+ public R asArguments() {
+ mode = Mode.ARGUMENTS;
+ return cast(this);
+ }
+
+ /**
+ * For subclasses to call from their {@link #render()} method.
+ */
+ protected void renderMemberContent() {
+ if (mode.isInline()) {
+ addDetailsLinkIfPersistent();
+ }
+
+ if (mode.isStandalone()) {
+ addLinkToSelf();
+ }
+
+ if (mode.isStandalone() || mode.isMutated()) {
+ addLinkToUp();
+ }
+
+ if (mode.isFollowed() || mode.isStandalone() || mode.isMutated()) {
+ addMutatorsIfEnabled();
+
+ putExtensionsIsisProprietary();
+ addLinksToFormalDomainModel();
+ addLinksIsisProprietary();
+ }
+ }
+
+ private void addLinkToSelf() {
+ getLinks().arrayAdd(linkTo.memberBuilder(Rel.SELF, memberType, objectMember).build());
+ }
+
+ private void addLinkToUp() {
+ getLinks().arrayAdd(linkTo.builder(Rel.UP).build());
+ }
+
+ protected abstract void addMutatorsIfEnabled();
+
+ /**
+ * For subclasses to call back to when {@link #addMutatorsIfEnabled() adding
+ * mutators}.
+ */
+ protected void addLinkFor(final MutatorSpec mutatorSpec) {
+ if (!hasMemberFacet(mutatorSpec.mutatorFacetType)) {
+ return;
+ }
+ final JsonRepresentation arguments = mutatorArgs(mutatorSpec);
+ final RepresentationType representationType = memberType.getRepresentationType();
+ final JsonRepresentation mutatorLink = linkToForMutatorInvoke().memberBuilder(mutatorSpec.rel, memberType, objectMember, representationType, mutatorSpec.suffix).withHttpMethod(mutatorSpec.httpMethod).withArguments(arguments).build();
+ getLinks().arrayAdd(mutatorLink);
+ }
+
+ /**
+ * Hook to allow actions to render invoke links that point to the
+ * contributing service.
+ */
+ protected ObjectAdapterLinkTo linkToForMutatorInvoke() {
+ return linkTo;
+ }
+
+ /**
+ * Default implementation (common to properties and collections) that can be
+ * overridden (ie by actions) if required.
+ */
+ protected JsonRepresentation mutatorArgs(final MutatorSpec mutatorSpec) {
+ if (mutatorSpec.arguments.isNone()) {
+ return null;
+ }
+ if (mutatorSpec.arguments.isOne()) {
+ final JsonRepresentation repr = JsonRepresentation.newMap();
+ repr.mapPut("value", NullNode.getInstance()); // force a null into
+ // the map
+ return repr;
+ }
+ // overridden by actions
+ throw new UnsupportedOperationException("override mutatorArgs() to populate for many arguments");
+ }
+
+ private void addDetailsLinkIfPersistent() {
+ if (!objectAdapter.representsPersistent()) {
+ return;
+ }
+ final JsonRepresentation link = linkTo.memberBuilder(Rel.DETAILS, memberType, objectMember).build();
+ getLinks().arrayAdd(link);
+
+ final LinkFollower membersLinkFollower = getLinkFollower();
+ final LinkFollower detailsLinkFollower = membersLinkFollower.follow("links[rel=%s]", Rel.DETAILS.getName());
+ if (membersLinkFollower.matches(representation) && detailsLinkFollower.matches(link)) {
+ followDetailsLink(link);
+ }
+ return;
+ }
+
+ protected abstract void followDetailsLink(JsonRepresentation detailsLink);
+
+ protected final void putDisabledReasonIfDisabled() {
+ final String disabledReasonRep = usability().getReason();
+ representation.mapPut("disabledReason", disabledReasonRep);
+ }
+
+ protected abstract void putExtensionsIsisProprietary();
+
+ protected abstract void addLinksToFormalDomainModel();
+
+ protected abstract void addLinksIsisProprietary();
+
+ /**
+ * Convenience method.
+ */
+ public boolean isMemberVisible() {
+ return visibility().isAllowed();
+ }
+
+ protected <F extends Facet> F getMemberSpecFacet(final Class<F> facetType) {
+ final ObjectSpecification otoaSpec = objectMember.getSpecification();
+ return otoaSpec.getFacet(facetType);
+ }
+
+ protected boolean hasMemberFacet(final Class<? extends Facet> facetType) {
+ return objectMember.getFacet(facetType) != null;
+ }
+
+ protected Consent usability() {
+ return objectMember.isUsable(getAuthenticationSession(), objectAdapter, where);
+ }
+
+ protected Consent visibility() {
+ return objectMember.isVisible(getAuthenticationSession(), objectAdapter, where);
+ }
+
+}
\ No newline at end of file