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/13 07:46:14 UTC
svn commit: r1145867 - in /incubator/isis/trunk/framework:
core/metamodel/src/main/java/org/apache/isis/core/metamodel/spec/feature/
core/metamodel/src/main/java/org/apache/isis/core/metamodel/specloader/
core/metamodel/src/main/java/org/apache/isis/co...
Author: danhaywood
Date: Wed Jul 13 05:46:13 2011
New Revision: 1145867
URL: http://svn.apache.org/viewvc?rev=1145867&view=rev
Log:
json viewer: implemented basic versions of the remaining object resource implementations (not tested yet); introduced concept of CollectionSemantics (provided by CollectionTypeRegistry) in order to verify put/post against set/list
Modified:
incubator/isis/trunk/framework/core/metamodel/src/main/java/org/apache/isis/core/metamodel/spec/feature/ObjectMemberContext.java
incubator/isis/trunk/framework/core/metamodel/src/main/java/org/apache/isis/core/metamodel/spec/feature/OneToManyFeature.java
incubator/isis/trunk/framework/core/metamodel/src/main/java/org/apache/isis/core/metamodel/spec/feature/OneToOneAssociation.java
incubator/isis/trunk/framework/core/metamodel/src/main/java/org/apache/isis/core/metamodel/specloader/ObjectReflectorDefault.java
incubator/isis/trunk/framework/core/metamodel/src/main/java/org/apache/isis/core/metamodel/specloader/collectiontyperegistry/CollectionTypeRegistry.java
incubator/isis/trunk/framework/core/metamodel/src/main/java/org/apache/isis/core/metamodel/specloader/collectiontyperegistry/CollectionTypeRegistryDefault.java
incubator/isis/trunk/framework/core/metamodel/src/main/java/org/apache/isis/core/metamodel/specloader/specimpl/ObjectMemberAbstract.java
incubator/isis/trunk/framework/core/metamodel/src/main/java/org/apache/isis/core/metamodel/specloader/specimpl/OneToManyAssociationImpl.java
incubator/isis/trunk/framework/core/metamodel/src/main/java/org/apache/isis/core/metamodel/specloader/specimpl/OneToOneAssociationImpl.java
incubator/isis/trunk/framework/core/metamodel/src/test/java/org/apache/isis/core/metamodel/specloader/specimpl/ObjectAssociationAbstractTest.java
incubator/isis/trunk/framework/runtimes/dflt/runtime/src/test/java/org/apache/isis/runtimes/dflt/runtime/system/ObjectActionImplTest.java
incubator/isis/trunk/framework/runtimes/dflt/runtime/src/test/java/org/apache/isis/runtimes/dflt/runtime/system/ObjectMemberAbstractTest.java
incubator/isis/trunk/framework/runtimes/dflt/runtime/src/test/java/org/apache/isis/runtimes/dflt/runtime/system/OneToManyAssociationImplTest.java
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/objects/DomainObjectResourceImpl.java
Modified: incubator/isis/trunk/framework/core/metamodel/src/main/java/org/apache/isis/core/metamodel/spec/feature/ObjectMemberContext.java
URL: http://svn.apache.org/viewvc/incubator/isis/trunk/framework/core/metamodel/src/main/java/org/apache/isis/core/metamodel/spec/feature/ObjectMemberContext.java?rev=1145867&r1=1145866&r2=1145867&view=diff
==============================================================================
--- incubator/isis/trunk/framework/core/metamodel/src/main/java/org/apache/isis/core/metamodel/spec/feature/ObjectMemberContext.java (original)
+++ incubator/isis/trunk/framework/core/metamodel/src/main/java/org/apache/isis/core/metamodel/spec/feature/ObjectMemberContext.java Wed Jul 13 05:46:13 2011
@@ -20,6 +20,7 @@ import org.apache.isis.core.commons.auth
import org.apache.isis.core.metamodel.adapter.QuerySubmitter;
import org.apache.isis.core.metamodel.adapter.map.AdapterMap;
import org.apache.isis.core.metamodel.spec.SpecificationLookup;
+import org.apache.isis.core.metamodel.specloader.collectiontyperegistry.CollectionTypeRegistry;
public class ObjectMemberContext {
@@ -27,14 +28,20 @@ public class ObjectMemberContext {
private final SpecificationLookup specificationLookup;
private final AdapterMap adapterManager;
private final QuerySubmitter querySubmitter;
+ private final CollectionTypeRegistry collectionTypeRegistry;
- public ObjectMemberContext(final AuthenticationSessionProvider authenticationSessionProvider,
- final SpecificationLookup specificationLookup, final AdapterMap adapterManager,
- final QuerySubmitter querySubmitter) {
+ public ObjectMemberContext(
+ final AuthenticationSessionProvider authenticationSessionProvider,
+ final SpecificationLookup specificationLookup,
+ final AdapterMap adapterManager,
+ final QuerySubmitter querySubmitter,
+ final CollectionTypeRegistry collectionTypeRegistry) {
+
this.authenticationSessionProvider = authenticationSessionProvider;
this.specificationLookup = specificationLookup;
this.adapterManager = adapterManager;
this.querySubmitter = querySubmitter;
+ this.collectionTypeRegistry = collectionTypeRegistry;
}
public AuthenticationSessionProvider getAuthenticationSessionProvider() {
@@ -52,4 +59,8 @@ public class ObjectMemberContext {
public QuerySubmitter getQuerySubmitter() {
return querySubmitter;
}
+
+ public CollectionTypeRegistry getCollectionTypeRegistry() {
+ return collectionTypeRegistry;
+ }
}
\ No newline at end of file
Modified: incubator/isis/trunk/framework/core/metamodel/src/main/java/org/apache/isis/core/metamodel/spec/feature/OneToManyFeature.java
URL: http://svn.apache.org/viewvc/incubator/isis/trunk/framework/core/metamodel/src/main/java/org/apache/isis/core/metamodel/spec/feature/OneToManyFeature.java?rev=1145867&r1=1145866&r2=1145867&view=diff
==============================================================================
--- incubator/isis/trunk/framework/core/metamodel/src/main/java/org/apache/isis/core/metamodel/spec/feature/OneToManyFeature.java (original)
+++ incubator/isis/trunk/framework/core/metamodel/src/main/java/org/apache/isis/core/metamodel/spec/feature/OneToManyFeature.java Wed Jul 13 05:46:13 2011
@@ -19,6 +19,10 @@
package org.apache.isis.core.metamodel.spec.feature;
+import java.util.Collection;
+import java.util.Queue;
+
+
/**
* Base interface for {@link OneToManyAssociation} only.
*
@@ -27,9 +31,31 @@ package org.apache.isis.core.metamodel.s
* the base interface for a <tt>OneToManyActionParameter</tt>.
*
* <p>
- * Is also the route upto the {@link ObjectFeature} superinterface.
+ * Is also the route up to the {@link ObjectFeature} superinterface.
*
*/
public interface OneToManyFeature extends ObjectFeature {
+ public enum CollectionSemantics {
+ LIST,
+ ARRAY,
+ SET,
+ OTHER;
+
+ /**
+ * The corresponding class is not a subclass of {@link Collection}.
+ */
+ public boolean isArray() { return this == ARRAY; }
+ public boolean isList() { return this == LIST; }
+ public boolean isSet() { return this == SET; }
+ /**
+ * For example, {@link Queue}, or some other 3rdparty implementation of {@link Collection}.
+ */
+ public boolean isOther() { return this == OTHER; }
+ public boolean isListOrArray() {
+ return isList() || isArray();
+ }
+ }
+
+ CollectionSemantics getCollectionSemantics();
}
Modified: incubator/isis/trunk/framework/core/metamodel/src/main/java/org/apache/isis/core/metamodel/spec/feature/OneToOneAssociation.java
URL: http://svn.apache.org/viewvc/incubator/isis/trunk/framework/core/metamodel/src/main/java/org/apache/isis/core/metamodel/spec/feature/OneToOneAssociation.java?rev=1145867&r1=1145866&r2=1145867&view=diff
==============================================================================
--- incubator/isis/trunk/framework/core/metamodel/src/main/java/org/apache/isis/core/metamodel/spec/feature/OneToOneAssociation.java (original)
+++ incubator/isis/trunk/framework/core/metamodel/src/main/java/org/apache/isis/core/metamodel/spec/feature/OneToOneAssociation.java Wed Jul 13 05:46:13 2011
@@ -69,8 +69,10 @@ public interface OneToOneAssociation ext
* back-links or bidirectional association). To initialise a recreated object to this logical state the
* <code>initAssociation</code> method should be used on each of the objects.
*
+ * @deprecated - see {@link #set(ObjectAdapter, ObjectAdapter)}
* @see #initAssociation(ObjectAdapter, ObjectAdapter)
*/
+ @Deprecated
void setAssociation(ObjectAdapter inObject, ObjectAdapter associate);
/**
@@ -78,7 +80,9 @@ public interface OneToOneAssociation ext
* back-link.
*
* @see #setAssociation(ObjectAdapter, ObjectAdapter)
+ * @deprecated - see {@link #set(ObjectAdapter, ObjectAdapter)}
*/
+ @Deprecated
void clearAssociation(ObjectAdapter inObject);
}
Modified: incubator/isis/trunk/framework/core/metamodel/src/main/java/org/apache/isis/core/metamodel/specloader/ObjectReflectorDefault.java
URL: http://svn.apache.org/viewvc/incubator/isis/trunk/framework/core/metamodel/src/main/java/org/apache/isis/core/metamodel/specloader/ObjectReflectorDefault.java?rev=1145867&r1=1145866&r2=1145867&view=diff
==============================================================================
--- incubator/isis/trunk/framework/core/metamodel/src/main/java/org/apache/isis/core/metamodel/specloader/ObjectReflectorDefault.java (original)
+++ incubator/isis/trunk/framework/core/metamodel/src/main/java/org/apache/isis/core/metamodel/specloader/ObjectReflectorDefault.java Wed Jul 13 05:46:13 2011
@@ -395,7 +395,7 @@ public class ObjectReflectorDefault impl
final AdapterMap adapterMap = getRuntimeContext().getAdapterMap();
final ObjectMemberContext objectMemberContext =
new ObjectMemberContext(authenticationSessionProvider, specificationLookup, adapterMap,
- getRuntimeContext().getQuerySubmitter());
+ getRuntimeContext().getQuerySubmitter(), collectionTypeRegistry);
final IntrospectionContext introspectionContext =
new IntrospectionContext(getClassSubstitutor(), getMemberLayoutArranger());
final DependencyInjector dependencyInjector = getRuntimeContext().getDependencyInjector();
Modified: incubator/isis/trunk/framework/core/metamodel/src/main/java/org/apache/isis/core/metamodel/specloader/collectiontyperegistry/CollectionTypeRegistry.java
URL: http://svn.apache.org/viewvc/incubator/isis/trunk/framework/core/metamodel/src/main/java/org/apache/isis/core/metamodel/specloader/collectiontyperegistry/CollectionTypeRegistry.java?rev=1145867&r1=1145866&r2=1145867&view=diff
==============================================================================
--- incubator/isis/trunk/framework/core/metamodel/src/main/java/org/apache/isis/core/metamodel/specloader/collectiontyperegistry/CollectionTypeRegistry.java (original)
+++ incubator/isis/trunk/framework/core/metamodel/src/main/java/org/apache/isis/core/metamodel/specloader/collectiontyperegistry/CollectionTypeRegistry.java Wed Jul 13 05:46:13 2011
@@ -21,6 +21,7 @@ package org.apache.isis.core.metamodel.s
import org.apache.isis.core.commons.components.ApplicationScopedComponent;
import org.apache.isis.core.commons.components.Injectable;
+import org.apache.isis.core.metamodel.spec.feature.OneToManyFeature.CollectionSemantics;
/**
* TODO: plan is to allow new collection types to be installed dynamically, allowing the domain programmer to declare
@@ -39,4 +40,6 @@ public interface CollectionTypeRegistry
public Class<?>[] getCollectionType();
+ public CollectionSemantics semanticsOf(Class<?> cls);
+
}
Modified: incubator/isis/trunk/framework/core/metamodel/src/main/java/org/apache/isis/core/metamodel/specloader/collectiontyperegistry/CollectionTypeRegistryDefault.java
URL: http://svn.apache.org/viewvc/incubator/isis/trunk/framework/core/metamodel/src/main/java/org/apache/isis/core/metamodel/specloader/collectiontyperegistry/CollectionTypeRegistryDefault.java?rev=1145867&r1=1145866&r2=1145867&view=diff
==============================================================================
--- incubator/isis/trunk/framework/core/metamodel/src/main/java/org/apache/isis/core/metamodel/specloader/collectiontyperegistry/CollectionTypeRegistryDefault.java (original)
+++ incubator/isis/trunk/framework/core/metamodel/src/main/java/org/apache/isis/core/metamodel/specloader/collectiontyperegistry/CollectionTypeRegistryDefault.java Wed Jul 13 05:46:13 2011
@@ -22,6 +22,9 @@ package org.apache.isis.core.metamodel.s
import java.util.ArrayList;
import java.util.Collection;
import java.util.List;
+import java.util.Set;
+
+import org.apache.isis.core.metamodel.spec.feature.OneToManyFeature.CollectionSemantics;
public class CollectionTypeRegistryDefault extends CollectionTypeRegistryAbstract {
@@ -61,4 +64,18 @@ public class CollectionTypeRegistryDefau
return collectionTypesAsArray;
}
+ public CollectionSemantics semanticsOf(Class<?> underlyingClass) {
+ if(!Collection.class.isAssignableFrom(underlyingClass)) {
+ return CollectionSemantics.ARRAY;
+ }
+ if(List.class.isAssignableFrom(underlyingClass)) {
+ return CollectionSemantics.LIST;
+ }
+ if(Set.class.isAssignableFrom(underlyingClass)) {
+ return CollectionSemantics.SET;
+ }
+ return CollectionSemantics.OTHER;
+ }
+
+
}
Modified: incubator/isis/trunk/framework/core/metamodel/src/main/java/org/apache/isis/core/metamodel/specloader/specimpl/ObjectMemberAbstract.java
URL: http://svn.apache.org/viewvc/incubator/isis/trunk/framework/core/metamodel/src/main/java/org/apache/isis/core/metamodel/specloader/specimpl/ObjectMemberAbstract.java?rev=1145867&r1=1145866&r2=1145867&view=diff
==============================================================================
--- incubator/isis/trunk/framework/core/metamodel/src/main/java/org/apache/isis/core/metamodel/specloader/specimpl/ObjectMemberAbstract.java (original)
+++ incubator/isis/trunk/framework/core/metamodel/src/main/java/org/apache/isis/core/metamodel/specloader/specimpl/ObjectMemberAbstract.java Wed Jul 13 05:46:13 2011
@@ -49,6 +49,7 @@ import org.apache.isis.core.metamodel.sp
import org.apache.isis.core.metamodel.spec.SpecificationLookup;
import org.apache.isis.core.metamodel.spec.feature.ObjectMember;
import org.apache.isis.core.metamodel.spec.feature.ObjectMemberContext;
+import org.apache.isis.core.metamodel.specloader.collectiontyperegistry.CollectionTypeRegistry;
public abstract class ObjectMemberAbstract implements ObjectMember {
@@ -65,9 +66,10 @@ public abstract class ObjectMemberAbstra
private final SpecificationLookup specificationLookup;
private final AdapterMap adapterMap;
private final QuerySubmitter querySubmitter;
+ private final CollectionTypeRegistry collectionTypeRegistry;
protected ObjectMemberAbstract(final FacetedMethod facetedMethod, final FeatureType featureType,
- final ObjectMemberContext objectMembercontext) {
+ final ObjectMemberContext objectMemberContext) {
final String id = facetedMethod.getIdentifier().getMemberName();
if (id == null) {
throw new IllegalArgumentException("Name must always be set");
@@ -77,10 +79,11 @@ public abstract class ObjectMemberAbstra
this.id = id;
this.defaultName = NameUtils.naturalName(this.id);
- this.authenticationSessionProvider = objectMembercontext.getAuthenticationSessionProvider();
- this.specificationLookup = objectMembercontext.getSpecificationLookup();
- this.adapterMap = objectMembercontext.getAdapterManager();
- this.querySubmitter = objectMembercontext.getQuerySubmitter();
+ this.authenticationSessionProvider = objectMemberContext.getAuthenticationSessionProvider();
+ this.specificationLookup = objectMemberContext.getSpecificationLookup();
+ this.adapterMap = objectMemberContext.getAdapterManager();
+ this.querySubmitter = objectMemberContext.getQuerySubmitter();
+ this.collectionTypeRegistry = objectMemberContext.getCollectionTypeRegistry();
}
// /////////////////////////////////////////////////////////////
@@ -302,4 +305,7 @@ public abstract class ObjectMemberAbstra
return querySubmitter;
}
+ public CollectionTypeRegistry getCollectionTypeRegistry() {
+ return collectionTypeRegistry;
+ }
}
Modified: incubator/isis/trunk/framework/core/metamodel/src/main/java/org/apache/isis/core/metamodel/specloader/specimpl/OneToManyAssociationImpl.java
URL: http://svn.apache.org/viewvc/incubator/isis/trunk/framework/core/metamodel/src/main/java/org/apache/isis/core/metamodel/specloader/specimpl/OneToManyAssociationImpl.java?rev=1145867&r1=1145866&r2=1145867&view=diff
==============================================================================
--- incubator/isis/trunk/framework/core/metamodel/src/main/java/org/apache/isis/core/metamodel/specloader/specimpl/OneToManyAssociationImpl.java (original)
+++ incubator/isis/trunk/framework/core/metamodel/src/main/java/org/apache/isis/core/metamodel/specloader/specimpl/OneToManyAssociationImpl.java Wed Jul 13 05:46:13 2011
@@ -54,6 +54,12 @@ public class OneToManyAssociationImpl ex
facetedMethod.getType()), objectMemberContext);
}
+ @Override
+ public CollectionSemantics getCollectionSemantics() {
+ Class<?> underlyingClass = getSpecification().getCorrespondingClass();
+ return getCollectionTypeRegistry().semanticsOf(underlyingClass);
+ }
+
// /////////////////////////////////////////////////////////////
// Hidden (or visible)
// /////////////////////////////////////////////////////////////
@@ -263,4 +269,5 @@ public class OneToManyAssociationImpl ex
return str.toString();
}
+
}
Modified: incubator/isis/trunk/framework/core/metamodel/src/main/java/org/apache/isis/core/metamodel/specloader/specimpl/OneToOneAssociationImpl.java
URL: http://svn.apache.org/viewvc/incubator/isis/trunk/framework/core/metamodel/src/main/java/org/apache/isis/core/metamodel/specloader/specimpl/OneToOneAssociationImpl.java?rev=1145867&r1=1145866&r2=1145867&view=diff
==============================================================================
--- incubator/isis/trunk/framework/core/metamodel/src/main/java/org/apache/isis/core/metamodel/specloader/specimpl/OneToOneAssociationImpl.java (original)
+++ incubator/isis/trunk/framework/core/metamodel/src/main/java/org/apache/isis/core/metamodel/specloader/specimpl/OneToOneAssociationImpl.java Wed Jul 13 05:46:13 2011
@@ -159,28 +159,47 @@ public class OneToOneAssociationImpl ext
@Override
public void set(final ObjectAdapter ownerAdapter, final ObjectAdapter newReferencedAdapter) {
if (newReferencedAdapter != null) {
- setAssociation(ownerAdapter, newReferencedAdapter);
+ setValue(ownerAdapter, newReferencedAdapter);
} else {
- clearAssociation(ownerAdapter);
+ clearValue(ownerAdapter);
}
}
+ /**
+ * @see #set(ObjectAdapter, ObjectAdapter)
+ */
+ @Deprecated
@Override
public void setAssociation(final ObjectAdapter ownerAdapter, final ObjectAdapter newReferencedAdapter) {
- final PropertySetterFacet setterFacet = getFacet(PropertySetterFacet.class);
- if (setterFacet != null) {
- if (ownerAdapter.isPersistent() && newReferencedAdapter != null && newReferencedAdapter.isTransient()
- && !newReferencedAdapter.getSpecification().isAggregated()) {
- // TODO: move to facet ?
- throw new IsisException("can't set a reference to a transient object from a persistent one: "
- + newReferencedAdapter.titleString() + " (transient)");
- }
- setterFacet.setProperty(ownerAdapter, newReferencedAdapter);
- }
+ setValue(ownerAdapter, newReferencedAdapter);
}
+ private void setValue(final ObjectAdapter ownerAdapter, final ObjectAdapter newReferencedAdapter) {
+ final PropertySetterFacet setterFacet = getFacet(PropertySetterFacet.class);
+ if (setterFacet == null) {
+ return;
+ }
+ if (ownerAdapter.isPersistent() &&
+ newReferencedAdapter != null &&
+ newReferencedAdapter.isTransient() &&
+ !newReferencedAdapter.getSpecification().isAggregated()) {
+ // TODO: move to facet ?
+ throw new IsisException("can't set a reference to a transient object from a persistent one: "
+ + newReferencedAdapter.titleString() + " (transient)");
+ }
+ setterFacet.setProperty(ownerAdapter, newReferencedAdapter);
+ }
+
+ /**
+ * @see #set(ObjectAdapter, ObjectAdapter)
+ */
+ @Deprecated
@Override
public void clearAssociation(final ObjectAdapter ownerAdapter) {
+ clearValue(ownerAdapter);
+ }
+
+ private void clearValue(final ObjectAdapter ownerAdapter) {
final PropertyClearFacet facet = getFacet(PropertyClearFacet.class);
facet.clearProperty(ownerAdapter);
}
Modified: incubator/isis/trunk/framework/core/metamodel/src/test/java/org/apache/isis/core/metamodel/specloader/specimpl/ObjectAssociationAbstractTest.java
URL: http://svn.apache.org/viewvc/incubator/isis/trunk/framework/core/metamodel/src/test/java/org/apache/isis/core/metamodel/specloader/specimpl/ObjectAssociationAbstractTest.java?rev=1145867&r1=1145866&r2=1145867&view=diff
==============================================================================
--- incubator/isis/trunk/framework/core/metamodel/src/test/java/org/apache/isis/core/metamodel/specloader/specimpl/ObjectAssociationAbstractTest.java (original)
+++ incubator/isis/trunk/framework/core/metamodel/src/test/java/org/apache/isis/core/metamodel/specloader/specimpl/ObjectAssociationAbstractTest.java Wed Jul 13 05:46:13 2011
@@ -71,7 +71,7 @@ public class ObjectAssociationAbstractTe
facetedMethod = FacetedMethod.createProperty(Customer.class, "firstName");
objectAssociation =
new ObjectAssociationAbstract(facetedMethod, FeatureType.PROPERTY, new TestProxySpecification("test"),
- new ObjectMemberContext(null, null, null, null)) {
+ new ObjectMemberContext(null, null, null, null, null)) {
@Override
public ObjectAdapter get(final ObjectAdapter fromObject) {
Modified: incubator/isis/trunk/framework/runtimes/dflt/runtime/src/test/java/org/apache/isis/runtimes/dflt/runtime/system/ObjectActionImplTest.java
URL: http://svn.apache.org/viewvc/incubator/isis/trunk/framework/runtimes/dflt/runtime/src/test/java/org/apache/isis/runtimes/dflt/runtime/system/ObjectActionImplTest.java?rev=1145867&r1=1145866&r2=1145867&view=diff
==============================================================================
--- incubator/isis/trunk/framework/runtimes/dflt/runtime/src/test/java/org/apache/isis/runtimes/dflt/runtime/system/ObjectActionImplTest.java (original)
+++ incubator/isis/trunk/framework/runtimes/dflt/runtime/src/test/java/org/apache/isis/runtimes/dflt/runtime/system/ObjectActionImplTest.java Wed Jul 13 05:46:13 2011
@@ -35,6 +35,7 @@ import org.apache.isis.core.metamodel.fa
import org.apache.isis.core.metamodel.spec.ObjectSpecification;
import org.apache.isis.core.metamodel.spec.SpecificationLookup;
import org.apache.isis.core.metamodel.spec.feature.ObjectMemberContext;
+import org.apache.isis.core.metamodel.specloader.collectiontyperegistry.CollectionTypeRegistry;
import org.apache.isis.core.metamodel.specloader.specimpl.ObjectActionImpl;
import org.apache.isis.runtimes.dflt.runtime.testsystem.ProxyJunit3TestCase;
import org.apache.isis.runtimes.dflt.runtime.testsystem.TestProxyAdapter;
@@ -68,6 +69,7 @@ public class ObjectActionImplTest extend
private AdapterMap mockAdapterManager;
private ServicesProvider mockServicesProvider;
private QuerySubmitter mockQuerySubmitter;
+ private CollectionTypeRegistry mockCollectionTypeRegistry;
@Override
@Before
@@ -80,6 +82,7 @@ public class ObjectActionImplTest extend
mockAdapterManager = mockery.mock(AdapterMap.class);
mockServicesProvider = mockery.mock(ServicesProvider.class);
mockQuerySubmitter = mockery.mock(QuerySubmitter.class);
+ mockCollectionTypeRegistry = mockery.mock(CollectionTypeRegistry.class);
mockery.checking(new Expectations() {
{
@@ -90,7 +93,7 @@ public class ObjectActionImplTest extend
action =
new ObjectActionImpl(mockFacetedMethod, new ObjectMemberContext(mockAuthenticationSessionProvider,
- mockSpecificationLookup, mockAdapterManager, mockQuerySubmitter), mockServicesProvider);
+ mockSpecificationLookup, mockAdapterManager, mockQuerySubmitter, mockCollectionTypeRegistry), mockServicesProvider);
}
@Test
Modified: incubator/isis/trunk/framework/runtimes/dflt/runtime/src/test/java/org/apache/isis/runtimes/dflt/runtime/system/ObjectMemberAbstractTest.java
URL: http://svn.apache.org/viewvc/incubator/isis/trunk/framework/runtimes/dflt/runtime/src/test/java/org/apache/isis/runtimes/dflt/runtime/system/ObjectMemberAbstractTest.java?rev=1145867&r1=1145866&r2=1145867&view=diff
==============================================================================
--- incubator/isis/trunk/framework/runtimes/dflt/runtime/src/test/java/org/apache/isis/runtimes/dflt/runtime/system/ObjectMemberAbstractTest.java (original)
+++ incubator/isis/trunk/framework/runtimes/dflt/runtime/src/test/java/org/apache/isis/runtimes/dflt/runtime/system/ObjectMemberAbstractTest.java Wed Jul 13 05:46:13 2011
@@ -204,7 +204,7 @@ class ObjectMemberAbstractImpl extends O
protected ObjectMemberAbstractImpl(final String id) {
super(FacetedMethod.createProperty(Customer.class, "firstName"), FeatureType.PROPERTY, new ObjectMemberContext(
- null, null, null, null));
+ null, null, null, null, null));
}
@Override
Modified: incubator/isis/trunk/framework/runtimes/dflt/runtime/src/test/java/org/apache/isis/runtimes/dflt/runtime/system/OneToManyAssociationImplTest.java
URL: http://svn.apache.org/viewvc/incubator/isis/trunk/framework/runtimes/dflt/runtime/src/test/java/org/apache/isis/runtimes/dflt/runtime/system/OneToManyAssociationImplTest.java?rev=1145867&r1=1145866&r2=1145867&view=diff
==============================================================================
--- incubator/isis/trunk/framework/runtimes/dflt/runtime/src/test/java/org/apache/isis/runtimes/dflt/runtime/system/OneToManyAssociationImplTest.java (original)
+++ incubator/isis/trunk/framework/runtimes/dflt/runtime/src/test/java/org/apache/isis/runtimes/dflt/runtime/system/OneToManyAssociationImplTest.java Wed Jul 13 05:46:13 2011
@@ -36,6 +36,7 @@ import org.apache.isis.core.metamodel.sp
import org.apache.isis.core.metamodel.spec.SpecificationLookup;
import org.apache.isis.core.metamodel.spec.feature.ObjectMemberContext;
import org.apache.isis.core.metamodel.spec.feature.OneToManyAssociation;
+import org.apache.isis.core.metamodel.specloader.collectiontyperegistry.CollectionTypeRegistry;
import org.apache.isis.core.metamodel.specloader.specimpl.OneToManyAssociationImpl;
import org.jmock.Expectations;
import org.jmock.Mockery;
@@ -78,6 +79,7 @@ public class OneToManyAssociationImplTes
private NamedFacet mockNamedFacet;
private CollectionAddToFacet mockCollectionAddToFacet;
+ private CollectionTypeRegistry mockCollectionTypeRegistry;
@Before
public void setUp() {
@@ -89,6 +91,7 @@ public class OneToManyAssociationImplTes
mockSpecificationLookup = context.mock(SpecificationLookup.class);
mockAdapterManager = context.mock(AdapterMap.class);
mockQuerySubmitter = context.mock(QuerySubmitter.class);
+ mockCollectionTypeRegistry = context.mock(CollectionTypeRegistry.class);
mockPeer = context.mock(FacetedMethod.class);
mockNamedFacet = context.mock(NamedFacet.class);
@@ -99,7 +102,7 @@ public class OneToManyAssociationImplTes
allowingSpecLoaderToReturnSpecs();
association =
new OneToManyAssociationImpl(mockPeer, new ObjectMemberContext(mockAuthenticationSessionProvider,
- mockSpecificationLookup, mockAdapterManager, mockQuerySubmitter));
+ mockSpecificationLookup, mockAdapterManager, mockQuerySubmitter, mockCollectionTypeRegistry));
}
private void allowingSpecLoaderToReturnSpecs() {
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=1145867&r1=1145866&r2=1145867&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 Wed Jul 13 05:46:13 2011
@@ -22,7 +22,6 @@ import java.io.InputStream;
import java.util.List;
import javax.ws.rs.DELETE;
-import javax.ws.rs.FormParam;
import javax.ws.rs.GET;
import javax.ws.rs.POST;
import javax.ws.rs.PUT;
@@ -31,6 +30,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 {
@@ -72,42 +72,41 @@ public interface DomainObjectResource {
@PUT
@Path("/{oid}/properties{propertyId}")
@Produces({ MediaType.APPLICATION_JSON })
- public Object modifyProperty(
+ public Response modifyProperty(
@PathParam("oid") final String oidStr,
@PathParam("propertyId") final String propertyId,
- @FormParam("proposedValue") final String proposedValue);
+ final InputStream body);
@PUT
@Path("/{oid}/collections/{collectionId}")
@Produces({ MediaType.APPLICATION_JSON })
- public String addToSet(
+ public Response addToSet(
@PathParam("oid") final String oidStr,
@PathParam("collectionId") final String collectionId,
- @FormParam("proposedValue") final String proposedValueOidStr);
+ final InputStream body);
@DELETE
@Path("/{oid}/properties/{propertyId}")
@Produces({ MediaType.APPLICATION_JSON })
- public String clearProperty(
+ public Response clearProperty(
@PathParam("oid") final String oidStr,
@PathParam("propertyId") final String propertyId);
@DELETE
@Path("/{oid}/collections/{collectionId}")
@Produces({ MediaType.APPLICATION_JSON })
- public String removeFromCollection(
+ public Response removeFromCollection(
@PathParam("oid") final String oidStr,
@PathParam("collectionId") final String collectionId,
- @FormParam("proposedValue") final String proposedValueOidStr);
+ final InputStream body);
@POST
@Path("/{oid}/collections/{collectionId}")
@Produces({ MediaType.APPLICATION_JSON })
- public String addToList(
+ public Response addToList(
@PathParam("oid") final String oidStr,
@PathParam("collectionId") final String collectionId,
- @FormParam("proposedValue") final String proposedValueOidStr);
-
+ final InputStream body);
@POST
@Path("/{oid}/actions/{actionId}/invoke")
@@ -116,7 +115,4 @@ public interface DomainObjectResource {
@PathParam("oid") final String oidStr,
@PathParam("actionId") final String actionId,
final InputStream body);
-
-
-
}
\ 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=1145867&r1=1145866&r2=1145867&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 Wed Jul 13 05:46:13 2011
@@ -25,7 +25,6 @@ import java.util.List;
import java.util.Map;
import javax.ws.rs.DELETE;
-import javax.ws.rs.FormParam;
import javax.ws.rs.GET;
import javax.ws.rs.POST;
import javax.ws.rs.PUT;
@@ -35,10 +34,10 @@ 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.metamodel.adapter.ObjectAdapter;
import org.apache.isis.core.metamodel.consent.Consent;
-import org.apache.isis.core.metamodel.consent.InteractionInvocationMethod;
import org.apache.isis.core.metamodel.facets.collections.modify.CollectionFacet;
import org.apache.isis.core.metamodel.facets.object.encodeable.EncodableFacet;
import org.apache.isis.core.metamodel.facets.object.value.ValueFacet;
@@ -50,7 +49,6 @@ import org.apache.isis.core.metamodel.sp
import org.apache.isis.core.metamodel.spec.feature.ObjectMember;
import org.apache.isis.core.metamodel.spec.feature.OneToManyAssociation;
import org.apache.isis.core.metamodel.spec.feature.OneToOneAssociation;
-import org.apache.isis.core.progmodel.facets.properties.modify.PropertyModifyFacetFactory;
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;
@@ -62,18 +60,17 @@ import com.google.common.collect.Lists;
import com.google.common.io.ByteStreams;
@Path("/objects")
-public class DomainObjectResourceImpl extends ResourceAbstract implements DomainObjectResource {
+public class DomainObjectResourceImpl extends ResourceAbstract implements
+ DomainObjectResource {
-
- @GET
+ @GET
@Path("/{oid}")
@Produces({ MediaType.APPLICATION_JSON })
- public String object(
- @PathParam("oid") final String oidStr) {
+ public String object(@PathParam("oid") final String oidStr) {
- final ObjectAdapter objectAdapter = getObjectAdapter(oidStr);
-
- final DomainObjectRepBuilder builder = DomainObjectRepBuilder.newBuilder(getResourceContext().repContext(), objectAdapter);
+ final ObjectAdapter objectAdapter = getObjectAdapter(oidStr);
+ final DomainObjectRepBuilder builder = DomainObjectRepBuilder
+ .newBuilder(getResourceContext().repContext(), objectAdapter);
return jsonRepresentionFrom(builder);
}
@@ -83,11 +80,13 @@ public class DomainObjectResourceImpl ex
public String propertyDetails(
@PathParam("oid") final String oidStr,
@PathParam("propertyId") final String propertyId) {
-
+
final ObjectAdapter objectAdapter = getObjectAdapter(oidStr);
- final OneToOneAssociation property = getPropertyThatIsVisibleAndUsable(objectAdapter, propertyId, Intent.ACCESS);
-
- final PropertyRepBuilder builder = PropertyRepBuilder.newBuilder(getResourceContext().repContext(), objectAdapter, property);
+ final OneToOneAssociation property = getPropertyThatIsVisibleAndUsable(
+ objectAdapter, propertyId, Intent.ACCESS);
+
+ final PropertyRepBuilder builder = PropertyRepBuilder.newBuilder(
+ getResourceContext().repContext(), objectAdapter, property);
return jsonRepresentionFrom(builder);
}
@@ -96,12 +95,14 @@ public class DomainObjectResourceImpl ex
@Produces({ MediaType.APPLICATION_JSON })
public String accessCollection(
@PathParam("oid") final String oidStr,
- @PathParam("collectionId") final String collectionId){
-
+ @PathParam("collectionId") final String collectionId) {
+
final ObjectAdapter objectAdapter = getObjectAdapter(oidStr);
- final OneToManyAssociation collection = getCollectionThatIsVisibleAndUsable(objectAdapter, collectionId, Intent.ACCESS);
-
- final CollectionRepBuilder builder = CollectionRepBuilder.newBuilder(getResourceContext().repContext(), objectAdapter, collection);
+ final OneToManyAssociation collection = getCollectionThatIsVisibleAndUsable(
+ objectAdapter, collectionId, Intent.ACCESS);
+
+ final CollectionRepBuilder builder = CollectionRepBuilder.newBuilder(
+ getResourceContext().repContext(), objectAdapter, collection);
return jsonRepresentionFrom(builder);
}
@@ -109,13 +110,15 @@ public class DomainObjectResourceImpl ex
@Path("/{oid}/actions/{actionId}")
@Produces({ MediaType.APPLICATION_JSON })
public String actionPrompt(
- @PathParam("oid") final String oidStr,
+ @PathParam("oid") final String oidStr,
@PathParam("actionId") final String actionId) {
final ObjectAdapter objectAdapter = getObjectAdapter(oidStr);
- final ObjectAction action = getObjectActionThatIsVisibleAndUsable(objectAdapter, actionId, Intent.ACCESS);
-
- ActionRepBuilder builder = ActionRepBuilder.newBuilder(getResourceContext().repContext(), objectAdapter, action);
+ final ObjectAction action = getObjectActionThatIsVisibleAndUsable(
+ objectAdapter, actionId, Intent.ACCESS);
+
+ ActionRepBuilder builder = ActionRepBuilder.newBuilder(
+ getResourceContext().repContext(), objectAdapter, action);
return jsonRepresentionFrom(builder);
}
@@ -123,92 +126,97 @@ public class DomainObjectResourceImpl ex
@Path("/{oid}/actions/{actionId}/invoke")
@Produces({ MediaType.APPLICATION_JSON })
public Object invokeActionIdempotent(
- @PathParam("oid") final String oidStr,
- @PathParam("actionId") final String actionId,
+ @PathParam("oid") final String oidStr,
+ @PathParam("actionId") final String actionId,
@QueryParam("arg") final List<String> arguments) {
- final ObjectAdapter objectAdapter = getObjectAdapter(oidStr);
- final ObjectAction action = getObjectActionThatIsVisibleAndUsable(objectAdapter, actionId, Intent.ACCESS);
-
- if(!isIdempotent(action)) {
- throw new WebApplicationException(responseOfMethodNotAllowed(
- "Method not allowed; action '" + action.getId() + "' is not idempotent"));
- }
- int numParameters = action.getParameterCount();
- int numArguments = arguments.size();
- if(numArguments != numParameters) {
- throw new WebApplicationException(responseOfBadRequest(
- "Action '" + action.getId() + "' has " + numParameters + " parameters but received " + numArguments + " arguments"));
- }
-
- final List<ObjectAdapter> parameters = argumentAdaptersFor(action, arguments);
- return invokeActionUsingAdapters(action, objectAdapter, parameters);
+ final ObjectAdapter objectAdapter = getObjectAdapter(oidStr);
+ final ObjectAction action = getObjectActionThatIsVisibleAndUsable(
+ objectAdapter, actionId, Intent.ACCESS);
+
+ if (!isIdempotent(action)) {
+ throw new WebApplicationException(
+ responseOfMethodNotAllowed("Method not allowed; action '"
+ + action.getId() + "' is not idempotent"));
+ }
+ int numParameters = action.getParameterCount();
+ int numArguments = arguments.size();
+ if (numArguments != numParameters) {
+ throw new WebApplicationException(
+ responseOfBadRequest("Action '" + action.getId() + "' has "
+ + numParameters + " parameters but received "
+ + numArguments + " arguments"));
+ }
+
+ final List<ObjectAdapter> parameters = argumentAdaptersFor(action,
+ arguments);
+ return invokeActionUsingAdapters(action, objectAdapter, parameters);
}
private boolean isIdempotent(final ObjectAction action) {
- // TODO: determine whether action is idempotent
- return true;
- }
-
- private List<ObjectAdapter> argumentAdaptersFor(ObjectAction action, List<String> arguments) {
- List<ObjectActionParameter> parameters = action.getParameters();
- List<ObjectAdapter> argumentAdapters = Lists.newArrayList();
- for(int i=0; i<parameters.size(); i++) {
- ObjectActionParameter parameter = parameters.get(i);
- ObjectSpecification paramSpc = parameter.getSpecification();
- String argument = arguments.get(i);
- argumentAdapters.add(objectAdapterFor(paramSpc, argument));
- }
-
- return argumentAdapters;
- }
-
- /**
- * Similar to {@link #objectAdapterFor(ObjectSpecification, Object)}, however the object
- * being interpreted is a String holding URL encoded JSON (rather than having already been
- * parsed into a List/Map representation).
- */
- private ObjectAdapter objectAdapterFor(ObjectSpecification spec, String urlEncodedJson) {
+ // TODO: determine whether action is idempotent
+ return true;
+ }
+
+ private List<ObjectAdapter> argumentAdaptersFor(ObjectAction action,
+ List<String> arguments) {
+ List<ObjectActionParameter> parameters = action.getParameters();
+ List<ObjectAdapter> argumentAdapters = Lists.newArrayList();
+ for (int i = 0; i < parameters.size(); i++) {
+ ObjectActionParameter parameter = parameters.get(i);
+ ObjectSpecification paramSpc = parameter.getSpecification();
+ String argument = arguments.get(i);
+ argumentAdapters.add(objectAdapterFor(paramSpc, argument));
+ }
+
+ return argumentAdapters;
+ }
+
+ /**
+ * Similar to {@link #objectAdapterFor(ObjectSpecification, Object)},
+ * however the object being interpreted is a String holding URL encoded JSON
+ * (rather than having already been parsed into a List/Map representation).
+ */
+ private ObjectAdapter objectAdapterFor(ObjectSpecification spec,
+ String urlEncodedJson) {
final String json = UrlDecoderUtils.urlDecode(urlEncodedJson);
- if(spec.containsFacet(EncodableFacet.class)) {
- EncodableFacet encodableFacet = spec.getFacet(EncodableFacet.class);
- return encodableFacet.fromEncodedString(json);
+ if (spec.containsFacet(EncodableFacet.class)) {
+ EncodableFacet encodableFacet = spec.getFacet(EncodableFacet.class);
+ return encodableFacet.fromEncodedString(json);
} else {
- @SuppressWarnings("unchecked")
- Map<String,Object> representation = objectMapper.convertValue(json, LinkedHashMap.class);
+ @SuppressWarnings("unchecked")
+ Map<String, Object> representation = objectMapper.convertValue(
+ json, LinkedHashMap.class);
return objectAdapterFor(spec, representation);
}
- }
+ }
+
+ // /////////////////////////////////////////////////////////////////
+ // put
+ // /////////////////////////////////////////////////////////////////
-
- ///////////////////////////////////////////////////////////////////
- // put
- ///////////////////////////////////////////////////////////////////
-
- @PUT
+ @PUT
@Path("/{oid}/properties/{propertyId}")
@Produces({ MediaType.APPLICATION_JSON })
- public Object modifyProperty(
- @PathParam("oid") final String oidStr,
- @PathParam("propertyId") final String propertyId,
- @FormParam("arg") final String proposedValue) {
+ public Response modifyProperty(@PathParam("oid") final String oidStr,
+ @PathParam("propertyId") final String propertyId,
+ final InputStream body) {
- // TODO: replace @FormParam with body inputstream
-
final ObjectAdapter objectAdapter = getObjectAdapter(oidStr);
- final OneToOneAssociation property = getPropertyThatIsVisibleAndUsable(objectAdapter, propertyId, Intent.MUTATE);
-
- ObjectSpecification objectSpec = property.getSpecification();
-
- ObjectAdapter proposedValueAdapter = objectAdapterFor(objectSpec, proposedValue);
-
- Consent consent = property.isAssociationValid(objectAdapter, proposedValueAdapter);
- if(consent.isVetoed()) {
- throw new WebApplicationException(responseOfPreconditionFailed(consent.getReason()));
- }
+ final OneToOneAssociation property = getPropertyThatIsVisibleAndUsable(
+ objectAdapter, propertyId, Intent.MUTATE);
+
+ ObjectSpecification propertySpec = property.getSpecification();
- PropertySetterFacet setterFacet = property.getFacet(PropertySetterFacet.class);
- setterFacet.setProperty(objectAdapter, proposedValueAdapter);
+ ObjectAdapter argAdapter = parseBody(propertySpec, body);
+
+ Consent consent = property.isAssociationValid(objectAdapter, argAdapter);
+ if (consent.isVetoed()) {
+ throw new WebApplicationException(
+ responseOfPreconditionFailed(consent.getReason()));
+ }
+
+ property.set(objectAdapter, argAdapter);
return responseOfOk();
}
@@ -216,236 +224,344 @@ public class DomainObjectResourceImpl ex
@PUT
@Path("/{oid}/collections/{collectionId}")
@Produces({ MediaType.APPLICATION_JSON })
- public String addToSet(
+ public Response addToSet(
@PathParam("oid") final String oidStr,
@PathParam("collectionId") final String collectionId,
- @FormParam("arg") final String proposedValueOidStr){
-
+ final InputStream body) {
+
final ObjectAdapter objectAdapter = getObjectAdapter(oidStr);
- final OneToManyAssociation collection = getCollectionThatIsVisibleAndUsable(objectAdapter, collectionId, Intent.MUTATE);
+ final OneToManyAssociation collection = getCollectionThatIsVisibleAndUsable(
+ objectAdapter, collectionId, Intent.MUTATE);
+
+ if (!collection.getCollectionSemantics().isSet()) {
+ throw new WebApplicationException(responseOfBadRequest("Collection '" + collectionId + "' does not have set semantics"));
+ }
+
+ ObjectSpecification collectionSpec = collection.getSpecification();
+ ObjectAdapter argAdapter = parseBody(collectionSpec, body);
+
+ Consent consent = collection.isValidToAdd(objectAdapter, argAdapter);
+ if (consent.isVetoed()) {
+ throw new WebApplicationException(responseOfPreconditionFailed(consent.getReason()));
+ }
+
+ collection.addElement(objectAdapter, argAdapter);
- return null;
+ return responseOfOk();
}
- ///////////////////////////////////////////////////////////////////
- // delete
- ///////////////////////////////////////////////////////////////////
+ // /////////////////////////////////////////////////////////////////
+ // delete
+ // /////////////////////////////////////////////////////////////////
@DELETE
@Path("/{oid}/properties/{propertyId}")
@Produces({ MediaType.APPLICATION_JSON })
- public String clearProperty(
- @PathParam("oid") final String oidStr,
- @PathParam("propertyId") final String propertyId){
-
+ public Response clearProperty(
+ @PathParam("oid") final String oidStr,
+ @PathParam("propertyId") final String propertyId) {
+
final ObjectAdapter objectAdapter = getObjectAdapter(oidStr);
- final OneToOneAssociation property = getPropertyThatIsVisibleAndUsable(objectAdapter, propertyId, Intent.MUTATE);
-
- return null;
+ final OneToOneAssociation property = getPropertyThatIsVisibleAndUsable(
+ objectAdapter, propertyId, Intent.MUTATE);
+
+ Consent consent = property.isAssociationValid(objectAdapter, null);
+ if (consent.isVetoed()) {
+ throw new WebApplicationException(
+ responseOfPreconditionFailed(consent.getReason()));
+ }
+
+ property.set(objectAdapter, null);
+
+ return responseOfOk();
}
@DELETE
@Path("/{oid}/collections/{collectionId}")
@Produces({ MediaType.APPLICATION_JSON })
- public String removeFromCollection(
+ public Response removeFromCollection(
@PathParam("oid") final String oidStr,
@PathParam("collectionId") final String collectionId,
- @FormParam("arg") final String proposedValueOidStr){
+ final InputStream body) {
+
+ final ObjectAdapter objectAdapter = getObjectAdapter(oidStr);
+ final OneToManyAssociation collection = getCollectionThatIsVisibleAndUsable(
+ objectAdapter, collectionId, Intent.MUTATE);
+
+ ObjectSpecification collectionSpec = collection.getSpecification();
+ ObjectAdapter argAdapter = parseBody(collectionSpec, body);
- final ObjectAdapter objectAdapter = getObjectAdapter(oidStr);
- final OneToManyAssociation collection = getCollectionThatIsVisibleAndUsable(objectAdapter, collectionId, Intent.MUTATE);
+ Consent consent = collection.isValidToRemove(objectAdapter, argAdapter);
+ if (consent.isVetoed()) {
+ throw new WebApplicationException(responseOfPreconditionFailed(consent.getReason()));
+ }
+
+ collection.removeElement(objectAdapter, argAdapter);
- return null;
+ return responseOfOk();
}
-
- ///////////////////////////////////////////////////////////////////
- // post
- ///////////////////////////////////////////////////////////////////
+ // /////////////////////////////////////////////////////////////////
+ // post
+ // /////////////////////////////////////////////////////////////////
@POST
@Path("/{oid}/collections/{collectionId}")
@Produces({ MediaType.APPLICATION_JSON })
- public String addToList(
+ public Response addToList(
@PathParam("oid") final String oidStr,
@PathParam("collectionId") final String collectionId,
- @FormParam("arg") final String proposedValueOidStr){
+ final InputStream body) {
final ObjectAdapter objectAdapter = getObjectAdapter(oidStr);
- final OneToManyAssociation collection = getCollectionThatIsVisibleAndUsable(objectAdapter, collectionId, Intent.MUTATE);
-
- return null;
- }
+ final OneToManyAssociation collection = getCollectionThatIsVisibleAndUsable(
+ objectAdapter, collectionId, Intent.MUTATE);
+
+ if (!collection.getCollectionSemantics().isListOrArray()) {
+ throw new WebApplicationException(responseOfBadRequest("Collection '" + collectionId + "' does not have list or array semantics"));
+ }
+
+ ObjectSpecification collectionSpec = collection.getSpecification();
+ ObjectAdapter argAdapter = parseBody(collectionSpec, body);
+
+ Consent consent = collection.isValidToAdd(objectAdapter, argAdapter);
+ if (consent.isVetoed()) {
+ throw new WebApplicationException(responseOfPreconditionFailed(consent.getReason()));
+ }
+ collection.addElement(objectAdapter, argAdapter);
+
+ return responseOfOk();
+ }
@POST
@Path("/{oid}/actions/{actionId}/invoke")
@Produces({ MediaType.APPLICATION_JSON })
public Object invokeAction(
- @PathParam("oid") final String oidStr,
+ @PathParam("oid") final String oidStr,
@PathParam("actionId") final String actionId,
- final InputStream body){
+ final InputStream body) {
final ObjectAdapter objectAdapter = getObjectAdapter(oidStr);
- final ObjectAction action = getObjectActionThatIsVisibleAndUsable(objectAdapter, actionId, Intent.MUTATE);
+ final ObjectAction action = getObjectActionThatIsVisibleAndUsable(
+ objectAdapter, actionId, Intent.MUTATE);
+
+ List<ObjectAdapter> argumentAdapters = parseBody(action, body);
+ return invokeActionUsingAdapters(action, objectAdapter,
+ argumentAdapters);
+ }
+
+ private List<ObjectAdapter> parseBody(final ObjectAction action,
+ final InputStream body) {
+ List<ObjectAdapter> argAdapters = Lists.newArrayList();
+ List<?> arguments = parseBody(body);
+
+ int numParameters = action.getParameterCount();
+ int numArguments = arguments.size();
+ if (numArguments != numParameters) {
+ throw new WebApplicationException(
+ responseOfBadRequest("Action '" + action.getId()
+ + "' has " + numParameters
+ + " parameters but received " + numArguments
+ + " arguments in body"));
+ }
+
+ for (int i = 0; i < numParameters; i++) {
+ ObjectAdapter argAdapter = objectAdapterFor(action, arguments, i);
+ argAdapters.add(argAdapter);
+ }
+ return argAdapters;
+
+ }
+
+ private ObjectAdapter objectAdapterFor(final ObjectAction action,
+ List<?> arguments, int i) {
+ List<ObjectActionParameter> parameters = action.getParameters();
+
+ ObjectSpecification paramSpec = parameters.get(i).getSpecification();
+ Object arg = arguments.get(i);
+
+ ObjectAdapter objectAdapter = objectAdapterFor(action, i, paramSpec, arg);
+ return objectAdapter;
+ }
+
+ private ObjectAdapter objectAdapterFor(final ObjectAction action, int i,
+ ObjectSpecification paramSpec, Object arg) {
+ try {
+ return objectAdapterFor(paramSpec, arg);
+ } catch (ExpectedStringRepresentingValueException e) {
+ throw new WebApplicationException(
+ responseOfBadRequest("Action '"
+ + action.getId()
+ + "', argument "
+ + i
+ + " should be a URL encoded string representing a value of type "
+ + resourceFor(paramSpec)));
+ } catch (ExpectedMapRepresentingReferenceException e) {
+ throw new WebApplicationException(
+ responseOfBadRequest("Action '"
+ + action.getId()
+ + "', argument "
+ + i
+ + " should be a map representing a link to reference of type "
+ + resourceFor(paramSpec)));
+ }
+ }
- List<ObjectAdapter> argumentAdapters = parseBody(action, body);
- return invokeActionUsingAdapters(action, objectAdapter, argumentAdapters);
+ // ///////////////////////////////////////////////////////////////////
+ // helpers
+ // ///////////////////////////////////////////////////////////////////
+
+ private Object invokeActionUsingAdapters(final ObjectAction action,
+ final ObjectAdapter objectAdapter,
+ final List<ObjectAdapter> argAdapters) {
+
+ List<ObjectActionParameter> parameters = action.getParameters();
+ for (int i = 0; i < parameters.size(); i++) {
+ ObjectActionParameter parameter = parameters.get(i);
+ ObjectAdapter paramAdapter = argAdapters.get(i);
+ if (paramAdapter.getSpecification().containsFacet(ValueFacet.class)) {
+ Object arg = paramAdapter.getObject();
+ String reasonNotValid = parameter.isValid(objectAdapter, arg);
+ if (reasonNotValid != null) {
+ throw new WebApplicationException(
+ responseOfPreconditionFailed(reasonNotValid));
+ }
+ }
+ }
+ ObjectAdapter[] argArray = argAdapters.toArray(new ObjectAdapter[0]);
+ Consent consent = action.isProposedArgumentSetValid(objectAdapter,
+ argArray);
+ if (consent.isVetoed()) {
+ throw new WebApplicationException(
+ responseOfPreconditionFailed(consent.getReason()));
+ }
+
+ final ObjectAdapter returnedAdapter = action.execute(objectAdapter,
+ argArray);
+ if (returnedAdapter == null) {
+ return responseOfOk();
+ }
+ final CollectionFacet facet = returnedAdapter.getSpecification()
+ .getFacet(CollectionFacet.class);
+ if (facet != null) {
+ final Collection<ObjectAdapter> collectionAdapters = facet
+ .collection(returnedAdapter);
+ return jsonRepresentationOf(collectionAdapters);
+ } else {
+ return jsonRepresentationOf(returnedAdapter);
+ }
+ }
+
+ private ObjectAdapter parseBody(ObjectSpecification objectSpec,
+ final InputStream body) {
+ List<?> arguments = parseBody(body);
+ if (arguments.size() != 1) {
+ throw new WebApplicationException(
+ responseOfBadRequest("Body should contain 1 argument representing a value of type '" + resourceFor(objectSpec) + "'"));
+ }
+
+ ObjectAdapter proposedValueAdapter = objectAdapterFor(objectSpec, arguments.get(0));
+ return proposedValueAdapter;
+ }
+
+ private List<?> parseBody(final InputStream body) {
+ try {
+ byte[] byteArray = ByteStreams.toByteArray(body);
+ String bodyAsString = new String(byteArray, Charsets.UTF_8);
+
+ List<?> arguments = objectMapper.readValue(bodyAsString, ArrayList.class);
+ return arguments;
+ } catch (JsonParseException e) {
+ throw new WebApplicationException(e,
+ responseOfBadRequest("could not parse body"));
+ } catch (JsonMappingException e) {
+ throw new WebApplicationException(
+ e,
+ responseOfBadRequest("could not map body to a Map structure"));
+ } catch (IOException e) {
+ throw new WebApplicationException(e,
+ responseOfBadRequest("could not read body"));
+ }
}
- private List<ObjectAdapter> parseBody(final ObjectAction action, final InputStream body) {
- List<ObjectAdapter> argAdapters = Lists.newArrayList();
- try {
- byte[] byteArray = ByteStreams.toByteArray(body);
- String bodyAsString = new String(byteArray, Charsets.UTF_8);
-
- List<?> arguments = objectMapper.readValue(bodyAsString, ArrayList.class);
-
- int numParameters = action.getParameterCount();
- int numArguments = arguments.size();
- if(numArguments != numParameters) {
- throw new WebApplicationException(responseOfBadRequest(
- "Action '" + action.getId() + "' has " + numParameters + " parameters but received " + numArguments + " arguments"));
- }
-
- for(int i=0; i<numParameters; i++) {
- ObjectAdapter argAdapter = toObjectAdapter(action, arguments, i);
- argAdapters.add(argAdapter);
- }
- return argAdapters;
-
- } catch (JsonParseException e) {
- throw new WebApplicationException(e, responseOfBadRequest("could not parse body"));
- } catch (JsonMappingException e) {
- throw new WebApplicationException(e, responseOfBadRequest("could not map body to a Map structure"));
- } catch (IOException e) {
- throw new WebApplicationException(e, responseOfBadRequest("could not read body"));
- }
- }
-
- private ObjectAdapter toObjectAdapter(final ObjectAction action, List<?> arguments, int i) {
- List<ObjectActionParameter> parameters = action.getParameters();
-
- ObjectSpecification paramSpec = parameters.get(i).getSpecification();
- Object arg = arguments.get(i);
-
- ObjectAdapter objectAdapter = toObjectAdapter(action, i, paramSpec, arg);
- return objectAdapter;
- }
-
- private ObjectAdapter toObjectAdapter(final ObjectAction action, int i, ObjectSpecification paramSpec, Object arg) {
- try {
- return objectAdapterFor(paramSpec, arg);
- } catch (ExpectedStringRepresentingValueException e) {
- throw new WebApplicationException(responseOfBadRequest("Action '" + action.getId() + "', argument " + i + " should be a URL encoded string representing a value of type " + resourceFor(paramSpec)));
- } catch (ExpectedMapRepresentingReferenceException e) {
- throw new WebApplicationException(responseOfBadRequest("Action '" + action.getId() + "', argument " + i + " should be a map representing a link to reference of type " + resourceFor(paramSpec)));
- }
- }
-
-
-
- /////////////////////////////////////////////////////////////////////
- // helpers
- /////////////////////////////////////////////////////////////////////
-
- private Object invokeActionUsingAdapters(final ObjectAction action,
- final ObjectAdapter objectAdapter,
- final List<ObjectAdapter> argAdapters) {
-
- List<ObjectActionParameter> parameters = action.getParameters();
- for(int i=0; i<parameters.size(); i++) {
- ObjectActionParameter parameter = parameters.get(i);
- ObjectAdapter paramAdapter = argAdapters.get(i);
- if(paramAdapter.getSpecification().containsFacet(ValueFacet.class)) {
- Object arg = paramAdapter.getObject();
- String reasonNotValid = parameter.isValid(objectAdapter, arg);
- if(reasonNotValid != null) {
- throw new WebApplicationException(responseOfPreconditionFailed(reasonNotValid));
- }
- }
- }
- ObjectAdapter[] argArray = argAdapters.toArray(new ObjectAdapter[0]);
- Consent consent = action.isProposedArgumentSetValid(objectAdapter, argArray);
- if(consent.isVetoed()) {
- throw new WebApplicationException(responseOfPreconditionFailed(consent.getReason()));
- }
-
- final ObjectAdapter returnedAdapter = action.execute(objectAdapter, argArray);
- if(returnedAdapter == null) {
- return responseOfOk();
- }
- final CollectionFacet facet = returnedAdapter.getSpecification().getFacet(CollectionFacet.class);
- if(facet != null) {
- final Collection<ObjectAdapter> collectionAdapters = facet.collection(returnedAdapter);
- return jsonRepresentationOf(collectionAdapters);
- } else {
- return jsonRepresentationOf(returnedAdapter);
- }
- }
-
-
- private static String resourceFor(ObjectSpecification paramSpec) {
- // TODO: should return a string in the form http://localhost:8080/types/xxx
- return paramSpec.getFullIdentifier();
- }
-
- private enum Intent {
- ACCESS,
- MUTATE;
-
- public boolean isMutate() {
- return this == MUTATE;
- }
- }
-
- private OneToOneAssociation getPropertyThatIsVisibleAndUsable(
- final ObjectAdapter objectAdapter, final String propertyId, final Intent intent) {
- ObjectAssociation association = objectAdapter.getSpecification().getAssociation(propertyId);
- if(association == null || !association.isOneToOneAssociation()) {
+ private static String resourceFor(ObjectSpecification objectSpec) {
+ // TODO: should return a string in the form
+ // http://localhost:8080/types/xxx
+ return objectSpec.getFullIdentifier();
+ }
+
+ private enum Intent {
+ ACCESS, MUTATE;
+
+ public boolean isMutate() {
+ return this == MUTATE;
+ }
+ }
+
+ private OneToOneAssociation getPropertyThatIsVisibleAndUsable(
+ 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);
- }
+ return ensureVisibleAndUsableForIntent(objectAdapter, property,
+ MemberType.PROPERTY, intent);
+ }
- private OneToManyAssociation getCollectionThatIsVisibleAndUsable(
- final ObjectAdapter objectAdapter, final String collectionId, final Intent intent) {
- ObjectAssociation association = objectAdapter.getSpecification().getAssociation(collectionId);
- if(association == null || !association.isOneToManyAssociation()) {
+ private OneToManyAssociation getCollectionThatIsVisibleAndUsable(
+ 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);
- }
+ return ensureVisibleAndUsableForIntent(objectAdapter, collection,
+ MemberType.COLLECTION, intent);
+ }
+
+ private ObjectAction getObjectActionThatIsVisibleAndUsable(
+ final ObjectAdapter objectAdapter,
+ final String actionId,
+ Intent intent) {
+
+ ObjectAction action = objectAdapter.getSpecification().getObjectAction(actionId);
+ return ensureVisibleAndUsableForIntent(objectAdapter, action, MemberType.ACTION, intent);
+ }
- private ObjectAction getObjectActionThatIsVisibleAndUsable(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()) {
+ 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()) {
- Consent usable = objectMember.isUsable(getSession(), objectAdapter);
- if(usable.isVetoed()) {
- String memberTypeStr = memberType.name().toLowerCase();
- throw new WebApplicationException(responseOfPreconditionFailed(
- memberTypeStr + " is not usable: '" + memberId + "' (" + usable.getReason() + ")"));
- }
+ if (intent.isMutate()) {
+ Consent usable = objectMember.isUsable(getSession(), objectAdapter);
+ if (usable.isVetoed()) {
+ String memberTypeStr = memberType.name().toLowerCase();
+ throw new WebApplicationException(
+ responseOfPreconditionFailed(memberTypeStr
+ + " is not usable: '" + memberId + "' ("
+ + usable.getReason() + ")"));
+ }
}
return objectMember;
- }
+ }
- private static void throwNotFoundException(final String memberId, MemberType memberType) {
+ private static void throwNotFoundException(final String memberId,
+ MemberType memberType) {
String memberTypeStr = memberType.name().toLowerCase();
- throw new WebApplicationException(responseOfNotFound(
- memberTypeStr + " '" + memberId + "' either does not exist or is not visible"));
+ throw new WebApplicationException(
+ responseOfNotFound(memberTypeStr + " '" + memberId
+ + "' either does not exist or is not visible"));
}
}