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 2011/07/10 08:51:30 UTC

svn commit: r1144784 - in /incubator/isis/trunk/framework/viewer/json: applib/src/main/java/org/apache/isis/viewer/json/applib/resources/ viewer/src/main/java/org/apache/isis/viewer/json/viewer/resources/ viewer/src/main/java/org/apache/isis/viewer/jso...

Author: danhaywood
Date: Sun Jul 10 06:51:30 2011
New Revision: 1144784

URL: http://svn.apache.org/viewvc?rev=1144784&view=rev
Log:
enhancing json viewer to allow actions to be invoked (currently just on GET, no args)

Added:
    incubator/isis/trunk/framework/viewer/json/viewer/src/main/java/org/apache/isis/viewer/json/viewer/resources/StatusTypes.java
Modified:
    incubator/isis/trunk/framework/viewer/json/applib/src/main/java/org/apache/isis/viewer/json/applib/resources/DomainObjectResource.java
    incubator/isis/trunk/framework/viewer/json/viewer/src/main/java/org/apache/isis/viewer/json/viewer/resources/ResourceAbstract.java
    incubator/isis/trunk/framework/viewer/json/viewer/src/main/java/org/apache/isis/viewer/json/viewer/resources/objects/ActionRepBuilder.java
    incubator/isis/trunk/framework/viewer/json/viewer/src/main/java/org/apache/isis/viewer/json/viewer/resources/objects/DomainObjectResourceImpl.java
    incubator/isis/trunk/framework/viewer/json/viewer/src/main/java/org/apache/isis/viewer/json/viewer/resources/objects/MemberType.java
    incubator/isis/trunk/framework/viewer/json/viewer/src/main/java/org/apache/isis/viewer/json/viewer/resources/services/ServicesResourceImpl.java

Modified: incubator/isis/trunk/framework/viewer/json/applib/src/main/java/org/apache/isis/viewer/json/applib/resources/DomainObjectResource.java
URL: http://svn.apache.org/viewvc/incubator/isis/trunk/framework/viewer/json/applib/src/main/java/org/apache/isis/viewer/json/applib/resources/DomainObjectResource.java?rev=1144784&r1=1144783&r2=1144784&view=diff
==============================================================================
--- incubator/isis/trunk/framework/viewer/json/applib/src/main/java/org/apache/isis/viewer/json/applib/resources/DomainObjectResource.java (original)
+++ incubator/isis/trunk/framework/viewer/json/applib/src/main/java/org/apache/isis/viewer/json/applib/resources/DomainObjectResource.java Sun Jul 10 06:51:30 2011
@@ -31,6 +31,7 @@ import javax.ws.rs.PathParam;
 import javax.ws.rs.Produces;
 import javax.ws.rs.QueryParam;
 import javax.ws.rs.core.MediaType;
+import javax.ws.rs.core.Response;
 
 // under /objects
 public interface DomainObjectResource {
@@ -47,6 +48,28 @@ public interface DomainObjectResource {
         @PathParam("oid") final String oidStr,
         @PathParam("propertyId") final String propertyId);
 
+    @GET
+    @Path("/{oid}/collections/{collectionId}")
+    @Produces({ MediaType.APPLICATION_JSON })
+    public String accessCollection(
+        @PathParam("oid") final String oidStr,
+        @PathParam("collectionId") final String collectionId);
+
+    @GET
+    @Path("/{oid}/actions/{actionId}")
+    @Produces({ MediaType.APPLICATION_JSON })
+    public String actionPrompt(
+        @PathParam("oid") final String oidStr, 
+        @PathParam("actionId") final String actionId);
+
+    @GET
+    @Path("/{oid}/actions/{actionId}/invoke")
+    @Produces({ MediaType.APPLICATION_JSON })
+    public Object invokeActionIdempotent(
+        @PathParam("oid") final String oidStr, 
+        @PathParam("actionId") final String actionId,
+        @QueryParam("argument") final List<String> arguments);
+
     @PUT
     @Path("/{oid}/properties{propertyId}")
     @Produces({ MediaType.APPLICATION_JSON })
@@ -55,6 +78,14 @@ public interface DomainObjectResource {
         @PathParam("propertyId") final String propertyId, 
         @FormParam("proposedValue") final String proposedValue);
 
+    @PUT
+    @Path("/{oid}/collections/{collectionId}")
+    @Produces({ MediaType.APPLICATION_JSON })
+    public String addToSet(
+        @PathParam("oid") final String oidStr,
+        @PathParam("collectionId") final String collectionId,
+        @FormParam("proposedValue") final String proposedValueOidStr);
+
     @DELETE
     @Path("/{oid}/properties/{propertyId}")
     @Produces({ MediaType.APPLICATION_JSON })
@@ -62,35 +93,22 @@ public interface DomainObjectResource {
         @PathParam("oid") final String oidStr, 
         @PathParam("propertyId") final String propertyId);
 
-    @GET
-    @Path("/{oid}/collections/{collectionId}")
-    @Produces({ MediaType.APPLICATION_JSON })
-    public String accessCollection(
-        @PathParam("oid") final String oidStr,
-        @PathParam("collectionId") final String collectionId);
-
-    @PUT
+    @DELETE
     @Path("/{oid}/collections/{collectionId}")
     @Produces({ MediaType.APPLICATION_JSON })
-    public String addToCollection(
+    public String removeFromCollection(
         @PathParam("oid") final String oidStr,
         @PathParam("collectionId") final String collectionId,
         @FormParam("proposedValue") final String proposedValueOidStr);
 
-    @DELETE
+    @POST
     @Path("/{oid}/collections/{collectionId}")
     @Produces({ MediaType.APPLICATION_JSON })
-    public String removeFromCollection(
+    public String addToList(
         @PathParam("oid") final String oidStr,
         @PathParam("collectionId") final String collectionId,
         @FormParam("proposedValue") final String proposedValueOidStr);
 
-    @GET
-    @Path("/{oid}/actions/{actionId}")
-    @Produces({ MediaType.APPLICATION_JSON })
-    public String actionPrompt(
-        @PathParam("oid") final String oidStr, 
-        @PathParam("actionId") final String actionId);
 
     @POST
     @Path("/{oid}/actions/{actionId}/invoke")
@@ -100,12 +118,6 @@ public interface DomainObjectResource {
         @PathParam("actionId") final String actionId,
         final InputStream body);
 
-    @GET
-    @Path("/{oid}/actions/{actionId}/invoke")
-    @Produces({ MediaType.APPLICATION_JSON })
-    public String invokeActionIdempotent(
-        @PathParam("oid") final String oidStr, 
-        @PathParam("actionId") final String actionId,
-        @QueryParam("argument") final List<String> arguments);
 
+    
 }
\ No newline at end of file

Modified: incubator/isis/trunk/framework/viewer/json/viewer/src/main/java/org/apache/isis/viewer/json/viewer/resources/ResourceAbstract.java
URL: http://svn.apache.org/viewvc/incubator/isis/trunk/framework/viewer/json/viewer/src/main/java/org/apache/isis/viewer/json/viewer/resources/ResourceAbstract.java?rev=1144784&r1=1144783&r2=1144784&view=diff
==============================================================================
--- incubator/isis/trunk/framework/viewer/json/viewer/src/main/java/org/apache/isis/viewer/json/viewer/resources/ResourceAbstract.java (original)
+++ incubator/isis/trunk/framework/viewer/json/viewer/src/main/java/org/apache/isis/viewer/json/viewer/resources/ResourceAbstract.java Sun Jul 10 06:51:30 2011
@@ -19,6 +19,8 @@
 package org.apache.isis.viewer.json.viewer.resources;
 
 import java.io.IOException;
+import java.util.Collection;
+import java.util.List;
 
 import javax.servlet.http.HttpServletRequest;
 import javax.servlet.http.HttpServletResponse;
@@ -28,6 +30,8 @@ import javax.ws.rs.core.HttpHeaders;
 import javax.ws.rs.core.Request;
 import javax.ws.rs.core.Response;
 import javax.ws.rs.core.Response.Status;
+import javax.ws.rs.core.Response.Status.Family;
+import javax.ws.rs.core.Response.StatusType;
 import javax.ws.rs.core.SecurityContext;
 import javax.ws.rs.core.UriInfo;
 
@@ -38,13 +42,17 @@ import org.apache.isis.core.metamodel.co
 import org.apache.isis.core.metamodel.spec.ActionType;
 import org.apache.isis.core.metamodel.spec.ObjectSpecification;
 import org.apache.isis.core.metamodel.spec.SpecificationLoader;
+import org.apache.isis.core.metamodel.spec.feature.ObjectAssociation;
+import org.apache.isis.core.metamodel.spec.feature.OneToOneAssociation;
 import org.apache.isis.runtimes.dflt.runtime.system.context.IsisContext;
 import org.apache.isis.runtimes.dflt.runtime.system.persistence.AdapterManager;
 import org.apache.isis.runtimes.dflt.runtime.system.persistence.OidGenerator;
 import org.apache.isis.runtimes.dflt.runtime.system.persistence.PersistenceSession;
+import org.apache.isis.viewer.json.viewer.RepContext;
 import org.apache.isis.viewer.json.viewer.ResourceContext;
 import org.apache.isis.viewer.json.viewer.representations.Representation;
 import org.apache.isis.viewer.json.viewer.representations.RepresentationBuilder;
+import org.apache.isis.viewer.json.viewer.resources.objects.DomainObjectRepBuilder;
 import org.apache.isis.viewer.json.viewer.util.OidUtils;
 import org.apache.isis.viewer.json.viewer.util.UrlDecoderUtils;
 import org.codehaus.jackson.JsonGenerationException;
@@ -52,9 +60,14 @@ import org.codehaus.jackson.map.JsonMapp
 import org.codehaus.jackson.map.ObjectMapper;
 import org.codehaus.jackson.map.SerializationConfig;
 
+import com.google.common.base.Function;
+import com.google.common.base.Functions;
+import com.google.common.collect.Collections2;
+import com.google.common.collect.Lists;
+
 public abstract class ResourceAbstract {
 
-    public final static ActionType[] ACTION_TYPES = { ActionType.USER, ActionType.DEBUG, ActionType.EXPLORATION,
+	public final static ActionType[] ACTION_TYPES = { ActionType.USER, ActionType.DEBUG, ActionType.EXPLORATION,
     // SET is excluded; we simply flatten contributed actions.
         };
 
@@ -99,6 +112,18 @@ public abstract class ResourceAbstract {
         return asJson(representation);
     }
 
+	protected String jsonRepresentationOf(
+			final Collection<ObjectAdapter> collectionAdapters) {
+		return asJson(Lists.newArrayList(
+            Collections2.transform(collectionAdapters, toObjectSelfRepresentation())));
+	}
+
+	protected String jsonRepresentationOf(
+			final ObjectAdapter objectAdapter) {
+		return asJson(toObjectSelfRepresentation().apply(objectAdapter));
+	}
+
+
     protected String asJson(final Object object) {
         ObjectMapper objectMapper = new ObjectMapper();
         objectMapper.configure(SerializationConfig.Feature.INDENT_OUTPUT, true);
@@ -113,6 +138,16 @@ public abstract class ResourceAbstract {
         }
     }
 
+	private Function<ObjectAdapter, Representation> toObjectSelfRepresentation() {
+		final RepContext representationContext = getResourceContext().repContext();
+        
+        Function<ObjectAdapter, Representation> objectSelfRepresentation = 
+            Functions.compose(
+                DomainObjectRepBuilder.selfOf(), 
+                DomainObjectRepBuilder.fromAdapter(representationContext));
+		return objectSelfRepresentation;
+	}
+
 
     // //////////////////////////////////////////////////////////////
     // Isis integration
@@ -123,6 +158,8 @@ public abstract class ResourceAbstract {
     }
 
     protected ObjectAdapter getObjectAdapter(final String oidEncodedStr) {
+        init();
+
         final ObjectAdapter objectAdapter = OidUtils.getObjectAdapter(oidEncodedStr, getOidStringifier());
         
         if (objectAdapter == null) {
@@ -132,6 +169,7 @@ public abstract class ResourceAbstract {
         return objectAdapter;
     }
 
+
     protected String getOidStr(final ObjectAdapter objectAdapter) {
         return OidUtils.getOidStr(objectAdapter, getOidStringifier());
     }
@@ -142,39 +180,43 @@ public abstract class ResourceAbstract {
     // Responses
     // //////////////////////////////////////////////////////////////
 
-    protected Response responseOfOk() {
+    protected static Response responseOfOk() {
         return Response.ok().build();
     }
 
-    protected Response responseOfGone(final String reason) {
+    protected static Response responseOfGone(final String reason) {
         return Response.status(Status.GONE).header("isis-reason", reason).build();
     }
 
-    protected Response responseOfBadRequest(final Consent consent) {
+    protected static Response responseOfBadRequest(final Consent consent) {
         return responseOfBadRequest(consent.getReason());
     }
 
-    protected Response responseOfNoContent(final String reason) {
+    protected static Response responseOfNoContent(final String reason) {
         return Response.status(Status.NO_CONTENT).header("isis-reason", reason).build();
     }
 
-    protected Response responseOfBadRequest(final String reason) {
+    protected static Response responseOfBadRequest(final String reason) {
         return Response.status(Status.BAD_REQUEST).header("isis-reason", reason).build();
     }
 
-    protected Response responseOfNotFound(final IllegalArgumentException e) {
+    protected static Response responseOfNotFound(final IllegalArgumentException e) {
         return responseOfNotFound(e.getMessage());
     }
 
-    protected Response responseOfNotFound(final String reason) {
+    protected static Response responseOfNotFound(final String reason) {
         return Response.status(Status.NOT_FOUND).header("isis-reason", reason).build();
     }
 
-    protected Response responseOfInternalServerError(final Exception ex) {
+    protected static Response responseOfPreconditionFailed(final String reason) {
+        return Response.status(StatusTypes.PRECONDITION_FAILED).header("isis-reason", reason).build();
+    }
+
+    protected static Response responseOfInternalServerError(final Exception ex) {
         return responseOfInternalServerError(ex.getMessage());
     }
 
-    protected Response responseOfInternalServerError(final String reason) {
+    protected static Response responseOfInternalServerError(final String reason) {
         return Response.status(Status.INTERNAL_SERVER_ERROR).header("isis-reason", reason).build();
     }
 

Added: incubator/isis/trunk/framework/viewer/json/viewer/src/main/java/org/apache/isis/viewer/json/viewer/resources/StatusTypes.java
URL: http://svn.apache.org/viewvc/incubator/isis/trunk/framework/viewer/json/viewer/src/main/java/org/apache/isis/viewer/json/viewer/resources/StatusTypes.java?rev=1144784&view=auto
==============================================================================
--- incubator/isis/trunk/framework/viewer/json/viewer/src/main/java/org/apache/isis/viewer/json/viewer/resources/StatusTypes.java (added)
+++ incubator/isis/trunk/framework/viewer/json/viewer/src/main/java/org/apache/isis/viewer/json/viewer/resources/StatusTypes.java Sun Jul 10 06:51:30 2011
@@ -0,0 +1,41 @@
+package org.apache.isis.viewer.json.viewer.resources;
+
+import javax.ws.rs.core.Response.Status.Family;
+import javax.ws.rs.core.Response.StatusType;
+
+public class StatusTypes {
+
+    private static class StatusTypeImpl implements StatusType {
+
+		private int statusCode;
+		private Family family;
+		private String reasonPhrase;
+
+		private StatusTypeImpl(final int statusCode, final Family family,
+				final String reasonPhrase) {
+			this.statusCode = statusCode;
+			this.family = family;
+			this.reasonPhrase = reasonPhrase;
+		}
+
+		@Override
+		public int getStatusCode() {
+			return statusCode;
+		}
+
+		@Override
+		public Family getFamily() {
+			return family;
+		}
+
+		@Override
+		public String getReasonPhrase() {
+			return reasonPhrase;
+		}
+    }
+
+
+    public final static StatusType METHOD_NOT_ALLOWED = new StatusTypeImpl(405, Family.CLIENT_ERROR, "Method not allowed");
+    public final static StatusType PRECONDITION_FAILED = new StatusTypeImpl(412, Family.CLIENT_ERROR, "Precondition failed");
+
+}

Modified: incubator/isis/trunk/framework/viewer/json/viewer/src/main/java/org/apache/isis/viewer/json/viewer/resources/objects/ActionRepBuilder.java
URL: http://svn.apache.org/viewvc/incubator/isis/trunk/framework/viewer/json/viewer/src/main/java/org/apache/isis/viewer/json/viewer/resources/objects/ActionRepBuilder.java?rev=1144784&r1=1144783&r2=1144784&view=diff
==============================================================================
--- incubator/isis/trunk/framework/viewer/json/viewer/src/main/java/org/apache/isis/viewer/json/viewer/resources/objects/ActionRepBuilder.java (original)
+++ incubator/isis/trunk/framework/viewer/json/viewer/src/main/java/org/apache/isis/viewer/json/viewer/resources/objects/ActionRepBuilder.java Sun Jul 10 06:51:30 2011
@@ -142,7 +142,7 @@ public class ActionRepBuilder extends Ab
     			return LinkRepBuilder.newObjectBuilder(repContext, objectAdapter, getOidStringifier()).build();
     		}
     	}
-    	return null;
+    	return "{value}";
 	}
 
 }
\ No newline at end of file

Modified: incubator/isis/trunk/framework/viewer/json/viewer/src/main/java/org/apache/isis/viewer/json/viewer/resources/objects/DomainObjectResourceImpl.java
URL: http://svn.apache.org/viewvc/incubator/isis/trunk/framework/viewer/json/viewer/src/main/java/org/apache/isis/viewer/json/viewer/resources/objects/DomainObjectResourceImpl.java?rev=1144784&r1=1144783&r2=1144784&view=diff
==============================================================================
--- incubator/isis/trunk/framework/viewer/json/viewer/src/main/java/org/apache/isis/viewer/json/viewer/resources/objects/DomainObjectResourceImpl.java (original)
+++ incubator/isis/trunk/framework/viewer/json/viewer/src/main/java/org/apache/isis/viewer/json/viewer/resources/objects/DomainObjectResourceImpl.java Sun Jul 10 06:51:30 2011
@@ -17,6 +17,7 @@
 package org.apache.isis.viewer.json.viewer.resources.objects;
 
 import java.io.InputStream;
+import java.util.Collection;
 import java.util.List;
 
 import javax.ws.rs.DELETE;
@@ -30,15 +31,19 @@ import javax.ws.rs.Produces;
 import javax.ws.rs.QueryParam;
 import javax.ws.rs.WebApplicationException;
 import javax.ws.rs.core.MediaType;
+import javax.ws.rs.core.Response;
 
+import org.apache.isis.core.commons.exceptions.NotYetImplementedException;
 import org.apache.isis.core.metamodel.adapter.ObjectAdapter;
+import org.apache.isis.core.metamodel.facets.collections.modify.CollectionFacet;
+import org.apache.isis.core.metamodel.spec.ObjectSpecification;
 import org.apache.isis.core.metamodel.spec.feature.ObjectAction;
 import org.apache.isis.core.metamodel.spec.feature.ObjectAssociation;
+import org.apache.isis.core.metamodel.spec.feature.ObjectMember;
 import org.apache.isis.core.metamodel.spec.feature.OneToManyAssociation;
 import org.apache.isis.core.metamodel.spec.feature.OneToOneAssociation;
 import org.apache.isis.viewer.json.applib.resources.DomainObjectResource;
 import org.apache.isis.viewer.json.viewer.resources.ResourceAbstract;
-import org.apache.isis.viewer.json.viewer.util.UrlDecoderUtils;
 
 @Path("/objects")
 public class DomainObjectResourceImpl extends ResourceAbstract implements DomainObjectResource {
@@ -46,11 +51,12 @@ public class DomainObjectResourceImpl ex
     @GET
     @Path("/{oid}")
     @Produces({ MediaType.APPLICATION_JSON })
-    public String object(@PathParam("oid") final String oidStr) {
-        init();
-        final ObjectAdapter objectAdapter = getObjectAdapter(oidStr);
+    public String object(
+    		@PathParam("oid") final String oidStr) {
+
+    	final ObjectAdapter objectAdapter = getObjectAdapter(oidStr);
 
-        DomainObjectRepBuilder builder = DomainObjectRepBuilder.newBuilder(getResourceContext().repContext(), objectAdapter);
+    	final DomainObjectRepBuilder builder = DomainObjectRepBuilder.newBuilder(getResourceContext().repContext(), objectAdapter);
         return jsonRepresentionFrom(builder);
     }
 
@@ -60,75 +66,116 @@ public class DomainObjectResourceImpl ex
     public String propertyDetails(
         @PathParam("oid") final String oidStr,
         @PathParam("propertyId") final String propertyId) {
-
-        init();
+    	
         final ObjectAdapter objectAdapter = getObjectAdapter(oidStr);
-        ObjectAssociation association = objectAdapter.getSpecification().getAssociation(propertyId);
-        if(association == null || !association.isOneToOneAssociation()) { 
-            throwPropertyNotFoundException(propertyId);
-        }
-        OneToOneAssociation property = (OneToOneAssociation) association;
-        PropertyRepBuilder builder = PropertyRepBuilder.newBuilder(getResourceContext().repContext(), objectAdapter, property);
-        if(!builder.isMemberVisible()) {
-            throwPropertyNotFoundException(propertyId);
-        }
+        final OneToOneAssociation property = getProperty(objectAdapter, propertyId, Intent.ACCESS);
+        
+        final PropertyRepBuilder builder = PropertyRepBuilder.newBuilder(getResourceContext().repContext(), objectAdapter, property);
 
         return jsonRepresentionFrom(builder);
     }
 
-    @PUT
-    @Path("/{oid}/properties/{propertyId}")
+    @GET
+    @Path("/{oid}/collections/{collectionId}")
     @Produces({ MediaType.APPLICATION_JSON })
-    public String modifyProperty(
-        @PathParam("oid") final String oidEncodedStr,
-        @PathParam("propertyId") final String propertyId, 
-        @FormParam("proposedValue") final String proposedValue) {
-
-        init();
-        final String oidStr = UrlDecoderUtils.urlDecode(oidEncodedStr);
+    public String accessCollection(
+        @PathParam("oid") final String oidStr,
+        @PathParam("collectionId") final String collectionId){
+    	
+        final ObjectAdapter objectAdapter = getObjectAdapter(oidStr);
+        final OneToManyAssociation collection = getCollection(objectAdapter, collectionId, Intent.ACCESS);
+        
+        final CollectionRepBuilder builder = CollectionRepBuilder.newBuilder(getResourceContext().repContext(), objectAdapter, collection);
 
-        return null;
+        return jsonRepresentionFrom(builder);
     }
 
-    @DELETE
-    @Path("/{oid}/properties/{propertyId}")
+    @GET
+    @Path("/{oid}/actions/{actionId}")
     @Produces({ MediaType.APPLICATION_JSON })
-    public String clearProperty(
+    public String actionPrompt(
         @PathParam("oid") final String oidStr, 
-        @PathParam("propertyId") final String propertyId){
+        @PathParam("actionId") final String actionId) {
+
+        final ObjectAdapter objectAdapter = getObjectAdapter(oidStr);
+        final ObjectAction action = getObjectAction(objectAdapter, actionId, Intent.ACCESS);
         
-        return null;
+        ActionRepBuilder builder = ActionRepBuilder.newBuilder(getResourceContext().repContext(), objectAdapter, action);
+
+        return jsonRepresentionFrom(builder);
     }
 
     @GET
-    @Path("/{oid}/collections/{collectionId}")
+    @Path("/{oid}/actions/{actionId}/invoke")
     @Produces({ MediaType.APPLICATION_JSON })
-    public String accessCollection(
+    public Object invokeActionIdempotent(
+        @PathParam("oid") String oidStr, 
+        @PathParam("actionId") String actionId, 
+        @QueryParam("argument") List<String> arguments) {
+
+    	final ObjectAdapter objectAdapter = getObjectAdapter(oidStr);
+    	final ObjectAction action = getObjectAction(objectAdapter, actionId, Intent.ACCESS);
+    	
+    	if(action.isContributed()) {
+    		throw new NotYetImplementedException();
+    	}
+    	if(action.getParameterCount() > 0) {
+    		throw new NotYetImplementedException();
+    	}
+    	// TODO: check action is idempotent, else throw exception
+    	
+    	ObjectAdapter[] parameters = new ObjectAdapter[0];
+		ObjectAdapter returnedAdapter = action.execute(objectAdapter, parameters);
+		if(returnedAdapter == null) {
+	        return responseOfOk();
+		}
+		CollectionFacet facet = returnedAdapter.getSpecification().getFacet(CollectionFacet.class);
+		if(facet != null) {
+			Collection<ObjectAdapter> collectionAdapters = facet.collection(returnedAdapter);
+			return jsonRepresentationOf(collectionAdapters);
+		} else {
+			return jsonRepresentationOf(returnedAdapter);
+		}
+    }
+
+
+    @PUT
+    @Path("/{oid}/properties/{propertyId}")
+    @Produces({ MediaType.APPLICATION_JSON })
+    public String modifyProperty(
         @PathParam("oid") final String oidStr,
-        @PathParam("collectionId") final String collectionId){
-        
-        init();
+        @PathParam("propertyId") final String propertyId, 
+        @FormParam("proposedValue") final String proposedValue) {
+    	
         final ObjectAdapter objectAdapter = getObjectAdapter(oidStr);
-        ObjectAssociation association = objectAdapter.getSpecification().getAssociation(collectionId);
-        if(association == null || !association.isOneToManyAssociation()) {
-            throwCollectionNotFoundException(collectionId);
-        }
-        OneToManyAssociation collection = (OneToManyAssociation) association;
-        CollectionRepBuilder builder = CollectionRepBuilder.newBuilder(getResourceContext().repContext(), objectAdapter, collection);
-        if(!builder.isMemberVisible()) {
-            throwCollectionNotFoundException(collectionId);
-        }
+        final OneToOneAssociation property = getProperty(objectAdapter, propertyId, Intent.MUTATE);
 
-        return jsonRepresentionFrom(builder);
+        return null;
     }
 
     @PUT
     @Path("/{oid}/collections/{collectionId}")
     @Produces({ MediaType.APPLICATION_JSON })
-    public String addToCollection(
+    public String addToSet(
         @PathParam("oid") final String oidStr,
         @PathParam("collectionId") final String collectionId,
         @FormParam("proposedValue") final String proposedValueOidStr){
+    	
+        final ObjectAdapter objectAdapter = getObjectAdapter(oidStr);
+        final OneToManyAssociation collection = getCollection(objectAdapter, collectionId, Intent.MUTATE);
+        
+        return null;
+    }
+
+    @DELETE
+    @Path("/{oid}/properties/{propertyId}")
+    @Produces({ MediaType.APPLICATION_JSON })
+    public String clearProperty(
+        @PathParam("oid") final String oidStr, 
+        @PathParam("propertyId") final String propertyId){
+    	
+        final ObjectAdapter objectAdapter = getObjectAdapter(oidStr);
+        final OneToOneAssociation property = getProperty(objectAdapter, propertyId, Intent.MUTATE);
         
         return null;
     }
@@ -140,30 +187,28 @@ public class DomainObjectResourceImpl ex
         @PathParam("oid") final String oidStr,
         @PathParam("collectionId") final String collectionId,
         @FormParam("proposedValue") final String proposedValueOidStr){
+
+    	final ObjectAdapter objectAdapter = getObjectAdapter(oidStr);
+    	final OneToManyAssociation collection = getCollection(objectAdapter, collectionId, Intent.MUTATE);
         
         return null;
     }
 
-    @GET
-    @Path("/{oid}/actions/{actionId}")
+
+    @POST
+    @Path("/{oid}/collections/{collectionId}")
     @Produces({ MediaType.APPLICATION_JSON })
-    public String actionPrompt(
-        @PathParam("oid") final String oidStr, 
-        @PathParam("actionId") final String actionId) {
+    public String addToList(
+        @PathParam("oid") final String oidStr,
+        @PathParam("collectionId") final String collectionId,
+        @FormParam("proposedValue") final String proposedValueOidStr){
 
-        init();
         final ObjectAdapter objectAdapter = getObjectAdapter(oidStr);
-        ObjectAction action = objectAdapter.getSpecification().getObjectAction(actionId);
-        if(action == null) {
-            throwActionNotFoundException(actionId);
-        }
-        ActionRepBuilder builder = ActionRepBuilder.newBuilder(getResourceContext().repContext(), objectAdapter, action);
-        if(!builder.isMemberVisible()) {
-            throwActionNotFoundException(actionId);
-        }
+        final OneToManyAssociation collection = getCollection(objectAdapter, collectionId, Intent.MUTATE);
+        
+        return null;
+	}
 
-        return jsonRepresentionFrom(builder);
-    }
 
     @POST
     @Path("/{oid}/actions/{actionId}/invoke")
@@ -173,46 +218,72 @@ public class DomainObjectResourceImpl ex
         @PathParam("actionId") final String actionId,
         final InputStream body){
 
+        final ObjectAdapter objectAdapter = getObjectAdapter(oidStr);
+        final ObjectAction action = getObjectAction(objectAdapter, actionId, Intent.MUTATE);
+        
         return null;
     }
 
-
-    @GET
-    @Path("/{oid}/actions/{actionId}/invoke")
-    @Produces({ MediaType.APPLICATION_JSON })
-    public String invokeActionIdempotent(
-        @PathParam("oid") String oidStr, 
-        @PathParam("actionId") String actionId, 
-        @QueryParam("argument") List<String> arguments) {
-
-        return null;
-    }
-
-
     
     /////////////////////////////////////////////////////////////////////
-    
-    private void throwPropertyNotFoundException(final String propertyId) {
-        throwNotFoundException(propertyId, MemberType.PROPERTY);
-    }
 
-    private void throwCollectionNotFoundException(final String collectionId) {
-        throwNotFoundException(collectionId, MemberType.COLLECTION);
-    }
+	private enum Intent {
+		ACCESS,
+		MUTATE;
+
+		public boolean isMutate() {
+			return this == MUTATE;
+		}
+	}
+
+	private OneToOneAssociation getProperty(
+			final ObjectAdapter objectAdapter, final String propertyId, final Intent intent) {
+		ObjectAssociation association = objectAdapter.getSpecification().getAssociation(propertyId);
+        if(association == null || !association.isOneToOneAssociation()) { 
+            throwNotFoundException(propertyId, MemberType.PROPERTY);
+        }
+        OneToOneAssociation property = (OneToOneAssociation) association;
+        return ensureVisibleAndUsableForIntent(objectAdapter, property, MemberType.PROPERTY, intent);
+	}
 
-    private void throwActionNotFoundException(final String actionId) {
-        throwNotFoundException(actionId, MemberType.ACTION);
-    }
+	private OneToManyAssociation getCollection(
+			final ObjectAdapter objectAdapter, final String collectionId, final Intent intent) {
+		ObjectAssociation association = objectAdapter.getSpecification().getAssociation(collectionId);
+        if(association == null || !association.isOneToManyAssociation()) {
+            throwNotFoundException(collectionId, MemberType.COLLECTION);
+        }
+        OneToManyAssociation collection = (OneToManyAssociation) association;
+        return ensureVisibleAndUsableForIntent(objectAdapter, collection, MemberType.COLLECTION, intent);
+	}
+
+	private ObjectAction getObjectAction(final ObjectAdapter objectAdapter,
+			final String actionId, Intent intent) {
+		ObjectAction action = objectAdapter.getSpecification().getObjectAction(actionId);
+		return ensureVisibleAndUsableForIntent(objectAdapter, action, MemberType.ACTION, intent);
+	}
+
+	public <T extends ObjectMember> T ensureVisibleAndUsableForIntent(
+			final ObjectAdapter objectAdapter, T objectMember, MemberType memberType, Intent intent) {
+		String memberId = objectMember.getId();
+        if(objectMember.isVisible(getSession(), objectAdapter).isVetoed()) {
+            throwNotFoundException(memberId, memberType);
+        }
+        if(intent.isMutate() && objectMember.isUsable(getSession(), objectAdapter).isVetoed()) {
+        	throwPreconditionFailedException(memberId, memberType);
+        }
+        return objectMember;
+	}
 
 
-    private void throwNotFoundException(final String propertyId, MemberType memberType) {
+    private static void throwNotFoundException(final String memberId, MemberType memberType) {
         String memberTypeStr = memberType.name().toLowerCase();
-        throw new WebApplicationException(responseOfNotFound("No such " +
-                memberTypeStr +
-                "/" +
-                memberTypeStr +
-                " not visible: '" + propertyId + "'"));
+        throw new WebApplicationException(responseOfNotFound(
+                memberTypeStr + " '" + memberId + "' either does not exist or is not visible"));
     }
 
-
+    private static void throwPreconditionFailedException(final String memberId, final MemberType memberType) {
+        String memberTypeStr = memberType.name().toLowerCase();
+        throw new WebApplicationException(responseOfPreconditionFailed(
+                memberTypeStr + " is not usable: '" + memberId + "'"));
+    }
 }

Modified: incubator/isis/trunk/framework/viewer/json/viewer/src/main/java/org/apache/isis/viewer/json/viewer/resources/objects/MemberType.java
URL: http://svn.apache.org/viewvc/incubator/isis/trunk/framework/viewer/json/viewer/src/main/java/org/apache/isis/viewer/json/viewer/resources/objects/MemberType.java?rev=1144784&r1=1144783&r2=1144784&view=diff
==============================================================================
--- incubator/isis/trunk/framework/viewer/json/viewer/src/main/java/org/apache/isis/viewer/json/viewer/resources/objects/MemberType.java (original)
+++ incubator/isis/trunk/framework/viewer/json/viewer/src/main/java/org/apache/isis/viewer/json/viewer/resources/objects/MemberType.java Sun Jul 10 06:51:30 2011
@@ -97,4 +97,12 @@ public enum MemberType {
     public static MemberType lookup(final String memberType) {
     	return valueOf(memberType.toUpperCase());
     }
+
+	public static MemberType of(ObjectMember objectMember) {
+		return objectMember.isAction()?
+				ACTION:
+					objectMember.isOneToOneAssociation()?
+						PROPERTY:
+						COLLECTION;
+	}
 }

Modified: incubator/isis/trunk/framework/viewer/json/viewer/src/main/java/org/apache/isis/viewer/json/viewer/resources/services/ServicesResourceImpl.java
URL: http://svn.apache.org/viewvc/incubator/isis/trunk/framework/viewer/json/viewer/src/main/java/org/apache/isis/viewer/json/viewer/resources/services/ServicesResourceImpl.java?rev=1144784&r1=1144783&r2=1144784&view=diff
==============================================================================
--- incubator/isis/trunk/framework/viewer/json/viewer/src/main/java/org/apache/isis/viewer/json/viewer/resources/services/ServicesResourceImpl.java (original)
+++ incubator/isis/trunk/framework/viewer/json/viewer/src/main/java/org/apache/isis/viewer/json/viewer/resources/services/ServicesResourceImpl.java Sun Jul 10 06:51:30 2011
@@ -48,19 +48,9 @@ public class ServicesResourceImpl extend
     public String services() {
         init();
 
-        return asJson(serviceSelfRepresentations());
-    }
-
-    protected List<Representation> serviceSelfRepresentations() {
         final List<ObjectAdapter> serviceAdapters = getPersistenceSession().getServices();
-        RepContext representationContext = getResourceContext().repContext();
-        
-        Function<ObjectAdapter, Representation> objectSelfRepresentation = 
-            Functions.compose(
-                DomainObjectRepBuilder.selfOf(), 
-                DomainObjectRepBuilder.fromAdapter(representationContext));
-        return Lists.newArrayList(
-            Collections2.transform(serviceAdapters, objectSelfRepresentation));
+		return jsonRepresentationOf(serviceAdapters);
     }
 
+
 }