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/04/27 20:31:44 UTC
[25/50] [abbrv] git commit: ISIS-233,
ISIS-361: validate non-parseable parameters, more tests for RO
ISIS-233, ISIS-361: validate non-parseable parameters, more tests for RO
* validation of invalid arguments when invoking service actions.
Project: http://git-wip-us.apache.org/repos/asf/isis/repo
Commit: http://git-wip-us.apache.org/repos/asf/isis/commit/7bc86916
Tree: http://git-wip-us.apache.org/repos/asf/isis/tree/7bc86916
Diff: http://git-wip-us.apache.org/repos/asf/isis/diff/7bc86916
Branch: refs/heads/master
Commit: 7bc8691649c5f25960d6223d277a2121af34c56d
Parents: b4dd583
Author: Dan Haywood <da...@apache.org>
Authored: Thu Mar 14 09:35:58 2013 +0000
Committer: Dan Haywood <da...@apache.org>
Committed: Sat Apr 27 19:01:20 2013 +0100
----------------------------------------------------------------------
.../applib/client/RestfulResponse.java | 4 -
.../rendering/domainobjects/JsonValueEncoder.java | 7 +-
.../RestfulObjectsApplicationExceptionMapper.java | 34 ++--
.../server/resources/DomainResourceHelper.java | 36 +---
...stfulObjectsApplicationExceptionMapperTest.java | 36 ++--
.../server/util/UrlParserUtilsTest.java | 8 +-
...mainServiceTest_req_safe_arg_bad_malformed.java | 124 +++++++++++
...ServiceTest_req_safe_optionalarg_resp_list.java | 164 +++++++++++++++
.../DomainServiceTest_req_safe_refarg_bad.java | 36 ++--
..._req_safe_simplearg_fail_mandatory_missing.java | 137 ++++++++++++
.../specloader/specimpl/ObjectActionImpl.java | 3 -
.../specimpl/ObjectActionParameterAbstract.java | 65 ++++++
.../specimpl/ObjectActionParameterParseable.java | 69 ++-----
.../specimpl/OneToOneActionParameterImpl.java | 17 +-
.../MustSatisfySpecificationOnParameterFacet.java | 3 +
.../tck/dom/actions/ActionsEntityRepository.java | 22 ++
16 files changed, 616 insertions(+), 149 deletions(-)
----------------------------------------------------------------------
http://git-wip-us.apache.org/repos/asf/isis/blob/7bc86916/component/viewer/restfulobjects/applib/src/main/java/org/apache/isis/viewer/restfulobjects/applib/client/RestfulResponse.java
----------------------------------------------------------------------
diff --git a/component/viewer/restfulobjects/applib/src/main/java/org/apache/isis/viewer/restfulobjects/applib/client/RestfulResponse.java b/component/viewer/restfulobjects/applib/src/main/java/org/apache/isis/viewer/restfulobjects/applib/client/RestfulResponse.java
index 758179c..c1869ac 100644
--- a/component/viewer/restfulobjects/applib/src/main/java/org/apache/isis/viewer/restfulobjects/applib/client/RestfulResponse.java
+++ b/component/viewer/restfulobjects/applib/src/main/java/org/apache/isis/viewer/restfulobjects/applib/client/RestfulResponse.java
@@ -30,17 +30,13 @@ import javax.ws.rs.core.Response.Status;
import javax.ws.rs.core.Response.Status.Family;
import javax.ws.rs.core.Response.StatusType;
-import org.apache.isis.core.commons.lang.StringUtils;
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;
-import org.apache.isis.viewer.restfulobjects.applib.errors.ErrorRepresentation;
import org.apache.isis.viewer.restfulobjects.applib.util.JsonMapper;
import org.apache.isis.viewer.restfulobjects.applib.util.Parser;
import org.codehaus.jackson.JsonParseException;
import org.codehaus.jackson.map.JsonMappingException;
-import com.google.common.base.Strings;
import com.google.common.collect.Maps;
public class RestfulResponse<T> {
http://git-wip-us.apache.org/repos/asf/isis/blob/7bc86916/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
index 6628dfc..1165c40 100644
--- 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
@@ -48,12 +48,15 @@ public final class JsonValueEncoder {
argRepr.mapPut("invalidReason", reason);
throw new IllegalArgumentException(reason);
}
- final JsonRepresentation argValueRepr = argRepr.getRepresentation("value");
- if(argValueRepr == null) {
+ if(!argRepr.mapHas("value")) {
String reason = "No 'value' key";
argRepr.mapPut("invalidReason", reason);
throw new IllegalArgumentException(reason);
}
+ final JsonRepresentation argValueRepr = argRepr.getRepresentation("value");
+ if(argValueRepr == null) {
+ return null;
+ }
if (!argValueRepr.isValue()) {
String reason = "Representation must be of a value";
argRepr.mapPut("invalidReason", reason);
http://git-wip-us.apache.org/repos/asf/isis/blob/7bc86916/component/viewer/restfulobjects/server/src/main/java/org/apache/isis/viewer/restfulobjects/server/RestfulObjectsApplicationExceptionMapper.java
----------------------------------------------------------------------
diff --git a/component/viewer/restfulobjects/server/src/main/java/org/apache/isis/viewer/restfulobjects/server/RestfulObjectsApplicationExceptionMapper.java b/component/viewer/restfulobjects/server/src/main/java/org/apache/isis/viewer/restfulobjects/server/RestfulObjectsApplicationExceptionMapper.java
index 524c43f..a2b7587 100644
--- a/component/viewer/restfulobjects/server/src/main/java/org/apache/isis/viewer/restfulobjects/server/RestfulObjectsApplicationExceptionMapper.java
+++ b/component/viewer/restfulobjects/server/src/main/java/org/apache/isis/viewer/restfulobjects/server/RestfulObjectsApplicationExceptionMapper.java
@@ -56,6 +56,23 @@ public class RestfulObjectsApplicationExceptionMapper implements ExceptionMapper
return builder.build();
}
+ static String bodyFor(final RestfulObjectsApplicationException ex) {
+ final JsonRepresentation jsonRepresentation = ex.getBody();
+ if (jsonRepresentation != null) {
+ return jsonRepresentation.toString();
+ }
+ Throwable cause = ex.getCause();
+ if(cause == null) {
+ return null;
+ }
+ try {
+ return JsonMapper.instance().write(ExceptionPojo.create(cause));
+ } catch (final Exception e) {
+ // fallback
+ return "{ \"exception\": \"" + ExceptionUtils.getFullStackTrace(cause) + "\" }";
+ }
+ }
+
private static class ExceptionPojo {
public static ExceptionPojo create(final Throwable ex) {
@@ -114,20 +131,5 @@ public class RestfulObjectsApplicationExceptionMapper implements ExceptionMapper
}
- static String bodyFor(final RestfulObjectsApplicationException ex) {
- final JsonRepresentation jsonRepresentation = ex.getBody();
- if (jsonRepresentation != null) {
- return jsonRepresentation.toString();
- }
- Throwable cause = ex.getCause();
- if(cause == null) {
- return null;
- }
- try {
- return JsonMapper.instance().write(ExceptionPojo.create(cause));
- } catch (final Exception e) {
- // fallback
- return "{ \"exception\": \"" + ExceptionUtils.getFullStackTrace(cause) + "\" }";
- }
- }
+
}
http://git-wip-us.apache.org/repos/asf/isis/blob/7bc86916/component/viewer/restfulobjects/server/src/main/java/org/apache/isis/viewer/restfulobjects/server/resources/DomainResourceHelper.java
----------------------------------------------------------------------
diff --git a/component/viewer/restfulobjects/server/src/main/java/org/apache/isis/viewer/restfulobjects/server/resources/DomainResourceHelper.java b/component/viewer/restfulobjects/server/src/main/java/org/apache/isis/viewer/restfulobjects/server/resources/DomainResourceHelper.java
index 67d546d..74d7cdf 100644
--- a/component/viewer/restfulobjects/server/src/main/java/org/apache/isis/viewer/restfulobjects/server/resources/DomainResourceHelper.java
+++ b/component/viewer/restfulobjects/server/src/main/java/org/apache/isis/viewer/restfulobjects/server/resources/DomainResourceHelper.java
@@ -445,7 +445,7 @@ public final class DomainResourceHelper {
final List<ObjectAdapter> argAdapters = Lists.newArrayList();
final List<ObjectActionParameter> parameters = action.getParameters();
- final StringBuilder invalidReasonBuf = new StringBuilder();
+ boolean valid = true;
for (int i = 0; i < argList.size(); i++) {
final JsonRepresentation argRepr = argList.get(i);
final ObjectSpecification paramSpec = parameters.get(i).getSpecification();
@@ -455,22 +455,15 @@ public final class DomainResourceHelper {
// validate individual arg
final ObjectActionParameter parameter = parameters.get(i);
- if (argAdapter == null) {
- // can only happen if this is an optional parameter; nothing to
- // do
- continue;
- }
- if (argAdapter.getSpecification().containsFacet(ValueFacet.class)) {
- final Object argPojo = argAdapter.getObject();
- final String reasonNotValid = parameter.isValid(objectAdapter, argPojo, null);
- if (reasonNotValid != null) {
- argRepr.mapPut("invalidReason", reasonNotValid);
- appendReasonTo(invalidReasonBuf, "Validation failed, see body for details");
- }
+ final Object argPojo = argAdapter!=null?argAdapter.getObject():null;
+ final String reasonNotValid = parameter.isValid(objectAdapter, argPojo, null);
+ if (reasonNotValid != null) {
+ argRepr.mapPut("invalidReason", reasonNotValid);
+ valid = false;
}
} catch (final IllegalArgumentException e) {
- String reason = e.getMessage();
- appendReasonTo(invalidReasonBuf, reason);
+ argAdapters.add(null);
+ valid = false;
}
}
@@ -479,23 +472,16 @@ public final class DomainResourceHelper {
final Consent consent = action.isProposedArgumentSetValid(objectAdapter, argArray);
if (consent.isVetoed()) {
arguments.mapPut("x-ro-invalidReason", consent.getReason());
- appendReasonTo(invalidReasonBuf, "Validation failed, see body for details");
+ valid = false;
}
- if(invalidReasonBuf.length()>0) {
- throw RestfulObjectsApplicationException.createWithBody(HttpStatusCode.VALIDATION_FAILED, arguments, invalidReasonBuf.toString());
+ if(!valid) {
+ throw RestfulObjectsApplicationException.createWithBody(HttpStatusCode.VALIDATION_FAILED, arguments, "Validation failed, see body for details");
}
return argAdapters;
}
- private void appendReasonTo(final StringBuilder buf, String reason) {
- if(buf.length()>0) {
- buf.append("; ");
- }
- buf.append(reason);
- }
-
private static List<JsonRepresentation> argListFor(final ObjectAction action, final JsonRepresentation arguments) {
final List<JsonRepresentation> argList = Lists.newArrayList();
http://git-wip-us.apache.org/repos/asf/isis/blob/7bc86916/component/viewer/restfulobjects/server/src/test/java/org/apache/isis/viewer/restfulobjects/server/RestfulObjectsApplicationExceptionMapperTest.java
----------------------------------------------------------------------
diff --git a/component/viewer/restfulobjects/server/src/test/java/org/apache/isis/viewer/restfulobjects/server/RestfulObjectsApplicationExceptionMapperTest.java b/component/viewer/restfulobjects/server/src/test/java/org/apache/isis/viewer/restfulobjects/server/RestfulObjectsApplicationExceptionMapperTest.java
index 6aa9834..3f68110 100644
--- a/component/viewer/restfulobjects/server/src/test/java/org/apache/isis/viewer/restfulobjects/server/RestfulObjectsApplicationExceptionMapperTest.java
+++ b/component/viewer/restfulobjects/server/src/test/java/org/apache/isis/viewer/restfulobjects/server/RestfulObjectsApplicationExceptionMapperTest.java
@@ -57,14 +57,7 @@ public class RestfulObjectsApplicationExceptionMapperTest {
// and then
final String entity = (String) response.getEntity();
- assertThat(entity, is(not(nullValue())));
- final JsonRepresentation jsonRepr = JsonMapper.instance().read(entity, JsonRepresentation.class);
-
- // then
- assertThat(jsonRepr.getString("message"), is(nullValue()));
- assertThat(jsonRepr.getArray("stackTrace"), is(not(nullValue())));
- assertThat(jsonRepr.getArray("stackTrace").size(), is(greaterThan(0)));
- assertThat(jsonRepr.getRepresentation("causedBy"), is(nullValue()));
+ assertThat(entity, is(nullValue()));
}
@Test
@@ -81,18 +74,34 @@ public class RestfulObjectsApplicationExceptionMapperTest {
// and then
final String entity = (String) response.getEntity();
+ assertThat(entity, is(nullValue()));
+ }
+
+ @Test
+ public void entity_forException() throws Exception {
+ // given
+ final Exception exception = new Exception("barfoo");
+ final RestfulObjectsApplicationException ex = RestfulObjectsApplicationException.createWithCauseAndMessage(HttpStatusCode.BAD_REQUEST, exception, "foobar");
+
+ // when
+ final Response response = exceptionMapper.toResponse(ex);
+ final String entity = (String) response.getEntity();
assertThat(entity, is(not(nullValue())));
final JsonRepresentation jsonRepr = JsonMapper.instance().read(entity, JsonRepresentation.class);
// then
- assertThat(jsonRepr.getString("message"), is(ex.getMessage()));
+ assertThat((String) response.getMetadata().get("Warning").get(0), is("199 RestfulObjects foobar"));
+ assertThat(jsonRepr.getString("message"), is("barfoo"));
+ final JsonRepresentation causedByRepr = jsonRepr.getRepresentation("causedBy");
+ assertThat(causedByRepr, is(nullValue()));
}
@Test
- public void entity_withCause() throws Exception {
+ public void entity_forExceptionWithCause() throws Exception {
// given
- final Exception cause = new Exception("barfoo");
- final RestfulObjectsApplicationException ex = RestfulObjectsApplicationException.createWithCauseAndMessage(HttpStatusCode.BAD_REQUEST, cause, "foobar");
+ final Exception cause = new Exception("bozfoz");
+ final Exception exception = new Exception("barfoo", cause);
+ final RestfulObjectsApplicationException ex = RestfulObjectsApplicationException.createWithCauseAndMessage(HttpStatusCode.BAD_REQUEST, exception, "foobar");
// when
final Response response = exceptionMapper.toResponse(ex);
@@ -101,7 +110,8 @@ public class RestfulObjectsApplicationExceptionMapperTest {
final JsonRepresentation jsonRepr = JsonMapper.instance().read(entity, JsonRepresentation.class);
// then
- assertThat(jsonRepr.getString("message"), is(ex.getMessage()));
+ assertThat((String) response.getMetadata().get("Warning").get(0), is("199 RestfulObjects foobar"));
+ assertThat(jsonRepr.getString("message"), is("barfoo"));
final JsonRepresentation causedByRepr = jsonRepr.getRepresentation("causedBy");
assertThat(causedByRepr, is(not(nullValue())));
assertThat(causedByRepr.getString("message"), is(cause.getMessage()));
http://git-wip-us.apache.org/repos/asf/isis/blob/7bc86916/component/viewer/restfulobjects/server/src/test/java/org/apache/isis/viewer/restfulobjects/server/util/UrlParserUtilsTest.java
----------------------------------------------------------------------
diff --git a/component/viewer/restfulobjects/server/src/test/java/org/apache/isis/viewer/restfulobjects/server/util/UrlParserUtilsTest.java b/component/viewer/restfulobjects/server/src/test/java/org/apache/isis/viewer/restfulobjects/server/util/UrlParserUtilsTest.java
index f564834..47c5686 100644
--- a/component/viewer/restfulobjects/server/src/test/java/org/apache/isis/viewer/restfulobjects/server/util/UrlParserUtilsTest.java
+++ b/component/viewer/restfulobjects/server/src/test/java/org/apache/isis/viewer/restfulobjects/server/util/UrlParserUtilsTest.java
@@ -28,7 +28,7 @@ public class UrlParserUtilsTest {
@Test
public void oidFromLink() throws Exception {
final JsonRepresentation link = JsonRepresentation.newMap();
- link.mapPut("href", "http://localhost/objects/OID:1");
+ link.mapPut("href", "http://localhost/objects/OID/1");
final String oidFromHref = UrlParserUtils.encodedOidFromLink(link);
assertEquals("OID:1", oidFromHref);
}
@@ -36,7 +36,7 @@ public class UrlParserUtilsTest {
@Test
public void domainTypeFromLink() throws Exception {
final JsonRepresentation link = JsonRepresentation.newMap();
- link.mapPut("href", "http://localhost/domainTypes/com.mycompany.myapp.Customer");
+ link.mapPut("href", "http://localhost/domain-types/com.mycompany.myapp.Customer");
final String oidFromHref = UrlParserUtils.domainTypeFrom(link);
assertEquals("com.mycompany.myapp.Customer", oidFromHref);
}
@@ -44,7 +44,7 @@ public class UrlParserUtilsTest {
@Test
public void domainTypeFromLinkTrailingSlash() throws Exception {
final JsonRepresentation link = JsonRepresentation.newMap();
- link.mapPut("href", "http://localhost/domainTypes/com.mycompany.myapp.Customer/");
+ link.mapPut("href", "http://localhost/domain-types/com.mycompany.myapp.Customer/");
final String oidFromHref = UrlParserUtils.domainTypeFrom(link);
assertEquals("com.mycompany.myapp.Customer", oidFromHref);
}
@@ -52,7 +52,7 @@ public class UrlParserUtilsTest {
@Test
public void domainTypeFromLinkFollowingStuff() throws Exception {
final JsonRepresentation link = JsonRepresentation.newMap();
- link.mapPut("href", "http://localhost/domainTypes/com.mycompany.myapp.Customer/otherStuffHere");
+ link.mapPut("href", "http://localhost/domain-types/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/7bc86916/component/viewer/restfulobjects/tck/src/test/java/org/apache/isis/viewer/restfulobjects/tck/domainservice/serviceId/action/invoke/DomainServiceTest_req_safe_arg_bad_malformed.java
----------------------------------------------------------------------
diff --git a/component/viewer/restfulobjects/tck/src/test/java/org/apache/isis/viewer/restfulobjects/tck/domainservice/serviceId/action/invoke/DomainServiceTest_req_safe_arg_bad_malformed.java b/component/viewer/restfulobjects/tck/src/test/java/org/apache/isis/viewer/restfulobjects/tck/domainservice/serviceId/action/invoke/DomainServiceTest_req_safe_arg_bad_malformed.java
new file mode 100644
index 0000000..6196072
--- /dev/null
+++ b/component/viewer/restfulobjects/tck/src/test/java/org/apache/isis/viewer/restfulobjects/tck/domainservice/serviceId/action/invoke/DomainServiceTest_req_safe_arg_bad_malformed.java
@@ -0,0 +1,124 @@
+/*
+ * 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.tck.domainservice.serviceId.action.invoke;
+
+import static org.apache.isis.viewer.restfulobjects.tck.RestfulMatchers.hasProfile;
+import static org.apache.isis.viewer.restfulobjects.tck.RestfulMatchers.isLink;
+import static org.hamcrest.CoreMatchers.*;
+import static org.hamcrest.CoreMatchers.is;
+import static org.junit.Assert.assertThat;
+
+import java.io.IOException;
+
+import javax.ws.rs.core.MediaType;
+import javax.ws.rs.core.Response;
+
+import org.apache.isis.viewer.restfulobjects.applib.JsonRepresentation;
+import org.apache.isis.viewer.restfulobjects.applib.LinkRepresentation;
+import org.apache.isis.viewer.restfulobjects.applib.Rel;
+import org.apache.isis.viewer.restfulobjects.applib.RestfulHttpMethod;
+import org.apache.isis.viewer.restfulobjects.applib.RestfulMediaType;
+import org.apache.isis.viewer.restfulobjects.applib.client.RestfulClient;
+import org.apache.isis.viewer.restfulobjects.applib.client.RestfulResponse;
+import org.apache.isis.viewer.restfulobjects.applib.client.RestfulResponse.Header;
+import org.apache.isis.viewer.restfulobjects.applib.domainobjects.ActionResultRepresentation;
+import org.apache.isis.viewer.restfulobjects.applib.domainobjects.ActionResultRepresentation.ResultType;
+import org.apache.isis.viewer.restfulobjects.applib.domainobjects.DomainServiceResource;
+import org.apache.isis.viewer.restfulobjects.applib.domainobjects.ListRepresentation;
+import org.apache.isis.viewer.restfulobjects.applib.domainobjects.ObjectActionRepresentation;
+import org.apache.isis.viewer.restfulobjects.applib.errors.ErrorRepresentation;
+import org.apache.isis.viewer.restfulobjects.applib.util.UrlEncodingUtils;
+import org.apache.isis.viewer.restfulobjects.tck.IsisWebServerRule;
+import org.apache.isis.viewer.restfulobjects.tck.RestfulMatchers;
+import org.apache.isis.viewer.restfulobjects.tck.Util;
+import org.codehaus.jackson.JsonParseException;
+import org.codehaus.jackson.map.JsonMappingException;
+import org.hamcrest.Matchers;
+import org.junit.Before;
+import org.junit.Ignore;
+import org.junit.Rule;
+import org.junit.Test;
+
+public class DomainServiceTest_req_safe_arg_bad_malformed {
+
+ @Rule
+ public IsisWebServerRule webServerRule = new IsisWebServerRule();
+
+ private RestfulClient client;
+
+ private DomainServiceResource serviceResource;
+
+ @Before
+ public void setUp() throws Exception {
+ client = webServerRule.getClient();
+ serviceResource = client.getDomainServiceResource();
+ }
+
+
+ @Test
+ public void usingClientFollow_whenImplicitlySetToNull() throws Exception {
+
+ // given
+ final JsonRepresentation givenAction = Util.givenAction(client, "ActionsEntities", "subListWithOptionalRange");
+ final ObjectActionRepresentation actionRepr = givenAction.as(ObjectActionRepresentation.class);
+
+ final LinkRepresentation invokeLink = actionRepr.getInvoke();
+
+ assertThat(invokeLink, isLink(client)
+ .rel(Rel.INVOKE)
+ .httpMethod(RestfulHttpMethod.GET)
+ .href(Matchers.endsWith(":39393/services/ActionsEntities/actions/subListWithOptionalRange/invoke"))
+ .build());
+
+ // when
+ JsonRepresentation args = JsonRepresentation.newMap();
+ args.mapPut("from", JsonRepresentation.newMap());
+ args.mapPut("to.value", (Integer)null);
+
+ final RestfulResponse<ActionResultRepresentation> restfulResponse = client.followT(invokeLink, args);
+
+ // then
+ then(restfulResponse);
+ }
+
+
+ @Test
+ public void usingResourceProxy_whenExplicitSetToNull() throws Exception {
+
+ // given, when
+ JsonRepresentation args = JsonRepresentation.newMap();
+ args.mapPut("from", JsonRepresentation.newMap());
+ args.mapPut("to.value", (Integer)null);
+
+ Response response = serviceResource.invokeActionQueryOnly("ActionsEntities", "subListWithOptionalRange", UrlEncodingUtils.urlEncode(args));
+ RestfulResponse<ActionResultRepresentation> restfulResponse = RestfulResponse.ofT(response);
+
+ // then
+ then(restfulResponse);
+ }
+
+
+ private static void then(RestfulResponse<ActionResultRepresentation> restfulResponse) throws JsonParseException, JsonMappingException, IOException {
+ assertThat(restfulResponse.getHeader(Header.CONTENT_TYPE), hasProfile(MediaType.APPLICATION_JSON));
+ final JsonRepresentation errorRepr = restfulResponse.wraps(JsonRepresentation.class).getEntity();
+
+ assertThat(errorRepr.getString("from.invalidReason"), is("No 'value' key"));
+ }
+
+}
http://git-wip-us.apache.org/repos/asf/isis/blob/7bc86916/component/viewer/restfulobjects/tck/src/test/java/org/apache/isis/viewer/restfulobjects/tck/domainservice/serviceId/action/invoke/DomainServiceTest_req_safe_optionalarg_resp_list.java
----------------------------------------------------------------------
diff --git a/component/viewer/restfulobjects/tck/src/test/java/org/apache/isis/viewer/restfulobjects/tck/domainservice/serviceId/action/invoke/DomainServiceTest_req_safe_optionalarg_resp_list.java b/component/viewer/restfulobjects/tck/src/test/java/org/apache/isis/viewer/restfulobjects/tck/domainservice/serviceId/action/invoke/DomainServiceTest_req_safe_optionalarg_resp_list.java
new file mode 100644
index 0000000..56195dc
--- /dev/null
+++ b/component/viewer/restfulobjects/tck/src/test/java/org/apache/isis/viewer/restfulobjects/tck/domainservice/serviceId/action/invoke/DomainServiceTest_req_safe_optionalarg_resp_list.java
@@ -0,0 +1,164 @@
+/*
+ * 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.tck.domainservice.serviceId.action.invoke;
+
+import static org.apache.isis.viewer.restfulobjects.tck.RestfulMatchers.hasProfile;
+import static org.apache.isis.viewer.restfulobjects.tck.RestfulMatchers.isLink;
+import static org.hamcrest.CoreMatchers.is;
+import static org.junit.Assert.assertThat;
+
+import java.io.IOException;
+
+import javax.ws.rs.core.Response;
+
+import org.apache.isis.viewer.restfulobjects.applib.JsonRepresentation;
+import org.apache.isis.viewer.restfulobjects.applib.LinkRepresentation;
+import org.apache.isis.viewer.restfulobjects.applib.Rel;
+import org.apache.isis.viewer.restfulobjects.applib.RestfulHttpMethod;
+import org.apache.isis.viewer.restfulobjects.applib.RestfulMediaType;
+import org.apache.isis.viewer.restfulobjects.applib.client.RestfulClient;
+import org.apache.isis.viewer.restfulobjects.applib.client.RestfulResponse;
+import org.apache.isis.viewer.restfulobjects.applib.client.RestfulResponse.Header;
+import org.apache.isis.viewer.restfulobjects.applib.domainobjects.ActionResultRepresentation;
+import org.apache.isis.viewer.restfulobjects.applib.domainobjects.ActionResultRepresentation.ResultType;
+import org.apache.isis.viewer.restfulobjects.applib.domainobjects.DomainServiceResource;
+import org.apache.isis.viewer.restfulobjects.applib.domainobjects.ListRepresentation;
+import org.apache.isis.viewer.restfulobjects.applib.domainobjects.ObjectActionRepresentation;
+import org.apache.isis.viewer.restfulobjects.applib.util.UrlEncodingUtils;
+import org.apache.isis.viewer.restfulobjects.tck.IsisWebServerRule;
+import org.apache.isis.viewer.restfulobjects.tck.RestfulMatchers;
+import org.apache.isis.viewer.restfulobjects.tck.Util;
+import org.codehaus.jackson.JsonParseException;
+import org.codehaus.jackson.map.JsonMappingException;
+import org.hamcrest.Matchers;
+import org.junit.Before;
+import org.junit.Ignore;
+import org.junit.Rule;
+import org.junit.Test;
+
+public class DomainServiceTest_req_safe_optionalarg_resp_list {
+
+ @Rule
+ public IsisWebServerRule webServerRule = new IsisWebServerRule();
+
+ private RestfulClient client;
+
+ private DomainServiceResource serviceResource;
+
+ @Before
+ public void setUp() throws Exception {
+ client = webServerRule.getClient();
+
+ serviceResource = client.getDomainServiceResource();
+ }
+
+ @Test
+ public void usingClientFollow_whenExplicitlySetToNull() throws Exception {
+
+ // given
+ final JsonRepresentation givenAction = Util.givenAction(client, "ActionsEntities", "subListWithOptionalRange");
+ final ObjectActionRepresentation actionRepr = givenAction.as(ObjectActionRepresentation.class);
+
+ final LinkRepresentation invokeLink = actionRepr.getInvoke();
+
+ assertThat(invokeLink, isLink(client)
+ .rel(Rel.INVOKE)
+ .httpMethod(RestfulHttpMethod.GET)
+ .href(Matchers.endsWith(":39393/services/ActionsEntities/actions/subListWithOptionalRange/invoke"))
+ .build());
+
+ JsonRepresentation args =invokeLink.getArguments();
+ assertThat(args.size(), is(2));
+ assertThat(args, RestfulMatchers.mapHas("from"));
+ assertThat(args, RestfulMatchers.mapHas("to"));
+
+ // when
+ args.mapPut("from.value", (Integer)null);
+ args.mapPut("to.value", (Integer)null);
+
+ final RestfulResponse<ActionResultRepresentation> restfulResponse = client.followT(invokeLink, args);
+
+ then(restfulResponse);
+ }
+
+
+ @Test
+ public void usingResourceProxy_whenExplicitlySetToNull() throws Exception {
+
+ // given, when
+ JsonRepresentation args = JsonRepresentation.newMap();
+ args.mapPut("from.value", (Integer)null);
+ args.mapPut("to.value", (Integer)null);
+ Response response = serviceResource.invokeActionQueryOnly("ActionsEntities", "subListWithOptionalRange", UrlEncodingUtils.urlEncode(args));
+ RestfulResponse<ActionResultRepresentation> restfulResponse = RestfulResponse.ofT(response);
+
+ // then
+ then(restfulResponse);
+ }
+
+
+ @Test
+ public void usingClientFollow_whenImplicitlySetToNull() throws Exception {
+
+ // given
+ final JsonRepresentation givenAction = Util.givenAction(client, "ActionsEntities", "subListWithOptionalRange");
+ final ObjectActionRepresentation actionRepr = givenAction.as(ObjectActionRepresentation.class);
+
+ final LinkRepresentation invokeLink = actionRepr.getInvoke();
+
+ assertThat(invokeLink, isLink(client)
+ .rel(Rel.INVOKE)
+ .httpMethod(RestfulHttpMethod.GET)
+ .href(Matchers.endsWith(":39393/services/ActionsEntities/actions/subListWithOptionalRange/invoke"))
+ .build());
+
+ // when
+ JsonRepresentation args = JsonRepresentation.newMap();
+
+ final RestfulResponse<ActionResultRepresentation> restfulResponse = client.followT(invokeLink, args);
+
+ then(restfulResponse);
+ }
+
+
+ @Test
+ public void usingResourceProxy_whenImplicitlySetToNull() throws Exception {
+
+ // given, when
+ JsonRepresentation args = JsonRepresentation.newMap();
+ Response response = serviceResource.invokeActionQueryOnly("ActionsEntities", "subListWithOptionalRange", UrlEncodingUtils.urlEncode(args));
+ RestfulResponse<ActionResultRepresentation> restfulResponse = RestfulResponse.ofT(response);
+
+ // then
+ then(restfulResponse);
+ }
+
+
+ private static void then(RestfulResponse<ActionResultRepresentation> restfulResponse) throws JsonParseException, JsonMappingException, IOException {
+ assertThat(restfulResponse.getHeader(Header.CONTENT_TYPE), hasProfile(RestfulMediaType.APPLICATION_JSON_ACTION_RESULT));
+ final ActionResultRepresentation actionResultRepr = restfulResponse.getEntity();
+
+ assertThat(actionResultRepr.getResultType(), is(ResultType.LIST));
+
+ final ListRepresentation listRepr = actionResultRepr.getResult().as(ListRepresentation.class);
+
+ assertThat(listRepr.getValue().size(), is(5));
+ }
+
+}
http://git-wip-us.apache.org/repos/asf/isis/blob/7bc86916/component/viewer/restfulobjects/tck/src/test/java/org/apache/isis/viewer/restfulobjects/tck/domainservice/serviceId/action/invoke/DomainServiceTest_req_safe_refarg_bad.java
----------------------------------------------------------------------
diff --git a/component/viewer/restfulobjects/tck/src/test/java/org/apache/isis/viewer/restfulobjects/tck/domainservice/serviceId/action/invoke/DomainServiceTest_req_safe_refarg_bad.java b/component/viewer/restfulobjects/tck/src/test/java/org/apache/isis/viewer/restfulobjects/tck/domainservice/serviceId/action/invoke/DomainServiceTest_req_safe_refarg_bad.java
index d31ca0e..c93b407 100644
--- a/component/viewer/restfulobjects/tck/src/test/java/org/apache/isis/viewer/restfulobjects/tck/domainservice/serviceId/action/invoke/DomainServiceTest_req_safe_refarg_bad.java
+++ b/component/viewer/restfulobjects/tck/src/test/java/org/apache/isis/viewer/restfulobjects/tck/domainservice/serviceId/action/invoke/DomainServiceTest_req_safe_refarg_bad.java
@@ -20,6 +20,7 @@ package org.apache.isis.viewer.restfulobjects.tck.domainservice.serviceId.action
import static org.apache.isis.viewer.restfulobjects.tck.RestfulMatchers.hasProfile;
import static org.apache.isis.viewer.restfulobjects.tck.RestfulMatchers.hasStatus;
+import static org.hamcrest.CoreMatchers.*;
import static org.hamcrest.CoreMatchers.is;
import static org.junit.Assert.assertThat;
@@ -82,26 +83,10 @@ public class DomainServiceTest_req_safe_refarg_bad {
RestfulResponse<ActionResultRepresentation> restfulResponse = client.followT(invokeLink, args);
+ // then
then(args, restfulResponse);
}
- private static void then(final JsonRepresentation args, RestfulResponse<ActionResultRepresentation> restfulResponse) throws JsonParseException, JsonMappingException, IOException {
- // then the response is an error
- assertThat(restfulResponse, hasStatus(HttpStatusCode.VALIDATION_FAILED));
-
- assertThat(restfulResponse.getHeader(Header.WARNING), is("'href' does not reference a known entity"));
-
- // hmmm... what is the media type, though? the spec doesn't say. testing for a generic one.
- assertThat(restfulResponse.getHeader(Header.CONTENT_TYPE), hasProfile(MediaType.APPLICATION_JSON));
-
- RestfulResponse<JsonRepresentation> restfulResponseOfError = restfulResponse.wraps(JsonRepresentation.class);
- JsonRepresentation repr = restfulResponseOfError.getEntity();
-
- assertThat(repr.getString("searchFor.value.href"), is(args.getString("searchFor.value.href")));
- assertThat(repr.getString("searchFor.invalidReason"), is("'href' does not reference a known entity"));
- }
-
-
@Test
public void usingResourceProxy() throws Exception {
@@ -117,8 +102,25 @@ public class DomainServiceTest_req_safe_refarg_bad {
Response response = serviceResource.invokeActionQueryOnly("ActionsEntities", "contains", UrlEncodingUtils.urlEncode(args));
RestfulResponse<ActionResultRepresentation> restfulResponse = RestfulResponse.ofT(response);
+ // then
then(args, restfulResponse);
}
+ private static void then(final JsonRepresentation args, RestfulResponse<ActionResultRepresentation> restfulResponse) throws JsonParseException, JsonMappingException, IOException {
+ // then the response is an error
+ assertThat(restfulResponse, hasStatus(HttpStatusCode.VALIDATION_FAILED));
+ assertThat(restfulResponse.getHeader(Header.WARNING), is("Validation failed, see body for details"));
+
+ // hmmm... what is the media type, though? the spec doesn't say. testing for a generic one.
+ assertThat(restfulResponse.getHeader(Header.CONTENT_TYPE), hasProfile(MediaType.APPLICATION_JSON));
+
+ RestfulResponse<JsonRepresentation> restfulResponseOfError = restfulResponse.wraps(JsonRepresentation.class);
+ JsonRepresentation repr = restfulResponseOfError.getEntity();
+
+ assertThat(repr.getString("searchFor.value.href"), is(args.getString("searchFor.value.href")));
+ assertThat(repr.getString("searchFor.invalidReason"), is("'href' does not reference a known entity"));
+ }
+
+
}
http://git-wip-us.apache.org/repos/asf/isis/blob/7bc86916/component/viewer/restfulobjects/tck/src/test/java/org/apache/isis/viewer/restfulobjects/tck/domainservice/serviceId/action/invoke/DomainServiceTest_req_safe_simplearg_fail_mandatory_missing.java
----------------------------------------------------------------------
diff --git a/component/viewer/restfulobjects/tck/src/test/java/org/apache/isis/viewer/restfulobjects/tck/domainservice/serviceId/action/invoke/DomainServiceTest_req_safe_simplearg_fail_mandatory_missing.java b/component/viewer/restfulobjects/tck/src/test/java/org/apache/isis/viewer/restfulobjects/tck/domainservice/serviceId/action/invoke/DomainServiceTest_req_safe_simplearg_fail_mandatory_missing.java
new file mode 100644
index 0000000..2116f54
--- /dev/null
+++ b/component/viewer/restfulobjects/tck/src/test/java/org/apache/isis/viewer/restfulobjects/tck/domainservice/serviceId/action/invoke/DomainServiceTest_req_safe_simplearg_fail_mandatory_missing.java
@@ -0,0 +1,137 @@
+/*
+ * 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.tck.domainservice.serviceId.action.invoke;
+
+import static org.apache.isis.viewer.restfulobjects.tck.RestfulMatchers.hasProfile;
+import static org.apache.isis.viewer.restfulobjects.tck.RestfulMatchers.hasStatus;
+import static org.apache.isis.viewer.restfulobjects.tck.RestfulMatchers.isLink;
+import static org.hamcrest.CoreMatchers.*;
+import static org.hamcrest.CoreMatchers.is;
+import static org.junit.Assert.assertThat;
+
+import java.io.IOException;
+
+import javax.ws.rs.core.MediaType;
+import javax.ws.rs.core.Response;
+
+import org.apache.isis.viewer.restfulobjects.applib.JsonRepresentation;
+import org.apache.isis.viewer.restfulobjects.applib.LinkRepresentation;
+import org.apache.isis.viewer.restfulobjects.applib.Rel;
+import org.apache.isis.viewer.restfulobjects.applib.RestfulHttpMethod;
+import org.apache.isis.viewer.restfulobjects.applib.RestfulMediaType;
+import org.apache.isis.viewer.restfulobjects.applib.client.RestfulClient;
+import org.apache.isis.viewer.restfulobjects.applib.client.RestfulResponse;
+import org.apache.isis.viewer.restfulobjects.applib.client.RestfulResponse.Header;
+import org.apache.isis.viewer.restfulobjects.applib.client.RestfulResponse.HttpStatusCode;
+import org.apache.isis.viewer.restfulobjects.applib.domainobjects.ActionResultRepresentation;
+import org.apache.isis.viewer.restfulobjects.applib.domainobjects.ActionResultRepresentation.ResultType;
+import org.apache.isis.viewer.restfulobjects.applib.domainobjects.DomainServiceResource;
+import org.apache.isis.viewer.restfulobjects.applib.domainobjects.ListRepresentation;
+import org.apache.isis.viewer.restfulobjects.applib.domainobjects.ObjectActionRepresentation;
+import org.apache.isis.viewer.restfulobjects.applib.util.UrlEncodingUtils;
+import org.apache.isis.viewer.restfulobjects.tck.IsisWebServerRule;
+import org.apache.isis.viewer.restfulobjects.tck.RestfulMatchers;
+import org.apache.isis.viewer.restfulobjects.tck.Util;
+import org.codehaus.jackson.JsonParseException;
+import org.codehaus.jackson.map.JsonMappingException;
+import org.hamcrest.Matchers;
+import org.junit.Before;
+import org.junit.Ignore;
+import org.junit.Rule;
+import org.junit.Test;
+
+public class DomainServiceTest_req_safe_simplearg_fail_mandatory_missing {
+
+ @Rule
+ public IsisWebServerRule webServerRule = new IsisWebServerRule();
+
+ private RestfulClient client;
+
+ private DomainServiceResource serviceResource;
+
+ @Before
+ public void setUp() throws Exception {
+ client = webServerRule.getClient();
+
+ serviceResource = client.getDomainServiceResource();
+ }
+
+ @Test
+ public void usingClientFollow() throws Exception {
+
+ // given
+ final JsonRepresentation givenAction = Util.givenAction(client, "ActionsEntities", "subList");
+ final ObjectActionRepresentation actionRepr = givenAction.as(ObjectActionRepresentation.class);
+
+ final LinkRepresentation invokeLink = actionRepr.getInvoke();
+
+ assertThat(invokeLink, isLink(client)
+ .rel(Rel.INVOKE)
+ .httpMethod(RestfulHttpMethod.GET)
+ .href(Matchers.endsWith(":39393/services/ActionsEntities/actions/subList/invoke"))
+ .build());
+
+ JsonRepresentation args =invokeLink.getArguments();
+ assertThat(args.size(), is(2));
+ assertThat(args, RestfulMatchers.mapHas("from"));
+ assertThat(args, RestfulMatchers.mapHas("to"));
+
+ // when
+ args.mapPut("from.value", (Integer)null);
+ args.mapPut("to.value", 0);
+
+ final RestfulResponse<ActionResultRepresentation> restfulResponse = client.followT(invokeLink, args);
+
+ // then
+ thenResponseIsErrorWithInvalidReason(restfulResponse);
+ }
+
+ @Ignore("to write")
+ @Test
+ public void usingResourceProxy() throws Exception {
+
+ // given, when
+ JsonRepresentation args = JsonRepresentation.newMap();
+ args.mapPut("from.value", 1);
+ args.mapPut("to.value", 0);
+ Response response = serviceResource.invokeActionQueryOnly("ActionsEntities", "subList", UrlEncodingUtils.urlEncode(args));
+ RestfulResponse<ActionResultRepresentation> restfulResponse = RestfulResponse.ofT(response);
+
+ // then
+ thenResponseIsErrorWithInvalidReason(restfulResponse);
+ }
+
+ private static void thenResponseIsErrorWithInvalidReason(final RestfulResponse<ActionResultRepresentation> restfulResponse) throws JsonParseException, JsonMappingException, IOException {
+ assertThat(restfulResponse, hasStatus(HttpStatusCode.VALIDATION_FAILED));
+ assertThat(restfulResponse.getHeader(Header.WARNING), is("Validation failed, see body for details"));
+
+ // hmmm... what is the media type, though? the spec doesn't say. testing for a generic one.
+ assertThat(restfulResponse.getHeader(Header.CONTENT_TYPE), hasProfile(MediaType.APPLICATION_JSON));
+
+ RestfulResponse<JsonRepresentation> restfulResponseOfError = restfulResponse.wraps(JsonRepresentation.class);
+ JsonRepresentation repr = restfulResponseOfError.getEntity();
+
+ assertThat(repr.getString("from.invalidReason"), is("Mandatory"));
+ // TODO: really ought to be null, but ObjectActionImpl.isProposedArgumentSetValidResultSet also checks that each argument is valid
+ assertThat(repr.getString("x-ro-invalidReason"), is("Mandatory"));
+ }
+
+
+
+}
http://git-wip-us.apache.org/repos/asf/isis/blob/7bc86916/core/metamodel/src/main/java/org/apache/isis/core/metamodel/specloader/specimpl/ObjectActionImpl.java
----------------------------------------------------------------------
diff --git a/core/metamodel/src/main/java/org/apache/isis/core/metamodel/specloader/specimpl/ObjectActionImpl.java b/core/metamodel/src/main/java/org/apache/isis/core/metamodel/specloader/specimpl/ObjectActionImpl.java
index cc5e5b7..4bb5fd1 100644
--- a/core/metamodel/src/main/java/org/apache/isis/core/metamodel/specloader/specimpl/ObjectActionImpl.java
+++ b/core/metamodel/src/main/java/org/apache/isis/core/metamodel/specloader/specimpl/ObjectActionImpl.java
@@ -379,9 +379,6 @@ public class ObjectActionImpl extends ObjectMemberAbstract implements ObjectActi
final InteractionResultSet resultSet = new InteractionResultSet();
final List<ObjectActionParameter> actionParameters = getParameters();
if (proposedArguments != null) {
- // TODO: doesn't seem to be used...
- // ObjectAdapter[] params = realParameters(object,
- // proposedArguments);
for (int i = 0; i < proposedArguments.length; i++) {
final ValidityContext<?> ic = actionParameters.get(i).createProposedArgumentInteractionContext(getAuthenticationSession(), invocationMethod, object, proposedArguments, i);
InteractionUtils.isValidResultSet(getParameter(i), ic, resultSet);
http://git-wip-us.apache.org/repos/asf/isis/blob/7bc86916/core/metamodel/src/main/java/org/apache/isis/core/metamodel/specloader/specimpl/ObjectActionParameterAbstract.java
----------------------------------------------------------------------
diff --git a/core/metamodel/src/main/java/org/apache/isis/core/metamodel/specloader/specimpl/ObjectActionParameterAbstract.java b/core/metamodel/src/main/java/org/apache/isis/core/metamodel/specloader/specimpl/ObjectActionParameterAbstract.java
index ea86b46..75951be 100644
--- a/core/metamodel/src/main/java/org/apache/isis/core/metamodel/specloader/specimpl/ObjectActionParameterAbstract.java
+++ b/core/metamodel/src/main/java/org/apache/isis/core/metamodel/specloader/specimpl/ObjectActionParameterAbstract.java
@@ -25,6 +25,7 @@ import com.google.common.collect.Lists;
import org.apache.isis.applib.Identifier;
import org.apache.isis.applib.filter.Filter;
+import org.apache.isis.applib.profiles.Localization;
import org.apache.isis.applib.query.Query;
import org.apache.isis.applib.query.QueryFindAllInstances;
import org.apache.isis.core.commons.authentication.AuthenticationSession;
@@ -36,6 +37,7 @@ import org.apache.isis.core.metamodel.adapter.mgr.AdapterManager;
import org.apache.isis.core.metamodel.consent.Allow;
import org.apache.isis.core.metamodel.consent.Consent;
import org.apache.isis.core.metamodel.consent.InteractionInvocationMethod;
+import org.apache.isis.core.metamodel.consent.InteractionResultSet;
import org.apache.isis.core.metamodel.deployment.DeploymentCategory;
import org.apache.isis.core.metamodel.facetapi.Facet;
import org.apache.isis.core.metamodel.facetapi.MultiTypedFacet;
@@ -44,9 +46,12 @@ import org.apache.isis.core.metamodel.facets.describedas.DescribedAsFacet;
import org.apache.isis.core.metamodel.facets.mandatory.MandatoryFacet;
import org.apache.isis.core.metamodel.facets.named.NamedFacet;
import org.apache.isis.core.metamodel.facets.object.bounded.BoundedFacetUtils;
+import org.apache.isis.core.metamodel.facets.object.parseable.ParseableFacet;
import org.apache.isis.core.metamodel.facets.param.choices.ActionParameterChoicesFacet;
import org.apache.isis.core.metamodel.facets.param.defaults.ActionParameterDefaultsFacet;
import org.apache.isis.core.metamodel.interactions.ActionArgumentContext;
+import org.apache.isis.core.metamodel.interactions.InteractionUtils;
+import org.apache.isis.core.metamodel.interactions.ValidityContext;
import org.apache.isis.core.metamodel.spec.DomainModelException;
import org.apache.isis.core.metamodel.spec.ObjectSpecification;
import org.apache.isis.core.metamodel.spec.SpecificationLoader;
@@ -307,6 +312,66 @@ public abstract class ObjectActionParameterAbstract implements ObjectActionParam
return getAuthenticationSessionProvider().getAuthenticationSession();
}
+
+
+ // /////////////////////////////////////////////////////////////
+ // Validation
+ // /////////////////////////////////////////////////////////////
+
+ @Override
+ public String isValid(final ObjectAdapter adapter, final Object proposedValue, final Localization localization) {
+
+ ObjectAdapter proposedValueAdapter = null;
+ ObjectSpecification proposedValueSpec;
+ if(proposedValue != null) {
+ proposedValueAdapter = getAdapterMap().adapterFor(proposedValue);
+ proposedValueSpec = proposedValueAdapter.getSpecification();
+ if(!proposedValueSpec.isOfType(proposedValueSpec)) {
+ proposedValueAdapter = doCoerceProposedValue(adapter, proposedValue, localization);
+ }
+
+ // check has been coerced into correct type; otherwise give up
+ if(proposedValueAdapter == null) {
+ return null;
+ }
+ proposedValueSpec = proposedValueAdapter.getSpecification();
+ if(!proposedValueSpec.isOfType(proposedValueSpec)) {
+ return null;
+ }
+ }
+
+
+ final ValidityContext<?> ic = createProposedArgumentInteractionContext(getAuthenticationSession(), InteractionInvocationMethod.BY_USER, adapter, arguments(proposedValueAdapter), getNumber());
+
+ final InteractionResultSet buf = new InteractionResultSet();
+ InteractionUtils.isValidResultSet(this, ic, buf);
+ if (buf.isVetoed()) {
+ return buf.getInteractionResult().getReason();
+ }
+ return null;
+
+ }
+
+ /**
+ * Optional hook for parsing.
+ */
+ protected ObjectAdapter doCoerceProposedValue(ObjectAdapter adapter, Object proposedValue, final Localization localization) {
+ return null;
+ }
+
+ /**
+ * TODO: this is not ideal, because we can only populate the array for
+ * single argument, rather than the entire argument set. Instead, we ought
+ * to do this in two passes, one to build up the argument set as a single
+ * unit, and then validate each in turn.
+ */
+ private ObjectAdapter[] arguments(final ObjectAdapter proposedValue) {
+ final int parameterCount = getAction().getParameterCount();
+ final ObjectAdapter[] arguments = new ObjectAdapter[parameterCount];
+ arguments[getNumber()] = proposedValue;
+ return arguments;
+ }
+
// /////////////////////////////////////////////////////////////
// Dependencies (from parent)
// /////////////////////////////////////////////////////////////
http://git-wip-us.apache.org/repos/asf/isis/blob/7bc86916/core/metamodel/src/main/java/org/apache/isis/core/metamodel/specloader/specimpl/ObjectActionParameterParseable.java
----------------------------------------------------------------------
diff --git a/core/metamodel/src/main/java/org/apache/isis/core/metamodel/specloader/specimpl/ObjectActionParameterParseable.java b/core/metamodel/src/main/java/org/apache/isis/core/metamodel/specloader/specimpl/ObjectActionParameterParseable.java
index 44de1c9..b976b9c 100644
--- a/core/metamodel/src/main/java/org/apache/isis/core/metamodel/specloader/specimpl/ObjectActionParameterParseable.java
+++ b/core/metamodel/src/main/java/org/apache/isis/core/metamodel/specloader/specimpl/ObjectActionParameterParseable.java
@@ -67,67 +67,24 @@ public class ObjectActionParameterParseable extends ObjectActionParameterAbstrac
final TypicalLengthFacet facet = getFacet(TypicalLengthFacet.class);
return facet.value();
}
-
- /**
- * Invoked when tab away, disables the OK button.
- *
- * <p>
- * Assumed to be invoked {@link InteractionInvocationMethod#BY_USER by user}.
- */
- @Override
- public String isValid(final ObjectAdapter adapter, final Object proposedValue, final Localization localization) {
-
-
- final ObjectActionParameter parameter = getAction().getParameters().get(getNumber());
- final ObjectSpecification parameterSpecification = parameter.getSpecification();
- if(proposedValue == null) {
+
+ protected ObjectAdapter doCoerceProposedValue(ObjectAdapter adapter, Object proposedValue, final Localization localization) {
+ // try to parse
+ if (!(proposedValue instanceof String)) {
return null;
}
-
- ObjectAdapter proposedValueAdapter = getAdapterMap().adapterFor(proposedValue);
- final ObjectSpecification proposedValueSpec = proposedValueAdapter.getSpecification();
- if(proposedValueSpec.isOfType(proposedValueSpec)) {
- // nothing to do
- } else {
- // try to parse
- if (!(parameter instanceof ParseableEntryActionParameter)) {
- return null;
- }
- if (!(proposedValue instanceof String)) {
- return null;
- }
- final String proposedString = (String) proposedValue;
-
- final ParseableFacet p = parameterSpecification.getFacet(ParseableFacet.class);
- proposedValueAdapter = p.parseTextEntry(null, proposedString, localization);
- }
-
- final ValidityContext<?> ic = parameter.createProposedArgumentInteractionContext(getAuthenticationSession(), InteractionInvocationMethod.BY_USER, adapter, arguments(proposedValueAdapter), getNumber());
-
- final InteractionResultSet buf = new InteractionResultSet();
- InteractionUtils.isValidResultSet(parameter, ic, buf);
- if (buf.isVetoed()) {
- return buf.getInteractionResult().getReason();
+ final String proposedString = (String) proposedValue;
+
+ final ObjectSpecification parameterSpecification = getSpecification();
+ final ParseableFacet p = parameterSpecification.getFacet(ParseableFacet.class);
+ try {
+ final ObjectAdapter parsedAdapter = p.parseTextEntry(null, proposedString, localization);
+ return parsedAdapter;
+ } catch(Exception ex) {
+ return null;
}
- return null;
-
}
- /**
- * TODO: this is not ideal, because we can only populate the array for
- * single argument, rather than the entire argument set. Instead, we ought
- * to do this in two passes, one to build up the argument set as a single
- * unit, and then validate each in turn.
- *
- * @param proposedValue
- * @return
- */
- private ObjectAdapter[] arguments(final ObjectAdapter proposedValue) {
- final int parameterCount = getAction().getParameterCount();
- final ObjectAdapter[] arguments = new ObjectAdapter[parameterCount];
- arguments[getNumber()] = proposedValue;
- return arguments;
- }
// /////////////////////////////////////////////////////////////
// getInstance
http://git-wip-us.apache.org/repos/asf/isis/blob/7bc86916/core/metamodel/src/main/java/org/apache/isis/core/metamodel/specloader/specimpl/OneToOneActionParameterImpl.java
----------------------------------------------------------------------
diff --git a/core/metamodel/src/main/java/org/apache/isis/core/metamodel/specloader/specimpl/OneToOneActionParameterImpl.java b/core/metamodel/src/main/java/org/apache/isis/core/metamodel/specloader/specimpl/OneToOneActionParameterImpl.java
index 325e2f6..88e69d7 100644
--- a/core/metamodel/src/main/java/org/apache/isis/core/metamodel/specloader/specimpl/OneToOneActionParameterImpl.java
+++ b/core/metamodel/src/main/java/org/apache/isis/core/metamodel/specloader/specimpl/OneToOneActionParameterImpl.java
@@ -22,10 +22,18 @@ package org.apache.isis.core.metamodel.specloader.specimpl;
import org.apache.isis.applib.profiles.Localization;
import org.apache.isis.core.metamodel.adapter.MutableProposedHolder;
import org.apache.isis.core.metamodel.adapter.ObjectAdapter;
+import org.apache.isis.core.metamodel.consent.InteractionInvocationMethod;
+import org.apache.isis.core.metamodel.consent.InteractionResultSet;
import org.apache.isis.core.metamodel.facetapi.FeatureType;
import org.apache.isis.core.metamodel.facets.TypedHolder;
+import org.apache.isis.core.metamodel.facets.object.parseable.ParseableFacet;
+import org.apache.isis.core.metamodel.interactions.InteractionUtils;
+import org.apache.isis.core.metamodel.interactions.ValidityContext;
import org.apache.isis.core.metamodel.spec.Instance;
+import org.apache.isis.core.metamodel.spec.ObjectSpecification;
+import org.apache.isis.core.metamodel.spec.feature.ObjectActionParameter;
import org.apache.isis.core.metamodel.spec.feature.OneToOneActionParameter;
+import org.apache.isis.core.metamodel.spec.feature.ParseableEntryActionParameter;
public class OneToOneActionParameterImpl extends ObjectActionParameterAbstract implements OneToOneActionParameter {
@@ -43,15 +51,6 @@ public class OneToOneActionParameterImpl extends ObjectActionParameterAbstract i
return true;
}
- /**
- * TODO: need to be able to validate parameters individually, eg if have
- * <tt>RegEx</tt> annotation; should delegate to the Check framework
- * instead.
- */
- @Override
- public String isValid(final ObjectAdapter adapter, final Object proposedValue, final Localization localization) {
- return null;
- }
// /////////////////////////////////////////////////////////////
// getInstance
http://git-wip-us.apache.org/repos/asf/isis/blob/7bc86916/core/metamodel/src/main/java/org/apache/isis/core/progmodel/facets/param/validate/perspec/MustSatisfySpecificationOnParameterFacet.java
----------------------------------------------------------------------
diff --git a/core/metamodel/src/main/java/org/apache/isis/core/progmodel/facets/param/validate/perspec/MustSatisfySpecificationOnParameterFacet.java b/core/metamodel/src/main/java/org/apache/isis/core/progmodel/facets/param/validate/perspec/MustSatisfySpecificationOnParameterFacet.java
index 6b7e667..e09b2ca 100644
--- a/core/metamodel/src/main/java/org/apache/isis/core/progmodel/facets/param/validate/perspec/MustSatisfySpecificationOnParameterFacet.java
+++ b/core/metamodel/src/main/java/org/apache/isis/core/progmodel/facets/param/validate/perspec/MustSatisfySpecificationOnParameterFacet.java
@@ -52,6 +52,9 @@ public class MustSatisfySpecificationOnParameterFacet extends FacetAbstract impl
}
final ProposedHolder proposedHolder = (ProposedHolder) validityContext;
final ObjectAdapter targetNO = proposedHolder.getProposed();
+ if(targetNO == null) {
+ return null;
+ }
final Object targetObject = targetNO.getObject();
final ReasonBuffer buf = new ReasonBuffer();
for (final Specification specification : specifications) {
http://git-wip-us.apache.org/repos/asf/isis/blob/7bc86916/core/tck/tck-dom/src/main/java/org/apache/isis/core/tck/dom/actions/ActionsEntityRepository.java
----------------------------------------------------------------------
diff --git a/core/tck/tck-dom/src/main/java/org/apache/isis/core/tck/dom/actions/ActionsEntityRepository.java b/core/tck/tck-dom/src/main/java/org/apache/isis/core/tck/dom/actions/ActionsEntityRepository.java
index 1c89a73..a517b9a 100644
--- a/core/tck/tck-dom/src/main/java/org/apache/isis/core/tck/dom/actions/ActionsEntityRepository.java
+++ b/core/tck/tck-dom/src/main/java/org/apache/isis/core/tck/dom/actions/ActionsEntityRepository.java
@@ -27,6 +27,7 @@ import org.apache.isis.applib.annotation.MemberOrder;
import org.apache.isis.applib.annotation.MustSatisfy;
import org.apache.isis.applib.annotation.Named;
import org.apache.isis.applib.annotation.ObjectType;
+import org.apache.isis.applib.annotation.Optional;
import org.apache.isis.applib.query.Query;
import org.apache.isis.applib.query.QueryDefault;
import org.apache.isis.applib.spec.Specification;
@@ -84,4 +85,25 @@ public class ActionsEntityRepository extends AbstractEntityRepository<ActionsEnt
return integer.intValue() < 0? "Cannot be less than zero": null;
}
}
+
+
+ @ActionSemantics(Of.SAFE)
+ @MemberOrder(sequence = "1")
+ public List<ActionsEntity> subListWithOptionalRange(
+ @Optional
+ @MustSatisfy(IntegerCannotBeNegative.class)
+ @Named("from") Integer from,
+ @Optional
+ @MustSatisfy(IntegerCannotBeNegative.class)
+ @Named("to") Integer to) {
+ return subList(valueElseDefault(from, 0), valueElseDefault(to, Integer.MAX_VALUE));
+ }
+
+ public String validateSubListWithOptionalRange(final Integer from, final Integer to) {
+ return validateSubList(valueElseDefault(from, 0), valueElseDefault(to, Integer.MAX_VALUE));
+ }
+
+ private static int valueElseDefault(Integer value, int i) {
+ return value != null? value: i;
+ }
}