You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@isis.apache.org by rm...@apache.org on 2012/10/17 22:43:53 UTC

svn commit: r1399424 - in /incubator/isis/trunk/framework/viewer/scimpi/scimpi-dispatcher/src/main/java/org/apache/isis/viewer/scimpi/dispatcher: action/ context/ util/ view/action/ view/simple/

Author: rmatthews
Date: Wed Oct 17 20:43:52 2012
New Revision: 1399424

URL: http://svn.apache.org/viewvc?rev=1399424&view=rev
Log:
ISIS-162 - fixed action elements so they work for contributed methods.

Modified:
    incubator/isis/trunk/framework/viewer/scimpi/scimpi-dispatcher/src/main/java/org/apache/isis/viewer/scimpi/dispatcher/action/ActionAction.java
    incubator/isis/trunk/framework/viewer/scimpi/scimpi-dispatcher/src/main/java/org/apache/isis/viewer/scimpi/dispatcher/context/RequestContext.java
    incubator/isis/trunk/framework/viewer/scimpi/scimpi-dispatcher/src/main/java/org/apache/isis/viewer/scimpi/dispatcher/util/MethodsUtils.java
    incubator/isis/trunk/framework/viewer/scimpi/scimpi-dispatcher/src/main/java/org/apache/isis/viewer/scimpi/dispatcher/view/action/ActionButton.java
    incubator/isis/trunk/framework/viewer/scimpi/scimpi-dispatcher/src/main/java/org/apache/isis/viewer/scimpi/dispatcher/view/action/ActionForm.java
    incubator/isis/trunk/framework/viewer/scimpi/scimpi-dispatcher/src/main/java/org/apache/isis/viewer/scimpi/dispatcher/view/action/ActionLink.java
    incubator/isis/trunk/framework/viewer/scimpi/scimpi-dispatcher/src/main/java/org/apache/isis/viewer/scimpi/dispatcher/view/simple/AbstractConditionalBlock.java

Modified: incubator/isis/trunk/framework/viewer/scimpi/scimpi-dispatcher/src/main/java/org/apache/isis/viewer/scimpi/dispatcher/action/ActionAction.java
URL: http://svn.apache.org/viewvc/incubator/isis/trunk/framework/viewer/scimpi/scimpi-dispatcher/src/main/java/org/apache/isis/viewer/scimpi/dispatcher/action/ActionAction.java?rev=1399424&r1=1399423&r2=1399424&view=diff
==============================================================================
--- incubator/isis/trunk/framework/viewer/scimpi/scimpi-dispatcher/src/main/java/org/apache/isis/viewer/scimpi/dispatcher/action/ActionAction.java (original)
+++ incubator/isis/trunk/framework/viewer/scimpi/scimpi-dispatcher/src/main/java/org/apache/isis/viewer/scimpi/dispatcher/action/ActionAction.java Wed Oct 17 20:43:52 2012
@@ -92,34 +92,10 @@ public class ActionAction implements Act
             }
 
             object.checkLock(context.getVersion(version));
-            /*
-             * Version adapterVersion = object.getVersion(); if
-             * (adapterVersion.different(context.getVersion(version))) {
-             * 
-             * IsisContext.getMessageBroker().addMessage("The " +
-             * object.getSpecification().getSingularName() + " was edited " +
-             * "by another user (" + adapterVersion.getUser() +
-             * "). Please  make your changes based on their changes.");
-             * 
-             * entryState.setForm(objectId + ":" + methodName);
-             * context.addVariable(ENTRY_FIELDS, entryState, Scope.REQUEST);
-             * context.addVariable(resultName, objectId, Scope.REQUEST); if
-             * (override != null) { context.addVariable(resultName, override,
-             * Scope.REQUEST); } final String error = entryState.getError(); if
-             * (error != null) { context.addVariable(RequestContext.ERROR,
-             * error, Scope.REQUEST); }
-             * 
-             * String view = context.getParameter(ERRORS);
-             * context.setRequestPath(view, Dispatcher.ACTION);
-             * 
-             * } else
-             */
             if (entryState.isValid()) {
                 final boolean hasResult = invokeMethod(context, resultName, object, action, entryState);
                 String view = context.getParameter(hasResult ? "_" + VIEW : "_" + VOID);
 
-                // context.clearVariables(Scope.REQUEST);
-
                 final int questionMark = view == null ? -1 : view.indexOf("?");
                 if (questionMark > -1) {
                     final String params[] = view.substring(questionMark + 1).split("&");
@@ -137,7 +113,7 @@ public class ActionAction implements Act
                 if (override != null) {
                     context.addVariable(resultName, override, Scope.REQUEST);
                 }
-                if (context.getVariable(resultName) == null) {
+                if (!action.hasReturn() && context.getVariable(resultName) == null) {
                     context.addVariable(resultName, objectId, Scope.REQUEST);
                 }
             } else {
@@ -148,12 +124,6 @@ public class ActionAction implements Act
                     context.addVariable(resultName, override, Scope.REQUEST);
                 }
                 final String error = entryState.getError();
-                /*
-                 * if (error != null) {
-                 * context.addVariable(RequestContext.ERROR, error,
-                 * Scope.REQUEST); }
-                 */
-
                 final String view = context.getParameter("_" + ERROR);
                 context.setRequestPath(view, Dispatcher.ACTION);
 

Modified: incubator/isis/trunk/framework/viewer/scimpi/scimpi-dispatcher/src/main/java/org/apache/isis/viewer/scimpi/dispatcher/context/RequestContext.java
URL: http://svn.apache.org/viewvc/incubator/isis/trunk/framework/viewer/scimpi/scimpi-dispatcher/src/main/java/org/apache/isis/viewer/scimpi/dispatcher/context/RequestContext.java?rev=1399424&r1=1399423&r2=1399424&view=diff
==============================================================================
--- incubator/isis/trunk/framework/viewer/scimpi/scimpi-dispatcher/src/main/java/org/apache/isis/viewer/scimpi/dispatcher/context/RequestContext.java (original)
+++ incubator/isis/trunk/framework/viewer/scimpi/scimpi-dispatcher/src/main/java/org/apache/isis/viewer/scimpi/dispatcher/context/RequestContext.java Wed Oct 17 20:43:52 2012
@@ -94,7 +94,7 @@ public abstract class RequestContext {
     private static final Map<String, Object> globalVariables = new HashMap<String, Object>();
     private static final Scope[] SCOPES = new Scope[] { Scope.ERROR, Scope.REQUEST, Scope.INTERACTION, Scope.SESSION, Scope.GLOBAL };
     
-    private final OidMarshaller oidMarshaller = getOidMarshaller();
+    private final OidMarshaller oidMarshaller = new OidMarshaller();
 
 
     private final ObjectMapping objectMapping;

Modified: incubator/isis/trunk/framework/viewer/scimpi/scimpi-dispatcher/src/main/java/org/apache/isis/viewer/scimpi/dispatcher/util/MethodsUtils.java
URL: http://svn.apache.org/viewvc/incubator/isis/trunk/framework/viewer/scimpi/scimpi-dispatcher/src/main/java/org/apache/isis/viewer/scimpi/dispatcher/util/MethodsUtils.java?rev=1399424&r1=1399423&r2=1399424&view=diff
==============================================================================
--- incubator/isis/trunk/framework/viewer/scimpi/scimpi-dispatcher/src/main/java/org/apache/isis/viewer/scimpi/dispatcher/util/MethodsUtils.java (original)
+++ incubator/isis/trunk/framework/viewer/scimpi/scimpi-dispatcher/src/main/java/org/apache/isis/viewer/scimpi/dispatcher/util/MethodsUtils.java Wed Oct 17 20:43:52 2012
@@ -136,8 +136,9 @@ public class MethodsUtils {
     }
 
     public static boolean isVisibleAndUsable(final ObjectAdapter object, final ObjectAction action, Where where) {
-        final boolean isVisible = action.isVisible(getAuthenticationSession(), object, where).isAllowed();
-        final boolean isUsable = getSession() != null && action.isUsable(getAuthenticationSession(), object, where).isAllowed();
+        AuthenticationSession authenticatedSession = getAuthenticationSession();
+        final boolean isVisible = action.isVisible(authenticatedSession, object, where).isAllowed();
+        final boolean isUsable = getSession() != null && action.isUsable(authenticatedSession, object, where).isAllowed();
         final boolean isVisibleAndUsable = isVisible && isUsable;
         return isVisibleAndUsable;
     }

Modified: incubator/isis/trunk/framework/viewer/scimpi/scimpi-dispatcher/src/main/java/org/apache/isis/viewer/scimpi/dispatcher/view/action/ActionButton.java
URL: http://svn.apache.org/viewvc/incubator/isis/trunk/framework/viewer/scimpi/scimpi-dispatcher/src/main/java/org/apache/isis/viewer/scimpi/dispatcher/view/action/ActionButton.java?rev=1399424&r1=1399423&r2=1399424&view=diff
==============================================================================
--- incubator/isis/trunk/framework/viewer/scimpi/scimpi-dispatcher/src/main/java/org/apache/isis/viewer/scimpi/dispatcher/view/action/ActionButton.java (original)
+++ incubator/isis/trunk/framework/viewer/scimpi/scimpi-dispatcher/src/main/java/org/apache/isis/viewer/scimpi/dispatcher/view/action/ActionButton.java Wed Oct 17 20:43:52 2012
@@ -32,6 +32,7 @@ import org.apache.isis.core.metamodel.sp
 import org.apache.isis.runtimes.dflt.runtime.system.context.IsisContext;
 import org.apache.isis.viewer.scimpi.dispatcher.AbstractElementProcessor;
 import org.apache.isis.viewer.scimpi.dispatcher.context.RequestContext;
+import org.apache.isis.viewer.scimpi.dispatcher.context.RequestContext.Scope;
 import org.apache.isis.viewer.scimpi.dispatcher.processor.Request;
 import org.apache.isis.viewer.scimpi.dispatcher.util.MethodsUtils;
 import org.apache.isis.viewer.scimpi.dispatcher.view.HelpLink;
@@ -56,7 +57,7 @@ public class ActionButton extends Abstra
         final String variable = request.getOptionalProperty(RESULT_NAME);
         final String scope = request.getOptionalProperty(SCOPE);
         final String buttonTitle = request.getOptionalProperty(BUTTON_TITLE);
-        final String resultOverride = request.getOptionalProperty(RESULT_OVERRIDE);
+        String resultOverride = request.getOptionalProperty(RESULT_OVERRIDE);
         final String idName = request.getOptionalProperty(ID, methodName);
         final String className = request.getOptionalProperty(CLASS);
         final boolean showMessage = request.isRequested(SHOW_MESSAGE, false);
@@ -70,25 +71,39 @@ public class ActionButton extends Abstra
         request.setBlockContent(parameterBlock);
         request.processUtilCloseTag();
         final String[] parameters = parameterBlock.getParameters();
-        final ObjectAdapter[] objectParameters = new ObjectAdapter[parameters.length];
-        int i = 0;
-        for (final ObjectActionParameter spec : action.getParameters()) {
-            final ObjectSpecification typ = spec.getSpecification();
-            if (parameters[i] == null) {
-                objectParameters[i] = null;
-            } else if (typ.getFacet(ParseableFacet.class) != null) {
-                final ParseableFacet facet = typ.getFacet(ParseableFacet.class);
-                Localization localization = IsisContext.getLocalization(); 
-                objectParameters[i] = facet.parseTextEntry(null, parameters[i], localization); 
-            } else {
-                objectParameters[i] = MethodsUtils.findObject(request.getContext(), parameters[i]);
+        final ObjectAdapter[] objectParameters;
+        
+        final ObjectAdapter target;
+        if (action.isContributed()) {
+            objectParameters= null;
+            System.arraycopy(parameters, 0, parameters, 1, parameters.length - 1);
+            parameters[0] = request.getContext().mapObject(object, Scope.REQUEST);
+            target =  action.realTarget(object);
+            if (!action.hasReturn() && resultOverride == null) {
+                resultOverride = parameters[0];
+            }
+        } else {
+            objectParameters = new ObjectAdapter[parameters.length];
+            target = object;
+            int i = 0;
+            for (final ObjectActionParameter spec : action.getParameters()) {
+                final ObjectSpecification type = spec.getSpecification();
+                if (parameters[i] == null) {
+                    objectParameters[i] = null;
+                } else if (type.getFacet(ParseableFacet.class) != null) {
+                    final ParseableFacet facet = type.getFacet(ParseableFacet.class);
+                    Localization localization = IsisContext.getLocalization(); 
+                    objectParameters[i] = facet.parseTextEntry(null, parameters[i], localization); 
+                } else {
+                    objectParameters[i] = MethodsUtils.findObject(request.getContext(), parameters[i]);
+                }
+                i++;
             }
-            i++;
         }
 
         if (MethodsUtils.isVisibleAndUsable(object, action, where) && MethodsUtils.canRunMethod(object, action, objectParameters).isAllowed()) {
             // TODO use the form creation mechanism as used in ActionForm
-            write(request, object, action, parameters, objectId, version, forwardResultTo, forwardVoidTo, forwardErrorTo, variable, scope, buttonTitle, completionMessage, resultOverride, idName, className);
+            write(request, target, action, parameters, objectId, version, forwardResultTo, forwardVoidTo, forwardErrorTo, variable, scope, buttonTitle, completionMessage, resultOverride, idName, className);
         }
 
         if (showMessage) {

Modified: incubator/isis/trunk/framework/viewer/scimpi/scimpi-dispatcher/src/main/java/org/apache/isis/viewer/scimpi/dispatcher/view/action/ActionForm.java
URL: http://svn.apache.org/viewvc/incubator/isis/trunk/framework/viewer/scimpi/scimpi-dispatcher/src/main/java/org/apache/isis/viewer/scimpi/dispatcher/view/action/ActionForm.java?rev=1399424&r1=1399423&r2=1399424&view=diff
==============================================================================
--- incubator/isis/trunk/framework/viewer/scimpi/scimpi-dispatcher/src/main/java/org/apache/isis/viewer/scimpi/dispatcher/view/action/ActionForm.java (original)
+++ incubator/isis/trunk/framework/viewer/scimpi/scimpi-dispatcher/src/main/java/org/apache/isis/viewer/scimpi/dispatcher/view/action/ActionForm.java Wed Oct 17 20:43:52 2012
@@ -106,6 +106,9 @@ public class ActionForm extends Abstract
         final String objectId = context.mapObject(object, Scope.INTERACTION);
         final String errorView = context.fullFilePath(parameterObject.forwardErrorTo == null ? context.getResourceFile() : parameterObject.forwardErrorTo);
         final String voidView = context.fullFilePath(parameterObject.forwardVoidTo == null ? context.getResourceFile() : parameterObject.forwardVoidTo);
+        if (action.isContributed() && !action.hasReturn() && parameterObject.resultOverride == null) {
+            parameterObject.resultOverride = objectId;
+        }
         final HiddenInputField[] hiddenFields = new HiddenInputField[] { new HiddenInputField("_" + OBJECT, objectId), new HiddenInputField("_" + VERSION, version), new HiddenInputField("_" + FORM_ID, parameterObject.formId), new HiddenInputField("_" + METHOD, parameterObject.methodName),
                 parameterObject.forwardResultTo == null ? null : new HiddenInputField("_" + VIEW, context.fullFilePath(parameterObject.forwardResultTo)), new HiddenInputField("_" + VOID, voidView), new HiddenInputField("_" + ERROR, errorView),
                 parameterObject.completionMessage == null ? null : new HiddenInputField("_" + MESSAGE, parameterObject.completionMessage), parameterObject.scope == null ? null : new HiddenInputField("_" + SCOPE, parameterObject.scope),

Modified: incubator/isis/trunk/framework/viewer/scimpi/scimpi-dispatcher/src/main/java/org/apache/isis/viewer/scimpi/dispatcher/view/action/ActionLink.java
URL: http://svn.apache.org/viewvc/incubator/isis/trunk/framework/viewer/scimpi/scimpi-dispatcher/src/main/java/org/apache/isis/viewer/scimpi/dispatcher/view/action/ActionLink.java?rev=1399424&r1=1399423&r2=1399424&view=diff
==============================================================================
--- incubator/isis/trunk/framework/viewer/scimpi/scimpi-dispatcher/src/main/java/org/apache/isis/viewer/scimpi/dispatcher/view/action/ActionLink.java (original)
+++ incubator/isis/trunk/framework/viewer/scimpi/scimpi-dispatcher/src/main/java/org/apache/isis/viewer/scimpi/dispatcher/view/action/ActionLink.java Wed Oct 17 20:43:52 2012
@@ -42,10 +42,7 @@ public class ActionLink extends Abstract
         final String method = request.getOptionalProperty(METHOD);
         final String forwardResultTo = request.getOptionalProperty(VIEW);
         final String forwardVoidTo = request.getOptionalProperty(VOID);
-        final String resultOverride = request.getOptionalProperty(RESULT_OVERRIDE);
-        
-        @SuppressWarnings("unused")
-        final String resultOverrideSegment = resultOverride == null ? "" : "&amp;" + RESULT_OVERRIDE + "=" + resultOverride;
+        String resultOverride = request.getOptionalProperty(RESULT_OVERRIDE);
         
         final String resultName = request.getOptionalProperty(RESULT_NAME);
         final String resultNameSegment = resultName == null ? "" : "&amp;" + RESULT_NAME + "=" + resultName;
@@ -66,34 +63,62 @@ public class ActionLink extends Abstract
         objectId = request.getContext().mapObject(object, Scope.REQUEST);
 
         final ActionContent parameterBlock = new ActionContent(action);
-        
         request.setBlockContent(parameterBlock);
         request.pushNewBuffer();
         request.processUtilCloseTag();
         final String text = request.popBuffer();
+        
+        final String[] parameters = parameterBlock.getParameters();
+        final String target;
+        if (action.isContributed()) {
+            System.arraycopy(parameters, 0, parameters, 1, parameters.length - 1);
+            parameters[0] = request.getContext().mapObject(object, Scope.REQUEST);
+            target =  request.getContext().mapObject(action.realTarget(object), Scope.REQUEST);
+            if (!action.hasReturn() && resultOverride == null) {
+                resultOverride = parameters[0];
+            }
+        } else {
+            target = objectId;
+        }
 
         if (MethodsUtils.isVisibleAndUsable(object, action, where)) {
-            writeLink(request, objectId, version, method, forwardResultTo, forwardVoidTo, resultNameSegment, scopeSegment, confirmSegment, messageSegment, context, action, parameterBlock, text);
+            writeLink(request, target, version, method, forwardResultTo, forwardVoidTo, resultNameSegment, resultOverride, scopeSegment,
+                    confirmSegment, messageSegment, context, action, parameters, text);
         }
         request.popBlockContent();
     }
 
-    public static void writeLink(final Request request, final String objectId, final String version, final String method, final String forwardResultTo, final String forwardVoidTo, final String resultNameSegment, final String scopeSegment, final String confirmSegment, final String messageSegment,
-            final RequestContext context, final ObjectAction action, final ActionContent parameterBlock, String text) {
+    public static void writeLink(
+            final Request request,
+            final String objectId,
+            final String version,
+            final String method,
+            final String forwardResultTo,
+            final String forwardVoidTo,
+            final String resultNameSegment,
+            final String resultOverride,
+            final String scopeSegment,
+            final String confirmSegment,
+            final String messageSegment,
+            final RequestContext context,
+            final ObjectAction action,
+            final String[] parameters,
+            String text) {
         text = text == null || text.trim().equals("") ? action.getName() : text;
 
         String parameterSegment = "";
-        final String[] parameters = parameterBlock.getParameters();
         for (int i = 0; i < parameters.length; i++) {
             parameterSegment += "&param" + (i + 1) + "=" + parameters[i];
         }
 
         final String interactionParamters = context.encodedInteractionParameters();
         final String forwardResultSegment = forwardResultTo == null ? "" : "&amp;" + "_" + VIEW + "=" + context.fullFilePath(forwardResultTo);
+        final String resultOverrideSegment = resultOverride == null ? "" : "&amp;" + "_" + RESULT_OVERRIDE + "=" + resultOverride;
         final String voidView = context.fullFilePath(forwardVoidTo == null ? context.getResourceFile() : forwardVoidTo);
         final String forwardVoidSegment = "&amp;" + "_" + VOID + "=" + voidView;
-        request.appendHtml("<a href=\"action.app?" + "_" + OBJECT + "=" + objectId + "&amp;" + "_" + VERSION + "=" + version + "&amp;" + "_" + METHOD + "=" + method + forwardResultSegment + forwardVoidSegment + resultNameSegment + parameterSegment + scopeSegment + confirmSegment + messageSegment
-                + interactionParamters + "\">");
+        request.appendHtml("<a href=\"action.app?" + "_" + OBJECT + "=" + objectId + "&amp;" + "_" + VERSION + "=" + version
+                + "&amp;" + "_" + METHOD + "=" + method + resultOverrideSegment + forwardResultSegment + forwardVoidSegment + resultNameSegment
+                + parameterSegment + scopeSegment + confirmSegment + messageSegment + interactionParamters + "\">");
         request.appendHtml(text);
         request.appendHtml("</a>");
         HelpLink.append(request, action.getDescription(), action.getHelp());

Modified: incubator/isis/trunk/framework/viewer/scimpi/scimpi-dispatcher/src/main/java/org/apache/isis/viewer/scimpi/dispatcher/view/simple/AbstractConditionalBlock.java
URL: http://svn.apache.org/viewvc/incubator/isis/trunk/framework/viewer/scimpi/scimpi-dispatcher/src/main/java/org/apache/isis/viewer/scimpi/dispatcher/view/simple/AbstractConditionalBlock.java?rev=1399424&r1=1399423&r2=1399424&view=diff
==============================================================================
--- incubator/isis/trunk/framework/viewer/scimpi/scimpi-dispatcher/src/main/java/org/apache/isis/viewer/scimpi/dispatcher/view/simple/AbstractConditionalBlock.java (original)
+++ incubator/isis/trunk/framework/viewer/scimpi/scimpi-dispatcher/src/main/java/org/apache/isis/viewer/scimpi/dispatcher/view/simple/AbstractConditionalBlock.java Wed Oct 17 20:43:52 2012
@@ -72,6 +72,9 @@ public abstract class AbstractConditiona
         // addNormal(new TestCollectionSize(), "collection-size-less-than");
         // addNormal(new TestCollectionSize(), "collection-size-greater-than");
 
+        addNormal(new TestFieldValue(), "test-field");
+        addNegated(new TestFieldValue(), "test-field");
+           
         addNormal(new TestFieldExists(), "field-exists");
         addNegated(new TestFieldExists(), "field-missing");
         addNormal(new TestFieldVisible(), "field-visible");
@@ -323,12 +326,33 @@ abstract class Test {
         }
         return cls;
     }
+    
+    protected ObjectAction findMethod(final String attributeName, final ObjectAdapter object) {
+        final ObjectAction objectAction = object.getSpecification().getObjectAction(ActionType.USER, attributeName, ObjectSpecification.EMPTY_LIST);
+        if (objectAction == null) {
+            throw new ScimpiException("No such method found in " + object.getSpecification().getIdentifier().getClassName() + " : " + attributeName);
+        }
+        return objectAction;
+    }
+
+    protected ObjectAssociation findProperty(final String attributeName, final ObjectAdapter object) {
+        final ObjectAssociation objectField = object.getSpecification().getAssociation(attributeName);
+        if (objectField == null) {
+            throw new ScimpiException("No such property found in " + object.getSpecification().getIdentifier().getClassName() + ": " + attributeName);
+        }
+        return objectField;
+    }
+
 }
 
 class TestVariableExists extends Test {
     @Override
     boolean test(final Request request, final String attributeName, final String targetId) {
-        return request.getContext().getVariable(attributeName) != null;
+        Object variable = request.getContext().getVariable(attributeName);
+        if (variable instanceof String && ((String) variable).equals("")) {
+            return false;
+        }
+        return variable != null;
     }
 }
 
@@ -401,7 +425,7 @@ class TestMethodVisible extends Test {
     boolean test(final Request request, final String attributeName, final String targetId) {
         final ObjectAdapter object = MethodsUtils.findObject(request.getContext(), targetId);
         // TODO needs to work irrespective of parameters
-        final ObjectAction objectAction = object.getSpecification().getObjectAction(ActionType.USER, attributeName, ObjectSpecification.EMPTY_LIST);
+        final ObjectAction objectAction = findMethod(attributeName, object);
         final Consent visible = objectAction.isVisible(IsisContext.getAuthenticationSession(), object, Where.ANYWHERE);
         return visible.isAllowed();
     }
@@ -412,7 +436,7 @@ class TestMethodUseable extends Test {
     boolean test(final Request request, final String attributeName, final String targetId) {
         final ObjectAdapter object = MethodsUtils.findObject(request.getContext(), targetId);
         // TODO needs to work irrespective of parameters
-        final ObjectAction objectAction = object.getSpecification().getObjectAction(ActionType.USER, attributeName, ObjectSpecification.EMPTY_LIST);
+        final ObjectAction objectAction = findMethod(attributeName, object);
         final Consent usable = objectAction.isUsable(IsisContext.getAuthenticationSession(), object, Where.ANYWHERE);
         return usable.isAllowed();
     }
@@ -438,7 +462,7 @@ class TestFieldVisible extends Test {
     @Override
     boolean test(final Request request, final String attributeName, final String targetId) {
         final ObjectAdapter object = MethodsUtils.findObject(request.getContext(), targetId);
-        final ObjectAssociation objectField = object.getSpecification().getAssociation(attributeName);
+        final ObjectAssociation objectField = findProperty(attributeName, object);
         final Consent visible = objectField.isVisible(IsisContext.getAuthenticationSession(), object, Where.ANYWHERE);
         return visible.isAllowed();
     }
@@ -448,7 +472,7 @@ class TestFieldEditable extends Test {
     @Override
     boolean test(final Request request, final String attributeName, final String targetId) {
         final ObjectAdapter object = MethodsUtils.findObject(request.getContext(), targetId);
-        final ObjectAssociation objectField = object.getSpecification().getAssociation(attributeName);
+        final ObjectAssociation objectField = findProperty(attributeName, object);
         final Consent usable = objectField.isUsable(IsisContext.getAuthenticationSession(), object, Where.ANYWHERE);
         return usable.isAllowed();
     }
@@ -468,7 +492,7 @@ class TestFieldSet extends Test {
     @Override
     boolean test(final Request request, final String attributeName, final String targetId) {
         final ObjectAdapter object = MethodsUtils.findObject(request.getContext(), targetId);
-        final ObjectAssociation objectField = object.getSpecification().getAssociation(attributeName);
+        final ObjectAssociation objectField = findProperty(attributeName, object);
         IsisContext.getPersistenceSession().resolveField(object, objectField);
         final ObjectAdapter fld = objectField.get(object);
         if (fld != null) {
@@ -487,6 +511,31 @@ class TestFieldSet extends Test {
     }
 }
 
+class TestFieldValue extends Test {
+    @Override
+    boolean test(Request request, String attributeName, String targetId) {
+        int pos = attributeName.indexOf("==");
+        // TODO test for other comparators
+        // TODO fail properly if none found
+        String fieldName = attributeName.substring(0, pos);
+        String fieldValue = attributeName.substring(pos + 2);
+        
+        final ObjectAdapter object = MethodsUtils.findObject(request.getContext(), targetId);
+        final ObjectAssociation objectField = findProperty(fieldName, object);
+        IsisContext.getPersistenceSession().resolveField(object, objectField);
+        final ObjectAdapter fld = objectField.get(object);
+        
+        // TODO test for reference or value
+        final ObjectAdapter object2 = MethodsUtils.findObject(request.getContext(), fieldValue);
+        
+        if (fld == object2) {
+            return true;
+        }
+        return false;
+    }
+    
+}
+
 class TestHasRole extends Test {
     @Override
     boolean test(final Request request, final String attributeName, final String targetId) {