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 2014/05/11 19:41:46 UTC

[01/16] git commit: ISIS-550: starting on PostsAddedToCollectionEvent

Repository: isis
Updated Branches:
  refs/heads/master b7909bf10 -> 5f15fa74c


ISIS-550: starting on PostsAddedToCollectionEvent

This is Oscar's patch attached to ISIS-550 ticket on 6-may-2014.


Project: http://git-wip-us.apache.org/repos/asf/isis/repo
Commit: http://git-wip-us.apache.org/repos/asf/isis/commit/548cb14f
Tree: http://git-wip-us.apache.org/repos/asf/isis/tree/548cb14f
Diff: http://git-wip-us.apache.org/repos/asf/isis/diff/548cb14f

Branch: refs/heads/master
Commit: 548cb14ff648c0099036a2e777b318e1f4d3daa0
Parents: 31acb0f
Author: Dan Haywood <da...@haywood-associates.co.uk>
Authored: Wed May 7 05:20:50 2014 +0100
Committer: Dan Haywood <da...@haywood-associates.co.uk>
Committed: Wed May 7 05:20:50 2014 +0100

----------------------------------------------------------------------
 .../annotation/PostsAddedToCollectionEvent.java |  59 +++++++
 .../PostsRemovedFromCollectionEvent.java        |  59 +++++++
 .../isis/applib/events/ActionArgumentEvent.java |   2 +-
 .../eventbus/AddedToCollectionEvent.java        |  55 +++++++
 .../eventbus/RemovedFromCollectionEvent.java    |  54 +++++++
 .../event/PostsAddedToCollectionEventFacet.java |  34 ++++
 .../PostsCollectionAddToEventFacetAbstract.java |  37 +++++
 ...lectionAddToEventAnnotationFacetFactory.java | 117 ++++++++++++++
 ...ostsCollectionAddToEventFacetAnnotation.java | 154 +++++++++++++++++++
 ...nAddedEventFacetAnnotationTest_newEvent.java |  41 +++++
 10 files changed, 611 insertions(+), 1 deletion(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/isis/blob/548cb14f/core/applib/src/main/java/org/apache/isis/applib/annotation/PostsAddedToCollectionEvent.java
----------------------------------------------------------------------
diff --git a/core/applib/src/main/java/org/apache/isis/applib/annotation/PostsAddedToCollectionEvent.java b/core/applib/src/main/java/org/apache/isis/applib/annotation/PostsAddedToCollectionEvent.java
new file mode 100644
index 0000000..28fa7c2
--- /dev/null
+++ b/core/applib/src/main/java/org/apache/isis/applib/annotation/PostsAddedToCollectionEvent.java
@@ -0,0 +1,59 @@
+/*
+ *  Licensed to the Apache Software Foundation (ASF) under one
+ *  or more contributor license agreements.  See the NOTICE file
+ *  distributed with this work for additional information
+ *  regarding copyright ownership.  The ASF licenses this file
+ *  to you under the Apache License, Version 2.0 (the
+ *  "License"); you may not use this file except in compliance
+ *  with the License.  You may obtain a copy of the License at
+ *
+ *        http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *  Unless required by applicable law or agreed to in writing,
+ *  software distributed under the License is distributed on an
+ *  "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ *  KIND, either express or implied.  See the License for the
+ *  specific language governing permissions and limitations
+ *  under the License.
+ */
+
+package org.apache.isis.applib.annotation;
+
+import java.lang.annotation.ElementType;
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+import java.lang.annotation.Target;
+
+import org.apache.isis.applib.services.eventbus.AddedToCollectionEvent;
+
+/**
+ * Applies only to collections; any changes should be propagated as events to subscribers.  
+ * Only posted after a successful validation.
+ * 
+ * <p>For example:
+ * <pre>
+ * public static class DomainEntityAddedToCollectionEvent extends AddedToCollectionEvent {}
+ * 
+ * &#64;PostsAddedToCollectionEvent(DomainEntityAddedToCollectionEvent.class)
+ * public DomainEntity getDomainEntity() { ...}
+ * </pre>
+ * 
+ * <p>
+ * It is highly advisable that only domain services - not domain entities - are registered as subscribers.  
+ * Domain services are guaranteed to be instantiated and resident in memory, whereas the same is not true
+ * of domain entities.  The typical implementation of a domain service subscriber is to identify the impacted entities,
+ * load them using a repository, and then to delegate to the event to them.
+ */
+@Retention(RetentionPolicy.RUNTIME)
+@Target({ElementType.TYPE, ElementType.METHOD})
+public @interface PostsAddedToCollectionEvent {
+
+    /**
+     * The subclass of {@link AddedToCollectionEvent event} to be instantiated and posted.
+     * 
+     * <p>
+     * This subclass must provide a no-arg constructor; the fields are set reflectively.
+     */
+    Class<? extends AddedToCollectionEvent<?,?>> value();
+
+}

http://git-wip-us.apache.org/repos/asf/isis/blob/548cb14f/core/applib/src/main/java/org/apache/isis/applib/annotation/PostsRemovedFromCollectionEvent.java
----------------------------------------------------------------------
diff --git a/core/applib/src/main/java/org/apache/isis/applib/annotation/PostsRemovedFromCollectionEvent.java b/core/applib/src/main/java/org/apache/isis/applib/annotation/PostsRemovedFromCollectionEvent.java
new file mode 100644
index 0000000..4198ce6
--- /dev/null
+++ b/core/applib/src/main/java/org/apache/isis/applib/annotation/PostsRemovedFromCollectionEvent.java
@@ -0,0 +1,59 @@
+/*
+ *  Licensed to the Apache Software Foundation (ASF) under one
+ *  or more contributor license agreements.  See the NOTICE file
+ *  distributed with this work for additional information
+ *  regarding copyright ownership.  The ASF licenses this file
+ *  to you under the Apache License, Version 2.0 (the
+ *  "License"); you may not use this file except in compliance
+ *  with the License.  You may obtain a copy of the License at
+ *
+ *        http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *  Unless required by applicable law or agreed to in writing,
+ *  software distributed under the License is distributed on an
+ *  "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ *  KIND, either express or implied.  See the License for the
+ *  specific language governing permissions and limitations
+ *  under the License.
+ */
+
+package org.apache.isis.applib.annotation;
+
+import java.lang.annotation.ElementType;
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+import java.lang.annotation.Target;
+
+import org.apache.isis.applib.services.eventbus.RemovedFromCollectionEvent;
+
+/**
+ * Applies only to collections; any changes should be propagated as events to subscribers.  
+ * Only posted after a successful validation.
+ * 
+ * <p>For example:
+ * <pre>
+ * public static class DomainEntityRemovedFromCollectionEvent extends RemovedFromCollectionEvent {}
+ * 
+ * &#64;PostsRemovedFromCollectionEvent(DomainEntityRemovedFromCollectionEvent.class)
+ * public DomainEntity getDomainEntity() { ...}
+ * </pre>
+ * 
+ * <p>
+ * It is highly advisable that only domain services - not domain entities - are registered as subscribers.  
+ * Domain services are guaranteed to be instantiated and resident in memory, whereas the same is not true
+ * of domain entities.  The typical implementation of a domain service subscriber is to identify the impacted entities,
+ * load them using a repository, and then to delegate to the event to them.
+ */
+@Retention(RetentionPolicy.RUNTIME)
+@Target({ElementType.TYPE, ElementType.METHOD})
+public @interface PostsRemovedFromCollectionEvent {
+
+    /**
+     * The subclass of {@link RemovedFromCollectionEvent event} to be instantiated and posted.
+     * 
+     * <p>
+     * This subclass must provide a no-arg constructor; the fields are set reflectively.
+     */
+    Class<? extends RemovedFromCollectionEvent<?,?>> value();
+
+}

http://git-wip-us.apache.org/repos/asf/isis/blob/548cb14f/core/applib/src/main/java/org/apache/isis/applib/events/ActionArgumentEvent.java
----------------------------------------------------------------------
diff --git a/core/applib/src/main/java/org/apache/isis/applib/events/ActionArgumentEvent.java b/core/applib/src/main/java/org/apache/isis/applib/events/ActionArgumentEvent.java
index e59ce18..7f1f5b0 100644
--- a/core/applib/src/main/java/org/apache/isis/applib/events/ActionArgumentEvent.java
+++ b/core/applib/src/main/java/org/apache/isis/applib/events/ActionArgumentEvent.java
@@ -67,7 +67,7 @@ public class ActionArgumentEvent extends ValidityEvent {
     
     @Override
     public String getReasonMessage() {
-    	return String.format("%s. Position: %s. Proposed: %s", super.getReasonMessage(), this.getPosition(), this.getProposed());
+    	return String.format("Invalid action argument. Position: %s. Proposed value: %s. Reason: %s", this.getPosition(), this.getProposed(), super.getReasonMessage());
     }
     
 }

http://git-wip-us.apache.org/repos/asf/isis/blob/548cb14f/core/applib/src/main/java/org/apache/isis/applib/services/eventbus/AddedToCollectionEvent.java
----------------------------------------------------------------------
diff --git a/core/applib/src/main/java/org/apache/isis/applib/services/eventbus/AddedToCollectionEvent.java b/core/applib/src/main/java/org/apache/isis/applib/services/eventbus/AddedToCollectionEvent.java
new file mode 100644
index 0000000..6b6bb02
--- /dev/null
+++ b/core/applib/src/main/java/org/apache/isis/applib/services/eventbus/AddedToCollectionEvent.java
@@ -0,0 +1,55 @@
+/*
+ *  Licensed to the Apache Software Foundation (ASF) under one
+ *  or more contributor license agreements.  See the NOTICE file
+ *  distributed with this work for additional information
+ *  regarding copyright ownership.  The ASF licenses this file
+ *  to you under the Apache License, Version 2.0 (the
+ *  "License"); you may not use this file except in compliance
+ *  with the License.  You may obtain a copy of the License at
+ *
+ *        http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *  Unless required by applicable law or agreed to in writing,
+ *  software distributed under the License is distributed on an
+ *  "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ *  KIND, either express or implied.  See the License for the
+ *  specific language governing permissions and limitations
+ *  under the License.
+ */
+package org.apache.isis.applib.services.eventbus;
+
+import org.apache.isis.applib.annotation.PostsPropertyChangedEvent;
+import org.apache.isis.applib.util.ObjectContracts;
+
+public abstract class AddedToCollectionEvent<S,T> {
+    private final S source;
+    private final T addedValue;
+    
+    /**
+     * To instantiate reflectively when the {@link PostsPropertyChangedEvent} annotation
+     * is used.
+     * 
+     * <p>
+     * The fields ({@link #source} and {@link #addedValue} are then set reflectively.
+     */
+    public AddedToCollectionEvent() {
+        this(null, null);
+    }
+    public AddedToCollectionEvent(S source, T addedValue) {
+        this.source = source;
+        this.addedValue = addedValue;
+    }
+
+    public S getSource() {
+        return source;
+    }
+    
+    public T getAddedValue() {
+        return addedValue;
+    }
+    
+    @Override
+    public String toString() {
+        return ObjectContracts.toString(this, "source,addedValue");
+    }
+}
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/isis/blob/548cb14f/core/applib/src/main/java/org/apache/isis/applib/services/eventbus/RemovedFromCollectionEvent.java
----------------------------------------------------------------------
diff --git a/core/applib/src/main/java/org/apache/isis/applib/services/eventbus/RemovedFromCollectionEvent.java b/core/applib/src/main/java/org/apache/isis/applib/services/eventbus/RemovedFromCollectionEvent.java
new file mode 100644
index 0000000..e33ed95
--- /dev/null
+++ b/core/applib/src/main/java/org/apache/isis/applib/services/eventbus/RemovedFromCollectionEvent.java
@@ -0,0 +1,54 @@
+/*
+ *  Licensed to the Apache Software Foundation (ASF) under one
+ *  or more contributor license agreements.  See the NOTICE file
+ *  distributed with this work for additional information
+ *  regarding copyright ownership.  The ASF licenses this file
+ *  to you under the Apache License, Version 2.0 (the
+ *  "License"); you may not use this file except in compliance
+ *  with the License.  You may obtain a copy of the License at
+ *
+ *        http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *  Unless required by applicable law or agreed to in writing,
+ *  software distributed under the License is distributed on an
+ *  "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ *  KIND, either express or implied.  See the License for the
+ *  specific language governing permissions and limitations
+ *  under the License.
+ */
+package org.apache.isis.applib.services.eventbus;
+
+import org.apache.isis.applib.util.ObjectContracts;
+
+public abstract class RemovedFromCollectionEvent<S,T> {
+    private final S source;
+    private final T removedValue;
+    
+    /**
+     * To instantiate reflectively when the {@link PostsAddedToCollectionEvent} annotation
+     * is used.
+     * 
+     * <p>
+     * The fields ({@link #source} and {@link #removedValue} are then set reflectively.
+     */
+    public RemovedFromCollectionEvent() {
+        this(null, null);
+    }
+    public RemovedFromCollectionEvent(S source, T removedValue) {
+        this.source = source;
+        this.removedValue = removedValue;
+    }
+
+    public S getSource() {
+        return source;
+    }
+    
+    public T getRemovedValue() {
+        return removedValue;
+    }
+    
+    @Override
+    public String toString() {
+        return ObjectContracts.toString(this, "source,removedValue");
+    }
+}
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/isis/blob/548cb14f/core/metamodel/src/main/java/org/apache/isis/core/metamodel/facets/collections/event/PostsAddedToCollectionEventFacet.java
----------------------------------------------------------------------
diff --git a/core/metamodel/src/main/java/org/apache/isis/core/metamodel/facets/collections/event/PostsAddedToCollectionEventFacet.java b/core/metamodel/src/main/java/org/apache/isis/core/metamodel/facets/collections/event/PostsAddedToCollectionEventFacet.java
new file mode 100644
index 0000000..b2f6c18
--- /dev/null
+++ b/core/metamodel/src/main/java/org/apache/isis/core/metamodel/facets/collections/event/PostsAddedToCollectionEventFacet.java
@@ -0,0 +1,34 @@
+/*
+ *  Licensed to the Apache Software Foundation (ASF) under one
+ *  or more contributor license agreements.  See the NOTICE file
+ *  distributed with this work for additional information
+ *  regarding copyright ownership.  The ASF licenses this file
+ *  to you under the Apache License, Version 2.0 (the
+ *  "License"); you may not use this file except in compliance
+ *  with the License.  You may obtain a copy of the License at
+ *
+ *        http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *  Unless required by applicable law or agreed to in writing,
+ *  software distributed under the License is distributed on an
+ *  "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ *  KIND, either express or implied.  See the License for the
+ *  specific language governing permissions and limitations
+ *  under the License.
+ */
+
+package org.apache.isis.core.metamodel.facets.collections.event;
+
+import org.apache.isis.applib.services.eventbus.EventBusService;
+import org.apache.isis.applib.services.eventbus.PropertyChangedEvent;
+import org.apache.isis.core.metamodel.facetapi.Facet;
+import org.apache.isis.core.metamodel.facetapi.MultiTypedFacet;
+import org.apache.isis.core.metamodel.facets.collections.modify.CollectionAddToFacet;
+
+/**
+ * Indicates that (the specified subclass of) {@link PropertyChangedEvent} should be posted to the
+ * {@link EventBusService}.
+ */
+public interface PostsAddedToCollectionEventFacet extends CollectionAddToFacet, MultiTypedFacet, Facet {
+
+}

http://git-wip-us.apache.org/repos/asf/isis/blob/548cb14f/core/metamodel/src/main/java/org/apache/isis/core/metamodel/facets/collections/event/PostsCollectionAddToEventFacetAbstract.java
----------------------------------------------------------------------
diff --git a/core/metamodel/src/main/java/org/apache/isis/core/metamodel/facets/collections/event/PostsCollectionAddToEventFacetAbstract.java b/core/metamodel/src/main/java/org/apache/isis/core/metamodel/facets/collections/event/PostsCollectionAddToEventFacetAbstract.java
new file mode 100644
index 0000000..44eec96
--- /dev/null
+++ b/core/metamodel/src/main/java/org/apache/isis/core/metamodel/facets/collections/event/PostsCollectionAddToEventFacetAbstract.java
@@ -0,0 +1,37 @@
+/*
+ *  Licensed to the Apache Software Foundation (ASF) under one
+ *  or more contributor license agreements.  See the NOTICE file
+ *  distributed with this work for additional information
+ *  regarding copyright ownership.  The ASF licenses this file
+ *  to you under the Apache License, Version 2.0 (the
+ *  "License"); you may not use this file except in compliance
+ *  with the License.  You may obtain a copy of the License at
+ *
+ *        http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *  Unless required by applicable law or agreed to in writing,
+ *  software distributed under the License is distributed on an
+ *  "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ *  KIND, either express or implied.  See the License for the
+ *  specific language governing permissions and limitations
+ *  under the License.
+ */
+
+package org.apache.isis.core.metamodel.facets.collections.event;
+
+import org.apache.isis.core.metamodel.facetapi.Facet;
+import org.apache.isis.core.metamodel.facetapi.FacetHolder;
+import org.apache.isis.core.metamodel.facets.collections.CollectionFacetAbstract;
+
+public abstract class PostsCollectionAddToEventFacetAbstract extends CollectionFacetAbstract implements PostsAddedToCollectionEventFacet {
+
+	public PostsCollectionAddToEventFacetAbstract(FacetHolder holder) {
+		super(holder);
+	}
+
+	public static Class<? extends Facet> type() {
+        return PostsAddedToCollectionEventFacet.class;
+    }
+	
+	  
+}

http://git-wip-us.apache.org/repos/asf/isis/blob/548cb14f/core/metamodel/src/main/java/org/apache/isis/core/progmodel/facets/collections/event/PostsCollectionAddToEventAnnotationFacetFactory.java
----------------------------------------------------------------------
diff --git a/core/metamodel/src/main/java/org/apache/isis/core/progmodel/facets/collections/event/PostsCollectionAddToEventAnnotationFacetFactory.java b/core/metamodel/src/main/java/org/apache/isis/core/progmodel/facets/collections/event/PostsCollectionAddToEventAnnotationFacetFactory.java
new file mode 100644
index 0000000..e68b05c
--- /dev/null
+++ b/core/metamodel/src/main/java/org/apache/isis/core/progmodel/facets/collections/event/PostsCollectionAddToEventAnnotationFacetFactory.java
@@ -0,0 +1,117 @@
+/*
+ *  Licensed to the Apache Software Foundation (ASF) under one
+ *  or more contributor license agreements.  See the NOTICE file
+ *  distributed with this work for additional information
+ *  regarding copyright ownership.  The ASF licenses this file
+ *  to you under the Apache License, Version 2.0 (the
+ *  "License"); you may not use this file except in compliance
+ *  with the License.  You may obtain a copy of the License at
+ *
+ *        http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *  Unless required by applicable law or agreed to in writing,
+ *  software distributed under the License is distributed on an
+ *  "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ *  KIND, either express or implied.  See the License for the
+ *  specific language governing permissions and limitations
+ *  under the License.
+ */
+
+package org.apache.isis.core.progmodel.facets.collections.event;
+
+import java.lang.reflect.Method;
+import java.util.Comparator;
+import java.util.List;
+
+import org.apache.isis.applib.annotation.PostsAddedToCollectionEvent;
+import org.apache.isis.applib.services.eventbus.AddedToCollectionEvent;
+import org.apache.isis.core.commons.config.IsisConfiguration;
+import org.apache.isis.core.metamodel.adapter.ServicesProvider;
+import org.apache.isis.core.metamodel.adapter.ServicesProviderAware;
+import org.apache.isis.core.metamodel.facetapi.FacetHolder;
+import org.apache.isis.core.metamodel.facetapi.FacetUtil;
+import org.apache.isis.core.metamodel.facetapi.FeatureType;
+import org.apache.isis.core.metamodel.facetapi.MetaModelValidatorRefiner;
+import org.apache.isis.core.metamodel.facets.Annotations;
+import org.apache.isis.core.metamodel.facets.FacetFactoryAbstract;
+import org.apache.isis.core.metamodel.facets.collections.modify.CollectionAddToFacet;
+import org.apache.isis.core.metamodel.facets.collections.modify.CollectionFacet;
+import org.apache.isis.core.metamodel.facets.collections.sortedby.SortedByFacet;
+import org.apache.isis.core.metamodel.facets.collections.event.PostsAddedToCollectionEventFacet;
+import org.apache.isis.core.metamodel.spec.ObjectSpecification;
+import org.apache.isis.core.metamodel.spec.feature.Contributed;
+import org.apache.isis.core.metamodel.spec.feature.OneToManyAssociation;
+import org.apache.isis.core.metamodel.specloader.validator.MetaModelValidatorComposite;
+import org.apache.isis.core.metamodel.specloader.validator.MetaModelValidatorVisiting;
+import org.apache.isis.core.metamodel.specloader.validator.MetaModelValidatorVisiting.Visitor;
+import org.apache.isis.core.metamodel.specloader.validator.ValidationFailures;
+
+public class PostsCollectionAddToEventAnnotationFacetFactory extends FacetFactoryAbstract implements ServicesProviderAware, MetaModelValidatorRefiner {
+
+    private ServicesProvider servicesProvider;
+
+    public PostsCollectionAddToEventAnnotationFacetFactory() {
+        super(FeatureType.PROPERTIES_ONLY);
+    }
+
+    @Override
+    public void process(final ProcessMethodContext processMethodContext) {
+        final Method method = processMethodContext.getMethod();
+        FacetUtil.addFacet(create(method, processMethodContext.getFacetHolder()));
+    }
+
+    private PostsAddedToCollectionEventFacet create(Method method, final FacetHolder holder) {
+        final PostsAddedToCollectionEvent annotation = Annotations.getAnnotation(method, PostsAddedToCollectionEvent.class);
+        if(annotation == null) {
+            return null;
+        }
+        final PostsAddedToCollectionEventFacet postsAddedToCollectionEventFacet = holder.getFacet(PostsAddedToCollectionEventFacet.class);
+        if(postsAddedToCollectionEventFacet == null) {
+            return null;
+        } 
+        final CollectionAddToFacet collectionAddToFacet = holder.getFacet(CollectionAddToFacet.class);
+        final CollectionFacet collectionFacet = holder.getFacet(CollectionFacet.class);
+        if(postsAddedToCollectionEventFacet != null) {
+            holder.removeFacet(postsAddedToCollectionEventFacet);
+        }
+        if(collectionAddToFacet != null) {
+            holder.removeFacet(collectionAddToFacet);
+        }
+        if(collectionFacet != null) {
+            holder.removeFacet(collectionFacet);
+        }
+        final Class<? extends AddedToCollectionEvent<?,?>> changedEventType = annotation.value();
+        return new PostsCollectionAddToEventFacetAnnotation(changedEventType, postsAddedToCollectionEventFacet, collectionAddToFacet, collectionFacet, servicesProvider, holder);
+    }
+
+    @Override
+    public void setServicesProvider(ServicesProvider servicesProvider) {
+        this.servicesProvider = servicesProvider;
+    }
+
+    @Override
+    public void refineMetaModelValidator(MetaModelValidatorComposite metaModelValidator, IsisConfiguration configuration) {
+        metaModelValidator.add(new MetaModelValidatorVisiting(newValidatorVisitor()));
+    }
+
+    protected Visitor newValidatorVisitor() {
+        return new MetaModelValidatorVisiting.Visitor() {
+
+            @Override
+            public boolean visit(ObjectSpecification objectSpec, ValidationFailures validationFailures) {
+                List<OneToManyAssociation> objectCollections = objectSpec.getCollections(Contributed.EXCLUDED);
+                for (OneToManyAssociation objectCollection : objectCollections) {
+                    final SortedByFacet facet = objectCollection.getFacet(SortedByFacet.class);
+                    if(facet != null) {
+                        final Class<? extends Comparator<?>> cls = facet.value();
+                        if(!Comparator.class.isAssignableFrom(cls)) {
+                            validationFailures.add("%s#%s is annotated with @SortedBy, but the class specified '%s' is not a Comparator", objectSpec.getIdentifier().getClassName(), objectCollection.getId(), facet.value().getName());
+                        }
+                    }
+                }
+                return true;
+            }
+        };
+    }
+
+}

http://git-wip-us.apache.org/repos/asf/isis/blob/548cb14f/core/metamodel/src/main/java/org/apache/isis/core/progmodel/facets/collections/event/PostsCollectionAddToEventFacetAnnotation.java
----------------------------------------------------------------------
diff --git a/core/metamodel/src/main/java/org/apache/isis/core/progmodel/facets/collections/event/PostsCollectionAddToEventFacetAnnotation.java b/core/metamodel/src/main/java/org/apache/isis/core/progmodel/facets/collections/event/PostsCollectionAddToEventFacetAnnotation.java
new file mode 100644
index 0000000..6c59633
--- /dev/null
+++ b/core/metamodel/src/main/java/org/apache/isis/core/progmodel/facets/collections/event/PostsCollectionAddToEventFacetAnnotation.java
@@ -0,0 +1,154 @@
+/*
+ *  Licensed to the Apache Software Foundation (ASF) under one
+ *  or more contributor license agreements.  See the NOTICE file
+ *  distributed with this work for additional information
+ *  regarding copyright ownership.  The ASF licenses this file
+ *  to you under the Apache License, Version 2.0 (the
+ *  "License"); you may not use this file except in compliance
+ *  with the License.  You may obtain a copy of the License at
+ *
+ *        http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *  Unless required by applicable law or agreed to in writing,
+ *  software distributed under the License is distributed on an
+ *  "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ *  KIND, either express or implied.  See the License for the
+ *  specific language governing permissions and limitations
+ *  under the License.
+ */
+
+package org.apache.isis.core.progmodel.facets.collections.event;
+
+import java.lang.reflect.Field;
+import java.util.Collection;
+import java.util.List;
+
+import com.google.common.collect.Lists;
+
+import org.apache.isis.applib.FatalException;
+import org.apache.isis.applib.services.eventbus.AddedToCollectionEvent;
+import org.apache.isis.applib.services.eventbus.EventBusService;
+import org.apache.isis.core.metamodel.adapter.ObjectAdapter;
+import org.apache.isis.core.metamodel.adapter.ServicesProvider;
+import org.apache.isis.core.metamodel.adapter.mgr.AdapterManager;
+import org.apache.isis.core.metamodel.facetapi.Facet;
+import org.apache.isis.core.metamodel.facetapi.FacetHolder;
+import org.apache.isis.core.metamodel.facets.collections.event.PostsAddedToCollectionEventFacet;
+import org.apache.isis.core.metamodel.facets.collections.event.PostsCollectionAddToEventFacetAbstract;
+import org.apache.isis.core.metamodel.facets.collections.modify.CollectionAddToFacet;
+import org.apache.isis.core.metamodel.facets.collections.modify.CollectionFacet;
+
+public class PostsCollectionAddToEventFacetAnnotation extends
+		PostsCollectionAddToEventFacetAbstract {
+
+	private final CollectionAddToFacet collectionAddToFacet;
+	private final CollectionFacet collectionFacet;
+	private final ServicesProvider servicesProvider;
+
+	private EventBusService eventBusService;
+	private boolean searchedForEventBusService = false;
+	private Class<? extends AddedToCollectionEvent<?, ?>> addedToCollectionEventType;
+
+	public PostsCollectionAddToEventFacetAnnotation(
+			Class<? extends AddedToCollectionEvent<?, ?>> addedToCollectionEventType,
+			CollectionAddToFacet collectionAddToFacet,
+			CollectionFacet collectionFacet,
+			ServicesProvider servicesProvider, FacetHolder holder) {
+		super(holder);
+		this.addedToCollectionEventType = addedToCollectionEventType;
+		this.collectionAddToFacet = collectionAddToFacet;
+		this.collectionFacet = collectionFacet;
+		this.servicesProvider = servicesProvider;
+	}
+
+	@Override
+	public void add(ObjectAdapter inObject, ObjectAdapter value) {
+		if (this.collectionAddToFacet == null) {
+			return;
+		}
+		eventBusService = getEventBusService();
+		if (eventBusService == null) {
+			collectionAddToFacet.add(inObject, value);
+			return;
+		}
+
+		final Boolean previouslyExisting = this.collectionFacet.contains(
+				inObject, value);
+		if (!previouslyExisting) {
+			collectionAddToFacet.add(inObject, value);
+			postEvent(inObject, value);
+		}
+	}
+
+	@SuppressWarnings({ "rawtypes", "unchecked" })
+	private void postEvent(ObjectAdapter inObject,
+			final Object addedValue) {
+		final Object source = inObject.getObject();
+		try {
+			final Class type =  addedToCollectionEventType;
+			final AddedToCollectionEvent<?, ?> event = newEvent(type, addedValue, source);
+
+			eventBusService.post(event);
+		} catch (Exception e) {
+			throw new FatalException(e);
+		}
+	}
+
+
+	static <S, T> AddedToCollectionEvent<S, T> newEvent(
+			final Class<? extends AddedToCollectionEvent<S, T>> type,
+			final T addedValue, final S source)
+			throws InstantiationException, IllegalAccessException,
+			NoSuchFieldException {
+		final AddedToCollectionEvent<S, T> event = type.newInstance();
+
+		setField("source", event, source);
+		setField("addedValue", event, addedValue);
+		return event;
+	}
+
+	private static void setField(final String name,
+			final AddedToCollectionEvent<?, ?> event, final Object sourceValue)
+			throws NoSuchFieldException, IllegalAccessException {
+		final Field sourceField = AddedToCollectionEvent.class
+				.getDeclaredField(name);
+		sourceField.setAccessible(true);
+		sourceField.set(event, sourceValue);
+	}
+
+	private EventBusService getEventBusService() {
+		if (!searchedForEventBusService) {
+			final List<ObjectAdapter> serviceAdapters = servicesProvider
+					.getServices();
+			for (ObjectAdapter serviceAdapter : serviceAdapters) {
+				final Object service = serviceAdapter.getObject();
+				if (service instanceof EventBusService) {
+					eventBusService = (EventBusService) service;
+					break;
+				}
+			}
+		}
+		searchedForEventBusService = true;
+		return eventBusService;
+	}
+
+	// //////////////////////////////////////
+	// MultiTypedFacet
+
+	@SuppressWarnings("unchecked")
+	@Override
+	public Class<? extends Facet>[] facetTypes() {
+		return Lists.newArrayList(PostsAddedToCollectionEventFacet.class,
+				CollectionAddToFacet.class).toArray(
+				new Class[] {});
+	}
+
+	@SuppressWarnings("unchecked")
+	@Override
+	public <T extends Facet> T getFacet(Class<T> facet) {
+		return (T) this;
+	}
+
+
+
+}

http://git-wip-us.apache.org/repos/asf/isis/blob/548cb14f/core/metamodel/src/test/java/org/apache/isis/core/progmodel/facets/collections/event/PostsCollectionAddedEventFacetAnnotationTest_newEvent.java
----------------------------------------------------------------------
diff --git a/core/metamodel/src/test/java/org/apache/isis/core/progmodel/facets/collections/event/PostsCollectionAddedEventFacetAnnotationTest_newEvent.java b/core/metamodel/src/test/java/org/apache/isis/core/progmodel/facets/collections/event/PostsCollectionAddedEventFacetAnnotationTest_newEvent.java
new file mode 100644
index 0000000..ab89c44
--- /dev/null
+++ b/core/metamodel/src/test/java/org/apache/isis/core/progmodel/facets/collections/event/PostsCollectionAddedEventFacetAnnotationTest_newEvent.java
@@ -0,0 +1,41 @@
+/**
+ *  Licensed to the Apache Software Foundation (ASF) under one or more
+ *  contributor license agreements.  See the NOTICE file distributed with
+ *  this work for additional information regarding copyright ownership.
+ *  The ASF licenses this file to You under the Apache License, Version 2.0
+ *  (the "License"); you may not use this file except in compliance with
+ *  the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *  Unless required by applicable law or agreed to in writing, software
+ *  distributed under the License is distributed on an "AS IS" BASIS,
+ *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ *  See the License for the specific language governing permissions and
+ *  limitations under the License.
+ */
+package org.apache.isis.core.progmodel.facets.properties.event;
+
+import static org.hamcrest.CoreMatchers.is;
+import static org.junit.Assert.assertThat;
+
+import org.joda.time.LocalDate;
+import org.junit.Test;
+
+import org.apache.isis.applib.services.eventbus.PropertyChangedEvent;
+
+public class PostsCollectionAddedEventFacetAnnotationTest_newEvent {
+
+    public static class SomeDomainObject {}
+    
+    public static class SomeDomainObjectCollectionAddedEvent extends AddToCollectionEvent<SomeDomainObject, SomeDomainObject> {}
+    
+    @Test
+    public void test() throws Exception {
+        SomeDomainObject sdo = new SomeDomainObject();
+        final PropertyChangedEvent<SomeDomainObject, LocalDate> ev = PostsPropertyChangedEventFacetAnnotation.newEvent(SomeDatePropertyChangedEvent.class, new SomeDomainObject(), sdo);
+        assertThat(ev.getSource(), is(sdo));
+        assertThat(ev.getNewValue(), is(new LocalDate(2013,4,1)));
+    }
+
+}


[04/16] git commit: ISIS-550: PostsCollectionAddToEvent first-cut impl

Posted by da...@apache.org.
ISIS-550: PostsCollectionAddToEvent first-cut impl

... pretty much there.


Project: http://git-wip-us.apache.org/repos/asf/isis/repo
Commit: http://git-wip-us.apache.org/repos/asf/isis/commit/2637a055
Tree: http://git-wip-us.apache.org/repos/asf/isis/tree/2637a055
Diff: http://git-wip-us.apache.org/repos/asf/isis/diff/2637a055

Branch: refs/heads/master
Commit: 2637a0551f49c2373154cd00b78791039c8d7dc0
Parents: 43c50c4
Author: Dan Haywood <da...@haywood-associates.co.uk>
Authored: Wed May 7 08:53:41 2014 +0100
Committer: Dan Haywood <da...@haywood-associates.co.uk>
Committed: Wed May 7 08:53:41 2014 +0100

----------------------------------------------------------------------
 .../annotation/PostsCollectionAddedToEvent.java |   9 +-
 .../PostsCollectionRemovedFromEvent.java        |   9 +-
 .../annotation/PostsPropertyChangedEvent.java   |   9 +-
 .../isis/applib/annotation/WrapperPolicy.java   |  35 ++++
 .../eventbus/CollectionAddedToEvent.java        |  37 ++--
 .../eventbus/CollectionRemovedFromEvent.java    |  35 ++--
 .../services/eventbus/PropertyChangedEvent.java |  23 ++-
 .../applib/services/publish/EventPayload.java   |   2 +-
 .../ObjectResolveAndObjectChangedEnhancer.java  |   4 +-
 .../ObjectResolveAndObjectChangedEnhancer.java  |   4 +-
 .../core/metamodel/facets/ImperativeFacet.java  |  85 +++++++++
 .../metamodel/facets/ImperativeFacetUtils.java  |  76 ++------
 .../facets/PostsEventWithWrapperPolicy.java     |  61 +++++++
 .../event/PostsAddedToCollectionEventFacet.java |  34 ----
 .../PostsCollectionAddToEventFacetAbstract.java |  37 ----
 .../event/PostsCollectionAddedToEventFacet.java |  37 ++++
 ...ostsCollectionAddedToEventFacetAbstract.java |  55 ++++++
 .../event/PostsPropertyChangedEventFacet.java   |   3 +-
 .../PostsPropertyChangedEventFacetAbstract.java |  17 +-
 .../collection/CollectionFacetFactory.java      |   6 +-
 ...lectionAddToEventAnnotationFacetFactory.java | 117 -------------
 ...ostsCollectionAddToEventFacetAnnotation.java | 154 -----------------
 ...ctionAddedToEventAnnotationFacetFactory.java |  78 +++++++++
 ...tsCollectionAddedToEventFacetAnnotation.java | 173 +++++++++++++++++++
 ...pertyChangedEventAnnotationFacetFactory.java |  11 +-
 ...ostsPropertyChangedEventFacetAnnotation.java |  64 ++++---
 .../dflt/ProgrammingModelFacetsJava5.java       |   4 +
 .../facets/ImperativeFacetUtilsTest.java        |  16 +-
 ...nAddedEventFacetAnnotationTest_newEvent.java |  34 ++--
 ...hangedEventFacetAnnotationTest_newEvent.java |  14 +-
 .../AbstractCollectionInvocationHandler.java    |   7 +-
 .../handlers/DomainObjectInvocationHandler.java |  96 ++++++++--
 .../dom/src/main/java/dom/todo/ToDoItem.java    |  25 ++-
 .../java/dom/todo/ToDoItemSubscriptions.java    |  14 ++
 .../webapp/pom.xml                              |   4 +
 .../src/main/webapp/WEB-INF/isis.properties     |   1 +
 36 files changed, 884 insertions(+), 506 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/isis/blob/2637a055/core/applib/src/main/java/org/apache/isis/applib/annotation/PostsCollectionAddedToEvent.java
----------------------------------------------------------------------
diff --git a/core/applib/src/main/java/org/apache/isis/applib/annotation/PostsCollectionAddedToEvent.java b/core/applib/src/main/java/org/apache/isis/applib/annotation/PostsCollectionAddedToEvent.java
index e67be7f..04037b8 100644
--- a/core/applib/src/main/java/org/apache/isis/applib/annotation/PostsCollectionAddedToEvent.java
+++ b/core/applib/src/main/java/org/apache/isis/applib/annotation/PostsCollectionAddedToEvent.java
@@ -25,6 +25,7 @@ import java.lang.annotation.RetentionPolicy;
 import java.lang.annotation.Target;
 
 import org.apache.isis.applib.services.eventbus.CollectionAddedToEvent;
+import org.apache.isis.applib.services.wrapper.WrapperFactory;
 
 /**
  * Applies only to collections; any changes should be propagated as events to subscribers.  
@@ -58,6 +59,12 @@ public @interface PostsCollectionAddedToEvent {
      * <p>
      * This subclass must provide a no-arg constructor; the fields are set reflectively.
      */
-    Class<? extends CollectionAddedToEvent<?,?>> value();
+    Class<? extends CollectionAddedToEvent<?,?>> value() default CollectionAddedToEvent.Default.class;
+    
+    /**
+     * If invoked through the {@link WrapperFactory}, whether business rules (&quot;see it, use it, do it&quot;)
+     * should be enforced or not.
+     */
+    WrapperPolicy wrapperPolicy() default WrapperPolicy.ENFORCE_RULES;
 
 }

http://git-wip-us.apache.org/repos/asf/isis/blob/2637a055/core/applib/src/main/java/org/apache/isis/applib/annotation/PostsCollectionRemovedFromEvent.java
----------------------------------------------------------------------
diff --git a/core/applib/src/main/java/org/apache/isis/applib/annotation/PostsCollectionRemovedFromEvent.java b/core/applib/src/main/java/org/apache/isis/applib/annotation/PostsCollectionRemovedFromEvent.java
index f560434..f94851f 100644
--- a/core/applib/src/main/java/org/apache/isis/applib/annotation/PostsCollectionRemovedFromEvent.java
+++ b/core/applib/src/main/java/org/apache/isis/applib/annotation/PostsCollectionRemovedFromEvent.java
@@ -25,6 +25,7 @@ import java.lang.annotation.RetentionPolicy;
 import java.lang.annotation.Target;
 
 import org.apache.isis.applib.services.eventbus.CollectionRemovedFromEvent;
+import org.apache.isis.applib.services.wrapper.WrapperFactory;
 
 /**
  * Applies only to collections; any changes should be propagated as events to subscribers.  
@@ -58,6 +59,12 @@ public @interface PostsCollectionRemovedFromEvent {
      * <p>
      * This subclass must provide a no-arg constructor; the fields are set reflectively.
      */
-    Class<? extends CollectionRemovedFromEvent<?,?>> value();
+    Class<? extends CollectionRemovedFromEvent<?,?>> value() default CollectionRemovedFromEvent.Default.class;
+
+    /**
+     * If invoked through the {@link WrapperFactory}, whether business rules (&quot;see it, use it, do it&quot;)
+     * should be enforced or not.
+     */
+    WrapperPolicy wrapperPolicy() default WrapperPolicy.ENFORCE_RULES;
 
 }

http://git-wip-us.apache.org/repos/asf/isis/blob/2637a055/core/applib/src/main/java/org/apache/isis/applib/annotation/PostsPropertyChangedEvent.java
----------------------------------------------------------------------
diff --git a/core/applib/src/main/java/org/apache/isis/applib/annotation/PostsPropertyChangedEvent.java b/core/applib/src/main/java/org/apache/isis/applib/annotation/PostsPropertyChangedEvent.java
index f1d9491..b55c961 100644
--- a/core/applib/src/main/java/org/apache/isis/applib/annotation/PostsPropertyChangedEvent.java
+++ b/core/applib/src/main/java/org/apache/isis/applib/annotation/PostsPropertyChangedEvent.java
@@ -25,6 +25,7 @@ import java.lang.annotation.RetentionPolicy;
 import java.lang.annotation.Target;
 
 import org.apache.isis.applib.services.eventbus.PropertyChangedEvent;
+import org.apache.isis.applib.services.wrapper.WrapperFactory;
 
 /**
  * Applies only to properties; any changes should be propagated as events to subscribers.  
@@ -54,6 +55,12 @@ public @interface PostsPropertyChangedEvent {
      * <p>
      * This subclass must provide a no-arg constructor; the fields are set reflectively.
      */
-    Class<? extends PropertyChangedEvent<?,?>> value();
+    Class<? extends PropertyChangedEvent<?,?>> value() default PropertyChangedEvent.Default.class;
+
+    /**
+     * If invoked through the {@link WrapperFactory}, whether business rules (&quot;see it, use it, do it&quot;)
+     * should be enforced or not.
+     */
+    WrapperPolicy wrapperPolicy() default WrapperPolicy.ENFORCE_RULES;
 
 }

http://git-wip-us.apache.org/repos/asf/isis/blob/2637a055/core/applib/src/main/java/org/apache/isis/applib/annotation/WrapperPolicy.java
----------------------------------------------------------------------
diff --git a/core/applib/src/main/java/org/apache/isis/applib/annotation/WrapperPolicy.java b/core/applib/src/main/java/org/apache/isis/applib/annotation/WrapperPolicy.java
new file mode 100644
index 0000000..a69c817
--- /dev/null
+++ b/core/applib/src/main/java/org/apache/isis/applib/annotation/WrapperPolicy.java
@@ -0,0 +1,35 @@
+/*
+ *  Licensed to the Apache Software Foundation (ASF) under one
+ *  or more contributor license agreements.  See the NOTICE file
+ *  distributed with this work for additional information
+ *  regarding copyright ownership.  The ASF licenses this file
+ *  to you under the Apache License, Version 2.0 (the
+ *  "License"); you may not use this file except in compliance
+ *  with the License.  You may obtain a copy of the License at
+ *
+ *        http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *  Unless required by applicable law or agreed to in writing,
+ *  software distributed under the License is distributed on an
+ *  "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ *  KIND, either express or implied.  See the License for the
+ *  specific language governing permissions and limitations
+ *  under the License.
+ */
+package org.apache.isis.applib.annotation;
+
+import org.apache.isis.applib.services.wrapper.WrapperFactory;
+
+/**
+ * An attribute of {@link PostsPropertyChangedEvent}, {@link PostsCollectionAddedToEvent} and other related annotations;
+ * is a hint to indicate that if the object member is interacted with through a {@link WrapperFactory}, then whether 
+ * business rules (&quot;see it, use it, do it&quot;) should be enforced or not.
+ * 
+ * <p>
+ * This provides a half-way house between strictly UI-interactions and fully programmatic interactions, so that an 
+ * event can be fired programmatically even if the object is disabled in the UI.
+ */
+public enum WrapperPolicy {
+    ENFORCE_RULES,
+    SKIP_RULES
+}
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/isis/blob/2637a055/core/applib/src/main/java/org/apache/isis/applib/services/eventbus/CollectionAddedToEvent.java
----------------------------------------------------------------------
diff --git a/core/applib/src/main/java/org/apache/isis/applib/services/eventbus/CollectionAddedToEvent.java b/core/applib/src/main/java/org/apache/isis/applib/services/eventbus/CollectionAddedToEvent.java
index 10229f7..7b2d8f1 100644
--- a/core/applib/src/main/java/org/apache/isis/applib/services/eventbus/CollectionAddedToEvent.java
+++ b/core/applib/src/main/java/org/apache/isis/applib/services/eventbus/CollectionAddedToEvent.java
@@ -18,38 +18,55 @@
  */
 package org.apache.isis.applib.services.eventbus;
 
+import org.apache.isis.applib.Identifier;
 import org.apache.isis.applib.annotation.PostsPropertyChangedEvent;
 import org.apache.isis.applib.util.ObjectContracts;
 
 public abstract class CollectionAddedToEvent<S,T> {
+    
+    public static class Default extends CollectionAddedToEvent<Object, Object> {}
+
     private final S source;
-    private final T addedValue;
+    private final Identifier identifier;
+    private final T value;
     
     /**
      * To instantiate reflectively when the {@link PostsPropertyChangedEvent} annotation
      * is used.
      * 
      * <p>
-     * The fields ({@link #source} and {@link #addedValue} are then set reflectively.
+     * The fields ({@link #source} and {@link #value} are then set reflectively.
      */
     public CollectionAddedToEvent() {
-        this(null, null);
+        this(null, null, null);
     }
-    public CollectionAddedToEvent(S source, T addedValue) {
-        this.source = source;
-        this.addedValue = addedValue;
+    
+    /**
+     * @deprecated - use {@link #CollectionAddedToEvent(Object, Identifier, Object)}
+     */
+    @Deprecated
+    public CollectionAddedToEvent(S source, T value) {
+        this(source, null, value);
     }
 
+    public CollectionAddedToEvent(S source, Identifier identifier, T value) {
+        this.source = source;
+        this.identifier = identifier;
+        this.value = value;
+    }
+    
     public S getSource() {
         return source;
     }
-    
-    public T getAddedValue() {
-        return addedValue;
+    public Identifier getIdentifier() {
+        return identifier;
+    }
+    public T getValue() {
+        return value;
     }
     
     @Override
     public String toString() {
-        return ObjectContracts.toString(this, "source,addedValue");
+        return ObjectContracts.toString(this, "source,identifier,value");
     }
 }
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/isis/blob/2637a055/core/applib/src/main/java/org/apache/isis/applib/services/eventbus/CollectionRemovedFromEvent.java
----------------------------------------------------------------------
diff --git a/core/applib/src/main/java/org/apache/isis/applib/services/eventbus/CollectionRemovedFromEvent.java b/core/applib/src/main/java/org/apache/isis/applib/services/eventbus/CollectionRemovedFromEvent.java
index 84289da..17b8fed 100644
--- a/core/applib/src/main/java/org/apache/isis/applib/services/eventbus/CollectionRemovedFromEvent.java
+++ b/core/applib/src/main/java/org/apache/isis/applib/services/eventbus/CollectionRemovedFromEvent.java
@@ -18,37 +18,52 @@
  */
 package org.apache.isis.applib.services.eventbus;
 
+import org.apache.isis.applib.Identifier;
 import org.apache.isis.applib.util.ObjectContracts;
 
 public abstract class CollectionRemovedFromEvent<S,T> {
+    
+    public static class Default extends CollectionRemovedFromEvent<Object, Object> {}
+
     private final S source;
-    private final T removedValue;
+    private final Identifier identifier;
+    private final T value;
     
     /**
-     * To instantiate reflectively when the {@link PostsCollectionAddedToEvent} annotation
+     * To instantiate reflectively when the {@link PostsCollectionRemovedFromEvent} annotation
      * is used.
      * 
      * <p>
-     * The fields ({@link #source} and {@link #removedValue} are then set reflectively.
+     * The fields ({@link #source} and {@link #value} are then set reflectively.
      */
     public CollectionRemovedFromEvent() {
-        this(null, null);
+        this(null, null, null);
     }
-    public CollectionRemovedFromEvent(S source, T removedValue) {
+    /**
+     * @deprecated - use {@link #CollectionRemovedFromEvent(Object, Identifier, Object)}
+     */
+    @Deprecated
+    public CollectionRemovedFromEvent(S source, T value) {
+        this(source, null, value);
+    }
+    public CollectionRemovedFromEvent(S source, Identifier identifier, T value) {
         this.source = source;
-        this.removedValue = removedValue;
+        this.identifier = identifier;
+        this.value = value;
     }
 
     public S getSource() {
         return source;
     }
-    
-    public T getRemovedValue() {
-        return removedValue;
+    public Identifier getIdentifier() {
+        return identifier;
+    }
+    public T getValue() {
+        return value;
     }
     
     @Override
     public String toString() {
-        return ObjectContracts.toString(this, "source,removedValue");
+        return ObjectContracts.toString(this, "source,value");
     }
 }
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/isis/blob/2637a055/core/applib/src/main/java/org/apache/isis/applib/services/eventbus/PropertyChangedEvent.java
----------------------------------------------------------------------
diff --git a/core/applib/src/main/java/org/apache/isis/applib/services/eventbus/PropertyChangedEvent.java b/core/applib/src/main/java/org/apache/isis/applib/services/eventbus/PropertyChangedEvent.java
index e528867..9ae0afe 100644
--- a/core/applib/src/main/java/org/apache/isis/applib/services/eventbus/PropertyChangedEvent.java
+++ b/core/applib/src/main/java/org/apache/isis/applib/services/eventbus/PropertyChangedEvent.java
@@ -18,11 +18,16 @@
  */
 package org.apache.isis.applib.services.eventbus;
 
+import org.apache.isis.applib.Identifier;
 import org.apache.isis.applib.annotation.PostsPropertyChangedEvent;
 import org.apache.isis.applib.util.ObjectContracts;
 
 public abstract class PropertyChangedEvent<S,T> {
+    
+    public static class Default extends PropertyChangedEvent<Object, Object> {}
+    
     private final S source;
+    private final Identifier identifier;
     private final T oldValue;
     private final T newValue;
     
@@ -35,18 +40,30 @@ public abstract class PropertyChangedEvent<S,T> {
      * then set reflectively.
      */
     public PropertyChangedEvent() {
-        this(null, null, null);
+        this(null, null, null, null);
     }
+    
+    /**
+     * @deprecated - use {@link #PropertyChangedEvent(Object, Identifier, Object, Object)}.
+     */
+    @Deprecated
     public PropertyChangedEvent(S source, T oldValue, T newValue) {
+        this(source, null, oldValue, newValue);
+    }
+
+    public PropertyChangedEvent(S source, Identifier identifier, T oldValue, T newValue) {
         this.source = source;
+        this.identifier = identifier;
         this.oldValue = oldValue;
         this.newValue = newValue;
     }
-
+    
     public S getSource() {
         return source;
     }
-    
+    public Identifier getIdentifier() {
+        return identifier;
+    }
     public T getOldValue() {
         return oldValue;
     }

http://git-wip-us.apache.org/repos/asf/isis/blob/2637a055/core/applib/src/main/java/org/apache/isis/applib/services/publish/EventPayload.java
----------------------------------------------------------------------
diff --git a/core/applib/src/main/java/org/apache/isis/applib/services/publish/EventPayload.java b/core/applib/src/main/java/org/apache/isis/applib/services/publish/EventPayload.java
index cbeb1fd..4dd96e1 100644
--- a/core/applib/src/main/java/org/apache/isis/applib/services/publish/EventPayload.java
+++ b/core/applib/src/main/java/org/apache/isis/applib/services/publish/EventPayload.java
@@ -32,7 +32,7 @@ import org.apache.isis.applib.annotation.Programmatic;
  * This should be prepared in a way that can be processed by the {@link EventSerializer}.  For example:
  * <ul>
  * <li>The {@link EventSerializer.Simple simple event serializer} simply invokes
- * {@link Object#toString() toString()} on the payload.  Use the {@link Simple simple} implementation
+ * {@link Object#toString() toString()} on the payload.  Use the {@link Default simple} implementation
  * which simply wraps a string.
  * </li>
  * <li>The <tt>RestfulObjectsSpecEventSerializer</tt> event serializer expects a pojo domain object

http://git-wip-us.apache.org/repos/asf/isis/blob/2637a055/core/bytecode-cglib/src/main/java/org/apache/isis/core/bytecode/cglib/ObjectResolveAndObjectChangedEnhancer.java
----------------------------------------------------------------------
diff --git a/core/bytecode-cglib/src/main/java/org/apache/isis/core/bytecode/cglib/ObjectResolveAndObjectChangedEnhancer.java b/core/bytecode-cglib/src/main/java/org/apache/isis/core/bytecode/cglib/ObjectResolveAndObjectChangedEnhancer.java
index 64ce728..d5c68a7 100644
--- a/core/bytecode-cglib/src/main/java/org/apache/isis/core/bytecode/cglib/ObjectResolveAndObjectChangedEnhancer.java
+++ b/core/bytecode-cglib/src/main/java/org/apache/isis/core/bytecode/cglib/ObjectResolveAndObjectChangedEnhancer.java
@@ -29,8 +29,8 @@ import net.sf.cglib.proxy.MethodInterceptor;
 import net.sf.cglib.proxy.MethodProxy;
 
 import org.apache.isis.core.commons.lang.ArrayExtensions;
+import org.apache.isis.core.metamodel.facets.ImperativeFacet;
 import org.apache.isis.core.metamodel.facets.ImperativeFacetUtils;
-import org.apache.isis.core.metamodel.facets.ImperativeFacetUtils.ImperativeFacetFlags;
 import org.apache.isis.core.metamodel.spec.SpecificationLoaderSpi;
 import org.apache.isis.core.metamodel.spec.feature.ObjectMember;
 import org.apache.isis.core.metamodel.specloader.classsubstitutor.CglibEnhanced;
@@ -62,7 +62,7 @@ public class ObjectResolveAndObjectChangedEnhancer extends ObjectResolveAndObjec
             public Object intercept(final Object proxied, final Method proxiedMethod, final Object[] args, final MethodProxy proxyMethod) throws Throwable {
 
                 final boolean ignore = proxiedMethod.getDeclaringClass().equals(Object.class);
-                ImperativeFacetFlags flags = null;
+                ImperativeFacet.Flags flags = null;
 
                 if (!ignore) {
                     final ObjectSpecificationDefault targetObjSpec = getJavaSpecificationOfOwningClass(proxiedMethod);

http://git-wip-us.apache.org/repos/asf/isis/blob/2637a055/core/bytecode-javassist/src/main/java/org/apache/isis/core/bytecode/javassist/ObjectResolveAndObjectChangedEnhancer.java
----------------------------------------------------------------------
diff --git a/core/bytecode-javassist/src/main/java/org/apache/isis/core/bytecode/javassist/ObjectResolveAndObjectChangedEnhancer.java b/core/bytecode-javassist/src/main/java/org/apache/isis/core/bytecode/javassist/ObjectResolveAndObjectChangedEnhancer.java
index df4ded0..b1103b0 100644
--- a/core/bytecode-javassist/src/main/java/org/apache/isis/core/bytecode/javassist/ObjectResolveAndObjectChangedEnhancer.java
+++ b/core/bytecode-javassist/src/main/java/org/apache/isis/core/bytecode/javassist/ObjectResolveAndObjectChangedEnhancer.java
@@ -28,8 +28,8 @@ import javassist.util.proxy.ProxyObject;
 
 import org.apache.isis.core.commons.exceptions.IsisException;
 import org.apache.isis.core.commons.lang.ArrayExtensions;
+import org.apache.isis.core.metamodel.facets.ImperativeFacet;
 import org.apache.isis.core.metamodel.facets.ImperativeFacetUtils;
-import org.apache.isis.core.metamodel.facets.ImperativeFacetUtils.ImperativeFacetFlags;
 import org.apache.isis.core.metamodel.spec.SpecificationLoaderSpi;
 import org.apache.isis.core.metamodel.spec.feature.ObjectMember;
 import org.apache.isis.core.metamodel.specloader.specimpl.dflt.ObjectSpecificationDefault;
@@ -54,7 +54,7 @@ public class ObjectResolveAndObjectChangedEnhancer extends ObjectResolveAndObjec
             public Object invoke(final Object proxied, final Method proxyMethod, final Method proxiedMethod, final Object[] args) throws Throwable {
 
                 final boolean ignore = proxyMethod.getDeclaringClass().equals(Object.class);
-                ImperativeFacetFlags flags = null;
+                ImperativeFacet.Flags flags = null;
 
                 if (!ignore) {
                     final ObjectSpecificationDefault targetObjSpec = getJavaSpecificationOfOwningClass(proxiedMethod);

http://git-wip-us.apache.org/repos/asf/isis/blob/2637a055/core/metamodel/src/main/java/org/apache/isis/core/metamodel/facets/ImperativeFacet.java
----------------------------------------------------------------------
diff --git a/core/metamodel/src/main/java/org/apache/isis/core/metamodel/facets/ImperativeFacet.java b/core/metamodel/src/main/java/org/apache/isis/core/metamodel/facets/ImperativeFacet.java
index f1f0e90..f702496 100644
--- a/core/metamodel/src/main/java/org/apache/isis/core/metamodel/facets/ImperativeFacet.java
+++ b/core/metamodel/src/main/java/org/apache/isis/core/metamodel/facets/ImperativeFacet.java
@@ -24,6 +24,9 @@ import java.util.List;
 
 import org.apache.isis.applib.DomainObjectContainer;
 import org.apache.isis.applib.filter.Filter;
+import org.apache.isis.applib.filter.Filters;
+import org.apache.isis.core.commons.lang.ObjectExtensions;
+import org.apache.isis.core.metamodel.facetapi.DecoratingFacet;
 import org.apache.isis.core.metamodel.facetapi.Facet;
 import org.apache.isis.core.metamodel.facetapi.FacetHolder;
 import org.apache.isis.core.metamodel.spec.ObjectSpecification;
@@ -93,4 +96,86 @@ public interface ImperativeFacet {
      */
     public boolean impliesObjectChanged();
 
+
+    // //////////////////////////////////////
+
+    public static class Util {
+        private Util(){}
+
+        /**
+         * Returns the provided {@link Facet facet} as an {@link ImperativeFacet} if
+         * it either is one or if it is a {@link DecoratingFacet} that in turn wraps
+         * an {@link ImperativeFacet}.
+         * 
+         * <p>
+         * Otherwise, returns <tt>null</tt>.
+         */
+        public static ImperativeFacet getImperativeFacet(final Facet facet) {
+            if (facet instanceof ImperativeFacet) {
+                return (ImperativeFacet) facet;
+            }
+            if (facet.getUnderlyingFacet() instanceof ImperativeFacet) {
+                return (ImperativeFacet) facet.getUnderlyingFacet();
+            }
+            if (facet instanceof DecoratingFacet) {
+                final DecoratingFacet<?> decoratingFacet = ObjectExtensions.asT(facet);
+                return getImperativeFacet(decoratingFacet.getDecoratedFacet());
+            }
+            return null;
+        }
+        
+        public static boolean isImperativeFacet(final Facet facet) {
+            return getImperativeFacet(facet) != null;
+        }
+
+        public static Flags getImperativeFacetFlags(final ObjectMember member, final Method method) {
+            final Flags flags = new Flags();
+            if (member == null) {
+                return flags;
+            }
+            final List<Facet> allFacets = member.getFacets(Filters.anyOfType(Facet.class));
+            for (final Facet facet : allFacets) {
+                final ImperativeFacet imperativeFacet = ImperativeFacetUtils.getImperativeFacet(facet);
+                if (imperativeFacet == null) {
+                    continue;
+                }
+                final List<Method> methods = imperativeFacet.getMethods();
+                if (!methods.contains(method)) {
+                    continue;
+                }
+                flags.apply(imperativeFacet);
+
+                // no need to search further
+                if (flags.bothSet()) {
+                    break;
+                }
+            }
+            return flags;
+        }
+    }
+
+    public static class Flags {
+        private boolean impliesResolve;
+        private boolean impliesObjectChanged;
+
+        public void apply(final ImperativeFacet imperativeFacet) {
+            this.impliesResolve |= imperativeFacet.impliesResolve();
+            this.impliesObjectChanged |= imperativeFacet.impliesObjectChanged();
+        }
+
+        public boolean bothSet() {
+            return impliesResolve && impliesObjectChanged;
+        }
+
+        public boolean impliesResolve() {
+            return impliesResolve;
+        }
+
+        public boolean impliesObjectChanged() {
+            return impliesObjectChanged;
+        }
+    }
+
+
+
 }

http://git-wip-us.apache.org/repos/asf/isis/blob/2637a055/core/metamodel/src/main/java/org/apache/isis/core/metamodel/facets/ImperativeFacetUtils.java
----------------------------------------------------------------------
diff --git a/core/metamodel/src/main/java/org/apache/isis/core/metamodel/facets/ImperativeFacetUtils.java b/core/metamodel/src/main/java/org/apache/isis/core/metamodel/facets/ImperativeFacetUtils.java
index b4e0beb..049ba3e 100644
--- a/core/metamodel/src/main/java/org/apache/isis/core/metamodel/facets/ImperativeFacetUtils.java
+++ b/core/metamodel/src/main/java/org/apache/isis/core/metamodel/facets/ImperativeFacetUtils.java
@@ -23,8 +23,6 @@ import java.lang.reflect.Method;
 import java.util.List;
 
 import org.apache.isis.applib.filter.Filters;
-import org.apache.isis.core.commons.lang.ObjectExtensions;
-import org.apache.isis.core.metamodel.facetapi.DecoratingFacet;
 import org.apache.isis.core.metamodel.facetapi.Facet;
 import org.apache.isis.core.metamodel.spec.feature.ObjectMember;
 
@@ -34,73 +32,27 @@ public final class ImperativeFacetUtils {
     }
 
     /**
-     * Returns the provided {@link Facet facet} as an {@link ImperativeFacet} if
-     * it either is one or if it is a {@link DecoratingFacet} that in turn wraps
-     * an {@link ImperativeFacet}.
-     * 
-     * <p>
-     * Otherwise, returns <tt>null</tt>.
+     * @deprecated - use {@link ImperativeFacet.Util#getImperativeFacet(Facet)}
      */
+    @Deprecated
     public static ImperativeFacet getImperativeFacet(final Facet facet) {
-        if (facet instanceof ImperativeFacet) {
-            return (ImperativeFacet) facet;
-        }
-        if (facet instanceof DecoratingFacet) {
-            final DecoratingFacet<?> decoratingFacet = ObjectExtensions.asT(facet);
-            return getImperativeFacet(decoratingFacet.getDecoratedFacet());
-        }
-        return null;
+        return ImperativeFacet.Util.getImperativeFacet(facet);
     }
 
+    /**
+     * @deprecated - use {@link ImperativeFacet.Util#isImperativeFacet(Facet)}
+     */
+    @Deprecated
     public static boolean isImperativeFacet(final Facet facet) {
-        return getImperativeFacet(facet) != null;
+        return ImperativeFacet.Util.isImperativeFacet(facet);
     }
 
-    public static class ImperativeFacetFlags {
-        private boolean impliesResolve;
-        private boolean impliesObjectChanged;
-
-        public void apply(final ImperativeFacet imperativeFacet) {
-            this.impliesResolve |= imperativeFacet.impliesResolve();
-            this.impliesObjectChanged |= imperativeFacet.impliesObjectChanged();
-        }
-
-        public boolean bothSet() {
-            return impliesResolve && impliesObjectChanged;
-        }
-
-        public boolean impliesResolve() {
-            return impliesResolve;
-        }
-
-        public boolean impliesObjectChanged() {
-            return impliesObjectChanged;
-        }
-    }
-
-    public static ImperativeFacetFlags getImperativeFacetFlags(final ObjectMember member, final Method method) {
-        final ImperativeFacetFlags flags = new ImperativeFacetFlags();
-        if (member == null) {
-            return flags;
-        }
-        final List<Facet> allFacets = member.getFacets(Filters.anyOfType(Facet.class));
-        for (final Facet facet : allFacets) {
-            final ImperativeFacet imperativeFacet = ImperativeFacetUtils.getImperativeFacet(facet);
-            if (imperativeFacet == null) {
-                continue;
-            }
-            final List<Method> methods = imperativeFacet.getMethods();
-            if (!methods.contains(method)) {
-                continue;
-            }
-            flags.apply(imperativeFacet);
-
-            // no need to search further
-            if (flags.bothSet()) {
-                break;
-            }
-        }
-        return flags;
+    /**
+     * @deprecated - use {@link ImperativeFacet.Util#getImperativeFacet(Facet)}
+     */
+    @Deprecated
+    public static ImperativeFacet.Flags getImperativeFacetFlags(final ObjectMember member, final Method method) {
+        return ImperativeFacet.Util.getImperativeFacetFlags(member, method);
     }
 
 }

http://git-wip-us.apache.org/repos/asf/isis/blob/2637a055/core/metamodel/src/main/java/org/apache/isis/core/metamodel/facets/PostsEventWithWrapperPolicy.java
----------------------------------------------------------------------
diff --git a/core/metamodel/src/main/java/org/apache/isis/core/metamodel/facets/PostsEventWithWrapperPolicy.java b/core/metamodel/src/main/java/org/apache/isis/core/metamodel/facets/PostsEventWithWrapperPolicy.java
new file mode 100644
index 0000000..0c12c1c
--- /dev/null
+++ b/core/metamodel/src/main/java/org/apache/isis/core/metamodel/facets/PostsEventWithWrapperPolicy.java
@@ -0,0 +1,61 @@
+/*
+ *  Licensed to the Apache Software Foundation (ASF) under one
+ *  or more contributor license agreements.  See the NOTICE file
+ *  distributed with this work for additional information
+ *  regarding copyright ownership.  The ASF licenses this file
+ *  to you under the Apache License, Version 2.0 (the
+ *  "License"); you may not use this file except in compliance
+ *  with the License.  You may obtain a copy of the License at
+ *
+ *        http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *  Unless required by applicable law or agreed to in writing,
+ *  software distributed under the License is distributed on an
+ *  "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ *  KIND, either express or implied.  See the License for the
+ *  specific language governing permissions and limitations
+ *  under the License.
+ */
+
+package org.apache.isis.core.metamodel.facets;
+
+import org.apache.isis.applib.annotation.WrapperPolicy;
+import org.apache.isis.applib.services.eventbus.EventBusService;
+import org.apache.isis.applib.services.eventbus.PropertyChangedEvent;
+import org.apache.isis.core.commons.lang.ObjectExtensions;
+import org.apache.isis.core.metamodel.facetapi.DecoratingFacet;
+import org.apache.isis.core.metamodel.facetapi.Facet;
+import org.apache.isis.core.metamodel.facetapi.MultiTypedFacet;
+import org.apache.isis.core.metamodel.facets.properties.modify.PropertyClearFacet;
+import org.apache.isis.core.metamodel.facets.properties.modify.PropertySetterFacet;
+
+public interface PostsEventWithWrapperPolicy {
+
+    WrapperPolicy getWrapperPolicy();
+    
+    public static class Util {
+        private Util(){}
+
+        /**
+         * Returns the provided {@link Facet facet} as an {@link PostsEventWithWrapperPolicy} if
+         * it either is one or if it is a {@link DecoratingFacet} that in turn wraps
+         * an {@link PostsEventWithWrapperPolicy}.
+         * 
+         * <p>
+         * Otherwise, returns <tt>null</tt>.
+         */
+        public static PostsEventWithWrapperPolicy getWrapperPolicyFacet(final Facet facet) {
+            if (facet instanceof PostsEventWithWrapperPolicy) {
+                return (PostsEventWithWrapperPolicy) facet;
+            }
+            if (facet.getUnderlyingFacet() instanceof PostsEventWithWrapperPolicy) {
+                return (PostsEventWithWrapperPolicy) facet.getUnderlyingFacet();
+            }
+            if (facet instanceof DecoratingFacet) {
+                final DecoratingFacet<?> decoratingFacet = ObjectExtensions.asT(facet);
+                return getWrapperPolicyFacet(decoratingFacet.getDecoratedFacet());
+            }
+            return null;
+        }
+    }
+}

http://git-wip-us.apache.org/repos/asf/isis/blob/2637a055/core/metamodel/src/main/java/org/apache/isis/core/metamodel/facets/collections/event/PostsAddedToCollectionEventFacet.java
----------------------------------------------------------------------
diff --git a/core/metamodel/src/main/java/org/apache/isis/core/metamodel/facets/collections/event/PostsAddedToCollectionEventFacet.java b/core/metamodel/src/main/java/org/apache/isis/core/metamodel/facets/collections/event/PostsAddedToCollectionEventFacet.java
deleted file mode 100644
index b2f6c18..0000000
--- a/core/metamodel/src/main/java/org/apache/isis/core/metamodel/facets/collections/event/PostsAddedToCollectionEventFacet.java
+++ /dev/null
@@ -1,34 +0,0 @@
-/*
- *  Licensed to the Apache Software Foundation (ASF) under one
- *  or more contributor license agreements.  See the NOTICE file
- *  distributed with this work for additional information
- *  regarding copyright ownership.  The ASF licenses this file
- *  to you under the Apache License, Version 2.0 (the
- *  "License"); you may not use this file except in compliance
- *  with the License.  You may obtain a copy of the License at
- *
- *        http://www.apache.org/licenses/LICENSE-2.0
- *
- *  Unless required by applicable law or agreed to in writing,
- *  software distributed under the License is distributed on an
- *  "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- *  KIND, either express or implied.  See the License for the
- *  specific language governing permissions and limitations
- *  under the License.
- */
-
-package org.apache.isis.core.metamodel.facets.collections.event;
-
-import org.apache.isis.applib.services.eventbus.EventBusService;
-import org.apache.isis.applib.services.eventbus.PropertyChangedEvent;
-import org.apache.isis.core.metamodel.facetapi.Facet;
-import org.apache.isis.core.metamodel.facetapi.MultiTypedFacet;
-import org.apache.isis.core.metamodel.facets.collections.modify.CollectionAddToFacet;
-
-/**
- * Indicates that (the specified subclass of) {@link PropertyChangedEvent} should be posted to the
- * {@link EventBusService}.
- */
-public interface PostsAddedToCollectionEventFacet extends CollectionAddToFacet, MultiTypedFacet, Facet {
-
-}

http://git-wip-us.apache.org/repos/asf/isis/blob/2637a055/core/metamodel/src/main/java/org/apache/isis/core/metamodel/facets/collections/event/PostsCollectionAddToEventFacetAbstract.java
----------------------------------------------------------------------
diff --git a/core/metamodel/src/main/java/org/apache/isis/core/metamodel/facets/collections/event/PostsCollectionAddToEventFacetAbstract.java b/core/metamodel/src/main/java/org/apache/isis/core/metamodel/facets/collections/event/PostsCollectionAddToEventFacetAbstract.java
deleted file mode 100644
index 44eec96..0000000
--- a/core/metamodel/src/main/java/org/apache/isis/core/metamodel/facets/collections/event/PostsCollectionAddToEventFacetAbstract.java
+++ /dev/null
@@ -1,37 +0,0 @@
-/*
- *  Licensed to the Apache Software Foundation (ASF) under one
- *  or more contributor license agreements.  See the NOTICE file
- *  distributed with this work for additional information
- *  regarding copyright ownership.  The ASF licenses this file
- *  to you under the Apache License, Version 2.0 (the
- *  "License"); you may not use this file except in compliance
- *  with the License.  You may obtain a copy of the License at
- *
- *        http://www.apache.org/licenses/LICENSE-2.0
- *
- *  Unless required by applicable law or agreed to in writing,
- *  software distributed under the License is distributed on an
- *  "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- *  KIND, either express or implied.  See the License for the
- *  specific language governing permissions and limitations
- *  under the License.
- */
-
-package org.apache.isis.core.metamodel.facets.collections.event;
-
-import org.apache.isis.core.metamodel.facetapi.Facet;
-import org.apache.isis.core.metamodel.facetapi.FacetHolder;
-import org.apache.isis.core.metamodel.facets.collections.CollectionFacetAbstract;
-
-public abstract class PostsCollectionAddToEventFacetAbstract extends CollectionFacetAbstract implements PostsAddedToCollectionEventFacet {
-
-	public PostsCollectionAddToEventFacetAbstract(FacetHolder holder) {
-		super(holder);
-	}
-
-	public static Class<? extends Facet> type() {
-        return PostsAddedToCollectionEventFacet.class;
-    }
-	
-	  
-}

http://git-wip-us.apache.org/repos/asf/isis/blob/2637a055/core/metamodel/src/main/java/org/apache/isis/core/metamodel/facets/collections/event/PostsCollectionAddedToEventFacet.java
----------------------------------------------------------------------
diff --git a/core/metamodel/src/main/java/org/apache/isis/core/metamodel/facets/collections/event/PostsCollectionAddedToEventFacet.java b/core/metamodel/src/main/java/org/apache/isis/core/metamodel/facets/collections/event/PostsCollectionAddedToEventFacet.java
new file mode 100644
index 0000000..91d7d3c
--- /dev/null
+++ b/core/metamodel/src/main/java/org/apache/isis/core/metamodel/facets/collections/event/PostsCollectionAddedToEventFacet.java
@@ -0,0 +1,37 @@
+/*
+ *  Licensed to the Apache Software Foundation (ASF) under one
+ *  or more contributor license agreements.  See the NOTICE file
+ *  distributed with this work for additional information
+ *  regarding copyright ownership.  The ASF licenses this file
+ *  to you under the Apache License, Version 2.0 (the
+ *  "License"); you may not use this file except in compliance
+ *  with the License.  You may obtain a copy of the License at
+ *
+ *        http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *  Unless required by applicable law or agreed to in writing,
+ *  software distributed under the License is distributed on an
+ *  "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ *  KIND, either express or implied.  See the License for the
+ *  specific language governing permissions and limitations
+ *  under the License.
+ */
+
+package org.apache.isis.core.metamodel.facets.collections.event;
+
+import org.apache.isis.applib.services.eventbus.CollectionAddedToEvent;
+import org.apache.isis.applib.services.eventbus.EventBusService;
+import org.apache.isis.applib.services.eventbus.PropertyChangedEvent;
+import org.apache.isis.core.metamodel.facetapi.Facet;
+import org.apache.isis.core.metamodel.facetapi.MultiTypedFacet;
+import org.apache.isis.core.metamodel.facets.PostsEventWithWrapperPolicy;
+import org.apache.isis.core.metamodel.facets.SingleValueFacet;
+import org.apache.isis.core.metamodel.facets.collections.modify.CollectionAddToFacet;
+
+/**
+ * Indicates that (the specified subclass of) {@link CollectionAddedToEvent} should be posted to the
+ * {@link EventBusService}.
+ */
+public interface PostsCollectionAddedToEventFacet extends SingleValueFacet<Class<? extends CollectionAddedToEvent<?,?>>>, CollectionAddToFacet, MultiTypedFacet, PostsEventWithWrapperPolicy {
+}
+

http://git-wip-us.apache.org/repos/asf/isis/blob/2637a055/core/metamodel/src/main/java/org/apache/isis/core/metamodel/facets/collections/event/PostsCollectionAddedToEventFacetAbstract.java
----------------------------------------------------------------------
diff --git a/core/metamodel/src/main/java/org/apache/isis/core/metamodel/facets/collections/event/PostsCollectionAddedToEventFacetAbstract.java b/core/metamodel/src/main/java/org/apache/isis/core/metamodel/facets/collections/event/PostsCollectionAddedToEventFacetAbstract.java
new file mode 100644
index 0000000..4f89185
--- /dev/null
+++ b/core/metamodel/src/main/java/org/apache/isis/core/metamodel/facets/collections/event/PostsCollectionAddedToEventFacetAbstract.java
@@ -0,0 +1,55 @@
+/*
+ *  Licensed to the Apache Software Foundation (ASF) under one
+ *  or more contributor license agreements.  See the NOTICE file
+ *  distributed with this work for additional information
+ *  regarding copyright ownership.  The ASF licenses this file
+ *  to you under the Apache License, Version 2.0 (the
+ *  "License"); you may not use this file except in compliance
+ *  with the License.  You may obtain a copy of the License at
+ *
+ *        http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *  Unless required by applicable law or agreed to in writing,
+ *  software distributed under the License is distributed on an
+ *  "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ *  KIND, either express or implied.  See the License for the
+ *  specific language governing permissions and limitations
+ *  under the License.
+ */
+
+package org.apache.isis.core.metamodel.facets.collections.event;
+
+import org.apache.isis.applib.annotation.WrapperPolicy;
+import org.apache.isis.applib.services.eventbus.CollectionAddedToEvent;
+import org.apache.isis.core.metamodel.facetapi.Facet;
+import org.apache.isis.core.metamodel.facetapi.FacetHolder;
+import org.apache.isis.core.metamodel.facets.SingleValueFacetAbstract;
+import org.apache.isis.core.metamodel.facets.collections.modify.CollectionAddToFacet;
+
+
+public abstract class PostsCollectionAddedToEventFacetAbstract 
+    extends SingleValueFacetAbstract<Class<? extends CollectionAddedToEvent<?,?>>> 
+    implements PostsCollectionAddedToEventFacet {
+
+	public static Class<? extends Facet> type() {
+	    
+	    // the "primary" type is CollectionAddToFacet rather than PostsAddedToCollectionEventFacet
+	    // so that this facet can wrap an existing (via setUnderlying).
+	    
+        //return PostsAddedToCollectionEventFacet.class;
+	    return CollectionAddToFacet.class;
+    }
+
+    private final WrapperPolicy wrapperPolicy;
+
+    public PostsCollectionAddedToEventFacetAbstract(Class<? extends CollectionAddedToEvent<?, ?>> changedEventType, WrapperPolicy wrapperPolicy, FacetHolder holder) {
+        super(type(), changedEventType, holder);
+        this.wrapperPolicy = wrapperPolicy;
+    }
+
+    @Override
+    public WrapperPolicy getWrapperPolicy() {
+        return wrapperPolicy;
+    }
+
+}

http://git-wip-us.apache.org/repos/asf/isis/blob/2637a055/core/metamodel/src/main/java/org/apache/isis/core/metamodel/facets/properties/event/PostsPropertyChangedEventFacet.java
----------------------------------------------------------------------
diff --git a/core/metamodel/src/main/java/org/apache/isis/core/metamodel/facets/properties/event/PostsPropertyChangedEventFacet.java b/core/metamodel/src/main/java/org/apache/isis/core/metamodel/facets/properties/event/PostsPropertyChangedEventFacet.java
index a01e7f4..e5c108f 100644
--- a/core/metamodel/src/main/java/org/apache/isis/core/metamodel/facets/properties/event/PostsPropertyChangedEventFacet.java
+++ b/core/metamodel/src/main/java/org/apache/isis/core/metamodel/facets/properties/event/PostsPropertyChangedEventFacet.java
@@ -22,6 +22,7 @@ package org.apache.isis.core.metamodel.facets.properties.event;
 import org.apache.isis.applib.services.eventbus.EventBusService;
 import org.apache.isis.applib.services.eventbus.PropertyChangedEvent;
 import org.apache.isis.core.metamodel.facetapi.MultiTypedFacet;
+import org.apache.isis.core.metamodel.facets.PostsEventWithWrapperPolicy;
 import org.apache.isis.core.metamodel.facets.SingleValueFacet;
 import org.apache.isis.core.metamodel.facets.properties.modify.PropertyClearFacet;
 import org.apache.isis.core.metamodel.facets.properties.modify.PropertySetterFacet;
@@ -30,6 +31,6 @@ import org.apache.isis.core.metamodel.facets.properties.modify.PropertySetterFac
  * Indicates that (the specified subclass of) {@link PropertyChangedEvent} should be posted to the
  * {@link EventBusService}.
  */
-public interface PostsPropertyChangedEventFacet extends SingleValueFacet<Class<? extends PropertyChangedEvent<?,?>>>, PropertyClearFacet, PropertySetterFacet, MultiTypedFacet {
+public interface PostsPropertyChangedEventFacet extends SingleValueFacet<Class<? extends PropertyChangedEvent<?,?>>>, PropertyClearFacet, PropertySetterFacet, MultiTypedFacet, PostsEventWithWrapperPolicy {
 
 }

http://git-wip-us.apache.org/repos/asf/isis/blob/2637a055/core/metamodel/src/main/java/org/apache/isis/core/metamodel/facets/properties/event/PostsPropertyChangedEventFacetAbstract.java
----------------------------------------------------------------------
diff --git a/core/metamodel/src/main/java/org/apache/isis/core/metamodel/facets/properties/event/PostsPropertyChangedEventFacetAbstract.java b/core/metamodel/src/main/java/org/apache/isis/core/metamodel/facets/properties/event/PostsPropertyChangedEventFacetAbstract.java
index 281438a..69ff6a0 100644
--- a/core/metamodel/src/main/java/org/apache/isis/core/metamodel/facets/properties/event/PostsPropertyChangedEventFacetAbstract.java
+++ b/core/metamodel/src/main/java/org/apache/isis/core/metamodel/facets/properties/event/PostsPropertyChangedEventFacetAbstract.java
@@ -19,19 +19,32 @@
 
 package org.apache.isis.core.metamodel.facets.properties.event;
 
+import org.apache.isis.applib.annotation.WrapperPolicy;
 import org.apache.isis.applib.services.eventbus.PropertyChangedEvent;
 import org.apache.isis.core.metamodel.facetapi.Facet;
 import org.apache.isis.core.metamodel.facetapi.FacetHolder;
 import org.apache.isis.core.metamodel.facets.SingleValueFacetAbstract;
 
-public abstract class PostsPropertyChangedEventFacetAbstract extends SingleValueFacetAbstract<Class<? extends PropertyChangedEvent<?,?>>> implements PostsPropertyChangedEventFacet {
+public abstract class PostsPropertyChangedEventFacetAbstract 
+        extends SingleValueFacetAbstract<Class<? extends PropertyChangedEvent<?,?>>> 
+        implements PostsPropertyChangedEventFacet {
 
     public static Class<? extends Facet> type() {
+        // different implementation to PostsCollectionAddToEventFacet (for example) because this facet wraps
+        // multiple facets and so we cannot use the setUnderlyingFacet capability.
         return PostsPropertyChangedEventFacet.class;
     }
 
-    public PostsPropertyChangedEventFacetAbstract(final Class<? extends PropertyChangedEvent<?,?>> changedEventType, final FacetHolder holder) {
+    private final WrapperPolicy wrapperPolicy;
+
+    public PostsPropertyChangedEventFacetAbstract(final Class<? extends PropertyChangedEvent<?,?>> changedEventType, final WrapperPolicy wrapperPolicy, final FacetHolder holder) {
         super(type(), changedEventType, holder);
+        this.wrapperPolicy = wrapperPolicy;
+    }
+
+    @Override
+    public WrapperPolicy getWrapperPolicy() {
+        return wrapperPolicy;
     }
 
 }

http://git-wip-us.apache.org/repos/asf/isis/blob/2637a055/core/metamodel/src/main/java/org/apache/isis/core/progmodel/facets/collections/collection/CollectionFacetFactory.java
----------------------------------------------------------------------
diff --git a/core/metamodel/src/main/java/org/apache/isis/core/progmodel/facets/collections/collection/CollectionFacetFactory.java b/core/metamodel/src/main/java/org/apache/isis/core/progmodel/facets/collections/collection/CollectionFacetFactory.java
index cbaa8f5..9b4b4a5 100644
--- a/core/metamodel/src/main/java/org/apache/isis/core/progmodel/facets/collections/collection/CollectionFacetFactory.java
+++ b/core/metamodel/src/main/java/org/apache/isis/core/progmodel/facets/collections/collection/CollectionFacetFactory.java
@@ -51,11 +51,11 @@ public class CollectionFacetFactory extends FacetFactoryAbstract implements Coll
 
     }
 
-    private void processCollectionType(final ProcessClassContext processClassContaxt) {
-        final FacetHolder facetHolder = processClassContaxt.getFacetHolder();
+    private void processCollectionType(final ProcessClassContext processClassContext) {
+        final FacetHolder facetHolder = processClassContext.getFacetHolder();
         final TypeOfFacet typeOfFacet = facetHolder.getFacet(TypeOfFacet.class);
         if (typeOfFacet == null) {
-            final Class<?> collectionElementType = collectionElementType(processClassContaxt.getCls());
+            final Class<?> collectionElementType = collectionElementType(processClassContext.getCls());
             facetHolder.addFacet(collectionElementType != Object.class ? new TypeOfFacetInferredFromGenerics(collectionElementType, facetHolder, getSpecificationLoader()) : new TypeOfFacetDefaultToObject(facetHolder, getSpecificationLoader()));
         } else {
             // nothing

http://git-wip-us.apache.org/repos/asf/isis/blob/2637a055/core/metamodel/src/main/java/org/apache/isis/core/progmodel/facets/collections/event/PostsCollectionAddToEventAnnotationFacetFactory.java
----------------------------------------------------------------------
diff --git a/core/metamodel/src/main/java/org/apache/isis/core/progmodel/facets/collections/event/PostsCollectionAddToEventAnnotationFacetFactory.java b/core/metamodel/src/main/java/org/apache/isis/core/progmodel/facets/collections/event/PostsCollectionAddToEventAnnotationFacetFactory.java
deleted file mode 100644
index 408a144..0000000
--- a/core/metamodel/src/main/java/org/apache/isis/core/progmodel/facets/collections/event/PostsCollectionAddToEventAnnotationFacetFactory.java
+++ /dev/null
@@ -1,117 +0,0 @@
-/*
- *  Licensed to the Apache Software Foundation (ASF) under one
- *  or more contributor license agreements.  See the NOTICE file
- *  distributed with this work for additional information
- *  regarding copyright ownership.  The ASF licenses this file
- *  to you under the Apache License, Version 2.0 (the
- *  "License"); you may not use this file except in compliance
- *  with the License.  You may obtain a copy of the License at
- *
- *        http://www.apache.org/licenses/LICENSE-2.0
- *
- *  Unless required by applicable law or agreed to in writing,
- *  software distributed under the License is distributed on an
- *  "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- *  KIND, either express or implied.  See the License for the
- *  specific language governing permissions and limitations
- *  under the License.
- */
-
-package org.apache.isis.core.progmodel.facets.collections.event;
-
-import java.lang.reflect.Method;
-import java.util.Comparator;
-import java.util.List;
-
-import org.apache.isis.applib.annotation.PostsCollectionAddedToEvent;
-import org.apache.isis.applib.services.eventbus.CollectionAddedToEvent;
-import org.apache.isis.core.commons.config.IsisConfiguration;
-import org.apache.isis.core.metamodel.adapter.ServicesProvider;
-import org.apache.isis.core.metamodel.adapter.ServicesProviderAware;
-import org.apache.isis.core.metamodel.facetapi.FacetHolder;
-import org.apache.isis.core.metamodel.facetapi.FacetUtil;
-import org.apache.isis.core.metamodel.facetapi.FeatureType;
-import org.apache.isis.core.metamodel.facetapi.MetaModelValidatorRefiner;
-import org.apache.isis.core.metamodel.facets.Annotations;
-import org.apache.isis.core.metamodel.facets.FacetFactoryAbstract;
-import org.apache.isis.core.metamodel.facets.collections.modify.CollectionAddToFacet;
-import org.apache.isis.core.metamodel.facets.collections.modify.CollectionFacet;
-import org.apache.isis.core.metamodel.facets.collections.sortedby.SortedByFacet;
-import org.apache.isis.core.metamodel.facets.collections.event.PostsAddedToCollectionEventFacet;
-import org.apache.isis.core.metamodel.spec.ObjectSpecification;
-import org.apache.isis.core.metamodel.spec.feature.Contributed;
-import org.apache.isis.core.metamodel.spec.feature.OneToManyAssociation;
-import org.apache.isis.core.metamodel.specloader.validator.MetaModelValidatorComposite;
-import org.apache.isis.core.metamodel.specloader.validator.MetaModelValidatorVisiting;
-import org.apache.isis.core.metamodel.specloader.validator.MetaModelValidatorVisiting.Visitor;
-import org.apache.isis.core.metamodel.specloader.validator.ValidationFailures;
-
-public class PostsCollectionAddToEventAnnotationFacetFactory extends FacetFactoryAbstract implements ServicesProviderAware, MetaModelValidatorRefiner {
-
-    private ServicesProvider servicesProvider;
-
-    public PostsCollectionAddToEventAnnotationFacetFactory() {
-        super(FeatureType.PROPERTIES_ONLY);
-    }
-
-    @Override
-    public void process(final ProcessMethodContext processMethodContext) {
-        final Method method = processMethodContext.getMethod();
-        FacetUtil.addFacet(create(method, processMethodContext.getFacetHolder()));
-    }
-
-    private PostsAddedToCollectionEventFacet create(Method method, final FacetHolder holder) {
-        final PostsCollectionAddedToEvent annotation = Annotations.getAnnotation(method, PostsCollectionAddedToEvent.class);
-        if(annotation == null) {
-            return null;
-        }
-        final PostsAddedToCollectionEventFacet postsAddedToCollectionEventFacet = holder.getFacet(PostsAddedToCollectionEventFacet.class);
-        if(postsAddedToCollectionEventFacet == null) {
-            return null;
-        } 
-        final CollectionAddToFacet collectionAddToFacet = holder.getFacet(CollectionAddToFacet.class);
-        final CollectionFacet collectionFacet = holder.getFacet(CollectionFacet.class);
-        if(postsAddedToCollectionEventFacet != null) {
-            holder.removeFacet(postsAddedToCollectionEventFacet);
-        }
-        if(collectionAddToFacet != null) {
-            holder.removeFacet(collectionAddToFacet);
-        }
-        if(collectionFacet != null) {
-            holder.removeFacet(collectionFacet);
-        }
-        final Class<? extends CollectionAddedToEvent<?,?>> changedEventType = annotation.value();
-        return new PostsCollectionAddToEventFacetAnnotation(changedEventType, postsAddedToCollectionEventFacet, collectionAddToFacet, collectionFacet, servicesProvider, holder);
-    }
-
-    @Override
-    public void setServicesProvider(ServicesProvider servicesProvider) {
-        this.servicesProvider = servicesProvider;
-    }
-
-    @Override
-    public void refineMetaModelValidator(MetaModelValidatorComposite metaModelValidator, IsisConfiguration configuration) {
-        metaModelValidator.add(new MetaModelValidatorVisiting(newValidatorVisitor()));
-    }
-
-    protected Visitor newValidatorVisitor() {
-        return new MetaModelValidatorVisiting.Visitor() {
-
-            @Override
-            public boolean visit(ObjectSpecification objectSpec, ValidationFailures validationFailures) {
-                List<OneToManyAssociation> objectCollections = objectSpec.getCollections(Contributed.EXCLUDED);
-                for (OneToManyAssociation objectCollection : objectCollections) {
-                    final SortedByFacet facet = objectCollection.getFacet(SortedByFacet.class);
-                    if(facet != null) {
-                        final Class<? extends Comparator<?>> cls = facet.value();
-                        if(!Comparator.class.isAssignableFrom(cls)) {
-                            validationFailures.add("%s#%s is annotated with @SortedBy, but the class specified '%s' is not a Comparator", objectSpec.getIdentifier().getClassName(), objectCollection.getId(), facet.value().getName());
-                        }
-                    }
-                }
-                return true;
-            }
-        };
-    }
-
-}

http://git-wip-us.apache.org/repos/asf/isis/blob/2637a055/core/metamodel/src/main/java/org/apache/isis/core/progmodel/facets/collections/event/PostsCollectionAddToEventFacetAnnotation.java
----------------------------------------------------------------------
diff --git a/core/metamodel/src/main/java/org/apache/isis/core/progmodel/facets/collections/event/PostsCollectionAddToEventFacetAnnotation.java b/core/metamodel/src/main/java/org/apache/isis/core/progmodel/facets/collections/event/PostsCollectionAddToEventFacetAnnotation.java
deleted file mode 100644
index 8318cdb..0000000
--- a/core/metamodel/src/main/java/org/apache/isis/core/progmodel/facets/collections/event/PostsCollectionAddToEventFacetAnnotation.java
+++ /dev/null
@@ -1,154 +0,0 @@
-/*
- *  Licensed to the Apache Software Foundation (ASF) under one
- *  or more contributor license agreements.  See the NOTICE file
- *  distributed with this work for additional information
- *  regarding copyright ownership.  The ASF licenses this file
- *  to you under the Apache License, Version 2.0 (the
- *  "License"); you may not use this file except in compliance
- *  with the License.  You may obtain a copy of the License at
- *
- *        http://www.apache.org/licenses/LICENSE-2.0
- *
- *  Unless required by applicable law or agreed to in writing,
- *  software distributed under the License is distributed on an
- *  "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- *  KIND, either express or implied.  See the License for the
- *  specific language governing permissions and limitations
- *  under the License.
- */
-
-package org.apache.isis.core.progmodel.facets.collections.event;
-
-import java.lang.reflect.Field;
-import java.util.Collection;
-import java.util.List;
-
-import com.google.common.collect.Lists;
-
-import org.apache.isis.applib.FatalException;
-import org.apache.isis.applib.services.eventbus.CollectionAddedToEvent;
-import org.apache.isis.applib.services.eventbus.EventBusService;
-import org.apache.isis.core.metamodel.adapter.ObjectAdapter;
-import org.apache.isis.core.metamodel.adapter.ServicesProvider;
-import org.apache.isis.core.metamodel.adapter.mgr.AdapterManager;
-import org.apache.isis.core.metamodel.facetapi.Facet;
-import org.apache.isis.core.metamodel.facetapi.FacetHolder;
-import org.apache.isis.core.metamodel.facets.collections.event.PostsAddedToCollectionEventFacet;
-import org.apache.isis.core.metamodel.facets.collections.event.PostsCollectionAddToEventFacetAbstract;
-import org.apache.isis.core.metamodel.facets.collections.modify.CollectionAddToFacet;
-import org.apache.isis.core.metamodel.facets.collections.modify.CollectionFacet;
-
-public class PostsCollectionAddToEventFacetAnnotation extends
-		PostsCollectionAddToEventFacetAbstract {
-
-	private final CollectionAddToFacet collectionAddToFacet;
-	private final CollectionFacet collectionFacet;
-	private final ServicesProvider servicesProvider;
-
-	private EventBusService eventBusService;
-	private boolean searchedForEventBusService = false;
-	private Class<? extends CollectionAddedToEvent<?, ?>> addedToCollectionEventType;
-
-	public PostsCollectionAddToEventFacetAnnotation(
-			Class<? extends CollectionAddedToEvent<?, ?>> addedToCollectionEventType,
-			CollectionAddToFacet collectionAddToFacet,
-			CollectionFacet collectionFacet,
-			ServicesProvider servicesProvider, FacetHolder holder) {
-		super(holder);
-		this.addedToCollectionEventType = addedToCollectionEventType;
-		this.collectionAddToFacet = collectionAddToFacet;
-		this.collectionFacet = collectionFacet;
-		this.servicesProvider = servicesProvider;
-	}
-
-	@Override
-	public void add(ObjectAdapter inObject, ObjectAdapter value) {
-		if (this.collectionAddToFacet == null) {
-			return;
-		}
-		eventBusService = getEventBusService();
-		if (eventBusService == null) {
-			collectionAddToFacet.add(inObject, value);
-			return;
-		}
-
-		final Boolean previouslyExisting = this.collectionFacet.contains(
-				inObject, value);
-		if (!previouslyExisting) {
-			collectionAddToFacet.add(inObject, value);
-			postEvent(inObject, value);
-		}
-	}
-
-	@SuppressWarnings({ "rawtypes", "unchecked" })
-	private void postEvent(ObjectAdapter inObject,
-			final Object addedValue) {
-		final Object source = inObject.getObject();
-		try {
-			final Class type =  addedToCollectionEventType;
-			final CollectionAddedToEvent<?, ?> event = newEvent(type, addedValue, source);
-
-			eventBusService.post(event);
-		} catch (Exception e) {
-			throw new FatalException(e);
-		}
-	}
-
-
-	static <S, T> CollectionAddedToEvent<S, T> newEvent(
-			final Class<? extends CollectionAddedToEvent<S, T>> type,
-			final T addedValue, final S source)
-			throws InstantiationException, IllegalAccessException,
-			NoSuchFieldException {
-		final CollectionAddedToEvent<S, T> event = type.newInstance();
-
-		setField("source", event, source);
-		setField("addedValue", event, addedValue);
-		return event;
-	}
-
-	private static void setField(final String name,
-			final CollectionAddedToEvent<?, ?> event, final Object sourceValue)
-			throws NoSuchFieldException, IllegalAccessException {
-		final Field sourceField = CollectionAddedToEvent.class
-				.getDeclaredField(name);
-		sourceField.setAccessible(true);
-		sourceField.set(event, sourceValue);
-	}
-
-	private EventBusService getEventBusService() {
-		if (!searchedForEventBusService) {
-			final List<ObjectAdapter> serviceAdapters = servicesProvider
-					.getServices();
-			for (ObjectAdapter serviceAdapter : serviceAdapters) {
-				final Object service = serviceAdapter.getObject();
-				if (service instanceof EventBusService) {
-					eventBusService = (EventBusService) service;
-					break;
-				}
-			}
-		}
-		searchedForEventBusService = true;
-		return eventBusService;
-	}
-
-	// //////////////////////////////////////
-	// MultiTypedFacet
-
-	@SuppressWarnings("unchecked")
-	@Override
-	public Class<? extends Facet>[] facetTypes() {
-		return Lists.newArrayList(PostsAddedToCollectionEventFacet.class,
-				CollectionAddToFacet.class).toArray(
-				new Class[] {});
-	}
-
-	@SuppressWarnings("unchecked")
-	@Override
-	public <T extends Facet> T getFacet(Class<T> facet) {
-		return (T) this;
-	}
-
-
-
-}

http://git-wip-us.apache.org/repos/asf/isis/blob/2637a055/core/metamodel/src/main/java/org/apache/isis/core/progmodel/facets/collections/event/PostsCollectionAddedToEventAnnotationFacetFactory.java
----------------------------------------------------------------------
diff --git a/core/metamodel/src/main/java/org/apache/isis/core/progmodel/facets/collections/event/PostsCollectionAddedToEventAnnotationFacetFactory.java b/core/metamodel/src/main/java/org/apache/isis/core/progmodel/facets/collections/event/PostsCollectionAddedToEventAnnotationFacetFactory.java
new file mode 100644
index 0000000..504dd64
--- /dev/null
+++ b/core/metamodel/src/main/java/org/apache/isis/core/progmodel/facets/collections/event/PostsCollectionAddedToEventAnnotationFacetFactory.java
@@ -0,0 +1,78 @@
+/*
+ *  Licensed to the Apache Software Foundation (ASF) under one
+ *  or more contributor license agreements.  See the NOTICE file
+ *  distributed with this work for additional information
+ *  regarding copyright ownership.  The ASF licenses this file
+ *  to you under the Apache License, Version 2.0 (the
+ *  "License"); you may not use this file except in compliance
+ *  with the License.  You may obtain a copy of the License at
+ *
+ *        http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *  Unless required by applicable law or agreed to in writing,
+ *  software distributed under the License is distributed on an
+ *  "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ *  KIND, either express or implied.  See the License for the
+ *  specific language governing permissions and limitations
+ *  under the License.
+ */
+
+package org.apache.isis.core.progmodel.facets.collections.event;
+
+import java.lang.reflect.Method;
+
+import org.apache.isis.applib.annotation.PostsCollectionAddedToEvent;
+import org.apache.isis.applib.annotation.WrapperPolicy;
+import org.apache.isis.applib.services.eventbus.CollectionAddedToEvent;
+import org.apache.isis.core.metamodel.adapter.ServicesProvider;
+import org.apache.isis.core.metamodel.adapter.ServicesProviderAware;
+import org.apache.isis.core.metamodel.facetapi.FacetHolder;
+import org.apache.isis.core.metamodel.facetapi.FacetUtil;
+import org.apache.isis.core.metamodel.facetapi.FeatureType;
+import org.apache.isis.core.metamodel.facets.Annotations;
+import org.apache.isis.core.metamodel.facets.FacetFactoryAbstract;
+import org.apache.isis.core.metamodel.facets.accessor.PropertyOrCollectionAccessorFacet;
+import org.apache.isis.core.metamodel.facets.collections.event.PostsCollectionAddedToEventFacet;
+import org.apache.isis.core.metamodel.facets.collections.modify.CollectionAddToFacet;
+
+public class PostsCollectionAddedToEventAnnotationFacetFactory extends FacetFactoryAbstract implements ServicesProviderAware {
+
+    private ServicesProvider servicesProvider;
+
+    public PostsCollectionAddedToEventAnnotationFacetFactory() {
+        super(FeatureType.COLLECTIONS_ONLY);
+    }
+
+    @Override
+    public void process(final ProcessMethodContext processMethodContext) {
+        final Method method = processMethodContext.getMethod();
+        FacetUtil.addFacet(create(method, processMethodContext.getFacetHolder()));
+    }
+
+    private PostsCollectionAddedToEventFacet create(Method method, final FacetHolder holder) {
+        final PostsCollectionAddedToEvent annotation = Annotations.getAnnotation(method, PostsCollectionAddedToEvent.class);
+        if(annotation == null) {
+            return null;
+        }
+        
+        final PropertyOrCollectionAccessorFacet getterFacet = holder.getFacet(PropertyOrCollectionAccessorFacet.class);
+        if(getterFacet == null) {
+            return null;
+        } 
+        final CollectionAddToFacet collectionAddToFacet = holder.getFacet(CollectionAddToFacet.class);
+        if(collectionAddToFacet == null) {
+            return null;
+        }
+        // the collectionAddToFacet will end up as the underlying facet of the PostsCollectionAddedToEventFacetAnnotation
+
+        final Class<? extends CollectionAddedToEvent<?,?>> changedEventType = annotation.value();
+        final WrapperPolicy wrapperPolicy = annotation.wrapperPolicy();
+        return new PostsCollectionAddedToEventFacetAnnotation(changedEventType, wrapperPolicy, getterFacet, collectionAddToFacet, servicesProvider, holder);
+    }
+
+    @Override
+    public void setServicesProvider(ServicesProvider servicesProvider) {
+        this.servicesProvider = servicesProvider;
+    }
+
+}

http://git-wip-us.apache.org/repos/asf/isis/blob/2637a055/core/metamodel/src/main/java/org/apache/isis/core/progmodel/facets/collections/event/PostsCollectionAddedToEventFacetAnnotation.java
----------------------------------------------------------------------
diff --git a/core/metamodel/src/main/java/org/apache/isis/core/progmodel/facets/collections/event/PostsCollectionAddedToEventFacetAnnotation.java b/core/metamodel/src/main/java/org/apache/isis/core/progmodel/facets/collections/event/PostsCollectionAddedToEventFacetAnnotation.java
new file mode 100644
index 0000000..f1e30ec
--- /dev/null
+++ b/core/metamodel/src/main/java/org/apache/isis/core/progmodel/facets/collections/event/PostsCollectionAddedToEventFacetAnnotation.java
@@ -0,0 +1,173 @@
+/*
+ *  Licensed to the Apache Software Foundation (ASF) under one
+ *  or more contributor license agreements.  See the NOTICE file
+ *  distributed with this work for additional information
+ *  regarding copyright ownership.  The ASF licenses this file
+ *  to you under the Apache License, Version 2.0 (the
+ *  "License"); you may not use this file except in compliance
+ *  with the License.  You may obtain a copy of the License at
+ *
+ *        http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *  Unless required by applicable law or agreed to in writing,
+ *  software distributed under the License is distributed on an
+ *  "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ *  KIND, either express or implied.  See the License for the
+ *  specific language governing permissions and limitations
+ *  under the License.
+ */
+
+package org.apache.isis.core.progmodel.facets.collections.event;
+
+import java.lang.reflect.Field;
+import java.util.List;
+import java.util.Set;
+
+import com.google.common.collect.Lists;
+
+import org.apache.isis.applib.FatalException;
+import org.apache.isis.applib.Identifier;
+import org.apache.isis.applib.annotation.WrapperPolicy;
+import org.apache.isis.applib.services.eventbus.CollectionAddedToEvent;
+import org.apache.isis.applib.services.eventbus.EventBusService;
+import org.apache.isis.core.metamodel.adapter.ObjectAdapter;
+import org.apache.isis.core.metamodel.adapter.ServicesProvider;
+import org.apache.isis.core.metamodel.adapter.util.AdapterUtils;
+import org.apache.isis.core.metamodel.facetapi.Facet;
+import org.apache.isis.core.metamodel.facetapi.FacetHolder;
+import org.apache.isis.core.metamodel.facetapi.FacetUtil;
+import org.apache.isis.core.metamodel.facets.accessor.PropertyOrCollectionAccessorFacet;
+import org.apache.isis.core.metamodel.facets.collections.event.PostsCollectionAddedToEventFacet;
+import org.apache.isis.core.metamodel.facets.collections.event.PostsCollectionAddedToEventFacetAbstract;
+import org.apache.isis.core.metamodel.facets.collections.modify.CollectionAddToFacet;
+
+public class PostsCollectionAddedToEventFacetAnnotation 
+        extends PostsCollectionAddedToEventFacetAbstract {
+
+    private final PropertyOrCollectionAccessorFacet getterFacet;
+	private final CollectionAddToFacet collectionAddToFacet;
+	private final ServicesProvider servicesProvider;
+
+	private EventBusService eventBusService;
+	private boolean searchedForEventBusService = false;
+
+	public PostsCollectionAddedToEventFacetAnnotation(
+			final Class<? extends CollectionAddedToEvent<?, ?>> eventType,
+            final WrapperPolicy wrapperPolicy,
+			final PropertyOrCollectionAccessorFacet getterFacet,
+			final CollectionAddToFacet collectionAddToFacet,
+			final ServicesProvider servicesProvider, 
+			final FacetHolder holder) {
+		super(eventType, wrapperPolicy, holder);
+        this.getterFacet = getterFacet;
+		this.collectionAddToFacet = collectionAddToFacet;
+		this.servicesProvider = servicesProvider;
+	}
+
+	@Override
+	public void add(ObjectAdapter targetAdapter, ObjectAdapter referencedObjectAdapter) {
+		if (this.collectionAddToFacet == null) {
+			return;
+		}
+		eventBusService = getEventBusService();
+		if (eventBusService == null) {
+			collectionAddToFacet.add(targetAdapter, referencedObjectAdapter);
+			return;
+		}
+
+		final Object referencedObject = AdapterUtils.unwrap(referencedObjectAdapter);
+		
+		// get hold of underlying collection
+		final Object collection = getterFacet.getProperty(targetAdapter);
+
+		// don't post event if has set semantics and contains object
+		if(collection instanceof Set) {
+            Set<?> set = (Set<?>) collection;
+            if(set.contains(referencedObject)) {
+                return;
+            }
+		}
+
+		// either doesn't contain object, or doesn't have set semantics, so post event
+		collectionAddToFacet.add(targetAdapter, referencedObjectAdapter);
+		
+		postEvent(targetAdapter, getIdentified().getIdentifier(), referencedObject);
+	}
+
+	@SuppressWarnings({ "rawtypes", "unchecked" })
+	private void postEvent(
+	        final ObjectAdapter targetAdapter,
+            final Identifier identifier,
+			final Object addedReference) {
+	    
+		final Object source = targetAdapter.getObject();
+		try {
+			final Class type = value();
+			final CollectionAddedToEvent<?, ?> event = newEvent(type, source, identifier, addedReference);
+			eventBusService.post(event);
+		} catch (Exception e) {
+			throw new FatalException(e);
+		}
+	}
+
+	static <S, T> CollectionAddedToEvent<S, T> newEvent(
+			final Class<? extends CollectionAddedToEvent<S, T>> type,
+			final S source, 
+			final Identifier identifier,
+			final T value)
+			throws InstantiationException, IllegalAccessException,
+			NoSuchFieldException {
+		final CollectionAddedToEvent<S, T> event = type.newInstance();
+
+		setField("source", event, source);
+		setField("identifier", event, identifier);
+		setField("value", event, value);
+		return event;
+	}
+
+	private static void setField(final String name,
+			final CollectionAddedToEvent<?, ?> event, final Object sourceValue)
+			throws NoSuchFieldException, IllegalAccessException {
+		final Field sourceField = CollectionAddedToEvent.class
+				.getDeclaredField(name);
+		sourceField.setAccessible(true);
+		sourceField.set(event, sourceValue);
+	}
+
+	private EventBusService getEventBusService() {
+		if (!searchedForEventBusService) {
+			final List<ObjectAdapter> serviceAdapters = servicesProvider
+					.getServices();
+			for (ObjectAdapter serviceAdapter : serviceAdapters) {
+				final Object service = serviceAdapter.getObject();
+				if (service instanceof EventBusService) {
+					eventBusService = (EventBusService) service;
+					break;
+				}
+			}
+		}
+		searchedForEventBusService = true;
+		return eventBusService;
+	}
+
+	// //////////////////////////////////////
+	// MultiTypedFacet
+	// //////////////////////////////////////
+
+	@SuppressWarnings("unchecked")
+	@Override
+	public Class<? extends Facet>[] facetTypes() {
+		return Lists.newArrayList(
+		            type(), // ie CollectionAddedToFacet
+    		        PostsCollectionAddedToEventFacet.class
+				).toArray(
+				new Class[] {});
+	}
+
+	@SuppressWarnings("unchecked")
+	@Override
+	public <T extends Facet> T getFacet(Class<T> facet) {
+		return (T) this;
+	}
+
+}

http://git-wip-us.apache.org/repos/asf/isis/blob/2637a055/core/metamodel/src/main/java/org/apache/isis/core/progmodel/facets/properties/event/PostsPropertyChangedEventAnnotationFacetFactory.java
----------------------------------------------------------------------
diff --git a/core/metamodel/src/main/java/org/apache/isis/core/progmodel/facets/properties/event/PostsPropertyChangedEventAnnotationFacetFactory.java b/core/metamodel/src/main/java/org/apache/isis/core/progmodel/facets/properties/event/PostsPropertyChangedEventAnnotationFacetFactory.java
index 3e87ff7..1a75d60 100644
--- a/core/metamodel/src/main/java/org/apache/isis/core/progmodel/facets/properties/event/PostsPropertyChangedEventAnnotationFacetFactory.java
+++ b/core/metamodel/src/main/java/org/apache/isis/core/progmodel/facets/properties/event/PostsPropertyChangedEventAnnotationFacetFactory.java
@@ -24,6 +24,7 @@ import java.util.Comparator;
 import java.util.List;
 
 import org.apache.isis.applib.annotation.PostsPropertyChangedEvent;
+import org.apache.isis.applib.annotation.WrapperPolicy;
 import org.apache.isis.applib.services.eventbus.PropertyChangedEvent;
 import org.apache.isis.core.commons.config.IsisConfiguration;
 import org.apache.isis.core.metamodel.adapter.ServicesProvider;
@@ -75,14 +76,22 @@ public class PostsPropertyChangedEventAnnotationFacetFactory extends FacetFactor
         if (clearFacet == null && setterFacet == null) {
             return null;
         }
+        
+        
+        // REVIEW: I'm a bit uncertain about this; this facet is multi-valued, but the setUnderlying(...) stuff only
+        // works for single valued types.
+        // the wrapperFactory stuff looks for underlying to find the imperative method, I think this only works in this
+        // case because (by accident rather than design) there is also the PropertyInitializationFacet wrapping the setter.
         if(setterFacet != null) {
             holder.removeFacet(setterFacet);
         }
         if(clearFacet != null) {
             holder.removeFacet(clearFacet);
         }
+        
         final Class<? extends PropertyChangedEvent<?, ?>> changedEventType = annotation.value();
-        return new PostsPropertyChangedEventFacetAnnotation(changedEventType, getterFacet, setterFacet, clearFacet, servicesProvider, holder);
+        final WrapperPolicy wrapperPolicy = annotation.wrapperPolicy();
+        return new PostsPropertyChangedEventFacetAnnotation(changedEventType, wrapperPolicy, getterFacet, setterFacet, clearFacet, servicesProvider, holder);
     }
 
     @Override

http://git-wip-us.apache.org/repos/asf/isis/blob/2637a055/core/metamodel/src/main/java/org/apache/isis/core/progmodel/facets/properties/event/PostsPropertyChangedEventFacetAnnotation.java
----------------------------------------------------------------------
diff --git a/core/metamodel/src/main/java/org/apache/isis/core/progmodel/facets/properties/event/PostsPropertyChangedEventFacetAnnotation.java b/core/metamodel/src/main/java/org/apache/isis/core/progmodel/facets/properties/event/PostsPropertyChangedEventFacetAnnotation.java
index 406ac36..afc96bb 100644
--- a/core/metamodel/src/main/java/org/apache/isis/core/progmodel/facets/properties/event/PostsPropertyChangedEventFacetAnnotation.java
+++ b/core/metamodel/src/main/java/org/apache/isis/core/progmodel/facets/properties/event/PostsPropertyChangedEventFacetAnnotation.java
@@ -26,7 +26,8 @@ import com.google.common.base.Objects;
 import com.google.common.collect.Lists;
 
 import org.apache.isis.applib.FatalException;
-import org.apache.isis.applib.RecoverableException;
+import org.apache.isis.applib.Identifier;
+import org.apache.isis.applib.annotation.WrapperPolicy;
 import org.apache.isis.applib.services.eventbus.EventBusService;
 import org.apache.isis.applib.services.eventbus.PropertyChangedEvent;
 import org.apache.isis.core.metamodel.adapter.ObjectAdapter;
@@ -50,13 +51,14 @@ public class PostsPropertyChangedEventFacetAnnotation extends PostsPropertyChang
     private boolean searchedForEventBusService = false;
 
     public PostsPropertyChangedEventFacetAnnotation(
-            final Class<? extends PropertyChangedEvent<?, ?>> changedEventType, 
+            final Class<? extends PropertyChangedEvent<?, ?>> eventType, 
+            final WrapperPolicy wrapperPolicy,
             final PropertyOrCollectionAccessorFacet getterFacet, 
             final PropertySetterFacet setterFacet, 
             final PropertyClearFacet clearFacet, 
             final ServicesProvider servicesProvider, 
             final FacetHolder holder) {
-        super(changedEventType, holder);
+        super(eventType, wrapperPolicy, holder);
         this.getterFacet = getterFacet;
         this.setterFacet = setterFacet;
         this.clearFacet = clearFacet;
@@ -64,50 +66,56 @@ public class PostsPropertyChangedEventFacetAnnotation extends PostsPropertyChang
     }
 
     @Override
-    public void setProperty(ObjectAdapter inObject, ObjectAdapter value) {
-        if(this.setterFacet == null) {
+    public void setProperty(ObjectAdapter targetAdapter, ObjectAdapter valueAdapter) {
+        if(setterFacet == null) {
             return;
         }
         eventBusService = getEventBusService();
         if(eventBusService == null) {
-            setterFacet.setProperty(inObject, value);
+            setterFacet.setProperty(targetAdapter, valueAdapter);
             return;
         }
         
-        final Object oldValue = this.getterFacet.getProperty(inObject);
-        this.setterFacet.setProperty(inObject, value);
-        final Object newValue = this.getterFacet.getProperty(inObject);
-        postEventIfChanged(inObject, oldValue, newValue);
+        final Object oldValue = getterFacet.getProperty(targetAdapter);
+        setterFacet.setProperty(targetAdapter, valueAdapter);
+        final Object newValue = getterFacet.getProperty(targetAdapter);
+        postEventIfChanged(targetAdapter, getIdentified().getIdentifier(), oldValue, newValue);
     }
 
     @Override
-    public void clearProperty(ObjectAdapter inObject) {
-        if(this.clearFacet == null) {
+    public void clearProperty(ObjectAdapter targetAdapter) {
+        if(clearFacet == null) {
             return;
         }
         eventBusService = getEventBusService();
         if(eventBusService == null) {
-            clearFacet.clearProperty(inObject);
+            clearFacet.clearProperty(targetAdapter);
             return;
         }
 
-        final Object oldValue = this.getterFacet.getProperty(inObject);
-        this.clearFacet.clearProperty(inObject);
-        final Object newValue = this.getterFacet.getProperty(inObject);
-        postEventIfChanged(inObject, oldValue, newValue);
+        final Object oldValue = getterFacet.getProperty(targetAdapter);
+        clearFacet.clearProperty(targetAdapter);
+        final Object newValue = getterFacet.getProperty(targetAdapter);
+        
+        postEventIfChanged(targetAdapter, getIdentified().getIdentifier(), oldValue, newValue);
     }
 
 
     @SuppressWarnings({ "rawtypes", "unchecked" })
-    private void postEventIfChanged(ObjectAdapter inObject, final Object oldValue, final Object newValue) {
+    private void postEventIfChanged(
+            final ObjectAdapter targetAdapter, 
+            final Identifier identifier, 
+            final Object oldValue, 
+            final Object newValue) {
+        
         if(Objects.equal(oldValue, newValue)) {
             // do nothing.
             return;
         }
-        final Object source = inObject.getObject();
+        final Object source = targetAdapter.getObject();
         try {
             final Class type = value();
-            final PropertyChangedEvent<?, ?> event = newEvent(type, oldValue, newValue, source);
+            final PropertyChangedEvent<?, ?> event = newEvent(type, source, identifier, oldValue, newValue);
             
             eventBusService.post(event);
         } catch (Exception e) {
@@ -115,10 +123,16 @@ public class PostsPropertyChangedEventFacetAnnotation extends PostsPropertyChang
         }
     }
 
-    static <S,T> PropertyChangedEvent<S,T> newEvent(final Class<? extends PropertyChangedEvent<S, T>> type, final T oldValue, final T newValue, final S source) throws InstantiationException, IllegalAccessException, NoSuchFieldException {
+    static <S,T> PropertyChangedEvent<S,T> newEvent(
+            final Class<? extends PropertyChangedEvent<S, T>> type, 
+            final S source, 
+            final Identifier identifier,
+            final T oldValue, 
+            final T newValue) throws InstantiationException, IllegalAccessException, NoSuchFieldException {
         final PropertyChangedEvent<S, T> event = type.newInstance();
         
         setField("source", event, source);
+        setField("identifier", event, identifier);
         setField("oldValue", event, oldValue);
         setField("newValue", event, newValue);
         return event;
@@ -147,12 +161,16 @@ public class PostsPropertyChangedEventFacetAnnotation extends PostsPropertyChang
     
     // //////////////////////////////////////
     // MultiTypedFacet
-
+    // //////////////////////////////////////
 
     @SuppressWarnings("unchecked")
     @Override
     public Class<? extends Facet>[] facetTypes() {
-        return Lists.newArrayList(PostsPropertyChangedEventFacet.class, PropertySetterFacet.class, PropertyClearFacet.class).toArray(new Class[]{});
+        return Lists.newArrayList(
+                    PostsPropertyChangedEventFacet.class, 
+                    PropertySetterFacet.class, 
+                    PropertyClearFacet.class
+                ).toArray(new Class[]{});
     }
 
     @SuppressWarnings("unchecked")

http://git-wip-us.apache.org/repos/asf/isis/blob/2637a055/core/metamodel/src/main/java/org/apache/isis/progmodels/dflt/ProgrammingModelFacetsJava5.java
----------------------------------------------------------------------
diff --git a/core/metamodel/src/main/java/org/apache/isis/progmodels/dflt/ProgrammingModelFacetsJava5.java b/core/metamodel/src/main/java/org/apache/isis/progmodels/dflt/ProgrammingModelFacetsJava5.java
index 69c6e70..1e4598c 100644
--- a/core/metamodel/src/main/java/org/apache/isis/progmodels/dflt/ProgrammingModelFacetsJava5.java
+++ b/core/metamodel/src/main/java/org/apache/isis/progmodels/dflt/ProgrammingModelFacetsJava5.java
@@ -47,6 +47,7 @@ import org.apache.isis.core.progmodel.facets.collections.aggregated.ParentedSinc
 import org.apache.isis.core.progmodel.facets.collections.clear.CollectionClearFacetFactory;
 import org.apache.isis.core.progmodel.facets.collections.collection.CollectionFacetFactory;
 import org.apache.isis.core.progmodel.facets.collections.disabled.fromimmutable.DisabledFacetForCollectionDerivedFromImmutableTypeFacetFactory;
+import org.apache.isis.core.progmodel.facets.collections.event.PostsCollectionAddedToEventAnnotationFacetFactory;
 import org.apache.isis.core.progmodel.facets.collections.modify.CollectionAddRemoveAndValidateFacetFactory;
 import org.apache.isis.core.progmodel.facets.collections.notpersisted.annotation.NotPersistedAnnotationForCollectionFacetFactory;
 import org.apache.isis.core.progmodel.facets.collections.sortedby.SortedByAnnotationFacetFactory;
@@ -362,8 +363,11 @@ public final class ProgrammingModelFacetsJava5 extends ProgrammingModelAbstract
         addFactory(DisabledFacetForPropertyDerivedFromImmutableTypeFacetFactory.class);
         addFactory(DisabledFacetForCollectionDerivedFromImmutableTypeFacetFactory.class);
 
+        // must come after the property/collection/action accessor+mutator facet factories
         addFactory(PostsPropertyChangedEventAnnotationFacetFactory.class);
+        addFactory(PostsCollectionAddedToEventAnnotationFacetFactory.class);
 
+        
         addFactory(ImmutableMarkerInterfaceFacetFactory.class);
 
         addFactory(ViewModelIntefaceFacetFactory.class);


[05/16] git commit: ISIS-550 and ISIS-776: merging

Posted by da...@apache.org.
ISIS-550 and ISIS-776: merging


Project: http://git-wip-us.apache.org/repos/asf/isis/repo
Commit: http://git-wip-us.apache.org/repos/asf/isis/commit/1dac3edf
Tree: http://git-wip-us.apache.org/repos/asf/isis/tree/1dac3edf
Diff: http://git-wip-us.apache.org/repos/asf/isis/diff/1dac3edf

Branch: refs/heads/master
Commit: 1dac3edff844f427a9916fc67aad8c1f615128f3
Parents: 2637a05 55c4ea8
Author: Dan Haywood <da...@haywood-associates.co.uk>
Authored: Fri May 9 17:54:04 2014 +0100
Committer: Dan Haywood <da...@haywood-associates.co.uk>
Committed: Fri May 9 17:54:04 2014 +0100

----------------------------------------------------------------------
 ...Put_whenArgValid_thenPropertyUpdated_ok.java | 262 ------------------
 ...henArgValid_thenPropertyUpdated_ok_TODO.java | 267 +++++++++++++++++++
 .../components/widgets/cssmenu/CssMenuPanel.css |   2 +-
 .../viewer/wicket/ui/pages/PageAbstract.css     |   2 +-
 core/applib/pom.xml                             |   6 +
 .../isis/applib/DomainObjectContainer.java      |   6 +
 .../fixturescripts/CompositeFixtureScript.java  |  90 +++++++
 .../applib/fixturescripts/FixtureResult.java    |  68 +++++
 .../fixturescripts/FixtureResultList.java       |  72 +++++
 .../applib/fixturescripts/FixtureScript.java    | 208 +++++++++++++++
 .../applib/fixturescripts/FixtureScripts.java   | 164 ++++++++++++
 .../fixturescripts/SimpleFixtureScript.java     |  56 ++++
 .../classdiscovery/ClassDiscoveryService.java   |  30 +++
 .../ClassDiscoveryServiceUsingReflections.java  |  42 +++
 .../metamodel/adapter/DomainObjectServices.java |   2 +
 .../noruntime/RuntimeContextNoRuntime.java      |   5 +
 .../container/DomainObjectContainerDefault.java |  11 +
 .../internal/RuntimeContextFromSession.java     |   5 +
 .../src/main/java/dom/todo/ToDoItem.layout.json |   6 +-
 .../fixture/todo/ToDoItemsCreateForUser.java    | 105 ++++++++
 .../fixture/todo/ToDoItemsDeleteForUser.java    |  60 +++++
 .../java/fixture/todo/ToDoItemsFixture.java     |  75 +-----
 .../fixture/todo/ToDoItemsFixturesService.java  |  34 +++
 .../fixture/todo/ToDoItemsResetForUser.java     |  75 ++++++
 .../java/integration/ToDoSystemInitializer.java |  12 +-
 .../integration/glue/CatalogOfFixturesGlue.java |   3 +-
 .../webapp/prototyping/DeveloperUtilities.java  |   2 +
 .../prototyping/ToDoItemsFixturesService.java   |  84 ------
 .../src/main/webapp/WEB-INF/isis.properties     |   3 +-
 29 files changed, 1329 insertions(+), 428 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/isis/blob/1dac3edf/example/application/quickstart_wicket_restful_jdo/webapp/src/main/webapp/WEB-INF/isis.properties
----------------------------------------------------------------------
diff --cc example/application/quickstart_wicket_restful_jdo/webapp/src/main/webapp/WEB-INF/isis.properties
index 153f3f9,a6f1e96..a542934
--- a/example/application/quickstart_wicket_restful_jdo/webapp/src/main/webapp/WEB-INF/isis.properties
+++ b/example/application/quickstart_wicket_restful_jdo/webapp/src/main/webapp/WEB-INF/isis.properties
@@@ -189,7 -189,7 +189,8 @@@ isis.services = 
                  org.apache.isis.applib.annotation.Bulk$InteractionContext,\
                  org.apache.isis.applib.services.scratchpad.Scratchpad,\
                  org.apache.isis.applib.services.queryresultscache.QueryResultsCache,\
 +                org.apache.isis.core.wrapper.WrapperFactoryDefault,\
+                 org.apache.isis.applib.services.classdiscovery.ClassDiscoveryServiceUsingReflections,\
                  \
                  # JDO implementation of the EventBusService, \
                  org.apache.isis.objectstore.jdo.datanucleus.service.eventbus.EventBusServiceJdo,\


[02/16] git commit: ISIS-550: renaming classes

Posted by da...@apache.org.
ISIS-550: renaming classes

to be consistent with current convention..
* AddToCollectionEvent -> CollectionAddToEvent
* RemoveFromCollectionEvent -> CollectionRemoveFromEvent
etc.

Also commented out some unit test that was incomplete.

Also:


Project: http://git-wip-us.apache.org/repos/asf/isis/repo
Commit: http://git-wip-us.apache.org/repos/asf/isis/commit/43c50c46
Tree: http://git-wip-us.apache.org/repos/asf/isis/tree/43c50c46
Diff: http://git-wip-us.apache.org/repos/asf/isis/diff/43c50c46

Branch: refs/heads/master
Commit: 43c50c463b5d664f1558dfa92752c2483654e738
Parents: 548cb14
Author: Dan Haywood <da...@haywood-associates.co.uk>
Authored: Wed May 7 05:31:56 2014 +0100
Committer: Dan Haywood <da...@haywood-associates.co.uk>
Committed: Wed May 7 05:31:56 2014 +0100

----------------------------------------------------------------------
 .../annotation/PostsAddedToCollectionEvent.java | 59 ------------------
 .../annotation/PostsCollectionAddedToEvent.java | 63 ++++++++++++++++++++
 .../PostsCollectionRemovedFromEvent.java        | 63 ++++++++++++++++++++
 .../PostsRemovedFromCollectionEvent.java        | 59 ------------------
 .../eventbus/AddedToCollectionEvent.java        | 55 -----------------
 .../eventbus/CollectionAddedToEvent.java        | 55 +++++++++++++++++
 .../eventbus/CollectionRemovedFromEvent.java    | 54 +++++++++++++++++
 .../eventbus/RemovedFromCollectionEvent.java    | 54 -----------------
 ...lectionAddToEventAnnotationFacetFactory.java |  8 +--
 ...ostsCollectionAddToEventFacetAnnotation.java | 18 +++---
 ...nAddedEventFacetAnnotationTest_newEvent.java | 20 +++----
 11 files changed, 258 insertions(+), 250 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/isis/blob/43c50c46/core/applib/src/main/java/org/apache/isis/applib/annotation/PostsAddedToCollectionEvent.java
----------------------------------------------------------------------
diff --git a/core/applib/src/main/java/org/apache/isis/applib/annotation/PostsAddedToCollectionEvent.java b/core/applib/src/main/java/org/apache/isis/applib/annotation/PostsAddedToCollectionEvent.java
deleted file mode 100644
index 28fa7c2..0000000
--- a/core/applib/src/main/java/org/apache/isis/applib/annotation/PostsAddedToCollectionEvent.java
+++ /dev/null
@@ -1,59 +0,0 @@
-/*
- *  Licensed to the Apache Software Foundation (ASF) under one
- *  or more contributor license agreements.  See the NOTICE file
- *  distributed with this work for additional information
- *  regarding copyright ownership.  The ASF licenses this file
- *  to you under the Apache License, Version 2.0 (the
- *  "License"); you may not use this file except in compliance
- *  with the License.  You may obtain a copy of the License at
- *
- *        http://www.apache.org/licenses/LICENSE-2.0
- *
- *  Unless required by applicable law or agreed to in writing,
- *  software distributed under the License is distributed on an
- *  "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- *  KIND, either express or implied.  See the License for the
- *  specific language governing permissions and limitations
- *  under the License.
- */
-
-package org.apache.isis.applib.annotation;
-
-import java.lang.annotation.ElementType;
-import java.lang.annotation.Retention;
-import java.lang.annotation.RetentionPolicy;
-import java.lang.annotation.Target;
-
-import org.apache.isis.applib.services.eventbus.AddedToCollectionEvent;
-
-/**
- * Applies only to collections; any changes should be propagated as events to subscribers.  
- * Only posted after a successful validation.
- * 
- * <p>For example:
- * <pre>
- * public static class DomainEntityAddedToCollectionEvent extends AddedToCollectionEvent {}
- * 
- * &#64;PostsAddedToCollectionEvent(DomainEntityAddedToCollectionEvent.class)
- * public DomainEntity getDomainEntity() { ...}
- * </pre>
- * 
- * <p>
- * It is highly advisable that only domain services - not domain entities - are registered as subscribers.  
- * Domain services are guaranteed to be instantiated and resident in memory, whereas the same is not true
- * of domain entities.  The typical implementation of a domain service subscriber is to identify the impacted entities,
- * load them using a repository, and then to delegate to the event to them.
- */
-@Retention(RetentionPolicy.RUNTIME)
-@Target({ElementType.TYPE, ElementType.METHOD})
-public @interface PostsAddedToCollectionEvent {
-
-    /**
-     * The subclass of {@link AddedToCollectionEvent event} to be instantiated and posted.
-     * 
-     * <p>
-     * This subclass must provide a no-arg constructor; the fields are set reflectively.
-     */
-    Class<? extends AddedToCollectionEvent<?,?>> value();
-
-}

http://git-wip-us.apache.org/repos/asf/isis/blob/43c50c46/core/applib/src/main/java/org/apache/isis/applib/annotation/PostsCollectionAddedToEvent.java
----------------------------------------------------------------------
diff --git a/core/applib/src/main/java/org/apache/isis/applib/annotation/PostsCollectionAddedToEvent.java b/core/applib/src/main/java/org/apache/isis/applib/annotation/PostsCollectionAddedToEvent.java
new file mode 100644
index 0000000..e67be7f
--- /dev/null
+++ b/core/applib/src/main/java/org/apache/isis/applib/annotation/PostsCollectionAddedToEvent.java
@@ -0,0 +1,63 @@
+/*
+ *  Licensed to the Apache Software Foundation (ASF) under one
+ *  or more contributor license agreements.  See the NOTICE file
+ *  distributed with this work for additional information
+ *  regarding copyright ownership.  The ASF licenses this file
+ *  to you under the Apache License, Version 2.0 (the
+ *  "License"); you may not use this file except in compliance
+ *  with the License.  You may obtain a copy of the License at
+ *
+ *        http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *  Unless required by applicable law or agreed to in writing,
+ *  software distributed under the License is distributed on an
+ *  "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ *  KIND, either express or implied.  See the License for the
+ *  specific language governing permissions and limitations
+ *  under the License.
+ */
+
+package org.apache.isis.applib.annotation;
+
+import java.lang.annotation.ElementType;
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+import java.lang.annotation.Target;
+
+import org.apache.isis.applib.services.eventbus.CollectionAddedToEvent;
+
+/**
+ * Applies only to collections; any changes should be propagated as events to subscribers.  
+ * Only posted after a successful validation.
+ * 
+ * <p>For example:
+ * <pre>
+ * public class Order {
+ *   public static class OrderLineItemsAddedToEvent extends CollectionAddedToEvent {}
+ * 
+ *   &#64;PostsCollectionAddedToEvent(OrderLineItemsAddedToEvent.class)
+ *   public SortedSet&lt;OrderLine&gt; getLineItems() { ...}
+ * }
+ * </pre>
+ * 
+ * <p>
+ * It is highly advisable that only domain services - not domain entities - are registered as subscribers.  
+ * Domain services are guaranteed to be instantiated and resident in memory, whereas the same is not true
+ * of domain entities.  The typical implementation of a domain service subscriber is to identify the impacted entities,
+ * load them using a repository, and then to delegate to the event to them.
+ * 
+ * @see PostsCollectionRemovedFromEvent
+ */
+@Retention(RetentionPolicy.RUNTIME)
+@Target({ElementType.TYPE, ElementType.METHOD})
+public @interface PostsCollectionAddedToEvent {
+
+    /**
+     * The subclass of {@link CollectionAddedToEvent event} to be instantiated and posted.
+     * 
+     * <p>
+     * This subclass must provide a no-arg constructor; the fields are set reflectively.
+     */
+    Class<? extends CollectionAddedToEvent<?,?>> value();
+
+}

http://git-wip-us.apache.org/repos/asf/isis/blob/43c50c46/core/applib/src/main/java/org/apache/isis/applib/annotation/PostsCollectionRemovedFromEvent.java
----------------------------------------------------------------------
diff --git a/core/applib/src/main/java/org/apache/isis/applib/annotation/PostsCollectionRemovedFromEvent.java b/core/applib/src/main/java/org/apache/isis/applib/annotation/PostsCollectionRemovedFromEvent.java
new file mode 100644
index 0000000..f560434
--- /dev/null
+++ b/core/applib/src/main/java/org/apache/isis/applib/annotation/PostsCollectionRemovedFromEvent.java
@@ -0,0 +1,63 @@
+/*
+ *  Licensed to the Apache Software Foundation (ASF) under one
+ *  or more contributor license agreements.  See the NOTICE file
+ *  distributed with this work for additional information
+ *  regarding copyright ownership.  The ASF licenses this file
+ *  to you under the Apache License, Version 2.0 (the
+ *  "License"); you may not use this file except in compliance
+ *  with the License.  You may obtain a copy of the License at
+ *
+ *        http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *  Unless required by applicable law or agreed to in writing,
+ *  software distributed under the License is distributed on an
+ *  "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ *  KIND, either express or implied.  See the License for the
+ *  specific language governing permissions and limitations
+ *  under the License.
+ */
+
+package org.apache.isis.applib.annotation;
+
+import java.lang.annotation.ElementType;
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+import java.lang.annotation.Target;
+
+import org.apache.isis.applib.services.eventbus.CollectionRemovedFromEvent;
+
+/**
+ * Applies only to collections; any changes should be propagated as events to subscribers.  
+ * Only posted after a successful validation.
+ * 
+ * <p>For example:
+ * <pre>
+ * public class Order {
+ *   public static class OrderLineItemsRemovedFromEvent extends CollectionRemovedFromEvent {}
+ * 
+ *   &#64;PostsCollectionRemovedFromEvent(OrderLineItemsRemovedFromEvent.class)
+ *   public SortedSet&lt;OrderLine&gt; getLineItems() { ...}
+ * }
+ * </pre>
+ * 
+ * <p>
+ * It is highly advisable that only domain services - not domain entities - are registered as subscribers.  
+ * Domain services are guaranteed to be instantiated and resident in memory, whereas the same is not true
+ * of domain entities.  The typical implementation of a domain service subscriber is to identify the impacted entities,
+ * load them using a repository, and then to delegate to the event to them.
+ * 
+ * @see PostsCollectionAddedToEvent
+ */
+@Retention(RetentionPolicy.RUNTIME)
+@Target({ElementType.TYPE, ElementType.METHOD})
+public @interface PostsCollectionRemovedFromEvent {
+
+    /**
+     * The subclass of {@link CollectionRemovedFromEvent event} to be instantiated and posted.
+     * 
+     * <p>
+     * This subclass must provide a no-arg constructor; the fields are set reflectively.
+     */
+    Class<? extends CollectionRemovedFromEvent<?,?>> value();
+
+}

http://git-wip-us.apache.org/repos/asf/isis/blob/43c50c46/core/applib/src/main/java/org/apache/isis/applib/annotation/PostsRemovedFromCollectionEvent.java
----------------------------------------------------------------------
diff --git a/core/applib/src/main/java/org/apache/isis/applib/annotation/PostsRemovedFromCollectionEvent.java b/core/applib/src/main/java/org/apache/isis/applib/annotation/PostsRemovedFromCollectionEvent.java
deleted file mode 100644
index 4198ce6..0000000
--- a/core/applib/src/main/java/org/apache/isis/applib/annotation/PostsRemovedFromCollectionEvent.java
+++ /dev/null
@@ -1,59 +0,0 @@
-/*
- *  Licensed to the Apache Software Foundation (ASF) under one
- *  or more contributor license agreements.  See the NOTICE file
- *  distributed with this work for additional information
- *  regarding copyright ownership.  The ASF licenses this file
- *  to you under the Apache License, Version 2.0 (the
- *  "License"); you may not use this file except in compliance
- *  with the License.  You may obtain a copy of the License at
- *
- *        http://www.apache.org/licenses/LICENSE-2.0
- *
- *  Unless required by applicable law or agreed to in writing,
- *  software distributed under the License is distributed on an
- *  "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- *  KIND, either express or implied.  See the License for the
- *  specific language governing permissions and limitations
- *  under the License.
- */
-
-package org.apache.isis.applib.annotation;
-
-import java.lang.annotation.ElementType;
-import java.lang.annotation.Retention;
-import java.lang.annotation.RetentionPolicy;
-import java.lang.annotation.Target;
-
-import org.apache.isis.applib.services.eventbus.RemovedFromCollectionEvent;
-
-/**
- * Applies only to collections; any changes should be propagated as events to subscribers.  
- * Only posted after a successful validation.
- * 
- * <p>For example:
- * <pre>
- * public static class DomainEntityRemovedFromCollectionEvent extends RemovedFromCollectionEvent {}
- * 
- * &#64;PostsRemovedFromCollectionEvent(DomainEntityRemovedFromCollectionEvent.class)
- * public DomainEntity getDomainEntity() { ...}
- * </pre>
- * 
- * <p>
- * It is highly advisable that only domain services - not domain entities - are registered as subscribers.  
- * Domain services are guaranteed to be instantiated and resident in memory, whereas the same is not true
- * of domain entities.  The typical implementation of a domain service subscriber is to identify the impacted entities,
- * load them using a repository, and then to delegate to the event to them.
- */
-@Retention(RetentionPolicy.RUNTIME)
-@Target({ElementType.TYPE, ElementType.METHOD})
-public @interface PostsRemovedFromCollectionEvent {
-
-    /**
-     * The subclass of {@link RemovedFromCollectionEvent event} to be instantiated and posted.
-     * 
-     * <p>
-     * This subclass must provide a no-arg constructor; the fields are set reflectively.
-     */
-    Class<? extends RemovedFromCollectionEvent<?,?>> value();
-
-}

http://git-wip-us.apache.org/repos/asf/isis/blob/43c50c46/core/applib/src/main/java/org/apache/isis/applib/services/eventbus/AddedToCollectionEvent.java
----------------------------------------------------------------------
diff --git a/core/applib/src/main/java/org/apache/isis/applib/services/eventbus/AddedToCollectionEvent.java b/core/applib/src/main/java/org/apache/isis/applib/services/eventbus/AddedToCollectionEvent.java
deleted file mode 100644
index 6b6bb02..0000000
--- a/core/applib/src/main/java/org/apache/isis/applib/services/eventbus/AddedToCollectionEvent.java
+++ /dev/null
@@ -1,55 +0,0 @@
-/*
- *  Licensed to the Apache Software Foundation (ASF) under one
- *  or more contributor license agreements.  See the NOTICE file
- *  distributed with this work for additional information
- *  regarding copyright ownership.  The ASF licenses this file
- *  to you under the Apache License, Version 2.0 (the
- *  "License"); you may not use this file except in compliance
- *  with the License.  You may obtain a copy of the License at
- *
- *        http://www.apache.org/licenses/LICENSE-2.0
- *
- *  Unless required by applicable law or agreed to in writing,
- *  software distributed under the License is distributed on an
- *  "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- *  KIND, either express or implied.  See the License for the
- *  specific language governing permissions and limitations
- *  under the License.
- */
-package org.apache.isis.applib.services.eventbus;
-
-import org.apache.isis.applib.annotation.PostsPropertyChangedEvent;
-import org.apache.isis.applib.util.ObjectContracts;
-
-public abstract class AddedToCollectionEvent<S,T> {
-    private final S source;
-    private final T addedValue;
-    
-    /**
-     * To instantiate reflectively when the {@link PostsPropertyChangedEvent} annotation
-     * is used.
-     * 
-     * <p>
-     * The fields ({@link #source} and {@link #addedValue} are then set reflectively.
-     */
-    public AddedToCollectionEvent() {
-        this(null, null);
-    }
-    public AddedToCollectionEvent(S source, T addedValue) {
-        this.source = source;
-        this.addedValue = addedValue;
-    }
-
-    public S getSource() {
-        return source;
-    }
-    
-    public T getAddedValue() {
-        return addedValue;
-    }
-    
-    @Override
-    public String toString() {
-        return ObjectContracts.toString(this, "source,addedValue");
-    }
-}
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/isis/blob/43c50c46/core/applib/src/main/java/org/apache/isis/applib/services/eventbus/CollectionAddedToEvent.java
----------------------------------------------------------------------
diff --git a/core/applib/src/main/java/org/apache/isis/applib/services/eventbus/CollectionAddedToEvent.java b/core/applib/src/main/java/org/apache/isis/applib/services/eventbus/CollectionAddedToEvent.java
new file mode 100644
index 0000000..10229f7
--- /dev/null
+++ b/core/applib/src/main/java/org/apache/isis/applib/services/eventbus/CollectionAddedToEvent.java
@@ -0,0 +1,55 @@
+/*
+ *  Licensed to the Apache Software Foundation (ASF) under one
+ *  or more contributor license agreements.  See the NOTICE file
+ *  distributed with this work for additional information
+ *  regarding copyright ownership.  The ASF licenses this file
+ *  to you under the Apache License, Version 2.0 (the
+ *  "License"); you may not use this file except in compliance
+ *  with the License.  You may obtain a copy of the License at
+ *
+ *        http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *  Unless required by applicable law or agreed to in writing,
+ *  software distributed under the License is distributed on an
+ *  "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ *  KIND, either express or implied.  See the License for the
+ *  specific language governing permissions and limitations
+ *  under the License.
+ */
+package org.apache.isis.applib.services.eventbus;
+
+import org.apache.isis.applib.annotation.PostsPropertyChangedEvent;
+import org.apache.isis.applib.util.ObjectContracts;
+
+public abstract class CollectionAddedToEvent<S,T> {
+    private final S source;
+    private final T addedValue;
+    
+    /**
+     * To instantiate reflectively when the {@link PostsPropertyChangedEvent} annotation
+     * is used.
+     * 
+     * <p>
+     * The fields ({@link #source} and {@link #addedValue} are then set reflectively.
+     */
+    public CollectionAddedToEvent() {
+        this(null, null);
+    }
+    public CollectionAddedToEvent(S source, T addedValue) {
+        this.source = source;
+        this.addedValue = addedValue;
+    }
+
+    public S getSource() {
+        return source;
+    }
+    
+    public T getAddedValue() {
+        return addedValue;
+    }
+    
+    @Override
+    public String toString() {
+        return ObjectContracts.toString(this, "source,addedValue");
+    }
+}
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/isis/blob/43c50c46/core/applib/src/main/java/org/apache/isis/applib/services/eventbus/CollectionRemovedFromEvent.java
----------------------------------------------------------------------
diff --git a/core/applib/src/main/java/org/apache/isis/applib/services/eventbus/CollectionRemovedFromEvent.java b/core/applib/src/main/java/org/apache/isis/applib/services/eventbus/CollectionRemovedFromEvent.java
new file mode 100644
index 0000000..84289da
--- /dev/null
+++ b/core/applib/src/main/java/org/apache/isis/applib/services/eventbus/CollectionRemovedFromEvent.java
@@ -0,0 +1,54 @@
+/*
+ *  Licensed to the Apache Software Foundation (ASF) under one
+ *  or more contributor license agreements.  See the NOTICE file
+ *  distributed with this work for additional information
+ *  regarding copyright ownership.  The ASF licenses this file
+ *  to you under the Apache License, Version 2.0 (the
+ *  "License"); you may not use this file except in compliance
+ *  with the License.  You may obtain a copy of the License at
+ *
+ *        http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *  Unless required by applicable law or agreed to in writing,
+ *  software distributed under the License is distributed on an
+ *  "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ *  KIND, either express or implied.  See the License for the
+ *  specific language governing permissions and limitations
+ *  under the License.
+ */
+package org.apache.isis.applib.services.eventbus;
+
+import org.apache.isis.applib.util.ObjectContracts;
+
+public abstract class CollectionRemovedFromEvent<S,T> {
+    private final S source;
+    private final T removedValue;
+    
+    /**
+     * To instantiate reflectively when the {@link PostsCollectionAddedToEvent} annotation
+     * is used.
+     * 
+     * <p>
+     * The fields ({@link #source} and {@link #removedValue} are then set reflectively.
+     */
+    public CollectionRemovedFromEvent() {
+        this(null, null);
+    }
+    public CollectionRemovedFromEvent(S source, T removedValue) {
+        this.source = source;
+        this.removedValue = removedValue;
+    }
+
+    public S getSource() {
+        return source;
+    }
+    
+    public T getRemovedValue() {
+        return removedValue;
+    }
+    
+    @Override
+    public String toString() {
+        return ObjectContracts.toString(this, "source,removedValue");
+    }
+}
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/isis/blob/43c50c46/core/applib/src/main/java/org/apache/isis/applib/services/eventbus/RemovedFromCollectionEvent.java
----------------------------------------------------------------------
diff --git a/core/applib/src/main/java/org/apache/isis/applib/services/eventbus/RemovedFromCollectionEvent.java b/core/applib/src/main/java/org/apache/isis/applib/services/eventbus/RemovedFromCollectionEvent.java
deleted file mode 100644
index e33ed95..0000000
--- a/core/applib/src/main/java/org/apache/isis/applib/services/eventbus/RemovedFromCollectionEvent.java
+++ /dev/null
@@ -1,54 +0,0 @@
-/*
- *  Licensed to the Apache Software Foundation (ASF) under one
- *  or more contributor license agreements.  See the NOTICE file
- *  distributed with this work for additional information
- *  regarding copyright ownership.  The ASF licenses this file
- *  to you under the Apache License, Version 2.0 (the
- *  "License"); you may not use this file except in compliance
- *  with the License.  You may obtain a copy of the License at
- *
- *        http://www.apache.org/licenses/LICENSE-2.0
- *
- *  Unless required by applicable law or agreed to in writing,
- *  software distributed under the License is distributed on an
- *  "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- *  KIND, either express or implied.  See the License for the
- *  specific language governing permissions and limitations
- *  under the License.
- */
-package org.apache.isis.applib.services.eventbus;
-
-import org.apache.isis.applib.util.ObjectContracts;
-
-public abstract class RemovedFromCollectionEvent<S,T> {
-    private final S source;
-    private final T removedValue;
-    
-    /**
-     * To instantiate reflectively when the {@link PostsAddedToCollectionEvent} annotation
-     * is used.
-     * 
-     * <p>
-     * The fields ({@link #source} and {@link #removedValue} are then set reflectively.
-     */
-    public RemovedFromCollectionEvent() {
-        this(null, null);
-    }
-    public RemovedFromCollectionEvent(S source, T removedValue) {
-        this.source = source;
-        this.removedValue = removedValue;
-    }
-
-    public S getSource() {
-        return source;
-    }
-    
-    public T getRemovedValue() {
-        return removedValue;
-    }
-    
-    @Override
-    public String toString() {
-        return ObjectContracts.toString(this, "source,removedValue");
-    }
-}
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/isis/blob/43c50c46/core/metamodel/src/main/java/org/apache/isis/core/progmodel/facets/collections/event/PostsCollectionAddToEventAnnotationFacetFactory.java
----------------------------------------------------------------------
diff --git a/core/metamodel/src/main/java/org/apache/isis/core/progmodel/facets/collections/event/PostsCollectionAddToEventAnnotationFacetFactory.java b/core/metamodel/src/main/java/org/apache/isis/core/progmodel/facets/collections/event/PostsCollectionAddToEventAnnotationFacetFactory.java
index e68b05c..408a144 100644
--- a/core/metamodel/src/main/java/org/apache/isis/core/progmodel/facets/collections/event/PostsCollectionAddToEventAnnotationFacetFactory.java
+++ b/core/metamodel/src/main/java/org/apache/isis/core/progmodel/facets/collections/event/PostsCollectionAddToEventAnnotationFacetFactory.java
@@ -23,8 +23,8 @@ import java.lang.reflect.Method;
 import java.util.Comparator;
 import java.util.List;
 
-import org.apache.isis.applib.annotation.PostsAddedToCollectionEvent;
-import org.apache.isis.applib.services.eventbus.AddedToCollectionEvent;
+import org.apache.isis.applib.annotation.PostsCollectionAddedToEvent;
+import org.apache.isis.applib.services.eventbus.CollectionAddedToEvent;
 import org.apache.isis.core.commons.config.IsisConfiguration;
 import org.apache.isis.core.metamodel.adapter.ServicesProvider;
 import org.apache.isis.core.metamodel.adapter.ServicesProviderAware;
@@ -61,7 +61,7 @@ public class PostsCollectionAddToEventAnnotationFacetFactory extends FacetFactor
     }
 
     private PostsAddedToCollectionEventFacet create(Method method, final FacetHolder holder) {
-        final PostsAddedToCollectionEvent annotation = Annotations.getAnnotation(method, PostsAddedToCollectionEvent.class);
+        final PostsCollectionAddedToEvent annotation = Annotations.getAnnotation(method, PostsCollectionAddedToEvent.class);
         if(annotation == null) {
             return null;
         }
@@ -80,7 +80,7 @@ public class PostsCollectionAddToEventAnnotationFacetFactory extends FacetFactor
         if(collectionFacet != null) {
             holder.removeFacet(collectionFacet);
         }
-        final Class<? extends AddedToCollectionEvent<?,?>> changedEventType = annotation.value();
+        final Class<? extends CollectionAddedToEvent<?,?>> changedEventType = annotation.value();
         return new PostsCollectionAddToEventFacetAnnotation(changedEventType, postsAddedToCollectionEventFacet, collectionAddToFacet, collectionFacet, servicesProvider, holder);
     }
 

http://git-wip-us.apache.org/repos/asf/isis/blob/43c50c46/core/metamodel/src/main/java/org/apache/isis/core/progmodel/facets/collections/event/PostsCollectionAddToEventFacetAnnotation.java
----------------------------------------------------------------------
diff --git a/core/metamodel/src/main/java/org/apache/isis/core/progmodel/facets/collections/event/PostsCollectionAddToEventFacetAnnotation.java b/core/metamodel/src/main/java/org/apache/isis/core/progmodel/facets/collections/event/PostsCollectionAddToEventFacetAnnotation.java
index 6c59633..8318cdb 100644
--- a/core/metamodel/src/main/java/org/apache/isis/core/progmodel/facets/collections/event/PostsCollectionAddToEventFacetAnnotation.java
+++ b/core/metamodel/src/main/java/org/apache/isis/core/progmodel/facets/collections/event/PostsCollectionAddToEventFacetAnnotation.java
@@ -26,7 +26,7 @@ import java.util.List;
 import com.google.common.collect.Lists;
 
 import org.apache.isis.applib.FatalException;
-import org.apache.isis.applib.services.eventbus.AddedToCollectionEvent;
+import org.apache.isis.applib.services.eventbus.CollectionAddedToEvent;
 import org.apache.isis.applib.services.eventbus.EventBusService;
 import org.apache.isis.core.metamodel.adapter.ObjectAdapter;
 import org.apache.isis.core.metamodel.adapter.ServicesProvider;
@@ -47,10 +47,10 @@ public class PostsCollectionAddToEventFacetAnnotation extends
 
 	private EventBusService eventBusService;
 	private boolean searchedForEventBusService = false;
-	private Class<? extends AddedToCollectionEvent<?, ?>> addedToCollectionEventType;
+	private Class<? extends CollectionAddedToEvent<?, ?>> addedToCollectionEventType;
 
 	public PostsCollectionAddToEventFacetAnnotation(
-			Class<? extends AddedToCollectionEvent<?, ?>> addedToCollectionEventType,
+			Class<? extends CollectionAddedToEvent<?, ?>> addedToCollectionEventType,
 			CollectionAddToFacet collectionAddToFacet,
 			CollectionFacet collectionFacet,
 			ServicesProvider servicesProvider, FacetHolder holder) {
@@ -86,7 +86,7 @@ public class PostsCollectionAddToEventFacetAnnotation extends
 		final Object source = inObject.getObject();
 		try {
 			final Class type =  addedToCollectionEventType;
-			final AddedToCollectionEvent<?, ?> event = newEvent(type, addedValue, source);
+			final CollectionAddedToEvent<?, ?> event = newEvent(type, addedValue, source);
 
 			eventBusService.post(event);
 		} catch (Exception e) {
@@ -95,12 +95,12 @@ public class PostsCollectionAddToEventFacetAnnotation extends
 	}
 
 
-	static <S, T> AddedToCollectionEvent<S, T> newEvent(
-			final Class<? extends AddedToCollectionEvent<S, T>> type,
+	static <S, T> CollectionAddedToEvent<S, T> newEvent(
+			final Class<? extends CollectionAddedToEvent<S, T>> type,
 			final T addedValue, final S source)
 			throws InstantiationException, IllegalAccessException,
 			NoSuchFieldException {
-		final AddedToCollectionEvent<S, T> event = type.newInstance();
+		final CollectionAddedToEvent<S, T> event = type.newInstance();
 
 		setField("source", event, source);
 		setField("addedValue", event, addedValue);
@@ -108,9 +108,9 @@ public class PostsCollectionAddToEventFacetAnnotation extends
 	}
 
 	private static void setField(final String name,
-			final AddedToCollectionEvent<?, ?> event, final Object sourceValue)
+			final CollectionAddedToEvent<?, ?> event, final Object sourceValue)
 			throws NoSuchFieldException, IllegalAccessException {
-		final Field sourceField = AddedToCollectionEvent.class
+		final Field sourceField = CollectionAddedToEvent.class
 				.getDeclaredField(name);
 		sourceField.setAccessible(true);
 		sourceField.set(event, sourceValue);

http://git-wip-us.apache.org/repos/asf/isis/blob/43c50c46/core/metamodel/src/test/java/org/apache/isis/core/progmodel/facets/collections/event/PostsCollectionAddedEventFacetAnnotationTest_newEvent.java
----------------------------------------------------------------------
diff --git a/core/metamodel/src/test/java/org/apache/isis/core/progmodel/facets/collections/event/PostsCollectionAddedEventFacetAnnotationTest_newEvent.java b/core/metamodel/src/test/java/org/apache/isis/core/progmodel/facets/collections/event/PostsCollectionAddedEventFacetAnnotationTest_newEvent.java
index ab89c44..5f22cc4 100644
--- a/core/metamodel/src/test/java/org/apache/isis/core/progmodel/facets/collections/event/PostsCollectionAddedEventFacetAnnotationTest_newEvent.java
+++ b/core/metamodel/src/test/java/org/apache/isis/core/progmodel/facets/collections/event/PostsCollectionAddedEventFacetAnnotationTest_newEvent.java
@@ -14,7 +14,7 @@
  *  See the License for the specific language governing permissions and
  *  limitations under the License.
  */
-package org.apache.isis.core.progmodel.facets.properties.event;
+package org.apache.isis.core.progmodel.facets.collections.event;
 
 import static org.hamcrest.CoreMatchers.is;
 import static org.junit.Assert.assertThat;
@@ -28,14 +28,14 @@ public class PostsCollectionAddedEventFacetAnnotationTest_newEvent {
 
     public static class SomeDomainObject {}
     
-    public static class SomeDomainObjectCollectionAddedEvent extends AddToCollectionEvent<SomeDomainObject, SomeDomainObject> {}
-    
-    @Test
-    public void test() throws Exception {
-        SomeDomainObject sdo = new SomeDomainObject();
-        final PropertyChangedEvent<SomeDomainObject, LocalDate> ev = PostsPropertyChangedEventFacetAnnotation.newEvent(SomeDatePropertyChangedEvent.class, new SomeDomainObject(), sdo);
-        assertThat(ev.getSource(), is(sdo));
-        assertThat(ev.getNewValue(), is(new LocalDate(2013,4,1)));
-    }
+//    public static class SomeDomainObjectCollectionAddedEvent extends AddToCollectionEvent<SomeDomainObject, SomeDomainObject> {}
+//    
+//    @Test
+//    public void test() throws Exception {
+//        SomeDomainObject sdo = new SomeDomainObject();
+//        final PropertyChangedEvent<SomeDomainObject, LocalDate> ev = PostsPropertyChangedEventFacetAnnotation.newEvent(SomeDatePropertyChangedEvent.class, new SomeDomainObject(), sdo);
+//        assertThat(ev.getSource(), is(sdo));
+//        assertThat(ev.getNewValue(), is(new LocalDate(2013,4,1)));
+//    }
 
 }


[14/16] ISIS-550: refactored DomainObjectInvocationHandler and ImperativeFacets

Posted by da...@apache.org.
http://git-wip-us.apache.org/repos/asf/isis/blob/5f15fa74/core/wrapper/src/test/java/org/apache/isis/progmodel/wrapper/WrapperFactoryAbstractTest_wrappedObject.java
----------------------------------------------------------------------
diff --git a/core/wrapper/src/test/java/org/apache/isis/progmodel/wrapper/WrapperFactoryAbstractTest_wrappedObject.java b/core/wrapper/src/test/java/org/apache/isis/progmodel/wrapper/WrapperFactoryAbstractTest_wrappedObject.java
index 1d38027..014fa49 100644
--- a/core/wrapper/src/test/java/org/apache/isis/progmodel/wrapper/WrapperFactoryAbstractTest_wrappedObject.java
+++ b/core/wrapper/src/test/java/org/apache/isis/progmodel/wrapper/WrapperFactoryAbstractTest_wrappedObject.java
@@ -47,6 +47,7 @@ import org.apache.isis.core.metamodel.adapter.mgr.AdapterManager;
 import org.apache.isis.core.metamodel.deployment.DeploymentCategory;
 import org.apache.isis.core.metamodel.facetapi.FacetUtil;
 import org.apache.isis.core.metamodel.facets.FacetedMethod;
+import org.apache.isis.core.metamodel.facets.named.NamedFacetInferred;
 import org.apache.isis.core.metamodel.spec.SpecificationLoader;
 import org.apache.isis.core.metamodel.spec.feature.ObjectMember;
 import org.apache.isis.core.metamodel.spec.feature.ObjectMemberContext;
@@ -118,8 +119,6 @@ public abstract class WrapperFactoryAbstractTest_wrappedObject {
     private WrapperFactoryAbstract wrapperFactory;
 
 
-
-
     @Before
     public void setUp() {
 
@@ -330,7 +329,7 @@ public abstract class WrapperFactoryAbstractTest_wrappedObject {
         FacetUtil.addFacet(new HideForContextFacetViaMethod(hide, facetedMethod));
         FacetUtil.addFacet(new DisableForContextFacetViaMethod(disable, facetedMethod));
         FacetUtil.addFacet(new PropertyValidateFacetViaMethod(validate, facetedMethod));
-        FacetUtil.addFacet(new NamedFacetViaMethod(accessor.getName(), accessor, facetedMethod));
+        FacetUtil.addFacet(new NamedFacetInferred(accessor.getName(), facetedMethod));
         return facetedMethod;
     }
 

http://git-wip-us.apache.org/repos/asf/isis/blob/5f15fa74/core/wrapper/src/test/java/org/apache/isis/progmodel/wrapper/WrapperFactoryAbstractTest_wrappedObject_transient.java
----------------------------------------------------------------------
diff --git a/core/wrapper/src/test/java/org/apache/isis/progmodel/wrapper/WrapperFactoryAbstractTest_wrappedObject_transient.java b/core/wrapper/src/test/java/org/apache/isis/progmodel/wrapper/WrapperFactoryAbstractTest_wrappedObject_transient.java
index 3d2d984..a3f8c04 100644
--- a/core/wrapper/src/test/java/org/apache/isis/progmodel/wrapper/WrapperFactoryAbstractTest_wrappedObject_transient.java
+++ b/core/wrapper/src/test/java/org/apache/isis/progmodel/wrapper/WrapperFactoryAbstractTest_wrappedObject_transient.java
@@ -30,6 +30,7 @@ import java.util.List;
 import org.jmock.Expectations;
 import org.jmock.auto.Mock;
 import org.junit.Before;
+import org.junit.Ignore;
 import org.junit.Rule;
 import org.junit.Test;
 
@@ -204,6 +205,7 @@ public abstract class WrapperFactoryAbstractTest_wrappedObject_transient {
         // then should throw exception
     }
 
+    @Ignore("TODO - reinstate or replace with integration tests")
     @Test
     public void canModifyProperty() {
         // given
@@ -228,9 +230,9 @@ public abstract class WrapperFactoryAbstractTest_wrappedObject_transient {
         facets = Arrays.asList((Facet)new PropertySetterFacetViaSetterMethod(setPasswordMethod, mockPasswordMember));
         context.checking(new Expectations() {
             {
-                oneOf(mockPasswordMember).getFacets(with(any(Filter.class)));
+                allowing(mockPasswordMember).getFacets(with(any(Filter.class)));
                 will(returnValue(facets));
-                
+
                 oneOf(mockPasswordMember).set(mockEmployeeAdapter, mockPasswordAdapter);
             }
         });
@@ -243,7 +245,7 @@ public abstract class WrapperFactoryAbstractTest_wrappedObject_transient {
         facets = Arrays.asList((Facet)new PropertyAccessorFacetViaAccessor(getPasswordMethod, mockPasswordMember));
         context.checking(new Expectations() {
             {
-                oneOf(mockPasswordMember).getFacets(with(any(Filter.class)));
+                allowing(mockPasswordMember).getFacets(with(any(Filter.class)));
                 will(returnValue(facets));
                 
                 oneOf(mockPasswordMember).get(mockEmployeeAdapter);


[11/16] ISIS-550: working on ActionInvokedEvent, adding integration tests.

Posted by da...@apache.org.
http://git-wip-us.apache.org/repos/asf/isis/blob/e1f19baa/core/metamodel/src/test/java/org/apache/isis/core/metamodel/facets/actions/event/PostsActionInvokedEventFacet_UtilTest_newEvent.java
----------------------------------------------------------------------
diff --git a/core/metamodel/src/test/java/org/apache/isis/core/metamodel/facets/actions/event/PostsActionInvokedEventFacet_UtilTest_newEvent.java b/core/metamodel/src/test/java/org/apache/isis/core/metamodel/facets/actions/event/PostsActionInvokedEventFacet_UtilTest_newEvent.java
new file mode 100644
index 0000000..1008d08
--- /dev/null
+++ b/core/metamodel/src/test/java/org/apache/isis/core/metamodel/facets/actions/event/PostsActionInvokedEventFacet_UtilTest_newEvent.java
@@ -0,0 +1,70 @@
+/**
+ *  Licensed to the Apache Software Foundation (ASF) under one or more
+ *  contributor license agreements.  See the NOTICE file distributed with
+ *  this work for additional information regarding copyright ownership.
+ *  The ASF licenses this file to You under the Apache License, Version 2.0
+ *  (the "License"); you may not use this file except in compliance with
+ *  the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *  Unless required by applicable law or agreed to in writing, software
+ *  distributed under the License is distributed on an "AS IS" BASIS,
+ *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ *  See the License for the specific language governing permissions and
+ *  limitations under the License.
+ */
+package org.apache.isis.core.metamodel.facets.actions.event;
+
+import static org.hamcrest.CoreMatchers.is;
+import static org.hamcrest.CoreMatchers.not;
+import static org.hamcrest.CoreMatchers.nullValue;
+import static org.junit.Assert.assertThat;
+
+import org.junit.Test;
+
+import org.apache.isis.applib.Identifier;
+import org.apache.isis.applib.services.eventbus.ActionInvokedEvent;
+
+public class PostsActionInvokedEventFacet_UtilTest_newEvent {
+
+    public static class SomeDomainObject {
+        public String foo(int x, String y) { return null; }
+    }
+    
+    public static class SomeDomainObjectFooInvokedEvent extends ActionInvokedEvent<SomeDomainObject> {
+        private static final long serialVersionUID = 1L;
+        public SomeDomainObjectFooInvokedEvent(SomeDomainObject source, Identifier identifier, Object... arguments) {
+            super(source, identifier, arguments);
+        }
+    }
+    
+    @Test
+    public void defaultEventType() throws Exception {
+        SomeDomainObject sdo = new SomeDomainObject();
+        Identifier identifier = Identifier.actionIdentifier(SomeDomainObject.class, "foo", new Class[]{int.class, String.class});
+
+        final ActionInvokedEvent<Object> ev = PostsActionInvokedEventFacet.Util.newEvent(
+                ActionInvokedEvent.Default.class, sdo, identifier, new Object[]{1, "bar"});
+        assertThat(ev.getSource(), is((Object)sdo));
+        assertThat(ev.getIdentifier(), is(identifier));
+        assertThat(ev.getArguments(), is(not(nullValue())));
+        assertThat(ev.getArguments().get(0), is((Object)Integer.valueOf(1)));
+        assertThat(ev.getArguments().get(1), is((Object)"bar"));
+    }
+
+    @Test
+    public void customEventType() throws Exception {
+        SomeDomainObject sdo = new SomeDomainObject();
+        Identifier identifier = Identifier.actionIdentifier(SomeDomainObject.class, "foo", new Class[]{int.class, String.class});
+        
+        final ActionInvokedEvent<SomeDomainObject> ev = PostsActionInvokedEventFacet.Util.newEvent(
+                SomeDomainObjectFooInvokedEvent.class, sdo, identifier, new Object[]{1, "bar"});
+        assertThat((SomeDomainObject)ev.getSource(), is(sdo));
+        assertThat(ev.getIdentifier(), is(identifier));
+        assertThat(ev.getArguments(), is(not(nullValue())));
+        assertThat(ev.getArguments().get(0), is((Object)Integer.valueOf(1)));
+        assertThat(ev.getArguments().get(1), is((Object)"bar"));
+    }
+    
+}

http://git-wip-us.apache.org/repos/asf/isis/blob/e1f19baa/core/metamodel/src/test/java/org/apache/isis/core/metamodel/facets/collections/event/PostsCollectionAddedToEventFacet_UtilTest_newEvent.java
----------------------------------------------------------------------
diff --git a/core/metamodel/src/test/java/org/apache/isis/core/metamodel/facets/collections/event/PostsCollectionAddedToEventFacet_UtilTest_newEvent.java b/core/metamodel/src/test/java/org/apache/isis/core/metamodel/facets/collections/event/PostsCollectionAddedToEventFacet_UtilTest_newEvent.java
new file mode 100644
index 0000000..e548365
--- /dev/null
+++ b/core/metamodel/src/test/java/org/apache/isis/core/metamodel/facets/collections/event/PostsCollectionAddedToEventFacet_UtilTest_newEvent.java
@@ -0,0 +1,72 @@
+/**
+ *  Licensed to the Apache Software Foundation (ASF) under one or more
+ *  contributor license agreements.  See the NOTICE file distributed with
+ *  this work for additional information regarding copyright ownership.
+ *  The ASF licenses this file to You under the Apache License, Version 2.0
+ *  (the "License"); you may not use this file except in compliance with
+ *  the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *  Unless required by applicable law or agreed to in writing, software
+ *  distributed under the License is distributed on an "AS IS" BASIS,
+ *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ *  See the License for the specific language governing permissions and
+ *  limitations under the License.
+ */
+package org.apache.isis.core.metamodel.facets.collections.event;
+
+import static org.hamcrest.CoreMatchers.is;
+import static org.junit.Assert.assertThat;
+
+import java.util.Set;
+
+import org.junit.Test;
+
+import org.apache.isis.applib.Identifier;
+import org.apache.isis.applib.annotation.PostsCollectionAddedToEvent;
+import org.apache.isis.applib.services.eventbus.CollectionAddedToEvent;
+import org.apache.isis.core.metamodel.facets.collections.event.PostsCollectionAddedToEventFacetAbstract;
+import org.apache.isis.core.progmodel.facets.collections.event.PostsCollectionAddedToEventFacetAnnotation;
+
+public class PostsCollectionAddedToEventFacet_UtilTest_newEvent {
+
+    public static class SomeDomainObject {
+        public Set<SomeReferencedObject> getReferences() { return null; }
+    }
+    public static class SomeReferencedObject {}
+    
+    public static class SomeDomainObjectCollectionAddedToEvent extends CollectionAddedToEvent<SomeDomainObject, SomeReferencedObject> {
+        private static final long serialVersionUID = 1L;
+        public SomeDomainObjectCollectionAddedToEvent(SomeDomainObject source, Identifier identifier, SomeReferencedObject value) {
+            super(source, identifier, value);
+        }
+    }
+    
+    @Test
+    public void defautEventType() throws Exception {
+        final SomeDomainObject sdo = new SomeDomainObject();
+        final SomeReferencedObject other = new SomeReferencedObject();
+        final Identifier identifier = Identifier.propertyOrCollectionIdentifier(SomeDomainObject.class, "references");
+
+        final CollectionAddedToEvent<Object, Object> ev = PostsCollectionAddedToEventFacet.Util.newEvent(
+                CollectionAddedToEvent.Default.class, sdo, identifier, other);
+        assertThat(ev.getSource(), is((Object)sdo));
+        assertThat(ev.getIdentifier(), is(identifier));
+        assertThat(ev.getValue(), is((Object)other));
+    }
+
+    @Test
+    public void customEventType() throws Exception {
+        final SomeDomainObject sdo = new SomeDomainObject();
+        final SomeReferencedObject other = new SomeReferencedObject();
+        final Identifier identifier = Identifier.propertyOrCollectionIdentifier(SomeDomainObject.class, "references");
+        
+        final CollectionAddedToEvent<SomeDomainObject, SomeReferencedObject> ev = PostsCollectionAddedToEventFacet.Util.newEvent(
+                SomeDomainObjectCollectionAddedToEvent.class, sdo, identifier, other);
+        assertThat(ev.getSource(), is(sdo));
+        assertThat(ev.getIdentifier(), is(identifier));
+        assertThat(ev.getValue(), is(other));
+    }
+    
+}

http://git-wip-us.apache.org/repos/asf/isis/blob/e1f19baa/core/metamodel/src/test/java/org/apache/isis/core/metamodel/facets/collections/event/PostsCollectionRemovedFromEventFacet_UtilTest_newEvent.java
----------------------------------------------------------------------
diff --git a/core/metamodel/src/test/java/org/apache/isis/core/metamodel/facets/collections/event/PostsCollectionRemovedFromEventFacet_UtilTest_newEvent.java b/core/metamodel/src/test/java/org/apache/isis/core/metamodel/facets/collections/event/PostsCollectionRemovedFromEventFacet_UtilTest_newEvent.java
new file mode 100644
index 0000000..7404a26
--- /dev/null
+++ b/core/metamodel/src/test/java/org/apache/isis/core/metamodel/facets/collections/event/PostsCollectionRemovedFromEventFacet_UtilTest_newEvent.java
@@ -0,0 +1,70 @@
+/**
+ *  Licensed to the Apache Software Foundation (ASF) under one or more
+ *  contributor license agreements.  See the NOTICE file distributed with
+ *  this work for additional information regarding copyright ownership.
+ *  The ASF licenses this file to You under the Apache License, Version 2.0
+ *  (the "License"); you may not use this file except in compliance with
+ *  the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *  Unless required by applicable law or agreed to in writing, software
+ *  distributed under the License is distributed on an "AS IS" BASIS,
+ *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ *  See the License for the specific language governing permissions and
+ *  limitations under the License.
+ */
+package org.apache.isis.core.metamodel.facets.collections.event;
+
+import static org.hamcrest.CoreMatchers.is;
+import static org.junit.Assert.assertThat;
+
+import java.util.Set;
+
+import org.junit.Test;
+
+import org.apache.isis.applib.Identifier;
+import org.apache.isis.applib.services.eventbus.CollectionRemovedFromEvent;
+import org.apache.isis.core.metamodel.facets.collections.event.PostsCollectionRemovedFromEventFacetAbstract;
+
+public class PostsCollectionRemovedFromEventFacet_UtilTest_newEvent {
+
+    public static class SomeDomainObject {
+        public Set<SomeReferencedObject> getReferences() { return null; }
+    }
+    public static class SomeReferencedObject {}
+    
+    public static class SomeDomainObjectCollectionRemovedFromEvent extends CollectionRemovedFromEvent<SomeDomainObject, SomeReferencedObject> {
+        private static final long serialVersionUID = 1L;
+        public SomeDomainObjectCollectionRemovedFromEvent(SomeDomainObject source, Identifier identifier, SomeReferencedObject value) {
+            super(source, identifier, value);
+        }
+    }
+    
+    @Test
+    public void defaultEventType() throws Exception {
+        SomeDomainObject sdo = new SomeDomainObject();
+        SomeReferencedObject other = new SomeReferencedObject();
+        Identifier identifier = Identifier.propertyOrCollectionIdentifier(SomeDomainObject.class, "references");
+
+        final CollectionRemovedFromEvent<Object, Object> ev = PostsCollectionRemovedFromEventFacet.Util.newEvent(
+                CollectionRemovedFromEvent.Default.class, sdo, identifier, other);
+        assertThat(ev.getSource(), is((Object)sdo));
+        assertThat(ev.getIdentifier(), is(identifier));
+        assertThat(ev.getValue(), is((Object)other));
+    }
+
+    @Test
+    public void customEventType() throws Exception {
+        SomeDomainObject sdo = new SomeDomainObject();
+        SomeReferencedObject other = new SomeReferencedObject();
+        Identifier identifier = Identifier.propertyOrCollectionIdentifier(SomeDomainObject.class, "references");
+        
+        final CollectionRemovedFromEvent<SomeDomainObject, SomeReferencedObject> ev = PostsCollectionRemovedFromEventFacet.Util.newEvent(
+                SomeDomainObjectCollectionRemovedFromEvent.class, sdo, identifier, other);
+        assertThat(ev.getSource(), is(sdo));
+        assertThat(ev.getIdentifier(), is(identifier));
+        assertThat(ev.getValue(), is(other));
+    }
+    
+}

http://git-wip-us.apache.org/repos/asf/isis/blob/e1f19baa/core/metamodel/src/test/java/org/apache/isis/core/metamodel/facets/properties/event/PostsPropertyChangedEventFacet_UtilTest_newEvent.java
----------------------------------------------------------------------
diff --git a/core/metamodel/src/test/java/org/apache/isis/core/metamodel/facets/properties/event/PostsPropertyChangedEventFacet_UtilTest_newEvent.java b/core/metamodel/src/test/java/org/apache/isis/core/metamodel/facets/properties/event/PostsPropertyChangedEventFacet_UtilTest_newEvent.java
new file mode 100644
index 0000000..2f554fe
--- /dev/null
+++ b/core/metamodel/src/test/java/org/apache/isis/core/metamodel/facets/properties/event/PostsPropertyChangedEventFacet_UtilTest_newEvent.java
@@ -0,0 +1,73 @@
+/**
+ *  Licensed to the Apache Software Foundation (ASF) under one or more
+ *  contributor license agreements.  See the NOTICE file distributed with
+ *  this work for additional information regarding copyright ownership.
+ *  The ASF licenses this file to You under the Apache License, Version 2.0
+ *  (the "License"); you may not use this file except in compliance with
+ *  the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *  Unless required by applicable law or agreed to in writing, software
+ *  distributed under the License is distributed on an "AS IS" BASIS,
+ *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ *  See the License for the specific language governing permissions and
+ *  limitations under the License.
+ */
+package org.apache.isis.core.metamodel.facets.properties.event;
+
+import static org.hamcrest.CoreMatchers.is;
+import static org.junit.Assert.assertThat;
+
+import org.joda.time.LocalDate;
+import org.junit.Test;
+
+import org.apache.isis.applib.Identifier;
+import org.apache.isis.applib.services.eventbus.PropertyChangedEvent;
+import org.apache.isis.core.metamodel.facets.properties.event.PostsPropertyChangedEventFacetAbstract;
+
+public class PostsPropertyChangedEventFacet_UtilTest_newEvent {
+
+    public static class SomeDomainObject {}
+    
+    public static class SomeDatePropertyChangedEvent extends PropertyChangedEvent<SomeDomainObject, LocalDate> {
+        private static final long serialVersionUID = 1L;
+        public SomeDatePropertyChangedEvent(SomeDomainObject source, Identifier identifier, LocalDate oldValue, LocalDate newValue) {
+            super(source, identifier, oldValue, newValue);
+        }
+    }
+
+    @Test
+    public void defaultEventType() throws Exception {
+        
+        SomeDomainObject sdo = new SomeDomainObject();
+        Identifier identifier = Identifier.propertyOrCollectionIdentifier(SomeDomainObject.class, "someDateProperty");
+        LocalDate oldValue = new LocalDate(2013,4,1);
+        LocalDate newValue = new LocalDate(2013,5,2);
+        
+        final PropertyChangedEvent<Object, Object> ev = 
+                PostsPropertyChangedEventFacet.Util.newEvent(PropertyChangedEvent.Default.class, sdo, identifier, oldValue, newValue);
+        assertThat(ev.getSource(), is((Object)sdo));
+        assertThat(ev.getIdentifier(), is(identifier));
+        assertThat(ev.getOldValue(), is((Object)oldValue));
+        assertThat(ev.getNewValue(), is((Object)newValue));
+    }
+
+
+    @Test
+    public void customEventType() throws Exception {
+
+        SomeDomainObject sdo = new SomeDomainObject();
+        Identifier identifier = Identifier.propertyOrCollectionIdentifier(SomeDomainObject.class, "someDateProperty");
+        LocalDate oldValue = new LocalDate(2013,4,1);
+        LocalDate newValue = new LocalDate(2013,5,2);
+        
+        final PropertyChangedEvent<SomeDomainObject, LocalDate> ev = 
+                PostsPropertyChangedEventFacet.Util.newEvent(SomeDatePropertyChangedEvent.class, sdo, identifier, oldValue, newValue);
+        assertThat(ev.getSource(), is(sdo));
+        assertThat(ev.getIdentifier(), is(identifier));
+        assertThat(ev.getOldValue(), is(oldValue));
+        assertThat(ev.getNewValue(), is(newValue));
+    }
+    
+}

http://git-wip-us.apache.org/repos/asf/isis/blob/e1f19baa/core/metamodel/src/test/java/org/apache/isis/core/progmodel/facets/collections/event/PostsCollectionAddedEventFacetAnnotationTest_newEvent.java
----------------------------------------------------------------------
diff --git a/core/metamodel/src/test/java/org/apache/isis/core/progmodel/facets/collections/event/PostsCollectionAddedEventFacetAnnotationTest_newEvent.java b/core/metamodel/src/test/java/org/apache/isis/core/progmodel/facets/collections/event/PostsCollectionAddedEventFacetAnnotationTest_newEvent.java
deleted file mode 100644
index 07baa29..0000000
--- a/core/metamodel/src/test/java/org/apache/isis/core/progmodel/facets/collections/event/PostsCollectionAddedEventFacetAnnotationTest_newEvent.java
+++ /dev/null
@@ -1,53 +0,0 @@
-/**
- *  Licensed to the Apache Software Foundation (ASF) under one or more
- *  contributor license agreements.  See the NOTICE file distributed with
- *  this work for additional information regarding copyright ownership.
- *  The ASF licenses this file to You under the Apache License, Version 2.0
- *  (the "License"); you may not use this file except in compliance with
- *  the License.  You may obtain a copy of the License at
- *
- *     http://www.apache.org/licenses/LICENSE-2.0
- *
- *  Unless required by applicable law or agreed to in writing, software
- *  distributed under the License is distributed on an "AS IS" BASIS,
- *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- *  See the License for the specific language governing permissions and
- *  limitations under the License.
- */
-package org.apache.isis.core.progmodel.facets.collections.event;
-
-import static org.hamcrest.CoreMatchers.is;
-import static org.junit.Assert.assertThat;
-
-import java.util.Set;
-
-import org.junit.Test;
-
-import org.apache.isis.applib.Identifier;
-import org.apache.isis.applib.services.eventbus.CollectionAddedToEvent;
-
-public class PostsCollectionAddedEventFacetAnnotationTest_newEvent {
-
-    public static class SomeDomainObject {
-        public Set<SomeReferencedObject> getReferences() { return null; }
-    }
-    public static class SomeReferencedObject {}
-    
-    public static class SomeDomainObjectCollectionAddedToEvent extends CollectionAddedToEvent<SomeDomainObject, SomeReferencedObject> {
-        private static final long serialVersionUID = 1L;
-    }
-    
-    @Test
-    public void test() throws Exception {
-        SomeDomainObject sdo = new SomeDomainObject();
-        SomeReferencedObject other = new SomeReferencedObject();
-        Identifier identifier = Identifier.propertyOrCollectionIdentifier(SomeDomainObject.class, "references");
-
-        final CollectionAddedToEvent<SomeDomainObject, SomeReferencedObject> ev = PostsCollectionAddedToEventFacetAnnotation.newEvent(
-                SomeDomainObjectCollectionAddedToEvent.class, sdo, identifier, other);
-        assertThat(ev.getSource(), is(sdo));
-        assertThat(ev.getIdentifier(), is(identifier));
-        assertThat(ev.getValue(), is(other));
-    }
-
-}

http://git-wip-us.apache.org/repos/asf/isis/blob/e1f19baa/core/metamodel/src/test/java/org/apache/isis/core/progmodel/facets/collections/event/PostsCollectionRemovedEventFacetAnnotationTest_newEvent.java
----------------------------------------------------------------------
diff --git a/core/metamodel/src/test/java/org/apache/isis/core/progmodel/facets/collections/event/PostsCollectionRemovedEventFacetAnnotationTest_newEvent.java b/core/metamodel/src/test/java/org/apache/isis/core/progmodel/facets/collections/event/PostsCollectionRemovedEventFacetAnnotationTest_newEvent.java
deleted file mode 100644
index 76ea7a4..0000000
--- a/core/metamodel/src/test/java/org/apache/isis/core/progmodel/facets/collections/event/PostsCollectionRemovedEventFacetAnnotationTest_newEvent.java
+++ /dev/null
@@ -1,52 +0,0 @@
-/**
- *  Licensed to the Apache Software Foundation (ASF) under one or more
- *  contributor license agreements.  See the NOTICE file distributed with
- *  this work for additional information regarding copyright ownership.
- *  The ASF licenses this file to You under the Apache License, Version 2.0
- *  (the "License"); you may not use this file except in compliance with
- *  the License.  You may obtain a copy of the License at
- *
- *     http://www.apache.org/licenses/LICENSE-2.0
- *
- *  Unless required by applicable law or agreed to in writing, software
- *  distributed under the License is distributed on an "AS IS" BASIS,
- *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- *  See the License for the specific language governing permissions and
- *  limitations under the License.
- */
-package org.apache.isis.core.progmodel.facets.collections.event;
-
-import static org.hamcrest.CoreMatchers.is;
-import static org.junit.Assert.assertThat;
-
-import java.util.Set;
-
-import org.junit.Test;
-import org.apache.isis.applib.Identifier;
-import org.apache.isis.applib.services.eventbus.CollectionRemovedFromEvent;
-
-public class PostsCollectionRemovedEventFacetAnnotationTest_newEvent {
-
-    public static class SomeDomainObject {
-        public Set<SomeReferencedObject> getReferences() { return null; }
-    }
-    public static class SomeReferencedObject {}
-    
-    public static class SomeDomainObjectCollectionRemovedFromEvent extends CollectionRemovedFromEvent<SomeDomainObject, SomeReferencedObject> {
-        private static final long serialVersionUID = 1L;
-    }
-    
-    @Test
-    public void test() throws Exception {
-        SomeDomainObject sdo = new SomeDomainObject();
-        SomeReferencedObject other = new SomeReferencedObject();
-        Identifier identifier = Identifier.propertyOrCollectionIdentifier(SomeDomainObject.class, "references");
-
-        final CollectionRemovedFromEvent<SomeDomainObject, SomeReferencedObject> ev = PostsCollectionRemovedFromEventFacetAnnotation.newEvent(
-                SomeDomainObjectCollectionRemovedFromEvent.class, sdo, identifier, other);
-        assertThat(ev.getSource(), is(sdo));
-        assertThat(ev.getIdentifier(), is(identifier));
-        assertThat(ev.getValue(), is(other));
-    }
-
-}

http://git-wip-us.apache.org/repos/asf/isis/blob/e1f19baa/core/metamodel/src/test/java/org/apache/isis/core/progmodel/facets/properties/event/PostsPropertyChangedEventFacetAnnotationTest_newEvent.java
----------------------------------------------------------------------
diff --git a/core/metamodel/src/test/java/org/apache/isis/core/progmodel/facets/properties/event/PostsPropertyChangedEventFacetAnnotationTest_newEvent.java b/core/metamodel/src/test/java/org/apache/isis/core/progmodel/facets/properties/event/PostsPropertyChangedEventFacetAnnotationTest_newEvent.java
deleted file mode 100644
index 4e4391d..0000000
--- a/core/metamodel/src/test/java/org/apache/isis/core/progmodel/facets/properties/event/PostsPropertyChangedEventFacetAnnotationTest_newEvent.java
+++ /dev/null
@@ -1,52 +0,0 @@
-/**
- *  Licensed to the Apache Software Foundation (ASF) under one or more
- *  contributor license agreements.  See the NOTICE file distributed with
- *  this work for additional information regarding copyright ownership.
- *  The ASF licenses this file to You under the Apache License, Version 2.0
- *  (the "License"); you may not use this file except in compliance with
- *  the License.  You may obtain a copy of the License at
- *
- *     http://www.apache.org/licenses/LICENSE-2.0
- *
- *  Unless required by applicable law or agreed to in writing, software
- *  distributed under the License is distributed on an "AS IS" BASIS,
- *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- *  See the License for the specific language governing permissions and
- *  limitations under the License.
- */
-package org.apache.isis.core.progmodel.facets.properties.event;
-
-import static org.hamcrest.CoreMatchers.is;
-import static org.junit.Assert.assertThat;
-
-import org.joda.time.LocalDate;
-import org.junit.Test;
-
-import org.apache.isis.applib.Identifier;
-import org.apache.isis.applib.services.eventbus.PropertyChangedEvent;
-
-public class PostsPropertyChangedEventFacetAnnotationTest_newEvent {
-
-    public static class SomeDomainObject {}
-    
-    public static class SomeDatePropertyChangedEvent extends PropertyChangedEvent<SomeDomainObject, LocalDate> {
-        private static final long serialVersionUID = 1L;
-    }
-    
-    @Test
-    public void test() throws Exception {
-
-        SomeDomainObject sdo = new SomeDomainObject();
-        Identifier identifier = Identifier.propertyOrCollectionIdentifier(SomeDomainObject.class, "someDateProperty");
-        LocalDate oldValue = new LocalDate(2013,4,1);
-        LocalDate newValue = new LocalDate(2013,5,2);
-        
-        final PropertyChangedEvent<SomeDomainObject, LocalDate> ev = 
-                PostsPropertyChangedEventFacetAnnotation.newEvent(SomeDatePropertyChangedEvent.class, sdo, identifier, oldValue, newValue);
-        assertThat(ev.getSource(), is(sdo));
-        assertThat(ev.getIdentifier(), is(identifier));
-        assertThat(ev.getOldValue(), is(oldValue));
-        assertThat(ev.getNewValue(), is(newValue));
-    }
-
-}

http://git-wip-us.apache.org/repos/asf/isis/blob/e1f19baa/example/application/quickstart_wicket_restful_jdo/dom/src/main/java/dom/todo/ToDoItem.java
----------------------------------------------------------------------
diff --git a/example/application/quickstart_wicket_restful_jdo/dom/src/main/java/dom/todo/ToDoItem.java b/example/application/quickstart_wicket_restful_jdo/dom/src/main/java/dom/todo/ToDoItem.java
index 2dae290..9d1f01c 100644
--- a/example/application/quickstart_wicket_restful_jdo/dom/src/main/java/dom/todo/ToDoItem.java
+++ b/example/application/quickstart_wicket_restful_jdo/dom/src/main/java/dom/todo/ToDoItem.java
@@ -34,6 +34,7 @@ import com.google.common.collect.Ordering;
 import org.joda.time.LocalDate;
 
 import org.apache.isis.applib.DomainObjectContainer;
+import org.apache.isis.applib.Identifier;
 import org.apache.isis.applib.NonRecoverableException;
 import org.apache.isis.applib.RecoverableException;
 import org.apache.isis.applib.annotation.*;
@@ -45,6 +46,7 @@ import org.apache.isis.applib.clock.Clock;
 import org.apache.isis.applib.services.background.BackgroundService;
 import org.apache.isis.applib.services.clock.ClockService;
 import org.apache.isis.applib.services.command.CommandContext;
+import org.apache.isis.applib.services.eventbus.ActionInvokedEvent;
 import org.apache.isis.applib.services.eventbus.CollectionAddedToEvent;
 import org.apache.isis.applib.services.eventbus.EventBusService;
 import org.apache.isis.applib.services.eventbus.PropertyChangedEvent;
@@ -141,6 +143,7 @@ public class ToDoItem implements Comparable<ToDoItem> {
     private String description;
 
     @javax.jdo.annotations.Column(allowsNull="false", length=100)
+    @PostsPropertyChangedEvent()
     @RegEx(validation = "\\w[@&:\\-\\,\\.\\+ \\w]*") 
     @TypicalLength(50)
     public String getDescription() {
@@ -299,6 +302,7 @@ public class ToDoItem implements Comparable<ToDoItem> {
         this.complete = complete;
     }
 
+    @PostsActionInvokedEvent(CompletedEvent.class)
     @Command
     @PublishedAction
     @Bulk
@@ -317,8 +321,6 @@ public class ToDoItem implements Comparable<ToDoItem> {
                 + (bulkInteractionContext.isFirst() ? " (first)" : "")
                 + (bulkInteractionContext.isLast() ? " (last)" : ""));
 
-        eventBusService.post(new CompletedEvent(this));
-
         // if invoked as a regular action, return this object;
         // otherwise (if invoked as bulk), return null (so go back to the list)
         return bulkInteractionContext.getInvokedAs() == InvokedAs.REGULAR? this: null;
@@ -328,14 +330,13 @@ public class ToDoItem implements Comparable<ToDoItem> {
         return isComplete() ? "Already completed" : null;
     }
 
+    @PostsActionInvokedEvent(NoLongerCompletedEvent.class)
     @Command
     @PublishedAction
     @Bulk
     public ToDoItem notYetCompleted() {
         setComplete(false);
 
-        eventBusService.post(new NoLongerCompletedEvent(this));
-
         // if invoked as a regular action, return this object;
         // otherwise (if invoked as bulk), return null (so go back to the list)
         return bulkInteractionContext.getInvokedAs() == InvokedAs.REGULAR? this: null;
@@ -418,7 +419,6 @@ public class ToDoItem implements Comparable<ToDoItem> {
     private String notes;
 
     @javax.jdo.annotations.Column(allowsNull="true", length=400)
-    @PostsPropertyChangedEvent()
     public String getNotes() {
         return notes;
     }
@@ -614,6 +614,7 @@ public class ToDoItem implements Comparable<ToDoItem> {
     //region > delete (action)
     // //////////////////////////////////////
 
+    @PostsActionInvokedEvent(DeletedEvent.class)
     @Bulk
     public List<ToDoItem> delete() {
         
@@ -621,8 +622,6 @@ public class ToDoItem implements Comparable<ToDoItem> {
 
         container.informUser("Deleted " + container.titleOf(this));
         
-        eventBusService.post(new DeletedEvent(this));
-        
         // invalid to return 'this' (cannot render a deleted object)
         return toDoItems.notYetComplete(); 
     }
@@ -730,9 +729,9 @@ public class ToDoItem implements Comparable<ToDoItem> {
         }
         return null;
     }
+    //endregion
 
-    // //////////////////////////////////////
-    // Programmatic Helpers
+    //region > programmatic helpers
     // //////////////////////////////////////
 
     private static final long ONE_WEEK_IN_MILLIS = 7 * 24 * 60 * 60 * 1000L;
@@ -753,41 +752,50 @@ public class ToDoItem implements Comparable<ToDoItem> {
 
     //region > events
     // //////////////////////////////////////
-    // Events
-    // //////////////////////////////////////
-
 
-    public static abstract class AbstractEvent {
-        private final String eventDescription;
-        private final ToDoItem toDoItem;
-        public AbstractEvent(String eventDescription, ToDoItem toDoItem) {
-            this.eventDescription = eventDescription;
-            this.toDoItem = toDoItem;
+    public static abstract class AbstractActionInvokedEvent extends ActionInvokedEvent<ToDoItem> {
+        private static final long serialVersionUID = 1L;
+        private final String description;
+        public AbstractActionInvokedEvent(
+                final String description, 
+                final ToDoItem source, 
+                final Identifier identifier, 
+                final Object... arguments) {
+            super(source, identifier, arguments);
+            this.description = description;
         }
         public String getEventDescription() {
-            return eventDescription;
-        }
-        public ToDoItem getToDoItem() {
-            return toDoItem;
+            return description;
         }
     }
 
-    public static class CompletedEvent extends AbstractEvent {
-
-        public CompletedEvent(ToDoItem toDoItem) {
-            super("completed", toDoItem);
+    public static class CompletedEvent extends AbstractActionInvokedEvent {
+        private static final long serialVersionUID = 1L;
+        public CompletedEvent(
+                final ToDoItem source, 
+                final Identifier identifier, 
+                final Object... arguments) {
+            super("completed", source, identifier, arguments);
         }
     }
 
-    public static class NoLongerCompletedEvent extends AbstractEvent {
-        public NoLongerCompletedEvent(ToDoItem toDoItem) {
-            super("no longer completed", toDoItem);
+    public static class NoLongerCompletedEvent extends AbstractActionInvokedEvent {
+        private static final long serialVersionUID = 1L;
+        public NoLongerCompletedEvent(
+                final ToDoItem source, 
+                final Identifier identifier, 
+                final Object... arguments) {
+            super("no longer completed", source, identifier, arguments);
         }
     }
 
-    public static class DeletedEvent extends AbstractEvent {
-        public DeletedEvent(ToDoItem toDoItem) {
-            super("deleted", toDoItem);
+    public static class DeletedEvent extends AbstractActionInvokedEvent {
+        private static final long serialVersionUID = 1L;
+        public DeletedEvent(
+                final ToDoItem source, 
+                final Identifier identifier, 
+                final Object... arguments) {
+            super("deleted", source, identifier, arguments);
         }
     }
     //endregion

http://git-wip-us.apache.org/repos/asf/isis/blob/e1f19baa/example/application/quickstart_wicket_restful_jdo/dom/src/main/java/dom/todo/ToDoItemSubscriptions.java
----------------------------------------------------------------------
diff --git a/example/application/quickstart_wicket_restful_jdo/dom/src/main/java/dom/todo/ToDoItemSubscriptions.java b/example/application/quickstart_wicket_restful_jdo/dom/src/main/java/dom/todo/ToDoItemSubscriptions.java
index 15623bb..ed5320f 100644
--- a/example/application/quickstart_wicket_restful_jdo/dom/src/main/java/dom/todo/ToDoItemSubscriptions.java
+++ b/example/application/quickstart_wicket_restful_jdo/dom/src/main/java/dom/todo/ToDoItemSubscriptions.java
@@ -18,6 +18,10 @@
  */
 package dom.todo;
 
+import java.util.EventObject;
+import java.util.List;
+
+import com.google.common.collect.Lists;
 import com.google.common.eventbus.Subscribe;
 
 import org.apache.isis.applib.DomainObjectContainer;
@@ -33,30 +37,80 @@ public class ToDoItemSubscriptions {
     private final static org.slf4j.Logger LOG = org.slf4j.LoggerFactory.getLogger(ToDoItemSubscriptions.class);
     //endregion
 
+    
+    //region > on(Event)...
+    // //////////////////////////////////////
+
     @Programmatic
     @Subscribe
-    public void on(ToDoItem.AbstractEvent ev) {
-        LOG.info(ev.getEventDescription() + ": " + container.titleOf(ev.getToDoItem()));
+    public void on(ToDoItem.AbstractActionInvokedEvent ev) {
+        recordEvent(ev);
+        LOG.info(ev.getEventDescription() + ": " + container.titleOf(ev.getSource()));
     }
 
     @Programmatic
     @Subscribe
     public void on(PropertyChangedEvent<?,?> ev) {
+        recordEvent(ev);
         LOG.info(container.titleOf(ev.getSource()) + ", changed " + ev.getIdentifier().getMemberName() + " : " + ev.getOldValue() + " -> " + ev.getNewValue());
     }
     
     @Programmatic
     @Subscribe
     public void on(CollectionAddedToEvent<?,?> ev) {
+        recordEvent(ev);
         LOG.info(container.titleOf(ev.getSource()) + ", added to " + ev.getIdentifier().getMemberName() + " : " + ev.getValue());
     }
     
     @Programmatic
     @Subscribe
     public void on(CollectionRemovedFromEvent<?,?> ev) {
+        recordEvent(ev);
         LOG.info(container.titleOf(ev.getSource()) + ", removed from " + ev.getIdentifier().getMemberName() + " : " + ev.getValue());
     }
+
+    //endregion
+
+    //region > receivedEvents
+    // //////////////////////////////////////
     
+    private final List<java.util.EventObject> receivedEvents = Lists.newLinkedList();
+
+    /**
+     * Used in integration tests.
+     */
+    @Programmatic
+    public List<java.util.EventObject> receivedEvents() {
+        return receivedEvents;
+    }
+    /**
+     * Used in integration tests.
+     */
+    @Programmatic
+    public <T extends java.util.EventObject> T mostRecentlyReceivedEvent(Class<T> expectedType) {
+        if (receivedEvents.isEmpty()) {
+            return null;
+        } 
+        final EventObject ev = receivedEvents.get(0);
+        if(!expectedType.isAssignableFrom(ev.getClass())) {
+            return null;
+        } 
+        return expectedType.cast(ev);
+    }
+    private void recordEvent(final java.util.EventObject ev) {
+        receivedEvents.add(0, ev);
+    }
+    /**
+     * Used in integration tests.
+     */
+    @Programmatic
+    public void reset() {
+        receivedEvents.clear();
+    }
+
+    //endregion
+
+
     //region > injected services
     // //////////////////////////////////////
     
@@ -70,4 +124,5 @@ public class ToDoItemSubscriptions {
     }
     //endregion
 
+
 }

http://git-wip-us.apache.org/repos/asf/isis/blob/e1f19baa/example/application/quickstart_wicket_restful_jdo/integtests/src/test/java/integration/ToDoSystemInitializer.java
----------------------------------------------------------------------
diff --git a/example/application/quickstart_wicket_restful_jdo/integtests/src/test/java/integration/ToDoSystemInitializer.java b/example/application/quickstart_wicket_restful_jdo/integtests/src/test/java/integration/ToDoSystemInitializer.java
index 7fbd36c..d936646 100644
--- a/example/application/quickstart_wicket_restful_jdo/integtests/src/test/java/integration/ToDoSystemInitializer.java
+++ b/example/application/quickstart_wicket_restful_jdo/integtests/src/test/java/integration/ToDoSystemInitializer.java
@@ -18,6 +18,7 @@ package integration;
 
 import app.ToDoItemAnalysis;
 import dom.todo.ToDoItemContributions;
+import dom.todo.ToDoItemSubscriptions;
 import dom.todo.ToDoItems;
 import fixture.todo.ToDoItemsFixturesService;
 
@@ -65,6 +66,7 @@ public class ToDoSystemInitializer {
                     new ToDoItemContributions(),
                     new ToDoItemsFixturesService(),
                     new ClassDiscoveryServiceUsingReflections(),
+                    new ToDoItemSubscriptions(),
                     new WrapperFactoryDefault(),
                     new IsisJdoSupportImpl(),
                     new Bulk.InteractionContext(),

http://git-wip-us.apache.org/repos/asf/isis/blob/e1f19baa/example/application/quickstart_wicket_restful_jdo/integtests/src/test/java/integration/tests/ToDoIntegTest.java
----------------------------------------------------------------------
diff --git a/example/application/quickstart_wicket_restful_jdo/integtests/src/test/java/integration/tests/ToDoIntegTest.java b/example/application/quickstart_wicket_restful_jdo/integtests/src/test/java/integration/tests/ToDoIntegTest.java
index 5770a29..cc7f5d8 100644
--- a/example/application/quickstart_wicket_restful_jdo/integtests/src/test/java/integration/tests/ToDoIntegTest.java
+++ b/example/application/quickstart_wicket_restful_jdo/integtests/src/test/java/integration/tests/ToDoIntegTest.java
@@ -23,18 +23,20 @@ import integration.ToDoSystemInitializer;
 import org.junit.BeforeClass;
 
 import org.apache.isis.core.integtestsupport.IntegrationTestAbstract;
+import org.apache.isis.core.integtestsupport.IsisSystemForTest;
 import org.apache.isis.core.integtestsupport.scenarios.ScenarioExecutionForIntegration;
 
 public abstract class ToDoIntegTest extends IntegrationTestAbstract {
-
+    
+    private static IsisSystemForTest isft;
     
     @BeforeClass
     public static void initClass() {
         org.apache.log4j.PropertyConfigurator.configure("logging.properties");
-        ToDoSystemInitializer.initIsft();
+        isft = ToDoSystemInitializer.initIsft();
         
         // instantiating will install onto ThreadLocal
         new ScenarioExecutionForIntegration();
     }
-
+    
 }

http://git-wip-us.apache.org/repos/asf/isis/blob/e1f19baa/example/application/quickstart_wicket_restful_jdo/integtests/src/test/java/integration/tests/actions/ToDoItemTest_completed.java
----------------------------------------------------------------------
diff --git a/example/application/quickstart_wicket_restful_jdo/integtests/src/test/java/integration/tests/actions/ToDoItemTest_completed.java b/example/application/quickstart_wicket_restful_jdo/integtests/src/test/java/integration/tests/actions/ToDoItemTest_completed.java
index 71a4042..d907776 100644
--- a/example/application/quickstart_wicket_restful_jdo/integtests/src/test/java/integration/tests/actions/ToDoItemTest_completed.java
+++ b/example/application/quickstart_wicket_restful_jdo/integtests/src/test/java/integration/tests/actions/ToDoItemTest_completed.java
@@ -18,22 +18,26 @@
  */
 package integration.tests.actions;
 
-import static org.hamcrest.CoreMatchers.is;
+import static org.hamcrest.CoreMatchers.*;
 import static org.junit.Assert.assertThat;
 import integration.tests.ToDoIntegTest;
 
+import java.util.EventObject;
 import java.util.List;
 
 import dom.todo.ToDoItem;
+import dom.todo.ToDoItemSubscriptions;
 import dom.todo.ToDoItems;
 import fixture.todo.ToDoItemsFixture;
 
+import org.junit.After;
 import org.junit.Before;
 import org.junit.Test;
 
 public class ToDoItemTest_completed extends ToDoIntegTest {
 
     private ToDoItem toDoItem;
+    private ToDoItemSubscriptions toDoItemSubscriptions;
 
     @Before
     public void setUp() throws Exception {
@@ -41,9 +45,16 @@ public class ToDoItemTest_completed extends ToDoIntegTest {
 
         final List<ToDoItem> all = wrap(service(ToDoItems.class)).notYetComplete();
         toDoItem = wrap(all.get(0));
+        
+        toDoItemSubscriptions = service(ToDoItemSubscriptions.class);
     }
 
+    @After
+    public void tearDown() throws Exception {
+        toDoItemSubscriptions.reset();
+    }
 
+    
     @Test
     public void happyCase() throws Exception {
         
@@ -55,9 +66,16 @@ public class ToDoItemTest_completed extends ToDoIntegTest {
         
         // then
         assertThat(toDoItem.isComplete(), is(true));
+        
+        // and then
+        final ToDoItem.CompletedEvent ev = toDoItemSubscriptions.mostRecentlyReceivedEvent(ToDoItem.CompletedEvent.class);
+        assertThat(ev, is(not(nullValue()))); 
+        
+        ToDoItem source = ev.getSource();
+        assertThat(source, is(equalTo(unwrap(toDoItem))));
+        assertThat(ev.getIdentifier().getMemberName(), is("completed"));
     }
 
-
     @Test
     public void cannotCompleteIfAlreadyCompleted() throws Exception {
         
@@ -67,6 +85,10 @@ public class ToDoItemTest_completed extends ToDoIntegTest {
         // when, then should fail
         expectedExceptions.expectMessage("Already completed");
         toDoItem.completed();
+
+        // and then
+        final EventObject ev = toDoItemSubscriptions.mostRecentlyReceivedEvent(EventObject.class);
+        assertThat(ev, is(nullValue())); 
     }
 
 
@@ -78,6 +100,10 @@ public class ToDoItemTest_completed extends ToDoIntegTest {
         // when, then should fail
         expectedExceptions.expectMessage("Always disabled");
         toDoItem.setComplete(true);
+
+        // and then
+        final EventObject ev = toDoItemSubscriptions.mostRecentlyReceivedEvent(EventObject.class);
+        assertThat(ev, is(nullValue())); 
     }
 
 }
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/isis/blob/e1f19baa/example/application/quickstart_wicket_restful_jdo/integtests/src/test/java/integration/tests/colls/ToDoItemTest_dependencies_add.java
----------------------------------------------------------------------
diff --git a/example/application/quickstart_wicket_restful_jdo/integtests/src/test/java/integration/tests/colls/ToDoItemTest_dependencies_add.java b/example/application/quickstart_wicket_restful_jdo/integtests/src/test/java/integration/tests/colls/ToDoItemTest_dependencies_add.java
index d71e134..813fd92 100644
--- a/example/application/quickstart_wicket_restful_jdo/integtests/src/test/java/integration/tests/colls/ToDoItemTest_dependencies_add.java
+++ b/example/application/quickstart_wicket_restful_jdo/integtests/src/test/java/integration/tests/colls/ToDoItemTest_dependencies_add.java
@@ -18,13 +18,17 @@
  */
 package integration.tests.colls;
 
+import static org.hamcrest.CoreMatchers.equalTo;
 import static org.hamcrest.CoreMatchers.is;
+import static org.hamcrest.CoreMatchers.not;
+import static org.hamcrest.CoreMatchers.nullValue;
 import static org.junit.Assert.assertThat;
 import integration.tests.ToDoIntegTest;
 
 import java.util.List;
 
 import dom.todo.ToDoItem;
+import dom.todo.ToDoItemSubscriptions;
 import dom.todo.ToDoItems;
 import fixture.todo.ToDoItemsFixture;
 
@@ -32,11 +36,16 @@ import org.junit.After;
 import org.junit.Before;
 import org.junit.Test;
 
+import org.apache.isis.applib.services.eventbus.CollectionAddedToEvent;
+import org.apache.isis.applib.services.eventbus.CollectionRemovedFromEvent;
+
 public class ToDoItemTest_dependencies_add extends ToDoIntegTest {
 
     private ToDoItem toDoItem;
     private ToDoItem otherToDoItem;
     
+    private ToDoItemSubscriptions toDoItemSubscriptions;
+    
 
     @Before
     public void setUp() throws Exception {
@@ -44,12 +53,15 @@ public class ToDoItemTest_dependencies_add extends ToDoIntegTest {
 
         final List<ToDoItem> items = wrap(service(ToDoItems.class)).notYetComplete();
         toDoItem = wrap(items.get(0));
-        otherToDoItem = items.get(1); // wrapping this seems to trip up cglib :-(
+        otherToDoItem = wrap(items.get(1));
+        
+        toDoItemSubscriptions = service(ToDoItemSubscriptions.class);
     }
 
     @After
     public void tearDown() throws Exception {
         unwrap(toDoItem).getDependencies().clear();
+        toDoItemSubscriptions.reset();
     }
 
     @Test
@@ -64,6 +76,16 @@ public class ToDoItemTest_dependencies_add extends ToDoIntegTest {
         // then
         assertThat(toDoItem.getDependencies().size(), is(1));
         assertThat(toDoItem.getDependencies().first(), is(unwrap(otherToDoItem)));
+        
+        // and then
+        @SuppressWarnings("unchecked")
+        final CollectionAddedToEvent<ToDoItem,ToDoItem> ev = toDoItemSubscriptions.mostRecentlyReceivedEvent(CollectionAddedToEvent.class);
+        assertThat(ev, is(not(nullValue()))); 
+        
+        ToDoItem source = ev.getSource();
+        assertThat(source, is(equalTo(unwrap(toDoItem))));
+        assertThat(ev.getIdentifier().getMemberName(), is("dependencies"));
+        assertThat(ev.getValue(), is(unwrap(otherToDoItem)));
     }
 
 

http://git-wip-us.apache.org/repos/asf/isis/blob/e1f19baa/example/application/quickstart_wicket_restful_jdo/integtests/src/test/java/integration/tests/colls/ToDoItemTest_dependencies_remove.java
----------------------------------------------------------------------
diff --git a/example/application/quickstart_wicket_restful_jdo/integtests/src/test/java/integration/tests/colls/ToDoItemTest_dependencies_remove.java b/example/application/quickstart_wicket_restful_jdo/integtests/src/test/java/integration/tests/colls/ToDoItemTest_dependencies_remove.java
index d566c1a..29fe5f8 100644
--- a/example/application/quickstart_wicket_restful_jdo/integtests/src/test/java/integration/tests/colls/ToDoItemTest_dependencies_remove.java
+++ b/example/application/quickstart_wicket_restful_jdo/integtests/src/test/java/integration/tests/colls/ToDoItemTest_dependencies_remove.java
@@ -18,13 +18,17 @@
  */
 package integration.tests.colls;
 
+import static org.hamcrest.CoreMatchers.equalTo;
 import static org.hamcrest.CoreMatchers.is;
+import static org.hamcrest.CoreMatchers.not;
+import static org.hamcrest.CoreMatchers.nullValue;
 import static org.junit.Assert.assertThat;
 import integration.tests.ToDoIntegTest;
 
 import java.util.List;
 
 import dom.todo.ToDoItem;
+import dom.todo.ToDoItemSubscriptions;
 import dom.todo.ToDoItems;
 import fixture.todo.ToDoItemsFixture;
 
@@ -32,12 +36,15 @@ import org.junit.After;
 import org.junit.Before;
 import org.junit.Test;
 
+import org.apache.isis.applib.services.eventbus.CollectionRemovedFromEvent;
+
 public class ToDoItemTest_dependencies_remove extends ToDoIntegTest {
 
     private ToDoItem toDoItem;
     private ToDoItem otherToDoItem;
     private ToDoItem yetAnotherToDoItem;
-    
+
+    private ToDoItemSubscriptions toDoItemSubscriptions;
 
     @Before
     public void setUp() throws Exception {
@@ -46,15 +53,17 @@ public class ToDoItemTest_dependencies_remove extends ToDoIntegTest {
 
         final List<ToDoItem> items = wrap(service(ToDoItems.class)).notYetComplete();
         toDoItem = wrap(items.get(0));
-        otherToDoItem = items.get(1); // wrapping this seems to trip up cglib :-(
-        yetAnotherToDoItem = items.get(2); // wrapping this seems to trip up cglib :-(
+        otherToDoItem = wrap(items.get(1));
+        yetAnotherToDoItem = wrap(items.get(2));
         
         toDoItem.add(otherToDoItem);
+        toDoItemSubscriptions = service(ToDoItemSubscriptions.class);
     }
 
     @After
     public void tearDown() throws Exception {
         unwrap(toDoItem).getDependencies().clear();
+        toDoItemSubscriptions.reset();
     }
 
     @Test
@@ -68,11 +77,21 @@ public class ToDoItemTest_dependencies_remove extends ToDoIntegTest {
         
         // then
         assertThat(toDoItem.getDependencies().size(), is(0));
+        
+        // and then
+        @SuppressWarnings("unchecked")
+        final CollectionRemovedFromEvent<ToDoItem,ToDoItem> ev = toDoItemSubscriptions.mostRecentlyReceivedEvent(CollectionRemovedFromEvent.class);
+        assertThat(ev, is(not(nullValue()))); 
+        
+        ToDoItem source = ev.getSource();
+        assertThat(source, is(equalTo(unwrap(toDoItem))));
+        assertThat(ev.getIdentifier().getMemberName(), is("dependencies"));
+        assertThat(ev.getValue(), is(unwrap(otherToDoItem)));
     }
 
 
     @Test
-    public void cannotRemoveItemIfNotADepedndency() throws Exception {
+    public void cannotRemoveItemIfNotADependency() throws Exception {
 
         // when, then
         expectedExceptions.expectMessage("Not a dependency");

http://git-wip-us.apache.org/repos/asf/isis/blob/e1f19baa/example/application/quickstart_wicket_restful_jdo/integtests/src/test/java/integration/tests/props/ToDoItemTest_description.java
----------------------------------------------------------------------
diff --git a/example/application/quickstart_wicket_restful_jdo/integtests/src/test/java/integration/tests/props/ToDoItemTest_description.java b/example/application/quickstart_wicket_restful_jdo/integtests/src/test/java/integration/tests/props/ToDoItemTest_description.java
index 11e5ae3..df85deb 100644
--- a/example/application/quickstart_wicket_restful_jdo/integtests/src/test/java/integration/tests/props/ToDoItemTest_description.java
+++ b/example/application/quickstart_wicket_restful_jdo/integtests/src/test/java/integration/tests/props/ToDoItemTest_description.java
@@ -18,22 +18,30 @@
  */
 package integration.tests.props;
 
+import static org.hamcrest.CoreMatchers.equalTo;
 import static org.hamcrest.CoreMatchers.is;
+import static org.hamcrest.CoreMatchers.not;
+import static org.hamcrest.CoreMatchers.nullValue;
 import static org.junit.Assert.assertThat;
 import integration.tests.ToDoIntegTest;
 
 import java.util.List;
 
 import dom.todo.ToDoItem;
+import dom.todo.ToDoItemSubscriptions;
 import dom.todo.ToDoItems;
 import fixture.todo.ToDoItemsFixture;
 
+import org.junit.After;
 import org.junit.Before;
 import org.junit.Test;
 
+import org.apache.isis.applib.services.eventbus.PropertyChangedEvent;
+
 public class ToDoItemTest_description extends ToDoIntegTest {
 
     private ToDoItem toDoItem;
+    private ToDoItemSubscriptions toDoItemSubscriptions;
 
     @Before
     public void setUp() throws Exception {
@@ -41,6 +49,12 @@ public class ToDoItemTest_description extends ToDoIntegTest {
 
         final List<ToDoItem> all = wrap(service(ToDoItems.class)).notYetComplete();
         toDoItem = wrap(all.get(0));
+        toDoItemSubscriptions = service(ToDoItemSubscriptions.class);
+    }
+
+    @After
+    public void tearDown() throws Exception {
+        toDoItemSubscriptions.reset();
     }
 
     @Test
@@ -54,6 +68,17 @@ public class ToDoItemTest_description extends ToDoIntegTest {
         
         // then
         assertThat(toDoItem.getDescription(), is("Buy bread and butter"));
+
+        // and then published and received
+        @SuppressWarnings("unchecked")
+        final PropertyChangedEvent<ToDoItem,String> ev = toDoItemSubscriptions.mostRecentlyReceivedEvent(PropertyChangedEvent.class);
+        assertThat(ev, is(not(nullValue()))); 
+        
+        ToDoItem source = ev.getSource();
+        assertThat(source, is(equalTo(unwrap(toDoItem))));
+        assertThat(ev.getIdentifier().getMemberName(), is("description"));
+        assertThat(ev.getOldValue(), is("Buy bread"));
+        assertThat(ev.getNewValue(), is("Buy bread and butter"));
     }
 
 

http://git-wip-us.apache.org/repos/asf/isis/blob/e1f19baa/example/application/quickstart_wicket_restful_jdo/integtests/src/test/java/integration/tests/props/ToDoItemTest_notes.java
----------------------------------------------------------------------
diff --git a/example/application/quickstart_wicket_restful_jdo/integtests/src/test/java/integration/tests/props/ToDoItemTest_notes.java b/example/application/quickstart_wicket_restful_jdo/integtests/src/test/java/integration/tests/props/ToDoItemTest_notes.java
index 9c6d96b..3ad42aa 100644
--- a/example/application/quickstart_wicket_restful_jdo/integtests/src/test/java/integration/tests/props/ToDoItemTest_notes.java
+++ b/example/application/quickstart_wicket_restful_jdo/integtests/src/test/java/integration/tests/props/ToDoItemTest_notes.java
@@ -18,22 +18,31 @@
  */
 package integration.tests.props;
 
+import static org.hamcrest.CoreMatchers.equalTo;
 import static org.hamcrest.CoreMatchers.is;
+import static org.hamcrest.CoreMatchers.not;
+import static org.hamcrest.CoreMatchers.nullValue;
 import static org.junit.Assert.assertThat;
 import integration.tests.ToDoIntegTest;
 
 import java.util.List;
 
 import dom.todo.ToDoItem;
+import dom.todo.ToDoItemSubscriptions;
 import dom.todo.ToDoItems;
 import fixture.todo.ToDoItemsFixture;
 
+import org.junit.After;
 import org.junit.Before;
 import org.junit.Test;
 
+import org.apache.isis.applib.services.eventbus.CollectionRemovedFromEvent;
+import org.apache.isis.applib.services.eventbus.PropertyChangedEvent;
+
 public class ToDoItemTest_notes extends ToDoIntegTest {
 
     private ToDoItem toDoItem;
+    private ToDoItemSubscriptions toDoItemSubscriptions;
 
     @Before
     public void setUp() throws Exception {
@@ -42,6 +51,12 @@ public class ToDoItemTest_notes extends ToDoIntegTest {
 
         final List<ToDoItem> all = wrap(service(ToDoItems.class)).notYetComplete();
         toDoItem = wrap(all.get(0));
+        toDoItemSubscriptions = service(ToDoItemSubscriptions.class);
+    }
+
+    @After
+    public void tearDown() throws Exception {
+        toDoItemSubscriptions.reset();
     }
 
     @Test
@@ -54,6 +69,11 @@ public class ToDoItemTest_notes extends ToDoIntegTest {
         
         // then
         assertThat(toDoItem.getNotes(), is(newNotes));
+
+        // and then not published so not received
+        @SuppressWarnings("unchecked")
+        final PropertyChangedEvent<ToDoItem,String> ev = toDoItemSubscriptions.mostRecentlyReceivedEvent(PropertyChangedEvent.class);
+        assertThat(ev, is(nullValue())); 
     }
 
     @Test


[10/16] git commit: ISIS-550: removed WrapperPolicy, replaced with ExecutionMode#SKIP_RULES

Posted by da...@apache.org.
ISIS-550: removed WrapperPolicy, replaced with ExecutionMode#SKIP_RULES

In addition:
- all the events inherit from java.util.EventObject
- additional convenience methods wrapNoExecute(.) and wrapSkipRules(.) in WrapperFactory.


Project: http://git-wip-us.apache.org/repos/asf/isis/repo
Commit: http://git-wip-us.apache.org/repos/asf/isis/commit/c2b250f0
Tree: http://git-wip-us.apache.org/repos/asf/isis/tree/c2b250f0
Diff: http://git-wip-us.apache.org/repos/asf/isis/diff/c2b250f0

Branch: refs/heads/master
Commit: c2b250f01e0b6ace2a71ac1c25d90694d50fc65e
Parents: c1a2596
Author: Dan Haywood <da...@haywood-associates.co.uk>
Authored: Sat May 10 08:08:45 2014 +0100
Committer: Dan Haywood <da...@haywood-associates.co.uk>
Committed: Sat May 10 08:08:45 2014 +0100

----------------------------------------------------------------------
 .../annotation/PostsActionInvokedEvent.java     |  7 ---
 .../annotation/PostsCollectionAddedToEvent.java |  7 ---
 .../PostsCollectionRemovedFromEvent.java        |  7 ---
 .../annotation/PostsPropertyChangedEvent.java   |  7 ---
 .../isis/applib/annotation/WrapperPolicy.java   | 35 -----------
 .../services/eventbus/ActionInvokedEvent.java   | 22 ++++---
 .../eventbus/CollectionAddedToEvent.java        | 28 ++++-----
 .../eventbus/CollectionRemovedFromEvent.java    | 27 ++++-----
 .../services/eventbus/PropertyChangedEvent.java | 15 +++--
 .../applib/services/wrapper/WrapperFactory.java | 52 ++++++++++++++++-
 .../facets/PostsEventWithWrapperPolicy.java     | 61 --------------------
 .../event/PostsCollectionAddedToEventFacet.java |  3 +-
 ...ostsCollectionAddedToEventFacetAbstract.java | 13 +----
 .../PostsCollectionRemovedFromEventFacet.java   |  3 +-
 ...CollectionRemovedFromEventFacetAbstract.java | 13 +----
 .../event/PostsPropertyChangedEventFacet.java   |  3 +-
 .../PostsPropertyChangedEventFacetAbstract.java | 13 +----
 ...ctionAddedToEventAnnotationFacetFactory.java |  4 +-
 ...tsCollectionAddedToEventFacetAnnotation.java |  4 +-
 ...nRemovedFromEventAnnotationFacetFactory.java |  4 +-
 ...llectionRemovedFromEventFacetAnnotation.java |  4 +-
 ...pertyChangedEventAnnotationFacetFactory.java |  4 +-
 ...ostsPropertyChangedEventFacetAnnotation.java |  4 +-
 ...nAddedEventFacetAnnotationTest_newEvent.java |  4 +-
 ...emovedEventFacetAnnotationTest_newEvent.java |  4 +-
 ...hangedEventFacetAnnotationTest_newEvent.java |  4 +-
 .../core/wrapper/WrapperFactoryAbstract.java    | 10 ++++
 .../handlers/DomainObjectInvocationHandler.java | 53 ++++-------------
 .../dom/src/main/java/dom/todo/ToDoItem.java    | 13 +++--
 29 files changed, 159 insertions(+), 269 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/isis/blob/c2b250f0/core/applib/src/main/java/org/apache/isis/applib/annotation/PostsActionInvokedEvent.java
----------------------------------------------------------------------
diff --git a/core/applib/src/main/java/org/apache/isis/applib/annotation/PostsActionInvokedEvent.java b/core/applib/src/main/java/org/apache/isis/applib/annotation/PostsActionInvokedEvent.java
index 6b772e7..ba11074 100644
--- a/core/applib/src/main/java/org/apache/isis/applib/annotation/PostsActionInvokedEvent.java
+++ b/core/applib/src/main/java/org/apache/isis/applib/annotation/PostsActionInvokedEvent.java
@@ -26,7 +26,6 @@ import java.lang.annotation.Target;
 
 import org.apache.isis.applib.services.eventbus.ActionInvokedEvent;
 import org.apache.isis.applib.services.eventbus.PropertyChangedEvent;
-import org.apache.isis.applib.services.wrapper.WrapperFactory;
 
 /**
  * Applies only to actions; any changes should be propagated as events to subscribers.  
@@ -58,10 +57,4 @@ public @interface PostsActionInvokedEvent {
      */
     Class<? extends ActionInvokedEvent<?>> value() default ActionInvokedEvent.Default.class;
 
-    /**
-     * If invoked through the {@link WrapperFactory}, whether business rules (&quot;see it, use it, do it&quot;)
-     * should be enforced or not.
-     */
-    WrapperPolicy wrapperPolicy() default WrapperPolicy.ENFORCE_RULES;
-
 }

http://git-wip-us.apache.org/repos/asf/isis/blob/c2b250f0/core/applib/src/main/java/org/apache/isis/applib/annotation/PostsCollectionAddedToEvent.java
----------------------------------------------------------------------
diff --git a/core/applib/src/main/java/org/apache/isis/applib/annotation/PostsCollectionAddedToEvent.java b/core/applib/src/main/java/org/apache/isis/applib/annotation/PostsCollectionAddedToEvent.java
index 04037b8..d3a8f31 100644
--- a/core/applib/src/main/java/org/apache/isis/applib/annotation/PostsCollectionAddedToEvent.java
+++ b/core/applib/src/main/java/org/apache/isis/applib/annotation/PostsCollectionAddedToEvent.java
@@ -60,11 +60,4 @@ public @interface PostsCollectionAddedToEvent {
      * This subclass must provide a no-arg constructor; the fields are set reflectively.
      */
     Class<? extends CollectionAddedToEvent<?,?>> value() default CollectionAddedToEvent.Default.class;
-    
-    /**
-     * If invoked through the {@link WrapperFactory}, whether business rules (&quot;see it, use it, do it&quot;)
-     * should be enforced or not.
-     */
-    WrapperPolicy wrapperPolicy() default WrapperPolicy.ENFORCE_RULES;
-
 }

http://git-wip-us.apache.org/repos/asf/isis/blob/c2b250f0/core/applib/src/main/java/org/apache/isis/applib/annotation/PostsCollectionRemovedFromEvent.java
----------------------------------------------------------------------
diff --git a/core/applib/src/main/java/org/apache/isis/applib/annotation/PostsCollectionRemovedFromEvent.java b/core/applib/src/main/java/org/apache/isis/applib/annotation/PostsCollectionRemovedFromEvent.java
index f94851f..40b194f 100644
--- a/core/applib/src/main/java/org/apache/isis/applib/annotation/PostsCollectionRemovedFromEvent.java
+++ b/core/applib/src/main/java/org/apache/isis/applib/annotation/PostsCollectionRemovedFromEvent.java
@@ -25,7 +25,6 @@ import java.lang.annotation.RetentionPolicy;
 import java.lang.annotation.Target;
 
 import org.apache.isis.applib.services.eventbus.CollectionRemovedFromEvent;
-import org.apache.isis.applib.services.wrapper.WrapperFactory;
 
 /**
  * Applies only to collections; any changes should be propagated as events to subscribers.  
@@ -61,10 +60,4 @@ public @interface PostsCollectionRemovedFromEvent {
      */
     Class<? extends CollectionRemovedFromEvent<?,?>> value() default CollectionRemovedFromEvent.Default.class;
 
-    /**
-     * If invoked through the {@link WrapperFactory}, whether business rules (&quot;see it, use it, do it&quot;)
-     * should be enforced or not.
-     */
-    WrapperPolicy wrapperPolicy() default WrapperPolicy.ENFORCE_RULES;
-
 }

http://git-wip-us.apache.org/repos/asf/isis/blob/c2b250f0/core/applib/src/main/java/org/apache/isis/applib/annotation/PostsPropertyChangedEvent.java
----------------------------------------------------------------------
diff --git a/core/applib/src/main/java/org/apache/isis/applib/annotation/PostsPropertyChangedEvent.java b/core/applib/src/main/java/org/apache/isis/applib/annotation/PostsPropertyChangedEvent.java
index b55c961..81a6219 100644
--- a/core/applib/src/main/java/org/apache/isis/applib/annotation/PostsPropertyChangedEvent.java
+++ b/core/applib/src/main/java/org/apache/isis/applib/annotation/PostsPropertyChangedEvent.java
@@ -25,7 +25,6 @@ import java.lang.annotation.RetentionPolicy;
 import java.lang.annotation.Target;
 
 import org.apache.isis.applib.services.eventbus.PropertyChangedEvent;
-import org.apache.isis.applib.services.wrapper.WrapperFactory;
 
 /**
  * Applies only to properties; any changes should be propagated as events to subscribers.  
@@ -57,10 +56,4 @@ public @interface PostsPropertyChangedEvent {
      */
     Class<? extends PropertyChangedEvent<?,?>> value() default PropertyChangedEvent.Default.class;
 
-    /**
-     * If invoked through the {@link WrapperFactory}, whether business rules (&quot;see it, use it, do it&quot;)
-     * should be enforced or not.
-     */
-    WrapperPolicy wrapperPolicy() default WrapperPolicy.ENFORCE_RULES;
-
 }

http://git-wip-us.apache.org/repos/asf/isis/blob/c2b250f0/core/applib/src/main/java/org/apache/isis/applib/annotation/WrapperPolicy.java
----------------------------------------------------------------------
diff --git a/core/applib/src/main/java/org/apache/isis/applib/annotation/WrapperPolicy.java b/core/applib/src/main/java/org/apache/isis/applib/annotation/WrapperPolicy.java
deleted file mode 100644
index a69c817..0000000
--- a/core/applib/src/main/java/org/apache/isis/applib/annotation/WrapperPolicy.java
+++ /dev/null
@@ -1,35 +0,0 @@
-/*
- *  Licensed to the Apache Software Foundation (ASF) under one
- *  or more contributor license agreements.  See the NOTICE file
- *  distributed with this work for additional information
- *  regarding copyright ownership.  The ASF licenses this file
- *  to you under the Apache License, Version 2.0 (the
- *  "License"); you may not use this file except in compliance
- *  with the License.  You may obtain a copy of the License at
- *
- *        http://www.apache.org/licenses/LICENSE-2.0
- *
- *  Unless required by applicable law or agreed to in writing,
- *  software distributed under the License is distributed on an
- *  "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- *  KIND, either express or implied.  See the License for the
- *  specific language governing permissions and limitations
- *  under the License.
- */
-package org.apache.isis.applib.annotation;
-
-import org.apache.isis.applib.services.wrapper.WrapperFactory;
-
-/**
- * An attribute of {@link PostsPropertyChangedEvent}, {@link PostsCollectionAddedToEvent} and other related annotations;
- * is a hint to indicate that if the object member is interacted with through a {@link WrapperFactory}, then whether 
- * business rules (&quot;see it, use it, do it&quot;) should be enforced or not.
- * 
- * <p>
- * This provides a half-way house between strictly UI-interactions and fully programmatic interactions, so that an 
- * event can be fired programmatically even if the object is disabled in the UI.
- */
-public enum WrapperPolicy {
-    ENFORCE_RULES,
-    SKIP_RULES
-}
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/isis/blob/c2b250f0/core/applib/src/main/java/org/apache/isis/applib/services/eventbus/ActionInvokedEvent.java
----------------------------------------------------------------------
diff --git a/core/applib/src/main/java/org/apache/isis/applib/services/eventbus/ActionInvokedEvent.java b/core/applib/src/main/java/org/apache/isis/applib/services/eventbus/ActionInvokedEvent.java
index 2140525..7dabf9b 100644
--- a/core/applib/src/main/java/org/apache/isis/applib/services/eventbus/ActionInvokedEvent.java
+++ b/core/applib/src/main/java/org/apache/isis/applib/services/eventbus/ActionInvokedEvent.java
@@ -18,14 +18,17 @@
  */
 package org.apache.isis.applib.services.eventbus;
 
-import org.apache.isis.applib.annotation.PostsPropertyChangedEvent;
+import org.apache.isis.applib.annotation.PostsActionInvokedEvent;
 import org.apache.isis.applib.util.ObjectContracts;
 
-public abstract class ActionInvokedEvent<S> {
+public abstract class ActionInvokedEvent<S> extends java.util.EventObject {
     
-    public static class Default extends ActionInvokedEvent<Object> {}
+    private static final long serialVersionUID = 1L;
+
+    public static class Default extends ActionInvokedEvent<Object> {
+        private static final long serialVersionUID = 1L;
+    }
 
-    private final S source;
     private final String action;
     private final String parameters;
     
@@ -40,14 +43,19 @@ public abstract class ActionInvokedEvent<S> {
         this(null, null, null);
     }
     
-    public ActionInvokedEvent(S source, String action, String parameters) {
-        this.source = source;
+    public ActionInvokedEvent(
+            final S source, 
+            final String action, 
+            final String parameters) {
+        super(source);
         this.action = action;
         this.parameters = parameters;
     }
     
+    @Override
+    @SuppressWarnings("unchecked")
     public S getSource() {
-        return source;
+        return (S)source;
     }
     public String getAction() {
         return action;

http://git-wip-us.apache.org/repos/asf/isis/blob/c2b250f0/core/applib/src/main/java/org/apache/isis/applib/services/eventbus/CollectionAddedToEvent.java
----------------------------------------------------------------------
diff --git a/core/applib/src/main/java/org/apache/isis/applib/services/eventbus/CollectionAddedToEvent.java b/core/applib/src/main/java/org/apache/isis/applib/services/eventbus/CollectionAddedToEvent.java
index 7b2d8f1..2b4302d 100644
--- a/core/applib/src/main/java/org/apache/isis/applib/services/eventbus/CollectionAddedToEvent.java
+++ b/core/applib/src/main/java/org/apache/isis/applib/services/eventbus/CollectionAddedToEvent.java
@@ -22,11 +22,14 @@ import org.apache.isis.applib.Identifier;
 import org.apache.isis.applib.annotation.PostsPropertyChangedEvent;
 import org.apache.isis.applib.util.ObjectContracts;
 
-public abstract class CollectionAddedToEvent<S,T> {
+public abstract class CollectionAddedToEvent<S,T> extends java.util.EventObject {
     
-    public static class Default extends CollectionAddedToEvent<Object, Object> {}
+    private static final long serialVersionUID = 1L;
+
+    public static class Default extends CollectionAddedToEvent<Object, Object> {
+        private static final long serialVersionUID = 1L;
+    }
 
-    private final S source;
     private final Identifier identifier;
     private final T value;
     
@@ -41,22 +44,19 @@ public abstract class CollectionAddedToEvent<S,T> {
         this(null, null, null);
     }
     
-    /**
-     * @deprecated - use {@link #CollectionAddedToEvent(Object, Identifier, Object)}
-     */
-    @Deprecated
-    public CollectionAddedToEvent(S source, T value) {
-        this(source, null, value);
-    }
-
-    public CollectionAddedToEvent(S source, Identifier identifier, T value) {
-        this.source = source;
+    public CollectionAddedToEvent(
+            final S source, 
+            final Identifier identifier, 
+            final T value) {
+        super(source);
         this.identifier = identifier;
         this.value = value;
     }
     
+    @Override
+    @SuppressWarnings("unchecked")
     public S getSource() {
-        return source;
+        return (S)source;
     }
     public Identifier getIdentifier() {
         return identifier;

http://git-wip-us.apache.org/repos/asf/isis/blob/c2b250f0/core/applib/src/main/java/org/apache/isis/applib/services/eventbus/CollectionRemovedFromEvent.java
----------------------------------------------------------------------
diff --git a/core/applib/src/main/java/org/apache/isis/applib/services/eventbus/CollectionRemovedFromEvent.java b/core/applib/src/main/java/org/apache/isis/applib/services/eventbus/CollectionRemovedFromEvent.java
index 17b8fed..47ff424 100644
--- a/core/applib/src/main/java/org/apache/isis/applib/services/eventbus/CollectionRemovedFromEvent.java
+++ b/core/applib/src/main/java/org/apache/isis/applib/services/eventbus/CollectionRemovedFromEvent.java
@@ -21,11 +21,14 @@ package org.apache.isis.applib.services.eventbus;
 import org.apache.isis.applib.Identifier;
 import org.apache.isis.applib.util.ObjectContracts;
 
-public abstract class CollectionRemovedFromEvent<S,T> {
+public abstract class CollectionRemovedFromEvent<S,T> extends java.util.EventObject {
     
-    public static class Default extends CollectionRemovedFromEvent<Object, Object> {}
+    private static final long serialVersionUID = 1L;
+
+    public static class Default extends CollectionRemovedFromEvent<Object, Object> {
+        private static final long serialVersionUID = 1L;
+    }
 
-    private final S source;
     private final Identifier identifier;
     private final T value;
     
@@ -39,21 +42,19 @@ public abstract class CollectionRemovedFromEvent<S,T> {
     public CollectionRemovedFromEvent() {
         this(null, null, null);
     }
-    /**
-     * @deprecated - use {@link #CollectionRemovedFromEvent(Object, Identifier, Object)}
-     */
-    @Deprecated
-    public CollectionRemovedFromEvent(S source, T value) {
-        this(source, null, value);
-    }
-    public CollectionRemovedFromEvent(S source, Identifier identifier, T value) {
-        this.source = source;
+    public CollectionRemovedFromEvent(
+            final S source, 
+            final Identifier identifier, 
+            final T value) {
+        super(source);
         this.identifier = identifier;
         this.value = value;
     }
 
+    @Override
+    @SuppressWarnings("unchecked")
     public S getSource() {
-        return source;
+        return (S) source;
     }
     public Identifier getIdentifier() {
         return identifier;

http://git-wip-us.apache.org/repos/asf/isis/blob/c2b250f0/core/applib/src/main/java/org/apache/isis/applib/services/eventbus/PropertyChangedEvent.java
----------------------------------------------------------------------
diff --git a/core/applib/src/main/java/org/apache/isis/applib/services/eventbus/PropertyChangedEvent.java b/core/applib/src/main/java/org/apache/isis/applib/services/eventbus/PropertyChangedEvent.java
index 9ae0afe..13666ff 100644
--- a/core/applib/src/main/java/org/apache/isis/applib/services/eventbus/PropertyChangedEvent.java
+++ b/core/applib/src/main/java/org/apache/isis/applib/services/eventbus/PropertyChangedEvent.java
@@ -22,11 +22,14 @@ import org.apache.isis.applib.Identifier;
 import org.apache.isis.applib.annotation.PostsPropertyChangedEvent;
 import org.apache.isis.applib.util.ObjectContracts;
 
-public abstract class PropertyChangedEvent<S,T> {
+public abstract class PropertyChangedEvent<S,T> extends java.util.EventObject {
     
-    public static class Default extends PropertyChangedEvent<Object, Object> {}
+    private static final long serialVersionUID = 1L;
+
+    public static class Default extends PropertyChangedEvent<Object, Object> {
+        private static final long serialVersionUID = 1L;
+    }
     
-    private final S source;
     private final Identifier identifier;
     private final T oldValue;
     private final T newValue;
@@ -52,14 +55,16 @@ public abstract class PropertyChangedEvent<S,T> {
     }
 
     public PropertyChangedEvent(S source, Identifier identifier, T oldValue, T newValue) {
-        this.source = source;
+        super(source);
         this.identifier = identifier;
         this.oldValue = oldValue;
         this.newValue = newValue;
     }
     
+    @Override
+    @SuppressWarnings("unchecked")
     public S getSource() {
-        return source;
+        return (S) source;
     }
     public Identifier getIdentifier() {
         return identifier;

http://git-wip-us.apache.org/repos/asf/isis/blob/c2b250f0/core/applib/src/main/java/org/apache/isis/applib/services/wrapper/WrapperFactory.java
----------------------------------------------------------------------
diff --git a/core/applib/src/main/java/org/apache/isis/applib/services/wrapper/WrapperFactory.java b/core/applib/src/main/java/org/apache/isis/applib/services/wrapper/WrapperFactory.java
index 1fb3c5a..4a8a452 100644
--- a/core/applib/src/main/java/org/apache/isis/applib/services/wrapper/WrapperFactory.java
+++ b/core/applib/src/main/java/org/apache/isis/applib/services/wrapper/WrapperFactory.java
@@ -70,7 +70,33 @@ public interface WrapperFactory {
      * @see WrapperFactory#wrap(Object, ExecutionMode)
      */
     public static enum ExecutionMode {
-        EXECUTE, NO_EXECUTE
+        /**
+         * Validate all business rules and then execute.
+         */
+        EXECUTE(true,true), 
+        /**
+         * Skip all business rules and then execute.
+         */
+        SKIP_RULES(false, true), 
+        /**
+         * Validate all business rules but do not execute.
+         */
+        NO_EXECUTE(true, false);
+        
+        private final boolean enforceRules;
+        private final boolean execute;
+
+        private ExecutionMode(final boolean enforceRules, final boolean execute) {
+            this.enforceRules = enforceRules;
+            this.execute = execute;
+        }
+
+        public boolean shouldEnforceRules() {
+            return enforceRules;
+        }
+        public boolean shouldExecute() {
+            return execute;
+        }
     }
 
     WrapperFactory NOOP = new WrapperFactory(){
@@ -81,6 +107,16 @@ public interface WrapperFactory {
         }
 
         @Override
+        public <T> T wrapNoExecute(T domainObject) {
+            return domainObject;
+        }
+        
+        @Override
+        public <T> T wrapSkipRules(T domainObject) {
+            return domainObject;
+        }
+        
+        @Override
         public <T> T wrap(T domainObject, ExecutionMode mode) {
             return domainObject;
         }
@@ -126,6 +162,20 @@ public interface WrapperFactory {
     <T> T wrap(T domainObject);
 
     /**
+     * Convenience method for {@link #wrap(Object, ExecutionMode)} with {@link ExecutionMode#NO_EXECUTE},
+     * to make this feature more discoverable.
+     */
+    @Programmatic
+    <T> T wrapNoExecute(T domainObject);
+    
+    /**
+     * Convenience method for {@link #wrap(Object, ExecutionMode)} with {@link ExecutionMode#SKIP_RULES},
+     * to make this feature more discoverable.
+     */
+    @Programmatic
+    <T> T wrapSkipRules(T domainObject);
+    
+    /**
      * Same as {@link #wrap(Object)}, except the actual execution occurs only if
      * the <tt>execute</tt> parameter indicates.
      * 

http://git-wip-us.apache.org/repos/asf/isis/blob/c2b250f0/core/metamodel/src/main/java/org/apache/isis/core/metamodel/facets/PostsEventWithWrapperPolicy.java
----------------------------------------------------------------------
diff --git a/core/metamodel/src/main/java/org/apache/isis/core/metamodel/facets/PostsEventWithWrapperPolicy.java b/core/metamodel/src/main/java/org/apache/isis/core/metamodel/facets/PostsEventWithWrapperPolicy.java
deleted file mode 100644
index 0c12c1c..0000000
--- a/core/metamodel/src/main/java/org/apache/isis/core/metamodel/facets/PostsEventWithWrapperPolicy.java
+++ /dev/null
@@ -1,61 +0,0 @@
-/*
- *  Licensed to the Apache Software Foundation (ASF) under one
- *  or more contributor license agreements.  See the NOTICE file
- *  distributed with this work for additional information
- *  regarding copyright ownership.  The ASF licenses this file
- *  to you under the Apache License, Version 2.0 (the
- *  "License"); you may not use this file except in compliance
- *  with the License.  You may obtain a copy of the License at
- *
- *        http://www.apache.org/licenses/LICENSE-2.0
- *
- *  Unless required by applicable law or agreed to in writing,
- *  software distributed under the License is distributed on an
- *  "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- *  KIND, either express or implied.  See the License for the
- *  specific language governing permissions and limitations
- *  under the License.
- */
-
-package org.apache.isis.core.metamodel.facets;
-
-import org.apache.isis.applib.annotation.WrapperPolicy;
-import org.apache.isis.applib.services.eventbus.EventBusService;
-import org.apache.isis.applib.services.eventbus.PropertyChangedEvent;
-import org.apache.isis.core.commons.lang.ObjectExtensions;
-import org.apache.isis.core.metamodel.facetapi.DecoratingFacet;
-import org.apache.isis.core.metamodel.facetapi.Facet;
-import org.apache.isis.core.metamodel.facetapi.MultiTypedFacet;
-import org.apache.isis.core.metamodel.facets.properties.modify.PropertyClearFacet;
-import org.apache.isis.core.metamodel.facets.properties.modify.PropertySetterFacet;
-
-public interface PostsEventWithWrapperPolicy {
-
-    WrapperPolicy getWrapperPolicy();
-    
-    public static class Util {
-        private Util(){}
-
-        /**
-         * Returns the provided {@link Facet facet} as an {@link PostsEventWithWrapperPolicy} if
-         * it either is one or if it is a {@link DecoratingFacet} that in turn wraps
-         * an {@link PostsEventWithWrapperPolicy}.
-         * 
-         * <p>
-         * Otherwise, returns <tt>null</tt>.
-         */
-        public static PostsEventWithWrapperPolicy getWrapperPolicyFacet(final Facet facet) {
-            if (facet instanceof PostsEventWithWrapperPolicy) {
-                return (PostsEventWithWrapperPolicy) facet;
-            }
-            if (facet.getUnderlyingFacet() instanceof PostsEventWithWrapperPolicy) {
-                return (PostsEventWithWrapperPolicy) facet.getUnderlyingFacet();
-            }
-            if (facet instanceof DecoratingFacet) {
-                final DecoratingFacet<?> decoratingFacet = ObjectExtensions.asT(facet);
-                return getWrapperPolicyFacet(decoratingFacet.getDecoratedFacet());
-            }
-            return null;
-        }
-    }
-}

http://git-wip-us.apache.org/repos/asf/isis/blob/c2b250f0/core/metamodel/src/main/java/org/apache/isis/core/metamodel/facets/collections/event/PostsCollectionAddedToEventFacet.java
----------------------------------------------------------------------
diff --git a/core/metamodel/src/main/java/org/apache/isis/core/metamodel/facets/collections/event/PostsCollectionAddedToEventFacet.java b/core/metamodel/src/main/java/org/apache/isis/core/metamodel/facets/collections/event/PostsCollectionAddedToEventFacet.java
index 72edf00..f437667 100644
--- a/core/metamodel/src/main/java/org/apache/isis/core/metamodel/facets/collections/event/PostsCollectionAddedToEventFacet.java
+++ b/core/metamodel/src/main/java/org/apache/isis/core/metamodel/facets/collections/event/PostsCollectionAddedToEventFacet.java
@@ -22,7 +22,6 @@ package org.apache.isis.core.metamodel.facets.collections.event;
 import org.apache.isis.applib.services.eventbus.CollectionAddedToEvent;
 import org.apache.isis.applib.services.eventbus.EventBusService;
 import org.apache.isis.core.metamodel.facetapi.MultiTypedFacet;
-import org.apache.isis.core.metamodel.facets.PostsEventWithWrapperPolicy;
 import org.apache.isis.core.metamodel.facets.SingleValueFacet;
 import org.apache.isis.core.metamodel.facets.collections.modify.CollectionAddToFacet;
 
@@ -30,6 +29,6 @@ import org.apache.isis.core.metamodel.facets.collections.modify.CollectionAddToF
  * Indicates that (the specified subclass of) {@link CollectionAddedToEvent} should be posted to the
  * {@link EventBusService}.
  */
-public interface PostsCollectionAddedToEventFacet extends SingleValueFacet<Class<? extends CollectionAddedToEvent<?,?>>>, CollectionAddToFacet, MultiTypedFacet, PostsEventWithWrapperPolicy {
+public interface PostsCollectionAddedToEventFacet extends SingleValueFacet<Class<? extends CollectionAddedToEvent<?,?>>>, CollectionAddToFacet, MultiTypedFacet {
 }
 

http://git-wip-us.apache.org/repos/asf/isis/blob/c2b250f0/core/metamodel/src/main/java/org/apache/isis/core/metamodel/facets/collections/event/PostsCollectionAddedToEventFacetAbstract.java
----------------------------------------------------------------------
diff --git a/core/metamodel/src/main/java/org/apache/isis/core/metamodel/facets/collections/event/PostsCollectionAddedToEventFacetAbstract.java b/core/metamodel/src/main/java/org/apache/isis/core/metamodel/facets/collections/event/PostsCollectionAddedToEventFacetAbstract.java
index 4f89185..7423a41 100644
--- a/core/metamodel/src/main/java/org/apache/isis/core/metamodel/facets/collections/event/PostsCollectionAddedToEventFacetAbstract.java
+++ b/core/metamodel/src/main/java/org/apache/isis/core/metamodel/facets/collections/event/PostsCollectionAddedToEventFacetAbstract.java
@@ -19,7 +19,6 @@
 
 package org.apache.isis.core.metamodel.facets.collections.event;
 
-import org.apache.isis.applib.annotation.WrapperPolicy;
 import org.apache.isis.applib.services.eventbus.CollectionAddedToEvent;
 import org.apache.isis.core.metamodel.facetapi.Facet;
 import org.apache.isis.core.metamodel.facetapi.FacetHolder;
@@ -40,16 +39,10 @@ public abstract class PostsCollectionAddedToEventFacetAbstract
 	    return CollectionAddToFacet.class;
     }
 
-    private final WrapperPolicy wrapperPolicy;
-
-    public PostsCollectionAddedToEventFacetAbstract(Class<? extends CollectionAddedToEvent<?, ?>> changedEventType, WrapperPolicy wrapperPolicy, FacetHolder holder) {
+    public PostsCollectionAddedToEventFacetAbstract(
+            final Class<? extends CollectionAddedToEvent<?, ?>> changedEventType, 
+            final FacetHolder holder) {
         super(type(), changedEventType, holder);
-        this.wrapperPolicy = wrapperPolicy;
-    }
-
-    @Override
-    public WrapperPolicy getWrapperPolicy() {
-        return wrapperPolicy;
     }
 
 }

http://git-wip-us.apache.org/repos/asf/isis/blob/c2b250f0/core/metamodel/src/main/java/org/apache/isis/core/metamodel/facets/collections/event/PostsCollectionRemovedFromEventFacet.java
----------------------------------------------------------------------
diff --git a/core/metamodel/src/main/java/org/apache/isis/core/metamodel/facets/collections/event/PostsCollectionRemovedFromEventFacet.java b/core/metamodel/src/main/java/org/apache/isis/core/metamodel/facets/collections/event/PostsCollectionRemovedFromEventFacet.java
index d351f84..90a657b 100644
--- a/core/metamodel/src/main/java/org/apache/isis/core/metamodel/facets/collections/event/PostsCollectionRemovedFromEventFacet.java
+++ b/core/metamodel/src/main/java/org/apache/isis/core/metamodel/facets/collections/event/PostsCollectionRemovedFromEventFacet.java
@@ -22,7 +22,6 @@ package org.apache.isis.core.metamodel.facets.collections.event;
 import org.apache.isis.applib.services.eventbus.CollectionRemovedFromEvent;
 import org.apache.isis.applib.services.eventbus.EventBusService;
 import org.apache.isis.core.metamodel.facetapi.MultiTypedFacet;
-import org.apache.isis.core.metamodel.facets.PostsEventWithWrapperPolicy;
 import org.apache.isis.core.metamodel.facets.SingleValueFacet;
 import org.apache.isis.core.metamodel.facets.collections.modify.CollectionRemoveFromFacet;
 
@@ -30,6 +29,6 @@ import org.apache.isis.core.metamodel.facets.collections.modify.CollectionRemove
  * Indicates that (the specified subclass of) {@link CollectionRemovedFromEvent} should be posted to the
  * {@link EventBusService}.
  */
-public interface PostsCollectionRemovedFromEventFacet extends SingleValueFacet<Class<? extends CollectionRemovedFromEvent<?,?>>>, CollectionRemoveFromFacet, MultiTypedFacet, PostsEventWithWrapperPolicy {
+public interface PostsCollectionRemovedFromEventFacet extends SingleValueFacet<Class<? extends CollectionRemovedFromEvent<?,?>>>, CollectionRemoveFromFacet, MultiTypedFacet {
 }
 

http://git-wip-us.apache.org/repos/asf/isis/blob/c2b250f0/core/metamodel/src/main/java/org/apache/isis/core/metamodel/facets/collections/event/PostsCollectionRemovedFromEventFacetAbstract.java
----------------------------------------------------------------------
diff --git a/core/metamodel/src/main/java/org/apache/isis/core/metamodel/facets/collections/event/PostsCollectionRemovedFromEventFacetAbstract.java b/core/metamodel/src/main/java/org/apache/isis/core/metamodel/facets/collections/event/PostsCollectionRemovedFromEventFacetAbstract.java
index a317467..18fc423 100644
--- a/core/metamodel/src/main/java/org/apache/isis/core/metamodel/facets/collections/event/PostsCollectionRemovedFromEventFacetAbstract.java
+++ b/core/metamodel/src/main/java/org/apache/isis/core/metamodel/facets/collections/event/PostsCollectionRemovedFromEventFacetAbstract.java
@@ -19,7 +19,6 @@
 
 package org.apache.isis.core.metamodel.facets.collections.event;
 
-import org.apache.isis.applib.annotation.WrapperPolicy;
 import org.apache.isis.applib.services.eventbus.CollectionRemovedFromEvent;
 import org.apache.isis.core.metamodel.facetapi.Facet;
 import org.apache.isis.core.metamodel.facetapi.FacetHolder;
@@ -40,16 +39,10 @@ public abstract class PostsCollectionRemovedFromEventFacetAbstract
 	    return CollectionRemoveFromFacet.class;
     }
 
-    private final WrapperPolicy wrapperPolicy;
-
-    public PostsCollectionRemovedFromEventFacetAbstract(Class<? extends CollectionRemovedFromEvent<?, ?>> changedEventType, WrapperPolicy wrapperPolicy, FacetHolder holder) {
+    public PostsCollectionRemovedFromEventFacetAbstract(
+            final Class<? extends CollectionRemovedFromEvent<?, ?>> changedEventType, 
+            final FacetHolder holder) {
         super(type(), changedEventType, holder);
-        this.wrapperPolicy = wrapperPolicy;
-    }
-
-    @Override
-    public WrapperPolicy getWrapperPolicy() {
-        return wrapperPolicy;
     }
 
 }

http://git-wip-us.apache.org/repos/asf/isis/blob/c2b250f0/core/metamodel/src/main/java/org/apache/isis/core/metamodel/facets/properties/event/PostsPropertyChangedEventFacet.java
----------------------------------------------------------------------
diff --git a/core/metamodel/src/main/java/org/apache/isis/core/metamodel/facets/properties/event/PostsPropertyChangedEventFacet.java b/core/metamodel/src/main/java/org/apache/isis/core/metamodel/facets/properties/event/PostsPropertyChangedEventFacet.java
index e5c108f..a01e7f4 100644
--- a/core/metamodel/src/main/java/org/apache/isis/core/metamodel/facets/properties/event/PostsPropertyChangedEventFacet.java
+++ b/core/metamodel/src/main/java/org/apache/isis/core/metamodel/facets/properties/event/PostsPropertyChangedEventFacet.java
@@ -22,7 +22,6 @@ package org.apache.isis.core.metamodel.facets.properties.event;
 import org.apache.isis.applib.services.eventbus.EventBusService;
 import org.apache.isis.applib.services.eventbus.PropertyChangedEvent;
 import org.apache.isis.core.metamodel.facetapi.MultiTypedFacet;
-import org.apache.isis.core.metamodel.facets.PostsEventWithWrapperPolicy;
 import org.apache.isis.core.metamodel.facets.SingleValueFacet;
 import org.apache.isis.core.metamodel.facets.properties.modify.PropertyClearFacet;
 import org.apache.isis.core.metamodel.facets.properties.modify.PropertySetterFacet;
@@ -31,6 +30,6 @@ import org.apache.isis.core.metamodel.facets.properties.modify.PropertySetterFac
  * Indicates that (the specified subclass of) {@link PropertyChangedEvent} should be posted to the
  * {@link EventBusService}.
  */
-public interface PostsPropertyChangedEventFacet extends SingleValueFacet<Class<? extends PropertyChangedEvent<?,?>>>, PropertyClearFacet, PropertySetterFacet, MultiTypedFacet, PostsEventWithWrapperPolicy {
+public interface PostsPropertyChangedEventFacet extends SingleValueFacet<Class<? extends PropertyChangedEvent<?,?>>>, PropertyClearFacet, PropertySetterFacet, MultiTypedFacet {
 
 }

http://git-wip-us.apache.org/repos/asf/isis/blob/c2b250f0/core/metamodel/src/main/java/org/apache/isis/core/metamodel/facets/properties/event/PostsPropertyChangedEventFacetAbstract.java
----------------------------------------------------------------------
diff --git a/core/metamodel/src/main/java/org/apache/isis/core/metamodel/facets/properties/event/PostsPropertyChangedEventFacetAbstract.java b/core/metamodel/src/main/java/org/apache/isis/core/metamodel/facets/properties/event/PostsPropertyChangedEventFacetAbstract.java
index 69ff6a0..1acbf8d 100644
--- a/core/metamodel/src/main/java/org/apache/isis/core/metamodel/facets/properties/event/PostsPropertyChangedEventFacetAbstract.java
+++ b/core/metamodel/src/main/java/org/apache/isis/core/metamodel/facets/properties/event/PostsPropertyChangedEventFacetAbstract.java
@@ -19,7 +19,6 @@
 
 package org.apache.isis.core.metamodel.facets.properties.event;
 
-import org.apache.isis.applib.annotation.WrapperPolicy;
 import org.apache.isis.applib.services.eventbus.PropertyChangedEvent;
 import org.apache.isis.core.metamodel.facetapi.Facet;
 import org.apache.isis.core.metamodel.facetapi.FacetHolder;
@@ -35,16 +34,10 @@ public abstract class PostsPropertyChangedEventFacetAbstract
         return PostsPropertyChangedEventFacet.class;
     }
 
-    private final WrapperPolicy wrapperPolicy;
-
-    public PostsPropertyChangedEventFacetAbstract(final Class<? extends PropertyChangedEvent<?,?>> changedEventType, final WrapperPolicy wrapperPolicy, final FacetHolder holder) {
+    public PostsPropertyChangedEventFacetAbstract(
+            final Class<? extends PropertyChangedEvent<?,?>> changedEventType, 
+            final FacetHolder holder) {
         super(type(), changedEventType, holder);
-        this.wrapperPolicy = wrapperPolicy;
-    }
-
-    @Override
-    public WrapperPolicy getWrapperPolicy() {
-        return wrapperPolicy;
     }
 
 }

http://git-wip-us.apache.org/repos/asf/isis/blob/c2b250f0/core/metamodel/src/main/java/org/apache/isis/core/progmodel/facets/collections/event/PostsCollectionAddedToEventAnnotationFacetFactory.java
----------------------------------------------------------------------
diff --git a/core/metamodel/src/main/java/org/apache/isis/core/progmodel/facets/collections/event/PostsCollectionAddedToEventAnnotationFacetFactory.java b/core/metamodel/src/main/java/org/apache/isis/core/progmodel/facets/collections/event/PostsCollectionAddedToEventAnnotationFacetFactory.java
index 504dd64..5292f07 100644
--- a/core/metamodel/src/main/java/org/apache/isis/core/progmodel/facets/collections/event/PostsCollectionAddedToEventAnnotationFacetFactory.java
+++ b/core/metamodel/src/main/java/org/apache/isis/core/progmodel/facets/collections/event/PostsCollectionAddedToEventAnnotationFacetFactory.java
@@ -22,7 +22,6 @@ package org.apache.isis.core.progmodel.facets.collections.event;
 import java.lang.reflect.Method;
 
 import org.apache.isis.applib.annotation.PostsCollectionAddedToEvent;
-import org.apache.isis.applib.annotation.WrapperPolicy;
 import org.apache.isis.applib.services.eventbus.CollectionAddedToEvent;
 import org.apache.isis.core.metamodel.adapter.ServicesProvider;
 import org.apache.isis.core.metamodel.adapter.ServicesProviderAware;
@@ -66,8 +65,7 @@ public class PostsCollectionAddedToEventAnnotationFacetFactory extends FacetFact
         // the collectionAddToFacet will end up as the underlying facet of the PostsCollectionAddedToEventFacetAnnotation
 
         final Class<? extends CollectionAddedToEvent<?,?>> changedEventType = annotation.value();
-        final WrapperPolicy wrapperPolicy = annotation.wrapperPolicy();
-        return new PostsCollectionAddedToEventFacetAnnotation(changedEventType, wrapperPolicy, getterFacet, collectionAddToFacet, servicesProvider, holder);
+        return new PostsCollectionAddedToEventFacetAnnotation(changedEventType, getterFacet, collectionAddToFacet, servicesProvider, holder);
     }
 
     @Override

http://git-wip-us.apache.org/repos/asf/isis/blob/c2b250f0/core/metamodel/src/main/java/org/apache/isis/core/progmodel/facets/collections/event/PostsCollectionAddedToEventFacetAnnotation.java
----------------------------------------------------------------------
diff --git a/core/metamodel/src/main/java/org/apache/isis/core/progmodel/facets/collections/event/PostsCollectionAddedToEventFacetAnnotation.java b/core/metamodel/src/main/java/org/apache/isis/core/progmodel/facets/collections/event/PostsCollectionAddedToEventFacetAnnotation.java
index bd69339..e566300 100644
--- a/core/metamodel/src/main/java/org/apache/isis/core/progmodel/facets/collections/event/PostsCollectionAddedToEventFacetAnnotation.java
+++ b/core/metamodel/src/main/java/org/apache/isis/core/progmodel/facets/collections/event/PostsCollectionAddedToEventFacetAnnotation.java
@@ -27,7 +27,6 @@ import com.google.common.collect.Lists;
 
 import org.apache.isis.applib.FatalException;
 import org.apache.isis.applib.Identifier;
-import org.apache.isis.applib.annotation.WrapperPolicy;
 import org.apache.isis.applib.services.eventbus.CollectionAddedToEvent;
 import org.apache.isis.applib.services.eventbus.EventBusService;
 import org.apache.isis.core.metamodel.adapter.ObjectAdapter;
@@ -52,12 +51,11 @@ public class PostsCollectionAddedToEventFacetAnnotation
 
 	public PostsCollectionAddedToEventFacetAnnotation(
 			final Class<? extends CollectionAddedToEvent<?, ?>> eventType,
-            final WrapperPolicy wrapperPolicy,
 			final PropertyOrCollectionAccessorFacet getterFacet,
 			final CollectionAddToFacet collectionAddToFacet,
 			final ServicesProvider servicesProvider, 
 			final FacetHolder holder) {
-		super(eventType, wrapperPolicy, holder);
+		super(eventType, holder);
         this.getterFacet = getterFacet;
 		this.collectionAddToFacet = collectionAddToFacet;
 		this.servicesProvider = servicesProvider;

http://git-wip-us.apache.org/repos/asf/isis/blob/c2b250f0/core/metamodel/src/main/java/org/apache/isis/core/progmodel/facets/collections/event/PostsCollectionRemovedFromEventAnnotationFacetFactory.java
----------------------------------------------------------------------
diff --git a/core/metamodel/src/main/java/org/apache/isis/core/progmodel/facets/collections/event/PostsCollectionRemovedFromEventAnnotationFacetFactory.java b/core/metamodel/src/main/java/org/apache/isis/core/progmodel/facets/collections/event/PostsCollectionRemovedFromEventAnnotationFacetFactory.java
index 67e8871..abf039c 100644
--- a/core/metamodel/src/main/java/org/apache/isis/core/progmodel/facets/collections/event/PostsCollectionRemovedFromEventAnnotationFacetFactory.java
+++ b/core/metamodel/src/main/java/org/apache/isis/core/progmodel/facets/collections/event/PostsCollectionRemovedFromEventAnnotationFacetFactory.java
@@ -22,7 +22,6 @@ package org.apache.isis.core.progmodel.facets.collections.event;
 import java.lang.reflect.Method;
 
 import org.apache.isis.applib.annotation.PostsCollectionRemovedFromEvent;
-import org.apache.isis.applib.annotation.WrapperPolicy;
 import org.apache.isis.applib.services.eventbus.CollectionRemovedFromEvent;
 import org.apache.isis.core.metamodel.adapter.ServicesProvider;
 import org.apache.isis.core.metamodel.adapter.ServicesProviderAware;
@@ -66,8 +65,7 @@ public class PostsCollectionRemovedFromEventAnnotationFacetFactory extends Facet
         // the collectionRemoveFromFacet will end up as the underlying facet of the PostsCollectionRemovedFromEventFacetAnnotation
 
         final Class<? extends CollectionRemovedFromEvent<?,?>> changedEventType = annotation.value();
-        final WrapperPolicy wrapperPolicy = annotation.wrapperPolicy();
-        return new PostsCollectionRemovedFromEventFacetAnnotation(changedEventType, wrapperPolicy, getterFacet, collectionRemoveFromFacet, servicesProvider, holder);
+        return new PostsCollectionRemovedFromEventFacetAnnotation(changedEventType, getterFacet, collectionRemoveFromFacet, servicesProvider, holder);
     }
 
     @Override

http://git-wip-us.apache.org/repos/asf/isis/blob/c2b250f0/core/metamodel/src/main/java/org/apache/isis/core/progmodel/facets/collections/event/PostsCollectionRemovedFromEventFacetAnnotation.java
----------------------------------------------------------------------
diff --git a/core/metamodel/src/main/java/org/apache/isis/core/progmodel/facets/collections/event/PostsCollectionRemovedFromEventFacetAnnotation.java b/core/metamodel/src/main/java/org/apache/isis/core/progmodel/facets/collections/event/PostsCollectionRemovedFromEventFacetAnnotation.java
index a19b55d..98524cf 100644
--- a/core/metamodel/src/main/java/org/apache/isis/core/progmodel/facets/collections/event/PostsCollectionRemovedFromEventFacetAnnotation.java
+++ b/core/metamodel/src/main/java/org/apache/isis/core/progmodel/facets/collections/event/PostsCollectionRemovedFromEventFacetAnnotation.java
@@ -27,7 +27,6 @@ import com.google.common.collect.Lists;
 
 import org.apache.isis.applib.FatalException;
 import org.apache.isis.applib.Identifier;
-import org.apache.isis.applib.annotation.WrapperPolicy;
 import org.apache.isis.applib.services.eventbus.CollectionRemovedFromEvent;
 import org.apache.isis.applib.services.eventbus.EventBusService;
 import org.apache.isis.core.metamodel.adapter.ObjectAdapter;
@@ -52,11 +51,10 @@ public class PostsCollectionRemovedFromEventFacetAnnotation extends
 
 	public PostsCollectionRemovedFromEventFacetAnnotation(
 			final Class<? extends CollectionRemovedFromEvent<?, ?>> eventType,
-			final WrapperPolicy wrapperPolicy,
 			final PropertyOrCollectionAccessorFacet getterFacet,
 			final CollectionRemoveFromFacet collectionRemoveFromFacet,
 			final ServicesProvider servicesProvider, final FacetHolder holder) {
-		super(eventType, wrapperPolicy, holder);
+		super(eventType, holder);
 		this.getterFacet = getterFacet;
 		this.collectionRemoveFromFacet = collectionRemoveFromFacet;
 		this.servicesProvider = servicesProvider;

http://git-wip-us.apache.org/repos/asf/isis/blob/c2b250f0/core/metamodel/src/main/java/org/apache/isis/core/progmodel/facets/properties/event/PostsPropertyChangedEventAnnotationFacetFactory.java
----------------------------------------------------------------------
diff --git a/core/metamodel/src/main/java/org/apache/isis/core/progmodel/facets/properties/event/PostsPropertyChangedEventAnnotationFacetFactory.java b/core/metamodel/src/main/java/org/apache/isis/core/progmodel/facets/properties/event/PostsPropertyChangedEventAnnotationFacetFactory.java
index 1a75d60..030a5b3 100644
--- a/core/metamodel/src/main/java/org/apache/isis/core/progmodel/facets/properties/event/PostsPropertyChangedEventAnnotationFacetFactory.java
+++ b/core/metamodel/src/main/java/org/apache/isis/core/progmodel/facets/properties/event/PostsPropertyChangedEventAnnotationFacetFactory.java
@@ -24,7 +24,6 @@ import java.util.Comparator;
 import java.util.List;
 
 import org.apache.isis.applib.annotation.PostsPropertyChangedEvent;
-import org.apache.isis.applib.annotation.WrapperPolicy;
 import org.apache.isis.applib.services.eventbus.PropertyChangedEvent;
 import org.apache.isis.core.commons.config.IsisConfiguration;
 import org.apache.isis.core.metamodel.adapter.ServicesProvider;
@@ -90,8 +89,7 @@ public class PostsPropertyChangedEventAnnotationFacetFactory extends FacetFactor
         }
         
         final Class<? extends PropertyChangedEvent<?, ?>> changedEventType = annotation.value();
-        final WrapperPolicy wrapperPolicy = annotation.wrapperPolicy();
-        return new PostsPropertyChangedEventFacetAnnotation(changedEventType, wrapperPolicy, getterFacet, setterFacet, clearFacet, servicesProvider, holder);
+        return new PostsPropertyChangedEventFacetAnnotation(changedEventType, getterFacet, setterFacet, clearFacet, servicesProvider, holder);
     }
 
     @Override

http://git-wip-us.apache.org/repos/asf/isis/blob/c2b250f0/core/metamodel/src/main/java/org/apache/isis/core/progmodel/facets/properties/event/PostsPropertyChangedEventFacetAnnotation.java
----------------------------------------------------------------------
diff --git a/core/metamodel/src/main/java/org/apache/isis/core/progmodel/facets/properties/event/PostsPropertyChangedEventFacetAnnotation.java b/core/metamodel/src/main/java/org/apache/isis/core/progmodel/facets/properties/event/PostsPropertyChangedEventFacetAnnotation.java
index afc96bb..017cf48 100644
--- a/core/metamodel/src/main/java/org/apache/isis/core/progmodel/facets/properties/event/PostsPropertyChangedEventFacetAnnotation.java
+++ b/core/metamodel/src/main/java/org/apache/isis/core/progmodel/facets/properties/event/PostsPropertyChangedEventFacetAnnotation.java
@@ -27,7 +27,6 @@ import com.google.common.collect.Lists;
 
 import org.apache.isis.applib.FatalException;
 import org.apache.isis.applib.Identifier;
-import org.apache.isis.applib.annotation.WrapperPolicy;
 import org.apache.isis.applib.services.eventbus.EventBusService;
 import org.apache.isis.applib.services.eventbus.PropertyChangedEvent;
 import org.apache.isis.core.metamodel.adapter.ObjectAdapter;
@@ -52,13 +51,12 @@ public class PostsPropertyChangedEventFacetAnnotation extends PostsPropertyChang
 
     public PostsPropertyChangedEventFacetAnnotation(
             final Class<? extends PropertyChangedEvent<?, ?>> eventType, 
-            final WrapperPolicy wrapperPolicy,
             final PropertyOrCollectionAccessorFacet getterFacet, 
             final PropertySetterFacet setterFacet, 
             final PropertyClearFacet clearFacet, 
             final ServicesProvider servicesProvider, 
             final FacetHolder holder) {
-        super(eventType, wrapperPolicy, holder);
+        super(eventType, holder);
         this.getterFacet = getterFacet;
         this.setterFacet = setterFacet;
         this.clearFacet = clearFacet;

http://git-wip-us.apache.org/repos/asf/isis/blob/c2b250f0/core/metamodel/src/test/java/org/apache/isis/core/progmodel/facets/collections/event/PostsCollectionAddedEventFacetAnnotationTest_newEvent.java
----------------------------------------------------------------------
diff --git a/core/metamodel/src/test/java/org/apache/isis/core/progmodel/facets/collections/event/PostsCollectionAddedEventFacetAnnotationTest_newEvent.java b/core/metamodel/src/test/java/org/apache/isis/core/progmodel/facets/collections/event/PostsCollectionAddedEventFacetAnnotationTest_newEvent.java
index c4f15c9..07baa29 100644
--- a/core/metamodel/src/test/java/org/apache/isis/core/progmodel/facets/collections/event/PostsCollectionAddedEventFacetAnnotationTest_newEvent.java
+++ b/core/metamodel/src/test/java/org/apache/isis/core/progmodel/facets/collections/event/PostsCollectionAddedEventFacetAnnotationTest_newEvent.java
@@ -33,7 +33,9 @@ public class PostsCollectionAddedEventFacetAnnotationTest_newEvent {
     }
     public static class SomeReferencedObject {}
     
-    public static class SomeDomainObjectCollectionAddedToEvent extends CollectionAddedToEvent<SomeDomainObject, SomeReferencedObject> {}
+    public static class SomeDomainObjectCollectionAddedToEvent extends CollectionAddedToEvent<SomeDomainObject, SomeReferencedObject> {
+        private static final long serialVersionUID = 1L;
+    }
     
     @Test
     public void test() throws Exception {

http://git-wip-us.apache.org/repos/asf/isis/blob/c2b250f0/core/metamodel/src/test/java/org/apache/isis/core/progmodel/facets/collections/event/PostsCollectionRemovedEventFacetAnnotationTest_newEvent.java
----------------------------------------------------------------------
diff --git a/core/metamodel/src/test/java/org/apache/isis/core/progmodel/facets/collections/event/PostsCollectionRemovedEventFacetAnnotationTest_newEvent.java b/core/metamodel/src/test/java/org/apache/isis/core/progmodel/facets/collections/event/PostsCollectionRemovedEventFacetAnnotationTest_newEvent.java
index a713a74..76ea7a4 100644
--- a/core/metamodel/src/test/java/org/apache/isis/core/progmodel/facets/collections/event/PostsCollectionRemovedEventFacetAnnotationTest_newEvent.java
+++ b/core/metamodel/src/test/java/org/apache/isis/core/progmodel/facets/collections/event/PostsCollectionRemovedEventFacetAnnotationTest_newEvent.java
@@ -32,7 +32,9 @@ public class PostsCollectionRemovedEventFacetAnnotationTest_newEvent {
     }
     public static class SomeReferencedObject {}
     
-    public static class SomeDomainObjectCollectionRemovedFromEvent extends CollectionRemovedFromEvent<SomeDomainObject, SomeReferencedObject> {}
+    public static class SomeDomainObjectCollectionRemovedFromEvent extends CollectionRemovedFromEvent<SomeDomainObject, SomeReferencedObject> {
+        private static final long serialVersionUID = 1L;
+    }
     
     @Test
     public void test() throws Exception {

http://git-wip-us.apache.org/repos/asf/isis/blob/c2b250f0/core/metamodel/src/test/java/org/apache/isis/core/progmodel/facets/properties/event/PostsPropertyChangedEventFacetAnnotationTest_newEvent.java
----------------------------------------------------------------------
diff --git a/core/metamodel/src/test/java/org/apache/isis/core/progmodel/facets/properties/event/PostsPropertyChangedEventFacetAnnotationTest_newEvent.java b/core/metamodel/src/test/java/org/apache/isis/core/progmodel/facets/properties/event/PostsPropertyChangedEventFacetAnnotationTest_newEvent.java
index f997473..4e4391d 100644
--- a/core/metamodel/src/test/java/org/apache/isis/core/progmodel/facets/properties/event/PostsPropertyChangedEventFacetAnnotationTest_newEvent.java
+++ b/core/metamodel/src/test/java/org/apache/isis/core/progmodel/facets/properties/event/PostsPropertyChangedEventFacetAnnotationTest_newEvent.java
@@ -29,7 +29,9 @@ public class PostsPropertyChangedEventFacetAnnotationTest_newEvent {
 
     public static class SomeDomainObject {}
     
-    public static class SomeDatePropertyChangedEvent extends PropertyChangedEvent<SomeDomainObject, LocalDate> {}
+    public static class SomeDatePropertyChangedEvent extends PropertyChangedEvent<SomeDomainObject, LocalDate> {
+        private static final long serialVersionUID = 1L;
+    }
     
     @Test
     public void test() throws Exception {

http://git-wip-us.apache.org/repos/asf/isis/blob/c2b250f0/core/wrapper/src/main/java/org/apache/isis/core/wrapper/WrapperFactoryAbstract.java
----------------------------------------------------------------------
diff --git a/core/wrapper/src/main/java/org/apache/isis/core/wrapper/WrapperFactoryAbstract.java b/core/wrapper/src/main/java/org/apache/isis/core/wrapper/WrapperFactoryAbstract.java
index 88c33c8..d0ba943 100644
--- a/core/wrapper/src/main/java/org/apache/isis/core/wrapper/WrapperFactoryAbstract.java
+++ b/core/wrapper/src/main/java/org/apache/isis/core/wrapper/WrapperFactoryAbstract.java
@@ -214,6 +214,16 @@ public abstract class WrapperFactoryAbstract implements WrapperFactory, Authenti
     }
 
     @Override
+    public <T> T wrapNoExecute(final T domainObject) {
+        return wrap(domainObject, ExecutionMode.NO_EXECUTE);
+    }
+    
+    @Override
+    public <T> T wrapSkipRules(final T domainObject) {
+        return wrap(domainObject, ExecutionMode.SKIP_RULES);
+    }
+    
+    @Override
     public <T> T wrap(final T domainObject, final ExecutionMode mode) {
         if (isWrapper(domainObject)) {
             return domainObject;

http://git-wip-us.apache.org/repos/asf/isis/blob/c2b250f0/core/wrapper/src/main/java/org/apache/isis/core/wrapper/handlers/DomainObjectInvocationHandler.java
----------------------------------------------------------------------
diff --git a/core/wrapper/src/main/java/org/apache/isis/core/wrapper/handlers/DomainObjectInvocationHandler.java b/core/wrapper/src/main/java/org/apache/isis/core/wrapper/handlers/DomainObjectInvocationHandler.java
index 1dc2293..01b03a0 100644
--- a/core/wrapper/src/main/java/org/apache/isis/core/wrapper/handlers/DomainObjectInvocationHandler.java
+++ b/core/wrapper/src/main/java/org/apache/isis/core/wrapper/handlers/DomainObjectInvocationHandler.java
@@ -27,7 +27,6 @@ import java.util.List;
 import java.util.Map;
 
 import org.apache.isis.applib.annotation.Where;
-import org.apache.isis.applib.annotation.WrapperPolicy;
 import org.apache.isis.applib.events.CollectionAccessEvent;
 import org.apache.isis.applib.events.InteractionEvent;
 import org.apache.isis.applib.events.ObjectTitleEvent;
@@ -55,7 +54,6 @@ import org.apache.isis.core.metamodel.consent.InteractionResult;
 import org.apache.isis.core.metamodel.facetapi.DecoratingFacet;
 import org.apache.isis.core.metamodel.facetapi.Facet;
 import org.apache.isis.core.metamodel.facets.ImperativeFacet;
-import org.apache.isis.core.metamodel.facets.PostsEventWithWrapperPolicy;
 import org.apache.isis.core.metamodel.facets.accessor.PropertyOrCollectionAccessorFacet;
 import org.apache.isis.core.metamodel.facets.actions.choices.ActionChoicesFacet;
 import org.apache.isis.core.metamodel.facets.actions.defaults.ActionDefaultsFacet;
@@ -329,7 +327,7 @@ public class DomainObjectInvocationHandler<T> extends DelegatingInvocationHandle
         final InteractionResult interactionResult = targetNoSpec.isValidResult(targetAdapter);
         notifyListenersAndVetoIfRequired(interactionResult);
 
-        if (getExecutionMode() == ExecutionMode.EXECUTE) {
+        if (getExecutionMode().shouldExecute()) {
             if (targetAdapter.isTransient()) {
                 getObjectPersistor().makePersistent(targetAdapter);
             }
@@ -370,8 +368,7 @@ public class DomainObjectInvocationHandler<T> extends DelegatingInvocationHandle
 
         final Object argumentObj = underlying(args[0]);
 
-        final WrapperPolicy wrapperPolicy = determineWrapperPolicy(otoa, argumentObj);
-        if(wrapperPolicy == WrapperPolicy.ENFORCE_RULES) {
+        if(getExecutionMode().shouldEnforceRules()) {
             checkVisibility(getAuthenticationSession(), targetAdapter, otoa);
             checkUsability(getAuthenticationSession(), targetAdapter, otoa);
         }
@@ -381,12 +378,12 @@ public class DomainObjectInvocationHandler<T> extends DelegatingInvocationHandle
         resolveIfRequired(targetAdapter);
 
 
-        if(wrapperPolicy == WrapperPolicy.ENFORCE_RULES) {
+        if(getExecutionMode().shouldEnforceRules()) {
             final InteractionResult interactionResult = otoa.isAssociationValid(targetAdapter, argumentAdapter).getInteractionResult();
             notifyListenersAndVetoIfRequired(interactionResult);
         }
 
-        if (getExecutionMode() == ExecutionMode.EXECUTE) {
+        if (getExecutionMode().shouldExecute()) {
             otoa.set(targetAdapter, argumentAdapter);
         }
 
@@ -395,19 +392,6 @@ public class DomainObjectInvocationHandler<T> extends DelegatingInvocationHandle
         return null;
     }
 
-    private static WrapperPolicy determineWrapperPolicy(final OneToOneAssociation otoa, final Object argumentObj) {
-        final PostsEventWithWrapperPolicy wrapperPolicyFacet;
-        if(argumentObj != null) {
-            final PropertySetterFacet setterFacet = otoa.getFacet(PropertySetterFacet.class);
-            wrapperPolicyFacet = PostsEventWithWrapperPolicy.Util.getWrapperPolicyFacet(setterFacet);
-        } else {
-            final PropertyClearFacet clearFacet = otoa.getFacet(PropertyClearFacet.class);
-            wrapperPolicyFacet = PostsEventWithWrapperPolicy.Util.getWrapperPolicyFacet(clearFacet);
-        }
-        return wrapperPolicyFacet != null ? wrapperPolicyFacet.getWrapperPolicy() : WrapperPolicy.ENFORCE_RULES;
-    }
-
-    
 
     // /////////////////////////////////////////////////////////////////
     // collection - access
@@ -480,8 +464,7 @@ public class DomainObjectInvocationHandler<T> extends DelegatingInvocationHandle
             throw new IllegalArgumentException("Invoking a addTo should only have a single argument");
         }
 
-        final WrapperPolicy wrapperPolicy = determineAddToWrapperPolicy(otma);
-        if(wrapperPolicy == WrapperPolicy.ENFORCE_RULES) {
+        if(getExecutionMode().shouldEnforceRules()) {
             checkVisibility(getAuthenticationSession(), targetAdapter, otma);
             checkUsability(getAuthenticationSession(), targetAdapter, otma);
         }
@@ -494,12 +477,12 @@ public class DomainObjectInvocationHandler<T> extends DelegatingInvocationHandle
         }
         final ObjectAdapter argumentNO = getAdapterManager().adapterFor(argumentObj);
 
-        if(wrapperPolicy == WrapperPolicy.ENFORCE_RULES) {
+        if(getExecutionMode().shouldEnforceRules()) {
             final InteractionResult interactionResult = otma.isValidToAdd(targetAdapter, argumentNO).getInteractionResult();
             notifyListenersAndVetoIfRequired(interactionResult);
         }
 
-        if (getExecutionMode() == ExecutionMode.EXECUTE) {
+        if (getExecutionMode().shouldExecute()) {
             otma.addElement(targetAdapter, argumentNO);
         }
 
@@ -508,12 +491,6 @@ public class DomainObjectInvocationHandler<T> extends DelegatingInvocationHandle
         return null;
     }
 
-    private static WrapperPolicy determineAddToWrapperPolicy(final OneToManyAssociation otma) {
-        final CollectionAddToFacet facet = otma.getFacet(CollectionAddToFacet.class);
-        final PostsEventWithWrapperPolicy wrapperPolicyFacet = PostsEventWithWrapperPolicy.Util.getWrapperPolicyFacet(facet);
-        return wrapperPolicyFacet != null ? wrapperPolicyFacet.getWrapperPolicy() : WrapperPolicy.ENFORCE_RULES;
-    }
-
 
     // /////////////////////////////////////////////////////////////////
     // collection - remove from
@@ -524,8 +501,7 @@ public class DomainObjectInvocationHandler<T> extends DelegatingInvocationHandle
             throw new IllegalArgumentException("Invoking a removeFrom should only have a single argument");
         }
 
-        final WrapperPolicy wrapperPolicy = determineRemoveFromWrapperPolicy(otma);
-        if(wrapperPolicy == WrapperPolicy.ENFORCE_RULES) {
+        if(getExecutionMode().shouldEnforceRules()) {
             checkVisibility(getAuthenticationSession(), targetAdapter, otma);
             checkUsability(getAuthenticationSession(), targetAdapter, otma);
         }
@@ -539,12 +515,12 @@ public class DomainObjectInvocationHandler<T> extends DelegatingInvocationHandle
         }
         final ObjectAdapter argumentAdapter = getAdapterManager().adapterFor(argumentObj);
 
-        if(wrapperPolicy == WrapperPolicy.ENFORCE_RULES) {
+        if(getExecutionMode().shouldEnforceRules()) {
             final InteractionResult interactionResult = otma.isValidToRemove(targetAdapter, argumentAdapter).getInteractionResult();
             notifyListenersAndVetoIfRequired(interactionResult);
         }
 
-        if (getExecutionMode() == ExecutionMode.EXECUTE) {
+        if (getExecutionMode().shouldExecute()) {
             otma.removeElement(targetAdapter, argumentAdapter);
         }
 
@@ -553,13 +529,6 @@ public class DomainObjectInvocationHandler<T> extends DelegatingInvocationHandle
         return null;
     }
 
-    private static WrapperPolicy determineRemoveFromWrapperPolicy(final OneToManyAssociation otma) {
-        final CollectionRemoveFromFacet removeFromFacet = otma.getFacet(CollectionRemoveFromFacet.class);
-
-        final PostsEventWithWrapperPolicy wrapperPolicyFacet = PostsEventWithWrapperPolicy.Util.getWrapperPolicyFacet(removeFromFacet);
-        return wrapperPolicyFacet != null ? wrapperPolicyFacet.getWrapperPolicy() : WrapperPolicy.ENFORCE_RULES;
-    }
-
     // /////////////////////////////////////////////////////////////////
     // action
     // /////////////////////////////////////////////////////////////////
@@ -581,7 +550,7 @@ public class DomainObjectInvocationHandler<T> extends DelegatingInvocationHandle
         final InteractionResult interactionResult = noa.isProposedArgumentSetValid(targetAdapter, argAdapters).getInteractionResult();
         notifyListenersAndVetoIfRequired(interactionResult);
 
-        if (getExecutionMode() == ExecutionMode.EXECUTE) {
+        if (getExecutionMode().shouldExecute()) {
             final ObjectAdapter actionReturnNO = noa.execute(targetAdapter, argAdapters);
             return AdapterUtils.unwrap(actionReturnNO);
         }

http://git-wip-us.apache.org/repos/asf/isis/blob/c2b250f0/example/application/quickstart_wicket_restful_jdo/dom/src/main/java/dom/todo/ToDoItem.java
----------------------------------------------------------------------
diff --git a/example/application/quickstart_wicket_restful_jdo/dom/src/main/java/dom/todo/ToDoItem.java b/example/application/quickstart_wicket_restful_jdo/dom/src/main/java/dom/todo/ToDoItem.java
index 6f81049..2dae290 100644
--- a/example/application/quickstart_wicket_restful_jdo/dom/src/main/java/dom/todo/ToDoItem.java
+++ b/example/application/quickstart_wicket_restful_jdo/dom/src/main/java/dom/todo/ToDoItem.java
@@ -50,6 +50,7 @@ import org.apache.isis.applib.services.eventbus.EventBusService;
 import org.apache.isis.applib.services.eventbus.PropertyChangedEvent;
 import org.apache.isis.applib.services.scratchpad.Scratchpad;
 import org.apache.isis.applib.services.wrapper.WrapperFactory;
+import org.apache.isis.applib.services.wrapper.WrapperFactory.ExecutionMode;
 import org.apache.isis.applib.util.ObjectContracts;
 import org.apache.isis.applib.util.TitleBuffer;
 import org.apache.isis.applib.value.Blob;
@@ -487,8 +488,8 @@ public class ToDoItem implements Comparable<ToDoItem> {
     @javax.jdo.annotations.Element(column="dependentId")
     private SortedSet<ToDoItem> dependencies = new TreeSet<ToDoItem>();
 
-    @PostsCollectionAddedToEvent(wrapperPolicy=WrapperPolicy.SKIP_RULES)
-    @PostsCollectionRemovedFromEvent(wrapperPolicy=WrapperPolicy.SKIP_RULES)
+    @PostsCollectionAddedToEvent
+    @PostsCollectionRemovedFromEvent
     @SortedBy(DependenciesComparator.class)
     public SortedSet<ToDoItem> getDependencies() {
         return dependencies;
@@ -511,8 +512,8 @@ public class ToDoItem implements Comparable<ToDoItem> {
             final ToDoItem toDoItem) {
     	// By wrapping the call, Isis will detect that the collection is modified 
     	// and it will automatically send a CollectionAddedToEvent to the Event Bus.
-    	// See ToDoItemSubscriptions.
-        wrapperFactory.wrap(this).addToDependencies(toDoItem);
+    	// ToDoItemSubscriptions is a demo subscriber to this event
+        wrapperFactory.wrapSkipRules(this).addToDependencies(toDoItem);
         return this;
     }
     public List<ToDoItem> autoComplete0Add(final @MinLength(2) String search) {
@@ -544,8 +545,8 @@ public class ToDoItem implements Comparable<ToDoItem> {
             final ToDoItem toDoItem) {
     	// By wrapping the call, Isis will detect that the collection is modified 
     	// and it will automatically send a CollectionRemovedFromEvent to the Event Bus.
-    	// See ToDoItemSubscriptions.
-        wrapperFactory.wrap(this).removeFromDependencies(toDoItem);
+        // ToDoItemSubscriptions is a demo subscriber to this event
+        wrapperFactory.wrapSkipRules(this).removeFromDependencies(toDoItem);
         return this;
     }
     // disable action dependent on state of object


[16/16] git commit: ISIS-550: refactored DomainObjectInvocationHandler and ImperativeFacets

Posted by da...@apache.org.
ISIS-550: refactored DomainObjectInvocationHandler and ImperativeFacets

Previously DOIH (that the WrapperFactory's wrapper proxies delegates to) was hard-coded to search for particular ImperativeFacets and act accordingly.
This has now been abstracted out into the concept of an Intent (enum defined in ImperativeFacet) which allows more precise control as to how to interpret any given method that is invoked through the wrapper .

In addition:
- split PostPropertyChangedEventFacet into two: PostsPropertyChangedEventSetterFacet and PostsPropertyChangedEventClearFacet, so that both can wrap an underlying *FacetViaMethod.
  This pattern is then consistent with the PostsCollectionFacets (though not the PostsActionInvokedEventFacet)
- (related to ISIS-769), have moved the setup of request-scoped services from the PersistenceSession#open and into IsisTransactionManager#startTransaction.  This is for symmetry with the #endTransaction.


Project: http://git-wip-us.apache.org/repos/asf/isis/repo
Commit: http://git-wip-us.apache.org/repos/asf/isis/commit/5f15fa74
Tree: http://git-wip-us.apache.org/repos/asf/isis/tree/5f15fa74
Diff: http://git-wip-us.apache.org/repos/asf/isis/diff/5f15fa74

Branch: refs/heads/master
Commit: 5f15fa74cb61ddd21040b9033af74e84cc838214
Parents: 6ba1b7c
Author: Dan Haywood <da...@haywood-associates.co.uk>
Authored: Sun May 11 18:41:24 2014 +0100
Committer: Dan Haywood <da...@haywood-associates.co.uk>
Committed: Sun May 11 18:41:24 2014 +0100

----------------------------------------------------------------------
 .../ObjectResolveAndObjectChangedEnhancer.java  |   2 +-
 .../tck/ObjectStoreContractTest_persist.java    |   9 ++
 .../integtestsupport/legacy/AbstractTest.java   |  16 +-
 .../legacy/ObjectImmutableTest.java             |  10 +-
 .../core/metamodel/facets/ImperativeFacet.java  |  72 ++++++++-
 .../metamodel/facets/ImperativeFacetUtils.java  |   2 +-
 .../PostsPropertyChangedEventClearFacet.java    |  48 ++++++
 ...sPropertyChangedEventClearFacetAbstract.java |  43 +++++
 .../event/PostsPropertyChangedEventFacet.java   |  73 ---------
 .../PostsPropertyChangedEventFacetAbstract.java |  47 ------
 .../PostsPropertyChangedEventSetterFacet.java   |  47 ++++++
 ...PropertyChangedEventSetterFacetAbstract.java |  43 +++++
 .../facets/properties/event/Utils.java          |  59 +++++++
 .../dflt/ObjectSpecificationDefault.java        |  18 ++-
 .../method/ActionDefaultsFacetViaMethod.java    |   6 +
 .../invoke/ActionInvocationFacetViaMethod.java  |   6 +
 .../method/ActionValidationFacetViaMethod.java  |   5 +
 .../CollectionAccessorFacetViaAccessor.java     |   6 +
 .../clear/CollectionClearFacetViaAccessor.java  |   6 +
 .../clear/CollectionClearFacetViaMethod.java    |   6 +
 .../modify/CollectionAddToFacetViaAccessor.java |   5 +
 .../modify/CollectionAddToFacetViaMethod.java   |   5 +
 .../CollectionRemoveFromFacetViaAccessor.java   |   6 +
 .../CollectionRemoveFromFacetViaMethod.java     |   6 +
 .../CollectionValidateAddToFacetViaMethod.java  |   6 +
 ...lectionValidateRemoveFromFacetViaMethod.java |   6 +
 .../staticmethod/DescribedAsFacetViaMethod.java |   6 +
 .../DisableForSessionFacetViaMethod.java        |   6 +
 .../method/DisableForContextFacetViaMethod.java |   6 +
 .../HideForSessionFacetViaMethod.java           |   6 +
 .../method/HideForContextFacetViaMethod.java    |   6 +
 .../named/staticmethod/NamedFacetViaMethod.java |   6 +
 .../create/CreatedCallbackFacetViaMethod.java   |   6 +
 .../load/LoadedCallbackFacetViaMethod.java      |   5 +
 .../load/LoadingCallbackFacetViaMethod.java     |   6 +
 .../PersistedCallbackFacetViaMethod.java        |   6 +
 .../PersistingCallbackFacetViaMethod.java       |   6 +
 .../remove/RemovedCallbackFacetViaMethod.java   |   6 +
 .../remove/RemovingCallbackFacetViaMethod.java  |   6 +
 .../update/UpdatedCallbackFacetViaMethod.java   |   6 +
 .../update/UpdatingCallbackFacetViaMethod.java  |   6 +
 .../method/ClearDirtyObjectFacetViaMethod.java  |   6 +
 .../method/IsDirtyObjectFacetViaMethod.java     |   6 +
 .../method/MarkDirtyObjectFacetViaMethod.java   |   6 +
 .../DisabledObjectFacetViaDisabledMethod.java   |   6 +
 .../object/title/TitleFacetViaTitleMethod.java  |   6 +
 .../title/TitleFacetViaToStringMethod.java      |   6 +
 .../ValidateObjectFacetViaValidateMethod.java   |   6 +
 ...tionParameterAutoCompleteFacetViaMethod.java |   6 +
 .../method/ActionChoicesFacetViaMethod.java     |   5 +
 .../ActionParameterChoicesFacetViaMethod.java   |   6 +
 .../ActionParameterDefaultsFacetViaMethod.java  |   6 +
 .../PropertyAccessorFacetViaAccessor.java       |   6 +
 .../PropertyAutoCompleteFacetViaMethod.java     |   6 +
 .../method/PropertyChoicesFacetViaMethod.java   |   6 +
 .../method/PropertyDefaultFacetViaMethod.java   |   6 +
 .../facets/properties/event/Helper.java         |  48 ++++++
 ...pertyChangedEventAnnotationFacetFactory.java |  38 ++---
 ...ropertyChangedEventClearFacetAnnotation.java | 118 ++++++++++++++
 ...ostsPropertyChangedEventFacetAnnotation.java | 157 -------------------
 ...opertyChangedEventSetterFacetAnnotation.java | 117 ++++++++++++++
 .../PropertyClearFacetViaClearMethod.java       |   6 +
 .../PropertyClearFacetViaSetterMethod.java      |   6 +
 ...pertyInitializationFacetViaSetterMethod.java |   7 +
 .../PropertySetterFacetViaModifyMethod.java     |   6 +
 .../PropertySetterFacetViaSetterMethod.java     |   6 +
 .../PropertyValidateFacetViaMethod.java         |   6 +
 .../facets/ImperativeFacetUtilsTest.java        |   4 +-
 ...ertyChangedEventFacet_UtilTest_newEvent.java |   6 +-
 .../eventbus/EventBusServiceDefault.java        |   3 +-
 .../system/persistence/PersistenceSession.java  |  77 ---------
 .../transaction/IsisTransactionManager.java     | 108 ++++++++++++-
 ...reTransactionManager_EndTransactionTest.java |   8 +-
 .../handlers/DomainObjectInvocationHandler.java |  57 +++----
 ...rapperFactoryAbstractTest_wrappedObject.java |   5 +-
 ...oryAbstractTest_wrappedObject_transient.java |   8 +-
 76 files changed, 1070 insertions(+), 457 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/isis/blob/5f15fa74/core/bytecode-cglib/src/main/java/org/apache/isis/core/bytecode/cglib/ObjectResolveAndObjectChangedEnhancer.java
----------------------------------------------------------------------
diff --git a/core/bytecode-cglib/src/main/java/org/apache/isis/core/bytecode/cglib/ObjectResolveAndObjectChangedEnhancer.java b/core/bytecode-cglib/src/main/java/org/apache/isis/core/bytecode/cglib/ObjectResolveAndObjectChangedEnhancer.java
index d5c68a7..a4ee0a6 100644
--- a/core/bytecode-cglib/src/main/java/org/apache/isis/core/bytecode/cglib/ObjectResolveAndObjectChangedEnhancer.java
+++ b/core/bytecode-cglib/src/main/java/org/apache/isis/core/bytecode/cglib/ObjectResolveAndObjectChangedEnhancer.java
@@ -68,7 +68,7 @@ public class ObjectResolveAndObjectChangedEnhancer extends ObjectResolveAndObjec
                     final ObjectSpecificationDefault targetObjSpec = getJavaSpecificationOfOwningClass(proxiedMethod);
                     final ObjectMember member = targetObjSpec.getMember(proxiedMethod);
 
-                    flags = ImperativeFacetUtils.getImperativeFacetFlags(member, proxiedMethod);
+                    flags = ImperativeFacet.Util.getFlags(member, proxiedMethod);
 
                     if (flags.impliesResolve()) {
                         objectResolver.resolve(proxied, member.getName());

http://git-wip-us.apache.org/repos/asf/isis/blob/5f15fa74/core/integtestsupport/src/main/java/org/apache/isis/core/integtestsupport/tck/ObjectStoreContractTest_persist.java
----------------------------------------------------------------------
diff --git a/core/integtestsupport/src/main/java/org/apache/isis/core/integtestsupport/tck/ObjectStoreContractTest_persist.java b/core/integtestsupport/src/main/java/org/apache/isis/core/integtestsupport/tck/ObjectStoreContractTest_persist.java
index 37606b2..a158b20 100644
--- a/core/integtestsupport/src/main/java/org/apache/isis/core/integtestsupport/tck/ObjectStoreContractTest_persist.java
+++ b/core/integtestsupport/src/main/java/org/apache/isis/core/integtestsupport/tck/ObjectStoreContractTest_persist.java
@@ -153,19 +153,28 @@ public abstract class ObjectStoreContractTest_persist {
     public void removeInstance() throws Exception {
 
         // given persisted
+        iswf.beginTran();
         resetPersistenceStore();
         ObjectAdapter adapter = iswf.persist(iswf.fixtures.smpl2);
         final RootOid oid = (RootOid) adapter.getOid();
+        iswf.commitTran();
+        
         iswf.bounceSystem();
 
         // when destroy
+        iswf.beginTran();
         adapter = iswf.reload(oid);
         
         SimpleEntity epv = (SimpleEntity) adapter.getObject();
         iswf.destroy(epv);
+        iswf.commitTran();
+
         iswf.bounceSystem();
 
         // then not found
+        iswf.beginTran();
         assertEquals(false, getStore().hasInstances(epvSpecification));
+        iswf.commitTran();
     }
 }
+

http://git-wip-us.apache.org/repos/asf/isis/blob/5f15fa74/core/integtestsupport/src/test/java/org/apache/isis/core/integtestsupport/legacy/AbstractTest.java
----------------------------------------------------------------------
diff --git a/core/integtestsupport/src/test/java/org/apache/isis/core/integtestsupport/legacy/AbstractTest.java b/core/integtestsupport/src/test/java/org/apache/isis/core/integtestsupport/legacy/AbstractTest.java
index 7f23be5..0406bdb 100644
--- a/core/integtestsupport/src/test/java/org/apache/isis/core/integtestsupport/legacy/AbstractTest.java
+++ b/core/integtestsupport/src/test/java/org/apache/isis/core/integtestsupport/legacy/AbstractTest.java
@@ -19,12 +19,16 @@
 
 package org.apache.isis.core.integtestsupport.legacy;
 
+import static org.hamcrest.CoreMatchers.is;
+import static org.junit.Assert.assertThat;
+
 import org.junit.After;
 import org.junit.Before;
 import org.junit.runner.RunWith;
 
 import org.apache.isis.applib.DomainObjectContainer;
 import org.apache.isis.applib.services.wrapper.WrapperFactory;
+import org.apache.isis.applib.services.wrapper.WrapperObject;
 import org.apache.isis.core.integtestsupport.legacy.sample.domain.Country;
 import org.apache.isis.core.integtestsupport.legacy.sample.domain.Customer;
 import org.apache.isis.core.integtestsupport.legacy.sample.domain.Product;
@@ -47,12 +51,12 @@ public abstract class AbstractTest {
     protected Customer custJsWO;
 
     protected Product product355DO;
-    protected Product product355VO;
+    protected Product product355WO;
 
     protected Product product850DO;
 
     protected Country countryGbrDO;
-    protected Country countryGbrVO;
+    protected Country countryGbrWO;
 
     protected Country countryUsaDO;
     protected Country countryAusDO;
@@ -68,17 +72,21 @@ public abstract class AbstractTest {
     public void setUp() {
 
         product355DO = productRepository.findByCode("355-40311");
-        product355VO = wrapperFactory.wrap(product355DO);
+        product355WO = wrapperFactory.wrap(product355DO);
         product850DO = productRepository.findByCode("850-18003");
 
         countryGbrDO = countryRepository.findByCode("GBR");
-        countryGbrVO = wrapperFactory.wrap(countryGbrDO);
+        countryGbrWO = wrapperFactory.wrap(countryGbrDO);
 
         countryUsaDO = countryRepository.findByCode("USA");
         countryAusDO = countryRepository.findByCode("AUS");
 
         custJsDO = customerRepository.findByName("Pawson");
         custJsWO = wrapperFactory.wrap(custJsDO);
+        
+        assertThat(product355WO instanceof WrapperObject, is(true));
+        assertThat(countryGbrWO instanceof WrapperObject, is(true));
+        assertThat(custJsWO instanceof WrapperObject, is(true));
     }
 
     @After

http://git-wip-us.apache.org/repos/asf/isis/blob/5f15fa74/core/integtestsupport/src/test/java/org/apache/isis/core/integtestsupport/legacy/ObjectImmutableTest.java
----------------------------------------------------------------------
diff --git a/core/integtestsupport/src/test/java/org/apache/isis/core/integtestsupport/legacy/ObjectImmutableTest.java b/core/integtestsupport/src/test/java/org/apache/isis/core/integtestsupport/legacy/ObjectImmutableTest.java
index 8addec2..e4ceb1d 100644
--- a/core/integtestsupport/src/test/java/org/apache/isis/core/integtestsupport/legacy/ObjectImmutableTest.java
+++ b/core/integtestsupport/src/test/java/org/apache/isis/core/integtestsupport/legacy/ObjectImmutableTest.java
@@ -35,7 +35,7 @@ public class ObjectImmutableTest extends AbstractTest {
     @Test
     public void settingValueOnImmutableObjectThrowsException() {
         try {
-            product355VO.setDescription("Changed");
+            product355WO.setDescription("Changed");
             fail("Should have thrown exception");
         } catch (final DisabledException ex) {
             assertThat(ex.getAdvisorClass(), classEqualTo(DisabledFacetForPropertyDerivedFromImmutable.class));
@@ -46,7 +46,7 @@ public class ObjectImmutableTest extends AbstractTest {
     @Test
     public void settingAssociationOnImmutableObjectThrowsException() {
         try {
-            product355VO.setPlaceOfManufacture(countryUsaDO);
+            product355WO.setPlaceOfManufacture(countryUsaDO);
             fail("Should have thrown exception");
         } catch (final DisabledException ex) {
             assertThat(ex.getAdvisorClass(), classEqualTo(DisabledFacetForPropertyDerivedFromImmutable.class));
@@ -57,7 +57,7 @@ public class ObjectImmutableTest extends AbstractTest {
     @Test
     public void addingToCollectionOnImmutableObjectThrowsException() {
         try {
-            product355VO.addToSimilarProducts(product850DO);
+            product355WO.addToSimilarProducts(product850DO);
             fail("Should have thrown exception");
         } catch (final DisabledException ex) {
             assertThat(ex.getAdvisorClass(), classEqualTo(DisabledFacetForCollectionDerivedFromImmutable.class));
@@ -71,7 +71,7 @@ public class ObjectImmutableTest extends AbstractTest {
                                                          // throws
         // ObjectPersistenceException
         try {
-            product355VO.removeFromSimilarProducts(product850DO);
+            product355WO.removeFromSimilarProducts(product850DO);
             fail("Should have thrown exception");
         } catch (final DisabledException ex) {
             assertThat(ex.getAdvisorClass(), classEqualTo(DisabledFacetForCollectionDerivedFromImmutable.class));
@@ -81,7 +81,7 @@ public class ObjectImmutableTest extends AbstractTest {
 
     @Test
     public void canInvokingOnImmutableObject() {
-        product355VO.foobar();
+        product355WO.foobar();
     }
 
 }

http://git-wip-us.apache.org/repos/asf/isis/blob/5f15fa74/core/metamodel/src/main/java/org/apache/isis/core/metamodel/facets/ImperativeFacet.java
----------------------------------------------------------------------
diff --git a/core/metamodel/src/main/java/org/apache/isis/core/metamodel/facets/ImperativeFacet.java b/core/metamodel/src/main/java/org/apache/isis/core/metamodel/facets/ImperativeFacet.java
index f702496..c56930f 100644
--- a/core/metamodel/src/main/java/org/apache/isis/core/metamodel/facets/ImperativeFacet.java
+++ b/core/metamodel/src/main/java/org/apache/isis/core/metamodel/facets/ImperativeFacet.java
@@ -22,9 +22,12 @@ package org.apache.isis.core.metamodel.facets;
 import java.lang.reflect.Method;
 import java.util.List;
 
+import com.google.common.collect.Lists;
+
 import org.apache.isis.applib.DomainObjectContainer;
 import org.apache.isis.applib.filter.Filter;
 import org.apache.isis.applib.filter.Filters;
+import org.apache.isis.applib.services.wrapper.WrapperFactory;
 import org.apache.isis.core.commons.lang.ObjectExtensions;
 import org.apache.isis.core.metamodel.facetapi.DecoratingFacet;
 import org.apache.isis.core.metamodel.facetapi.Facet;
@@ -71,6 +74,33 @@ public interface ImperativeFacet {
      */
     public List<Method> getMethods();
 
+    public static enum Intent {
+        CHECK_IF_HIDDEN,
+        CHECK_IF_DISABLED,
+        CHECK_IF_VALID,
+        ACCESSOR,
+        EXECUTE,
+        MODIFY_PROPERTY,
+        /**
+         * Modify property using modify/clear rather than simply using set.
+         */
+        MODIFY_PROPERTY_SUPPORTING, 
+        MODIFY_COLLECTION_ADD,
+        MODIFY_COLLECTION_REMOVE,
+        CHOICES_OR_AUTOCOMPLETE,
+        DEFAULTS, 
+        INITIALIZATION,
+        LIFECYCLE, 
+        UI_HINT
+    }
+    
+    /**
+     * The intent of this method, so that the {@link WrapperFactory} knows whether to delegate on or to reject.
+     * @param method - one of the methods returned from {@link #getMethods()}
+     */
+    public Intent getIntent(Method method);
+
+
     /**
      * For use by
      * {@link FacetHolder#getFacets(org.apache.isis.core.metamodel.facetapi.progmodel.facets.org.apache.isis.nof.arch.facets.Facet.Filter)}
@@ -78,7 +108,7 @@ public interface ImperativeFacet {
     public static Filter<Facet> FILTER = new Filter<Facet>() {
         @Override
         public boolean accept(final Facet facet) {
-            return ImperativeFacetUtils.isImperativeFacet(facet);
+            return ImperativeFacet.Util.isImperativeFacet(facet);
         }
     };
 
@@ -128,14 +158,14 @@ public interface ImperativeFacet {
             return getImperativeFacet(facet) != null;
         }
 
-        public static Flags getImperativeFacetFlags(final ObjectMember member, final Method method) {
+        public static Flags getFlags(final ObjectMember member, final Method method) {
             final Flags flags = new Flags();
             if (member == null) {
                 return flags;
             }
             final List<Facet> allFacets = member.getFacets(Filters.anyOfType(Facet.class));
             for (final Facet facet : allFacets) {
-                final ImperativeFacet imperativeFacet = ImperativeFacetUtils.getImperativeFacet(facet);
+                final ImperativeFacet imperativeFacet = ImperativeFacet.Util.getImperativeFacet(facet);
                 if (imperativeFacet == null) {
                     continue;
                 }
@@ -152,6 +182,40 @@ public interface ImperativeFacet {
             }
             return flags;
         }
+        
+        public static Intent getIntent(final ObjectMember member, final Method method) {
+            final List<Facet> allFacets = member.getFacets(Filters.anyOfType(Facet.class));
+            final List<ImperativeFacet> imperativeFacets = Lists.newArrayList();
+            for (final Facet facet : allFacets) {
+                final ImperativeFacet imperativeFacet = ImperativeFacet.Util.getImperativeFacet(facet);
+                if (imperativeFacet == null) {
+                    continue;
+                }
+                final List<Method> methods = imperativeFacet.getMethods();
+                if (!methods.contains(method)) {
+                    continue;
+                }
+                imperativeFacets.add(imperativeFacet);
+            }
+            switch(imperativeFacets.size()) {
+                case 0:
+                    break;
+                case 1:
+                    return imperativeFacets.get(0).getIntent(method);
+                default:
+                    Intent intentToReturn = null;
+                    for (ImperativeFacet imperativeFacet : imperativeFacets) {
+                        Intent intent = imperativeFacet.getIntent(method);
+                        if(intentToReturn == null) {
+                            intentToReturn = intent;
+                        } else if(intentToReturn != intent) {
+                            throw new IllegalArgumentException(member.getIdentifier().toClassAndNameIdentityString() +  ": more than one ImperativeFacet for method " + method.getName() + " , with inconsistent intents: " + imperativeFacets.toString());
+                        }
+                    }
+                    return intentToReturn;
+            }
+            throw new IllegalArgumentException(member.getIdentifier().toClassAndNameIdentityString() +  ": unable to determine intent of " + method.getName());
+        }
     }
 
     public static class Flags {
@@ -176,6 +240,4 @@ public interface ImperativeFacet {
         }
     }
 
-
-
 }

http://git-wip-us.apache.org/repos/asf/isis/blob/5f15fa74/core/metamodel/src/main/java/org/apache/isis/core/metamodel/facets/ImperativeFacetUtils.java
----------------------------------------------------------------------
diff --git a/core/metamodel/src/main/java/org/apache/isis/core/metamodel/facets/ImperativeFacetUtils.java b/core/metamodel/src/main/java/org/apache/isis/core/metamodel/facets/ImperativeFacetUtils.java
index 049ba3e..5fd8463 100644
--- a/core/metamodel/src/main/java/org/apache/isis/core/metamodel/facets/ImperativeFacetUtils.java
+++ b/core/metamodel/src/main/java/org/apache/isis/core/metamodel/facets/ImperativeFacetUtils.java
@@ -52,7 +52,7 @@ public final class ImperativeFacetUtils {
      */
     @Deprecated
     public static ImperativeFacet.Flags getImperativeFacetFlags(final ObjectMember member, final Method method) {
-        return ImperativeFacet.Util.getImperativeFacetFlags(member, method);
+        return ImperativeFacet.Util.getFlags(member, method);
     }
 
 }

http://git-wip-us.apache.org/repos/asf/isis/blob/5f15fa74/core/metamodel/src/main/java/org/apache/isis/core/metamodel/facets/properties/event/PostsPropertyChangedEventClearFacet.java
----------------------------------------------------------------------
diff --git a/core/metamodel/src/main/java/org/apache/isis/core/metamodel/facets/properties/event/PostsPropertyChangedEventClearFacet.java b/core/metamodel/src/main/java/org/apache/isis/core/metamodel/facets/properties/event/PostsPropertyChangedEventClearFacet.java
new file mode 100644
index 0000000..e9a0b31
--- /dev/null
+++ b/core/metamodel/src/main/java/org/apache/isis/core/metamodel/facets/properties/event/PostsPropertyChangedEventClearFacet.java
@@ -0,0 +1,48 @@
+/*
+ *  Licensed to the Apache Software Foundation (ASF) under one
+ *  or more contributor license agreements.  See the NOTICE file
+ *  distributed with this work for additional information
+ *  regarding copyright ownership.  The ASF licenses this file
+ *  to you under the Apache License, Version 2.0 (the
+ *  "License"); you may not use this file except in compliance
+ *  with the License.  You may obtain a copy of the License at
+ *
+ *        http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *  Unless required by applicable law or agreed to in writing,
+ *  software distributed under the License is distributed on an
+ *  "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ *  KIND, either express or implied.  See the License for the
+ *  specific language governing permissions and limitations
+ *  under the License.
+ */
+
+package org.apache.isis.core.metamodel.facets.properties.event;
+
+import java.lang.reflect.InvocationTargetException;
+
+import org.apache.isis.applib.Identifier;
+import org.apache.isis.applib.services.eventbus.EventBusService;
+import org.apache.isis.applib.services.eventbus.PropertyChangedEvent;
+import org.apache.isis.core.metamodel.facets.SingleValueFacet;
+import org.apache.isis.core.metamodel.facets.properties.modify.PropertyClearFacet;
+
+/**
+ * Indicates that (the specified subclass of) {@link PropertyChangedEvent} should be posted to the
+ * {@link EventBusService}.
+ */
+public interface PostsPropertyChangedEventClearFacet 
+        extends SingleValueFacet<Class<? extends PropertyChangedEvent<?,?>>>, PropertyClearFacet {
+
+    public static class Util {
+        private Util(){}
+        public static <S,T> PropertyChangedEvent<S,T> newEvent(
+                final Class<? extends PropertyChangedEvent<S, T>> type, 
+                final S source, 
+                final Identifier identifier,
+                final T oldValue, 
+                final T newValue) throws NoSuchMethodException, SecurityException, InstantiationException, IllegalAccessException, IllegalArgumentException, InvocationTargetException  {
+            return org.apache.isis.core.metamodel.facets.properties.event.Utils.newEvent(type, source, identifier, oldValue, newValue);
+        }
+    }
+}

http://git-wip-us.apache.org/repos/asf/isis/blob/5f15fa74/core/metamodel/src/main/java/org/apache/isis/core/metamodel/facets/properties/event/PostsPropertyChangedEventClearFacetAbstract.java
----------------------------------------------------------------------
diff --git a/core/metamodel/src/main/java/org/apache/isis/core/metamodel/facets/properties/event/PostsPropertyChangedEventClearFacetAbstract.java b/core/metamodel/src/main/java/org/apache/isis/core/metamodel/facets/properties/event/PostsPropertyChangedEventClearFacetAbstract.java
new file mode 100644
index 0000000..786b573
--- /dev/null
+++ b/core/metamodel/src/main/java/org/apache/isis/core/metamodel/facets/properties/event/PostsPropertyChangedEventClearFacetAbstract.java
@@ -0,0 +1,43 @@
+/*
+ *  Licensed to the Apache Software Foundation (ASF) under one
+ *  or more contributor license agreements.  See the NOTICE file
+ *  distributed with this work for additional information
+ *  regarding copyright ownership.  The ASF licenses this file
+ *  to you under the Apache License, Version 2.0 (the
+ *  "License"); you may not use this file except in compliance
+ *  with the License.  You may obtain a copy of the License at
+ *
+ *        http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *  Unless required by applicable law or agreed to in writing,
+ *  software distributed under the License is distributed on an
+ *  "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ *  KIND, either express or implied.  See the License for the
+ *  specific language governing permissions and limitations
+ *  under the License.
+ */
+
+package org.apache.isis.core.metamodel.facets.properties.event;
+
+import org.apache.isis.applib.services.eventbus.PropertyChangedEvent;
+import org.apache.isis.core.metamodel.facetapi.Facet;
+import org.apache.isis.core.metamodel.facetapi.FacetHolder;
+import org.apache.isis.core.metamodel.facetapi.MultiTypedFacet;
+import org.apache.isis.core.metamodel.facets.SingleValueFacetAbstract;
+import org.apache.isis.core.metamodel.facets.properties.modify.PropertyClearFacet;
+
+public abstract class PostsPropertyChangedEventClearFacetAbstract 
+        extends SingleValueFacetAbstract<Class<? extends PropertyChangedEvent<?,?>>> 
+        implements PostsPropertyChangedEventClearFacet, MultiTypedFacet {
+
+    public static Class<? extends Facet> type() {
+        return PropertyClearFacet.class;
+    }
+
+    public PostsPropertyChangedEventClearFacetAbstract(
+            final Class<? extends PropertyChangedEvent<?,?>> changedEventType, 
+            final FacetHolder holder) {
+        super(type(), changedEventType, holder);
+    }
+
+}

http://git-wip-us.apache.org/repos/asf/isis/blob/5f15fa74/core/metamodel/src/main/java/org/apache/isis/core/metamodel/facets/properties/event/PostsPropertyChangedEventFacet.java
----------------------------------------------------------------------
diff --git a/core/metamodel/src/main/java/org/apache/isis/core/metamodel/facets/properties/event/PostsPropertyChangedEventFacet.java b/core/metamodel/src/main/java/org/apache/isis/core/metamodel/facets/properties/event/PostsPropertyChangedEventFacet.java
deleted file mode 100644
index a7d3fd5..0000000
--- a/core/metamodel/src/main/java/org/apache/isis/core/metamodel/facets/properties/event/PostsPropertyChangedEventFacet.java
+++ /dev/null
@@ -1,73 +0,0 @@
-/*
- *  Licensed to the Apache Software Foundation (ASF) under one
- *  or more contributor license agreements.  See the NOTICE file
- *  distributed with this work for additional information
- *  regarding copyright ownership.  The ASF licenses this file
- *  to you under the Apache License, Version 2.0 (the
- *  "License"); you may not use this file except in compliance
- *  with the License.  You may obtain a copy of the License at
- *
- *        http://www.apache.org/licenses/LICENSE-2.0
- *
- *  Unless required by applicable law or agreed to in writing,
- *  software distributed under the License is distributed on an
- *  "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- *  KIND, either express or implied.  See the License for the
- *  specific language governing permissions and limitations
- *  under the License.
- */
-
-package org.apache.isis.core.metamodel.facets.properties.event;
-
-import java.lang.reflect.Constructor;
-import java.lang.reflect.InvocationTargetException;
-
-import org.apache.isis.applib.Identifier;
-import org.apache.isis.applib.services.eventbus.ActionInvokedEvent;
-import org.apache.isis.applib.services.eventbus.EventBusService;
-import org.apache.isis.applib.services.eventbus.PropertyChangedEvent;
-import org.apache.isis.core.metamodel.facetapi.MultiTypedFacet;
-import org.apache.isis.core.metamodel.facets.SingleValueFacet;
-import org.apache.isis.core.metamodel.facets.properties.modify.PropertyClearFacet;
-import org.apache.isis.core.metamodel.facets.properties.modify.PropertySetterFacet;
-
-/**
- * Indicates that (the specified subclass of) {@link PropertyChangedEvent} should be posted to the
- * {@link EventBusService}.
- */
-public interface PostsPropertyChangedEventFacet extends SingleValueFacet<Class<? extends PropertyChangedEvent<?,?>>>, PropertyClearFacet, PropertySetterFacet, MultiTypedFacet {
-
-    public static class Util {
-        private Util(){}
-        @SuppressWarnings("unchecked")
-        public static <S,T> PropertyChangedEvent<S,T> newEvent(
-                final Class<? extends PropertyChangedEvent<S, T>> type, 
-                final S source, 
-                final Identifier identifier,
-                final T oldValue, 
-                final T newValue) throws NoSuchMethodException, SecurityException, InstantiationException, IllegalAccessException, IllegalArgumentException, InvocationTargetException  {
-            final Constructor<?>[] constructors = type.getConstructors();
-            for (final Constructor<?> constructor : constructors) {
-                final Class<?>[] parameterTypes = constructor.getParameterTypes();
-                if(parameterTypes.length != 4) {
-                    continue;
-                }
-                if(!parameterTypes[0].isAssignableFrom(source.getClass())) {
-                    continue;
-                }
-                if(!parameterTypes[1].isAssignableFrom(Identifier.class)) {
-                    continue;
-                }
-                if(oldValue != null && !parameterTypes[2].isAssignableFrom(oldValue.getClass())) {
-                    continue;
-                }
-                if(newValue != null && !parameterTypes[3].isAssignableFrom(newValue.getClass())) {
-                    continue;
-                }
-                final Object event = constructor.newInstance(source, identifier, oldValue, newValue);
-                return (PropertyChangedEvent<S, T>) event;
-            }
-            throw new NoSuchMethodException(type.getName()+".<init>(? super " + source.getClass().getName() + ", " + Identifier.class.getName() + ", java.lang.Object, java.lang.Object)");
-        }
-    }
-}

http://git-wip-us.apache.org/repos/asf/isis/blob/5f15fa74/core/metamodel/src/main/java/org/apache/isis/core/metamodel/facets/properties/event/PostsPropertyChangedEventFacetAbstract.java
----------------------------------------------------------------------
diff --git a/core/metamodel/src/main/java/org/apache/isis/core/metamodel/facets/properties/event/PostsPropertyChangedEventFacetAbstract.java b/core/metamodel/src/main/java/org/apache/isis/core/metamodel/facets/properties/event/PostsPropertyChangedEventFacetAbstract.java
deleted file mode 100644
index 968d4ae..0000000
--- a/core/metamodel/src/main/java/org/apache/isis/core/metamodel/facets/properties/event/PostsPropertyChangedEventFacetAbstract.java
+++ /dev/null
@@ -1,47 +0,0 @@
-/*
- *  Licensed to the Apache Software Foundation (ASF) under one
- *  or more contributor license agreements.  See the NOTICE file
- *  distributed with this work for additional information
- *  regarding copyright ownership.  The ASF licenses this file
- *  to you under the Apache License, Version 2.0 (the
- *  "License"); you may not use this file except in compliance
- *  with the License.  You may obtain a copy of the License at
- *
- *        http://www.apache.org/licenses/LICENSE-2.0
- *
- *  Unless required by applicable law or agreed to in writing,
- *  software distributed under the License is distributed on an
- *  "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- *  KIND, either express or implied.  See the License for the
- *  specific language governing permissions and limitations
- *  under the License.
- */
-
-package org.apache.isis.core.metamodel.facets.properties.event;
-
-import java.lang.reflect.Constructor;
-import java.lang.reflect.InvocationTargetException;
-
-import org.apache.isis.applib.Identifier;
-import org.apache.isis.applib.services.eventbus.PropertyChangedEvent;
-import org.apache.isis.core.metamodel.facetapi.Facet;
-import org.apache.isis.core.metamodel.facetapi.FacetHolder;
-import org.apache.isis.core.metamodel.facets.SingleValueFacetAbstract;
-
-public abstract class PostsPropertyChangedEventFacetAbstract 
-        extends SingleValueFacetAbstract<Class<? extends PropertyChangedEvent<?,?>>> 
-        implements PostsPropertyChangedEventFacet {
-
-    public static Class<? extends Facet> type() {
-        // different implementation to PostsCollectionAddToEventFacet (for example) because this facet wraps
-        // multiple facets and so we cannot use the setUnderlyingFacet capability.
-        return PostsPropertyChangedEventFacet.class;
-    }
-
-    public PostsPropertyChangedEventFacetAbstract(
-            final Class<? extends PropertyChangedEvent<?,?>> changedEventType, 
-            final FacetHolder holder) {
-        super(type(), changedEventType, holder);
-    }
-
-}

http://git-wip-us.apache.org/repos/asf/isis/blob/5f15fa74/core/metamodel/src/main/java/org/apache/isis/core/metamodel/facets/properties/event/PostsPropertyChangedEventSetterFacet.java
----------------------------------------------------------------------
diff --git a/core/metamodel/src/main/java/org/apache/isis/core/metamodel/facets/properties/event/PostsPropertyChangedEventSetterFacet.java b/core/metamodel/src/main/java/org/apache/isis/core/metamodel/facets/properties/event/PostsPropertyChangedEventSetterFacet.java
new file mode 100644
index 0000000..c40581a
--- /dev/null
+++ b/core/metamodel/src/main/java/org/apache/isis/core/metamodel/facets/properties/event/PostsPropertyChangedEventSetterFacet.java
@@ -0,0 +1,47 @@
+/*
+ *  Licensed to the Apache Software Foundation (ASF) under one
+ *  or more contributor license agreements.  See the NOTICE file
+ *  distributed with this work for additional information
+ *  regarding copyright ownership.  The ASF licenses this file
+ *  to you under the Apache License, Version 2.0 (the
+ *  "License"); you may not use this file except in compliance
+ *  with the License.  You may obtain a copy of the License at
+ *
+ *        http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *  Unless required by applicable law or agreed to in writing,
+ *  software distributed under the License is distributed on an
+ *  "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ *  KIND, either express or implied.  See the License for the
+ *  specific language governing permissions and limitations
+ *  under the License.
+ */
+
+package org.apache.isis.core.metamodel.facets.properties.event;
+
+import java.lang.reflect.InvocationTargetException;
+
+import org.apache.isis.applib.Identifier;
+import org.apache.isis.applib.services.eventbus.EventBusService;
+import org.apache.isis.applib.services.eventbus.PropertyChangedEvent;
+import org.apache.isis.core.metamodel.facets.SingleValueFacet;
+import org.apache.isis.core.metamodel.facets.properties.modify.PropertySetterFacet;
+
+/**
+ * Indicates that (the specified subclass of) {@link PropertyChangedEvent} should be posted to the
+ * {@link EventBusService}.
+ */
+public interface PostsPropertyChangedEventSetterFacet extends SingleValueFacet<Class<? extends PropertyChangedEvent<?,?>>>, PropertySetterFacet {
+
+    public static class Util {
+        private Util(){}
+        public static <S,T> PropertyChangedEvent<S,T> newEvent(
+                final Class<? extends PropertyChangedEvent<S, T>> type, 
+                final S source, 
+                final Identifier identifier,
+                final T oldValue, 
+                final T newValue) throws NoSuchMethodException, SecurityException, InstantiationException, IllegalAccessException, IllegalArgumentException, InvocationTargetException  {
+            return org.apache.isis.core.metamodel.facets.properties.event.Utils.newEvent(type, source, identifier, oldValue, newValue);
+        }
+    }
+}

http://git-wip-us.apache.org/repos/asf/isis/blob/5f15fa74/core/metamodel/src/main/java/org/apache/isis/core/metamodel/facets/properties/event/PostsPropertyChangedEventSetterFacetAbstract.java
----------------------------------------------------------------------
diff --git a/core/metamodel/src/main/java/org/apache/isis/core/metamodel/facets/properties/event/PostsPropertyChangedEventSetterFacetAbstract.java b/core/metamodel/src/main/java/org/apache/isis/core/metamodel/facets/properties/event/PostsPropertyChangedEventSetterFacetAbstract.java
new file mode 100644
index 0000000..b8afca3
--- /dev/null
+++ b/core/metamodel/src/main/java/org/apache/isis/core/metamodel/facets/properties/event/PostsPropertyChangedEventSetterFacetAbstract.java
@@ -0,0 +1,43 @@
+/*
+ *  Licensed to the Apache Software Foundation (ASF) under one
+ *  or more contributor license agreements.  See the NOTICE file
+ *  distributed with this work for additional information
+ *  regarding copyright ownership.  The ASF licenses this file
+ *  to you under the Apache License, Version 2.0 (the
+ *  "License"); you may not use this file except in compliance
+ *  with the License.  You may obtain a copy of the License at
+ *
+ *        http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *  Unless required by applicable law or agreed to in writing,
+ *  software distributed under the License is distributed on an
+ *  "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ *  KIND, either express or implied.  See the License for the
+ *  specific language governing permissions and limitations
+ *  under the License.
+ */
+
+package org.apache.isis.core.metamodel.facets.properties.event;
+
+import org.apache.isis.applib.services.eventbus.PropertyChangedEvent;
+import org.apache.isis.core.metamodel.facetapi.Facet;
+import org.apache.isis.core.metamodel.facetapi.FacetHolder;
+import org.apache.isis.core.metamodel.facetapi.MultiTypedFacet;
+import org.apache.isis.core.metamodel.facets.SingleValueFacetAbstract;
+import org.apache.isis.core.metamodel.facets.properties.modify.PropertySetterFacet;
+
+public abstract class PostsPropertyChangedEventSetterFacetAbstract 
+        extends SingleValueFacetAbstract<Class<? extends PropertyChangedEvent<?,?>>> 
+        implements PostsPropertyChangedEventSetterFacet, MultiTypedFacet {
+
+    public static Class<? extends Facet> type() {
+        return PropertySetterFacet.class;
+    }
+
+    public PostsPropertyChangedEventSetterFacetAbstract(
+            final Class<? extends PropertyChangedEvent<?,?>> changedEventType, 
+            final FacetHolder holder) {
+        super(type(), changedEventType, holder);
+    }
+
+}

http://git-wip-us.apache.org/repos/asf/isis/blob/5f15fa74/core/metamodel/src/main/java/org/apache/isis/core/metamodel/facets/properties/event/Utils.java
----------------------------------------------------------------------
diff --git a/core/metamodel/src/main/java/org/apache/isis/core/metamodel/facets/properties/event/Utils.java b/core/metamodel/src/main/java/org/apache/isis/core/metamodel/facets/properties/event/Utils.java
new file mode 100644
index 0000000..b29420f
--- /dev/null
+++ b/core/metamodel/src/main/java/org/apache/isis/core/metamodel/facets/properties/event/Utils.java
@@ -0,0 +1,59 @@
+/*
+ *  Licensed to the Apache Software Foundation (ASF) under one
+ *  or more contributor license agreements.  See the NOTICE file
+ *  distributed with this work for additional information
+ *  regarding copyright ownership.  The ASF licenses this file
+ *  to you under the Apache License, Version 2.0 (the
+ *  "License"); you may not use this file except in compliance
+ *  with the License.  You may obtain a copy of the License at
+ *
+ *        http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *  Unless required by applicable law or agreed to in writing,
+ *  software distributed under the License is distributed on an
+ *  "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ *  KIND, either express or implied.  See the License for the
+ *  specific language governing permissions and limitations
+ *  under the License.
+ */
+package org.apache.isis.core.metamodel.facets.properties.event;
+
+import java.lang.reflect.Constructor;
+import java.lang.reflect.InvocationTargetException;
+
+import org.apache.isis.applib.Identifier;
+import org.apache.isis.applib.services.eventbus.PropertyChangedEvent;
+
+class Utils {
+    private Utils(){}
+    @SuppressWarnings("unchecked")
+    public static <S,T> PropertyChangedEvent<S,T> newEvent(
+            final Class<? extends PropertyChangedEvent<S, T>> type, 
+            final S source, 
+            final Identifier identifier,
+            final T oldValue, 
+            final T newValue) throws NoSuchMethodException, SecurityException, InstantiationException, IllegalAccessException, IllegalArgumentException, InvocationTargetException  {
+        final Constructor<?>[] constructors = type.getConstructors();
+        for (final Constructor<?> constructor : constructors) {
+            final Class<?>[] parameterTypes = constructor.getParameterTypes();
+            if(parameterTypes.length != 4) {
+                continue;
+            }
+            if(!parameterTypes[0].isAssignableFrom(source.getClass())) {
+                continue;
+            }
+            if(!parameterTypes[1].isAssignableFrom(Identifier.class)) {
+                continue;
+            }
+            if(oldValue != null && !parameterTypes[2].isAssignableFrom(oldValue.getClass())) {
+                continue;
+            }
+            if(newValue != null && !parameterTypes[3].isAssignableFrom(newValue.getClass())) {
+                continue;
+            }
+            final Object event = constructor.newInstance(source, identifier, oldValue, newValue);
+            return (PropertyChangedEvent<S, T>) event;
+        }
+        throw new NoSuchMethodException(type.getName()+".<init>(? super " + source.getClass().getName() + ", " + Identifier.class.getName() + ", java.lang.Object, java.lang.Object)");
+    }
+}
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/isis/blob/5f15fa74/core/metamodel/src/main/java/org/apache/isis/core/metamodel/specloader/specimpl/dflt/ObjectSpecificationDefault.java
----------------------------------------------------------------------
diff --git a/core/metamodel/src/main/java/org/apache/isis/core/metamodel/specloader/specimpl/dflt/ObjectSpecificationDefault.java b/core/metamodel/src/main/java/org/apache/isis/core/metamodel/specloader/specimpl/dflt/ObjectSpecificationDefault.java
index 72fb21c..dd2073d 100644
--- a/core/metamodel/src/main/java/org/apache/isis/core/metamodel/specloader/specimpl/dflt/ObjectSpecificationDefault.java
+++ b/core/metamodel/src/main/java/org/apache/isis/core/metamodel/specloader/specimpl/dflt/ObjectSpecificationDefault.java
@@ -97,7 +97,7 @@ public class ObjectSpecificationDefault extends ObjectSpecificationAbstract impl
      * Lazily built by {@link #getMember(Method)}.
      */
     private Map<Method, ObjectMember> membersByMethod = null;
-
+    
     private final IntrospectionContext introspectionContext;
     private final CreateObjectContext createObjectContext;
 
@@ -425,14 +425,18 @@ public class ObjectSpecificationDefault extends ObjectSpecificationAbstract impl
 
     public ObjectMember getMember(final Method method) {
         if (membersByMethod == null) {
-            final HashMap<Method, ObjectMember> membersByMethod = Maps.newHashMap();
-            cataloguePropertiesAndCollections(membersByMethod);
-            catalogueActions(membersByMethod);
-            this.membersByMethod = membersByMethod;
+            this.membersByMethod = catalogueMembers();
         }
         return membersByMethod.get(method);
     }
 
+    private HashMap<Method, ObjectMember> catalogueMembers() {
+        final HashMap<Method, ObjectMember> membersByMethod = Maps.newHashMap();
+        cataloguePropertiesAndCollections(membersByMethod);
+        catalogueActions(membersByMethod);
+        return membersByMethod;
+    }
+    
     private void cataloguePropertiesAndCollections(final Map<Method, ObjectMember> membersByMethod) {
         final Filter<ObjectAssociation> noop = Filters.anyOfType(ObjectAssociation.class);
         final List<ObjectAssociation> fields = getAssociations(Contributed.EXCLUDED, noop);
@@ -440,7 +444,7 @@ public class ObjectSpecificationDefault extends ObjectSpecificationAbstract impl
             final ObjectAssociation field = fields.get(i);
             final List<Facet> facets = field.getFacets(ImperativeFacet.FILTER);
             for (final Facet facet : facets) {
-                final ImperativeFacet imperativeFacet = ImperativeFacetUtils.getImperativeFacet(facet);
+                final ImperativeFacet imperativeFacet = ImperativeFacet.Util.getImperativeFacet(facet);
                 for (final Method imperativeFacetMethod : imperativeFacet.getMethods()) {
                     membersByMethod.put(imperativeFacetMethod, field);
                 }
@@ -454,7 +458,7 @@ public class ObjectSpecificationDefault extends ObjectSpecificationAbstract impl
             final ObjectAction userAction = userActions.get(i);
             final List<Facet> facets = userAction.getFacets(ImperativeFacet.FILTER);
             for (final Facet facet : facets) {
-                final ImperativeFacet imperativeFacet = ImperativeFacetUtils.getImperativeFacet(facet);
+                final ImperativeFacet imperativeFacet = ImperativeFacet.Util.getImperativeFacet(facet);
                 for (final Method imperativeFacetMethod : imperativeFacet.getMethods()) {
                     membersByMethod.put(imperativeFacetMethod, userAction);
                 }

http://git-wip-us.apache.org/repos/asf/isis/blob/5f15fa74/core/metamodel/src/main/java/org/apache/isis/core/progmodel/facets/actions/defaults/method/ActionDefaultsFacetViaMethod.java
----------------------------------------------------------------------
diff --git a/core/metamodel/src/main/java/org/apache/isis/core/progmodel/facets/actions/defaults/method/ActionDefaultsFacetViaMethod.java b/core/metamodel/src/main/java/org/apache/isis/core/progmodel/facets/actions/defaults/method/ActionDefaultsFacetViaMethod.java
index d73e76c..7753529 100644
--- a/core/metamodel/src/main/java/org/apache/isis/core/progmodel/facets/actions/defaults/method/ActionDefaultsFacetViaMethod.java
+++ b/core/metamodel/src/main/java/org/apache/isis/core/progmodel/facets/actions/defaults/method/ActionDefaultsFacetViaMethod.java
@@ -28,6 +28,7 @@ import org.apache.isis.core.metamodel.adapter.util.AdapterInvokeUtils;
 import org.apache.isis.core.metamodel.facetapi.Facet;
 import org.apache.isis.core.metamodel.facetapi.FacetHolder;
 import org.apache.isis.core.metamodel.facets.ImperativeFacet;
+import org.apache.isis.core.metamodel.facets.ImperativeFacet.Intent;
 import org.apache.isis.core.metamodel.facets.actions.defaults.ActionDefaultsFacetAbstract;
 import org.apache.isis.core.metamodel.facets.actions.invoke.ActionInvocationFacet;
 import org.apache.isis.core.progmodel.facets.actions.invoke.ActionInvocationFacetViaMethod;
@@ -67,6 +68,11 @@ public class ActionDefaultsFacetViaMethod extends ActionDefaultsFacetAbstract im
     }
 
     @Override
+    public Intent getIntent(final Method method) {
+        return Intent.DEFAULTS;
+    }
+
+    @Override
     public boolean impliesResolve() {
         return true;
     }

http://git-wip-us.apache.org/repos/asf/isis/blob/5f15fa74/core/metamodel/src/main/java/org/apache/isis/core/progmodel/facets/actions/invoke/ActionInvocationFacetViaMethod.java
----------------------------------------------------------------------
diff --git a/core/metamodel/src/main/java/org/apache/isis/core/progmodel/facets/actions/invoke/ActionInvocationFacetViaMethod.java b/core/metamodel/src/main/java/org/apache/isis/core/progmodel/facets/actions/invoke/ActionInvocationFacetViaMethod.java
index e9956d1..42ae7d5 100644
--- a/core/metamodel/src/main/java/org/apache/isis/core/progmodel/facets/actions/invoke/ActionInvocationFacetViaMethod.java
+++ b/core/metamodel/src/main/java/org/apache/isis/core/progmodel/facets/actions/invoke/ActionInvocationFacetViaMethod.java
@@ -47,6 +47,7 @@ import org.apache.isis.core.metamodel.adapter.ObjectAdapter;
 import org.apache.isis.core.metamodel.adapter.mgr.AdapterManager;
 import org.apache.isis.core.metamodel.facetapi.FacetHolder;
 import org.apache.isis.core.metamodel.facets.ImperativeFacet;
+import org.apache.isis.core.metamodel.facets.ImperativeFacet.Intent;
 import org.apache.isis.core.metamodel.facets.actions.command.CommandFacet;
 import org.apache.isis.core.metamodel.facets.actions.invoke.ActionInvocationFacet;
 import org.apache.isis.core.metamodel.facets.actions.invoke.ActionInvocationFacetAbstract;
@@ -100,6 +101,11 @@ public class ActionInvocationFacetViaMethod extends ActionInvocationFacetAbstrac
     }
 
     @Override
+    public Intent getIntent(final Method method) {
+        return Intent.EXECUTE;
+    }
+
+    @Override
     public ObjectSpecification getReturnType() {
         return returnType;
     }

http://git-wip-us.apache.org/repos/asf/isis/blob/5f15fa74/core/metamodel/src/main/java/org/apache/isis/core/progmodel/facets/actions/validate/method/ActionValidationFacetViaMethod.java
----------------------------------------------------------------------
diff --git a/core/metamodel/src/main/java/org/apache/isis/core/progmodel/facets/actions/validate/method/ActionValidationFacetViaMethod.java b/core/metamodel/src/main/java/org/apache/isis/core/progmodel/facets/actions/validate/method/ActionValidationFacetViaMethod.java
index 4c63bc1..f4769a2 100644
--- a/core/metamodel/src/main/java/org/apache/isis/core/progmodel/facets/actions/validate/method/ActionValidationFacetViaMethod.java
+++ b/core/metamodel/src/main/java/org/apache/isis/core/progmodel/facets/actions/validate/method/ActionValidationFacetViaMethod.java
@@ -48,6 +48,11 @@ public class ActionValidationFacetViaMethod extends ActionValidationFacetAbstrac
     }
 
     @Override
+    public Intent getIntent(final Method method) {
+        return Intent.CHECK_IF_VALID;
+    }
+
+    @Override
     public boolean impliesResolve() {
         return true;
     }

http://git-wip-us.apache.org/repos/asf/isis/blob/5f15fa74/core/metamodel/src/main/java/org/apache/isis/core/progmodel/facets/collections/accessor/CollectionAccessorFacetViaAccessor.java
----------------------------------------------------------------------
diff --git a/core/metamodel/src/main/java/org/apache/isis/core/progmodel/facets/collections/accessor/CollectionAccessorFacetViaAccessor.java b/core/metamodel/src/main/java/org/apache/isis/core/progmodel/facets/collections/accessor/CollectionAccessorFacetViaAccessor.java
index e0d9c2d..3417e35 100644
--- a/core/metamodel/src/main/java/org/apache/isis/core/progmodel/facets/collections/accessor/CollectionAccessorFacetViaAccessor.java
+++ b/core/metamodel/src/main/java/org/apache/isis/core/progmodel/facets/collections/accessor/CollectionAccessorFacetViaAccessor.java
@@ -28,6 +28,7 @@ import org.apache.isis.core.metamodel.adapter.ObjectAdapter;
 import org.apache.isis.core.metamodel.adapter.util.AdapterInvokeUtils;
 import org.apache.isis.core.metamodel.facetapi.FacetHolder;
 import org.apache.isis.core.metamodel.facets.ImperativeFacet;
+import org.apache.isis.core.metamodel.facets.ImperativeFacet.Intent;
 import org.apache.isis.core.metamodel.facets.accessor.PropertyOrCollectionAccessorFacetAbstract;
 
 public class CollectionAccessorFacetViaAccessor extends PropertyOrCollectionAccessorFacetAbstract implements ImperativeFacet {
@@ -49,6 +50,11 @@ public class CollectionAccessorFacetViaAccessor extends PropertyOrCollectionAcce
     }
 
     @Override
+    public Intent getIntent(final Method method) {
+        return Intent.ACCESSOR;
+    }
+
+    @Override
     public boolean impliesResolve() {
         return true;
     }

http://git-wip-us.apache.org/repos/asf/isis/blob/5f15fa74/core/metamodel/src/main/java/org/apache/isis/core/progmodel/facets/collections/clear/CollectionClearFacetViaAccessor.java
----------------------------------------------------------------------
diff --git a/core/metamodel/src/main/java/org/apache/isis/core/progmodel/facets/collections/clear/CollectionClearFacetViaAccessor.java b/core/metamodel/src/main/java/org/apache/isis/core/progmodel/facets/collections/clear/CollectionClearFacetViaAccessor.java
index 7f4fd80..79633c4 100644
--- a/core/metamodel/src/main/java/org/apache/isis/core/progmodel/facets/collections/clear/CollectionClearFacetViaAccessor.java
+++ b/core/metamodel/src/main/java/org/apache/isis/core/progmodel/facets/collections/clear/CollectionClearFacetViaAccessor.java
@@ -31,6 +31,7 @@ import org.apache.isis.core.metamodel.adapter.mgr.AdapterManager;
 import org.apache.isis.core.metamodel.adapter.util.AdapterInvokeUtils;
 import org.apache.isis.core.metamodel.facetapi.FacetHolder;
 import org.apache.isis.core.metamodel.facets.ImperativeFacet;
+import org.apache.isis.core.metamodel.facets.ImperativeFacet.Intent;
 import org.apache.isis.core.metamodel.facets.collections.modify.CollectionClearFacetAbstract;
 
 public class CollectionClearFacetViaAccessor extends CollectionClearFacetAbstract implements ImperativeFacet {
@@ -56,6 +57,11 @@ public class CollectionClearFacetViaAccessor extends CollectionClearFacetAbstrac
     }
 
     @Override
+    public Intent getIntent(final Method method) {
+        return Intent.ACCESSOR;
+    }
+
+    @Override
     public boolean impliesResolve() {
         return true;
     }

http://git-wip-us.apache.org/repos/asf/isis/blob/5f15fa74/core/metamodel/src/main/java/org/apache/isis/core/progmodel/facets/collections/clear/CollectionClearFacetViaMethod.java
----------------------------------------------------------------------
diff --git a/core/metamodel/src/main/java/org/apache/isis/core/progmodel/facets/collections/clear/CollectionClearFacetViaMethod.java b/core/metamodel/src/main/java/org/apache/isis/core/progmodel/facets/collections/clear/CollectionClearFacetViaMethod.java
index 9bb2e5a..c9deb4b 100644
--- a/core/metamodel/src/main/java/org/apache/isis/core/progmodel/facets/collections/clear/CollectionClearFacetViaMethod.java
+++ b/core/metamodel/src/main/java/org/apache/isis/core/progmodel/facets/collections/clear/CollectionClearFacetViaMethod.java
@@ -27,6 +27,7 @@ import org.apache.isis.core.metamodel.adapter.ObjectAdapter;
 import org.apache.isis.core.metamodel.adapter.util.AdapterInvokeUtils;
 import org.apache.isis.core.metamodel.facetapi.FacetHolder;
 import org.apache.isis.core.metamodel.facets.ImperativeFacet;
+import org.apache.isis.core.metamodel.facets.ImperativeFacet.Intent;
 import org.apache.isis.core.metamodel.facets.collections.modify.CollectionClearFacetAbstract;
 
 public class CollectionClearFacetViaMethod extends CollectionClearFacetAbstract implements ImperativeFacet {
@@ -48,6 +49,11 @@ public class CollectionClearFacetViaMethod extends CollectionClearFacetAbstract
     }
 
     @Override
+    public Intent getIntent(final Method method) {
+        return Intent.MODIFY_COLLECTION_ADD;
+    }
+
+    @Override
     public boolean impliesResolve() {
         return true;
     }

http://git-wip-us.apache.org/repos/asf/isis/blob/5f15fa74/core/metamodel/src/main/java/org/apache/isis/core/progmodel/facets/collections/modify/CollectionAddToFacetViaAccessor.java
----------------------------------------------------------------------
diff --git a/core/metamodel/src/main/java/org/apache/isis/core/progmodel/facets/collections/modify/CollectionAddToFacetViaAccessor.java b/core/metamodel/src/main/java/org/apache/isis/core/progmodel/facets/collections/modify/CollectionAddToFacetViaAccessor.java
index ddfab1e..0334828 100644
--- a/core/metamodel/src/main/java/org/apache/isis/core/progmodel/facets/collections/modify/CollectionAddToFacetViaAccessor.java
+++ b/core/metamodel/src/main/java/org/apache/isis/core/progmodel/facets/collections/modify/CollectionAddToFacetViaAccessor.java
@@ -54,6 +54,11 @@ public class CollectionAddToFacetViaAccessor extends CollectionAddToFacetAbstrac
     }
 
     @Override
+    public Intent getIntent(final Method method) {
+        return Intent.MODIFY_COLLECTION_ADD;
+    }
+
+    @Override
     public boolean impliesResolve() {
         return true;
     }

http://git-wip-us.apache.org/repos/asf/isis/blob/5f15fa74/core/metamodel/src/main/java/org/apache/isis/core/progmodel/facets/collections/modify/CollectionAddToFacetViaMethod.java
----------------------------------------------------------------------
diff --git a/core/metamodel/src/main/java/org/apache/isis/core/progmodel/facets/collections/modify/CollectionAddToFacetViaMethod.java b/core/metamodel/src/main/java/org/apache/isis/core/progmodel/facets/collections/modify/CollectionAddToFacetViaMethod.java
index 3a04676..7778c81 100644
--- a/core/metamodel/src/main/java/org/apache/isis/core/progmodel/facets/collections/modify/CollectionAddToFacetViaMethod.java
+++ b/core/metamodel/src/main/java/org/apache/isis/core/progmodel/facets/collections/modify/CollectionAddToFacetViaMethod.java
@@ -48,6 +48,11 @@ public class CollectionAddToFacetViaMethod extends CollectionAddToFacetAbstract
     }
 
     @Override
+    public Intent getIntent(final Method method) {
+        return Intent.MODIFY_COLLECTION_ADD;
+    }
+
+    @Override
     public boolean impliesResolve() {
         return true;
     }

http://git-wip-us.apache.org/repos/asf/isis/blob/5f15fa74/core/metamodel/src/main/java/org/apache/isis/core/progmodel/facets/collections/modify/CollectionRemoveFromFacetViaAccessor.java
----------------------------------------------------------------------
diff --git a/core/metamodel/src/main/java/org/apache/isis/core/progmodel/facets/collections/modify/CollectionRemoveFromFacetViaAccessor.java b/core/metamodel/src/main/java/org/apache/isis/core/progmodel/facets/collections/modify/CollectionRemoveFromFacetViaAccessor.java
index 612d4aa..1c36aa6 100644
--- a/core/metamodel/src/main/java/org/apache/isis/core/progmodel/facets/collections/modify/CollectionRemoveFromFacetViaAccessor.java
+++ b/core/metamodel/src/main/java/org/apache/isis/core/progmodel/facets/collections/modify/CollectionRemoveFromFacetViaAccessor.java
@@ -31,6 +31,7 @@ import org.apache.isis.core.metamodel.adapter.util.AdapterInvokeUtils;
 import org.apache.isis.core.metamodel.adapter.util.AdapterUtils;
 import org.apache.isis.core.metamodel.facetapi.FacetHolder;
 import org.apache.isis.core.metamodel.facets.ImperativeFacet;
+import org.apache.isis.core.metamodel.facets.ImperativeFacet.Intent;
 import org.apache.isis.core.metamodel.facets.collections.modify.CollectionRemoveFromFacetAbstract;
 
 public class CollectionRemoveFromFacetViaAccessor extends CollectionRemoveFromFacetAbstract implements ImperativeFacet {
@@ -54,6 +55,11 @@ public class CollectionRemoveFromFacetViaAccessor extends CollectionRemoveFromFa
     }
 
     @Override
+    public Intent getIntent(final Method method) {
+        return Intent.MODIFY_COLLECTION_REMOVE;
+    }
+
+    @Override
     public boolean impliesResolve() {
         return true;
     }

http://git-wip-us.apache.org/repos/asf/isis/blob/5f15fa74/core/metamodel/src/main/java/org/apache/isis/core/progmodel/facets/collections/modify/CollectionRemoveFromFacetViaMethod.java
----------------------------------------------------------------------
diff --git a/core/metamodel/src/main/java/org/apache/isis/core/progmodel/facets/collections/modify/CollectionRemoveFromFacetViaMethod.java b/core/metamodel/src/main/java/org/apache/isis/core/progmodel/facets/collections/modify/CollectionRemoveFromFacetViaMethod.java
index 9fbda42..4fb7641 100644
--- a/core/metamodel/src/main/java/org/apache/isis/core/progmodel/facets/collections/modify/CollectionRemoveFromFacetViaMethod.java
+++ b/core/metamodel/src/main/java/org/apache/isis/core/progmodel/facets/collections/modify/CollectionRemoveFromFacetViaMethod.java
@@ -27,6 +27,7 @@ import org.apache.isis.core.metamodel.adapter.ObjectAdapter;
 import org.apache.isis.core.metamodel.adapter.util.AdapterInvokeUtils;
 import org.apache.isis.core.metamodel.facetapi.FacetHolder;
 import org.apache.isis.core.metamodel.facets.ImperativeFacet;
+import org.apache.isis.core.metamodel.facets.ImperativeFacet.Intent;
 import org.apache.isis.core.metamodel.facets.collections.modify.CollectionRemoveFromFacetAbstract;
 
 public class CollectionRemoveFromFacetViaMethod extends CollectionRemoveFromFacetAbstract implements ImperativeFacet {
@@ -48,6 +49,11 @@ public class CollectionRemoveFromFacetViaMethod extends CollectionRemoveFromFace
     }
 
     @Override
+    public Intent getIntent(final Method method) {
+        return Intent.MODIFY_COLLECTION_REMOVE;
+    }
+
+    @Override
     public boolean impliesResolve() {
         return true;
     }

http://git-wip-us.apache.org/repos/asf/isis/blob/5f15fa74/core/metamodel/src/main/java/org/apache/isis/core/progmodel/facets/collections/validate/CollectionValidateAddToFacetViaMethod.java
----------------------------------------------------------------------
diff --git a/core/metamodel/src/main/java/org/apache/isis/core/progmodel/facets/collections/validate/CollectionValidateAddToFacetViaMethod.java b/core/metamodel/src/main/java/org/apache/isis/core/progmodel/facets/collections/validate/CollectionValidateAddToFacetViaMethod.java
index f4d0cca..6d24b89 100644
--- a/core/metamodel/src/main/java/org/apache/isis/core/progmodel/facets/collections/validate/CollectionValidateAddToFacetViaMethod.java
+++ b/core/metamodel/src/main/java/org/apache/isis/core/progmodel/facets/collections/validate/CollectionValidateAddToFacetViaMethod.java
@@ -27,6 +27,7 @@ import org.apache.isis.core.metamodel.adapter.ObjectAdapter;
 import org.apache.isis.core.metamodel.adapter.util.AdapterInvokeUtils;
 import org.apache.isis.core.metamodel.facetapi.FacetHolder;
 import org.apache.isis.core.metamodel.facets.ImperativeFacet;
+import org.apache.isis.core.metamodel.facets.ImperativeFacet.Intent;
 
 public class CollectionValidateAddToFacetViaMethod extends CollectionValidateAddToFacetAbstract implements ImperativeFacet {
 
@@ -47,6 +48,11 @@ public class CollectionValidateAddToFacetViaMethod extends CollectionValidateAdd
     }
 
     @Override
+    public Intent getIntent(final Method method) {
+        return Intent.CHECK_IF_VALID;
+    }
+
+    @Override
     public boolean impliesResolve() {
         return true;
     }

http://git-wip-us.apache.org/repos/asf/isis/blob/5f15fa74/core/metamodel/src/main/java/org/apache/isis/core/progmodel/facets/collections/validate/CollectionValidateRemoveFromFacetViaMethod.java
----------------------------------------------------------------------
diff --git a/core/metamodel/src/main/java/org/apache/isis/core/progmodel/facets/collections/validate/CollectionValidateRemoveFromFacetViaMethod.java b/core/metamodel/src/main/java/org/apache/isis/core/progmodel/facets/collections/validate/CollectionValidateRemoveFromFacetViaMethod.java
index 7a4a213..f5424d8 100644
--- a/core/metamodel/src/main/java/org/apache/isis/core/progmodel/facets/collections/validate/CollectionValidateRemoveFromFacetViaMethod.java
+++ b/core/metamodel/src/main/java/org/apache/isis/core/progmodel/facets/collections/validate/CollectionValidateRemoveFromFacetViaMethod.java
@@ -27,6 +27,7 @@ import org.apache.isis.core.metamodel.adapter.ObjectAdapter;
 import org.apache.isis.core.metamodel.adapter.util.AdapterInvokeUtils;
 import org.apache.isis.core.metamodel.facetapi.FacetHolder;
 import org.apache.isis.core.metamodel.facets.ImperativeFacet;
+import org.apache.isis.core.metamodel.facets.ImperativeFacet.Intent;
 
 public class CollectionValidateRemoveFromFacetViaMethod extends CollectionValidateRemoveFromFacetAbstract implements ImperativeFacet {
 
@@ -47,6 +48,11 @@ public class CollectionValidateRemoveFromFacetViaMethod extends CollectionValida
     }
 
     @Override
+    public Intent getIntent(final Method method) {
+        return Intent.CHECK_IF_VALID;
+    }
+
+    @Override
     public boolean impliesResolve() {
         return true;
     }

http://git-wip-us.apache.org/repos/asf/isis/blob/5f15fa74/core/metamodel/src/main/java/org/apache/isis/core/progmodel/facets/members/describedas/staticmethod/DescribedAsFacetViaMethod.java
----------------------------------------------------------------------
diff --git a/core/metamodel/src/main/java/org/apache/isis/core/progmodel/facets/members/describedas/staticmethod/DescribedAsFacetViaMethod.java b/core/metamodel/src/main/java/org/apache/isis/core/progmodel/facets/members/describedas/staticmethod/DescribedAsFacetViaMethod.java
index 672b56d..59fb27f 100644
--- a/core/metamodel/src/main/java/org/apache/isis/core/progmodel/facets/members/describedas/staticmethod/DescribedAsFacetViaMethod.java
+++ b/core/metamodel/src/main/java/org/apache/isis/core/progmodel/facets/members/describedas/staticmethod/DescribedAsFacetViaMethod.java
@@ -25,6 +25,7 @@ import java.util.List;
 
 import org.apache.isis.core.metamodel.facetapi.FacetHolder;
 import org.apache.isis.core.metamodel.facets.ImperativeFacet;
+import org.apache.isis.core.metamodel.facets.ImperativeFacet.Intent;
 import org.apache.isis.core.metamodel.facets.describedas.DescribedAsFacetAbstract;
 
 public class DescribedAsFacetViaMethod extends DescribedAsFacetAbstract implements ImperativeFacet {
@@ -42,6 +43,11 @@ public class DescribedAsFacetViaMethod extends DescribedAsFacetAbstract implemen
     }
 
     @Override
+    public Intent getIntent(final Method method) {
+        return Intent.UI_HINT;
+    }
+
+    @Override
     public boolean impliesResolve() {
         return false;
     }

http://git-wip-us.apache.org/repos/asf/isis/blob/5f15fa74/core/metamodel/src/main/java/org/apache/isis/core/progmodel/facets/members/disabled/forsession/DisableForSessionFacetViaMethod.java
----------------------------------------------------------------------
diff --git a/core/metamodel/src/main/java/org/apache/isis/core/progmodel/facets/members/disabled/forsession/DisableForSessionFacetViaMethod.java b/core/metamodel/src/main/java/org/apache/isis/core/progmodel/facets/members/disabled/forsession/DisableForSessionFacetViaMethod.java
index 19723e6..3262b62 100644
--- a/core/metamodel/src/main/java/org/apache/isis/core/progmodel/facets/members/disabled/forsession/DisableForSessionFacetViaMethod.java
+++ b/core/metamodel/src/main/java/org/apache/isis/core/progmodel/facets/members/disabled/forsession/DisableForSessionFacetViaMethod.java
@@ -28,6 +28,7 @@ import org.apache.isis.core.commons.authentication.AuthenticationSessionUtils;
 import org.apache.isis.core.commons.lang.MethodExtensions;
 import org.apache.isis.core.metamodel.facetapi.FacetHolder;
 import org.apache.isis.core.metamodel.facets.ImperativeFacet;
+import org.apache.isis.core.metamodel.facets.ImperativeFacet.Intent;
 import org.apache.isis.core.progmodel.facets.members.disabled.DisableForSessionFacetAbstract;
 
 public class DisableForSessionFacetViaMethod extends DisableForSessionFacetAbstract implements ImperativeFacet {
@@ -49,6 +50,11 @@ public class DisableForSessionFacetViaMethod extends DisableForSessionFacetAbstr
     }
 
     @Override
+    public Intent getIntent(final Method method) {
+        return Intent.CHECK_IF_DISABLED;
+    }
+
+    @Override
     public boolean impliesResolve() {
         return true;
     }

http://git-wip-us.apache.org/repos/asf/isis/blob/5f15fa74/core/metamodel/src/main/java/org/apache/isis/core/progmodel/facets/members/disabled/method/DisableForContextFacetViaMethod.java
----------------------------------------------------------------------
diff --git a/core/metamodel/src/main/java/org/apache/isis/core/progmodel/facets/members/disabled/method/DisableForContextFacetViaMethod.java b/core/metamodel/src/main/java/org/apache/isis/core/progmodel/facets/members/disabled/method/DisableForContextFacetViaMethod.java
index 0282b7c..a16700b 100644
--- a/core/metamodel/src/main/java/org/apache/isis/core/progmodel/facets/members/disabled/method/DisableForContextFacetViaMethod.java
+++ b/core/metamodel/src/main/java/org/apache/isis/core/progmodel/facets/members/disabled/method/DisableForContextFacetViaMethod.java
@@ -28,6 +28,7 @@ import org.apache.isis.core.metamodel.adapter.ObjectAdapter;
 import org.apache.isis.core.metamodel.adapter.util.AdapterInvokeUtils;
 import org.apache.isis.core.metamodel.facetapi.FacetHolder;
 import org.apache.isis.core.metamodel.facets.ImperativeFacet;
+import org.apache.isis.core.metamodel.facets.ImperativeFacet.Intent;
 import org.apache.isis.core.metamodel.interactions.UsabilityContext;
 import org.apache.isis.core.progmodel.facets.members.disabled.DisableForContextFacetAbstract;
 
@@ -50,6 +51,11 @@ public class DisableForContextFacetViaMethod extends DisableForContextFacetAbstr
     }
 
     @Override
+    public Intent getIntent(final Method method) {
+        return Intent.CHECK_IF_DISABLED;
+    }
+
+    @Override
     public boolean impliesResolve() {
         return true;
     }

http://git-wip-us.apache.org/repos/asf/isis/blob/5f15fa74/core/metamodel/src/main/java/org/apache/isis/core/progmodel/facets/members/hidden/forsession/HideForSessionFacetViaMethod.java
----------------------------------------------------------------------
diff --git a/core/metamodel/src/main/java/org/apache/isis/core/progmodel/facets/members/hidden/forsession/HideForSessionFacetViaMethod.java b/core/metamodel/src/main/java/org/apache/isis/core/progmodel/facets/members/hidden/forsession/HideForSessionFacetViaMethod.java
index c558504..9b49f86 100644
--- a/core/metamodel/src/main/java/org/apache/isis/core/progmodel/facets/members/hidden/forsession/HideForSessionFacetViaMethod.java
+++ b/core/metamodel/src/main/java/org/apache/isis/core/progmodel/facets/members/hidden/forsession/HideForSessionFacetViaMethod.java
@@ -28,6 +28,7 @@ import org.apache.isis.core.commons.authentication.AuthenticationSessionUtils;
 import org.apache.isis.core.commons.lang.MethodExtensions;
 import org.apache.isis.core.metamodel.facetapi.FacetHolder;
 import org.apache.isis.core.metamodel.facets.ImperativeFacet;
+import org.apache.isis.core.metamodel.facets.ImperativeFacet.Intent;
 import org.apache.isis.core.progmodel.facets.members.hidden.HideForSessionFacetAbstract;
 
 public class HideForSessionFacetViaMethod extends HideForSessionFacetAbstract implements ImperativeFacet {
@@ -49,6 +50,11 @@ public class HideForSessionFacetViaMethod extends HideForSessionFacetAbstract im
     }
 
     @Override
+    public Intent getIntent(final Method method) {
+        return Intent.CHECK_IF_HIDDEN;
+    }
+
+    @Override
     public boolean impliesResolve() {
         return true;
     }

http://git-wip-us.apache.org/repos/asf/isis/blob/5f15fa74/core/metamodel/src/main/java/org/apache/isis/core/progmodel/facets/members/hidden/method/HideForContextFacetViaMethod.java
----------------------------------------------------------------------
diff --git a/core/metamodel/src/main/java/org/apache/isis/core/progmodel/facets/members/hidden/method/HideForContextFacetViaMethod.java b/core/metamodel/src/main/java/org/apache/isis/core/progmodel/facets/members/hidden/method/HideForContextFacetViaMethod.java
index 40e3bc4..8e3af31 100644
--- a/core/metamodel/src/main/java/org/apache/isis/core/progmodel/facets/members/hidden/method/HideForContextFacetViaMethod.java
+++ b/core/metamodel/src/main/java/org/apache/isis/core/progmodel/facets/members/hidden/method/HideForContextFacetViaMethod.java
@@ -28,6 +28,7 @@ import org.apache.isis.core.metamodel.adapter.ObjectAdapter;
 import org.apache.isis.core.metamodel.adapter.util.AdapterInvokeUtils;
 import org.apache.isis.core.metamodel.facetapi.FacetHolder;
 import org.apache.isis.core.metamodel.facets.ImperativeFacet;
+import org.apache.isis.core.metamodel.facets.ImperativeFacet.Intent;
 import org.apache.isis.core.metamodel.interactions.VisibilityContext;
 import org.apache.isis.core.progmodel.facets.members.hidden.HideForContextFacetAbstract;
 
@@ -50,6 +51,11 @@ public class HideForContextFacetViaMethod extends HideForContextFacetAbstract im
     }
 
     @Override
+    public Intent getIntent(final Method method) {
+        return Intent.CHECK_IF_HIDDEN;
+    }
+
+    @Override
     public boolean impliesResolve() {
         return true;
     }

http://git-wip-us.apache.org/repos/asf/isis/blob/5f15fa74/core/metamodel/src/main/java/org/apache/isis/core/progmodel/facets/members/named/staticmethod/NamedFacetViaMethod.java
----------------------------------------------------------------------
diff --git a/core/metamodel/src/main/java/org/apache/isis/core/progmodel/facets/members/named/staticmethod/NamedFacetViaMethod.java b/core/metamodel/src/main/java/org/apache/isis/core/progmodel/facets/members/named/staticmethod/NamedFacetViaMethod.java
index 8739251..b3d6f3b 100644
--- a/core/metamodel/src/main/java/org/apache/isis/core/progmodel/facets/members/named/staticmethod/NamedFacetViaMethod.java
+++ b/core/metamodel/src/main/java/org/apache/isis/core/progmodel/facets/members/named/staticmethod/NamedFacetViaMethod.java
@@ -25,6 +25,7 @@ import java.util.List;
 
 import org.apache.isis.core.metamodel.facetapi.FacetHolder;
 import org.apache.isis.core.metamodel.facets.ImperativeFacet;
+import org.apache.isis.core.metamodel.facets.ImperativeFacet.Intent;
 import org.apache.isis.core.metamodel.facets.named.NamedFacetAbstract;
 
 public class NamedFacetViaMethod extends NamedFacetAbstract implements ImperativeFacet {
@@ -46,6 +47,11 @@ public class NamedFacetViaMethod extends NamedFacetAbstract implements Imperativ
     }
 
     @Override
+    public Intent getIntent(final Method method) {
+        return Intent.UI_HINT;
+    }
+
+    @Override
     public boolean impliesResolve() {
         return true;
     }

http://git-wip-us.apache.org/repos/asf/isis/blob/5f15fa74/core/metamodel/src/main/java/org/apache/isis/core/progmodel/facets/object/callbacks/create/CreatedCallbackFacetViaMethod.java
----------------------------------------------------------------------
diff --git a/core/metamodel/src/main/java/org/apache/isis/core/progmodel/facets/object/callbacks/create/CreatedCallbackFacetViaMethod.java b/core/metamodel/src/main/java/org/apache/isis/core/progmodel/facets/object/callbacks/create/CreatedCallbackFacetViaMethod.java
index d0bee2a..01e9014 100644
--- a/core/metamodel/src/main/java/org/apache/isis/core/progmodel/facets/object/callbacks/create/CreatedCallbackFacetViaMethod.java
+++ b/core/metamodel/src/main/java/org/apache/isis/core/progmodel/facets/object/callbacks/create/CreatedCallbackFacetViaMethod.java
@@ -28,6 +28,7 @@ import org.apache.isis.core.metamodel.adapter.ObjectAdapter;
 import org.apache.isis.core.metamodel.adapter.util.AdapterInvokeUtils;
 import org.apache.isis.core.metamodel.facetapi.FacetHolder;
 import org.apache.isis.core.metamodel.facets.ImperativeFacet;
+import org.apache.isis.core.metamodel.facets.ImperativeFacet.Intent;
 
 public class CreatedCallbackFacetViaMethod extends CreatedCallbackFacetAbstract implements ImperativeFacet {
 
@@ -44,6 +45,11 @@ public class CreatedCallbackFacetViaMethod extends CreatedCallbackFacetAbstract
     }
 
     @Override
+    public Intent getIntent(final Method method) {
+        return Intent.LIFECYCLE;
+    }
+
+    @Override
     public List<Method> getMethods() {
         return Collections.unmodifiableList(methods);
     }

http://git-wip-us.apache.org/repos/asf/isis/blob/5f15fa74/core/metamodel/src/main/java/org/apache/isis/core/progmodel/facets/object/callbacks/load/LoadedCallbackFacetViaMethod.java
----------------------------------------------------------------------
diff --git a/core/metamodel/src/main/java/org/apache/isis/core/progmodel/facets/object/callbacks/load/LoadedCallbackFacetViaMethod.java b/core/metamodel/src/main/java/org/apache/isis/core/progmodel/facets/object/callbacks/load/LoadedCallbackFacetViaMethod.java
index 918ad4d..2c8cf86 100644
--- a/core/metamodel/src/main/java/org/apache/isis/core/progmodel/facets/object/callbacks/load/LoadedCallbackFacetViaMethod.java
+++ b/core/metamodel/src/main/java/org/apache/isis/core/progmodel/facets/object/callbacks/load/LoadedCallbackFacetViaMethod.java
@@ -49,6 +49,11 @@ public class LoadedCallbackFacetViaMethod extends LoadedCallbackFacetAbstract im
     }
 
     @Override
+    public Intent getIntent(final Method method) {
+        return Intent.LIFECYCLE;
+    }
+
+    @Override
     public boolean impliesResolve() {
         return false;
     }

http://git-wip-us.apache.org/repos/asf/isis/blob/5f15fa74/core/metamodel/src/main/java/org/apache/isis/core/progmodel/facets/object/callbacks/load/LoadingCallbackFacetViaMethod.java
----------------------------------------------------------------------
diff --git a/core/metamodel/src/main/java/org/apache/isis/core/progmodel/facets/object/callbacks/load/LoadingCallbackFacetViaMethod.java b/core/metamodel/src/main/java/org/apache/isis/core/progmodel/facets/object/callbacks/load/LoadingCallbackFacetViaMethod.java
index 1619f20..5a97e2b 100644
--- a/core/metamodel/src/main/java/org/apache/isis/core/progmodel/facets/object/callbacks/load/LoadingCallbackFacetViaMethod.java
+++ b/core/metamodel/src/main/java/org/apache/isis/core/progmodel/facets/object/callbacks/load/LoadingCallbackFacetViaMethod.java
@@ -28,6 +28,7 @@ import org.apache.isis.core.metamodel.adapter.ObjectAdapter;
 import org.apache.isis.core.metamodel.adapter.util.AdapterInvokeUtils;
 import org.apache.isis.core.metamodel.facetapi.FacetHolder;
 import org.apache.isis.core.metamodel.facets.ImperativeFacet;
+import org.apache.isis.core.metamodel.facets.ImperativeFacet.Intent;
 
 public class LoadingCallbackFacetViaMethod extends LoadingCallbackFacetAbstract implements ImperativeFacet {
 
@@ -49,6 +50,11 @@ public class LoadingCallbackFacetViaMethod extends LoadingCallbackFacetAbstract
     }
 
     @Override
+    public Intent getIntent(final Method method) {
+        return Intent.LIFECYCLE;
+    }
+
+    @Override
     public boolean impliesResolve() {
         return false;
     }

http://git-wip-us.apache.org/repos/asf/isis/blob/5f15fa74/core/metamodel/src/main/java/org/apache/isis/core/progmodel/facets/object/callbacks/persist/PersistedCallbackFacetViaMethod.java
----------------------------------------------------------------------
diff --git a/core/metamodel/src/main/java/org/apache/isis/core/progmodel/facets/object/callbacks/persist/PersistedCallbackFacetViaMethod.java b/core/metamodel/src/main/java/org/apache/isis/core/progmodel/facets/object/callbacks/persist/PersistedCallbackFacetViaMethod.java
index 0582cf1..9c9f27b 100644
--- a/core/metamodel/src/main/java/org/apache/isis/core/progmodel/facets/object/callbacks/persist/PersistedCallbackFacetViaMethod.java
+++ b/core/metamodel/src/main/java/org/apache/isis/core/progmodel/facets/object/callbacks/persist/PersistedCallbackFacetViaMethod.java
@@ -28,6 +28,7 @@ import org.apache.isis.core.metamodel.adapter.ObjectAdapter;
 import org.apache.isis.core.metamodel.adapter.util.AdapterInvokeUtils;
 import org.apache.isis.core.metamodel.facetapi.FacetHolder;
 import org.apache.isis.core.metamodel.facets.ImperativeFacet;
+import org.apache.isis.core.metamodel.facets.ImperativeFacet.Intent;
 
 public class PersistedCallbackFacetViaMethod extends PersistedCallbackFacetAbstract implements ImperativeFacet {
 
@@ -44,6 +45,11 @@ public class PersistedCallbackFacetViaMethod extends PersistedCallbackFacetAbstr
     }
 
     @Override
+    public Intent getIntent(final Method method) {
+        return Intent.LIFECYCLE;
+    }
+
+    @Override
     public List<Method> getMethods() {
         return Collections.unmodifiableList(methods);
     }

http://git-wip-us.apache.org/repos/asf/isis/blob/5f15fa74/core/metamodel/src/main/java/org/apache/isis/core/progmodel/facets/object/callbacks/persist/PersistingCallbackFacetViaMethod.java
----------------------------------------------------------------------
diff --git a/core/metamodel/src/main/java/org/apache/isis/core/progmodel/facets/object/callbacks/persist/PersistingCallbackFacetViaMethod.java b/core/metamodel/src/main/java/org/apache/isis/core/progmodel/facets/object/callbacks/persist/PersistingCallbackFacetViaMethod.java
index 6e60d2d..ab125f8 100644
--- a/core/metamodel/src/main/java/org/apache/isis/core/progmodel/facets/object/callbacks/persist/PersistingCallbackFacetViaMethod.java
+++ b/core/metamodel/src/main/java/org/apache/isis/core/progmodel/facets/object/callbacks/persist/PersistingCallbackFacetViaMethod.java
@@ -28,6 +28,7 @@ import org.apache.isis.core.metamodel.adapter.ObjectAdapter;
 import org.apache.isis.core.metamodel.adapter.util.AdapterInvokeUtils;
 import org.apache.isis.core.metamodel.facetapi.FacetHolder;
 import org.apache.isis.core.metamodel.facets.ImperativeFacet;
+import org.apache.isis.core.metamodel.facets.ImperativeFacet.Intent;
 
 public class PersistingCallbackFacetViaMethod extends PersistingCallbackFacetAbstract implements ImperativeFacet {
 
@@ -49,6 +50,11 @@ public class PersistingCallbackFacetViaMethod extends PersistingCallbackFacetAbs
     }
 
     @Override
+    public Intent getIntent(final Method method) {
+        return Intent.LIFECYCLE;
+    }
+
+    @Override
     public boolean impliesResolve() {
         return false;
     }

http://git-wip-us.apache.org/repos/asf/isis/blob/5f15fa74/core/metamodel/src/main/java/org/apache/isis/core/progmodel/facets/object/callbacks/remove/RemovedCallbackFacetViaMethod.java
----------------------------------------------------------------------
diff --git a/core/metamodel/src/main/java/org/apache/isis/core/progmodel/facets/object/callbacks/remove/RemovedCallbackFacetViaMethod.java b/core/metamodel/src/main/java/org/apache/isis/core/progmodel/facets/object/callbacks/remove/RemovedCallbackFacetViaMethod.java
index 3afa9f7..e81a0a6 100644
--- a/core/metamodel/src/main/java/org/apache/isis/core/progmodel/facets/object/callbacks/remove/RemovedCallbackFacetViaMethod.java
+++ b/core/metamodel/src/main/java/org/apache/isis/core/progmodel/facets/object/callbacks/remove/RemovedCallbackFacetViaMethod.java
@@ -28,6 +28,7 @@ import org.apache.isis.core.metamodel.adapter.ObjectAdapter;
 import org.apache.isis.core.metamodel.adapter.util.AdapterInvokeUtils;
 import org.apache.isis.core.metamodel.facetapi.FacetHolder;
 import org.apache.isis.core.metamodel.facets.ImperativeFacet;
+import org.apache.isis.core.metamodel.facets.ImperativeFacet.Intent;
 
 public class RemovedCallbackFacetViaMethod extends RemovedCallbackFacetAbstract implements ImperativeFacet {
 
@@ -49,6 +50,11 @@ public class RemovedCallbackFacetViaMethod extends RemovedCallbackFacetAbstract
     }
 
     @Override
+    public Intent getIntent(final Method method) {
+        return Intent.LIFECYCLE;
+    }
+
+    @Override
     public boolean impliesResolve() {
         return false;
     }

http://git-wip-us.apache.org/repos/asf/isis/blob/5f15fa74/core/metamodel/src/main/java/org/apache/isis/core/progmodel/facets/object/callbacks/remove/RemovingCallbackFacetViaMethod.java
----------------------------------------------------------------------
diff --git a/core/metamodel/src/main/java/org/apache/isis/core/progmodel/facets/object/callbacks/remove/RemovingCallbackFacetViaMethod.java b/core/metamodel/src/main/java/org/apache/isis/core/progmodel/facets/object/callbacks/remove/RemovingCallbackFacetViaMethod.java
index 9d04a2e..c0670ab 100644
--- a/core/metamodel/src/main/java/org/apache/isis/core/progmodel/facets/object/callbacks/remove/RemovingCallbackFacetViaMethod.java
+++ b/core/metamodel/src/main/java/org/apache/isis/core/progmodel/facets/object/callbacks/remove/RemovingCallbackFacetViaMethod.java
@@ -28,6 +28,7 @@ import org.apache.isis.core.metamodel.adapter.ObjectAdapter;
 import org.apache.isis.core.metamodel.adapter.util.AdapterInvokeUtils;
 import org.apache.isis.core.metamodel.facetapi.FacetHolder;
 import org.apache.isis.core.metamodel.facets.ImperativeFacet;
+import org.apache.isis.core.metamodel.facets.ImperativeFacet.Intent;
 
 public class RemovingCallbackFacetViaMethod extends RemovingCallbackFacetAbstract implements ImperativeFacet {
 
@@ -49,6 +50,11 @@ public class RemovingCallbackFacetViaMethod extends RemovingCallbackFacetAbstrac
     }
 
     @Override
+    public Intent getIntent(final Method method) {
+        return Intent.LIFECYCLE;
+    }
+
+    @Override
     public boolean impliesObjectChanged() {
         return false;
     }

http://git-wip-us.apache.org/repos/asf/isis/blob/5f15fa74/core/metamodel/src/main/java/org/apache/isis/core/progmodel/facets/object/callbacks/update/UpdatedCallbackFacetViaMethod.java
----------------------------------------------------------------------
diff --git a/core/metamodel/src/main/java/org/apache/isis/core/progmodel/facets/object/callbacks/update/UpdatedCallbackFacetViaMethod.java b/core/metamodel/src/main/java/org/apache/isis/core/progmodel/facets/object/callbacks/update/UpdatedCallbackFacetViaMethod.java
index e052bf3..3cf2a97 100644
--- a/core/metamodel/src/main/java/org/apache/isis/core/progmodel/facets/object/callbacks/update/UpdatedCallbackFacetViaMethod.java
+++ b/core/metamodel/src/main/java/org/apache/isis/core/progmodel/facets/object/callbacks/update/UpdatedCallbackFacetViaMethod.java
@@ -28,6 +28,7 @@ import org.apache.isis.core.metamodel.adapter.ObjectAdapter;
 import org.apache.isis.core.metamodel.adapter.util.AdapterInvokeUtils;
 import org.apache.isis.core.metamodel.facetapi.FacetHolder;
 import org.apache.isis.core.metamodel.facets.ImperativeFacet;
+import org.apache.isis.core.metamodel.facets.ImperativeFacet.Intent;
 
 public class UpdatedCallbackFacetViaMethod extends UpdatedCallbackFacetAbstract implements ImperativeFacet {
 
@@ -49,6 +50,11 @@ public class UpdatedCallbackFacetViaMethod extends UpdatedCallbackFacetAbstract
     }
 
     @Override
+    public Intent getIntent(final Method method) {
+        return Intent.LIFECYCLE;
+    }
+
+    @Override
     public boolean impliesResolve() {
         return false;
     }

http://git-wip-us.apache.org/repos/asf/isis/blob/5f15fa74/core/metamodel/src/main/java/org/apache/isis/core/progmodel/facets/object/callbacks/update/UpdatingCallbackFacetViaMethod.java
----------------------------------------------------------------------
diff --git a/core/metamodel/src/main/java/org/apache/isis/core/progmodel/facets/object/callbacks/update/UpdatingCallbackFacetViaMethod.java b/core/metamodel/src/main/java/org/apache/isis/core/progmodel/facets/object/callbacks/update/UpdatingCallbackFacetViaMethod.java
index f2bcee9..69256cd 100644
--- a/core/metamodel/src/main/java/org/apache/isis/core/progmodel/facets/object/callbacks/update/UpdatingCallbackFacetViaMethod.java
+++ b/core/metamodel/src/main/java/org/apache/isis/core/progmodel/facets/object/callbacks/update/UpdatingCallbackFacetViaMethod.java
@@ -28,6 +28,7 @@ import org.apache.isis.core.metamodel.adapter.ObjectAdapter;
 import org.apache.isis.core.metamodel.adapter.util.AdapterInvokeUtils;
 import org.apache.isis.core.metamodel.facetapi.FacetHolder;
 import org.apache.isis.core.metamodel.facets.ImperativeFacet;
+import org.apache.isis.core.metamodel.facets.ImperativeFacet.Intent;
 
 public class UpdatingCallbackFacetViaMethod extends UpdatingCallbackFacetAbstract implements ImperativeFacet {
 
@@ -49,6 +50,11 @@ public class UpdatingCallbackFacetViaMethod extends UpdatingCallbackFacetAbstrac
     }
 
     @Override
+    public Intent getIntent(final Method method) {
+        return Intent.LIFECYCLE;
+    }
+
+    @Override
     public boolean impliesResolve() {
         return false;
     }


[07/16] git commit: ISIS-550: fixing unit test.

Posted by da...@apache.org.
ISIS-550: fixing unit test.


Project: http://git-wip-us.apache.org/repos/asf/isis/repo
Commit: http://git-wip-us.apache.org/repos/asf/isis/commit/fe05886c
Tree: http://git-wip-us.apache.org/repos/asf/isis/tree/fe05886c
Diff: http://git-wip-us.apache.org/repos/asf/isis/diff/fe05886c

Branch: refs/heads/master
Commit: fe05886c7ad70560419647bbee0c220f466a0046
Parents: f883304
Author: Dan Haywood <da...@haywood-associates.co.uk>
Authored: Fri May 9 18:33:48 2014 +0100
Committer: Dan Haywood <da...@haywood-associates.co.uk>
Committed: Fri May 9 18:33:48 2014 +0100

----------------------------------------------------------------------
 .../facets/ImperativeFacetUtilsTest.java        | 47 ++++++++++++++------
 1 file changed, 33 insertions(+), 14 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/isis/blob/fe05886c/core/metamodel/src/test/java/org/apache/isis/core/metamodel/facets/ImperativeFacetUtilsTest.java
----------------------------------------------------------------------
diff --git a/core/metamodel/src/test/java/org/apache/isis/core/metamodel/facets/ImperativeFacetUtilsTest.java b/core/metamodel/src/test/java/org/apache/isis/core/metamodel/facets/ImperativeFacetUtilsTest.java
index 5efadc3..feee4dd 100644
--- a/core/metamodel/src/test/java/org/apache/isis/core/metamodel/facets/ImperativeFacetUtilsTest.java
+++ b/core/metamodel/src/test/java/org/apache/isis/core/metamodel/facets/ImperativeFacetUtilsTest.java
@@ -30,20 +30,26 @@ import com.google.common.collect.Lists;
 
 import org.jmock.Expectations;
 import org.jmock.Mockery;
+import org.jmock.auto.Mock;
 import org.jmock.integration.junit4.JMock;
 import org.jmock.integration.junit4.JUnit4Mockery;
 import org.junit.Before;
+import org.junit.Rule;
 import org.junit.Test;
 import org.junit.runner.RunWith;
 
 import org.apache.isis.applib.filter.Filter;
 import org.apache.isis.core.metamodel.facetapi.Facet;
 import org.apache.isis.core.metamodel.spec.feature.ObjectMember;
+import org.apache.isis.core.unittestsupport.jmocking.JUnitRuleMockery2;
+import org.apache.isis.core.unittestsupport.jmocking.JUnitRuleMockery2.Mode;
 import org.apache.isis.core.unittestsupport.jmocking.JavassistImposteriser;
 
-@RunWith(JMock.class)
 public class ImperativeFacetUtilsTest {
 
+    @Rule
+    public JUnitRuleMockery2 context = JUnitRuleMockery2.createFor(Mode.INTERFACES_AND_CLASSES);
+
     public static class Customer {
 
         private String firstName;
@@ -58,31 +64,45 @@ public class ImperativeFacetUtilsTest {
 
     }
 
-    private final Mockery context = new JUnit4Mockery() {
-        {
-            setImposteriser(JavassistImposteriser.INSTANCE);
-        }
-    };
-
+    @Mock
     private ObjectMember mockObjectMember;
+
+    public static interface ImperativeFacetAndFacet extends ImperativeFacet, Facet {}
+    @Mock
+    private ImperativeFacetAndFacet mockImperativeFacet;
+    
     private Method method;
 
     @Before
     public void setUp() throws Exception {
-        mockObjectMember = context.mock(ObjectMember.class);
         method = Customer.class.getDeclaredMethod("getFirstName");
+
+        context.checking(new Expectations() {
+            {
+                allowing(mockImperativeFacet).getMethods();
+                will(returnValue(Lists.newArrayList(method)));
+
+                allowing(mockImperativeFacet).impliesResolve();
+                will(returnValue(true));
+                
+                allowing(mockImperativeFacet).impliesObjectChanged();
+                will(returnValue(true));
+            }
+        });
+
     }
 
     @SuppressWarnings("unchecked")
     @Test
     public void getImperativeFacetsWhenHasNone() throws Exception {
+        
         context.checking(new Expectations() {
             {
-                one(mockObjectMember).getFacets(with(any(Filter.class)));
+                oneOf(mockObjectMember).getFacets(with(any(Filter.class)));
                 will(returnValue(Lists.newArrayList()));
             }
         });
-        final ImperativeFacet.Flags flags = ImperativeFacetUtils.getImperativeFacetFlags(mockObjectMember, method);
+        final ImperativeFacet.Flags flags = ImperativeFacet.Util.getImperativeFacetFlags(mockObjectMember, method);
         assertThat(flags, is(not(nullValue())));
         assertThat(flags.impliesResolve(), is(false));
         assertThat(flags.impliesObjectChanged(), is(false));
@@ -91,14 +111,13 @@ public class ImperativeFacetUtilsTest {
     @SuppressWarnings("unchecked")
     @Test
     public void getImperativeFacetsWhenHasOneImperativeFacet() throws Exception {
-        final ImperativeFacet imperativeFacet = null;
         context.checking(new Expectations() {
             {
-                one(mockObjectMember).getFacets(with(any(Filter.class)));
-                will(returnValue(Lists.newArrayList((Facet) imperativeFacet)));
+                oneOf(mockObjectMember).getFacets(with(any(Filter.class)));
+                will(returnValue(Lists.newArrayList((Facet) mockImperativeFacet)));
             }
         });
-        final ImperativeFacet.Flags flags = ImperativeFacetUtils.getImperativeFacetFlags(mockObjectMember, method);
+        final ImperativeFacet.Flags flags = ImperativeFacet.Util.getImperativeFacetFlags(mockObjectMember, method);
         assertThat(flags, is(not(nullValue())));
         // TODO: need more tests here, these don't go deep enough...
     }


[08/16] git commit: ISIS-550: Oscar's work to date on ActionInvokedEvent

Posted by da...@apache.org.
ISIS-550: Oscar's work to date on ActionInvokedEvent

- Refactored ActionInvocationFacetViaMethod (distinguish meaning of null, introduced internalInvoke)
- New PostsActionInvokedEvent annotation class
- New facet interface, abstract class, implementation (latter subclassing ActionInvocationFacetViaMethod).


Project: http://git-wip-us.apache.org/repos/asf/isis/repo
Commit: http://git-wip-us.apache.org/repos/asf/isis/commit/cfcb2018
Tree: http://git-wip-us.apache.org/repos/asf/isis/tree/cfcb2018
Diff: http://git-wip-us.apache.org/repos/asf/isis/diff/cfcb2018

Branch: refs/heads/master
Commit: cfcb201838aeda52396563539cee2418d5e20f3c
Parents: fe05886
Author: Dan Haywood <da...@haywood-associates.co.uk>
Authored: Sat May 10 07:05:33 2014 +0100
Committer: Dan Haywood <da...@haywood-associates.co.uk>
Committed: Sat May 10 07:05:33 2014 +0100

----------------------------------------------------------------------
 .../annotation/PostsActionInvokedEvent.java     |  67 +++++++
 .../services/eventbus/ActionInvokedEvent.java   |  63 ++++++
 .../event/PostsActionInvokedEventFacet.java     |  32 +++
 .../PostsActionInvokedEventFacetAbstract.java   |  42 ++++
 .../invoke/ActionInvocationFacetViaMethod.java  |  45 ++++-
 .../PostsActionInvokedEventFacetFactory.java    | 196 +++++++++++++++++++
 .../PostsActionInvokedEventFacetViaMethod.java  | 129 ++++++++++++
 .../dflt/ProgrammingModelFacetsJava5.java       |   2 +
 8 files changed, 570 insertions(+), 6 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/isis/blob/cfcb2018/core/applib/src/main/java/org/apache/isis/applib/annotation/PostsActionInvokedEvent.java
----------------------------------------------------------------------
diff --git a/core/applib/src/main/java/org/apache/isis/applib/annotation/PostsActionInvokedEvent.java b/core/applib/src/main/java/org/apache/isis/applib/annotation/PostsActionInvokedEvent.java
new file mode 100644
index 0000000..6b772e7
--- /dev/null
+++ b/core/applib/src/main/java/org/apache/isis/applib/annotation/PostsActionInvokedEvent.java
@@ -0,0 +1,67 @@
+/*
+ *  Licensed to the Apache Software Foundation (ASF) under one
+ *  or more contributor license agreements.  See the NOTICE file
+ *  distributed with this work for additional information
+ *  regarding copyright ownership.  The ASF licenses this file
+ *  to you under the Apache License, Version 2.0 (the
+ *  "License"); you may not use this file except in compliance
+ *  with the License.  You may obtain a copy of the License at
+ *
+ *        http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *  Unless required by applicable law or agreed to in writing,
+ *  software distributed under the License is distributed on an
+ *  "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ *  KIND, either express or implied.  See the License for the
+ *  specific language governing permissions and limitations
+ *  under the License.
+ */
+
+package org.apache.isis.applib.annotation;
+
+import java.lang.annotation.ElementType;
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+import java.lang.annotation.Target;
+
+import org.apache.isis.applib.services.eventbus.ActionInvokedEvent;
+import org.apache.isis.applib.services.eventbus.PropertyChangedEvent;
+import org.apache.isis.applib.services.wrapper.WrapperFactory;
+
+/**
+ * Applies only to actions; any changes should be propagated as events to subscribers.  
+ * Only posted if no exception is thrown.
+ * 
+ * <p>For example:
+ * <pre>
+ * public static class ChangeStartDateEvent extends ActionInvokedEvent {}
+ * 
+ * &#64;PostsActionInvokedEvent(StartDateChangedEvent.class)
+ * public void changeStartDate(final Date startDate) { ...}
+ * </pre>
+ * 
+ * <p>
+ * It is highly advisable that only domain services - not domain entities - are registered as subscribers.  
+ * Domain services are guaranteed to be instantiated and resident in memory, whereas the same is not true
+ * of domain entities.  The typical implementation of a domain service subscriber is to identify the impacted entities,
+ * load them using a repository, and then to delegate to the event to them.
+ */
+@Retention(RetentionPolicy.RUNTIME)
+@Target({ElementType.TYPE, ElementType.METHOD})
+public @interface PostsActionInvokedEvent {
+
+    /**
+     * The subclass of {@link PropertyChangedEvent event} to be instantiated and posted.
+     * 
+     * <p>
+     * This subclass must provide a no-arg constructor; the fields are set reflectively.
+     */
+    Class<? extends ActionInvokedEvent<?>> value() default ActionInvokedEvent.Default.class;
+
+    /**
+     * If invoked through the {@link WrapperFactory}, whether business rules (&quot;see it, use it, do it&quot;)
+     * should be enforced or not.
+     */
+    WrapperPolicy wrapperPolicy() default WrapperPolicy.ENFORCE_RULES;
+
+}

http://git-wip-us.apache.org/repos/asf/isis/blob/cfcb2018/core/applib/src/main/java/org/apache/isis/applib/services/eventbus/ActionInvokedEvent.java
----------------------------------------------------------------------
diff --git a/core/applib/src/main/java/org/apache/isis/applib/services/eventbus/ActionInvokedEvent.java b/core/applib/src/main/java/org/apache/isis/applib/services/eventbus/ActionInvokedEvent.java
new file mode 100644
index 0000000..2140525
--- /dev/null
+++ b/core/applib/src/main/java/org/apache/isis/applib/services/eventbus/ActionInvokedEvent.java
@@ -0,0 +1,63 @@
+/*
+ *  Licensed to the Apache Software Foundation (ASF) under one
+ *  or more contributor license agreements.  See the NOTICE file
+ *  distributed with this work for additional information
+ *  regarding copyright ownership.  The ASF licenses this file
+ *  to you under the Apache License, Version 2.0 (the
+ *  "License"); you may not use this file except in compliance
+ *  with the License.  You may obtain a copy of the License at
+ *
+ *        http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *  Unless required by applicable law or agreed to in writing,
+ *  software distributed under the License is distributed on an
+ *  "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ *  KIND, either express or implied.  See the License for the
+ *  specific language governing permissions and limitations
+ *  under the License.
+ */
+package org.apache.isis.applib.services.eventbus;
+
+import org.apache.isis.applib.annotation.PostsPropertyChangedEvent;
+import org.apache.isis.applib.util.ObjectContracts;
+
+public abstract class ActionInvokedEvent<S> {
+    
+    public static class Default extends ActionInvokedEvent<Object> {}
+
+    private final S source;
+    private final String action;
+    private final String parameters;
+    
+    /**
+     * To instantiate reflectively when the {@link PostsActionInvokedEvent} annotation
+     * is used.
+     * 
+     * <p>
+     * The fields ({@link #source} and {@link #value} are then set reflectively.
+     */
+    public ActionInvokedEvent() {
+        this(null, null, null);
+    }
+    
+    public ActionInvokedEvent(S source, String action, String parameters) {
+        this.source = source;
+        this.action = action;
+        this.parameters = parameters;
+    }
+    
+    public S getSource() {
+        return source;
+    }
+    public String getAction() {
+        return action;
+    }
+    public String getParameters() {
+        return parameters;
+    }
+    
+    @Override
+    public String toString() {
+        return ObjectContracts.toString(this, "source,action,parameters");
+    }
+}
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/isis/blob/cfcb2018/core/metamodel/src/main/java/org/apache/isis/core/metamodel/facets/actions/invoke/event/PostsActionInvokedEventFacet.java
----------------------------------------------------------------------
diff --git a/core/metamodel/src/main/java/org/apache/isis/core/metamodel/facets/actions/invoke/event/PostsActionInvokedEventFacet.java b/core/metamodel/src/main/java/org/apache/isis/core/metamodel/facets/actions/invoke/event/PostsActionInvokedEventFacet.java
new file mode 100644
index 0000000..8f9d070
--- /dev/null
+++ b/core/metamodel/src/main/java/org/apache/isis/core/metamodel/facets/actions/invoke/event/PostsActionInvokedEventFacet.java
@@ -0,0 +1,32 @@
+/*
+ *  Licensed to the Apache Software Foundation (ASF) under one
+ *  or more contributor license agreements.  See the NOTICE file
+ *  distributed with this work for additional information
+ *  regarding copyright ownership.  The ASF licenses this file
+ *  to you under the Apache License, Version 2.0 (the
+ *  "License"); you may not use this file except in compliance
+ *  with the License.  You may obtain a copy of the License at
+ *
+ *        http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *  Unless required by applicable law or agreed to in writing,
+ *  software distributed under the License is distributed on an
+ *  "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ *  KIND, either express or implied.  See the License for the
+ *  specific language governing permissions and limitations
+ *  under the License.
+ */
+
+package org.apache.isis.core.metamodel.facets.actions.invoke.event;
+
+import org.apache.isis.core.metamodel.facets.actions.invoke.ActionInvocationFacet;
+
+/**
+ * Extends the mechanism by which the action should be invoked by sending an
+ * Event to the internal Event Bus after being invoked without throwing 
+ * an Exception.
+ * 
+ */
+public interface PostsActionInvokedEventFacet extends ActionInvocationFacet {
+
+}

http://git-wip-us.apache.org/repos/asf/isis/blob/cfcb2018/core/metamodel/src/main/java/org/apache/isis/core/metamodel/facets/actions/invoke/event/PostsActionInvokedEventFacetAbstract.java
----------------------------------------------------------------------
diff --git a/core/metamodel/src/main/java/org/apache/isis/core/metamodel/facets/actions/invoke/event/PostsActionInvokedEventFacetAbstract.java b/core/metamodel/src/main/java/org/apache/isis/core/metamodel/facets/actions/invoke/event/PostsActionInvokedEventFacetAbstract.java
new file mode 100644
index 0000000..8a0115f
--- /dev/null
+++ b/core/metamodel/src/main/java/org/apache/isis/core/metamodel/facets/actions/invoke/event/PostsActionInvokedEventFacetAbstract.java
@@ -0,0 +1,42 @@
+/*
+ *  Licensed to the Apache Software Foundation (ASF) under one
+ *  or more contributor license agreements.  See the NOTICE file
+ *  distributed with this work for additional information
+ *  regarding copyright ownership.  The ASF licenses this file
+ *  to you under the Apache License, Version 2.0 (the
+ *  "License"); you may not use this file except in compliance
+ *  with the License.  You may obtain a copy of the License at
+ *
+ *        http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *  Unless required by applicable law or agreed to in writing,
+ *  software distributed under the License is distributed on an
+ *  "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ *  KIND, either express or implied.  See the License for the
+ *  specific language governing permissions and limitations
+ *  under the License.
+ */
+
+package org.apache.isis.core.metamodel.facets.actions.invoke.event;
+
+import org.apache.isis.core.metamodel.facetapi.Facet;
+import org.apache.isis.core.metamodel.facetapi.FacetAbstract;
+import org.apache.isis.core.metamodel.facetapi.FacetHolder;
+import org.apache.isis.core.metamodel.facets.actions.invoke.ActionInvocationFacet;
+
+public abstract class PostsActionInvokedEventFacetAbstract extends FacetAbstract implements ActionInvocationFacet {
+
+    public static Class<? extends Facet> type() {
+    	
+	    // the "primary" type is ActionInvocationFacet rather than PostsActionInvokedEventFacet
+	    // so that this facet can wrap an existing (via setUnderlying).
+	    
+        //return PostsActionInvokedEventFacetAbstract.class;
+        return ActionInvocationFacet.class;
+    }
+
+    public PostsActionInvokedEventFacetAbstract(final FacetHolder holder) {
+        super(type(), holder, Derivation.NOT_DERIVED);
+    }
+
+}

http://git-wip-us.apache.org/repos/asf/isis/blob/cfcb2018/core/metamodel/src/main/java/org/apache/isis/core/progmodel/facets/actions/invoke/ActionInvocationFacetViaMethod.java
----------------------------------------------------------------------
diff --git a/core/metamodel/src/main/java/org/apache/isis/core/progmodel/facets/actions/invoke/ActionInvocationFacetViaMethod.java b/core/metamodel/src/main/java/org/apache/isis/core/progmodel/facets/actions/invoke/ActionInvocationFacetViaMethod.java
index 4063b49..c8f81d3 100644
--- a/core/metamodel/src/main/java/org/apache/isis/core/progmodel/facets/actions/invoke/ActionInvocationFacetViaMethod.java
+++ b/core/metamodel/src/main/java/org/apache/isis/core/progmodel/facets/actions/invoke/ActionInvocationFacetViaMethod.java
@@ -113,13 +113,44 @@ public class ActionInvocationFacetViaMethod extends ActionInvocationFacetAbstrac
     public ObjectAdapter invoke(final ObjectAdapter target, final ObjectAdapter[] parameters) {
         return invoke(null, target, parameters);
     }
-
+    
     @Override
     public ObjectAdapter invoke(
             final ObjectAction owningAction, 
             final ObjectAdapter targetAdapter, 
             final ObjectAdapter[] arguments) {
-
+    
+    	// Can return null both because the action finally was not invoked 
+    	// or because it returned null.
+    	return internalInvoke(owningAction, targetAdapter, arguments).getResult();
+    	
+    }
+    
+    public class InvocationResult {
+    	
+    	private final Boolean wasInvoked;
+    	private final ObjectAdapter result;
+    	
+    	public InvocationResult(Boolean invoked, ObjectAdapter result) {
+    		this.wasInvoked = invoked;
+    		this.result = result;
+    	}
+
+		public Boolean getWasInvoked() {
+			return wasInvoked;
+		}
+
+		public ObjectAdapter getResult() {
+			return result;
+		}
+    	
+    }
+    
+    protected InvocationResult internalInvoke(
+            final ObjectAction owningAction, 
+            final ObjectAdapter targetAdapter, 
+            final ObjectAdapter[] arguments) {
+    	
         final Bulk.InteractionContext bulkInteractionContext = getServicesInjector().lookupService(Bulk.InteractionContext.class);
         final CommandContext commandContext = getServicesInjector().lookupService(CommandContext.class);
         final Command command = commandContext != null ? commandContext.getCommand() : null;
@@ -195,7 +226,7 @@ public class ActionInvocationFacetViaMethod extends ActionInvocationFacetAbstrac
                 if(commandService.persistIfPossible(command)) {
                     // force persistence, then return the command itself.
                     final ObjectAdapter resultAdapter = getAdapterManager().adapterFor(command);
-                    return resultAdapter;
+                    return new InvocationResult(true, resultAdapter);
                 } else {
                     throw new IsisException(
                             "Unable to schedule action '"
@@ -216,7 +247,7 @@ public class ActionInvocationFacetViaMethod extends ActionInvocationFacetAbstrac
                     LOG.debug(" action result " + result);
                 }
                 if (result == null) {
-                    return null;
+                	return new InvocationResult(true, null);
                 }
 
                 final ObjectAdapter resultAdapter = getAdapterManager().adapterFor(result);
@@ -238,7 +269,7 @@ public class ActionInvocationFacetViaMethod extends ActionInvocationFacetAbstrac
                             ? new CurrentInvocation(targetAdapter, getIdentified(), arguments, resultAdapter, command)
                             :null);
                 
-                return resultAdapter;
+                return new InvocationResult(true, resultAdapter);
             }
 
         } catch (final IllegalArgumentException e) {
@@ -259,7 +290,9 @@ public class ActionInvocationFacetViaMethod extends ActionInvocationFacetAbstrac
             }
 
             ThrowableExtensions.throwWithinIsisException(e, "Exception executing " + method);
-            return null;
+            
+            // Action was not invoked (an Exception was thrown)
+            return new InvocationResult(false, null);
         } catch (final IllegalAccessException e) {
             throw new ReflectiveActionException("Illegal access of " + method, e);
         }

http://git-wip-us.apache.org/repos/asf/isis/blob/cfcb2018/core/metamodel/src/main/java/org/apache/isis/core/progmodel/facets/actions/invoke/event/PostsActionInvokedEventFacetFactory.java
----------------------------------------------------------------------
diff --git a/core/metamodel/src/main/java/org/apache/isis/core/progmodel/facets/actions/invoke/event/PostsActionInvokedEventFacetFactory.java b/core/metamodel/src/main/java/org/apache/isis/core/progmodel/facets/actions/invoke/event/PostsActionInvokedEventFacetFactory.java
new file mode 100644
index 0000000..e46e7cc
--- /dev/null
+++ b/core/metamodel/src/main/java/org/apache/isis/core/progmodel/facets/actions/invoke/event/PostsActionInvokedEventFacetFactory.java
@@ -0,0 +1,196 @@
+/*
+ *  Licensed to the Apache Software Foundation (ASF) under one
+ *  or more contributor license agreements.  See the NOTICE file
+ *  distributed with this work for additional information
+ *  regarding copyright ownership.  The ASF licenses this file
+ *  to you under the Apache License, Version 2.0 (the
+ *  "License"); you may not use this file except in compliance
+ *  with the License.  You may obtain a copy of the License at
+ *
+ *        http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *  Unless required by applicable law or agreed to in writing,
+ *  software distributed under the License is distributed on an
+ *  "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ *  KIND, either express or implied.  See the License for the
+ *  specific language governing permissions and limitations
+ *  under the License.
+ */
+
+package org.apache.isis.core.progmodel.facets.actions.invoke.event;
+
+import java.lang.reflect.Method;
+
+import org.apache.isis.applib.annotation.PostsCollectionAddedToEvent;
+import org.apache.isis.applib.services.eventbus.CollectionAddedToEvent;
+import org.apache.isis.core.commons.lang.StringExtensions;
+import org.apache.isis.core.metamodel.adapter.mgr.AdapterManager;
+import org.apache.isis.core.metamodel.adapter.mgr.AdapterManagerAware;
+import org.apache.isis.core.metamodel.facetapi.Facet;
+import org.apache.isis.core.metamodel.facetapi.FacetHolder;
+import org.apache.isis.core.metamodel.facetapi.FacetUtil;
+import org.apache.isis.core.metamodel.facetapi.FeatureType;
+import org.apache.isis.core.metamodel.facets.Annotations;
+import org.apache.isis.core.metamodel.facets.actions.debug.DebugFacet;
+import org.apache.isis.core.metamodel.facets.actions.exploration.ExplorationFacet;
+import org.apache.isis.core.metamodel.facets.actions.invoke.ActionInvocationFacet;
+import org.apache.isis.core.metamodel.facets.named.NamedFacet;
+import org.apache.isis.core.metamodel.facets.named.NamedFacetInferred;
+import org.apache.isis.core.metamodel.runtimecontext.RuntimeContext;
+import org.apache.isis.core.metamodel.runtimecontext.RuntimeContextAware;
+import org.apache.isis.core.metamodel.runtimecontext.ServicesInjector;
+import org.apache.isis.core.metamodel.runtimecontext.ServicesInjectorAware;
+import org.apache.isis.core.metamodel.spec.ObjectSpecification;
+import org.apache.isis.core.progmodel.facets.MethodPrefixBasedFacetFactoryAbstract;
+import org.apache.isis.core.progmodel.facets.actions.invoke.DebugFacetViaNamingConvention;
+import org.apache.isis.core.progmodel.facets.actions.invoke.ExplorationFacetViaNamingConvention;
+
+/**
+ * Sets up {@link ActionInvocationFacet}, along with a number of supporting
+ * facets that are based on the action's name.
+ * 
+ * <p>
+ * The supporting methods are: {@link ExecutedFacet}, {@link ExplorationFacet}
+ * and {@link DebugFacet}. In addition a {@link NamedFacet} is inferred from the
+ * name (taking into account the above well-known prefixes).
+ */
+public class PostsActionInvokedEventFacetFactory extends MethodPrefixBasedFacetFactoryAbstract implements AdapterManagerAware, ServicesInjectorAware, RuntimeContextAware {
+
+    private static final String EXPLORATION_PREFIX = "Exploration";
+    private static final String DEBUG_PREFIX = "Debug";
+
+    private static final String[] PREFIXES = { EXPLORATION_PREFIX, DEBUG_PREFIX };
+
+    private AdapterManager adapterManager;
+    private ServicesInjector servicesInjector;
+    private RuntimeContext runtimeContext;
+
+    /**
+     * Note that the {@link Facet}s registered are the generic ones from
+     * noa-architecture (where they exist)
+     */
+    public PostsActionInvokedEventFacetFactory() {
+        super(FeatureType.ACTIONS_ONLY, OrphanValidation.VALIDATE, PREFIXES);
+    }
+
+    // ///////////////////////////////////////////////////////
+    // Actions
+    // ///////////////////////////////////////////////////////
+
+    @Override
+    public void process(final ProcessMethodContext processMethodContext) {
+
+        // InvocationFacet
+        attachInvocationFacet(processMethodContext);
+
+        // DebugFacet, ExplorationFacet
+        attachDebugFacetIfActionMethodNamePrefixed(processMethodContext);
+        attachExplorationFacetIfActionMethodNamePrefixed(processMethodContext);
+
+        // inferred name
+        // (must be called after the attachinvocationFacet methods)
+        attachNamedFacetInferredFromMethodName(processMethodContext); 
+    }
+
+    private void attachInvocationFacet(final ProcessMethodContext processMethodContext) {
+
+        final Method actionMethod = processMethodContext.getMethod();
+
+        try {
+            final PostsCollectionAddedToEvent annotation = Annotations.getAnnotation(actionMethod, PostsCollectionAddedToEvent.class);
+            if(annotation == null) {
+                return;
+            }
+        	
+            final Class<?> returnType = actionMethod.getReturnType();
+            final ObjectSpecification returnSpec = getSpecificationLoader().loadSpecification(returnType);
+            if (returnSpec == null) {
+                return;
+            }
+
+            final Class<?> cls = processMethodContext.getCls();
+            final ObjectSpecification typeSpec = getSpecificationLoader().loadSpecification(cls);
+            final FacetHolder holder = processMethodContext.getFacetHolder();
+            
+            final Class<? extends CollectionAddedToEvent<?,?>> changedEventType = annotation.value();
+
+            FacetUtil.addFacet(new PostsActionInvokedEventFacetViaMethod(actionMethod, typeSpec, returnSpec, holder, getRuntimeContext(), getAdapterManager(), getServicesInjector(), changedEventType));
+        } finally {
+            processMethodContext.removeMethod(actionMethod);
+        }
+    }
+
+    private void attachDebugFacetIfActionMethodNamePrefixed(final ProcessMethodContext processMethodContext) {
+
+        final Method actionMethod = processMethodContext.getMethod();
+        final String capitalizedName = StringExtensions.asCapitalizedName(actionMethod.getName());
+        if (!capitalizedName.startsWith(DEBUG_PREFIX)) {
+            return;
+        }
+        final FacetHolder facetedMethod = processMethodContext.getFacetHolder();
+        FacetUtil.addFacet(new DebugFacetViaNamingConvention(facetedMethod));
+    }
+
+    private void attachExplorationFacetIfActionMethodNamePrefixed(final ProcessMethodContext processMethodContext) {
+
+        final Method actionMethod = processMethodContext.getMethod();
+        final String capitalizedName = StringExtensions.asCapitalizedName(actionMethod.getName());
+        if (!capitalizedName.startsWith(EXPLORATION_PREFIX)) {
+            return;
+        }
+        final FacetHolder facetedMethod = processMethodContext.getFacetHolder();
+        FacetUtil.addFacet(new ExplorationFacetViaNamingConvention(facetedMethod));
+    }
+
+    /**
+     * Must be called after added the debug, exploration etc facets.
+     * 
+     * <p>
+     * TODO: remove this hack
+     */
+    private void attachNamedFacetInferredFromMethodName(final ProcessMethodContext processMethodContext) {
+
+        final Method method = processMethodContext.getMethod();
+        final String capitalizedName = StringExtensions.asCapitalizedName(method.getName());
+
+        // this is nasty...
+        String name = capitalizedName;
+        name = StringExtensions.removePrefix(name, DEBUG_PREFIX);
+        name = StringExtensions.removePrefix(name, EXPLORATION_PREFIX);
+        name = StringExtensions.asNaturalName2(name);
+
+        final FacetHolder facetedMethod = processMethodContext.getFacetHolder();
+        FacetUtil.addFacet(new NamedFacetInferred(name, facetedMethod));
+    }
+
+    // ///////////////////////////////////////////////////////////////
+    // Dependencies
+    // ///////////////////////////////////////////////////////////////
+
+    @Override
+    public void setAdapterManager(final AdapterManager adapterManager) {
+        this.adapterManager = adapterManager;
+    }
+
+    private AdapterManager getAdapterManager() {
+        return adapterManager;
+    }
+
+    @Override
+    public void setServicesInjector(final ServicesInjector servicesInjector) {
+        this.servicesInjector = servicesInjector;
+    }
+
+    private ServicesInjector getServicesInjector() {
+        return servicesInjector;
+    }
+
+    private RuntimeContext getRuntimeContext() {
+        return runtimeContext;
+    }
+    
+    @Override
+    public void setRuntimeContext(RuntimeContext runtimeContext) {
+        this.runtimeContext = runtimeContext;
+    }
+}

http://git-wip-us.apache.org/repos/asf/isis/blob/cfcb2018/core/metamodel/src/main/java/org/apache/isis/core/progmodel/facets/actions/invoke/event/PostsActionInvokedEventFacetViaMethod.java
----------------------------------------------------------------------
diff --git a/core/metamodel/src/main/java/org/apache/isis/core/progmodel/facets/actions/invoke/event/PostsActionInvokedEventFacetViaMethod.java b/core/metamodel/src/main/java/org/apache/isis/core/progmodel/facets/actions/invoke/event/PostsActionInvokedEventFacetViaMethod.java
new file mode 100644
index 0000000..7e22b78
--- /dev/null
+++ b/core/metamodel/src/main/java/org/apache/isis/core/progmodel/facets/actions/invoke/event/PostsActionInvokedEventFacetViaMethod.java
@@ -0,0 +1,129 @@
+/*
+ *  Licensed to the Apache Software Foundation (ASF) under one
+ *  or more contributor license agreements.  See the NOTICE file
+ *  distributed with this work for additional information
+ *  regarding copyright ownership.  The ASF licenses this file
+ *  to you under the Apache License, Version 2.0 (the
+ *  "License"); you may not use this file except in compliance
+ *  with the License.  You may obtain a copy of the License at
+ *
+ *        http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *  Unless required by applicable law or agreed to in writing,
+ *  software distributed under the License is distributed on an
+ *  "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ *  KIND, either express or implied.  See the License for the
+ *  specific language governing permissions and limitations
+ *  under the License.
+ */
+
+package org.apache.isis.core.progmodel.facets.actions.invoke.event;
+
+import java.lang.reflect.Field;
+import java.lang.reflect.Method;
+
+import org.apache.isis.applib.FatalException;
+import org.apache.isis.applib.services.eventbus.ActionInvokedEvent;
+import org.apache.isis.applib.services.eventbus.CollectionAddedToEvent;
+import org.apache.isis.applib.services.eventbus.EventBusService;
+import org.apache.isis.core.metamodel.adapter.ObjectAdapter;
+import org.apache.isis.core.metamodel.adapter.mgr.AdapterManager;
+import org.apache.isis.core.metamodel.facetapi.FacetHolder;
+import org.apache.isis.core.metamodel.facets.ImperativeFacet;
+import org.apache.isis.core.metamodel.runtimecontext.RuntimeContext;
+import org.apache.isis.core.metamodel.runtimecontext.ServicesInjector;
+import org.apache.isis.core.metamodel.spec.ObjectSpecification;
+import org.apache.isis.core.metamodel.spec.feature.ObjectAction;
+import org.apache.isis.core.progmodel.facets.actions.invoke.ActionInvocationFacetViaMethod;
+
+public class PostsActionInvokedEventFacetViaMethod extends ActionInvocationFacetViaMethod implements ImperativeFacet {
+	
+	private EventBusService eventBusService;
+	private boolean searchedForEventBusService = false;
+	private ServicesInjector servicesInjector;
+	private Class<? extends CollectionAddedToEvent<?, ?>> eventType;
+
+    public PostsActionInvokedEventFacetViaMethod(
+            final Method method, 
+            final ObjectSpecification onType, 
+            final ObjectSpecification returnType, 
+            final FacetHolder holder, 
+            final RuntimeContext runtimeContext, 
+            final AdapterManager adapterManager, 
+            final ServicesInjector servicesInjector,
+			final Class<? extends CollectionAddedToEvent<?, ?>> eventType) {
+        super(method, onType, returnType, holder, runtimeContext, adapterManager, servicesInjector);
+        
+        // Also needed here.
+        this.servicesInjector = servicesInjector;
+        
+        this.eventType = eventType;
+    }
+
+    @Override
+    public ObjectAdapter invoke(
+            final ObjectAction owningAction, 
+            final ObjectAdapter targetAdapter, 
+            final ObjectAdapter[] arguments) {
+
+    	final InvocationResult invocationResult = this.internalInvoke(owningAction, targetAdapter, arguments);
+    	
+    	// Perhaps the Action was not properly invoked (i.e. an exception was raised).
+    	if (invocationResult.getWasInvoked()) {
+    		// If invoked, then send the ActionInvokedEvent to the EventBus.
+    		postEvent(owningAction, targetAdapter, arguments);
+    	}
+    	
+    	return invocationResult.getResult();
+    	
+    }
+    
+	@SuppressWarnings({ "rawtypes", "unchecked" })
+	private void postEvent(
+            final ObjectAction owningAction, 
+            final ObjectAdapter targetAdapter, 
+            final ObjectAdapter[] arguments) {
+	    
+		final Object source = targetAdapter.getObject();
+		try {
+			final Class type = eventType;
+			final ActionInvokedEvent event = newEvent(type, owningAction, source, arguments);
+			getEventBusService().post(event);
+		} catch (Exception e) {
+			throw new FatalException(e);
+		}
+	}
+
+	static <S> ActionInvokedEvent<S> newEvent(
+			final Class<? extends ActionInvokedEvent<S>> type,
+		            final ObjectAction owningAction, 
+		            final S source, 
+		            final ObjectAdapter[] arguments)
+			throws InstantiationException, IllegalAccessException,
+			NoSuchFieldException {
+		final ActionInvokedEvent<S> event = type.newInstance();
+
+		setField("owningAction", event, owningAction);
+		setField("targetAdapter", event, source);
+		setField("arguments", event, arguments.toString());
+		return event;
+	}
+
+	private static void setField(final String name,
+			final ActionInvokedEvent<?> event, final Object sourceValue)
+			throws NoSuchFieldException, IllegalAccessException {
+		final Field sourceField = CollectionAddedToEvent.class
+				.getDeclaredField(name);
+		sourceField.setAccessible(true);
+		sourceField.set(event, sourceValue);
+	}
+
+	private EventBusService getEventBusService() {
+		if (!searchedForEventBusService) {
+			eventBusService = this.servicesInjector.lookupService(EventBusService.class);
+		}
+		searchedForEventBusService = true;
+		return eventBusService;
+	}
+
+}

http://git-wip-us.apache.org/repos/asf/isis/blob/cfcb2018/core/metamodel/src/main/java/org/apache/isis/progmodels/dflt/ProgrammingModelFacetsJava5.java
----------------------------------------------------------------------
diff --git a/core/metamodel/src/main/java/org/apache/isis/progmodels/dflt/ProgrammingModelFacetsJava5.java b/core/metamodel/src/main/java/org/apache/isis/progmodels/dflt/ProgrammingModelFacetsJava5.java
index ca75555..74933a9 100644
--- a/core/metamodel/src/main/java/org/apache/isis/progmodels/dflt/ProgrammingModelFacetsJava5.java
+++ b/core/metamodel/src/main/java/org/apache/isis/progmodels/dflt/ProgrammingModelFacetsJava5.java
@@ -31,6 +31,7 @@ import org.apache.isis.core.progmodel.facets.actions.defaults.method.ActionDefau
 import org.apache.isis.core.progmodel.facets.actions.exploration.annotation.ExplorationAnnotationFacetFactory;
 import org.apache.isis.core.progmodel.facets.actions.homepage.HomePageAnnotationFacetFactory;
 import org.apache.isis.core.progmodel.facets.actions.invoke.ActionInvocationFacetFactory;
+import org.apache.isis.core.progmodel.facets.actions.invoke.event.PostsActionInvokedEventFacetFactory;
 import org.apache.isis.core.progmodel.facets.actions.notcontributed.annotation.NotContributedAnnotationFacetFactory;
 import org.apache.isis.core.progmodel.facets.actions.notinservicemenu.annotation.NotInServiceMenuAnnotationFacetFactory;
 import org.apache.isis.core.progmodel.facets.actions.notinservicemenu.method.NotInServiceMenuMethodFacetFactory;
@@ -368,6 +369,7 @@ public final class ProgrammingModelFacetsJava5 extends ProgrammingModelAbstract
         addFactory(PostsPropertyChangedEventAnnotationFacetFactory.class);
         addFactory(PostsCollectionAddedToEventAnnotationFacetFactory.class);
         addFactory(PostsCollectionRemovedFromEventAnnotationFacetFactory.class);
+        addFactory(PostsActionInvokedEventFacetFactory.class);
 
         
         addFactory(ImmutableMarkerInterfaceFacetFactory.class);


[06/16] git commit: ISIS-550: PostsCollectionRemovedFromEvent implemented. Subscription Tests needed

Posted by da...@apache.org.
ISIS-550: PostsCollectionRemovedFromEvent implemented. Subscription Tests needed


Project: http://git-wip-us.apache.org/repos/asf/isis/repo
Commit: http://git-wip-us.apache.org/repos/asf/isis/commit/f8833040
Tree: http://git-wip-us.apache.org/repos/asf/isis/tree/f8833040
Diff: http://git-wip-us.apache.org/repos/asf/isis/diff/f8833040

Branch: refs/heads/master
Commit: f8833040119f72d41e0a7f7442725f4b2e118184
Parents: 1dac3ed
Author: Oscar Bou <os...@apache.org>
Authored: Fri May 9 13:47:23 2014 +0200
Committer: Dan Haywood <da...@haywood-associates.co.uk>
Committed: Fri May 9 17:58:45 2014 +0100

----------------------------------------------------------------------
 .../event/PostsCollectionAddedToEventFacet.java |   2 -
 .../PostsCollectionRemovedFromEventFacet.java   |  35 ++++
 ...CollectionRemovedFromEventFacetAbstract.java |  55 ++++++
 ...tsCollectionAddedToEventFacetAnnotation.java |   1 -
 ...nRemovedFromEventAnnotationFacetFactory.java |  78 +++++++++
 ...llectionRemovedFromEventFacetAnnotation.java | 167 +++++++++++++++++++
 .../dflt/ProgrammingModelFacetsJava5.java       |   2 +
 ...emovedEventFacetAnnotationTest_newEvent.java |  50 ++++++
 .../dom/src/main/java/dom/todo/ToDoItem.java    |   9 +-
 .../java/dom/todo/ToDoItemSubscriptions.java    |   7 +
 .../ToDoItemTest_dependencies_addedEvent.java   |  85 ++++++++++
 11 files changed, 487 insertions(+), 4 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/isis/blob/f8833040/core/metamodel/src/main/java/org/apache/isis/core/metamodel/facets/collections/event/PostsCollectionAddedToEventFacet.java
----------------------------------------------------------------------
diff --git a/core/metamodel/src/main/java/org/apache/isis/core/metamodel/facets/collections/event/PostsCollectionAddedToEventFacet.java b/core/metamodel/src/main/java/org/apache/isis/core/metamodel/facets/collections/event/PostsCollectionAddedToEventFacet.java
index 91d7d3c..72edf00 100644
--- a/core/metamodel/src/main/java/org/apache/isis/core/metamodel/facets/collections/event/PostsCollectionAddedToEventFacet.java
+++ b/core/metamodel/src/main/java/org/apache/isis/core/metamodel/facets/collections/event/PostsCollectionAddedToEventFacet.java
@@ -21,8 +21,6 @@ package org.apache.isis.core.metamodel.facets.collections.event;
 
 import org.apache.isis.applib.services.eventbus.CollectionAddedToEvent;
 import org.apache.isis.applib.services.eventbus.EventBusService;
-import org.apache.isis.applib.services.eventbus.PropertyChangedEvent;
-import org.apache.isis.core.metamodel.facetapi.Facet;
 import org.apache.isis.core.metamodel.facetapi.MultiTypedFacet;
 import org.apache.isis.core.metamodel.facets.PostsEventWithWrapperPolicy;
 import org.apache.isis.core.metamodel.facets.SingleValueFacet;

http://git-wip-us.apache.org/repos/asf/isis/blob/f8833040/core/metamodel/src/main/java/org/apache/isis/core/metamodel/facets/collections/event/PostsCollectionRemovedFromEventFacet.java
----------------------------------------------------------------------
diff --git a/core/metamodel/src/main/java/org/apache/isis/core/metamodel/facets/collections/event/PostsCollectionRemovedFromEventFacet.java b/core/metamodel/src/main/java/org/apache/isis/core/metamodel/facets/collections/event/PostsCollectionRemovedFromEventFacet.java
new file mode 100644
index 0000000..d351f84
--- /dev/null
+++ b/core/metamodel/src/main/java/org/apache/isis/core/metamodel/facets/collections/event/PostsCollectionRemovedFromEventFacet.java
@@ -0,0 +1,35 @@
+/*
+ *  Licensed to the Apache Software Foundation (ASF) under one
+ *  or more contributor license agreements.  See the NOTICE file
+ *  distributed with this work for additional information
+ *  regarding copyright ownership.  The ASF licenses this file
+ *  to you under the Apache License, Version 2.0 (the
+ *  "License"); you may not use this file except in compliance
+ *  with the License.  You may obtain a copy of the License at
+ *
+ *        http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *  Unless required by applicable law or agreed to in writing,
+ *  software distributed under the License is distributed on an
+ *  "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ *  KIND, either express or implied.  See the License for the
+ *  specific language governing permissions and limitations
+ *  under the License.
+ */
+
+package org.apache.isis.core.metamodel.facets.collections.event;
+
+import org.apache.isis.applib.services.eventbus.CollectionRemovedFromEvent;
+import org.apache.isis.applib.services.eventbus.EventBusService;
+import org.apache.isis.core.metamodel.facetapi.MultiTypedFacet;
+import org.apache.isis.core.metamodel.facets.PostsEventWithWrapperPolicy;
+import org.apache.isis.core.metamodel.facets.SingleValueFacet;
+import org.apache.isis.core.metamodel.facets.collections.modify.CollectionRemoveFromFacet;
+
+/**
+ * Indicates that (the specified subclass of) {@link CollectionRemovedFromEvent} should be posted to the
+ * {@link EventBusService}.
+ */
+public interface PostsCollectionRemovedFromEventFacet extends SingleValueFacet<Class<? extends CollectionRemovedFromEvent<?,?>>>, CollectionRemoveFromFacet, MultiTypedFacet, PostsEventWithWrapperPolicy {
+}
+

http://git-wip-us.apache.org/repos/asf/isis/blob/f8833040/core/metamodel/src/main/java/org/apache/isis/core/metamodel/facets/collections/event/PostsCollectionRemovedFromEventFacetAbstract.java
----------------------------------------------------------------------
diff --git a/core/metamodel/src/main/java/org/apache/isis/core/metamodel/facets/collections/event/PostsCollectionRemovedFromEventFacetAbstract.java b/core/metamodel/src/main/java/org/apache/isis/core/metamodel/facets/collections/event/PostsCollectionRemovedFromEventFacetAbstract.java
new file mode 100644
index 0000000..a317467
--- /dev/null
+++ b/core/metamodel/src/main/java/org/apache/isis/core/metamodel/facets/collections/event/PostsCollectionRemovedFromEventFacetAbstract.java
@@ -0,0 +1,55 @@
+/*
+ *  Licensed to the Apache Software Foundation (ASF) under one
+ *  or more contributor license agreements.  See the NOTICE file
+ *  distributed with this work for additional information
+ *  regarding copyright ownership.  The ASF licenses this file
+ *  to you under the Apache License, Version 2.0 (the
+ *  "License"); you may not use this file except in compliance
+ *  with the License.  You may obtain a copy of the License at
+ *
+ *        http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *  Unless required by applicable law or agreed to in writing,
+ *  software distributed under the License is distributed on an
+ *  "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ *  KIND, either express or implied.  See the License for the
+ *  specific language governing permissions and limitations
+ *  under the License.
+ */
+
+package org.apache.isis.core.metamodel.facets.collections.event;
+
+import org.apache.isis.applib.annotation.WrapperPolicy;
+import org.apache.isis.applib.services.eventbus.CollectionRemovedFromEvent;
+import org.apache.isis.core.metamodel.facetapi.Facet;
+import org.apache.isis.core.metamodel.facetapi.FacetHolder;
+import org.apache.isis.core.metamodel.facets.SingleValueFacetAbstract;
+import org.apache.isis.core.metamodel.facets.collections.modify.CollectionRemoveFromFacet;
+
+
+public abstract class PostsCollectionRemovedFromEventFacetAbstract 
+    extends SingleValueFacetAbstract<Class<? extends CollectionRemovedFromEvent<?,?>>> 
+    implements PostsCollectionRemovedFromEventFacet {
+
+	public static Class<? extends Facet> type() {
+	    
+	    // the "primary" type is CollectionAddToFacet rather than PostsRemovedFromCollectionEventFacet
+	    // so that this facet can wrap an existing (via setUnderlying).
+	    
+        //return PostsRemovedFromCollectionEventFacet.class;
+	    return CollectionRemoveFromFacet.class;
+    }
+
+    private final WrapperPolicy wrapperPolicy;
+
+    public PostsCollectionRemovedFromEventFacetAbstract(Class<? extends CollectionRemovedFromEvent<?, ?>> changedEventType, WrapperPolicy wrapperPolicy, FacetHolder holder) {
+        super(type(), changedEventType, holder);
+        this.wrapperPolicy = wrapperPolicy;
+    }
+
+    @Override
+    public WrapperPolicy getWrapperPolicy() {
+        return wrapperPolicy;
+    }
+
+}

http://git-wip-us.apache.org/repos/asf/isis/blob/f8833040/core/metamodel/src/main/java/org/apache/isis/core/progmodel/facets/collections/event/PostsCollectionAddedToEventFacetAnnotation.java
----------------------------------------------------------------------
diff --git a/core/metamodel/src/main/java/org/apache/isis/core/progmodel/facets/collections/event/PostsCollectionAddedToEventFacetAnnotation.java b/core/metamodel/src/main/java/org/apache/isis/core/progmodel/facets/collections/event/PostsCollectionAddedToEventFacetAnnotation.java
index f1e30ec..bd69339 100644
--- a/core/metamodel/src/main/java/org/apache/isis/core/progmodel/facets/collections/event/PostsCollectionAddedToEventFacetAnnotation.java
+++ b/core/metamodel/src/main/java/org/apache/isis/core/progmodel/facets/collections/event/PostsCollectionAddedToEventFacetAnnotation.java
@@ -35,7 +35,6 @@ import org.apache.isis.core.metamodel.adapter.ServicesProvider;
 import org.apache.isis.core.metamodel.adapter.util.AdapterUtils;
 import org.apache.isis.core.metamodel.facetapi.Facet;
 import org.apache.isis.core.metamodel.facetapi.FacetHolder;
-import org.apache.isis.core.metamodel.facetapi.FacetUtil;
 import org.apache.isis.core.metamodel.facets.accessor.PropertyOrCollectionAccessorFacet;
 import org.apache.isis.core.metamodel.facets.collections.event.PostsCollectionAddedToEventFacet;
 import org.apache.isis.core.metamodel.facets.collections.event.PostsCollectionAddedToEventFacetAbstract;

http://git-wip-us.apache.org/repos/asf/isis/blob/f8833040/core/metamodel/src/main/java/org/apache/isis/core/progmodel/facets/collections/event/PostsCollectionRemovedFromEventAnnotationFacetFactory.java
----------------------------------------------------------------------
diff --git a/core/metamodel/src/main/java/org/apache/isis/core/progmodel/facets/collections/event/PostsCollectionRemovedFromEventAnnotationFacetFactory.java b/core/metamodel/src/main/java/org/apache/isis/core/progmodel/facets/collections/event/PostsCollectionRemovedFromEventAnnotationFacetFactory.java
new file mode 100644
index 0000000..67e8871
--- /dev/null
+++ b/core/metamodel/src/main/java/org/apache/isis/core/progmodel/facets/collections/event/PostsCollectionRemovedFromEventAnnotationFacetFactory.java
@@ -0,0 +1,78 @@
+/*
+ *  Licensed to the Apache Software Foundation (ASF) under one
+ *  or more contributor license agreements.  See the NOTICE file
+ *  distributed with this work for additional information
+ *  regarding copyright ownership.  The ASF licenses this file
+ *  to you under the Apache License, Version 2.0 (the
+ *  "License"); you may not use this file except in compliance
+ *  with the License.  You may obtain a copy of the License at
+ *
+ *        http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *  Unless required by applicable law or agreed to in writing,
+ *  software distributed under the License is distributed on an
+ *  "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ *  KIND, either express or implied.  See the License for the
+ *  specific language governing permissions and limitations
+ *  under the License.
+ */
+
+package org.apache.isis.core.progmodel.facets.collections.event;
+
+import java.lang.reflect.Method;
+
+import org.apache.isis.applib.annotation.PostsCollectionRemovedFromEvent;
+import org.apache.isis.applib.annotation.WrapperPolicy;
+import org.apache.isis.applib.services.eventbus.CollectionRemovedFromEvent;
+import org.apache.isis.core.metamodel.adapter.ServicesProvider;
+import org.apache.isis.core.metamodel.adapter.ServicesProviderAware;
+import org.apache.isis.core.metamodel.facetapi.FacetHolder;
+import org.apache.isis.core.metamodel.facetapi.FacetUtil;
+import org.apache.isis.core.metamodel.facetapi.FeatureType;
+import org.apache.isis.core.metamodel.facets.Annotations;
+import org.apache.isis.core.metamodel.facets.FacetFactoryAbstract;
+import org.apache.isis.core.metamodel.facets.accessor.PropertyOrCollectionAccessorFacet;
+import org.apache.isis.core.metamodel.facets.collections.event.PostsCollectionRemovedFromEventFacet;
+import org.apache.isis.core.metamodel.facets.collections.modify.CollectionRemoveFromFacet;
+
+public class PostsCollectionRemovedFromEventAnnotationFacetFactory extends FacetFactoryAbstract implements ServicesProviderAware {
+
+    private ServicesProvider servicesProvider;
+
+    public PostsCollectionRemovedFromEventAnnotationFacetFactory() {
+        super(FeatureType.COLLECTIONS_ONLY);
+    }
+
+    @Override
+    public void process(final ProcessMethodContext processMethodContext) {
+        final Method method = processMethodContext.getMethod();
+        FacetUtil.addFacet(create(method, processMethodContext.getFacetHolder()));
+    }
+
+    private PostsCollectionRemovedFromEventFacet create(Method method, final FacetHolder holder) {
+        final PostsCollectionRemovedFromEvent annotation = Annotations.getAnnotation(method, PostsCollectionRemovedFromEvent.class);
+        if(annotation == null) {
+            return null;
+        }
+        
+        final PropertyOrCollectionAccessorFacet getterFacet = holder.getFacet(PropertyOrCollectionAccessorFacet.class);
+        if(getterFacet == null) {
+            return null;
+        } 
+        final CollectionRemoveFromFacet collectionRemoveFromFacet = holder.getFacet(CollectionRemoveFromFacet.class);
+        if(collectionRemoveFromFacet == null) {
+            return null;
+        }
+        // the collectionRemoveFromFacet will end up as the underlying facet of the PostsCollectionRemovedFromEventFacetAnnotation
+
+        final Class<? extends CollectionRemovedFromEvent<?,?>> changedEventType = annotation.value();
+        final WrapperPolicy wrapperPolicy = annotation.wrapperPolicy();
+        return new PostsCollectionRemovedFromEventFacetAnnotation(changedEventType, wrapperPolicy, getterFacet, collectionRemoveFromFacet, servicesProvider, holder);
+    }
+
+    @Override
+    public void setServicesProvider(ServicesProvider servicesProvider) {
+        this.servicesProvider = servicesProvider;
+    }
+
+}

http://git-wip-us.apache.org/repos/asf/isis/blob/f8833040/core/metamodel/src/main/java/org/apache/isis/core/progmodel/facets/collections/event/PostsCollectionRemovedFromEventFacetAnnotation.java
----------------------------------------------------------------------
diff --git a/core/metamodel/src/main/java/org/apache/isis/core/progmodel/facets/collections/event/PostsCollectionRemovedFromEventFacetAnnotation.java b/core/metamodel/src/main/java/org/apache/isis/core/progmodel/facets/collections/event/PostsCollectionRemovedFromEventFacetAnnotation.java
new file mode 100644
index 0000000..a19b55d
--- /dev/null
+++ b/core/metamodel/src/main/java/org/apache/isis/core/progmodel/facets/collections/event/PostsCollectionRemovedFromEventFacetAnnotation.java
@@ -0,0 +1,167 @@
+/*
+ *  Licensed to the Apache Software Foundation (ASF) under one
+ *  or more contributor license agreements.  See the NOTICE file
+ *  distributed with this work for additional information
+ *  regarding copyright ownership.  The ASF licenses this file
+ *  to you under the Apache License, Version 2.0 (the
+ *  "License"); you may not use this file except in compliance
+ *  with the License.  You may obtain a copy of the License at
+ *
+ *        http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *  Unless required by applicable law or agreed to in writing,
+ *  software distributed under the License is distributed on an
+ *  "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ *  KIND, either express or implied.  See the License for the
+ *  specific language governing permissions and limitations
+ *  under the License.
+ */
+
+package org.apache.isis.core.progmodel.facets.collections.event;
+
+import java.lang.reflect.Field;
+import java.util.Collection;
+import java.util.List;
+
+import com.google.common.collect.Lists;
+
+import org.apache.isis.applib.FatalException;
+import org.apache.isis.applib.Identifier;
+import org.apache.isis.applib.annotation.WrapperPolicy;
+import org.apache.isis.applib.services.eventbus.CollectionRemovedFromEvent;
+import org.apache.isis.applib.services.eventbus.EventBusService;
+import org.apache.isis.core.metamodel.adapter.ObjectAdapter;
+import org.apache.isis.core.metamodel.adapter.ServicesProvider;
+import org.apache.isis.core.metamodel.adapter.util.AdapterUtils;
+import org.apache.isis.core.metamodel.facetapi.Facet;
+import org.apache.isis.core.metamodel.facetapi.FacetHolder;
+import org.apache.isis.core.metamodel.facets.accessor.PropertyOrCollectionAccessorFacet;
+import org.apache.isis.core.metamodel.facets.collections.event.PostsCollectionRemovedFromEventFacet;
+import org.apache.isis.core.metamodel.facets.collections.event.PostsCollectionRemovedFromEventFacetAbstract;
+import org.apache.isis.core.metamodel.facets.collections.modify.CollectionRemoveFromFacet;
+
+public class PostsCollectionRemovedFromEventFacetAnnotation extends
+		PostsCollectionRemovedFromEventFacetAbstract {
+
+	private final PropertyOrCollectionAccessorFacet getterFacet;
+	private final CollectionRemoveFromFacet collectionRemoveFromFacet;
+	private final ServicesProvider servicesProvider;
+
+	private EventBusService eventBusService;
+	private boolean searchedForEventBusService = false;
+
+	public PostsCollectionRemovedFromEventFacetAnnotation(
+			final Class<? extends CollectionRemovedFromEvent<?, ?>> eventType,
+			final WrapperPolicy wrapperPolicy,
+			final PropertyOrCollectionAccessorFacet getterFacet,
+			final CollectionRemoveFromFacet collectionRemoveFromFacet,
+			final ServicesProvider servicesProvider, final FacetHolder holder) {
+		super(eventType, wrapperPolicy, holder);
+		this.getterFacet = getterFacet;
+		this.collectionRemoveFromFacet = collectionRemoveFromFacet;
+		this.servicesProvider = servicesProvider;
+	}
+
+	@Override
+	public void remove(ObjectAdapter targetAdapter,
+			ObjectAdapter referencedObjectAdapter) {
+		if (this.collectionRemoveFromFacet == null) {
+			return;
+		}
+		eventBusService = getEventBusService();
+		if (eventBusService == null) {
+			collectionRemoveFromFacet.remove(targetAdapter,
+					referencedObjectAdapter);
+			return;
+		}
+
+		final Object referencedObject = AdapterUtils
+				.unwrap(referencedObjectAdapter);
+
+		// get hold of underlying collection
+		final Object collection = getterFacet.getProperty(targetAdapter);
+
+		// don't post event if the collections does not contain object
+		if (!((Collection<?>) collection).contains(referencedObject)) {
+			return;
+		}
+
+		// contains the element. So the event must be posted.
+		collectionRemoveFromFacet
+				.remove(targetAdapter, referencedObjectAdapter);
+
+		postEvent(targetAdapter, getIdentified().getIdentifier(),
+				referencedObject);
+	}
+
+	@SuppressWarnings({ "rawtypes", "unchecked" })
+	private void postEvent(final ObjectAdapter targetAdapter,
+			final Identifier identifier, final Object removedReference) {
+
+		final Object source = targetAdapter.getObject();
+		try {
+			final Class type = value();
+			final CollectionRemovedFromEvent<?, ?> event = newEvent(type, source,
+					identifier, removedReference);
+			eventBusService.post(event);
+		} catch (Exception e) {
+			throw new FatalException(e);
+		}
+	}
+
+	static <S, T> CollectionRemovedFromEvent<S, T> newEvent(
+			final Class<? extends CollectionRemovedFromEvent<S, T>> type,
+			final S source, final Identifier identifier, final T value)
+			throws InstantiationException, IllegalAccessException,
+			NoSuchFieldException {
+		final CollectionRemovedFromEvent<S, T> event = type.newInstance();
+
+		setField("source", event, source);
+		setField("identifier", event, identifier);
+		setField("value", event, value);
+		return event;
+	}
+
+	private static void setField(final String name,
+			final CollectionRemovedFromEvent<?, ?> event, final Object sourceValue)
+			throws NoSuchFieldException, IllegalAccessException {
+		final Field sourceField = CollectionRemovedFromEvent.class
+				.getDeclaredField(name);
+		sourceField.setAccessible(true);
+		sourceField.set(event, sourceValue);
+	}
+
+	private EventBusService getEventBusService() {
+		if (!searchedForEventBusService) {
+			final List<ObjectAdapter> serviceAdapters = servicesProvider
+					.getServices();
+			for (ObjectAdapter serviceAdapter : serviceAdapters) {
+				final Object service = serviceAdapter.getObject();
+				if (service instanceof EventBusService) {
+					eventBusService = (EventBusService) service;
+					break;
+				}
+			}
+		}
+		searchedForEventBusService = true;
+		return eventBusService;
+	}
+
+	// //////////////////////////////////////
+	// MultiTypedFacet
+	// //////////////////////////////////////
+
+	@SuppressWarnings("unchecked")
+	@Override
+	public Class<? extends Facet>[] facetTypes() {
+		return Lists.newArrayList(type(), // ie CollectionRemoveFromFacet
+				PostsCollectionRemovedFromEventFacet.class).toArray(new Class[] {});
+	}
+
+	@SuppressWarnings("unchecked")
+	@Override
+	public <T extends Facet> T getFacet(Class<T> facet) {
+		return (T) this;
+	}
+
+}

http://git-wip-us.apache.org/repos/asf/isis/blob/f8833040/core/metamodel/src/main/java/org/apache/isis/progmodels/dflt/ProgrammingModelFacetsJava5.java
----------------------------------------------------------------------
diff --git a/core/metamodel/src/main/java/org/apache/isis/progmodels/dflt/ProgrammingModelFacetsJava5.java b/core/metamodel/src/main/java/org/apache/isis/progmodels/dflt/ProgrammingModelFacetsJava5.java
index 1e4598c..ca75555 100644
--- a/core/metamodel/src/main/java/org/apache/isis/progmodels/dflt/ProgrammingModelFacetsJava5.java
+++ b/core/metamodel/src/main/java/org/apache/isis/progmodels/dflt/ProgrammingModelFacetsJava5.java
@@ -48,6 +48,7 @@ import org.apache.isis.core.progmodel.facets.collections.clear.CollectionClearFa
 import org.apache.isis.core.progmodel.facets.collections.collection.CollectionFacetFactory;
 import org.apache.isis.core.progmodel.facets.collections.disabled.fromimmutable.DisabledFacetForCollectionDerivedFromImmutableTypeFacetFactory;
 import org.apache.isis.core.progmodel.facets.collections.event.PostsCollectionAddedToEventAnnotationFacetFactory;
+import org.apache.isis.core.progmodel.facets.collections.event.PostsCollectionRemovedFromEventAnnotationFacetFactory;
 import org.apache.isis.core.progmodel.facets.collections.modify.CollectionAddRemoveAndValidateFacetFactory;
 import org.apache.isis.core.progmodel.facets.collections.notpersisted.annotation.NotPersistedAnnotationForCollectionFacetFactory;
 import org.apache.isis.core.progmodel.facets.collections.sortedby.SortedByAnnotationFacetFactory;
@@ -366,6 +367,7 @@ public final class ProgrammingModelFacetsJava5 extends ProgrammingModelAbstract
         // must come after the property/collection/action accessor+mutator facet factories
         addFactory(PostsPropertyChangedEventAnnotationFacetFactory.class);
         addFactory(PostsCollectionAddedToEventAnnotationFacetFactory.class);
+        addFactory(PostsCollectionRemovedFromEventAnnotationFacetFactory.class);
 
         
         addFactory(ImmutableMarkerInterfaceFacetFactory.class);

http://git-wip-us.apache.org/repos/asf/isis/blob/f8833040/core/metamodel/src/test/java/org/apache/isis/core/progmodel/facets/collections/event/PostsCollectionRemovedEventFacetAnnotationTest_newEvent.java
----------------------------------------------------------------------
diff --git a/core/metamodel/src/test/java/org/apache/isis/core/progmodel/facets/collections/event/PostsCollectionRemovedEventFacetAnnotationTest_newEvent.java b/core/metamodel/src/test/java/org/apache/isis/core/progmodel/facets/collections/event/PostsCollectionRemovedEventFacetAnnotationTest_newEvent.java
new file mode 100644
index 0000000..a713a74
--- /dev/null
+++ b/core/metamodel/src/test/java/org/apache/isis/core/progmodel/facets/collections/event/PostsCollectionRemovedEventFacetAnnotationTest_newEvent.java
@@ -0,0 +1,50 @@
+/**
+ *  Licensed to the Apache Software Foundation (ASF) under one or more
+ *  contributor license agreements.  See the NOTICE file distributed with
+ *  this work for additional information regarding copyright ownership.
+ *  The ASF licenses this file to You under the Apache License, Version 2.0
+ *  (the "License"); you may not use this file except in compliance with
+ *  the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *  Unless required by applicable law or agreed to in writing, software
+ *  distributed under the License is distributed on an "AS IS" BASIS,
+ *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ *  See the License for the specific language governing permissions and
+ *  limitations under the License.
+ */
+package org.apache.isis.core.progmodel.facets.collections.event;
+
+import static org.hamcrest.CoreMatchers.is;
+import static org.junit.Assert.assertThat;
+
+import java.util.Set;
+
+import org.junit.Test;
+import org.apache.isis.applib.Identifier;
+import org.apache.isis.applib.services.eventbus.CollectionRemovedFromEvent;
+
+public class PostsCollectionRemovedEventFacetAnnotationTest_newEvent {
+
+    public static class SomeDomainObject {
+        public Set<SomeReferencedObject> getReferences() { return null; }
+    }
+    public static class SomeReferencedObject {}
+    
+    public static class SomeDomainObjectCollectionRemovedFromEvent extends CollectionRemovedFromEvent<SomeDomainObject, SomeReferencedObject> {}
+    
+    @Test
+    public void test() throws Exception {
+        SomeDomainObject sdo = new SomeDomainObject();
+        SomeReferencedObject other = new SomeReferencedObject();
+        Identifier identifier = Identifier.propertyOrCollectionIdentifier(SomeDomainObject.class, "references");
+
+        final CollectionRemovedFromEvent<SomeDomainObject, SomeReferencedObject> ev = PostsCollectionRemovedFromEventFacetAnnotation.newEvent(
+                SomeDomainObjectCollectionRemovedFromEvent.class, sdo, identifier, other);
+        assertThat(ev.getSource(), is(sdo));
+        assertThat(ev.getIdentifier(), is(identifier));
+        assertThat(ev.getValue(), is(other));
+    }
+
+}

http://git-wip-us.apache.org/repos/asf/isis/blob/f8833040/example/application/quickstart_wicket_restful_jdo/dom/src/main/java/dom/todo/ToDoItem.java
----------------------------------------------------------------------
diff --git a/example/application/quickstart_wicket_restful_jdo/dom/src/main/java/dom/todo/ToDoItem.java b/example/application/quickstart_wicket_restful_jdo/dom/src/main/java/dom/todo/ToDoItem.java
index 5f9fc1d..6f81049 100644
--- a/example/application/quickstart_wicket_restful_jdo/dom/src/main/java/dom/todo/ToDoItem.java
+++ b/example/application/quickstart_wicket_restful_jdo/dom/src/main/java/dom/todo/ToDoItem.java
@@ -488,6 +488,7 @@ public class ToDoItem implements Comparable<ToDoItem> {
     private SortedSet<ToDoItem> dependencies = new TreeSet<ToDoItem>();
 
     @PostsCollectionAddedToEvent(wrapperPolicy=WrapperPolicy.SKIP_RULES)
+    @PostsCollectionRemovedFromEvent(wrapperPolicy=WrapperPolicy.SKIP_RULES)
     @SortedBy(DependenciesComparator.class)
     public SortedSet<ToDoItem> getDependencies() {
         return dependencies;
@@ -508,6 +509,9 @@ public class ToDoItem implements Comparable<ToDoItem> {
     public ToDoItem add(
             @TypicalLength(20)
             final ToDoItem toDoItem) {
+    	// By wrapping the call, Isis will detect that the collection is modified 
+    	// and it will automatically send a CollectionAddedToEvent to the Event Bus.
+    	// See ToDoItemSubscriptions.
         wrapperFactory.wrap(this).addToDependencies(toDoItem);
         return this;
     }
@@ -538,7 +542,10 @@ public class ToDoItem implements Comparable<ToDoItem> {
     public ToDoItem remove(
             @TypicalLength(20)
             final ToDoItem toDoItem) {
-        this.removeFromDependencies(toDoItem);
+    	// By wrapping the call, Isis will detect that the collection is modified 
+    	// and it will automatically send a CollectionRemovedFromEvent to the Event Bus.
+    	// See ToDoItemSubscriptions.
+        wrapperFactory.wrap(this).removeFromDependencies(toDoItem);
         return this;
     }
     // disable action dependent on state of object

http://git-wip-us.apache.org/repos/asf/isis/blob/f8833040/example/application/quickstart_wicket_restful_jdo/dom/src/main/java/dom/todo/ToDoItemSubscriptions.java
----------------------------------------------------------------------
diff --git a/example/application/quickstart_wicket_restful_jdo/dom/src/main/java/dom/todo/ToDoItemSubscriptions.java b/example/application/quickstart_wicket_restful_jdo/dom/src/main/java/dom/todo/ToDoItemSubscriptions.java
index 0a4b02f..15623bb 100644
--- a/example/application/quickstart_wicket_restful_jdo/dom/src/main/java/dom/todo/ToDoItemSubscriptions.java
+++ b/example/application/quickstart_wicket_restful_jdo/dom/src/main/java/dom/todo/ToDoItemSubscriptions.java
@@ -23,6 +23,7 @@ import com.google.common.eventbus.Subscribe;
 import org.apache.isis.applib.DomainObjectContainer;
 import org.apache.isis.applib.annotation.Programmatic;
 import org.apache.isis.applib.services.eventbus.CollectionAddedToEvent;
+import org.apache.isis.applib.services.eventbus.CollectionRemovedFromEvent;
 import org.apache.isis.applib.services.eventbus.EventBusService;
 import org.apache.isis.applib.services.eventbus.PropertyChangedEvent;
 
@@ -50,6 +51,12 @@ public class ToDoItemSubscriptions {
         LOG.info(container.titleOf(ev.getSource()) + ", added to " + ev.getIdentifier().getMemberName() + " : " + ev.getValue());
     }
     
+    @Programmatic
+    @Subscribe
+    public void on(CollectionRemovedFromEvent<?,?> ev) {
+        LOG.info(container.titleOf(ev.getSource()) + ", removed from " + ev.getIdentifier().getMemberName() + " : " + ev.getValue());
+    }
+    
     //region > injected services
     // //////////////////////////////////////
     

http://git-wip-us.apache.org/repos/asf/isis/blob/f8833040/example/application/quickstart_wicket_restful_jdo/integtests/src/test/java/integration/tests/events/ToDoItemTest_dependencies_addedEvent.java
----------------------------------------------------------------------
diff --git a/example/application/quickstart_wicket_restful_jdo/integtests/src/test/java/integration/tests/events/ToDoItemTest_dependencies_addedEvent.java b/example/application/quickstart_wicket_restful_jdo/integtests/src/test/java/integration/tests/events/ToDoItemTest_dependencies_addedEvent.java
new file mode 100644
index 0000000..6cfd491
--- /dev/null
+++ b/example/application/quickstart_wicket_restful_jdo/integtests/src/test/java/integration/tests/events/ToDoItemTest_dependencies_addedEvent.java
@@ -0,0 +1,85 @@
+/*
+ *  Licensed to the Apache Software Foundation (ASF) under one
+ *  or more contributor license agreements.  See the NOTICE file
+ *  distributed with this work for additional information
+ *  regarding copyright ownership.  The ASF licenses this file
+ *  to you under the Apache License, Version 2.0 (the
+ *  "License"); you may not use this file except in compliance
+ *  with the License.  You may obtain a copy of the License at
+ *
+ *        http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *  Unless required by applicable law or agreed to in writing,
+ *  software distributed under the License is distributed on an
+ *  "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ *  KIND, either express or implied.  See the License for the
+ *  specific language governing permissions and limitations
+ *  under the License.
+ */
+package integration.tests.events;
+
+import integration.tests.ToDoIntegTest;
+
+import java.util.List;
+
+import dom.todo.ToDoItem;
+import dom.todo.ToDoItems;
+import fixture.todo.ToDoItemsFixture;
+
+import org.apache.isis.applib.annotation.Programmatic;
+import org.apache.isis.applib.services.eventbus.CollectionAddedToEvent;
+import org.apache.isis.applib.services.eventbus.EventBusService;
+import org.junit.After;
+import org.junit.Before;
+import org.junit.Test;
+
+import com.google.common.eventbus.Subscribe;
+
+public class ToDoItemTest_dependencies_addedEvent extends ToDoIntegTest {
+
+    private ToDoItem toDoItem;
+    private ToDoItem otherToDoItem;
+    private EventBusService eventBusService;
+    
+    
+    public class TestSubscription {
+    	
+        @Programmatic
+        @Subscribe
+        public Boolean on(CollectionAddedToEvent<?,?> ev) {
+            return true;
+        }
+    	
+    }
+    
+
+    @Before
+    public void setUp() throws Exception {
+        scenarioExecution().install(new ToDoItemsFixture());
+
+        final List<ToDoItem> items = wrap(service(ToDoItems.class)).notYetComplete();
+        toDoItem = wrap(items.get(0));
+        otherToDoItem = items.get(1); // wrapping this seems to trip up cglib :-(
+        eventBusService = this.service(EventBusService.class);
+        
+        // Register new Service.
+        
+    }
+
+    @After
+    public void tearDown() throws Exception {
+        unwrap(toDoItem).getDependencies().clear();
+    }
+
+    @Test
+    public void collectionAddedToEventReceived() throws Exception {
+
+        // given
+        
+        // when
+        toDoItem.add(otherToDoItem);
+        
+        // then
+    }
+
+}
\ No newline at end of file


[09/16] git commit: ISIS-550: minor refactoring of InvocationResult

Posted by da...@apache.org.
ISIS-550: minor refactoring of InvocationResult

- make nested static class
- use factory methods to avoid boolean in method signature.


Project: http://git-wip-us.apache.org/repos/asf/isis/repo
Commit: http://git-wip-us.apache.org/repos/asf/isis/commit/c1a25966
Tree: http://git-wip-us.apache.org/repos/asf/isis/tree/c1a25966
Diff: http://git-wip-us.apache.org/repos/asf/isis/diff/c1a25966

Branch: refs/heads/master
Commit: c1a259667282c21654435bcae22ee39f8e8bbefb
Parents: cfcb201
Author: Dan Haywood <da...@haywood-associates.co.uk>
Authored: Sat May 10 07:24:04 2014 +0100
Committer: Dan Haywood <da...@haywood-associates.co.uk>
Committed: Sat May 10 07:24:04 2014 +0100

----------------------------------------------------------------------
 .../invoke/ActionInvocationFacetViaMethod.java  | 55 ++++++++++++++------
 .../PostsActionInvokedEventFacetViaMethod.java  |  4 +-
 2 files changed, 40 insertions(+), 19 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/isis/blob/c1a25966/core/metamodel/src/main/java/org/apache/isis/core/progmodel/facets/actions/invoke/ActionInvocationFacetViaMethod.java
----------------------------------------------------------------------
diff --git a/core/metamodel/src/main/java/org/apache/isis/core/progmodel/facets/actions/invoke/ActionInvocationFacetViaMethod.java b/core/metamodel/src/main/java/org/apache/isis/core/progmodel/facets/actions/invoke/ActionInvocationFacetViaMethod.java
index c8f81d3..4f9dfbf 100644
--- a/core/metamodel/src/main/java/org/apache/isis/core/progmodel/facets/actions/invoke/ActionInvocationFacetViaMethod.java
+++ b/core/metamodel/src/main/java/org/apache/isis/core/progmodel/facets/actions/invoke/ActionInvocationFacetViaMethod.java
@@ -122,27 +122,48 @@ public class ActionInvocationFacetViaMethod extends ActionInvocationFacetAbstrac
     
     	// Can return null both because the action finally was not invoked 
     	// or because it returned null.
-    	return internalInvoke(owningAction, targetAdapter, arguments).getResult();
+    	return internalInvoke(owningAction, targetAdapter, arguments).getAdapter();
     	
     }
-    
-    public class InvocationResult {
-    	
-    	private final Boolean wasInvoked;
-    	private final ObjectAdapter result;
+
+    /**
+     * Introduced to disambiguate the meaning of <tt>null</tt> as a return value of
+     * {@link ActionInvocationFacetViaMethod#invoke(ObjectAdapter, ObjectAdapter[])}
+     */
+    public static class InvocationResult {
+
+        public static InvocationResult forActionThatReturned(final ObjectAdapter resultAdapter) {
+            return new InvocationResult(true, resultAdapter);
+        }
+
+        public static InvocationResult forActionNotInvoked() {
+            return new InvocationResult(false, null);
+        }
+
+    	private final boolean whetherInvoked;
+    	private final ObjectAdapter adapter;
     	
-    	public InvocationResult(Boolean invoked, ObjectAdapter result) {
-    		this.wasInvoked = invoked;
-    		this.result = result;
+    	private InvocationResult(final boolean whetherInvoked, final ObjectAdapter result) {
+    		this.whetherInvoked = whetherInvoked;
+    		this.adapter = result;
     	}
 
-		public Boolean getWasInvoked() {
-			return wasInvoked;
+		public boolean getWhetherInvoked() {
+			return whetherInvoked;
 		}
 
-		public ObjectAdapter getResult() {
-			return result;
+		/**
+		 * Returns the result, or null if either the action invocation returned null or 
+		 * if the action was never invoked in the first place.
+		 * 
+		 * <p>
+		 * Use {@link #getWhetherInvoked()} to distinguish between these two cases.
+		 */
+		public ObjectAdapter getAdapter() {
+			return adapter;
 		}
+
+
     	
     }
     
@@ -226,7 +247,7 @@ public class ActionInvocationFacetViaMethod extends ActionInvocationFacetAbstrac
                 if(commandService.persistIfPossible(command)) {
                     // force persistence, then return the command itself.
                     final ObjectAdapter resultAdapter = getAdapterManager().adapterFor(command);
-                    return new InvocationResult(true, resultAdapter);
+                    return InvocationResult.forActionThatReturned(resultAdapter);
                 } else {
                     throw new IsisException(
                             "Unable to schedule action '"
@@ -247,7 +268,7 @@ public class ActionInvocationFacetViaMethod extends ActionInvocationFacetAbstrac
                     LOG.debug(" action result " + result);
                 }
                 if (result == null) {
-                	return new InvocationResult(true, null);
+                	return InvocationResult.forActionThatReturned(null);
                 }
 
                 final ObjectAdapter resultAdapter = getAdapterManager().adapterFor(result);
@@ -269,7 +290,7 @@ public class ActionInvocationFacetViaMethod extends ActionInvocationFacetAbstrac
                             ? new CurrentInvocation(targetAdapter, getIdentified(), arguments, resultAdapter, command)
                             :null);
                 
-                return new InvocationResult(true, resultAdapter);
+                return InvocationResult.forActionThatReturned(resultAdapter);
             }
 
         } catch (final IllegalArgumentException e) {
@@ -292,7 +313,7 @@ public class ActionInvocationFacetViaMethod extends ActionInvocationFacetAbstrac
             ThrowableExtensions.throwWithinIsisException(e, "Exception executing " + method);
             
             // Action was not invoked (an Exception was thrown)
-            return new InvocationResult(false, null);
+            return InvocationResult.forActionNotInvoked();
         } catch (final IllegalAccessException e) {
             throw new ReflectiveActionException("Illegal access of " + method, e);
         }

http://git-wip-us.apache.org/repos/asf/isis/blob/c1a25966/core/metamodel/src/main/java/org/apache/isis/core/progmodel/facets/actions/invoke/event/PostsActionInvokedEventFacetViaMethod.java
----------------------------------------------------------------------
diff --git a/core/metamodel/src/main/java/org/apache/isis/core/progmodel/facets/actions/invoke/event/PostsActionInvokedEventFacetViaMethod.java b/core/metamodel/src/main/java/org/apache/isis/core/progmodel/facets/actions/invoke/event/PostsActionInvokedEventFacetViaMethod.java
index 7e22b78..16f2fb7 100644
--- a/core/metamodel/src/main/java/org/apache/isis/core/progmodel/facets/actions/invoke/event/PostsActionInvokedEventFacetViaMethod.java
+++ b/core/metamodel/src/main/java/org/apache/isis/core/progmodel/facets/actions/invoke/event/PostsActionInvokedEventFacetViaMethod.java
@@ -69,12 +69,12 @@ public class PostsActionInvokedEventFacetViaMethod extends ActionInvocationFacet
     	final InvocationResult invocationResult = this.internalInvoke(owningAction, targetAdapter, arguments);
     	
     	// Perhaps the Action was not properly invoked (i.e. an exception was raised).
-    	if (invocationResult.getWasInvoked()) {
+    	if (invocationResult.getWhetherInvoked()) {
     		// If invoked, then send the ActionInvokedEvent to the EventBus.
     		postEvent(owningAction, targetAdapter, arguments);
     	}
     	
-    	return invocationResult.getResult();
+    	return invocationResult.getAdapter();
     	
     }
     


[03/16] ISIS-550: PostsCollectionAddToEvent first-cut impl

Posted by da...@apache.org.
http://git-wip-us.apache.org/repos/asf/isis/blob/2637a055/core/metamodel/src/test/java/org/apache/isis/core/metamodel/facets/ImperativeFacetUtilsTest.java
----------------------------------------------------------------------
diff --git a/core/metamodel/src/test/java/org/apache/isis/core/metamodel/facets/ImperativeFacetUtilsTest.java b/core/metamodel/src/test/java/org/apache/isis/core/metamodel/facets/ImperativeFacetUtilsTest.java
index 23238d9..5efadc3 100644
--- a/core/metamodel/src/test/java/org/apache/isis/core/metamodel/facets/ImperativeFacetUtilsTest.java
+++ b/core/metamodel/src/test/java/org/apache/isis/core/metamodel/facets/ImperativeFacetUtilsTest.java
@@ -19,8 +19,15 @@
 
 package org.apache.isis.core.metamodel.facets;
 
+import static org.hamcrest.CoreMatchers.is;
+import static org.hamcrest.CoreMatchers.not;
+import static org.hamcrest.CoreMatchers.nullValue;
+import static org.junit.Assert.assertThat;
+
 import java.lang.reflect.Method;
+
 import com.google.common.collect.Lists;
+
 import org.jmock.Expectations;
 import org.jmock.Mockery;
 import org.jmock.integration.junit4.JMock;
@@ -28,15 +35,12 @@ import org.jmock.integration.junit4.JUnit4Mockery;
 import org.junit.Before;
 import org.junit.Test;
 import org.junit.runner.RunWith;
+
 import org.apache.isis.applib.filter.Filter;
 import org.apache.isis.core.metamodel.facetapi.Facet;
-import org.apache.isis.core.metamodel.facets.ImperativeFacetUtils.ImperativeFacetFlags;
 import org.apache.isis.core.metamodel.spec.feature.ObjectMember;
 import org.apache.isis.core.unittestsupport.jmocking.JavassistImposteriser;
 
-import static org.hamcrest.CoreMatchers.*;
-import static org.junit.Assert.assertThat;
-
 @RunWith(JMock.class)
 public class ImperativeFacetUtilsTest {
 
@@ -78,7 +82,7 @@ public class ImperativeFacetUtilsTest {
                 will(returnValue(Lists.newArrayList()));
             }
         });
-        final ImperativeFacetFlags flags = ImperativeFacetUtils.getImperativeFacetFlags(mockObjectMember, method);
+        final ImperativeFacet.Flags flags = ImperativeFacetUtils.getImperativeFacetFlags(mockObjectMember, method);
         assertThat(flags, is(not(nullValue())));
         assertThat(flags.impliesResolve(), is(false));
         assertThat(flags.impliesObjectChanged(), is(false));
@@ -94,7 +98,7 @@ public class ImperativeFacetUtilsTest {
                 will(returnValue(Lists.newArrayList((Facet) imperativeFacet)));
             }
         });
-        final ImperativeFacetFlags flags = ImperativeFacetUtils.getImperativeFacetFlags(mockObjectMember, method);
+        final ImperativeFacet.Flags flags = ImperativeFacetUtils.getImperativeFacetFlags(mockObjectMember, method);
         assertThat(flags, is(not(nullValue())));
         // TODO: need more tests here, these don't go deep enough...
     }

http://git-wip-us.apache.org/repos/asf/isis/blob/2637a055/core/metamodel/src/test/java/org/apache/isis/core/progmodel/facets/collections/event/PostsCollectionAddedEventFacetAnnotationTest_newEvent.java
----------------------------------------------------------------------
diff --git a/core/metamodel/src/test/java/org/apache/isis/core/progmodel/facets/collections/event/PostsCollectionAddedEventFacetAnnotationTest_newEvent.java b/core/metamodel/src/test/java/org/apache/isis/core/progmodel/facets/collections/event/PostsCollectionAddedEventFacetAnnotationTest_newEvent.java
index 5f22cc4..c4f15c9 100644
--- a/core/metamodel/src/test/java/org/apache/isis/core/progmodel/facets/collections/event/PostsCollectionAddedEventFacetAnnotationTest_newEvent.java
+++ b/core/metamodel/src/test/java/org/apache/isis/core/progmodel/facets/collections/event/PostsCollectionAddedEventFacetAnnotationTest_newEvent.java
@@ -19,23 +19,33 @@ package org.apache.isis.core.progmodel.facets.collections.event;
 import static org.hamcrest.CoreMatchers.is;
 import static org.junit.Assert.assertThat;
 
-import org.joda.time.LocalDate;
+import java.util.Set;
+
 import org.junit.Test;
 
-import org.apache.isis.applib.services.eventbus.PropertyChangedEvent;
+import org.apache.isis.applib.Identifier;
+import org.apache.isis.applib.services.eventbus.CollectionAddedToEvent;
 
 public class PostsCollectionAddedEventFacetAnnotationTest_newEvent {
 
-    public static class SomeDomainObject {}
+    public static class SomeDomainObject {
+        public Set<SomeReferencedObject> getReferences() { return null; }
+    }
+    public static class SomeReferencedObject {}
+    
+    public static class SomeDomainObjectCollectionAddedToEvent extends CollectionAddedToEvent<SomeDomainObject, SomeReferencedObject> {}
     
-//    public static class SomeDomainObjectCollectionAddedEvent extends AddToCollectionEvent<SomeDomainObject, SomeDomainObject> {}
-//    
-//    @Test
-//    public void test() throws Exception {
-//        SomeDomainObject sdo = new SomeDomainObject();
-//        final PropertyChangedEvent<SomeDomainObject, LocalDate> ev = PostsPropertyChangedEventFacetAnnotation.newEvent(SomeDatePropertyChangedEvent.class, new SomeDomainObject(), sdo);
-//        assertThat(ev.getSource(), is(sdo));
-//        assertThat(ev.getNewValue(), is(new LocalDate(2013,4,1)));
-//    }
+    @Test
+    public void test() throws Exception {
+        SomeDomainObject sdo = new SomeDomainObject();
+        SomeReferencedObject other = new SomeReferencedObject();
+        Identifier identifier = Identifier.propertyOrCollectionIdentifier(SomeDomainObject.class, "references");
+
+        final CollectionAddedToEvent<SomeDomainObject, SomeReferencedObject> ev = PostsCollectionAddedToEventFacetAnnotation.newEvent(
+                SomeDomainObjectCollectionAddedToEvent.class, sdo, identifier, other);
+        assertThat(ev.getSource(), is(sdo));
+        assertThat(ev.getIdentifier(), is(identifier));
+        assertThat(ev.getValue(), is(other));
+    }
 
 }

http://git-wip-us.apache.org/repos/asf/isis/blob/2637a055/core/metamodel/src/test/java/org/apache/isis/core/progmodel/facets/properties/event/PostsPropertyChangedEventFacetAnnotationTest_newEvent.java
----------------------------------------------------------------------
diff --git a/core/metamodel/src/test/java/org/apache/isis/core/progmodel/facets/properties/event/PostsPropertyChangedEventFacetAnnotationTest_newEvent.java b/core/metamodel/src/test/java/org/apache/isis/core/progmodel/facets/properties/event/PostsPropertyChangedEventFacetAnnotationTest_newEvent.java
index 972aea6..f997473 100644
--- a/core/metamodel/src/test/java/org/apache/isis/core/progmodel/facets/properties/event/PostsPropertyChangedEventFacetAnnotationTest_newEvent.java
+++ b/core/metamodel/src/test/java/org/apache/isis/core/progmodel/facets/properties/event/PostsPropertyChangedEventFacetAnnotationTest_newEvent.java
@@ -22,6 +22,7 @@ import static org.junit.Assert.assertThat;
 import org.joda.time.LocalDate;
 import org.junit.Test;
 
+import org.apache.isis.applib.Identifier;
 import org.apache.isis.applib.services.eventbus.PropertyChangedEvent;
 
 public class PostsPropertyChangedEventFacetAnnotationTest_newEvent {
@@ -32,11 +33,18 @@ public class PostsPropertyChangedEventFacetAnnotationTest_newEvent {
     
     @Test
     public void test() throws Exception {
+
         SomeDomainObject sdo = new SomeDomainObject();
-        final PropertyChangedEvent<SomeDomainObject, LocalDate> ev = PostsPropertyChangedEventFacetAnnotation.newEvent(SomeDatePropertyChangedEvent.class, new LocalDate(2013,4,1), new LocalDate(2013,5,2), sdo);
+        Identifier identifier = Identifier.propertyOrCollectionIdentifier(SomeDomainObject.class, "someDateProperty");
+        LocalDate oldValue = new LocalDate(2013,4,1);
+        LocalDate newValue = new LocalDate(2013,5,2);
+        
+        final PropertyChangedEvent<SomeDomainObject, LocalDate> ev = 
+                PostsPropertyChangedEventFacetAnnotation.newEvent(SomeDatePropertyChangedEvent.class, sdo, identifier, oldValue, newValue);
         assertThat(ev.getSource(), is(sdo));
-        assertThat(ev.getOldValue(), is(new LocalDate(2013,4,1)));
-        assertThat(ev.getNewValue(), is(new LocalDate(2013,5,2)));
+        assertThat(ev.getIdentifier(), is(identifier));
+        assertThat(ev.getOldValue(), is(oldValue));
+        assertThat(ev.getNewValue(), is(newValue));
     }
 
 }

http://git-wip-us.apache.org/repos/asf/isis/blob/2637a055/core/wrapper/src/main/java/org/apache/isis/core/wrapper/handlers/AbstractCollectionInvocationHandler.java
----------------------------------------------------------------------
diff --git a/core/wrapper/src/main/java/org/apache/isis/core/wrapper/handlers/AbstractCollectionInvocationHandler.java b/core/wrapper/src/main/java/org/apache/isis/core/wrapper/handlers/AbstractCollectionInvocationHandler.java
index ab1e808..b8a4464 100644
--- a/core/wrapper/src/main/java/org/apache/isis/core/wrapper/handlers/AbstractCollectionInvocationHandler.java
+++ b/core/wrapper/src/main/java/org/apache/isis/core/wrapper/handlers/AbstractCollectionInvocationHandler.java
@@ -23,14 +23,17 @@ import java.lang.reflect.Method;
 import java.util.ArrayList;
 import java.util.List;
 
+import com.google.common.collect.Lists;
+
 import org.apache.isis.applib.events.CollectionMethodEvent;
 import org.apache.isis.applib.events.InteractionEvent;
 import org.apache.isis.core.metamodel.spec.feature.OneToManyAssociation;
 
 abstract class AbstractCollectionInvocationHandler<T, C> extends DelegatingInvocationHandlerDefault<C> {
 
-    private final List<Method> interceptedMethods = new ArrayList<Method>();
-    private final List<Method> vetoedMethods = new ArrayList<Method>();
+    private final List<Method> interceptedMethods = Lists.newArrayList();
+    private final List<Method> vetoedMethods = Lists.newArrayList();
+
     private final String collectionName;
     private final OneToManyAssociation oneToManyAssociation;
     private final T domainObject;

http://git-wip-us.apache.org/repos/asf/isis/blob/2637a055/core/wrapper/src/main/java/org/apache/isis/core/wrapper/handlers/DomainObjectInvocationHandler.java
----------------------------------------------------------------------
diff --git a/core/wrapper/src/main/java/org/apache/isis/core/wrapper/handlers/DomainObjectInvocationHandler.java b/core/wrapper/src/main/java/org/apache/isis/core/wrapper/handlers/DomainObjectInvocationHandler.java
index 93b6d6b..1dc2293 100644
--- a/core/wrapper/src/main/java/org/apache/isis/core/wrapper/handlers/DomainObjectInvocationHandler.java
+++ b/core/wrapper/src/main/java/org/apache/isis/core/wrapper/handlers/DomainObjectInvocationHandler.java
@@ -27,6 +27,7 @@ import java.util.List;
 import java.util.Map;
 
 import org.apache.isis.applib.annotation.Where;
+import org.apache.isis.applib.annotation.WrapperPolicy;
 import org.apache.isis.applib.events.CollectionAccessEvent;
 import org.apache.isis.applib.events.InteractionEvent;
 import org.apache.isis.applib.events.ObjectTitleEvent;
@@ -40,8 +41,8 @@ import org.apache.isis.applib.services.wrapper.HiddenException;
 import org.apache.isis.applib.services.wrapper.InteractionException;
 import org.apache.isis.applib.services.wrapper.InvalidException;
 import org.apache.isis.applib.services.wrapper.WrapperFactory;
-import org.apache.isis.applib.services.wrapper.WrapperObject;
 import org.apache.isis.applib.services.wrapper.WrapperFactory.ExecutionMode;
+import org.apache.isis.applib.services.wrapper.WrapperObject;
 import org.apache.isis.core.commons.authentication.AuthenticationSession;
 import org.apache.isis.core.commons.authentication.AuthenticationSessionProvider;
 import org.apache.isis.core.metamodel.adapter.ObjectAdapter;
@@ -54,6 +55,7 @@ import org.apache.isis.core.metamodel.consent.InteractionResult;
 import org.apache.isis.core.metamodel.facetapi.DecoratingFacet;
 import org.apache.isis.core.metamodel.facetapi.Facet;
 import org.apache.isis.core.metamodel.facets.ImperativeFacet;
+import org.apache.isis.core.metamodel.facets.PostsEventWithWrapperPolicy;
 import org.apache.isis.core.metamodel.facets.accessor.PropertyOrCollectionAccessorFacet;
 import org.apache.isis.core.metamodel.facets.actions.choices.ActionChoicesFacet;
 import org.apache.isis.core.metamodel.facets.actions.defaults.ActionDefaultsFacet;
@@ -62,6 +64,7 @@ import org.apache.isis.core.metamodel.facets.collections.modify.CollectionRemove
 import org.apache.isis.core.metamodel.facets.param.choices.ActionParameterChoicesFacet;
 import org.apache.isis.core.metamodel.facets.properties.choices.PropertyChoicesFacet;
 import org.apache.isis.core.metamodel.facets.properties.defaults.PropertyDefaultFacet;
+import org.apache.isis.core.metamodel.facets.properties.modify.PropertyClearFacet;
 import org.apache.isis.core.metamodel.facets.properties.modify.PropertyInitializationFacet;
 import org.apache.isis.core.metamodel.facets.properties.modify.PropertySetterFacet;
 import org.apache.isis.core.metamodel.interactions.ObjectTitleContext;
@@ -176,9 +179,6 @@ public class DomainObjectInvocationHandler<T> extends DelegatingInvocationHandle
             return method.invoke(getDelegate(), args);
         }
 
-        // for all members, check visibility and usability
-        checkVisibility(getAuthenticationSession(), targetAdapter, objectMember);
-
         if (objectMember.isOneToOneAssociation()) {
 
             if (instanceOf(imperativeFacets, PropertyValidateFacetViaMethod.class, PropertySetterFacetViaModifyMethod.class, PropertyClearFacetViaClearMethod.class)) {
@@ -186,11 +186,12 @@ public class DomainObjectInvocationHandler<T> extends DelegatingInvocationHandle
             }
 
             final OneToOneAssociation otoa = (OneToOneAssociation) objectMember;
+            
             if (instanceOf(imperativeFacets, PropertyOrCollectionAccessorFacet.class)) {
                 return handleGetterMethodOnProperty(args, targetAdapter, otoa, methodName);
             }
+            
             if (instanceOf(imperativeFacets, PropertySetterFacet.class, PropertyInitializationFacet.class)) {
-                checkUsability(getAuthenticationSession(), targetAdapter, objectMember);
                 return handleSetterMethodOnProperty(args, getAuthenticationSession(), targetAdapter, otoa, methodName);
             }
         }
@@ -200,16 +201,15 @@ public class DomainObjectInvocationHandler<T> extends DelegatingInvocationHandle
                 throw new UnsupportedOperationException(String.format("Cannot invoke supporting method '%s'; use only collection accessor/mutator", memberName));
             }
 
+
             final OneToManyAssociation otma = (OneToManyAssociation) objectMember;
             if (instanceOf(imperativeFacets, PropertyOrCollectionAccessorFacet.class)) {
                 return handleGetterMethodOnCollection(method, args, targetAdapter, otma, memberName);
             }
             if (instanceOf(imperativeFacets, CollectionAddToFacet.class)) {
-                checkUsability(getAuthenticationSession(), targetAdapter, objectMember);
                 return handleCollectionAddToMethod(args, targetAdapter, otma, methodName);
             }
             if (instanceOf(imperativeFacets, CollectionRemoveFromFacet.class)) {
-                checkUsability(getAuthenticationSession(), targetAdapter, objectMember);
                 return handleCollectionRemoveFromMethod(args, targetAdapter, otma, methodName);
             }
         }
@@ -230,6 +230,10 @@ public class DomainObjectInvocationHandler<T> extends DelegatingInvocationHandle
 
         if (objectMember instanceof ObjectAction) {
 
+            // for all members, check visibility and usability
+            checkVisibility(getAuthenticationSession(), targetAdapter, objectMember);
+
+
             if (instanceOf(imperativeFacets, ActionValidationFacetViaMethod.class)) {
                 throw new UnsupportedOperationException(String.format("Cannot invoke supporting method '%s'; use only the 'invoke' method", memberName));
             }
@@ -338,10 +342,13 @@ public class DomainObjectInvocationHandler<T> extends DelegatingInvocationHandle
     // /////////////////////////////////////////////////////////////////
 
     private Object handleGetterMethodOnProperty(final Object[] args, final ObjectAdapter targetAdapter, final OneToOneAssociation otoa, final String methodName) {
+
         if (args.length != 0) {
             throw new IllegalArgumentException("Invoking a 'get' should have no arguments");
         }
 
+        checkVisibility(getAuthenticationSession(), targetAdapter, otoa);
+
         resolveIfRequired(targetAdapter);
 
         final ObjectAdapter currentReferencedAdapter = otoa.get(targetAdapter);
@@ -361,13 +368,23 @@ public class DomainObjectInvocationHandler<T> extends DelegatingInvocationHandle
             throw new IllegalArgumentException("Invoking a setter should only have a single argument");
         }
 
-        resolveIfRequired(targetAdapter);
-
         final Object argumentObj = underlying(args[0]);
+
+        final WrapperPolicy wrapperPolicy = determineWrapperPolicy(otoa, argumentObj);
+        if(wrapperPolicy == WrapperPolicy.ENFORCE_RULES) {
+            checkVisibility(getAuthenticationSession(), targetAdapter, otoa);
+            checkUsability(getAuthenticationSession(), targetAdapter, otoa);
+        }
+
         final ObjectAdapter argumentAdapter = argumentObj != null ? getAdapterManager().adapterFor(argumentObj) : null;
 
-        final InteractionResult interactionResult = otoa.isAssociationValid(targetAdapter, argumentAdapter).getInteractionResult();
-        notifyListenersAndVetoIfRequired(interactionResult);
+        resolveIfRequired(targetAdapter);
+
+
+        if(wrapperPolicy == WrapperPolicy.ENFORCE_RULES) {
+            final InteractionResult interactionResult = otoa.isAssociationValid(targetAdapter, argumentAdapter).getInteractionResult();
+            notifyListenersAndVetoIfRequired(interactionResult);
+        }
 
         if (getExecutionMode() == ExecutionMode.EXECUTE) {
             otoa.set(targetAdapter, argumentAdapter);
@@ -378,15 +395,33 @@ public class DomainObjectInvocationHandler<T> extends DelegatingInvocationHandle
         return null;
     }
 
+    private static WrapperPolicy determineWrapperPolicy(final OneToOneAssociation otoa, final Object argumentObj) {
+        final PostsEventWithWrapperPolicy wrapperPolicyFacet;
+        if(argumentObj != null) {
+            final PropertySetterFacet setterFacet = otoa.getFacet(PropertySetterFacet.class);
+            wrapperPolicyFacet = PostsEventWithWrapperPolicy.Util.getWrapperPolicyFacet(setterFacet);
+        } else {
+            final PropertyClearFacet clearFacet = otoa.getFacet(PropertyClearFacet.class);
+            wrapperPolicyFacet = PostsEventWithWrapperPolicy.Util.getWrapperPolicyFacet(clearFacet);
+        }
+        return wrapperPolicyFacet != null ? wrapperPolicyFacet.getWrapperPolicy() : WrapperPolicy.ENFORCE_RULES;
+    }
+
+    
+
     // /////////////////////////////////////////////////////////////////
     // collection - access
     // /////////////////////////////////////////////////////////////////
 
     private Object handleGetterMethodOnCollection(final Method method, final Object[] args, final ObjectAdapter targetAdapter, final OneToManyAssociation otma, final String memberName) {
+
+
         if (args.length != 0) {
             throw new IllegalArgumentException("Invoking a 'get' should have no arguments");
         }
 
+        checkVisibility(getAuthenticationSession(), targetAdapter, otma);
+        
         resolveIfRequired(targetAdapter);
 
         final ObjectAdapter currentReferencedAdapter = otma.get(targetAdapter);
@@ -445,6 +480,12 @@ public class DomainObjectInvocationHandler<T> extends DelegatingInvocationHandle
             throw new IllegalArgumentException("Invoking a addTo should only have a single argument");
         }
 
+        final WrapperPolicy wrapperPolicy = determineAddToWrapperPolicy(otma);
+        if(wrapperPolicy == WrapperPolicy.ENFORCE_RULES) {
+            checkVisibility(getAuthenticationSession(), targetAdapter, otma);
+            checkUsability(getAuthenticationSession(), targetAdapter, otma);
+        }
+
         resolveIfRequired(targetAdapter);
 
         final Object argumentObj = underlying(args[0]);
@@ -453,8 +494,10 @@ public class DomainObjectInvocationHandler<T> extends DelegatingInvocationHandle
         }
         final ObjectAdapter argumentNO = getAdapterManager().adapterFor(argumentObj);
 
-        final InteractionResult interactionResult = otma.isValidToAdd(targetAdapter, argumentNO).getInteractionResult();
-        notifyListenersAndVetoIfRequired(interactionResult);
+        if(wrapperPolicy == WrapperPolicy.ENFORCE_RULES) {
+            final InteractionResult interactionResult = otma.isValidToAdd(targetAdapter, argumentNO).getInteractionResult();
+            notifyListenersAndVetoIfRequired(interactionResult);
+        }
 
         if (getExecutionMode() == ExecutionMode.EXECUTE) {
             otma.addElement(targetAdapter, argumentNO);
@@ -465,6 +508,13 @@ public class DomainObjectInvocationHandler<T> extends DelegatingInvocationHandle
         return null;
     }
 
+    private static WrapperPolicy determineAddToWrapperPolicy(final OneToManyAssociation otma) {
+        final CollectionAddToFacet facet = otma.getFacet(CollectionAddToFacet.class);
+        final PostsEventWithWrapperPolicy wrapperPolicyFacet = PostsEventWithWrapperPolicy.Util.getWrapperPolicyFacet(facet);
+        return wrapperPolicyFacet != null ? wrapperPolicyFacet.getWrapperPolicy() : WrapperPolicy.ENFORCE_RULES;
+    }
+
+
     // /////////////////////////////////////////////////////////////////
     // collection - remove from
     // /////////////////////////////////////////////////////////////////
@@ -474,6 +524,13 @@ public class DomainObjectInvocationHandler<T> extends DelegatingInvocationHandle
             throw new IllegalArgumentException("Invoking a removeFrom should only have a single argument");
         }
 
+        final WrapperPolicy wrapperPolicy = determineRemoveFromWrapperPolicy(otma);
+        if(wrapperPolicy == WrapperPolicy.ENFORCE_RULES) {
+            checkVisibility(getAuthenticationSession(), targetAdapter, otma);
+            checkUsability(getAuthenticationSession(), targetAdapter, otma);
+        }
+
+
         resolveIfRequired(targetAdapter);
 
         final Object argumentObj = underlying(args[0]);
@@ -482,8 +539,10 @@ public class DomainObjectInvocationHandler<T> extends DelegatingInvocationHandle
         }
         final ObjectAdapter argumentAdapter = getAdapterManager().adapterFor(argumentObj);
 
-        final InteractionResult interactionResult = otma.isValidToRemove(targetAdapter, argumentAdapter).getInteractionResult();
-        notifyListenersAndVetoIfRequired(interactionResult);
+        if(wrapperPolicy == WrapperPolicy.ENFORCE_RULES) {
+            final InteractionResult interactionResult = otma.isValidToRemove(targetAdapter, argumentAdapter).getInteractionResult();
+            notifyListenersAndVetoIfRequired(interactionResult);
+        }
 
         if (getExecutionMode() == ExecutionMode.EXECUTE) {
             otma.removeElement(targetAdapter, argumentAdapter);
@@ -494,6 +553,13 @@ public class DomainObjectInvocationHandler<T> extends DelegatingInvocationHandle
         return null;
     }
 
+    private static WrapperPolicy determineRemoveFromWrapperPolicy(final OneToManyAssociation otma) {
+        final CollectionRemoveFromFacet removeFromFacet = otma.getFacet(CollectionRemoveFromFacet.class);
+
+        final PostsEventWithWrapperPolicy wrapperPolicyFacet = PostsEventWithWrapperPolicy.Util.getWrapperPolicyFacet(removeFromFacet);
+        return wrapperPolicyFacet != null ? wrapperPolicyFacet.getWrapperPolicy() : WrapperPolicy.ENFORCE_RULES;
+    }
+
     // /////////////////////////////////////////////////////////////////
     // action
     // /////////////////////////////////////////////////////////////////

http://git-wip-us.apache.org/repos/asf/isis/blob/2637a055/example/application/quickstart_wicket_restful_jdo/dom/src/main/java/dom/todo/ToDoItem.java
----------------------------------------------------------------------
diff --git a/example/application/quickstart_wicket_restful_jdo/dom/src/main/java/dom/todo/ToDoItem.java b/example/application/quickstart_wicket_restful_jdo/dom/src/main/java/dom/todo/ToDoItem.java
index c384a9c..5f9fc1d 100644
--- a/example/application/quickstart_wicket_restful_jdo/dom/src/main/java/dom/todo/ToDoItem.java
+++ b/example/application/quickstart_wicket_restful_jdo/dom/src/main/java/dom/todo/ToDoItem.java
@@ -22,13 +22,17 @@ import java.math.BigDecimal;
 import java.net.MalformedURLException;
 import java.net.URL;
 import java.util.*;
+
 import javax.jdo.JDOHelper;
 import javax.jdo.annotations.IdentityType;
 import javax.jdo.annotations.VersionStrategy;
+
 import com.google.common.base.Objects;
 import com.google.common.base.Predicate;
 import com.google.common.collect.Ordering;
+
 import org.joda.time.LocalDate;
+
 import org.apache.isis.applib.DomainObjectContainer;
 import org.apache.isis.applib.NonRecoverableException;
 import org.apache.isis.applib.RecoverableException;
@@ -41,8 +45,11 @@ import org.apache.isis.applib.clock.Clock;
 import org.apache.isis.applib.services.background.BackgroundService;
 import org.apache.isis.applib.services.clock.ClockService;
 import org.apache.isis.applib.services.command.CommandContext;
+import org.apache.isis.applib.services.eventbus.CollectionAddedToEvent;
 import org.apache.isis.applib.services.eventbus.EventBusService;
+import org.apache.isis.applib.services.eventbus.PropertyChangedEvent;
 import org.apache.isis.applib.services.scratchpad.Scratchpad;
+import org.apache.isis.applib.services.wrapper.WrapperFactory;
 import org.apache.isis.applib.util.ObjectContracts;
 import org.apache.isis.applib.util.TitleBuffer;
 import org.apache.isis.applib.value.Blob;
@@ -410,6 +417,7 @@ public class ToDoItem implements Comparable<ToDoItem> {
     private String notes;
 
     @javax.jdo.annotations.Column(allowsNull="true", length=400)
+    @PostsPropertyChangedEvent()
     public String getNotes() {
         return notes;
     }
@@ -479,6 +487,7 @@ public class ToDoItem implements Comparable<ToDoItem> {
     @javax.jdo.annotations.Element(column="dependentId")
     private SortedSet<ToDoItem> dependencies = new TreeSet<ToDoItem>();
 
+    @PostsCollectionAddedToEvent(wrapperPolicy=WrapperPolicy.SKIP_RULES)
     @SortedBy(DependenciesComparator.class)
     public SortedSet<ToDoItem> getDependencies() {
         return dependencies;
@@ -487,13 +496,19 @@ public class ToDoItem implements Comparable<ToDoItem> {
     public void setDependencies(final SortedSet<ToDoItem> dependencies) {
         this.dependencies = dependencies;
     }
-
     
+    public void addToDependencies(final ToDoItem toDoItem) {
+        getDependencies().add(toDoItem);
+    }
+    public void removeFromDependencies(final ToDoItem toDoItem) {
+        getDependencies().remove(toDoItem);
+    }
+
     @PublishedAction
     public ToDoItem add(
             @TypicalLength(20)
             final ToDoItem toDoItem) {
-        getDependencies().add(toDoItem);
+        wrapperFactory.wrap(this).addToDependencies(toDoItem);
         return this;
     }
     public List<ToDoItem> autoComplete0Add(final @MinLength(2) String search) {
@@ -523,7 +538,7 @@ public class ToDoItem implements Comparable<ToDoItem> {
     public ToDoItem remove(
             @TypicalLength(20)
             final ToDoItem toDoItem) {
-        getDependencies().remove(toDoItem);
+        this.removeFromDependencies(toDoItem);
         return this;
     }
     // disable action dependent on state of object
@@ -733,6 +748,7 @@ public class ToDoItem implements Comparable<ToDoItem> {
     // Events
     // //////////////////////////////////////
 
+
     public static abstract class AbstractEvent {
         private final String eventDescription;
         private final ToDoItem toDoItem;
@@ -899,6 +915,9 @@ public class ToDoItem implements Comparable<ToDoItem> {
         this.eventBusService = eventBusService;
     }
 
+    @javax.inject.Inject
+    private WrapperFactory wrapperFactory;
+    
     //endregion
 
 }

http://git-wip-us.apache.org/repos/asf/isis/blob/2637a055/example/application/quickstart_wicket_restful_jdo/dom/src/main/java/dom/todo/ToDoItemSubscriptions.java
----------------------------------------------------------------------
diff --git a/example/application/quickstart_wicket_restful_jdo/dom/src/main/java/dom/todo/ToDoItemSubscriptions.java b/example/application/quickstart_wicket_restful_jdo/dom/src/main/java/dom/todo/ToDoItemSubscriptions.java
index c748e18..0a4b02f 100644
--- a/example/application/quickstart_wicket_restful_jdo/dom/src/main/java/dom/todo/ToDoItemSubscriptions.java
+++ b/example/application/quickstart_wicket_restful_jdo/dom/src/main/java/dom/todo/ToDoItemSubscriptions.java
@@ -22,7 +22,9 @@ import com.google.common.eventbus.Subscribe;
 
 import org.apache.isis.applib.DomainObjectContainer;
 import org.apache.isis.applib.annotation.Programmatic;
+import org.apache.isis.applib.services.eventbus.CollectionAddedToEvent;
 import org.apache.isis.applib.services.eventbus.EventBusService;
+import org.apache.isis.applib.services.eventbus.PropertyChangedEvent;
 
 public class ToDoItemSubscriptions {
 
@@ -36,6 +38,18 @@ public class ToDoItemSubscriptions {
         LOG.info(ev.getEventDescription() + ": " + container.titleOf(ev.getToDoItem()));
     }
 
+    @Programmatic
+    @Subscribe
+    public void on(PropertyChangedEvent<?,?> ev) {
+        LOG.info(container.titleOf(ev.getSource()) + ", changed " + ev.getIdentifier().getMemberName() + " : " + ev.getOldValue() + " -> " + ev.getNewValue());
+    }
+    
+    @Programmatic
+    @Subscribe
+    public void on(CollectionAddedToEvent<?,?> ev) {
+        LOG.info(container.titleOf(ev.getSource()) + ", added to " + ev.getIdentifier().getMemberName() + " : " + ev.getValue());
+    }
+    
     //region > injected services
     // //////////////////////////////////////
     

http://git-wip-us.apache.org/repos/asf/isis/blob/2637a055/example/application/quickstart_wicket_restful_jdo/webapp/pom.xml
----------------------------------------------------------------------
diff --git a/example/application/quickstart_wicket_restful_jdo/webapp/pom.xml b/example/application/quickstart_wicket_restful_jdo/webapp/pom.xml
index e415798..1381579 100644
--- a/example/application/quickstart_wicket_restful_jdo/webapp/pom.xml
+++ b/example/application/quickstart_wicket_restful_jdo/webapp/pom.xml
@@ -185,6 +185,10 @@
         </dependency>
         <dependency>
             <groupId>org.apache.isis.core</groupId>
+            <artifactId>isis-core-wrapper</artifactId>
+        </dependency>
+        <dependency>
+            <groupId>org.apache.isis.core</groupId>
             <artifactId>isis-core-profilestore</artifactId>
         </dependency>
         <dependency>

http://git-wip-us.apache.org/repos/asf/isis/blob/2637a055/example/application/quickstart_wicket_restful_jdo/webapp/src/main/webapp/WEB-INF/isis.properties
----------------------------------------------------------------------
diff --git a/example/application/quickstart_wicket_restful_jdo/webapp/src/main/webapp/WEB-INF/isis.properties b/example/application/quickstart_wicket_restful_jdo/webapp/src/main/webapp/WEB-INF/isis.properties
index 87f1857..153f3f9 100644
--- a/example/application/quickstart_wicket_restful_jdo/webapp/src/main/webapp/WEB-INF/isis.properties
+++ b/example/application/quickstart_wicket_restful_jdo/webapp/src/main/webapp/WEB-INF/isis.properties
@@ -189,6 +189,7 @@ isis.services = \
                 org.apache.isis.applib.annotation.Bulk$InteractionContext,\
                 org.apache.isis.applib.services.scratchpad.Scratchpad,\
                 org.apache.isis.applib.services.queryresultscache.QueryResultsCache,\
+                org.apache.isis.core.wrapper.WrapperFactoryDefault,\
                 \
                 # JDO implementation of the EventBusService, \
                 org.apache.isis.objectstore.jdo.datanucleus.service.eventbus.EventBusServiceJdo,\


[13/16] git commit: Merge branch 'ISIS-550'

Posted by da...@apache.org.
Merge branch 'ISIS-550'


Project: http://git-wip-us.apache.org/repos/asf/isis/repo
Commit: http://git-wip-us.apache.org/repos/asf/isis/commit/6ba1b7cf
Tree: http://git-wip-us.apache.org/repos/asf/isis/tree/6ba1b7cf
Diff: http://git-wip-us.apache.org/repos/asf/isis/diff/6ba1b7cf

Branch: refs/heads/master
Commit: 6ba1b7cffe0f4357e0c45d293db0b1e647290c64
Parents: b7909bf e1f19ba
Author: Dan Haywood <da...@haywood-associates.co.uk>
Authored: Sun May 11 13:32:10 2014 +0100
Committer: Dan Haywood <da...@haywood-associates.co.uk>
Committed: Sun May 11 13:32:10 2014 +0100

----------------------------------------------------------------------
 .../annotation/PostsActionInvokedEvent.java     |  60 ++++++
 .../annotation/PostsCollectionAddedToEvent.java |  63 ++++++
 .../PostsCollectionRemovedFromEvent.java        |  63 ++++++
 .../annotation/PostsPropertyChangedEvent.java   |   2 +-
 .../isis/applib/events/ActionArgumentEvent.java |   2 +-
 .../services/eventbus/ActionInvokedEvent.java   |  74 +++++++
 .../eventbus/CollectionAddedToEvent.java        |  64 ++++++
 .../eventbus/CollectionRemovedFromEvent.java    |  63 ++++++
 .../services/eventbus/PropertyChangedEvent.java |  48 +++--
 .../applib/services/publish/EventPayload.java   |   2 +-
 .../applib/services/wrapper/WrapperFactory.java |  52 ++++-
 .../ObjectResolveAndObjectChangedEnhancer.java  |   4 +-
 .../ObjectResolveAndObjectChangedEnhancer.java  |   4 +-
 .../core/metamodel/adapter/ObjectAdapter.java   |  68 ++++++-
 .../metamodel/adapter/util/AdapterUtils.java    |  84 ++++----
 .../core/metamodel/facets/ImperativeFacet.java  |  85 ++++++++
 .../metamodel/facets/ImperativeFacetUtils.java  |  76 ++-----
 .../event/PostsActionInvokedEventFacet.java     |  66 +++++++
 .../PostsActionInvokedEventFacetAbstract.java   |  44 +++++
 .../event/PostsCollectionAddedToEventFacet.java |  71 +++++++
 ...ostsCollectionAddedToEventFacetAbstract.java |  54 +++++
 .../PostsCollectionRemovedFromEventFacet.java   |  72 +++++++
 ...CollectionRemovedFromEventFacetAbstract.java |  51 +++++
 .../event/PostsPropertyChangedEventFacet.java   |  38 ++++
 .../PostsPropertyChangedEventFacetAbstract.java |  14 +-
 .../invoke/ActionInvocationFacetViaMethod.java  |  61 +++++-
 .../PostsActionInvokedEventFacetAnnotation.java | 112 +++++++++++
 .../PostsActionInvokedEventFacetFactory.java    | 198 +++++++++++++++++++
 .../collection/CollectionFacetFactory.java      |   6 +-
 ...ctionAddedToEventAnnotationFacetFactory.java |  80 ++++++++
 ...tsCollectionAddedToEventFacetAnnotation.java | 136 +++++++++++++
 ...nRemovedFromEventAnnotationFacetFactory.java |  80 ++++++++
 ...llectionRemovedFromEventFacetAnnotation.java | 137 +++++++++++++
 ...pertyChangedEventAnnotationFacetFactory.java |  30 ++-
 ...ostsPropertyChangedEventFacetAnnotation.java |  92 ++++-----
 .../dflt/ProgrammingModelFacetsJava5.java       |   8 +
 .../facets/ImperativeFacetUtilsTest.java        |  59 ++++--
 ...tionInvokedEventFacet_UtilTest_newEvent.java |  70 +++++++
 ...tionAddedToEventFacet_UtilTest_newEvent.java |  72 +++++++
 ...RemovedFromEventFacet_UtilTest_newEvent.java |  70 +++++++
 ...ertyChangedEventFacet_UtilTest_newEvent.java |  73 +++++++
 ...hangedEventFacetAnnotationTest_newEvent.java |  42 ----
 .../core/wrapper/WrapperFactoryAbstract.java    |  10 +
 .../AbstractCollectionInvocationHandler.java    |   7 +-
 .../handlers/DomainObjectInvocationHandler.java |  75 +++++--
 .../dom/src/main/java/dom/todo/ToDoItem.java    |  97 +++++----
 .../java/dom/todo/ToDoItemSubscriptions.java    |  80 +++++++-
 .../java/integration/ToDoSystemInitializer.java |   2 +
 .../java/integration/tests/ToDoIntegTest.java   |   8 +-
 .../tests/actions/ToDoItemTest_completed.java   |  30 ++-
 .../colls/ToDoItemTest_dependencies_add.java    |  24 ++-
 .../colls/ToDoItemTest_dependencies_remove.java |  27 ++-
 .../ToDoItemTest_dependencies_addedEvent.java   |  85 ++++++++
 .../tests/props/ToDoItemTest_description.java   |  25 +++
 .../tests/props/ToDoItemTest_notes.java         |  20 ++
 .../webapp/pom.xml                              |   4 +
 .../src/main/webapp/WEB-INF/isis.properties     |   1 +
 57 files changed, 2712 insertions(+), 333 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/isis/blob/6ba1b7cf/example/application/quickstart_wicket_restful_jdo/dom/src/main/java/dom/todo/ToDoItem.java
----------------------------------------------------------------------
diff --cc example/application/quickstart_wicket_restful_jdo/dom/src/main/java/dom/todo/ToDoItem.java
index e7ddd99,9d1f01c..e82fd63
--- a/example/application/quickstart_wicket_restful_jdo/dom/src/main/java/dom/todo/ToDoItem.java
+++ b/example/application/quickstart_wicket_restful_jdo/dom/src/main/java/dom/todo/ToDoItem.java
@@@ -904,8 -931,9 +932,11 @@@ public class ToDoItem implements Compar
          this.eventBusService = eventBusService;
      }
  
+     @javax.inject.Inject
+     private WrapperFactory wrapperFactory;
+     
      //endregion
  
 +    
 +
  }


[12/16] git commit: ISIS-550: working on ActionInvokedEvent, adding integration tests.

Posted by da...@apache.org.
ISIS-550: working on ActionInvokedEvent, adding integration tests.

This is nearly there, but there is an issue with the open/close of services in the integration tests that needs addressing.


Project: http://git-wip-us.apache.org/repos/asf/isis/repo
Commit: http://git-wip-us.apache.org/repos/asf/isis/commit/e1f19baa
Tree: http://git-wip-us.apache.org/repos/asf/isis/tree/e1f19baa
Diff: http://git-wip-us.apache.org/repos/asf/isis/diff/e1f19baa

Branch: refs/heads/master
Commit: e1f19baaac4138800c77499cb056015101d0aa79
Parents: c2b250f
Author: Dan Haywood <da...@haywood-associates.co.uk>
Authored: Sun May 11 12:08:20 2014 +0100
Committer: Dan Haywood <da...@haywood-associates.co.uk>
Committed: Sun May 11 12:08:20 2014 +0100

----------------------------------------------------------------------
 .../services/eventbus/ActionInvokedEvent.java   |  47 +++----
 .../eventbus/CollectionAddedToEvent.java        |  14 +-
 .../eventbus/CollectionRemovedFromEvent.java    |  13 +-
 .../services/eventbus/PropertyChangedEvent.java |  24 ++--
 .../core/metamodel/adapter/ObjectAdapter.java   |  68 +++++++++-
 .../metamodel/adapter/util/AdapterUtils.java    |  84 ++++++------
 .../event/PostsActionInvokedEventFacet.java     |  66 ++++++++++
 .../PostsActionInvokedEventFacetAbstract.java   |  44 +++++++
 .../event/PostsActionInvokedEventFacet.java     |  32 -----
 .../PostsActionInvokedEventFacetAbstract.java   |  42 ------
 .../event/PostsCollectionAddedToEventFacet.java |  37 ++++++
 ...ostsCollectionAddedToEventFacetAbstract.java |   6 +
 .../PostsCollectionRemovedFromEventFacet.java   |  38 ++++++
 ...CollectionRemovedFromEventFacetAbstract.java |   3 +
 .../event/PostsPropertyChangedEventFacet.java   |  38 ++++++
 .../PostsPropertyChangedEventFacetAbstract.java |   4 +
 .../invoke/ActionInvocationFacetViaMethod.java  |   3 -
 .../PostsActionInvokedEventFacetAnnotation.java | 112 ++++++++++++++++
 .../PostsActionInvokedEventFacetFactory.java    |   8 +-
 .../PostsActionInvokedEventFacetViaMethod.java  | 129 -------------------
 ...ctionAddedToEventAnnotationFacetFactory.java |  14 +-
 ...tsCollectionAddedToEventFacetAnnotation.java |  60 ++-------
 ...nRemovedFromEventAnnotationFacetFactory.java |  14 +-
 ...llectionRemovedFromEventFacetAnnotation.java |  58 +++------
 ...pertyChangedEventAnnotationFacetFactory.java |  23 ++--
 ...ostsPropertyChangedEventFacetAnnotation.java |  48 ++-----
 ...tionInvokedEventFacet_UtilTest_newEvent.java |  70 ++++++++++
 ...tionAddedToEventFacet_UtilTest_newEvent.java |  72 +++++++++++
 ...RemovedFromEventFacet_UtilTest_newEvent.java |  70 ++++++++++
 ...ertyChangedEventFacet_UtilTest_newEvent.java |  73 +++++++++++
 ...nAddedEventFacetAnnotationTest_newEvent.java |  53 --------
 ...emovedEventFacetAnnotationTest_newEvent.java |  52 --------
 ...hangedEventFacetAnnotationTest_newEvent.java |  52 --------
 .../dom/src/main/java/dom/todo/ToDoItem.java    |  72 ++++++-----
 .../java/dom/todo/ToDoItemSubscriptions.java    |  59 ++++++++-
 .../java/integration/ToDoSystemInitializer.java |   2 +
 .../java/integration/tests/ToDoIntegTest.java   |   8 +-
 .../tests/actions/ToDoItemTest_completed.java   |  30 ++++-
 .../colls/ToDoItemTest_dependencies_add.java    |  24 +++-
 .../colls/ToDoItemTest_dependencies_remove.java |  27 +++-
 .../tests/props/ToDoItemTest_description.java   |  25 ++++
 .../tests/props/ToDoItemTest_notes.java         |  20 +++
 42 files changed, 1074 insertions(+), 664 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/isis/blob/e1f19baa/core/applib/src/main/java/org/apache/isis/applib/services/eventbus/ActionInvokedEvent.java
----------------------------------------------------------------------
diff --git a/core/applib/src/main/java/org/apache/isis/applib/services/eventbus/ActionInvokedEvent.java b/core/applib/src/main/java/org/apache/isis/applib/services/eventbus/ActionInvokedEvent.java
index 7dabf9b..cbfa948 100644
--- a/core/applib/src/main/java/org/apache/isis/applib/services/eventbus/ActionInvokedEvent.java
+++ b/core/applib/src/main/java/org/apache/isis/applib/services/eventbus/ActionInvokedEvent.java
@@ -18,6 +18,11 @@
  */
 package org.apache.isis.applib.services.eventbus;
 
+import java.util.Arrays;
+import java.util.Collections;
+import java.util.List;
+
+import org.apache.isis.applib.Identifier;
 import org.apache.isis.applib.annotation.PostsActionInvokedEvent;
 import org.apache.isis.applib.util.ObjectContracts;
 
@@ -27,29 +32,28 @@ public abstract class ActionInvokedEvent<S> extends java.util.EventObject {
 
     public static class Default extends ActionInvokedEvent<Object> {
         private static final long serialVersionUID = 1L;
+        public Default(Object source, Identifier identifier, Object... arguments) {
+            super(source, identifier, arguments);
+        }
     }
 
-    private final String action;
-    private final String parameters;
-    
-    /**
-     * To instantiate reflectively when the {@link PostsActionInvokedEvent} annotation
-     * is used.
-     * 
-     * <p>
-     * The fields ({@link #source} and {@link #value} are then set reflectively.
-     */
-    public ActionInvokedEvent() {
-        this(null, null, null);
+    private final Identifier identifier;
+    private final List<Object> arguments;
+
+    public ActionInvokedEvent(
+            final S source, 
+            final Identifier identifier, 
+            final Object... arguments) {
+        this(source, identifier, arguments != null? Arrays.asList(arguments): Collections.emptyList());
     }
     
     public ActionInvokedEvent(
             final S source, 
-            final String action, 
-            final String parameters) {
+            final Identifier identifier, 
+            final List<Object> arguments) {
         super(source);
-        this.action = action;
-        this.parameters = parameters;
+        this.identifier = identifier;
+        this.arguments = Collections.unmodifiableList(arguments);
     }
     
     @Override
@@ -57,15 +61,14 @@ public abstract class ActionInvokedEvent<S> extends java.util.EventObject {
     public S getSource() {
         return (S)source;
     }
-    public String getAction() {
-        return action;
+    public Identifier getIdentifier() {
+        return identifier;
     }
-    public String getParameters() {
-        return parameters;
+    public List<Object> getArguments() {
+        return arguments;
     }
-    
     @Override
     public String toString() {
-        return ObjectContracts.toString(this, "source,action,parameters");
+        return ObjectContracts.toString(this, "source,identifier");
     }
 }
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/isis/blob/e1f19baa/core/applib/src/main/java/org/apache/isis/applib/services/eventbus/CollectionAddedToEvent.java
----------------------------------------------------------------------
diff --git a/core/applib/src/main/java/org/apache/isis/applib/services/eventbus/CollectionAddedToEvent.java b/core/applib/src/main/java/org/apache/isis/applib/services/eventbus/CollectionAddedToEvent.java
index 2b4302d..ca8f2ee 100644
--- a/core/applib/src/main/java/org/apache/isis/applib/services/eventbus/CollectionAddedToEvent.java
+++ b/core/applib/src/main/java/org/apache/isis/applib/services/eventbus/CollectionAddedToEvent.java
@@ -28,22 +28,14 @@ public abstract class CollectionAddedToEvent<S,T> extends java.util.EventObject
 
     public static class Default extends CollectionAddedToEvent<Object, Object> {
         private static final long serialVersionUID = 1L;
+        public Default(Object source, Identifier identifier, Object value) {
+            super(source, identifier, value);
+        }
     }
 
     private final Identifier identifier;
     private final T value;
     
-    /**
-     * To instantiate reflectively when the {@link PostsPropertyChangedEvent} annotation
-     * is used.
-     * 
-     * <p>
-     * The fields ({@link #source} and {@link #value} are then set reflectively.
-     */
-    public CollectionAddedToEvent() {
-        this(null, null, null);
-    }
-    
     public CollectionAddedToEvent(
             final S source, 
             final Identifier identifier, 

http://git-wip-us.apache.org/repos/asf/isis/blob/e1f19baa/core/applib/src/main/java/org/apache/isis/applib/services/eventbus/CollectionRemovedFromEvent.java
----------------------------------------------------------------------
diff --git a/core/applib/src/main/java/org/apache/isis/applib/services/eventbus/CollectionRemovedFromEvent.java b/core/applib/src/main/java/org/apache/isis/applib/services/eventbus/CollectionRemovedFromEvent.java
index 47ff424..fb0d3ca 100644
--- a/core/applib/src/main/java/org/apache/isis/applib/services/eventbus/CollectionRemovedFromEvent.java
+++ b/core/applib/src/main/java/org/apache/isis/applib/services/eventbus/CollectionRemovedFromEvent.java
@@ -27,21 +27,14 @@ public abstract class CollectionRemovedFromEvent<S,T> extends java.util.EventObj
 
     public static class Default extends CollectionRemovedFromEvent<Object, Object> {
         private static final long serialVersionUID = 1L;
+        public Default(Object source, Identifier identifier, Object value) {
+            super(source, identifier, value);
+        }
     }
 
     private final Identifier identifier;
     private final T value;
     
-    /**
-     * To instantiate reflectively when the {@link PostsCollectionRemovedFromEvent} annotation
-     * is used.
-     * 
-     * <p>
-     * The fields ({@link #source} and {@link #value} are then set reflectively.
-     */
-    public CollectionRemovedFromEvent() {
-        this(null, null, null);
-    }
     public CollectionRemovedFromEvent(
             final S source, 
             final Identifier identifier, 

http://git-wip-us.apache.org/repos/asf/isis/blob/e1f19baa/core/applib/src/main/java/org/apache/isis/applib/services/eventbus/PropertyChangedEvent.java
----------------------------------------------------------------------
diff --git a/core/applib/src/main/java/org/apache/isis/applib/services/eventbus/PropertyChangedEvent.java b/core/applib/src/main/java/org/apache/isis/applib/services/eventbus/PropertyChangedEvent.java
index 13666ff..a5fc83a 100644
--- a/core/applib/src/main/java/org/apache/isis/applib/services/eventbus/PropertyChangedEvent.java
+++ b/core/applib/src/main/java/org/apache/isis/applib/services/eventbus/PropertyChangedEvent.java
@@ -28,6 +28,9 @@ public abstract class PropertyChangedEvent<S,T> extends java.util.EventObject {
 
     public static class Default extends PropertyChangedEvent<Object, Object> {
         private static final long serialVersionUID = 1L;
+        public Default(Object source, Identifier identifier, Object oldValue, Object newValue) {
+            super(source, identifier, oldValue, newValue);
+        }
     }
     
     private final Identifier identifier;
@@ -35,26 +38,19 @@ public abstract class PropertyChangedEvent<S,T> extends java.util.EventObject {
     private final T newValue;
     
     /**
-     * To instantiate reflectively when the {@link PostsPropertyChangedEvent} annotation
-     * is used.
-     * 
-     * <p>
-     * The fields ({@link #source}, {@link #oldValue} and {@link #newValue}) are
-     * then set reflectively.
-     */
-    public PropertyChangedEvent() {
-        this(null, null, null, null);
-    }
-    
-    /**
      * @deprecated - use {@link #PropertyChangedEvent(Object, Identifier, Object, Object)}.
      */
     @Deprecated
-    public PropertyChangedEvent(S source, T oldValue, T newValue) {
+    public PropertyChangedEvent(
+            final S source, 
+            final T oldValue, final T newValue) {
         this(source, null, oldValue, newValue);
     }
 
-    public PropertyChangedEvent(S source, Identifier identifier, T oldValue, T newValue) {
+    public PropertyChangedEvent(
+            final S source, 
+            final Identifier identifier, 
+            final T oldValue, final T newValue) {
         super(source);
         this.identifier = identifier;
         this.oldValue = oldValue;

http://git-wip-us.apache.org/repos/asf/isis/blob/e1f19baa/core/metamodel/src/main/java/org/apache/isis/core/metamodel/adapter/ObjectAdapter.java
----------------------------------------------------------------------
diff --git a/core/metamodel/src/main/java/org/apache/isis/core/metamodel/adapter/ObjectAdapter.java b/core/metamodel/src/main/java/org/apache/isis/core/metamodel/adapter/ObjectAdapter.java
index 859195f..e39f9e7 100644
--- a/core/metamodel/src/main/java/org/apache/isis/core/metamodel/adapter/ObjectAdapter.java
+++ b/core/metamodel/src/main/java/org/apache/isis/core/metamodel/adapter/ObjectAdapter.java
@@ -250,10 +250,36 @@ public interface ObjectAdapter extends Instance, org.apache.isis.applib.annotati
         private Util() {
         }
 
+
         public static Object unwrap(final ObjectAdapter adapter) {
             return adapter != null ? adapter.getObject() : null;
         }
 
+        public static Object[] unwrap(final ObjectAdapter[] adapters) {
+            if (adapters == null) {
+                return null;
+            }
+            final Object[] unwrappedObjects = new Object[adapters.length];
+            int i = 0;
+            for (final ObjectAdapter adapter : adapters) {
+                unwrappedObjects[i++] = unwrap(adapter);
+            }
+            return unwrappedObjects;
+        }
+
+        public static List<Object> unwrap(final List<ObjectAdapter> adapters) {
+            List<Object> objects = Lists.newArrayList();
+            for (ObjectAdapter adapter : adapters) {
+                objects.add(unwrap(adapter));
+            }
+            return objects;
+        }
+
+        @SuppressWarnings("unchecked")
+        public static <T> List<T> unwrapT(final List<ObjectAdapter> adapters) {
+            return (List<T>) unwrap(adapters);
+        }
+
         public static String unwrapAsString(final ObjectAdapter adapter) {
             final Object obj = unwrap(adapter);
             if (obj == null) {
@@ -265,13 +291,45 @@ public interface ObjectAdapter extends Instance, org.apache.isis.applib.annotati
             return (String) obj;
         }
 
+        public static String titleString(final ObjectAdapter adapter) {
+            return adapter != null ? adapter.titleString(null) : "";
+        }
 
-        public static List<Object> unwrap(final List<ObjectAdapter> adapters) {
-            List<Object> objects = Lists.newArrayList();
-            for (ObjectAdapter adapter : adapters) {
-                objects.add(unwrap(adapter));
+        public static boolean exists(final ObjectAdapter adapter) {
+            return adapter != null && adapter.getObject() != null;
+        }
+
+        public static boolean wrappedEqual(final ObjectAdapter adapter1, final ObjectAdapter adapter2) {
+            final boolean defined1 = exists(adapter1);
+            final boolean defined2 = exists(adapter2);
+            if (defined1 && !defined2) {
+                return false;
             }
-            return objects;
+            if (!defined1 && defined2) {
+                return false;
+            }
+            if (!defined1 && !defined2) {
+                return true;
+            } // both null
+            return adapter1.getObject().equals(adapter2.getObject());
+        }
+
+        public static boolean nullSafeEquals(final Object obj1, final Object obj2) {
+            if (obj1 == null && obj2 == null) {
+                return true;
+            }
+            if (obj1 == null || obj2 == null) {
+                return false;
+            }
+            if (obj1.equals(obj2)) {
+                return true;
+            }
+            if (obj1 instanceof ObjectAdapter && obj2 instanceof ObjectAdapter) {
+                final ObjectAdapter adapterObj1 = (ObjectAdapter) obj1;
+                final ObjectAdapter adapterObj2 = (ObjectAdapter) obj2;
+                return nullSafeEquals(adapterObj1.getObject(), adapterObj2.getObject());
+            }
+            return false;
         }
 
     }

http://git-wip-us.apache.org/repos/asf/isis/blob/e1f19baa/core/metamodel/src/main/java/org/apache/isis/core/metamodel/adapter/util/AdapterUtils.java
----------------------------------------------------------------------
diff --git a/core/metamodel/src/main/java/org/apache/isis/core/metamodel/adapter/util/AdapterUtils.java b/core/metamodel/src/main/java/org/apache/isis/core/metamodel/adapter/util/AdapterUtils.java
index f64013e..eb3457d 100644
--- a/core/metamodel/src/main/java/org/apache/isis/core/metamodel/adapter/util/AdapterUtils.java
+++ b/core/metamodel/src/main/java/org/apache/isis/core/metamodel/adapter/util/AdapterUtils.java
@@ -19,7 +19,6 @@
 
 package org.apache.isis.core.metamodel.adapter.util;
 
-import java.util.ArrayList;
 import java.util.List;
 
 import org.apache.isis.core.metamodel.adapter.ObjectAdapter;
@@ -28,71 +27,60 @@ public class AdapterUtils {
 
     private AdapterUtils() {
     }
-
+    
+    /**
+     * @deprecated - use {@link ObjectAdapter.Util#exists(ObjectAdapter)}
+     */
+    @Deprecated
     public static boolean exists(final ObjectAdapter adapter) {
-        return adapter != null && adapter.getObject() != null;
+        return ObjectAdapter.Util.exists(adapter);
     }
-
+    
+    /**
+     * @deprecated - use {@link ObjectAdapter.Util#wrappedEqual(ObjectAdapter, ObjectAdapter)}
+     */
+    @Deprecated
     public static boolean wrappedEqual(final ObjectAdapter adapter1, final ObjectAdapter adapter2) {
-        final boolean defined1 = exists(adapter1);
-        final boolean defined2 = exists(adapter2);
-        if (defined1 && !defined2) {
-            return false;
-        }
-        if (!defined1 && defined2) {
-            return false;
-        }
-        if (!defined1 && !defined2) {
-            return true;
-        } // both null
-        return adapter1.getObject().equals(adapter2.getObject());
+        return ObjectAdapter.Util.wrappedEqual(adapter1, adapter2);
     }
 
+    /**
+     * @deprecated - use {@link ObjectAdapter.Util#unwrap(ObjectAdapter)}
+     */
+    @Deprecated
     public static Object unwrap(final ObjectAdapter adapter) {
-        return adapter != null ? adapter.getObject() : null;
+        return ObjectAdapter.Util.unwrap(adapter);
     }
 
+    /**
+     * @deprecated - use {@link ObjectAdapter.Util#unwrap(ObjectAdapter[])}
+     */
     public static Object[] unwrap(final ObjectAdapter[] adapters) {
-        if (adapters == null) {
-            return null;
-        }
-        final Object[] unwrappedObjects = new Object[adapters.length];
-        int i = 0;
-        for (final ObjectAdapter adapter : adapters) {
-            unwrappedObjects[i++] = unwrap(adapter);
-        }
-        return unwrappedObjects;
+        return ObjectAdapter.Util.unwrap(adapters);
     }
 
-    @SuppressWarnings("unchecked")
+    /**
+     * @deprecated - use {@link ObjectAdapter.Util#unwrapT(List)}
+     */
+    @Deprecated
     public static <T> List<T> unwrap(final List<ObjectAdapter> adapters) {
-        final List<T> list = new ArrayList<T>();
-        for (final ObjectAdapter adapter : adapters) {
-            list.add((T) unwrap(adapter));
-        }
-        return list;
+        return ObjectAdapter.Util.unwrapT(adapters);
     }
 
+    /**
+     * @deprecated - use {@link ObjectAdapter.Util#titleString(ObjectAdapter)}
+     */
+    @Deprecated
     public static String titleString(final ObjectAdapter adapter) {
-        return adapter != null ? adapter.titleString() : "";
+        return ObjectAdapter.Util.titleString(adapter);
     }
 
+    /**
+     * @deprecated - use {@link ObjectAdapter.Util#nullSafeEquals(Object, Object)}
+     */
+    @Deprecated
     public static boolean nullSafeEquals(final Object obj1, final Object obj2) {
-        if (obj1 == null && obj2 == null) {
-            return true;
-        }
-        if (obj1 == null || obj2 == null) {
-            return false;
-        }
-        if (obj1.equals(obj2)) {
-            return true;
-        }
-        if (obj1 instanceof ObjectAdapter && obj2 instanceof ObjectAdapter) {
-            final ObjectAdapter adapterObj1 = (ObjectAdapter) obj1;
-            final ObjectAdapter adapterObj2 = (ObjectAdapter) obj2;
-            return nullSafeEquals(adapterObj1.getObject(), adapterObj2.getObject());
-        }
-        return false;
+        return ObjectAdapter.Util.nullSafeEquals(obj1, obj2);
     }
 
 }

http://git-wip-us.apache.org/repos/asf/isis/blob/e1f19baa/core/metamodel/src/main/java/org/apache/isis/core/metamodel/facets/actions/event/PostsActionInvokedEventFacet.java
----------------------------------------------------------------------
diff --git a/core/metamodel/src/main/java/org/apache/isis/core/metamodel/facets/actions/event/PostsActionInvokedEventFacet.java b/core/metamodel/src/main/java/org/apache/isis/core/metamodel/facets/actions/event/PostsActionInvokedEventFacet.java
new file mode 100644
index 0000000..eefbda2
--- /dev/null
+++ b/core/metamodel/src/main/java/org/apache/isis/core/metamodel/facets/actions/event/PostsActionInvokedEventFacet.java
@@ -0,0 +1,66 @@
+/*
+ *  Licensed to the Apache Software Foundation (ASF) under one
+ *  or more contributor license agreements.  See the NOTICE file
+ *  distributed with this work for additional information
+ *  regarding copyright ownership.  The ASF licenses this file
+ *  to you under the Apache License, Version 2.0 (the
+ *  "License"); you may not use this file except in compliance
+ *  with the License.  You may obtain a copy of the License at
+ *
+ *        http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *  Unless required by applicable law or agreed to in writing,
+ *  software distributed under the License is distributed on an
+ *  "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ *  KIND, either express or implied.  See the License for the
+ *  specific language governing permissions and limitations
+ *  under the License.
+ */
+
+package org.apache.isis.core.metamodel.facets.actions.event;
+
+import java.lang.reflect.Constructor;
+import java.lang.reflect.InvocationTargetException;
+
+import org.apache.isis.applib.Identifier;
+import org.apache.isis.applib.services.eventbus.ActionInvokedEvent;
+import org.apache.isis.core.metamodel.facets.actions.invoke.ActionInvocationFacet;
+
+/**
+ * Extends the mechanism by which the action should be invoked by sending an
+ * Event to the internal Event Bus after being invoked without throwing 
+ * an Exception.
+ */
+public interface PostsActionInvokedEventFacet extends ActionInvocationFacet {
+
+    public static class Util {
+        private Util(){}
+        
+        @SuppressWarnings("unchecked")
+        public static <S> ActionInvokedEvent<S> newEvent(
+                    final Class<? extends ActionInvokedEvent<S>> type, 
+                    final S source, 
+                    final Identifier identifier, 
+                    final Object... arguments) throws InstantiationException, IllegalAccessException, IllegalArgumentException, InvocationTargetException, NoSuchMethodException, SecurityException {
+            final Constructor<?>[] constructors = type.getConstructors();
+            for (final Constructor<?> constructor : constructors) {
+                final Class<?>[] parameterTypes = constructor.getParameterTypes();
+                if(parameterTypes.length != 3) {
+                    continue;
+                }
+                if(!parameterTypes[0].isAssignableFrom(source.getClass())) {
+                    continue;
+                }
+                if(!parameterTypes[1].isAssignableFrom(Identifier.class)) {
+                    continue;
+                }
+                if(!parameterTypes[2].isAssignableFrom(Object[].class)) {
+                    continue;
+                }
+                final Object event = constructor.newInstance(source, identifier, arguments);
+                return (ActionInvokedEvent<S>) event;
+            }
+            throw new NoSuchMethodException(type.getName()+".<init>(? super " + source.getClass().getName() + ", " + Identifier.class.getName() + ", [Ljava.lang.Object;)");
+        }
+    }
+}

http://git-wip-us.apache.org/repos/asf/isis/blob/e1f19baa/core/metamodel/src/main/java/org/apache/isis/core/metamodel/facets/actions/event/PostsActionInvokedEventFacetAbstract.java
----------------------------------------------------------------------
diff --git a/core/metamodel/src/main/java/org/apache/isis/core/metamodel/facets/actions/event/PostsActionInvokedEventFacetAbstract.java b/core/metamodel/src/main/java/org/apache/isis/core/metamodel/facets/actions/event/PostsActionInvokedEventFacetAbstract.java
new file mode 100644
index 0000000..2d74722
--- /dev/null
+++ b/core/metamodel/src/main/java/org/apache/isis/core/metamodel/facets/actions/event/PostsActionInvokedEventFacetAbstract.java
@@ -0,0 +1,44 @@
+/*
+ *  Licensed to the Apache Software Foundation (ASF) under one
+ *  or more contributor license agreements.  See the NOTICE file
+ *  distributed with this work for additional information
+ *  regarding copyright ownership.  The ASF licenses this file
+ *  to you under the Apache License, Version 2.0 (the
+ *  "License"); you may not use this file except in compliance
+ *  with the License.  You may obtain a copy of the License at
+ *
+ *        http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *  Unless required by applicable law or agreed to in writing,
+ *  software distributed under the License is distributed on an
+ *  "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ *  KIND, either express or implied.  See the License for the
+ *  specific language governing permissions and limitations
+ *  under the License.
+ */
+
+package org.apache.isis.core.metamodel.facets.actions.event;
+
+import org.apache.isis.core.metamodel.facetapi.Facet;
+import org.apache.isis.core.metamodel.facetapi.FacetAbstract;
+import org.apache.isis.core.metamodel.facetapi.FacetHolder;
+import org.apache.isis.core.metamodel.facets.actions.invoke.ActionInvocationFacet;
+
+public abstract class PostsActionInvokedEventFacetAbstract 
+        extends FacetAbstract 
+        implements ActionInvocationFacet {
+
+    public static Class<? extends Facet> type() {
+    	
+	    // the "primary" type is ActionInvocationFacet rather than PostsActionInvokedEventFacet
+	    // so that this facet can wrap an existing (via setUnderlying).
+	    
+        //return PostsActionInvokedEventFacetAbstract.class;
+        return ActionInvocationFacet.class;
+    }
+
+    public PostsActionInvokedEventFacetAbstract(final FacetHolder holder) {
+        super(type(), holder, Derivation.NOT_DERIVED);
+    }
+
+}

http://git-wip-us.apache.org/repos/asf/isis/blob/e1f19baa/core/metamodel/src/main/java/org/apache/isis/core/metamodel/facets/actions/invoke/event/PostsActionInvokedEventFacet.java
----------------------------------------------------------------------
diff --git a/core/metamodel/src/main/java/org/apache/isis/core/metamodel/facets/actions/invoke/event/PostsActionInvokedEventFacet.java b/core/metamodel/src/main/java/org/apache/isis/core/metamodel/facets/actions/invoke/event/PostsActionInvokedEventFacet.java
deleted file mode 100644
index 8f9d070..0000000
--- a/core/metamodel/src/main/java/org/apache/isis/core/metamodel/facets/actions/invoke/event/PostsActionInvokedEventFacet.java
+++ /dev/null
@@ -1,32 +0,0 @@
-/*
- *  Licensed to the Apache Software Foundation (ASF) under one
- *  or more contributor license agreements.  See the NOTICE file
- *  distributed with this work for additional information
- *  regarding copyright ownership.  The ASF licenses this file
- *  to you under the Apache License, Version 2.0 (the
- *  "License"); you may not use this file except in compliance
- *  with the License.  You may obtain a copy of the License at
- *
- *        http://www.apache.org/licenses/LICENSE-2.0
- *
- *  Unless required by applicable law or agreed to in writing,
- *  software distributed under the License is distributed on an
- *  "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- *  KIND, either express or implied.  See the License for the
- *  specific language governing permissions and limitations
- *  under the License.
- */
-
-package org.apache.isis.core.metamodel.facets.actions.invoke.event;
-
-import org.apache.isis.core.metamodel.facets.actions.invoke.ActionInvocationFacet;
-
-/**
- * Extends the mechanism by which the action should be invoked by sending an
- * Event to the internal Event Bus after being invoked without throwing 
- * an Exception.
- * 
- */
-public interface PostsActionInvokedEventFacet extends ActionInvocationFacet {
-
-}

http://git-wip-us.apache.org/repos/asf/isis/blob/e1f19baa/core/metamodel/src/main/java/org/apache/isis/core/metamodel/facets/actions/invoke/event/PostsActionInvokedEventFacetAbstract.java
----------------------------------------------------------------------
diff --git a/core/metamodel/src/main/java/org/apache/isis/core/metamodel/facets/actions/invoke/event/PostsActionInvokedEventFacetAbstract.java b/core/metamodel/src/main/java/org/apache/isis/core/metamodel/facets/actions/invoke/event/PostsActionInvokedEventFacetAbstract.java
deleted file mode 100644
index 8a0115f..0000000
--- a/core/metamodel/src/main/java/org/apache/isis/core/metamodel/facets/actions/invoke/event/PostsActionInvokedEventFacetAbstract.java
+++ /dev/null
@@ -1,42 +0,0 @@
-/*
- *  Licensed to the Apache Software Foundation (ASF) under one
- *  or more contributor license agreements.  See the NOTICE file
- *  distributed with this work for additional information
- *  regarding copyright ownership.  The ASF licenses this file
- *  to you under the Apache License, Version 2.0 (the
- *  "License"); you may not use this file except in compliance
- *  with the License.  You may obtain a copy of the License at
- *
- *        http://www.apache.org/licenses/LICENSE-2.0
- *
- *  Unless required by applicable law or agreed to in writing,
- *  software distributed under the License is distributed on an
- *  "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- *  KIND, either express or implied.  See the License for the
- *  specific language governing permissions and limitations
- *  under the License.
- */
-
-package org.apache.isis.core.metamodel.facets.actions.invoke.event;
-
-import org.apache.isis.core.metamodel.facetapi.Facet;
-import org.apache.isis.core.metamodel.facetapi.FacetAbstract;
-import org.apache.isis.core.metamodel.facetapi.FacetHolder;
-import org.apache.isis.core.metamodel.facets.actions.invoke.ActionInvocationFacet;
-
-public abstract class PostsActionInvokedEventFacetAbstract extends FacetAbstract implements ActionInvocationFacet {
-
-    public static Class<? extends Facet> type() {
-    	
-	    // the "primary" type is ActionInvocationFacet rather than PostsActionInvokedEventFacet
-	    // so that this facet can wrap an existing (via setUnderlying).
-	    
-        //return PostsActionInvokedEventFacetAbstract.class;
-        return ActionInvocationFacet.class;
-    }
-
-    public PostsActionInvokedEventFacetAbstract(final FacetHolder holder) {
-        super(type(), holder, Derivation.NOT_DERIVED);
-    }
-
-}

http://git-wip-us.apache.org/repos/asf/isis/blob/e1f19baa/core/metamodel/src/main/java/org/apache/isis/core/metamodel/facets/collections/event/PostsCollectionAddedToEventFacet.java
----------------------------------------------------------------------
diff --git a/core/metamodel/src/main/java/org/apache/isis/core/metamodel/facets/collections/event/PostsCollectionAddedToEventFacet.java b/core/metamodel/src/main/java/org/apache/isis/core/metamodel/facets/collections/event/PostsCollectionAddedToEventFacet.java
index f437667..f64aa8d 100644
--- a/core/metamodel/src/main/java/org/apache/isis/core/metamodel/facets/collections/event/PostsCollectionAddedToEventFacet.java
+++ b/core/metamodel/src/main/java/org/apache/isis/core/metamodel/facets/collections/event/PostsCollectionAddedToEventFacet.java
@@ -19,8 +19,13 @@
 
 package org.apache.isis.core.metamodel.facets.collections.event;
 
+import java.lang.reflect.Constructor;
+import java.lang.reflect.InvocationTargetException;
+
+import org.apache.isis.applib.Identifier;
 import org.apache.isis.applib.services.eventbus.CollectionAddedToEvent;
 import org.apache.isis.applib.services.eventbus.EventBusService;
+import org.apache.isis.applib.services.eventbus.PropertyChangedEvent;
 import org.apache.isis.core.metamodel.facetapi.MultiTypedFacet;
 import org.apache.isis.core.metamodel.facets.SingleValueFacet;
 import org.apache.isis.core.metamodel.facets.collections.modify.CollectionAddToFacet;
@@ -30,5 +35,37 @@ import org.apache.isis.core.metamodel.facets.collections.modify.CollectionAddToF
  * {@link EventBusService}.
  */
 public interface PostsCollectionAddedToEventFacet extends SingleValueFacet<Class<? extends CollectionAddedToEvent<?,?>>>, CollectionAddToFacet, MultiTypedFacet {
+    
+    public static class Util {
+        private Util(){}
+        
+        @SuppressWarnings("unchecked")
+        public static <S, T> CollectionAddedToEvent<S, T> newEvent(
+                final Class<? extends CollectionAddedToEvent<S, T>> type,
+                final S source, 
+                final Identifier identifier,
+                final T value) throws NoSuchMethodException, SecurityException, InstantiationException, IllegalAccessException, IllegalArgumentException, InvocationTargetException {
+            final Constructor<?>[] constructors = type.getConstructors();
+            for (final Constructor<?> constructor : constructors) {
+                final Class<?>[] parameterTypes = constructor.getParameterTypes();
+                if(parameterTypes.length != 3) {
+                    continue;
+                }
+                if(!parameterTypes[0].isAssignableFrom(source.getClass())) {
+                    continue;
+                }
+                if(!parameterTypes[1].isAssignableFrom(Identifier.class)) {
+                    continue;
+                }
+                if(value != null && !parameterTypes[2].isAssignableFrom(value.getClass())) {
+                    continue;
+                }
+                final Object event = constructor.newInstance(source, identifier, value);
+                return (CollectionAddedToEvent<S, T>) event;
+            }
+            throw new NoSuchMethodException(type.getName()+".<init>(? super " + source.getClass().getName() + ", " + Identifier.class.getName() + ", java.lang.Object)");
+        }
+
+    }
 }
 

http://git-wip-us.apache.org/repos/asf/isis/blob/e1f19baa/core/metamodel/src/main/java/org/apache/isis/core/metamodel/facets/collections/event/PostsCollectionAddedToEventFacetAbstract.java
----------------------------------------------------------------------
diff --git a/core/metamodel/src/main/java/org/apache/isis/core/metamodel/facets/collections/event/PostsCollectionAddedToEventFacetAbstract.java b/core/metamodel/src/main/java/org/apache/isis/core/metamodel/facets/collections/event/PostsCollectionAddedToEventFacetAbstract.java
index 7423a41..57a1618 100644
--- a/core/metamodel/src/main/java/org/apache/isis/core/metamodel/facets/collections/event/PostsCollectionAddedToEventFacetAbstract.java
+++ b/core/metamodel/src/main/java/org/apache/isis/core/metamodel/facets/collections/event/PostsCollectionAddedToEventFacetAbstract.java
@@ -19,7 +19,12 @@
 
 package org.apache.isis.core.metamodel.facets.collections.event;
 
+import java.lang.reflect.Constructor;
+import java.lang.reflect.InvocationTargetException;
+
+import org.apache.isis.applib.Identifier;
 import org.apache.isis.applib.services.eventbus.CollectionAddedToEvent;
+import org.apache.isis.applib.services.eventbus.PropertyChangedEvent;
 import org.apache.isis.core.metamodel.facetapi.Facet;
 import org.apache.isis.core.metamodel.facetapi.FacetHolder;
 import org.apache.isis.core.metamodel.facets.SingleValueFacetAbstract;
@@ -45,4 +50,5 @@ public abstract class PostsCollectionAddedToEventFacetAbstract
         super(type(), changedEventType, holder);
     }
 
+
 }

http://git-wip-us.apache.org/repos/asf/isis/blob/e1f19baa/core/metamodel/src/main/java/org/apache/isis/core/metamodel/facets/collections/event/PostsCollectionRemovedFromEventFacet.java
----------------------------------------------------------------------
diff --git a/core/metamodel/src/main/java/org/apache/isis/core/metamodel/facets/collections/event/PostsCollectionRemovedFromEventFacet.java b/core/metamodel/src/main/java/org/apache/isis/core/metamodel/facets/collections/event/PostsCollectionRemovedFromEventFacet.java
index 90a657b..18ff1b6 100644
--- a/core/metamodel/src/main/java/org/apache/isis/core/metamodel/facets/collections/event/PostsCollectionRemovedFromEventFacet.java
+++ b/core/metamodel/src/main/java/org/apache/isis/core/metamodel/facets/collections/event/PostsCollectionRemovedFromEventFacet.java
@@ -19,6 +19,10 @@
 
 package org.apache.isis.core.metamodel.facets.collections.event;
 
+import java.lang.reflect.Constructor;
+import java.lang.reflect.InvocationTargetException;
+
+import org.apache.isis.applib.Identifier;
 import org.apache.isis.applib.services.eventbus.CollectionRemovedFromEvent;
 import org.apache.isis.applib.services.eventbus.EventBusService;
 import org.apache.isis.core.metamodel.facetapi.MultiTypedFacet;
@@ -30,5 +34,39 @@ import org.apache.isis.core.metamodel.facets.collections.modify.CollectionRemove
  * {@link EventBusService}.
  */
 public interface PostsCollectionRemovedFromEventFacet extends SingleValueFacet<Class<? extends CollectionRemovedFromEvent<?,?>>>, CollectionRemoveFromFacet, MultiTypedFacet {
+
+
+    public static class Util {
+        private Util(){}
+
+        @SuppressWarnings("unchecked")
+        public static <S, T> CollectionRemovedFromEvent<S, T> newEvent(
+                final Class<? extends CollectionRemovedFromEvent<S, T>> type,
+                        final S source, 
+                        final Identifier identifier, 
+                        final T value) 
+                                throws InstantiationException, IllegalAccessException, IllegalArgumentException, InvocationTargetException, NoSuchMethodException, SecurityException {
+            final Constructor<?>[] constructors = type.getConstructors();
+            for (final Constructor<?> constructor : constructors) {
+                final Class<?>[] parameterTypes = constructor.getParameterTypes();
+                if(parameterTypes.length != 3) {
+                    continue;
+                }
+                if(!parameterTypes[0].isAssignableFrom(source.getClass())) {
+                    continue;
+                }
+                if(!parameterTypes[1].isAssignableFrom(Identifier.class)) {
+                    continue;
+                }
+                if(value != null && !parameterTypes[2].isAssignableFrom(value.getClass())) {
+                    continue;
+                }
+                final Object event = constructor.newInstance(source, identifier, value);
+                return (CollectionRemovedFromEvent<S, T>) event;
+            }
+            throw new NoSuchMethodException(type.getName()+".<init>(? super " + source.getClass().getName() + ", " + Identifier.class.getName() + ", java.lang.Object)");
+        }
+    }
+
 }
 

http://git-wip-us.apache.org/repos/asf/isis/blob/e1f19baa/core/metamodel/src/main/java/org/apache/isis/core/metamodel/facets/collections/event/PostsCollectionRemovedFromEventFacetAbstract.java
----------------------------------------------------------------------
diff --git a/core/metamodel/src/main/java/org/apache/isis/core/metamodel/facets/collections/event/PostsCollectionRemovedFromEventFacetAbstract.java b/core/metamodel/src/main/java/org/apache/isis/core/metamodel/facets/collections/event/PostsCollectionRemovedFromEventFacetAbstract.java
index 18fc423..ed1e0a4 100644
--- a/core/metamodel/src/main/java/org/apache/isis/core/metamodel/facets/collections/event/PostsCollectionRemovedFromEventFacetAbstract.java
+++ b/core/metamodel/src/main/java/org/apache/isis/core/metamodel/facets/collections/event/PostsCollectionRemovedFromEventFacetAbstract.java
@@ -19,6 +19,9 @@
 
 package org.apache.isis.core.metamodel.facets.collections.event;
 
+import java.lang.reflect.InvocationTargetException;
+
+import org.apache.isis.applib.Identifier;
 import org.apache.isis.applib.services.eventbus.CollectionRemovedFromEvent;
 import org.apache.isis.core.metamodel.facetapi.Facet;
 import org.apache.isis.core.metamodel.facetapi.FacetHolder;

http://git-wip-us.apache.org/repos/asf/isis/blob/e1f19baa/core/metamodel/src/main/java/org/apache/isis/core/metamodel/facets/properties/event/PostsPropertyChangedEventFacet.java
----------------------------------------------------------------------
diff --git a/core/metamodel/src/main/java/org/apache/isis/core/metamodel/facets/properties/event/PostsPropertyChangedEventFacet.java b/core/metamodel/src/main/java/org/apache/isis/core/metamodel/facets/properties/event/PostsPropertyChangedEventFacet.java
index a01e7f4..a7d3fd5 100644
--- a/core/metamodel/src/main/java/org/apache/isis/core/metamodel/facets/properties/event/PostsPropertyChangedEventFacet.java
+++ b/core/metamodel/src/main/java/org/apache/isis/core/metamodel/facets/properties/event/PostsPropertyChangedEventFacet.java
@@ -19,6 +19,11 @@
 
 package org.apache.isis.core.metamodel.facets.properties.event;
 
+import java.lang.reflect.Constructor;
+import java.lang.reflect.InvocationTargetException;
+
+import org.apache.isis.applib.Identifier;
+import org.apache.isis.applib.services.eventbus.ActionInvokedEvent;
 import org.apache.isis.applib.services.eventbus.EventBusService;
 import org.apache.isis.applib.services.eventbus.PropertyChangedEvent;
 import org.apache.isis.core.metamodel.facetapi.MultiTypedFacet;
@@ -32,4 +37,37 @@ import org.apache.isis.core.metamodel.facets.properties.modify.PropertySetterFac
  */
 public interface PostsPropertyChangedEventFacet extends SingleValueFacet<Class<? extends PropertyChangedEvent<?,?>>>, PropertyClearFacet, PropertySetterFacet, MultiTypedFacet {
 
+    public static class Util {
+        private Util(){}
+        @SuppressWarnings("unchecked")
+        public static <S,T> PropertyChangedEvent<S,T> newEvent(
+                final Class<? extends PropertyChangedEvent<S, T>> type, 
+                final S source, 
+                final Identifier identifier,
+                final T oldValue, 
+                final T newValue) throws NoSuchMethodException, SecurityException, InstantiationException, IllegalAccessException, IllegalArgumentException, InvocationTargetException  {
+            final Constructor<?>[] constructors = type.getConstructors();
+            for (final Constructor<?> constructor : constructors) {
+                final Class<?>[] parameterTypes = constructor.getParameterTypes();
+                if(parameterTypes.length != 4) {
+                    continue;
+                }
+                if(!parameterTypes[0].isAssignableFrom(source.getClass())) {
+                    continue;
+                }
+                if(!parameterTypes[1].isAssignableFrom(Identifier.class)) {
+                    continue;
+                }
+                if(oldValue != null && !parameterTypes[2].isAssignableFrom(oldValue.getClass())) {
+                    continue;
+                }
+                if(newValue != null && !parameterTypes[3].isAssignableFrom(newValue.getClass())) {
+                    continue;
+                }
+                final Object event = constructor.newInstance(source, identifier, oldValue, newValue);
+                return (PropertyChangedEvent<S, T>) event;
+            }
+            throw new NoSuchMethodException(type.getName()+".<init>(? super " + source.getClass().getName() + ", " + Identifier.class.getName() + ", java.lang.Object, java.lang.Object)");
+        }
+    }
 }

http://git-wip-us.apache.org/repos/asf/isis/blob/e1f19baa/core/metamodel/src/main/java/org/apache/isis/core/metamodel/facets/properties/event/PostsPropertyChangedEventFacetAbstract.java
----------------------------------------------------------------------
diff --git a/core/metamodel/src/main/java/org/apache/isis/core/metamodel/facets/properties/event/PostsPropertyChangedEventFacetAbstract.java b/core/metamodel/src/main/java/org/apache/isis/core/metamodel/facets/properties/event/PostsPropertyChangedEventFacetAbstract.java
index 1acbf8d..968d4ae 100644
--- a/core/metamodel/src/main/java/org/apache/isis/core/metamodel/facets/properties/event/PostsPropertyChangedEventFacetAbstract.java
+++ b/core/metamodel/src/main/java/org/apache/isis/core/metamodel/facets/properties/event/PostsPropertyChangedEventFacetAbstract.java
@@ -19,6 +19,10 @@
 
 package org.apache.isis.core.metamodel.facets.properties.event;
 
+import java.lang.reflect.Constructor;
+import java.lang.reflect.InvocationTargetException;
+
+import org.apache.isis.applib.Identifier;
 import org.apache.isis.applib.services.eventbus.PropertyChangedEvent;
 import org.apache.isis.core.metamodel.facetapi.Facet;
 import org.apache.isis.core.metamodel.facetapi.FacetHolder;

http://git-wip-us.apache.org/repos/asf/isis/blob/e1f19baa/core/metamodel/src/main/java/org/apache/isis/core/progmodel/facets/actions/invoke/ActionInvocationFacetViaMethod.java
----------------------------------------------------------------------
diff --git a/core/metamodel/src/main/java/org/apache/isis/core/progmodel/facets/actions/invoke/ActionInvocationFacetViaMethod.java b/core/metamodel/src/main/java/org/apache/isis/core/progmodel/facets/actions/invoke/ActionInvocationFacetViaMethod.java
index 4f9dfbf..e9956d1 100644
--- a/core/metamodel/src/main/java/org/apache/isis/core/progmodel/facets/actions/invoke/ActionInvocationFacetViaMethod.java
+++ b/core/metamodel/src/main/java/org/apache/isis/core/progmodel/facets/actions/invoke/ActionInvocationFacetViaMethod.java
@@ -162,9 +162,6 @@ public class ActionInvocationFacetViaMethod extends ActionInvocationFacetAbstrac
 		public ObjectAdapter getAdapter() {
 			return adapter;
 		}
-
-
-    	
     }
     
     protected InvocationResult internalInvoke(

http://git-wip-us.apache.org/repos/asf/isis/blob/e1f19baa/core/metamodel/src/main/java/org/apache/isis/core/progmodel/facets/actions/invoke/event/PostsActionInvokedEventFacetAnnotation.java
----------------------------------------------------------------------
diff --git a/core/metamodel/src/main/java/org/apache/isis/core/progmodel/facets/actions/invoke/event/PostsActionInvokedEventFacetAnnotation.java b/core/metamodel/src/main/java/org/apache/isis/core/progmodel/facets/actions/invoke/event/PostsActionInvokedEventFacetAnnotation.java
new file mode 100644
index 0000000..db1155f
--- /dev/null
+++ b/core/metamodel/src/main/java/org/apache/isis/core/progmodel/facets/actions/invoke/event/PostsActionInvokedEventFacetAnnotation.java
@@ -0,0 +1,112 @@
+/*
+ *  Licensed to the Apache Software Foundation (ASF) under one
+ *  or more contributor license agreements.  See the NOTICE file
+ *  distributed with this work for additional information
+ *  regarding copyright ownership.  The ASF licenses this file
+ *  to you under the Apache License, Version 2.0 (the
+ *  "License"); you may not use this file except in compliance
+ *  with the License.  You may obtain a copy of the License at
+ *
+ *        http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *  Unless required by applicable law or agreed to in writing,
+ *  software distributed under the License is distributed on an
+ *  "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ *  KIND, either express or implied.  See the License for the
+ *  specific language governing permissions and limitations
+ *  under the License.
+ */
+
+package org.apache.isis.core.progmodel.facets.actions.invoke.event;
+
+import java.lang.reflect.Field;
+import java.lang.reflect.Method;
+
+import org.apache.isis.applib.FatalException;
+import org.apache.isis.applib.Identifier;
+import org.apache.isis.applib.services.eventbus.ActionInvokedEvent;
+import org.apache.isis.applib.services.eventbus.CollectionAddedToEvent;
+import org.apache.isis.applib.services.eventbus.EventBusService;
+import org.apache.isis.core.metamodel.adapter.ObjectAdapter;
+import org.apache.isis.core.metamodel.adapter.mgr.AdapterManager;
+import org.apache.isis.core.metamodel.adapter.util.AdapterUtils;
+import org.apache.isis.core.metamodel.facetapi.FacetHolder;
+import org.apache.isis.core.metamodel.facets.ImperativeFacet;
+import org.apache.isis.core.metamodel.facets.actions.event.PostsActionInvokedEventFacet;
+import org.apache.isis.core.metamodel.runtimecontext.RuntimeContext;
+import org.apache.isis.core.metamodel.runtimecontext.ServicesInjector;
+import org.apache.isis.core.metamodel.spec.ObjectSpecification;
+import org.apache.isis.core.metamodel.spec.feature.ObjectAction;
+import org.apache.isis.core.progmodel.facets.actions.invoke.ActionInvocationFacetViaMethod;
+
+public class PostsActionInvokedEventFacetAnnotation 
+        extends ActionInvocationFacetViaMethod 
+        implements ImperativeFacet, PostsActionInvokedEventFacet {
+	
+	private ServicesInjector servicesInjector;
+	private Class<? extends ActionInvokedEvent<?>> eventType;
+
+	private EventBusService eventBusService;
+	private boolean searchedForEventBusService = false;
+	
+    public PostsActionInvokedEventFacetAnnotation(
+            final Method method, 
+            final ObjectSpecification onType, 
+            final ObjectSpecification returnType, 
+            final FacetHolder holder, 
+            final RuntimeContext runtimeContext, 
+            final AdapterManager adapterManager, 
+            final ServicesInjector servicesInjector,
+			final Class<? extends ActionInvokedEvent<?>> eventType) {
+        super(method, onType, returnType, holder, runtimeContext, adapterManager, servicesInjector);
+        
+        this.servicesInjector = servicesInjector;
+        
+        this.eventType = eventType;
+    }
+
+    @Override
+    public ObjectAdapter invoke(
+            final ObjectAction owningAction, 
+            final ObjectAdapter targetAdapter, 
+            final ObjectAdapter[] arguments) {
+
+    	final InvocationResult invocationResult = this.internalInvoke(owningAction, targetAdapter, arguments);
+    	
+    	// Perhaps the Action was not properly invoked (i.e. an exception was raised).
+    	if (invocationResult.getWhetherInvoked()) {
+    		// If invoked, then send the ActionInvokedEvent to the EventBus.
+    		postEvent(owningAction, targetAdapter, arguments);
+    	}
+    	
+    	return invocationResult.getAdapter();
+    }
+    
+	@SuppressWarnings({ "rawtypes" })
+	private void postEvent(
+            final ObjectAction owningAction, 
+            final ObjectAdapter targetAdapter, 
+            final ObjectAdapter[] argumentAdapters) {
+	    
+		try {
+			final Class type = eventType;
+			Identifier actionIdentifier = owningAction.getIdentifier();
+	        final Object source = AdapterUtils.unwrap(targetAdapter);
+			final Object[] arguments = AdapterUtils.unwrap(argumentAdapters);
+            @SuppressWarnings("unchecked")
+            final ActionInvokedEvent<?> event = org.apache.isis.core.metamodel.facets.actions.event.PostsActionInvokedEventFacet.Util.newEvent(type, source, actionIdentifier, arguments);
+			getEventBusService().post(event);
+		} catch (Exception e) {
+			throw new FatalException(e);
+		}
+	}
+
+	private EventBusService getEventBusService() {
+		if (!searchedForEventBusService) {
+			eventBusService = this.servicesInjector.lookupService(EventBusService.class);
+		}
+		searchedForEventBusService = true;
+		return eventBusService;
+	}
+
+}

http://git-wip-us.apache.org/repos/asf/isis/blob/e1f19baa/core/metamodel/src/main/java/org/apache/isis/core/progmodel/facets/actions/invoke/event/PostsActionInvokedEventFacetFactory.java
----------------------------------------------------------------------
diff --git a/core/metamodel/src/main/java/org/apache/isis/core/progmodel/facets/actions/invoke/event/PostsActionInvokedEventFacetFactory.java b/core/metamodel/src/main/java/org/apache/isis/core/progmodel/facets/actions/invoke/event/PostsActionInvokedEventFacetFactory.java
index e46e7cc..d52b55a 100644
--- a/core/metamodel/src/main/java/org/apache/isis/core/progmodel/facets/actions/invoke/event/PostsActionInvokedEventFacetFactory.java
+++ b/core/metamodel/src/main/java/org/apache/isis/core/progmodel/facets/actions/invoke/event/PostsActionInvokedEventFacetFactory.java
@@ -21,7 +21,9 @@ package org.apache.isis.core.progmodel.facets.actions.invoke.event;
 
 import java.lang.reflect.Method;
 
+import org.apache.isis.applib.annotation.PostsActionInvokedEvent;
 import org.apache.isis.applib.annotation.PostsCollectionAddedToEvent;
+import org.apache.isis.applib.services.eventbus.ActionInvokedEvent;
 import org.apache.isis.applib.services.eventbus.CollectionAddedToEvent;
 import org.apache.isis.core.commons.lang.StringExtensions;
 import org.apache.isis.core.metamodel.adapter.mgr.AdapterManager;
@@ -97,7 +99,7 @@ public class PostsActionInvokedEventFacetFactory extends MethodPrefixBasedFacetF
         final Method actionMethod = processMethodContext.getMethod();
 
         try {
-            final PostsCollectionAddedToEvent annotation = Annotations.getAnnotation(actionMethod, PostsCollectionAddedToEvent.class);
+            final PostsActionInvokedEvent annotation = Annotations.getAnnotation(actionMethod, PostsActionInvokedEvent.class);
             if(annotation == null) {
                 return;
             }
@@ -112,9 +114,9 @@ public class PostsActionInvokedEventFacetFactory extends MethodPrefixBasedFacetF
             final ObjectSpecification typeSpec = getSpecificationLoader().loadSpecification(cls);
             final FacetHolder holder = processMethodContext.getFacetHolder();
             
-            final Class<? extends CollectionAddedToEvent<?,?>> changedEventType = annotation.value();
+            final Class<? extends ActionInvokedEvent<?>> changedEventType = annotation.value();
 
-            FacetUtil.addFacet(new PostsActionInvokedEventFacetViaMethod(actionMethod, typeSpec, returnSpec, holder, getRuntimeContext(), getAdapterManager(), getServicesInjector(), changedEventType));
+            FacetUtil.addFacet(new PostsActionInvokedEventFacetAnnotation(actionMethod, typeSpec, returnSpec, holder, getRuntimeContext(), getAdapterManager(), getServicesInjector(), changedEventType));
         } finally {
             processMethodContext.removeMethod(actionMethod);
         }

http://git-wip-us.apache.org/repos/asf/isis/blob/e1f19baa/core/metamodel/src/main/java/org/apache/isis/core/progmodel/facets/actions/invoke/event/PostsActionInvokedEventFacetViaMethod.java
----------------------------------------------------------------------
diff --git a/core/metamodel/src/main/java/org/apache/isis/core/progmodel/facets/actions/invoke/event/PostsActionInvokedEventFacetViaMethod.java b/core/metamodel/src/main/java/org/apache/isis/core/progmodel/facets/actions/invoke/event/PostsActionInvokedEventFacetViaMethod.java
deleted file mode 100644
index 16f2fb7..0000000
--- a/core/metamodel/src/main/java/org/apache/isis/core/progmodel/facets/actions/invoke/event/PostsActionInvokedEventFacetViaMethod.java
+++ /dev/null
@@ -1,129 +0,0 @@
-/*
- *  Licensed to the Apache Software Foundation (ASF) under one
- *  or more contributor license agreements.  See the NOTICE file
- *  distributed with this work for additional information
- *  regarding copyright ownership.  The ASF licenses this file
- *  to you under the Apache License, Version 2.0 (the
- *  "License"); you may not use this file except in compliance
- *  with the License.  You may obtain a copy of the License at
- *
- *        http://www.apache.org/licenses/LICENSE-2.0
- *
- *  Unless required by applicable law or agreed to in writing,
- *  software distributed under the License is distributed on an
- *  "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- *  KIND, either express or implied.  See the License for the
- *  specific language governing permissions and limitations
- *  under the License.
- */
-
-package org.apache.isis.core.progmodel.facets.actions.invoke.event;
-
-import java.lang.reflect.Field;
-import java.lang.reflect.Method;
-
-import org.apache.isis.applib.FatalException;
-import org.apache.isis.applib.services.eventbus.ActionInvokedEvent;
-import org.apache.isis.applib.services.eventbus.CollectionAddedToEvent;
-import org.apache.isis.applib.services.eventbus.EventBusService;
-import org.apache.isis.core.metamodel.adapter.ObjectAdapter;
-import org.apache.isis.core.metamodel.adapter.mgr.AdapterManager;
-import org.apache.isis.core.metamodel.facetapi.FacetHolder;
-import org.apache.isis.core.metamodel.facets.ImperativeFacet;
-import org.apache.isis.core.metamodel.runtimecontext.RuntimeContext;
-import org.apache.isis.core.metamodel.runtimecontext.ServicesInjector;
-import org.apache.isis.core.metamodel.spec.ObjectSpecification;
-import org.apache.isis.core.metamodel.spec.feature.ObjectAction;
-import org.apache.isis.core.progmodel.facets.actions.invoke.ActionInvocationFacetViaMethod;
-
-public class PostsActionInvokedEventFacetViaMethod extends ActionInvocationFacetViaMethod implements ImperativeFacet {
-	
-	private EventBusService eventBusService;
-	private boolean searchedForEventBusService = false;
-	private ServicesInjector servicesInjector;
-	private Class<? extends CollectionAddedToEvent<?, ?>> eventType;
-
-    public PostsActionInvokedEventFacetViaMethod(
-            final Method method, 
-            final ObjectSpecification onType, 
-            final ObjectSpecification returnType, 
-            final FacetHolder holder, 
-            final RuntimeContext runtimeContext, 
-            final AdapterManager adapterManager, 
-            final ServicesInjector servicesInjector,
-			final Class<? extends CollectionAddedToEvent<?, ?>> eventType) {
-        super(method, onType, returnType, holder, runtimeContext, adapterManager, servicesInjector);
-        
-        // Also needed here.
-        this.servicesInjector = servicesInjector;
-        
-        this.eventType = eventType;
-    }
-
-    @Override
-    public ObjectAdapter invoke(
-            final ObjectAction owningAction, 
-            final ObjectAdapter targetAdapter, 
-            final ObjectAdapter[] arguments) {
-
-    	final InvocationResult invocationResult = this.internalInvoke(owningAction, targetAdapter, arguments);
-    	
-    	// Perhaps the Action was not properly invoked (i.e. an exception was raised).
-    	if (invocationResult.getWhetherInvoked()) {
-    		// If invoked, then send the ActionInvokedEvent to the EventBus.
-    		postEvent(owningAction, targetAdapter, arguments);
-    	}
-    	
-    	return invocationResult.getAdapter();
-    	
-    }
-    
-	@SuppressWarnings({ "rawtypes", "unchecked" })
-	private void postEvent(
-            final ObjectAction owningAction, 
-            final ObjectAdapter targetAdapter, 
-            final ObjectAdapter[] arguments) {
-	    
-		final Object source = targetAdapter.getObject();
-		try {
-			final Class type = eventType;
-			final ActionInvokedEvent event = newEvent(type, owningAction, source, arguments);
-			getEventBusService().post(event);
-		} catch (Exception e) {
-			throw new FatalException(e);
-		}
-	}
-
-	static <S> ActionInvokedEvent<S> newEvent(
-			final Class<? extends ActionInvokedEvent<S>> type,
-		            final ObjectAction owningAction, 
-		            final S source, 
-		            final ObjectAdapter[] arguments)
-			throws InstantiationException, IllegalAccessException,
-			NoSuchFieldException {
-		final ActionInvokedEvent<S> event = type.newInstance();
-
-		setField("owningAction", event, owningAction);
-		setField("targetAdapter", event, source);
-		setField("arguments", event, arguments.toString());
-		return event;
-	}
-
-	private static void setField(final String name,
-			final ActionInvokedEvent<?> event, final Object sourceValue)
-			throws NoSuchFieldException, IllegalAccessException {
-		final Field sourceField = CollectionAddedToEvent.class
-				.getDeclaredField(name);
-		sourceField.setAccessible(true);
-		sourceField.set(event, sourceValue);
-	}
-
-	private EventBusService getEventBusService() {
-		if (!searchedForEventBusService) {
-			eventBusService = this.servicesInjector.lookupService(EventBusService.class);
-		}
-		searchedForEventBusService = true;
-		return eventBusService;
-	}
-
-}

http://git-wip-us.apache.org/repos/asf/isis/blob/e1f19baa/core/metamodel/src/main/java/org/apache/isis/core/progmodel/facets/collections/event/PostsCollectionAddedToEventAnnotationFacetFactory.java
----------------------------------------------------------------------
diff --git a/core/metamodel/src/main/java/org/apache/isis/core/progmodel/facets/collections/event/PostsCollectionAddedToEventAnnotationFacetFactory.java b/core/metamodel/src/main/java/org/apache/isis/core/progmodel/facets/collections/event/PostsCollectionAddedToEventAnnotationFacetFactory.java
index 5292f07..d59a07a 100644
--- a/core/metamodel/src/main/java/org/apache/isis/core/progmodel/facets/collections/event/PostsCollectionAddedToEventAnnotationFacetFactory.java
+++ b/core/metamodel/src/main/java/org/apache/isis/core/progmodel/facets/collections/event/PostsCollectionAddedToEventAnnotationFacetFactory.java
@@ -33,10 +33,12 @@ import org.apache.isis.core.metamodel.facets.FacetFactoryAbstract;
 import org.apache.isis.core.metamodel.facets.accessor.PropertyOrCollectionAccessorFacet;
 import org.apache.isis.core.metamodel.facets.collections.event.PostsCollectionAddedToEventFacet;
 import org.apache.isis.core.metamodel.facets.collections.modify.CollectionAddToFacet;
+import org.apache.isis.core.metamodel.runtimecontext.ServicesInjector;
+import org.apache.isis.core.metamodel.runtimecontext.ServicesInjectorAware;
 
-public class PostsCollectionAddedToEventAnnotationFacetFactory extends FacetFactoryAbstract implements ServicesProviderAware {
+public class PostsCollectionAddedToEventAnnotationFacetFactory extends FacetFactoryAbstract implements ServicesInjectorAware {
 
-    private ServicesProvider servicesProvider;
+    private ServicesInjector servicesInjector;
 
     public PostsCollectionAddedToEventAnnotationFacetFactory() {
         super(FeatureType.COLLECTIONS_ONLY);
@@ -65,12 +67,14 @@ public class PostsCollectionAddedToEventAnnotationFacetFactory extends FacetFact
         // the collectionAddToFacet will end up as the underlying facet of the PostsCollectionAddedToEventFacetAnnotation
 
         final Class<? extends CollectionAddedToEvent<?,?>> changedEventType = annotation.value();
-        return new PostsCollectionAddedToEventFacetAnnotation(changedEventType, getterFacet, collectionAddToFacet, servicesProvider, holder);
+        return new PostsCollectionAddedToEventFacetAnnotation(changedEventType, getterFacet, collectionAddToFacet, servicesInjector, holder);
     }
 
+    // //////////////////////////////////////
+
     @Override
-    public void setServicesProvider(ServicesProvider servicesProvider) {
-        this.servicesProvider = servicesProvider;
+    public void setServicesInjector(ServicesInjector servicesInjector) {
+        this.servicesInjector = servicesInjector;
     }
 
 }

http://git-wip-us.apache.org/repos/asf/isis/blob/e1f19baa/core/metamodel/src/main/java/org/apache/isis/core/progmodel/facets/collections/event/PostsCollectionAddedToEventFacetAnnotation.java
----------------------------------------------------------------------
diff --git a/core/metamodel/src/main/java/org/apache/isis/core/progmodel/facets/collections/event/PostsCollectionAddedToEventFacetAnnotation.java b/core/metamodel/src/main/java/org/apache/isis/core/progmodel/facets/collections/event/PostsCollectionAddedToEventFacetAnnotation.java
index e566300..e093b44 100644
--- a/core/metamodel/src/main/java/org/apache/isis/core/progmodel/facets/collections/event/PostsCollectionAddedToEventFacetAnnotation.java
+++ b/core/metamodel/src/main/java/org/apache/isis/core/progmodel/facets/collections/event/PostsCollectionAddedToEventFacetAnnotation.java
@@ -19,8 +19,6 @@
 
 package org.apache.isis.core.progmodel.facets.collections.event;
 
-import java.lang.reflect.Field;
-import java.util.List;
 import java.util.Set;
 
 import com.google.common.collect.Lists;
@@ -30,7 +28,6 @@ import org.apache.isis.applib.Identifier;
 import org.apache.isis.applib.services.eventbus.CollectionAddedToEvent;
 import org.apache.isis.applib.services.eventbus.EventBusService;
 import org.apache.isis.core.metamodel.adapter.ObjectAdapter;
-import org.apache.isis.core.metamodel.adapter.ServicesProvider;
 import org.apache.isis.core.metamodel.adapter.util.AdapterUtils;
 import org.apache.isis.core.metamodel.facetapi.Facet;
 import org.apache.isis.core.metamodel.facetapi.FacetHolder;
@@ -38,13 +35,14 @@ import org.apache.isis.core.metamodel.facets.accessor.PropertyOrCollectionAccess
 import org.apache.isis.core.metamodel.facets.collections.event.PostsCollectionAddedToEventFacet;
 import org.apache.isis.core.metamodel.facets.collections.event.PostsCollectionAddedToEventFacetAbstract;
 import org.apache.isis.core.metamodel.facets.collections.modify.CollectionAddToFacet;
+import org.apache.isis.core.metamodel.runtimecontext.ServicesInjector;
 
 public class PostsCollectionAddedToEventFacetAnnotation 
         extends PostsCollectionAddedToEventFacetAbstract {
 
     private final PropertyOrCollectionAccessorFacet getterFacet;
 	private final CollectionAddToFacet collectionAddToFacet;
-	private final ServicesProvider servicesProvider;
+	private final ServicesInjector servicesInjector;
 
 	private EventBusService eventBusService;
 	private boolean searchedForEventBusService = false;
@@ -53,12 +51,12 @@ public class PostsCollectionAddedToEventFacetAnnotation
 			final Class<? extends CollectionAddedToEvent<?, ?>> eventType,
 			final PropertyOrCollectionAccessorFacet getterFacet,
 			final CollectionAddToFacet collectionAddToFacet,
-			final ServicesProvider servicesProvider, 
+		    final ServicesInjector servicesInjector,
 			final FacetHolder holder) {
 		super(eventType, holder);
         this.getterFacet = getterFacet;
 		this.collectionAddToFacet = collectionAddToFacet;
-		this.servicesProvider = servicesProvider;
+		this.servicesInjector = servicesInjector;
 	}
 
 	@Override
@@ -97,55 +95,23 @@ public class PostsCollectionAddedToEventFacetAnnotation
             final Identifier identifier,
 			final Object addedReference) {
 	    
-		final Object source = targetAdapter.getObject();
 		try {
 			final Class type = value();
-			final CollectionAddedToEvent<?, ?> event = newEvent(type, source, identifier, addedReference);
+            final Object source = AdapterUtils.unwrap(targetAdapter);
+			final CollectionAddedToEvent<?, ?> event = Util.newEvent(type, source, identifier, addedReference);
 			eventBusService.post(event);
 		} catch (Exception e) {
 			throw new FatalException(e);
 		}
 	}
 
-	static <S, T> CollectionAddedToEvent<S, T> newEvent(
-			final Class<? extends CollectionAddedToEvent<S, T>> type,
-			final S source, 
-			final Identifier identifier,
-			final T value)
-			throws InstantiationException, IllegalAccessException,
-			NoSuchFieldException {
-		final CollectionAddedToEvent<S, T> event = type.newInstance();
-
-		setField("source", event, source);
-		setField("identifier", event, identifier);
-		setField("value", event, value);
-		return event;
-	}
-
-	private static void setField(final String name,
-			final CollectionAddedToEvent<?, ?> event, final Object sourceValue)
-			throws NoSuchFieldException, IllegalAccessException {
-		final Field sourceField = CollectionAddedToEvent.class
-				.getDeclaredField(name);
-		sourceField.setAccessible(true);
-		sourceField.set(event, sourceValue);
-	}
-
-	private EventBusService getEventBusService() {
-		if (!searchedForEventBusService) {
-			final List<ObjectAdapter> serviceAdapters = servicesProvider
-					.getServices();
-			for (ObjectAdapter serviceAdapter : serviceAdapters) {
-				final Object service = serviceAdapter.getObject();
-				if (service instanceof EventBusService) {
-					eventBusService = (EventBusService) service;
-					break;
-				}
-			}
-		}
-		searchedForEventBusService = true;
-		return eventBusService;
-	}
+    private EventBusService getEventBusService() {
+        if (!searchedForEventBusService) {
+            eventBusService = this.servicesInjector.lookupService(EventBusService.class);
+        }
+        searchedForEventBusService = true;
+        return eventBusService;
+    }
 
 	// //////////////////////////////////////
 	// MultiTypedFacet

http://git-wip-us.apache.org/repos/asf/isis/blob/e1f19baa/core/metamodel/src/main/java/org/apache/isis/core/progmodel/facets/collections/event/PostsCollectionRemovedFromEventAnnotationFacetFactory.java
----------------------------------------------------------------------
diff --git a/core/metamodel/src/main/java/org/apache/isis/core/progmodel/facets/collections/event/PostsCollectionRemovedFromEventAnnotationFacetFactory.java b/core/metamodel/src/main/java/org/apache/isis/core/progmodel/facets/collections/event/PostsCollectionRemovedFromEventAnnotationFacetFactory.java
index abf039c..c8b8ffa 100644
--- a/core/metamodel/src/main/java/org/apache/isis/core/progmodel/facets/collections/event/PostsCollectionRemovedFromEventAnnotationFacetFactory.java
+++ b/core/metamodel/src/main/java/org/apache/isis/core/progmodel/facets/collections/event/PostsCollectionRemovedFromEventAnnotationFacetFactory.java
@@ -33,10 +33,12 @@ import org.apache.isis.core.metamodel.facets.FacetFactoryAbstract;
 import org.apache.isis.core.metamodel.facets.accessor.PropertyOrCollectionAccessorFacet;
 import org.apache.isis.core.metamodel.facets.collections.event.PostsCollectionRemovedFromEventFacet;
 import org.apache.isis.core.metamodel.facets.collections.modify.CollectionRemoveFromFacet;
+import org.apache.isis.core.metamodel.runtimecontext.ServicesInjector;
+import org.apache.isis.core.metamodel.runtimecontext.ServicesInjectorAware;
 
-public class PostsCollectionRemovedFromEventAnnotationFacetFactory extends FacetFactoryAbstract implements ServicesProviderAware {
+public class PostsCollectionRemovedFromEventAnnotationFacetFactory extends FacetFactoryAbstract implements ServicesInjectorAware {
 
-    private ServicesProvider servicesProvider;
+    private ServicesInjector servicesInjector;
 
     public PostsCollectionRemovedFromEventAnnotationFacetFactory() {
         super(FeatureType.COLLECTIONS_ONLY);
@@ -65,12 +67,14 @@ public class PostsCollectionRemovedFromEventAnnotationFacetFactory extends Facet
         // the collectionRemoveFromFacet will end up as the underlying facet of the PostsCollectionRemovedFromEventFacetAnnotation
 
         final Class<? extends CollectionRemovedFromEvent<?,?>> changedEventType = annotation.value();
-        return new PostsCollectionRemovedFromEventFacetAnnotation(changedEventType, getterFacet, collectionRemoveFromFacet, servicesProvider, holder);
+        return new PostsCollectionRemovedFromEventFacetAnnotation(changedEventType, getterFacet, collectionRemoveFromFacet, servicesInjector, holder);
     }
 
+    // //////////////////////////////////////
+
     @Override
-    public void setServicesProvider(ServicesProvider servicesProvider) {
-        this.servicesProvider = servicesProvider;
+    public void setServicesInjector(ServicesInjector servicesInjector) {
+        this.servicesInjector = servicesInjector;
     }
 
 }

http://git-wip-us.apache.org/repos/asf/isis/blob/e1f19baa/core/metamodel/src/main/java/org/apache/isis/core/progmodel/facets/collections/event/PostsCollectionRemovedFromEventFacetAnnotation.java
----------------------------------------------------------------------
diff --git a/core/metamodel/src/main/java/org/apache/isis/core/progmodel/facets/collections/event/PostsCollectionRemovedFromEventFacetAnnotation.java b/core/metamodel/src/main/java/org/apache/isis/core/progmodel/facets/collections/event/PostsCollectionRemovedFromEventFacetAnnotation.java
index 98524cf..0cd48c9 100644
--- a/core/metamodel/src/main/java/org/apache/isis/core/progmodel/facets/collections/event/PostsCollectionRemovedFromEventFacetAnnotation.java
+++ b/core/metamodel/src/main/java/org/apache/isis/core/progmodel/facets/collections/event/PostsCollectionRemovedFromEventFacetAnnotation.java
@@ -20,6 +20,7 @@
 package org.apache.isis.core.progmodel.facets.collections.event;
 
 import java.lang.reflect.Field;
+import java.lang.reflect.InvocationTargetException;
 import java.util.Collection;
 import java.util.List;
 
@@ -38,13 +39,14 @@ import org.apache.isis.core.metamodel.facets.accessor.PropertyOrCollectionAccess
 import org.apache.isis.core.metamodel.facets.collections.event.PostsCollectionRemovedFromEventFacet;
 import org.apache.isis.core.metamodel.facets.collections.event.PostsCollectionRemovedFromEventFacetAbstract;
 import org.apache.isis.core.metamodel.facets.collections.modify.CollectionRemoveFromFacet;
+import org.apache.isis.core.metamodel.runtimecontext.ServicesInjector;
 
 public class PostsCollectionRemovedFromEventFacetAnnotation extends
 		PostsCollectionRemovedFromEventFacetAbstract {
 
 	private final PropertyOrCollectionAccessorFacet getterFacet;
 	private final CollectionRemoveFromFacet collectionRemoveFromFacet;
-	private final ServicesProvider servicesProvider;
+    private final ServicesInjector servicesInjector;
 
 	private EventBusService eventBusService;
 	private boolean searchedForEventBusService = false;
@@ -53,11 +55,12 @@ public class PostsCollectionRemovedFromEventFacetAnnotation extends
 			final Class<? extends CollectionRemovedFromEvent<?, ?>> eventType,
 			final PropertyOrCollectionAccessorFacet getterFacet,
 			final CollectionRemoveFromFacet collectionRemoveFromFacet,
-			final ServicesProvider servicesProvider, final FacetHolder holder) {
+            final ServicesInjector servicesInjector,
+			final FacetHolder holder) {
 		super(eventType, holder);
 		this.getterFacet = getterFacet;
 		this.collectionRemoveFromFacet = collectionRemoveFromFacet;
-		this.servicesProvider = servicesProvider;
+        this.servicesInjector = servicesInjector;
 	}
 
 	@Override
@@ -96,54 +99,23 @@ public class PostsCollectionRemovedFromEventFacetAnnotation extends
 	private void postEvent(final ObjectAdapter targetAdapter,
 			final Identifier identifier, final Object removedReference) {
 
-		final Object source = targetAdapter.getObject();
 		try {
 			final Class type = value();
-			final CollectionRemovedFromEvent<?, ?> event = newEvent(type, source,
-					identifier, removedReference);
+			final Object source = AdapterUtils.unwrap(targetAdapter);
+			final CollectionRemovedFromEvent<?, ?> event = Util.newEvent(type, source, identifier, removedReference);
 			eventBusService.post(event);
 		} catch (Exception e) {
 			throw new FatalException(e);
 		}
 	}
 
-	static <S, T> CollectionRemovedFromEvent<S, T> newEvent(
-			final Class<? extends CollectionRemovedFromEvent<S, T>> type,
-			final S source, final Identifier identifier, final T value)
-			throws InstantiationException, IllegalAccessException,
-			NoSuchFieldException {
-		final CollectionRemovedFromEvent<S, T> event = type.newInstance();
-
-		setField("source", event, source);
-		setField("identifier", event, identifier);
-		setField("value", event, value);
-		return event;
-	}
-
-	private static void setField(final String name,
-			final CollectionRemovedFromEvent<?, ?> event, final Object sourceValue)
-			throws NoSuchFieldException, IllegalAccessException {
-		final Field sourceField = CollectionRemovedFromEvent.class
-				.getDeclaredField(name);
-		sourceField.setAccessible(true);
-		sourceField.set(event, sourceValue);
-	}
-
-	private EventBusService getEventBusService() {
-		if (!searchedForEventBusService) {
-			final List<ObjectAdapter> serviceAdapters = servicesProvider
-					.getServices();
-			for (ObjectAdapter serviceAdapter : serviceAdapters) {
-				final Object service = serviceAdapter.getObject();
-				if (service instanceof EventBusService) {
-					eventBusService = (EventBusService) service;
-					break;
-				}
-			}
-		}
-		searchedForEventBusService = true;
-		return eventBusService;
-	}
+    private EventBusService getEventBusService() {
+        if (!searchedForEventBusService) {
+            eventBusService = this.servicesInjector.lookupService(EventBusService.class);
+        }
+        searchedForEventBusService = true;
+        return eventBusService;
+    }
 
 	// //////////////////////////////////////
 	// MultiTypedFacet

http://git-wip-us.apache.org/repos/asf/isis/blob/e1f19baa/core/metamodel/src/main/java/org/apache/isis/core/progmodel/facets/properties/event/PostsPropertyChangedEventAnnotationFacetFactory.java
----------------------------------------------------------------------
diff --git a/core/metamodel/src/main/java/org/apache/isis/core/progmodel/facets/properties/event/PostsPropertyChangedEventAnnotationFacetFactory.java b/core/metamodel/src/main/java/org/apache/isis/core/progmodel/facets/properties/event/PostsPropertyChangedEventAnnotationFacetFactory.java
index 030a5b3..89bd745 100644
--- a/core/metamodel/src/main/java/org/apache/isis/core/progmodel/facets/properties/event/PostsPropertyChangedEventAnnotationFacetFactory.java
+++ b/core/metamodel/src/main/java/org/apache/isis/core/progmodel/facets/properties/event/PostsPropertyChangedEventAnnotationFacetFactory.java
@@ -39,6 +39,8 @@ import org.apache.isis.core.metamodel.facets.collections.sortedby.SortedByFacet;
 import org.apache.isis.core.metamodel.facets.properties.event.PostsPropertyChangedEventFacet;
 import org.apache.isis.core.metamodel.facets.properties.modify.PropertyClearFacet;
 import org.apache.isis.core.metamodel.facets.properties.modify.PropertySetterFacet;
+import org.apache.isis.core.metamodel.runtimecontext.ServicesInjector;
+import org.apache.isis.core.metamodel.runtimecontext.ServicesInjectorAware;
 import org.apache.isis.core.metamodel.spec.ObjectSpecification;
 import org.apache.isis.core.metamodel.spec.feature.Contributed;
 import org.apache.isis.core.metamodel.spec.feature.OneToManyAssociation;
@@ -47,9 +49,9 @@ import org.apache.isis.core.metamodel.specloader.validator.MetaModelValidatorVis
 import org.apache.isis.core.metamodel.specloader.validator.MetaModelValidatorVisiting.Visitor;
 import org.apache.isis.core.metamodel.specloader.validator.ValidationFailures;
 
-public class PostsPropertyChangedEventAnnotationFacetFactory extends FacetFactoryAbstract implements ServicesProviderAware, MetaModelValidatorRefiner {
+public class PostsPropertyChangedEventAnnotationFacetFactory extends FacetFactoryAbstract implements ServicesInjectorAware, MetaModelValidatorRefiner {
 
-    private ServicesProvider servicesProvider;
+    private ServicesInjector servicesInjector;
 
     public PostsPropertyChangedEventAnnotationFacetFactory() {
         super(FeatureType.PROPERTIES_ONLY);
@@ -89,14 +91,11 @@ public class PostsPropertyChangedEventAnnotationFacetFactory extends FacetFactor
         }
         
         final Class<? extends PropertyChangedEvent<?, ?>> changedEventType = annotation.value();
-        return new PostsPropertyChangedEventFacetAnnotation(changedEventType, getterFacet, setterFacet, clearFacet, servicesProvider, holder);
-    }
-
-    @Override
-    public void setServicesProvider(ServicesProvider servicesProvider) {
-        this.servicesProvider = servicesProvider;
+        return new PostsPropertyChangedEventFacetAnnotation(changedEventType, getterFacet, setterFacet, clearFacet, servicesInjector, holder);
     }
 
+    // //////////////////////////////////////
+    
     @Override
     public void refineMetaModelValidator(MetaModelValidatorComposite metaModelValidator, IsisConfiguration configuration) {
         metaModelValidator.add(new MetaModelValidatorVisiting(newValidatorVisitor()));
@@ -122,4 +121,12 @@ public class PostsPropertyChangedEventAnnotationFacetFactory extends FacetFactor
         };
     }
 
+    // //////////////////////////////////////
+
+    @Override
+    public void setServicesInjector(ServicesInjector servicesInjector) {
+        this.servicesInjector = servicesInjector;
+    }
+
+    
 }

http://git-wip-us.apache.org/repos/asf/isis/blob/e1f19baa/core/metamodel/src/main/java/org/apache/isis/core/progmodel/facets/properties/event/PostsPropertyChangedEventFacetAnnotation.java
----------------------------------------------------------------------
diff --git a/core/metamodel/src/main/java/org/apache/isis/core/progmodel/facets/properties/event/PostsPropertyChangedEventFacetAnnotation.java b/core/metamodel/src/main/java/org/apache/isis/core/progmodel/facets/properties/event/PostsPropertyChangedEventFacetAnnotation.java
index 017cf48..db67de1 100644
--- a/core/metamodel/src/main/java/org/apache/isis/core/progmodel/facets/properties/event/PostsPropertyChangedEventFacetAnnotation.java
+++ b/core/metamodel/src/main/java/org/apache/isis/core/progmodel/facets/properties/event/PostsPropertyChangedEventFacetAnnotation.java
@@ -19,7 +19,9 @@
 
 package org.apache.isis.core.progmodel.facets.properties.event;
 
+import java.lang.reflect.Constructor;
 import java.lang.reflect.Field;
+import java.lang.reflect.InvocationTargetException;
 import java.util.List;
 
 import com.google.common.base.Objects;
@@ -31,6 +33,7 @@ import org.apache.isis.applib.services.eventbus.EventBusService;
 import org.apache.isis.applib.services.eventbus.PropertyChangedEvent;
 import org.apache.isis.core.metamodel.adapter.ObjectAdapter;
 import org.apache.isis.core.metamodel.adapter.ServicesProvider;
+import org.apache.isis.core.metamodel.adapter.util.AdapterUtils;
 import org.apache.isis.core.metamodel.facetapi.Facet;
 import org.apache.isis.core.metamodel.facetapi.FacetHolder;
 import org.apache.isis.core.metamodel.facets.accessor.PropertyOrCollectionAccessorFacet;
@@ -38,13 +41,14 @@ import org.apache.isis.core.metamodel.facets.properties.event.PostsPropertyChang
 import org.apache.isis.core.metamodel.facets.properties.event.PostsPropertyChangedEventFacetAbstract;
 import org.apache.isis.core.metamodel.facets.properties.modify.PropertyClearFacet;
 import org.apache.isis.core.metamodel.facets.properties.modify.PropertySetterFacet;
+import org.apache.isis.core.metamodel.runtimecontext.ServicesInjector;
 
 public class PostsPropertyChangedEventFacetAnnotation extends PostsPropertyChangedEventFacetAbstract {
 
     private final PropertyOrCollectionAccessorFacet getterFacet;
     private final PropertySetterFacet setterFacet;
     private final PropertyClearFacet clearFacet;
-    private final ServicesProvider servicesProvider;
+    private final ServicesInjector servicesInjector;
     
     private EventBusService eventBusService;
     private boolean searchedForEventBusService = false;
@@ -54,13 +58,13 @@ public class PostsPropertyChangedEventFacetAnnotation extends PostsPropertyChang
             final PropertyOrCollectionAccessorFacet getterFacet, 
             final PropertySetterFacet setterFacet, 
             final PropertyClearFacet clearFacet, 
-            final ServicesProvider servicesProvider, 
+            final ServicesInjector servicesInjector,
             final FacetHolder holder) {
         super(eventType, holder);
         this.getterFacet = getterFacet;
         this.setterFacet = setterFacet;
         this.clearFacet = clearFacet;
-        this.servicesProvider = servicesProvider;
+        this.servicesInjector = servicesInjector;
     }
 
     @Override
@@ -110,10 +114,10 @@ public class PostsPropertyChangedEventFacetAnnotation extends PostsPropertyChang
             // do nothing.
             return;
         }
-        final Object source = targetAdapter.getObject();
         try {
             final Class type = value();
-            final PropertyChangedEvent<?, ?> event = newEvent(type, source, identifier, oldValue, newValue);
+            final Object source = ObjectAdapter.Util.unwrap(targetAdapter);
+            final PropertyChangedEvent<?, ?> event = Util.newEvent(type, source, identifier, oldValue, newValue);
             
             eventBusService.post(event);
         } catch (Exception e) {
@@ -121,38 +125,10 @@ public class PostsPropertyChangedEventFacetAnnotation extends PostsPropertyChang
         }
     }
 
-    static <S,T> PropertyChangedEvent<S,T> newEvent(
-            final Class<? extends PropertyChangedEvent<S, T>> type, 
-            final S source, 
-            final Identifier identifier,
-            final T oldValue, 
-            final T newValue) throws InstantiationException, IllegalAccessException, NoSuchFieldException {
-        final PropertyChangedEvent<S, T> event = type.newInstance();
-        
-        setField("source", event, source);
-        setField("identifier", event, identifier);
-        setField("oldValue", event, oldValue);
-        setField("newValue", event, newValue);
-        return event;
-    }
-
-    private static void setField(final String name, final PropertyChangedEvent<?, ?> event, final Object sourceValue) throws NoSuchFieldException, IllegalAccessException {
-        final Field sourceField = PropertyChangedEvent.class.getDeclaredField(name);
-        sourceField.setAccessible(true);
-        sourceField.set(event, sourceValue);
-    }
-    
     private EventBusService getEventBusService() {
-        if(!searchedForEventBusService) {
-            final List<ObjectAdapter> serviceAdapters = servicesProvider.getServices();
-            for (ObjectAdapter serviceAdapter : serviceAdapters) {
-                final Object service = serviceAdapter.getObject();
-                if(service instanceof EventBusService) {
-                    eventBusService = (EventBusService) service;
-                    break;
-                }
-            }
-        } 
+        if (!searchedForEventBusService) {
+            eventBusService = this.servicesInjector.lookupService(EventBusService.class);
+        }
         searchedForEventBusService = true;
         return eventBusService;
     }


[15/16] ISIS-550: refactored DomainObjectInvocationHandler and ImperativeFacets

Posted by da...@apache.org.
http://git-wip-us.apache.org/repos/asf/isis/blob/5f15fa74/core/metamodel/src/main/java/org/apache/isis/core/progmodel/facets/object/dirty/method/ClearDirtyObjectFacetViaMethod.java
----------------------------------------------------------------------
diff --git a/core/metamodel/src/main/java/org/apache/isis/core/progmodel/facets/object/dirty/method/ClearDirtyObjectFacetViaMethod.java b/core/metamodel/src/main/java/org/apache/isis/core/progmodel/facets/object/dirty/method/ClearDirtyObjectFacetViaMethod.java
index 3f97714..1e0172c 100644
--- a/core/metamodel/src/main/java/org/apache/isis/core/progmodel/facets/object/dirty/method/ClearDirtyObjectFacetViaMethod.java
+++ b/core/metamodel/src/main/java/org/apache/isis/core/progmodel/facets/object/dirty/method/ClearDirtyObjectFacetViaMethod.java
@@ -27,6 +27,7 @@ import org.apache.isis.core.commons.lang.MethodExtensions;
 import org.apache.isis.core.metamodel.adapter.ObjectAdapter;
 import org.apache.isis.core.metamodel.facetapi.FacetHolder;
 import org.apache.isis.core.metamodel.facets.ImperativeFacet;
+import org.apache.isis.core.metamodel.facets.ImperativeFacet.Intent;
 import org.apache.isis.core.progmodel.facets.object.dirty.ClearDirtyObjectFacetAbstract;
 
 public class ClearDirtyObjectFacetViaMethod extends ClearDirtyObjectFacetAbstract implements ImperativeFacet {
@@ -48,6 +49,11 @@ public class ClearDirtyObjectFacetViaMethod extends ClearDirtyObjectFacetAbstrac
     }
 
     @Override
+    public Intent getIntent(final Method method) {
+        return Intent.LIFECYCLE;
+    }
+
+    @Override
     public boolean impliesResolve() {
         return false;
     }

http://git-wip-us.apache.org/repos/asf/isis/blob/5f15fa74/core/metamodel/src/main/java/org/apache/isis/core/progmodel/facets/object/dirty/method/IsDirtyObjectFacetViaMethod.java
----------------------------------------------------------------------
diff --git a/core/metamodel/src/main/java/org/apache/isis/core/progmodel/facets/object/dirty/method/IsDirtyObjectFacetViaMethod.java b/core/metamodel/src/main/java/org/apache/isis/core/progmodel/facets/object/dirty/method/IsDirtyObjectFacetViaMethod.java
index 355cfeb..c8c5e32 100644
--- a/core/metamodel/src/main/java/org/apache/isis/core/progmodel/facets/object/dirty/method/IsDirtyObjectFacetViaMethod.java
+++ b/core/metamodel/src/main/java/org/apache/isis/core/progmodel/facets/object/dirty/method/IsDirtyObjectFacetViaMethod.java
@@ -27,6 +27,7 @@ import org.apache.isis.core.commons.lang.MethodExtensions;
 import org.apache.isis.core.metamodel.adapter.ObjectAdapter;
 import org.apache.isis.core.metamodel.facetapi.FacetHolder;
 import org.apache.isis.core.metamodel.facets.ImperativeFacet;
+import org.apache.isis.core.metamodel.facets.ImperativeFacet.Intent;
 import org.apache.isis.core.progmodel.facets.object.dirty.IsDirtyObjectFacetAbstract;
 
 public class IsDirtyObjectFacetViaMethod extends IsDirtyObjectFacetAbstract implements ImperativeFacet {
@@ -48,6 +49,11 @@ public class IsDirtyObjectFacetViaMethod extends IsDirtyObjectFacetAbstract impl
     }
 
     @Override
+    public Intent getIntent(final Method method) {
+        return Intent.LIFECYCLE;
+    }
+
+    @Override
     public boolean impliesResolve() {
         return false;
     }

http://git-wip-us.apache.org/repos/asf/isis/blob/5f15fa74/core/metamodel/src/main/java/org/apache/isis/core/progmodel/facets/object/dirty/method/MarkDirtyObjectFacetViaMethod.java
----------------------------------------------------------------------
diff --git a/core/metamodel/src/main/java/org/apache/isis/core/progmodel/facets/object/dirty/method/MarkDirtyObjectFacetViaMethod.java b/core/metamodel/src/main/java/org/apache/isis/core/progmodel/facets/object/dirty/method/MarkDirtyObjectFacetViaMethod.java
index f1ee36e..21d24bd 100644
--- a/core/metamodel/src/main/java/org/apache/isis/core/progmodel/facets/object/dirty/method/MarkDirtyObjectFacetViaMethod.java
+++ b/core/metamodel/src/main/java/org/apache/isis/core/progmodel/facets/object/dirty/method/MarkDirtyObjectFacetViaMethod.java
@@ -27,6 +27,7 @@ import org.apache.isis.core.commons.lang.MethodExtensions;
 import org.apache.isis.core.metamodel.adapter.ObjectAdapter;
 import org.apache.isis.core.metamodel.facetapi.FacetHolder;
 import org.apache.isis.core.metamodel.facets.ImperativeFacet;
+import org.apache.isis.core.metamodel.facets.ImperativeFacet.Intent;
 import org.apache.isis.core.progmodel.facets.object.dirty.MarkDirtyObjectFacetAbstract;
 
 public class MarkDirtyObjectFacetViaMethod extends MarkDirtyObjectFacetAbstract implements ImperativeFacet {
@@ -44,6 +45,11 @@ public class MarkDirtyObjectFacetViaMethod extends MarkDirtyObjectFacetAbstract
     }
 
     @Override
+    public Intent getIntent(final Method method) {
+        return Intent.LIFECYCLE;
+    }
+
+    @Override
     public boolean impliesResolve() {
         return false;
     }

http://git-wip-us.apache.org/repos/asf/isis/blob/5f15fa74/core/metamodel/src/main/java/org/apache/isis/core/progmodel/facets/object/disabled/method/DisabledObjectFacetViaDisabledMethod.java
----------------------------------------------------------------------
diff --git a/core/metamodel/src/main/java/org/apache/isis/core/progmodel/facets/object/disabled/method/DisabledObjectFacetViaDisabledMethod.java b/core/metamodel/src/main/java/org/apache/isis/core/progmodel/facets/object/disabled/method/DisabledObjectFacetViaDisabledMethod.java
index d11f3fc..224ae14 100755
--- a/core/metamodel/src/main/java/org/apache/isis/core/progmodel/facets/object/disabled/method/DisabledObjectFacetViaDisabledMethod.java
+++ b/core/metamodel/src/main/java/org/apache/isis/core/progmodel/facets/object/disabled/method/DisabledObjectFacetViaDisabledMethod.java
@@ -30,6 +30,7 @@ import org.apache.isis.core.metamodel.adapter.util.AdapterInvokeUtils;
 import org.apache.isis.core.metamodel.facetapi.FacetHolder;
 import org.apache.isis.core.metamodel.facetapi.FacetUtil;
 import org.apache.isis.core.metamodel.facets.ImperativeFacet;
+import org.apache.isis.core.metamodel.facets.ImperativeFacet.Intent;
 import org.apache.isis.core.progmodel.facets.object.disabled.DisabledObjectFacetAbstract;
 
 public class DisabledObjectFacetViaDisabledMethod extends DisabledObjectFacetAbstract implements ImperativeFacet {
@@ -47,6 +48,11 @@ public class DisabledObjectFacetViaDisabledMethod extends DisabledObjectFacetAbs
     }
 
     @Override
+    public Intent getIntent(final Method method) {
+        return Intent.CHECK_IF_DISABLED;
+    }
+
+    @Override
     public boolean impliesResolve() {
         return true;
     }

http://git-wip-us.apache.org/repos/asf/isis/blob/5f15fa74/core/metamodel/src/main/java/org/apache/isis/core/progmodel/facets/object/title/TitleFacetViaTitleMethod.java
----------------------------------------------------------------------
diff --git a/core/metamodel/src/main/java/org/apache/isis/core/progmodel/facets/object/title/TitleFacetViaTitleMethod.java b/core/metamodel/src/main/java/org/apache/isis/core/progmodel/facets/object/title/TitleFacetViaTitleMethod.java
index ed535b1..f03dc5d 100644
--- a/core/metamodel/src/main/java/org/apache/isis/core/progmodel/facets/object/title/TitleFacetViaTitleMethod.java
+++ b/core/metamodel/src/main/java/org/apache/isis/core/progmodel/facets/object/title/TitleFacetViaTitleMethod.java
@@ -31,6 +31,7 @@ import org.apache.isis.core.metamodel.adapter.ObjectAdapter;
 import org.apache.isis.core.metamodel.adapter.util.AdapterInvokeUtils;
 import org.apache.isis.core.metamodel.facetapi.FacetHolder;
 import org.apache.isis.core.metamodel.facets.ImperativeFacet;
+import org.apache.isis.core.metamodel.facets.ImperativeFacet.Intent;
 import org.apache.isis.core.metamodel.facets.object.title.TitleFacetAbstract;
 
 public class TitleFacetViaTitleMethod extends TitleFacetAbstract implements ImperativeFacet {
@@ -53,6 +54,11 @@ public class TitleFacetViaTitleMethod extends TitleFacetAbstract implements Impe
     }
 
     @Override
+    public Intent getIntent(final Method method) {
+        return Intent.UI_HINT;
+    }
+
+    @Override
     public boolean impliesResolve() {
         return true;
     }

http://git-wip-us.apache.org/repos/asf/isis/blob/5f15fa74/core/metamodel/src/main/java/org/apache/isis/core/progmodel/facets/object/title/TitleFacetViaToStringMethod.java
----------------------------------------------------------------------
diff --git a/core/metamodel/src/main/java/org/apache/isis/core/progmodel/facets/object/title/TitleFacetViaToStringMethod.java b/core/metamodel/src/main/java/org/apache/isis/core/progmodel/facets/object/title/TitleFacetViaToStringMethod.java
index e73c281..3fb7bbd 100644
--- a/core/metamodel/src/main/java/org/apache/isis/core/progmodel/facets/object/title/TitleFacetViaToStringMethod.java
+++ b/core/metamodel/src/main/java/org/apache/isis/core/progmodel/facets/object/title/TitleFacetViaToStringMethod.java
@@ -27,6 +27,7 @@ import org.apache.isis.applib.profiles.Localization;
 import org.apache.isis.core.metamodel.adapter.ObjectAdapter;
 import org.apache.isis.core.metamodel.facetapi.FacetHolder;
 import org.apache.isis.core.metamodel.facets.ImperativeFacet;
+import org.apache.isis.core.metamodel.facets.ImperativeFacet.Intent;
 import org.apache.isis.core.metamodel.facets.object.title.TitleFacetAbstract;
 
 public class TitleFacetViaToStringMethod extends TitleFacetAbstract implements ImperativeFacet {
@@ -48,6 +49,11 @@ public class TitleFacetViaToStringMethod extends TitleFacetAbstract implements I
     }
 
     @Override
+    public Intent getIntent(final Method method) {
+        return Intent.UI_HINT;
+    }
+
+    @Override
     public boolean impliesResolve() {
         return true;
     }

http://git-wip-us.apache.org/repos/asf/isis/blob/5f15fa74/core/metamodel/src/main/java/org/apache/isis/core/progmodel/facets/object/validate/method/ValidateObjectFacetViaValidateMethod.java
----------------------------------------------------------------------
diff --git a/core/metamodel/src/main/java/org/apache/isis/core/progmodel/facets/object/validate/method/ValidateObjectFacetViaValidateMethod.java b/core/metamodel/src/main/java/org/apache/isis/core/progmodel/facets/object/validate/method/ValidateObjectFacetViaValidateMethod.java
index 65d7dbf..1ddcda3 100644
--- a/core/metamodel/src/main/java/org/apache/isis/core/progmodel/facets/object/validate/method/ValidateObjectFacetViaValidateMethod.java
+++ b/core/metamodel/src/main/java/org/apache/isis/core/progmodel/facets/object/validate/method/ValidateObjectFacetViaValidateMethod.java
@@ -27,6 +27,7 @@ import org.apache.isis.core.metamodel.adapter.ObjectAdapter;
 import org.apache.isis.core.metamodel.adapter.util.AdapterInvokeUtils;
 import org.apache.isis.core.metamodel.facetapi.FacetHolder;
 import org.apache.isis.core.metamodel.facets.ImperativeFacet;
+import org.apache.isis.core.metamodel.facets.ImperativeFacet.Intent;
 import org.apache.isis.core.progmodel.facets.object.validate.ValidateObjectFacetAbstract;
 
 public class ValidateObjectFacetViaValidateMethod extends ValidateObjectFacetAbstract implements ImperativeFacet {
@@ -44,6 +45,11 @@ public class ValidateObjectFacetViaValidateMethod extends ValidateObjectFacetAbs
     }
 
     @Override
+    public Intent getIntent(final Method method) {
+        return Intent.CHECK_IF_VALID;
+    }
+
+    @Override
     public boolean impliesResolve() {
         return true;
     }

http://git-wip-us.apache.org/repos/asf/isis/blob/5f15fa74/core/metamodel/src/main/java/org/apache/isis/core/progmodel/facets/param/autocomplete/ActionParameterAutoCompleteFacetViaMethod.java
----------------------------------------------------------------------
diff --git a/core/metamodel/src/main/java/org/apache/isis/core/progmodel/facets/param/autocomplete/ActionParameterAutoCompleteFacetViaMethod.java b/core/metamodel/src/main/java/org/apache/isis/core/progmodel/facets/param/autocomplete/ActionParameterAutoCompleteFacetViaMethod.java
index 2217227..34ad250 100644
--- a/core/metamodel/src/main/java/org/apache/isis/core/progmodel/facets/param/autocomplete/ActionParameterAutoCompleteFacetViaMethod.java
+++ b/core/metamodel/src/main/java/org/apache/isis/core/progmodel/facets/param/autocomplete/ActionParameterAutoCompleteFacetViaMethod.java
@@ -29,6 +29,7 @@ import org.apache.isis.core.metamodel.adapter.mgr.AdapterManager;
 import org.apache.isis.core.metamodel.adapter.util.AdapterInvokeUtils;
 import org.apache.isis.core.metamodel.facetapi.FacetHolder;
 import org.apache.isis.core.metamodel.facets.ImperativeFacet;
+import org.apache.isis.core.metamodel.facets.ImperativeFacet.Intent;
 import org.apache.isis.core.metamodel.spec.ObjectSpecification;
 import org.apache.isis.core.metamodel.spec.SpecificationLoader;
 import org.apache.isis.core.progmodel.facets.CollectionUtils;
@@ -56,6 +57,11 @@ public class ActionParameterAutoCompleteFacetViaMethod extends ActionParameterAu
     }
     
     @Override
+    public Intent getIntent(final Method method) {
+        return Intent.CHOICES_OR_AUTOCOMPLETE;
+    }
+
+    @Override
     public int getMinLength() {
         return minLength;
     }

http://git-wip-us.apache.org/repos/asf/isis/blob/5f15fa74/core/metamodel/src/main/java/org/apache/isis/core/progmodel/facets/param/choices/method/ActionChoicesFacetViaMethod.java
----------------------------------------------------------------------
diff --git a/core/metamodel/src/main/java/org/apache/isis/core/progmodel/facets/param/choices/method/ActionChoicesFacetViaMethod.java b/core/metamodel/src/main/java/org/apache/isis/core/progmodel/facets/param/choices/method/ActionChoicesFacetViaMethod.java
index 569a35b..628dca3 100644
--- a/core/metamodel/src/main/java/org/apache/isis/core/progmodel/facets/param/choices/method/ActionChoicesFacetViaMethod.java
+++ b/core/metamodel/src/main/java/org/apache/isis/core/progmodel/facets/param/choices/method/ActionChoicesFacetViaMethod.java
@@ -60,6 +60,11 @@ public class ActionChoicesFacetViaMethod extends ActionChoicesFacetAbstract impl
     }
 
     @Override
+    public Intent getIntent(final Method method) {
+        return Intent.CHOICES_OR_AUTOCOMPLETE;
+    }
+
+    @Override
     public boolean impliesResolve() {
         return true;
     }

http://git-wip-us.apache.org/repos/asf/isis/blob/5f15fa74/core/metamodel/src/main/java/org/apache/isis/core/progmodel/facets/param/choices/methodnum/ActionParameterChoicesFacetViaMethod.java
----------------------------------------------------------------------
diff --git a/core/metamodel/src/main/java/org/apache/isis/core/progmodel/facets/param/choices/methodnum/ActionParameterChoicesFacetViaMethod.java b/core/metamodel/src/main/java/org/apache/isis/core/progmodel/facets/param/choices/methodnum/ActionParameterChoicesFacetViaMethod.java
index 068c20f..3024ad4 100644
--- a/core/metamodel/src/main/java/org/apache/isis/core/progmodel/facets/param/choices/methodnum/ActionParameterChoicesFacetViaMethod.java
+++ b/core/metamodel/src/main/java/org/apache/isis/core/progmodel/facets/param/choices/methodnum/ActionParameterChoicesFacetViaMethod.java
@@ -29,6 +29,7 @@ import org.apache.isis.core.metamodel.adapter.mgr.AdapterManager;
 import org.apache.isis.core.metamodel.adapter.util.AdapterInvokeUtils;
 import org.apache.isis.core.metamodel.facetapi.FacetHolder;
 import org.apache.isis.core.metamodel.facets.ImperativeFacet;
+import org.apache.isis.core.metamodel.facets.ImperativeFacet.Intent;
 import org.apache.isis.core.metamodel.spec.ObjectSpecification;
 import org.apache.isis.core.metamodel.spec.SpecificationLoader;
 import org.apache.isis.core.progmodel.facets.CollectionUtils;
@@ -55,6 +56,11 @@ public class ActionParameterChoicesFacetViaMethod extends ActionParameterChoices
     }
 
     @Override
+    public Intent getIntent(final Method method) {
+        return Intent.CHOICES_OR_AUTOCOMPLETE;
+    }
+
+    @Override
     public boolean impliesResolve() {
         return true;
     }

http://git-wip-us.apache.org/repos/asf/isis/blob/5f15fa74/core/metamodel/src/main/java/org/apache/isis/core/progmodel/facets/param/defaults/methodnum/ActionParameterDefaultsFacetViaMethod.java
----------------------------------------------------------------------
diff --git a/core/metamodel/src/main/java/org/apache/isis/core/progmodel/facets/param/defaults/methodnum/ActionParameterDefaultsFacetViaMethod.java b/core/metamodel/src/main/java/org/apache/isis/core/progmodel/facets/param/defaults/methodnum/ActionParameterDefaultsFacetViaMethod.java
index 6832806..0f573eb 100644
--- a/core/metamodel/src/main/java/org/apache/isis/core/progmodel/facets/param/defaults/methodnum/ActionParameterDefaultsFacetViaMethod.java
+++ b/core/metamodel/src/main/java/org/apache/isis/core/progmodel/facets/param/defaults/methodnum/ActionParameterDefaultsFacetViaMethod.java
@@ -28,6 +28,7 @@ import org.apache.isis.core.metamodel.adapter.mgr.AdapterManager;
 import org.apache.isis.core.metamodel.adapter.util.AdapterInvokeUtils;
 import org.apache.isis.core.metamodel.facetapi.FacetHolder;
 import org.apache.isis.core.metamodel.facets.ImperativeFacet;
+import org.apache.isis.core.metamodel.facets.ImperativeFacet.Intent;
 import org.apache.isis.core.progmodel.facets.param.defaults.ActionParameterDefaultsFacetAbstract;
 
 public class ActionParameterDefaultsFacetViaMethod extends ActionParameterDefaultsFacetAbstract implements ImperativeFacet {
@@ -51,6 +52,11 @@ public class ActionParameterDefaultsFacetViaMethod extends ActionParameterDefaul
     }
 
     @Override
+    public Intent getIntent(final Method method) {
+        return Intent.DEFAULTS;
+    }
+
+    @Override
     public boolean impliesResolve() {
         return true;
     }

http://git-wip-us.apache.org/repos/asf/isis/blob/5f15fa74/core/metamodel/src/main/java/org/apache/isis/core/progmodel/facets/properties/accessor/PropertyAccessorFacetViaAccessor.java
----------------------------------------------------------------------
diff --git a/core/metamodel/src/main/java/org/apache/isis/core/progmodel/facets/properties/accessor/PropertyAccessorFacetViaAccessor.java b/core/metamodel/src/main/java/org/apache/isis/core/progmodel/facets/properties/accessor/PropertyAccessorFacetViaAccessor.java
index 6b7002f..2fc316a 100644
--- a/core/metamodel/src/main/java/org/apache/isis/core/progmodel/facets/properties/accessor/PropertyAccessorFacetViaAccessor.java
+++ b/core/metamodel/src/main/java/org/apache/isis/core/progmodel/facets/properties/accessor/PropertyAccessorFacetViaAccessor.java
@@ -28,6 +28,7 @@ import org.apache.isis.core.metamodel.adapter.ObjectAdapter;
 import org.apache.isis.core.metamodel.adapter.util.AdapterInvokeUtils;
 import org.apache.isis.core.metamodel.facetapi.FacetHolder;
 import org.apache.isis.core.metamodel.facets.ImperativeFacet;
+import org.apache.isis.core.metamodel.facets.ImperativeFacet.Intent;
 import org.apache.isis.core.metamodel.facets.accessor.PropertyOrCollectionAccessorFacetAbstract;
 
 public class PropertyAccessorFacetViaAccessor extends PropertyOrCollectionAccessorFacetAbstract implements ImperativeFacet {
@@ -49,6 +50,11 @@ public class PropertyAccessorFacetViaAccessor extends PropertyOrCollectionAccess
     }
 
     @Override
+    public Intent getIntent(final Method method) {
+        return Intent.ACCESSOR;
+    }
+
+    @Override
     public boolean impliesResolve() {
         return true;
     }

http://git-wip-us.apache.org/repos/asf/isis/blob/5f15fa74/core/metamodel/src/main/java/org/apache/isis/core/progmodel/facets/properties/autocomplete/PropertyAutoCompleteFacetViaMethod.java
----------------------------------------------------------------------
diff --git a/core/metamodel/src/main/java/org/apache/isis/core/progmodel/facets/properties/autocomplete/PropertyAutoCompleteFacetViaMethod.java b/core/metamodel/src/main/java/org/apache/isis/core/progmodel/facets/properties/autocomplete/PropertyAutoCompleteFacetViaMethod.java
index 88116ed..b3ac280 100644
--- a/core/metamodel/src/main/java/org/apache/isis/core/progmodel/facets/properties/autocomplete/PropertyAutoCompleteFacetViaMethod.java
+++ b/core/metamodel/src/main/java/org/apache/isis/core/progmodel/facets/properties/autocomplete/PropertyAutoCompleteFacetViaMethod.java
@@ -29,6 +29,7 @@ import org.apache.isis.core.metamodel.adapter.mgr.AdapterManager;
 import org.apache.isis.core.metamodel.adapter.util.AdapterInvokeUtils;
 import org.apache.isis.core.metamodel.facetapi.FacetHolder;
 import org.apache.isis.core.metamodel.facets.ImperativeFacet;
+import org.apache.isis.core.metamodel.facets.ImperativeFacet.Intent;
 import org.apache.isis.core.metamodel.spec.ObjectSpecification;
 import org.apache.isis.core.metamodel.spec.SpecificationLoader;
 import org.apache.isis.core.progmodel.facets.CollectionUtils;
@@ -62,6 +63,11 @@ public class PropertyAutoCompleteFacetViaMethod extends PropertyAutoCompleteFace
     }
 
     @Override
+    public Intent getIntent(final Method method) {
+        return Intent.CHOICES_OR_AUTOCOMPLETE;
+    }
+
+    @Override
     public int getMinLength() {
         return minLength;
     }

http://git-wip-us.apache.org/repos/asf/isis/blob/5f15fa74/core/metamodel/src/main/java/org/apache/isis/core/progmodel/facets/properties/choices/method/PropertyChoicesFacetViaMethod.java
----------------------------------------------------------------------
diff --git a/core/metamodel/src/main/java/org/apache/isis/core/progmodel/facets/properties/choices/method/PropertyChoicesFacetViaMethod.java b/core/metamodel/src/main/java/org/apache/isis/core/progmodel/facets/properties/choices/method/PropertyChoicesFacetViaMethod.java
index cb2b694..d752f3f 100644
--- a/core/metamodel/src/main/java/org/apache/isis/core/progmodel/facets/properties/choices/method/PropertyChoicesFacetViaMethod.java
+++ b/core/metamodel/src/main/java/org/apache/isis/core/progmodel/facets/properties/choices/method/PropertyChoicesFacetViaMethod.java
@@ -29,6 +29,7 @@ import org.apache.isis.core.metamodel.adapter.mgr.AdapterManager;
 import org.apache.isis.core.metamodel.adapter.util.AdapterInvokeUtils;
 import org.apache.isis.core.metamodel.facetapi.FacetHolder;
 import org.apache.isis.core.metamodel.facets.ImperativeFacet;
+import org.apache.isis.core.metamodel.facets.ImperativeFacet.Intent;
 import org.apache.isis.core.metamodel.spec.ObjectSpecification;
 import org.apache.isis.core.metamodel.spec.SpecificationLoader;
 import org.apache.isis.core.progmodel.facets.CollectionUtils;
@@ -58,6 +59,11 @@ public class PropertyChoicesFacetViaMethod extends PropertyChoicesFacetAbstract
     }
 
     @Override
+    public Intent getIntent(final Method method) {
+        return Intent.CHOICES_OR_AUTOCOMPLETE;
+    }
+
+    @Override
     public boolean impliesResolve() {
         return true;
     }

http://git-wip-us.apache.org/repos/asf/isis/blob/5f15fa74/core/metamodel/src/main/java/org/apache/isis/core/progmodel/facets/properties/defaults/method/PropertyDefaultFacetViaMethod.java
----------------------------------------------------------------------
diff --git a/core/metamodel/src/main/java/org/apache/isis/core/progmodel/facets/properties/defaults/method/PropertyDefaultFacetViaMethod.java b/core/metamodel/src/main/java/org/apache/isis/core/progmodel/facets/properties/defaults/method/PropertyDefaultFacetViaMethod.java
index b5a1610..35a2294 100644
--- a/core/metamodel/src/main/java/org/apache/isis/core/progmodel/facets/properties/defaults/method/PropertyDefaultFacetViaMethod.java
+++ b/core/metamodel/src/main/java/org/apache/isis/core/progmodel/facets/properties/defaults/method/PropertyDefaultFacetViaMethod.java
@@ -29,6 +29,7 @@ import org.apache.isis.core.metamodel.adapter.mgr.AdapterManager;
 import org.apache.isis.core.metamodel.adapter.util.AdapterInvokeUtils;
 import org.apache.isis.core.metamodel.facetapi.FacetHolder;
 import org.apache.isis.core.metamodel.facets.ImperativeFacet;
+import org.apache.isis.core.metamodel.facets.ImperativeFacet.Intent;
 import org.apache.isis.core.metamodel.spec.ObjectSpecification;
 import org.apache.isis.core.metamodel.spec.SpecificationLoader;
 import org.apache.isis.core.progmodel.facets.properties.defaults.PropertyDefaultFacetAbstract;
@@ -56,6 +57,11 @@ public class PropertyDefaultFacetViaMethod extends PropertyDefaultFacetAbstract
     }
 
     @Override
+    public Intent getIntent(final Method method) {
+        return Intent.DEFAULTS;
+    }
+
+    @Override
     public boolean impliesResolve() {
         return true;
     }

http://git-wip-us.apache.org/repos/asf/isis/blob/5f15fa74/core/metamodel/src/main/java/org/apache/isis/core/progmodel/facets/properties/event/Helper.java
----------------------------------------------------------------------
diff --git a/core/metamodel/src/main/java/org/apache/isis/core/progmodel/facets/properties/event/Helper.java b/core/metamodel/src/main/java/org/apache/isis/core/progmodel/facets/properties/event/Helper.java
new file mode 100644
index 0000000..de4cdac
--- /dev/null
+++ b/core/metamodel/src/main/java/org/apache/isis/core/progmodel/facets/properties/event/Helper.java
@@ -0,0 +1,48 @@
+/*
+ *  Licensed to the Apache Software Foundation (ASF) under one
+ *  or more contributor license agreements.  See the NOTICE file
+ *  distributed with this work for additional information
+ *  regarding copyright ownership.  The ASF licenses this file
+ *  to you under the Apache License, Version 2.0 (the
+ *  "License"); you may not use this file except in compliance
+ *  with the License.  You may obtain a copy of the License at
+ *
+ *        http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *  Unless required by applicable law or agreed to in writing,
+ *  software distributed under the License is distributed on an
+ *  "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ *  KIND, either express or implied.  See the License for the
+ *  specific language governing permissions and limitations
+ *  under the License.
+ */
+
+package org.apache.isis.core.progmodel.facets.properties.event;
+
+import org.apache.isis.applib.services.eventbus.EventBusService;
+import org.apache.isis.applib.services.eventbus.PropertyChangedEvent;
+import org.apache.isis.core.metamodel.runtimecontext.ServicesInjector;
+
+class Helper {
+
+    private final ServicesInjector servicesInjector;
+
+    private EventBusService eventBusService;
+    private boolean searchedForEventBusService = false;
+
+    public Helper(final ServicesInjector servicesInjector) {
+        this.servicesInjector = servicesInjector;
+    }
+
+    void postEvent(final PropertyChangedEvent<?, ?> event) {
+        eventBusService.post(event);
+    }
+
+    EventBusService getEventBusService() {
+        if (!searchedForEventBusService) {
+            eventBusService = this.servicesInjector.lookupService(EventBusService.class);
+        }
+        searchedForEventBusService = true;
+        return eventBusService;
+    }
+}

http://git-wip-us.apache.org/repos/asf/isis/blob/5f15fa74/core/metamodel/src/main/java/org/apache/isis/core/progmodel/facets/properties/event/PostsPropertyChangedEventAnnotationFacetFactory.java
----------------------------------------------------------------------
diff --git a/core/metamodel/src/main/java/org/apache/isis/core/progmodel/facets/properties/event/PostsPropertyChangedEventAnnotationFacetFactory.java b/core/metamodel/src/main/java/org/apache/isis/core/progmodel/facets/properties/event/PostsPropertyChangedEventAnnotationFacetFactory.java
index 89bd745..98eb385 100644
--- a/core/metamodel/src/main/java/org/apache/isis/core/progmodel/facets/properties/event/PostsPropertyChangedEventAnnotationFacetFactory.java
+++ b/core/metamodel/src/main/java/org/apache/isis/core/progmodel/facets/properties/event/PostsPropertyChangedEventAnnotationFacetFactory.java
@@ -26,17 +26,14 @@ import java.util.List;
 import org.apache.isis.applib.annotation.PostsPropertyChangedEvent;
 import org.apache.isis.applib.services.eventbus.PropertyChangedEvent;
 import org.apache.isis.core.commons.config.IsisConfiguration;
-import org.apache.isis.core.metamodel.adapter.ServicesProvider;
-import org.apache.isis.core.metamodel.adapter.ServicesProviderAware;
-import org.apache.isis.core.metamodel.facetapi.FacetHolder;
 import org.apache.isis.core.metamodel.facetapi.FacetUtil;
 import org.apache.isis.core.metamodel.facetapi.FeatureType;
 import org.apache.isis.core.metamodel.facetapi.MetaModelValidatorRefiner;
 import org.apache.isis.core.metamodel.facets.Annotations;
 import org.apache.isis.core.metamodel.facets.FacetFactoryAbstract;
+import org.apache.isis.core.metamodel.facets.FacetedMethod;
 import org.apache.isis.core.metamodel.facets.accessor.PropertyOrCollectionAccessorFacet;
 import org.apache.isis.core.metamodel.facets.collections.sortedby.SortedByFacet;
-import org.apache.isis.core.metamodel.facets.properties.event.PostsPropertyChangedEventFacet;
 import org.apache.isis.core.metamodel.facets.properties.modify.PropertyClearFacet;
 import org.apache.isis.core.metamodel.facets.properties.modify.PropertySetterFacet;
 import org.apache.isis.core.metamodel.runtimecontext.ServicesInjector;
@@ -60,38 +57,28 @@ public class PostsPropertyChangedEventAnnotationFacetFactory extends FacetFactor
     @Override
     public void process(final ProcessMethodContext processMethodContext) {
         final Method method = processMethodContext.getMethod();
-        FacetUtil.addFacet(create(method, processMethodContext.getFacetHolder()));
-    }
-
-    private PostsPropertyChangedEventFacet create(Method method, final FacetHolder holder) {
+        FacetedMethod holder = processMethodContext.getFacetHolder();
+        
         final PostsPropertyChangedEvent annotation = Annotations.getAnnotation(method, PostsPropertyChangedEvent.class);
         if(annotation == null) {
-            return null;
+            return;
         }
         final PropertyOrCollectionAccessorFacet getterFacet = holder.getFacet(PropertyOrCollectionAccessorFacet.class);
         if(getterFacet == null) {
-            return null;
+            return;
         } 
-        final PropertyClearFacet clearFacet = holder.getFacet(PropertyClearFacet.class);
-        final PropertySetterFacet setterFacet = holder.getFacet(PropertySetterFacet.class);
-        if (clearFacet == null && setterFacet == null) {
-            return null;
-        }
         
-        
-        // REVIEW: I'm a bit uncertain about this; this facet is multi-valued, but the setUnderlying(...) stuff only
-        // works for single valued types.
-        // the wrapperFactory stuff looks for underlying to find the imperative method, I think this only works in this
-        // case because (by accident rather than design) there is also the PropertyInitializationFacet wrapping the setter.
+        final PropertySetterFacet setterFacet = holder.getFacet(PropertySetterFacet.class);
         if(setterFacet != null) {
-            holder.removeFacet(setterFacet);
+            final Class<? extends PropertyChangedEvent<?, ?>> changedEventType = annotation.value();
+            FacetUtil.addFacet(new PostsPropertyChangedEventSetterFacetAnnotation(changedEventType, getterFacet, setterFacet, servicesInjector, holder));
         }
+        
+        final PropertyClearFacet clearFacet = holder.getFacet(PropertyClearFacet.class);
         if(clearFacet != null) {
-            holder.removeFacet(clearFacet);
+            final Class<? extends PropertyChangedEvent<?, ?>> changedEventType = annotation.value();
+            FacetUtil.addFacet(new PostsPropertyChangedEventClearFacetAnnotation(changedEventType, getterFacet, clearFacet, servicesInjector, holder));
         }
-        
-        final Class<? extends PropertyChangedEvent<?, ?>> changedEventType = annotation.value();
-        return new PostsPropertyChangedEventFacetAnnotation(changedEventType, getterFacet, setterFacet, clearFacet, servicesInjector, holder);
     }
 
     // //////////////////////////////////////
@@ -128,5 +115,4 @@ public class PostsPropertyChangedEventAnnotationFacetFactory extends FacetFactor
         this.servicesInjector = servicesInjector;
     }
 
-    
 }

http://git-wip-us.apache.org/repos/asf/isis/blob/5f15fa74/core/metamodel/src/main/java/org/apache/isis/core/progmodel/facets/properties/event/PostsPropertyChangedEventClearFacetAnnotation.java
----------------------------------------------------------------------
diff --git a/core/metamodel/src/main/java/org/apache/isis/core/progmodel/facets/properties/event/PostsPropertyChangedEventClearFacetAnnotation.java b/core/metamodel/src/main/java/org/apache/isis/core/progmodel/facets/properties/event/PostsPropertyChangedEventClearFacetAnnotation.java
new file mode 100644
index 0000000..0dff445
--- /dev/null
+++ b/core/metamodel/src/main/java/org/apache/isis/core/progmodel/facets/properties/event/PostsPropertyChangedEventClearFacetAnnotation.java
@@ -0,0 +1,118 @@
+/*
+ *  Licensed to the Apache Software Foundation (ASF) under one
+ *  or more contributor license agreements.  See the NOTICE file
+ *  distributed with this work for additional information
+ *  regarding copyright ownership.  The ASF licenses this file
+ *  to you under the Apache License, Version 2.0 (the
+ *  "License"); you may not use this file except in compliance
+ *  with the License.  You may obtain a copy of the License at
+ *
+ *        http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *  Unless required by applicable law or agreed to in writing,
+ *  software distributed under the License is distributed on an
+ *  "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ *  KIND, either express or implied.  See the License for the
+ *  specific language governing permissions and limitations
+ *  under the License.
+ */
+
+package org.apache.isis.core.progmodel.facets.properties.event;
+
+import com.google.common.base.Objects;
+import com.google.common.collect.Lists;
+
+import org.apache.isis.applib.FatalException;
+import org.apache.isis.applib.Identifier;
+import org.apache.isis.applib.services.eventbus.EventBusService;
+import org.apache.isis.applib.services.eventbus.PropertyChangedEvent;
+import org.apache.isis.core.metamodel.adapter.ObjectAdapter;
+import org.apache.isis.core.metamodel.facetapi.Facet;
+import org.apache.isis.core.metamodel.facetapi.FacetHolder;
+import org.apache.isis.core.metamodel.facets.accessor.PropertyOrCollectionAccessorFacet;
+import org.apache.isis.core.metamodel.facets.properties.event.PostsPropertyChangedEventClearFacet;
+import org.apache.isis.core.metamodel.facets.properties.event.PostsPropertyChangedEventClearFacetAbstract;
+import org.apache.isis.core.metamodel.facets.properties.modify.PropertyClearFacet;
+import org.apache.isis.core.metamodel.runtimecontext.ServicesInjector;
+
+public class PostsPropertyChangedEventClearFacetAnnotation 
+        extends PostsPropertyChangedEventClearFacetAbstract {
+
+    private final PropertyOrCollectionAccessorFacet getterFacet;
+    private final PropertyClearFacet clearFacet;
+    private final Helper helper;
+    
+    public PostsPropertyChangedEventClearFacetAnnotation(
+            final Class<? extends PropertyChangedEvent<?, ?>> eventType, 
+            final PropertyOrCollectionAccessorFacet getterFacet, 
+            final PropertyClearFacet clearFacet, 
+            final ServicesInjector servicesInjector,
+            final FacetHolder holder) {
+        super(eventType, holder);
+        this.getterFacet = getterFacet;
+        this.clearFacet = clearFacet;
+        this.helper = new Helper(servicesInjector);
+    }
+
+    @Override
+    public void clearProperty(ObjectAdapter targetAdapter) {
+        if(clearFacet == null) {
+            return;
+        }
+
+        if(helper.getEventBusService() == null) {
+            clearFacet.clearProperty(targetAdapter);
+            return;
+        }
+
+        final Object oldValue = getterFacet.getProperty(targetAdapter);
+        clearFacet.clearProperty(targetAdapter);
+        final Object newValue = getterFacet.getProperty(targetAdapter);
+        
+        postEventIfChanged(targetAdapter, getIdentified().getIdentifier(), oldValue, newValue);
+    }
+
+
+    @SuppressWarnings({ "rawtypes", "unchecked" })
+    private void postEventIfChanged(
+            final ObjectAdapter targetAdapter, 
+            final Identifier identifier, 
+            final Object oldValue, 
+            final Object newValue) {
+        
+        if(Objects.equal(oldValue, newValue)) {
+            // do nothing.
+            return;
+        }
+        try {
+            final Class type = value();
+            final Object source = ObjectAdapter.Util.unwrap(targetAdapter);
+            final PropertyChangedEvent<?, ?> event = Util.newEvent(type, source, identifier, oldValue, newValue);
+            
+            helper.postEvent(event);
+        } catch (Exception e) {
+            throw new FatalException(e);
+        }
+    }
+
+    // //////////////////////////////////////
+    // MultiTypedFacet
+    // //////////////////////////////////////
+
+    @SuppressWarnings("unchecked")
+    @Override
+    public Class<? extends Facet>[] facetTypes() {
+        return Lists.newArrayList(
+                    type(),
+                    PostsPropertyChangedEventClearFacet.class
+                ).toArray(new Class[]{});
+    }
+
+    @SuppressWarnings("unchecked")
+    @Override
+    public <T extends Facet> T getFacet(Class<T> facet) {
+        return (T) this;
+    }
+
+
+}

http://git-wip-us.apache.org/repos/asf/isis/blob/5f15fa74/core/metamodel/src/main/java/org/apache/isis/core/progmodel/facets/properties/event/PostsPropertyChangedEventFacetAnnotation.java
----------------------------------------------------------------------
diff --git a/core/metamodel/src/main/java/org/apache/isis/core/progmodel/facets/properties/event/PostsPropertyChangedEventFacetAnnotation.java b/core/metamodel/src/main/java/org/apache/isis/core/progmodel/facets/properties/event/PostsPropertyChangedEventFacetAnnotation.java
deleted file mode 100644
index db67de1..0000000
--- a/core/metamodel/src/main/java/org/apache/isis/core/progmodel/facets/properties/event/PostsPropertyChangedEventFacetAnnotation.java
+++ /dev/null
@@ -1,157 +0,0 @@
-/*
- *  Licensed to the Apache Software Foundation (ASF) under one
- *  or more contributor license agreements.  See the NOTICE file
- *  distributed with this work for additional information
- *  regarding copyright ownership.  The ASF licenses this file
- *  to you under the Apache License, Version 2.0 (the
- *  "License"); you may not use this file except in compliance
- *  with the License.  You may obtain a copy of the License at
- *
- *        http://www.apache.org/licenses/LICENSE-2.0
- *
- *  Unless required by applicable law or agreed to in writing,
- *  software distributed under the License is distributed on an
- *  "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- *  KIND, either express or implied.  See the License for the
- *  specific language governing permissions and limitations
- *  under the License.
- */
-
-package org.apache.isis.core.progmodel.facets.properties.event;
-
-import java.lang.reflect.Constructor;
-import java.lang.reflect.Field;
-import java.lang.reflect.InvocationTargetException;
-import java.util.List;
-
-import com.google.common.base.Objects;
-import com.google.common.collect.Lists;
-
-import org.apache.isis.applib.FatalException;
-import org.apache.isis.applib.Identifier;
-import org.apache.isis.applib.services.eventbus.EventBusService;
-import org.apache.isis.applib.services.eventbus.PropertyChangedEvent;
-import org.apache.isis.core.metamodel.adapter.ObjectAdapter;
-import org.apache.isis.core.metamodel.adapter.ServicesProvider;
-import org.apache.isis.core.metamodel.adapter.util.AdapterUtils;
-import org.apache.isis.core.metamodel.facetapi.Facet;
-import org.apache.isis.core.metamodel.facetapi.FacetHolder;
-import org.apache.isis.core.metamodel.facets.accessor.PropertyOrCollectionAccessorFacet;
-import org.apache.isis.core.metamodel.facets.properties.event.PostsPropertyChangedEventFacet;
-import org.apache.isis.core.metamodel.facets.properties.event.PostsPropertyChangedEventFacetAbstract;
-import org.apache.isis.core.metamodel.facets.properties.modify.PropertyClearFacet;
-import org.apache.isis.core.metamodel.facets.properties.modify.PropertySetterFacet;
-import org.apache.isis.core.metamodel.runtimecontext.ServicesInjector;
-
-public class PostsPropertyChangedEventFacetAnnotation extends PostsPropertyChangedEventFacetAbstract {
-
-    private final PropertyOrCollectionAccessorFacet getterFacet;
-    private final PropertySetterFacet setterFacet;
-    private final PropertyClearFacet clearFacet;
-    private final ServicesInjector servicesInjector;
-    
-    private EventBusService eventBusService;
-    private boolean searchedForEventBusService = false;
-
-    public PostsPropertyChangedEventFacetAnnotation(
-            final Class<? extends PropertyChangedEvent<?, ?>> eventType, 
-            final PropertyOrCollectionAccessorFacet getterFacet, 
-            final PropertySetterFacet setterFacet, 
-            final PropertyClearFacet clearFacet, 
-            final ServicesInjector servicesInjector,
-            final FacetHolder holder) {
-        super(eventType, holder);
-        this.getterFacet = getterFacet;
-        this.setterFacet = setterFacet;
-        this.clearFacet = clearFacet;
-        this.servicesInjector = servicesInjector;
-    }
-
-    @Override
-    public void setProperty(ObjectAdapter targetAdapter, ObjectAdapter valueAdapter) {
-        if(setterFacet == null) {
-            return;
-        }
-        eventBusService = getEventBusService();
-        if(eventBusService == null) {
-            setterFacet.setProperty(targetAdapter, valueAdapter);
-            return;
-        }
-        
-        final Object oldValue = getterFacet.getProperty(targetAdapter);
-        setterFacet.setProperty(targetAdapter, valueAdapter);
-        final Object newValue = getterFacet.getProperty(targetAdapter);
-        postEventIfChanged(targetAdapter, getIdentified().getIdentifier(), oldValue, newValue);
-    }
-
-    @Override
-    public void clearProperty(ObjectAdapter targetAdapter) {
-        if(clearFacet == null) {
-            return;
-        }
-        eventBusService = getEventBusService();
-        if(eventBusService == null) {
-            clearFacet.clearProperty(targetAdapter);
-            return;
-        }
-
-        final Object oldValue = getterFacet.getProperty(targetAdapter);
-        clearFacet.clearProperty(targetAdapter);
-        final Object newValue = getterFacet.getProperty(targetAdapter);
-        
-        postEventIfChanged(targetAdapter, getIdentified().getIdentifier(), oldValue, newValue);
-    }
-
-
-    @SuppressWarnings({ "rawtypes", "unchecked" })
-    private void postEventIfChanged(
-            final ObjectAdapter targetAdapter, 
-            final Identifier identifier, 
-            final Object oldValue, 
-            final Object newValue) {
-        
-        if(Objects.equal(oldValue, newValue)) {
-            // do nothing.
-            return;
-        }
-        try {
-            final Class type = value();
-            final Object source = ObjectAdapter.Util.unwrap(targetAdapter);
-            final PropertyChangedEvent<?, ?> event = Util.newEvent(type, source, identifier, oldValue, newValue);
-            
-            eventBusService.post(event);
-        } catch (Exception e) {
-            throw new FatalException(e);
-        }
-    }
-
-    private EventBusService getEventBusService() {
-        if (!searchedForEventBusService) {
-            eventBusService = this.servicesInjector.lookupService(EventBusService.class);
-        }
-        searchedForEventBusService = true;
-        return eventBusService;
-    }
-    
-    // //////////////////////////////////////
-    // MultiTypedFacet
-    // //////////////////////////////////////
-
-    @SuppressWarnings("unchecked")
-    @Override
-    public Class<? extends Facet>[] facetTypes() {
-        return Lists.newArrayList(
-                    PostsPropertyChangedEventFacet.class, 
-                    PropertySetterFacet.class, 
-                    PropertyClearFacet.class
-                ).toArray(new Class[]{});
-    }
-
-    @SuppressWarnings("unchecked")
-    @Override
-    public <T extends Facet> T getFacet(Class<T> facet) {
-        return (T) this;
-    }
-
-
-}

http://git-wip-us.apache.org/repos/asf/isis/blob/5f15fa74/core/metamodel/src/main/java/org/apache/isis/core/progmodel/facets/properties/event/PostsPropertyChangedEventSetterFacetAnnotation.java
----------------------------------------------------------------------
diff --git a/core/metamodel/src/main/java/org/apache/isis/core/progmodel/facets/properties/event/PostsPropertyChangedEventSetterFacetAnnotation.java b/core/metamodel/src/main/java/org/apache/isis/core/progmodel/facets/properties/event/PostsPropertyChangedEventSetterFacetAnnotation.java
new file mode 100644
index 0000000..23647b2
--- /dev/null
+++ b/core/metamodel/src/main/java/org/apache/isis/core/progmodel/facets/properties/event/PostsPropertyChangedEventSetterFacetAnnotation.java
@@ -0,0 +1,117 @@
+/*
+ *  Licensed to the Apache Software Foundation (ASF) under one
+ *  or more contributor license agreements.  See the NOTICE file
+ *  distributed with this work for additional information
+ *  regarding copyright ownership.  The ASF licenses this file
+ *  to you under the Apache License, Version 2.0 (the
+ *  "License"); you may not use this file except in compliance
+ *  with the License.  You may obtain a copy of the License at
+ *
+ *        http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *  Unless required by applicable law or agreed to in writing,
+ *  software distributed under the License is distributed on an
+ *  "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ *  KIND, either express or implied.  See the License for the
+ *  specific language governing permissions and limitations
+ *  under the License.
+ */
+
+package org.apache.isis.core.progmodel.facets.properties.event;
+
+import com.google.common.base.Objects;
+import com.google.common.collect.Lists;
+
+import org.apache.isis.applib.FatalException;
+import org.apache.isis.applib.Identifier;
+import org.apache.isis.applib.services.eventbus.EventBusService;
+import org.apache.isis.applib.services.eventbus.PropertyChangedEvent;
+import org.apache.isis.core.metamodel.adapter.ObjectAdapter;
+import org.apache.isis.core.metamodel.facetapi.Facet;
+import org.apache.isis.core.metamodel.facetapi.FacetHolder;
+import org.apache.isis.core.metamodel.facets.accessor.PropertyOrCollectionAccessorFacet;
+import org.apache.isis.core.metamodel.facets.properties.event.PostsPropertyChangedEventSetterFacet;
+import org.apache.isis.core.metamodel.facets.properties.event.PostsPropertyChangedEventSetterFacetAbstract;
+import org.apache.isis.core.metamodel.facets.properties.modify.PropertySetterFacet;
+import org.apache.isis.core.metamodel.runtimecontext.ServicesInjector;
+
+public class PostsPropertyChangedEventSetterFacetAnnotation 
+        extends PostsPropertyChangedEventSetterFacetAbstract {
+
+    private final PropertyOrCollectionAccessorFacet getterFacet;
+    private final PropertySetterFacet setterFacet;
+    
+    private final Helper helper;
+    
+    public PostsPropertyChangedEventSetterFacetAnnotation(
+            final Class<? extends PropertyChangedEvent<?, ?>> eventType, 
+            final PropertyOrCollectionAccessorFacet getterFacet, 
+            final PropertySetterFacet setterFacet, 
+            final ServicesInjector servicesInjector,
+            final FacetHolder holder) {
+        super(eventType, holder);
+        this.getterFacet = getterFacet;
+        this.setterFacet = setterFacet;
+        this.helper = new Helper(servicesInjector);
+    }
+
+    @Override
+    public void setProperty(ObjectAdapter targetAdapter, ObjectAdapter valueAdapter) {
+        if(setterFacet == null) {
+            return;
+        }
+        if(helper.getEventBusService() == null) {
+            setterFacet.setProperty(targetAdapter, valueAdapter);
+            return;
+        }
+        
+        final Object oldValue = getterFacet.getProperty(targetAdapter);
+        setterFacet.setProperty(targetAdapter, valueAdapter);
+        final Object newValue = getterFacet.getProperty(targetAdapter);
+        postEventIfChanged(targetAdapter, getIdentified().getIdentifier(), oldValue, newValue);
+    }
+
+    @SuppressWarnings({ "rawtypes", "unchecked" })
+    private void postEventIfChanged(
+            final ObjectAdapter targetAdapter, 
+            final Identifier identifier, 
+            final Object oldValue, 
+            final Object newValue) {
+        
+        if(Objects.equal(oldValue, newValue)) {
+            // do nothing.
+            return;
+        }
+        try {
+            final Class type = value();
+            final Object source = ObjectAdapter.Util.unwrap(targetAdapter);
+            final PropertyChangedEvent<?, ?> event = Util.newEvent(type, source, identifier, oldValue, newValue);
+
+            helper.postEvent(event);
+        } catch (Exception e) {
+            throw new FatalException(e);
+        }
+    }
+
+    
+    // //////////////////////////////////////
+    // MultiTypedFacet
+    // //////////////////////////////////////
+
+    @SuppressWarnings("unchecked")
+    @Override
+    public Class<? extends Facet>[] facetTypes() {
+        return Lists.newArrayList(
+                    type(),
+                    PostsPropertyChangedEventSetterFacet.class
+                ).toArray(new Class[]{});
+    }
+
+    @SuppressWarnings("unchecked")
+    @Override
+    public <T extends Facet> T getFacet(Class<T> facet) {
+        return (T) this;
+    }
+
+
+}

http://git-wip-us.apache.org/repos/asf/isis/blob/5f15fa74/core/metamodel/src/main/java/org/apache/isis/core/progmodel/facets/properties/modify/PropertyClearFacetViaClearMethod.java
----------------------------------------------------------------------
diff --git a/core/metamodel/src/main/java/org/apache/isis/core/progmodel/facets/properties/modify/PropertyClearFacetViaClearMethod.java b/core/metamodel/src/main/java/org/apache/isis/core/progmodel/facets/properties/modify/PropertyClearFacetViaClearMethod.java
index 1b2a84e..ec4bde6 100644
--- a/core/metamodel/src/main/java/org/apache/isis/core/progmodel/facets/properties/modify/PropertyClearFacetViaClearMethod.java
+++ b/core/metamodel/src/main/java/org/apache/isis/core/progmodel/facets/properties/modify/PropertyClearFacetViaClearMethod.java
@@ -27,6 +27,7 @@ import org.apache.isis.core.metamodel.adapter.ObjectAdapter;
 import org.apache.isis.core.metamodel.adapter.util.AdapterInvokeUtils;
 import org.apache.isis.core.metamodel.facetapi.FacetHolder;
 import org.apache.isis.core.metamodel.facets.ImperativeFacet;
+import org.apache.isis.core.metamodel.facets.ImperativeFacet.Intent;
 import org.apache.isis.core.metamodel.facets.properties.modify.PropertyClearFacetAbstract;
 
 public class PropertyClearFacetViaClearMethod extends PropertyClearFacetAbstract implements ImperativeFacet {
@@ -48,6 +49,11 @@ public class PropertyClearFacetViaClearMethod extends PropertyClearFacetAbstract
     }
 
     @Override
+    public Intent getIntent(final Method method) {
+        return Intent.MODIFY_PROPERTY_SUPPORTING;
+    }
+
+    @Override
     public boolean impliesResolve() {
         return true;
     }

http://git-wip-us.apache.org/repos/asf/isis/blob/5f15fa74/core/metamodel/src/main/java/org/apache/isis/core/progmodel/facets/properties/modify/PropertyClearFacetViaSetterMethod.java
----------------------------------------------------------------------
diff --git a/core/metamodel/src/main/java/org/apache/isis/core/progmodel/facets/properties/modify/PropertyClearFacetViaSetterMethod.java b/core/metamodel/src/main/java/org/apache/isis/core/progmodel/facets/properties/modify/PropertyClearFacetViaSetterMethod.java
index 9cde05d..de6bf15 100644
--- a/core/metamodel/src/main/java/org/apache/isis/core/progmodel/facets/properties/modify/PropertyClearFacetViaSetterMethod.java
+++ b/core/metamodel/src/main/java/org/apache/isis/core/progmodel/facets/properties/modify/PropertyClearFacetViaSetterMethod.java
@@ -27,6 +27,7 @@ import org.apache.isis.core.metamodel.adapter.ObjectAdapter;
 import org.apache.isis.core.metamodel.adapter.util.AdapterInvokeUtils;
 import org.apache.isis.core.metamodel.facetapi.FacetHolder;
 import org.apache.isis.core.metamodel.facets.ImperativeFacet;
+import org.apache.isis.core.metamodel.facets.ImperativeFacet.Intent;
 import org.apache.isis.core.metamodel.facets.properties.modify.PropertyClearFacetAbstract;
 
 public class PropertyClearFacetViaSetterMethod extends PropertyClearFacetAbstract implements ImperativeFacet {
@@ -48,6 +49,11 @@ public class PropertyClearFacetViaSetterMethod extends PropertyClearFacetAbstrac
     }
 
     @Override
+    public Intent getIntent(final Method method) {
+        return Intent.MODIFY_PROPERTY;
+    }
+
+    @Override
     public boolean impliesResolve() {
         return true;
     }

http://git-wip-us.apache.org/repos/asf/isis/blob/5f15fa74/core/metamodel/src/main/java/org/apache/isis/core/progmodel/facets/properties/modify/PropertyInitializationFacetViaSetterMethod.java
----------------------------------------------------------------------
diff --git a/core/metamodel/src/main/java/org/apache/isis/core/progmodel/facets/properties/modify/PropertyInitializationFacetViaSetterMethod.java b/core/metamodel/src/main/java/org/apache/isis/core/progmodel/facets/properties/modify/PropertyInitializationFacetViaSetterMethod.java
index 4b86ad8..9710320 100644
--- a/core/metamodel/src/main/java/org/apache/isis/core/progmodel/facets/properties/modify/PropertyInitializationFacetViaSetterMethod.java
+++ b/core/metamodel/src/main/java/org/apache/isis/core/progmodel/facets/properties/modify/PropertyInitializationFacetViaSetterMethod.java
@@ -47,6 +47,13 @@ public class PropertyInitializationFacetViaSetterMethod extends PropertyInitiali
     }
 
     @Override
+    public Intent getIntent(final Method method) {
+        // LIMITATION: we cannot distinguish between setXxx being called for a modify or for an initialization
+        // so we just assume its a setter.
+        return Intent.MODIFY_PROPERTY;
+    }
+
+    @Override
     public boolean impliesResolve() {
         return false;
     }

http://git-wip-us.apache.org/repos/asf/isis/blob/5f15fa74/core/metamodel/src/main/java/org/apache/isis/core/progmodel/facets/properties/modify/PropertySetterFacetViaModifyMethod.java
----------------------------------------------------------------------
diff --git a/core/metamodel/src/main/java/org/apache/isis/core/progmodel/facets/properties/modify/PropertySetterFacetViaModifyMethod.java b/core/metamodel/src/main/java/org/apache/isis/core/progmodel/facets/properties/modify/PropertySetterFacetViaModifyMethod.java
index f37ee09..4d99e81 100644
--- a/core/metamodel/src/main/java/org/apache/isis/core/progmodel/facets/properties/modify/PropertySetterFacetViaModifyMethod.java
+++ b/core/metamodel/src/main/java/org/apache/isis/core/progmodel/facets/properties/modify/PropertySetterFacetViaModifyMethod.java
@@ -27,6 +27,7 @@ import org.apache.isis.core.metamodel.adapter.ObjectAdapter;
 import org.apache.isis.core.metamodel.adapter.util.AdapterInvokeUtils;
 import org.apache.isis.core.metamodel.facetapi.FacetHolder;
 import org.apache.isis.core.metamodel.facets.ImperativeFacet;
+import org.apache.isis.core.metamodel.facets.ImperativeFacet.Intent;
 import org.apache.isis.core.metamodel.facets.properties.modify.PropertySetterFacetAbstract;
 
 public class PropertySetterFacetViaModifyMethod extends PropertySetterFacetAbstract implements ImperativeFacet {
@@ -48,6 +49,11 @@ public class PropertySetterFacetViaModifyMethod extends PropertySetterFacetAbstr
     }
 
     @Override
+    public Intent getIntent(final Method method) {
+        return Intent.MODIFY_PROPERTY_SUPPORTING;
+    }
+
+    @Override
     public boolean impliesResolve() {
         return true;
     }

http://git-wip-us.apache.org/repos/asf/isis/blob/5f15fa74/core/metamodel/src/main/java/org/apache/isis/core/progmodel/facets/properties/modify/PropertySetterFacetViaSetterMethod.java
----------------------------------------------------------------------
diff --git a/core/metamodel/src/main/java/org/apache/isis/core/progmodel/facets/properties/modify/PropertySetterFacetViaSetterMethod.java b/core/metamodel/src/main/java/org/apache/isis/core/progmodel/facets/properties/modify/PropertySetterFacetViaSetterMethod.java
index 660d241..6688deb 100644
--- a/core/metamodel/src/main/java/org/apache/isis/core/progmodel/facets/properties/modify/PropertySetterFacetViaSetterMethod.java
+++ b/core/metamodel/src/main/java/org/apache/isis/core/progmodel/facets/properties/modify/PropertySetterFacetViaSetterMethod.java
@@ -27,6 +27,7 @@ import org.apache.isis.core.metamodel.adapter.ObjectAdapter;
 import org.apache.isis.core.metamodel.adapter.util.AdapterInvokeUtils;
 import org.apache.isis.core.metamodel.facetapi.FacetHolder;
 import org.apache.isis.core.metamodel.facets.ImperativeFacet;
+import org.apache.isis.core.metamodel.facets.ImperativeFacet.Intent;
 import org.apache.isis.core.metamodel.facets.properties.modify.PropertySetterFacetAbstract;
 
 public class PropertySetterFacetViaSetterMethod extends PropertySetterFacetAbstract implements ImperativeFacet {
@@ -48,6 +49,11 @@ public class PropertySetterFacetViaSetterMethod extends PropertySetterFacetAbstr
     }
 
     @Override
+    public Intent getIntent(final Method method) {
+        return Intent.MODIFY_PROPERTY;
+    }
+
+    @Override
     public boolean impliesResolve() {
         return true;
     }

http://git-wip-us.apache.org/repos/asf/isis/blob/5f15fa74/core/metamodel/src/main/java/org/apache/isis/core/progmodel/facets/properties/validate/PropertyValidateFacetViaMethod.java
----------------------------------------------------------------------
diff --git a/core/metamodel/src/main/java/org/apache/isis/core/progmodel/facets/properties/validate/PropertyValidateFacetViaMethod.java b/core/metamodel/src/main/java/org/apache/isis/core/progmodel/facets/properties/validate/PropertyValidateFacetViaMethod.java
index 0df3e71..1f9718a 100644
--- a/core/metamodel/src/main/java/org/apache/isis/core/progmodel/facets/properties/validate/PropertyValidateFacetViaMethod.java
+++ b/core/metamodel/src/main/java/org/apache/isis/core/progmodel/facets/properties/validate/PropertyValidateFacetViaMethod.java
@@ -27,6 +27,7 @@ import org.apache.isis.core.metamodel.adapter.ObjectAdapter;
 import org.apache.isis.core.metamodel.adapter.util.AdapterInvokeUtils;
 import org.apache.isis.core.metamodel.facetapi.FacetHolder;
 import org.apache.isis.core.metamodel.facets.ImperativeFacet;
+import org.apache.isis.core.metamodel.facets.ImperativeFacet.Intent;
 
 public class PropertyValidateFacetViaMethod extends PropertyValidateFacetAbstract implements ImperativeFacet {
 
@@ -47,6 +48,11 @@ public class PropertyValidateFacetViaMethod extends PropertyValidateFacetAbstrac
     }
 
     @Override
+    public Intent getIntent(final Method method) {
+        return Intent.CHECK_IF_VALID;
+    }
+
+    @Override
     public boolean impliesResolve() {
         return true;
     }

http://git-wip-us.apache.org/repos/asf/isis/blob/5f15fa74/core/metamodel/src/test/java/org/apache/isis/core/metamodel/facets/ImperativeFacetUtilsTest.java
----------------------------------------------------------------------
diff --git a/core/metamodel/src/test/java/org/apache/isis/core/metamodel/facets/ImperativeFacetUtilsTest.java b/core/metamodel/src/test/java/org/apache/isis/core/metamodel/facets/ImperativeFacetUtilsTest.java
index feee4dd..459484e 100644
--- a/core/metamodel/src/test/java/org/apache/isis/core/metamodel/facets/ImperativeFacetUtilsTest.java
+++ b/core/metamodel/src/test/java/org/apache/isis/core/metamodel/facets/ImperativeFacetUtilsTest.java
@@ -102,7 +102,7 @@ public class ImperativeFacetUtilsTest {
                 will(returnValue(Lists.newArrayList()));
             }
         });
-        final ImperativeFacet.Flags flags = ImperativeFacet.Util.getImperativeFacetFlags(mockObjectMember, method);
+        final ImperativeFacet.Flags flags = ImperativeFacet.Util.getFlags(mockObjectMember, method);
         assertThat(flags, is(not(nullValue())));
         assertThat(flags.impliesResolve(), is(false));
         assertThat(flags.impliesObjectChanged(), is(false));
@@ -117,7 +117,7 @@ public class ImperativeFacetUtilsTest {
                 will(returnValue(Lists.newArrayList((Facet) mockImperativeFacet)));
             }
         });
-        final ImperativeFacet.Flags flags = ImperativeFacet.Util.getImperativeFacetFlags(mockObjectMember, method);
+        final ImperativeFacet.Flags flags = ImperativeFacet.Util.getFlags(mockObjectMember, method);
         assertThat(flags, is(not(nullValue())));
         // TODO: need more tests here, these don't go deep enough...
     }

http://git-wip-us.apache.org/repos/asf/isis/blob/5f15fa74/core/metamodel/src/test/java/org/apache/isis/core/metamodel/facets/properties/event/PostsPropertyChangedEventFacet_UtilTest_newEvent.java
----------------------------------------------------------------------
diff --git a/core/metamodel/src/test/java/org/apache/isis/core/metamodel/facets/properties/event/PostsPropertyChangedEventFacet_UtilTest_newEvent.java b/core/metamodel/src/test/java/org/apache/isis/core/metamodel/facets/properties/event/PostsPropertyChangedEventFacet_UtilTest_newEvent.java
index 2f554fe..c67013d 100644
--- a/core/metamodel/src/test/java/org/apache/isis/core/metamodel/facets/properties/event/PostsPropertyChangedEventFacet_UtilTest_newEvent.java
+++ b/core/metamodel/src/test/java/org/apache/isis/core/metamodel/facets/properties/event/PostsPropertyChangedEventFacet_UtilTest_newEvent.java
@@ -24,7 +24,7 @@ import org.junit.Test;
 
 import org.apache.isis.applib.Identifier;
 import org.apache.isis.applib.services.eventbus.PropertyChangedEvent;
-import org.apache.isis.core.metamodel.facets.properties.event.PostsPropertyChangedEventFacetAbstract;
+import org.apache.isis.core.metamodel.facets.properties.event.PostsPropertyChangedEventSetterFacetAbstract;
 
 public class PostsPropertyChangedEventFacet_UtilTest_newEvent {
 
@@ -46,7 +46,7 @@ public class PostsPropertyChangedEventFacet_UtilTest_newEvent {
         LocalDate newValue = new LocalDate(2013,5,2);
         
         final PropertyChangedEvent<Object, Object> ev = 
-                PostsPropertyChangedEventFacet.Util.newEvent(PropertyChangedEvent.Default.class, sdo, identifier, oldValue, newValue);
+                PostsPropertyChangedEventSetterFacet.Util.newEvent(PropertyChangedEvent.Default.class, sdo, identifier, oldValue, newValue);
         assertThat(ev.getSource(), is((Object)sdo));
         assertThat(ev.getIdentifier(), is(identifier));
         assertThat(ev.getOldValue(), is((Object)oldValue));
@@ -63,7 +63,7 @@ public class PostsPropertyChangedEventFacet_UtilTest_newEvent {
         LocalDate newValue = new LocalDate(2013,5,2);
         
         final PropertyChangedEvent<SomeDomainObject, LocalDate> ev = 
-                PostsPropertyChangedEventFacet.Util.newEvent(SomeDatePropertyChangedEvent.class, sdo, identifier, oldValue, newValue);
+                PostsPropertyChangedEventSetterFacet.Util.newEvent(SomeDatePropertyChangedEvent.class, sdo, identifier, oldValue, newValue);
         assertThat(ev.getSource(), is(sdo));
         assertThat(ev.getIdentifier(), is(identifier));
         assertThat(ev.getOldValue(), is(oldValue));

http://git-wip-us.apache.org/repos/asf/isis/blob/5f15fa74/core/runtime/src/main/java/org/apache/isis/core/runtime/services/eventbus/EventBusServiceDefault.java
----------------------------------------------------------------------
diff --git a/core/runtime/src/main/java/org/apache/isis/core/runtime/services/eventbus/EventBusServiceDefault.java b/core/runtime/src/main/java/org/apache/isis/core/runtime/services/eventbus/EventBusServiceDefault.java
index f689a55..955fb7f 100644
--- a/core/runtime/src/main/java/org/apache/isis/core/runtime/services/eventbus/EventBusServiceDefault.java
+++ b/core/runtime/src/main/java/org/apache/isis/core/runtime/services/eventbus/EventBusServiceDefault.java
@@ -25,7 +25,6 @@ import org.apache.isis.applib.services.eventbus.EventBusService;
 import org.apache.isis.core.runtime.system.context.IsisContext;
 
 public class EventBusServiceDefault extends EventBusService {
-
     
     private final Set<Object> objectsToRegister = Sets.newHashSet();
     
@@ -52,12 +51,14 @@ public class EventBusServiceDefault extends EventBusService {
     }
 
     public void open() {
+        final Set<Object> objectsToRegister = this.objectsToRegister;
         for (final Object object : objectsToRegister) {
             getEventBus().register(object);
         }
     }
 
     public void close() {
+        final Set<Object> objectsToRegister = this.objectsToRegister;
         for (final Object object : objectsToRegister) {
             getEventBus().unregister(object);
         }

http://git-wip-us.apache.org/repos/asf/isis/blob/5f15fa74/core/runtime/src/main/java/org/apache/isis/core/runtime/system/persistence/PersistenceSession.java
----------------------------------------------------------------------
diff --git a/core/runtime/src/main/java/org/apache/isis/core/runtime/system/persistence/PersistenceSession.java b/core/runtime/src/main/java/org/apache/isis/core/runtime/system/persistence/PersistenceSession.java
index 0c2a6c8..9cdddb5 100644
--- a/core/runtime/src/main/java/org/apache/isis/core/runtime/system/persistence/PersistenceSession.java
+++ b/core/runtime/src/main/java/org/apache/isis/core/runtime/system/persistence/PersistenceSession.java
@@ -240,13 +240,7 @@ public class PersistenceSession implements Persistor, EnlistedObjectDirtying, To
 
         final List<Object> registeredServices = servicesInjector.getRegisteredServices();
         
-        startRequestOnRequestScopedServices(registeredServices);
-
-        createCommandIfConfigured();
-        
         createServiceAdapters(registeredServices);
-        
-        initOtherApplibServicesIfConfigured(registeredServices);
     }
 
     /**
@@ -274,67 +268,6 @@ public class PersistenceSession implements Persistor, EnlistedObjectDirtying, To
         }
     }
 
-    private void initOtherApplibServicesIfConfigured(final List<Object> registeredServices) {
-        
-        final EventBusServiceDefault ebsd = getServiceOrNull(EventBusServiceDefault.class);
-        if(ebsd != null) {
-            ebsd.open();
-        }
-        
-        final Bulk.InteractionContext bic = getServiceOrNull(Bulk.InteractionContext.class);
-        if(bic != null) {
-            Bulk.InteractionContext.current.set(bic);
-        }
-        
-    }
-
-    private void startRequestOnRequestScopedServices(final List<Object> registeredServices) {
-        for (final Object service : registeredServices) {
-            if(service instanceof RequestScopedService) {
-                ((RequestScopedService)service).__isis_startRequest();
-            }
-        }
-    }
-
-    private void createCommandIfConfigured() {
-        final CommandContext commandContext = getServiceOrNull(CommandContext.class);
-        if(commandContext == null) {
-            return;
-        } 
-        final CommandService commandService = getServiceOrNull(CommandService.class);
-        final Command command = 
-                commandService != null 
-                    ? commandService.create() 
-                    : new CommandDefault();
-        commandContext.setCommand(command);
-
-        if(command.getTimestamp() == null) {
-            command.setTimestamp(Clock.getTimeAsJavaSqlTimestamp());
-        }
-        if(command.getUser() == null) {
-            command.setUser(getAuthenticationSession().getUserName());
-        }
-        
-        // the remaining properties are set further down the call-stack, if an action is actually performed
-    }
-
-
-    /**
-     * Called by IsisTransactionManager on start
-     */
-    public void startTransactionOnCommandIfConfigured(final UUID transactionId) {
-        final CommandContext commandContext = getServiceOrNull(CommandContext.class);
-        if(commandContext == null) {
-            return;
-        } 
-        final CommandService commandService = getServiceOrNull(CommandService.class);
-        if(commandService == null) {
-            return;
-        } 
-        final Command command = commandContext.getCommand();
-        commandService.startTransaction(command, transactionId);
-    }
-
 
     /**
      * @return - the service, or <tt>null</tt> if no service registered of specified type.
@@ -382,20 +315,10 @@ public class PersistenceSession implements Persistor, EnlistedObjectDirtying, To
             // ignore
         }
 
-        endRequestOnRequestScopeServices();
-        
         setState(State.CLOSED);
     }
 
 
-    private void endRequestOnRequestScopeServices() {
-        for (final Object service : servicesInjector.getRegisteredServices()) {
-            if(service instanceof RequestScopedService) {
-                ((RequestScopedService)service).__isis_endRequest();
-            }
-        }
-    }
-
     // ///////////////////////////////////////////////////////////////////////////
     // State Management
     // ///////////////////////////////////////////////////////////////////////////

http://git-wip-us.apache.org/repos/asf/isis/blob/5f15fa74/core/runtime/src/main/java/org/apache/isis/core/runtime/system/transaction/IsisTransactionManager.java
----------------------------------------------------------------------
diff --git a/core/runtime/src/main/java/org/apache/isis/core/runtime/system/transaction/IsisTransactionManager.java b/core/runtime/src/main/java/org/apache/isis/core/runtime/system/transaction/IsisTransactionManager.java
index 1ac5b64..a7a9d17 100644
--- a/core/runtime/src/main/java/org/apache/isis/core/runtime/system/transaction/IsisTransactionManager.java
+++ b/core/runtime/src/main/java/org/apache/isis/core/runtime/system/transaction/IsisTransactionManager.java
@@ -27,16 +27,22 @@ import static org.hamcrest.CoreMatchers.notNullValue;
 import static org.hamcrest.CoreMatchers.nullValue;
 
 import java.util.List;
+import java.util.UUID;
 
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
 import org.apache.isis.applib.Identifier;
+import org.apache.isis.applib.annotation.Bulk;
 import org.apache.isis.applib.annotation.PublishedAction;
 import org.apache.isis.applib.annotation.PublishedObject;
 import org.apache.isis.applib.annotation.PublishedObject.ChangeKind;
+import org.apache.isis.applib.clock.Clock;
 import org.apache.isis.applib.services.audit.AuditingService3;
+import org.apache.isis.applib.services.command.Command;
 import org.apache.isis.applib.services.command.CommandContext;
+import org.apache.isis.applib.services.command.CommandDefault;
+import org.apache.isis.applib.services.command.spi.CommandService;
 import org.apache.isis.applib.services.publish.EventPayload;
 import org.apache.isis.applib.services.publish.EventPayloadForActionInvocation;
 import org.apache.isis.applib.services.publish.EventPayloadForObjectChanged;
@@ -53,6 +59,8 @@ import org.apache.isis.core.metamodel.services.ServicesInjectorSpi;
 import org.apache.isis.core.runtime.persistence.objectstore.transaction.PersistenceCommand;
 import org.apache.isis.core.runtime.persistence.objectstore.transaction.PublishingServiceWithDefaultPayloadFactories;
 import org.apache.isis.core.runtime.persistence.objectstore.transaction.TransactionalResource;
+import org.apache.isis.core.runtime.services.RequestScopedService;
+import org.apache.isis.core.runtime.services.eventbus.EventBusServiceDefault;
 import org.apache.isis.core.runtime.system.context.IsisContext;
 import org.apache.isis.core.runtime.system.persistence.PersistenceSession;
 import org.apache.isis.core.runtime.system.session.IsisSession;
@@ -262,7 +270,7 @@ public class IsisTransactionManager implements SessionScopedComponent {
     
 
     // //////////////////////////////////////////////////////
-    // start, flush, abort, end
+    // start
     // //////////////////////////////////////////////////////
 
     public synchronized void startTransaction() {
@@ -271,12 +279,18 @@ public class IsisTransactionManager implements SessionScopedComponent {
         if (getTransaction() == null || getTransaction().getState().isComplete()) {
             noneInProgress = true;
 
+            final List<Object> registeredServices = servicesInjector.getRegisteredServices();
+
+            startRequestOnRequestScopedServices(registeredServices);
+            createCommandIfConfigured();
+            initOtherApplibServicesIfConfigured(registeredServices);
+            
             IsisTransaction isisTransaction = createTransaction();
             transactionLevel = 0;
 
             transactionalResource.startTransaction();
-            
-            persistenceSession.startTransactionOnCommandIfConfigured(isisTransaction.getTransactionId());
+
+            startTransactionOnCommandIfConfigured(isisTransaction.getTransactionId());
         }
 
         transactionLevel++;
@@ -286,6 +300,88 @@ public class IsisTransactionManager implements SessionScopedComponent {
         }
     }
 
+    
+    private void initOtherApplibServicesIfConfigured(final List<Object> registeredServices) {
+        
+        final EventBusServiceDefault ebsd = getServiceOrNull(EventBusServiceDefault.class);
+        if(ebsd != null) {
+            ebsd.open();
+        }
+        
+        final Bulk.InteractionContext bic = getServiceOrNull(Bulk.InteractionContext.class);
+        if(bic != null) {
+            Bulk.InteractionContext.current.set(bic);
+        }
+        
+    }
+
+    private void startRequestOnRequestScopedServices(final List<Object> registeredServices) {
+        for (final Object service : registeredServices) {
+            if(service instanceof RequestScopedService) {
+                ((RequestScopedService)service).__isis_startRequest();
+            }
+        }
+    }
+
+    private void endRequestOnRequestScopeServices() {
+        for (final Object service : servicesInjector.getRegisteredServices()) {
+            if(service instanceof RequestScopedService) {
+                ((RequestScopedService)service).__isis_endRequest();
+            }
+        }
+    }
+
+    private void createCommandIfConfigured() {
+        final CommandContext commandContext = getServiceOrNull(CommandContext.class);
+        if(commandContext == null) {
+            return;
+        } 
+        final CommandService commandService = getServiceOrNull(CommandService.class);
+        final Command command = 
+                commandService != null 
+                    ? commandService.create() 
+                    : new CommandDefault();
+        commandContext.setCommand(command);
+
+        if(command.getTimestamp() == null) {
+            command.setTimestamp(Clock.getTimeAsJavaSqlTimestamp());
+        }
+        if(command.getUser() == null) {
+            command.setUser(getAuthenticationSession().getUserName());
+        }
+        
+        // the remaining properties are set further down the call-stack, if an action is actually performed
+    }
+
+    /**
+     * Called by IsisTransactionManager on start
+     */
+    public void startTransactionOnCommandIfConfigured(final UUID transactionId) {
+        final CommandContext commandContext = getServiceOrNull(CommandContext.class);
+        if(commandContext == null) {
+            return;
+        } 
+        final CommandService commandService = getServiceOrNull(CommandService.class);
+        if(commandService == null) {
+            return;
+        } 
+        final Command command = commandContext.getCommand();
+        commandService.startTransaction(command, transactionId);
+    }
+
+
+    /**
+     * @return - the service, or <tt>null</tt> if no service registered of specified type.
+     */
+    public <T> T getServiceOrNull(Class<T> serviceType) {
+        return servicesInjector.lookupService(serviceType);
+    }
+
+
+
+    // //////////////////////////////////////////////////////
+    // flush
+    // //////////////////////////////////////////////////////
 
     public synchronized boolean flushTransaction() {
 
@@ -300,6 +396,10 @@ public class IsisTransactionManager implements SessionScopedComponent {
         return false;
     }
 
+    // //////////////////////////////////////////////////////
+    // end, abort
+    // //////////////////////////////////////////////////////
+
     /**
      * Ends the transaction if nesting level is 0 (but will abort the transaction instead, 
      * even if nesting level is not 0, if an {@link IsisTransaction#getAbortCause() abort cause}
@@ -411,6 +511,8 @@ public class IsisTransactionManager implements SessionScopedComponent {
                 }
             }
             
+            
+            endRequestOnRequestScopeServices();
 
             if(abortCause != null) {
                 

http://git-wip-us.apache.org/repos/asf/isis/blob/5f15fa74/core/runtime/src/test/java/org/apache/isis/core/runtime/persistence/objectstore/transaction/ObjectStoreTransactionManager_EndTransactionTest.java
----------------------------------------------------------------------
diff --git a/core/runtime/src/test/java/org/apache/isis/core/runtime/persistence/objectstore/transaction/ObjectStoreTransactionManager_EndTransactionTest.java b/core/runtime/src/test/java/org/apache/isis/core/runtime/persistence/objectstore/transaction/ObjectStoreTransactionManager_EndTransactionTest.java
index 68eca35..baa6080 100644
--- a/core/runtime/src/test/java/org/apache/isis/core/runtime/persistence/objectstore/transaction/ObjectStoreTransactionManager_EndTransactionTest.java
+++ b/core/runtime/src/test/java/org/apache/isis/core/runtime/persistence/objectstore/transaction/ObjectStoreTransactionManager_EndTransactionTest.java
@@ -110,14 +110,8 @@ public class ObjectStoreTransactionManager_EndTransactionTest {
     public void endTransactionCommitsTransactionWhenLevelDecrementsDownToZero() throws Exception {
         // setup
         context.ignoring(mockObjectStore);
-        context.checking(new Expectations() {
-            {
-                oneOf(mockPersistenceSession).startTransactionOnCommandIfConfigured(with(any(UUID.class)));
-            }
-        });
         transactionManager.startTransaction();
 
-        
         context.checking(new Expectations() {
             {
                 oneOf(mockPersistenceSession).objectChangedAllDirty();
@@ -150,7 +144,7 @@ public class ObjectStoreTransactionManager_EndTransactionTest {
         context.checking(new Expectations() {
             {
                 final Sequence transactionOrdering = context.sequence("transactionOrdering");
-                one(mockObjectStore).startTransaction();
+                oneOf(mockObjectStore).startTransaction();
                 inSequence(transactionOrdering);
 
                 // flushed twice, once before publishing, once after

http://git-wip-us.apache.org/repos/asf/isis/blob/5f15fa74/core/wrapper/src/main/java/org/apache/isis/core/wrapper/handlers/DomainObjectInvocationHandler.java
----------------------------------------------------------------------
diff --git a/core/wrapper/src/main/java/org/apache/isis/core/wrapper/handlers/DomainObjectInvocationHandler.java b/core/wrapper/src/main/java/org/apache/isis/core/wrapper/handlers/DomainObjectInvocationHandler.java
index 01b03a0..aa7b320 100644
--- a/core/wrapper/src/main/java/org/apache/isis/core/wrapper/handlers/DomainObjectInvocationHandler.java
+++ b/core/wrapper/src/main/java/org/apache/isis/core/wrapper/handlers/DomainObjectInvocationHandler.java
@@ -54,6 +54,7 @@ import org.apache.isis.core.metamodel.consent.InteractionResult;
 import org.apache.isis.core.metamodel.facetapi.DecoratingFacet;
 import org.apache.isis.core.metamodel.facetapi.Facet;
 import org.apache.isis.core.metamodel.facets.ImperativeFacet;
+import org.apache.isis.core.metamodel.facets.ImperativeFacet.Intent;
 import org.apache.isis.core.metamodel.facets.accessor.PropertyOrCollectionAccessorFacet;
 import org.apache.isis.core.metamodel.facets.actions.choices.ActionChoicesFacet;
 import org.apache.isis.core.metamodel.facets.actions.defaults.ActionDefaultsFacet;
@@ -105,7 +106,7 @@ public class DomainObjectInvocationHandler<T> extends DelegatingInvocationHandle
     protected Method saveMethod;
 
     /**
-     * The <tt>underlying()</tt> method from {@link WrapperObject#wrapped()}.
+     * The <tt>wrapped()</tt> method from {@link WrapperObject#wrapped()}.
      */
     protected Method wrappedMethod;
 
@@ -150,7 +151,6 @@ public class DomainObjectInvocationHandler<T> extends DelegatingInvocationHandle
         }
 
 
-
         final ObjectSpecification targetNoSpec = targetAdapter.getSpecification();
 
         // save method, through the proxy
@@ -158,81 +158,65 @@ public class DomainObjectInvocationHandler<T> extends DelegatingInvocationHandle
             return handleSaveMethod(getAuthenticationSession(), targetAdapter, targetNoSpec);
         }
 
-        if (isUnderlyingMethod(method)) {
+        if (isWrappedMethod(method)) {
             return getDelegate();
         }
 
         final ObjectMember objectMember = locateAndCheckMember(method);
-        final List<Facet> imperativeFacets = getImperativeFacets(objectMember, method);
 
         final String memberName = objectMember.getName();
 
-        if (instanceOf(imperativeFacets, DisableForContextFacetViaMethod.class, HideForContextFacetViaMethod.class)) {
+        final Intent intent = ImperativeFacet.Util.getIntent(objectMember, method);
+        if(intent == Intent.CHECK_IF_HIDDEN || intent == Intent.CHECK_IF_DISABLED) {
             throw new UnsupportedOperationException(String.format("Cannot invoke supporting method '%s'", memberName));
         }
 
         final String methodName = method.getName();
 
-        if (instanceOf(imperativeFacets, ActionDefaultsFacet.class, PropertyDefaultFacet.class, ActionChoicesFacet.class, ActionParameterChoicesFacet.class, PropertyChoicesFacet.class)) {
+        if (intent == Intent.DEFAULTS || intent == Intent.CHOICES_OR_AUTOCOMPLETE) {
             return method.invoke(getDelegate(), args);
         }
 
         if (objectMember.isOneToOneAssociation()) {
 
-            if (instanceOf(imperativeFacets, PropertyValidateFacetViaMethod.class, PropertySetterFacetViaModifyMethod.class, PropertyClearFacetViaClearMethod.class)) {
+            if (intent == Intent.CHECK_IF_VALID || intent == Intent.MODIFY_PROPERTY_SUPPORTING) {
                 throw new UnsupportedOperationException(String.format("Cannot invoke supporting method for '%s'; use only property accessor/mutator", memberName));
             }
 
             final OneToOneAssociation otoa = (OneToOneAssociation) objectMember;
             
-            if (instanceOf(imperativeFacets, PropertyOrCollectionAccessorFacet.class)) {
+            if (intent == Intent.ACCESSOR) {
                 return handleGetterMethodOnProperty(args, targetAdapter, otoa, methodName);
             }
             
-            if (instanceOf(imperativeFacets, PropertySetterFacet.class, PropertyInitializationFacet.class)) {
+            if (intent == Intent.MODIFY_PROPERTY || intent == Intent.INITIALIZATION) {
                 return handleSetterMethodOnProperty(args, getAuthenticationSession(), targetAdapter, otoa, methodName);
             }
         }
         if (objectMember.isOneToManyAssociation()) {
 
-            if (instanceOf(imperativeFacets, CollectionValidateAddToFacetViaMethod.class, CollectionValidateRemoveFromFacetViaMethod.class)) {
+            if (intent == Intent.CHECK_IF_VALID) {
                 throw new UnsupportedOperationException(String.format("Cannot invoke supporting method '%s'; use only collection accessor/mutator", memberName));
             }
 
-
             final OneToManyAssociation otma = (OneToManyAssociation) objectMember;
-            if (instanceOf(imperativeFacets, PropertyOrCollectionAccessorFacet.class)) {
+            if (intent == Intent.ACCESSOR) {
                 return handleGetterMethodOnCollection(method, args, targetAdapter, otma, memberName);
             }
-            if (instanceOf(imperativeFacets, CollectionAddToFacet.class)) {
+            if (intent == Intent.MODIFY_COLLECTION_ADD) {
                 return handleCollectionAddToMethod(args, targetAdapter, otma, methodName);
             }
-            if (instanceOf(imperativeFacets, CollectionRemoveFromFacet.class)) {
+            if (intent == Intent.MODIFY_COLLECTION_REMOVE) {
                 return handleCollectionRemoveFromMethod(args, targetAdapter, otma, methodName);
             }
         }
 
-        // filter out
-        if (instanceOf(imperativeFacets, PropertyOrCollectionAccessorFacet.class)) {
-            throw new UnsupportedOperationException(String.format("Can only invoke accessor on properties or collections; '%s' represents %s", methodName, decode(objectMember)));
-        }
-        if (instanceOf(imperativeFacets, PropertySetterFacet.class)) {
-            throw new UnsupportedOperationException(String.format("Can only invoke mutator on properties; '%s' represents %s", methodName, decode(objectMember)));
-        }
-        if (instanceOf(imperativeFacets, CollectionAddToFacet.class)) {
-            throw new UnsupportedOperationException(String.format("Can only invoke 'adder' on collections; '%s' represents %s", methodName, decode(objectMember)));
-        }
-        if (instanceOf(imperativeFacets, CollectionRemoveFromFacet.class)) {
-            throw new UnsupportedOperationException(String.format("Can only invoke 'remover' on collections; '%s' represents %s", methodName, decode(objectMember)));
-        }
-
         if (objectMember instanceof ObjectAction) {
 
             // for all members, check visibility and usability
             checkVisibility(getAuthenticationSession(), targetAdapter, objectMember);
 
-
-            if (instanceOf(imperativeFacets, ActionValidationFacetViaMethod.class)) {
+            if (intent == Intent.CHECK_IF_VALID) {
                 throw new UnsupportedOperationException(String.format("Cannot invoke supporting method '%s'; use only the 'invoke' method", memberName));
             }
 
@@ -289,8 +273,9 @@ public class DomainObjectInvocationHandler<T> extends DelegatingInvocationHandle
 
     private static boolean instanceOf(final List<?> objects, final Class<?>... superTypes) {
         for (final Class<?> superType : superTypes) {
+            // REVIEW: this is all a bit hacky...
             for (Object obj : objects) {
-                // handle the *WrapTransaction facets etc
+                // handle the *decorators
                 if(obj instanceof DecoratingFacet) {
                     DecoratingFacet<?> decoratingFacet = (DecoratingFacet<?>) obj;
                     obj = ((DecoratingFacet<?>) obj).getDecoratedFacet();
@@ -298,6 +283,14 @@ public class DomainObjectInvocationHandler<T> extends DelegatingInvocationHandle
                 if (superType.isAssignableFrom(obj.getClass())) {
                     return true;
                 }
+                if(obj instanceof Facet) {
+                    Facet facet = (Facet) obj;
+                    // handle any wrapping (eg PostPropertyChangedSetterEventFacet)
+                    Facet underlyingFacet = facet.getUnderlyingFacet();
+                    if(underlyingFacet != null && superType.isAssignableFrom(obj.getClass())) {
+                        return true;
+                    }
+                }
             }
         }
         return false;
@@ -662,7 +655,7 @@ public class DomainObjectInvocationHandler<T> extends DelegatingInvocationHandle
         return method.equals(saveMethod);
     }
 
-    protected boolean isUnderlyingMethod(final Method method) {
+    protected boolean isWrappedMethod(final Method method) {
         return method.equals(wrappedMethod);
     }