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 2015/10/09 19:00:32 UTC

[2/3] isis git commit: ISIS-1211: no-arg versions of domain events, to reduce boilerplate.

ISIS-1211: no-arg versions of domain events, to reduce boilerplate.


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

Branch: refs/heads/master
Commit: c5aeadd2bdb982971bd6e21f31cfad96cc93f290
Parents: 6ad9088
Author: Dan Haywood <da...@haywood-associates.co.uk>
Authored: Fri Oct 9 17:33:51 2015 +0100
Committer: Dan Haywood <da...@haywood-associates.co.uk>
Committed: Fri Oct 9 17:33:51 2015 +0100

----------------------------------------------------------------------
 .../apache/isis/applib/IsisApplibModule.java    | 36 +++++++++++--
 .../services/eventbus/AbstractDomainEvent.java  | 37 ++++++++++++-
 .../eventbus/AbstractInteractionEvent.java      |  5 ++
 .../services/eventbus/ActionDomainEvent.java    | 32 ++++++++++-
 .../eventbus/CollectionDomainEvent.java         | 19 +++++++
 .../services/eventbus/PropertyDomainEvent.java  | 19 +++++++
 .../metamodel/facets/DomainEventHelper.java     | 56 ++++++++++++++++++++
 .../java/domainapp/dom/simple/SimpleObject.java | 48 +++++------------
 8 files changed, 210 insertions(+), 42 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/isis/blob/c5aeadd2/core/applib/src/main/java/org/apache/isis/applib/IsisApplibModule.java
----------------------------------------------------------------------
diff --git a/core/applib/src/main/java/org/apache/isis/applib/IsisApplibModule.java b/core/applib/src/main/java/org/apache/isis/applib/IsisApplibModule.java
index fa728f9..6209d50 100644
--- a/core/applib/src/main/java/org/apache/isis/applib/IsisApplibModule.java
+++ b/core/applib/src/main/java/org/apache/isis/applib/IsisApplibModule.java
@@ -25,34 +25,62 @@ public final class IsisApplibModule {
     private IsisApplibModule(){}
 
     public abstract static class ActionDomainEvent<S> extends org.apache.isis.applib.services.eventbus.ActionDomainEvent<S> {
+        public ActionDomainEvent() {}
+
+        /**
+         * @deprecated - use the {@link #ActionDomainEvent() no-arg constructor} instead to avoid boilerplate.
+         */
+        @Deprecated
         public ActionDomainEvent(final S source, final Identifier identifier) {
             super(source, identifier);
         }
-
+        /**
+         * @deprecated - use the {@link #ActionDomainEvent() no-arg constructor} instead to avoid boilerplate.
+         */
+        @Deprecated
         public ActionDomainEvent(final S source, final Identifier identifier, final Object... arguments) {
             super(source, identifier, arguments);
         }
-
+        /**
+         * @deprecated - use the {@link #ActionDomainEvent() no-arg constructor} instead to avoid boilerplate.
+         */
+        @Deprecated
         public ActionDomainEvent(final S source, final Identifier identifier, final List<Object> arguments) {
             super(source, identifier, arguments);
         }
     }
 
     public abstract static class CollectionDomainEvent<S,T> extends org.apache.isis.applib.services.eventbus.CollectionDomainEvent<S,T> {
+        public CollectionDomainEvent() { }
+        /**
+         * @deprecated - use the {@link #CollectionDomainEvent() no-arg constructor} instead to avoid boilerplate.
+         */
+        @Deprecated
         public CollectionDomainEvent(final S source, final Identifier identifier, final Of of) {
             super(source, identifier, of);
         }
-    
+        /**
+         * @deprecated - use the {@link #CollectionDomainEvent() no-arg constructor} instead to avoid boilerplate.
+         */
+        @Deprecated
         public CollectionDomainEvent(final S source, final Identifier identifier, final Of of, final T value) {
             super(source, identifier, of, value);
         }
     }
 
     public abstract static class PropertyDomainEvent<S,T> extends org.apache.isis.applib.services.eventbus.PropertyDomainEvent<S,T> {
+        public PropertyDomainEvent() { }
+        /**
+         * @deprecated - use the {@link #PropertyDomainEvent() no-arg constructor} instead to avoid boilerplate.
+         */
+        @Deprecated
         public PropertyDomainEvent(final S source, final Identifier identifier) {
             super(source, identifier);
         }
-
+        /**
+         * @deprecated - use the {@link #PropertyDomainEvent() no-arg constructor} instead to avoid boilerplate.
+         */
+        @Deprecated
         public PropertyDomainEvent(final S source, final Identifier identifier, final T oldValue, final T newValue) {
             super(source, identifier, oldValue, newValue);
         }

http://git-wip-us.apache.org/repos/asf/isis/blob/c5aeadd2/core/applib/src/main/java/org/apache/isis/applib/services/eventbus/AbstractDomainEvent.java
----------------------------------------------------------------------
diff --git a/core/applib/src/main/java/org/apache/isis/applib/services/eventbus/AbstractDomainEvent.java b/core/applib/src/main/java/org/apache/isis/applib/services/eventbus/AbstractDomainEvent.java
index 1e74584..cab9149 100644
--- a/core/applib/src/main/java/org/apache/isis/applib/services/eventbus/AbstractDomainEvent.java
+++ b/core/applib/src/main/java/org/apache/isis/applib/services/eventbus/AbstractDomainEvent.java
@@ -18,6 +18,7 @@
  */
 package org.apache.isis.applib.services.eventbus;
 
+import java.util.EventObject;
 import java.util.Map;
 import com.google.common.collect.Maps;
 import org.apache.isis.applib.Identifier;
@@ -29,13 +30,28 @@ public abstract class AbstractDomainEvent<S> extends java.util.EventObject {
 
     private static final long serialVersionUID = 1L;
 
+    /**
+     * If used then the framework will set state via (non-API) setters.
+     *
+     * <p>
+     *     Because the {@link EventObject} superclass prohibits a null source, a dummy value is temporarily used.
+     * </p>
+     */
+    public AbstractDomainEvent() {
+        this(null, null);
+    }
+
     public AbstractDomainEvent(
             final S source,
             final Identifier identifier) {
-        super(source);
+        super(sourceElseDummy(source));
         this.identifier = identifier;
     }
 
+    private static Object sourceElseDummy(final Object source) {
+        return source != null ? source : new Object();
+    }
+
     //region > Phase
 
     public enum Phase {
@@ -94,13 +110,30 @@ public abstract class AbstractDomainEvent<S> extends java.util.EventObject {
     public S getSource() {
         return (S)source;
     }
+
+    /**
+     * Not API, set by the framework if the no-arg constructor is used.
+     */
+    public void setSource(S source) {
+        this.source = source;
+    }
     //endregion
 
     //region > identifier
-    private final Identifier identifier;
+    /**
+     * If the no-arg constructor is used, then the framework will populate this field reflectively.
+     */
+    private Identifier identifier;
     public Identifier getIdentifier() {
         return identifier;
     }
+
+    /**
+     * Not API, set by the framework if the no-arg constructor is used.
+     */
+    public void setIdentifier(final Identifier identifier) {
+        this.identifier = identifier;
+    }
     //endregion
 
     //region > hide, isHidden

http://git-wip-us.apache.org/repos/asf/isis/blob/c5aeadd2/core/applib/src/main/java/org/apache/isis/applib/services/eventbus/AbstractInteractionEvent.java
----------------------------------------------------------------------
diff --git a/core/applib/src/main/java/org/apache/isis/applib/services/eventbus/AbstractInteractionEvent.java b/core/applib/src/main/java/org/apache/isis/applib/services/eventbus/AbstractInteractionEvent.java
index 8762844..8e14186 100644
--- a/core/applib/src/main/java/org/apache/isis/applib/services/eventbus/AbstractInteractionEvent.java
+++ b/core/applib/src/main/java/org/apache/isis/applib/services/eventbus/AbstractInteractionEvent.java
@@ -27,6 +27,11 @@ import org.apache.isis.applib.Identifier;
 @Deprecated
 public abstract class AbstractInteractionEvent<S> extends AbstractDomainEvent<S> {
 
+    /**
+     * If used then the framework will set state via (non-API) setters.
+     */
+    public AbstractInteractionEvent() {}
+
     public AbstractInteractionEvent(
             final S source,
             final Identifier identifier) {

http://git-wip-us.apache.org/repos/asf/isis/blob/c5aeadd2/core/applib/src/main/java/org/apache/isis/applib/services/eventbus/ActionDomainEvent.java
----------------------------------------------------------------------
diff --git a/core/applib/src/main/java/org/apache/isis/applib/services/eventbus/ActionDomainEvent.java b/core/applib/src/main/java/org/apache/isis/applib/services/eventbus/ActionDomainEvent.java
index 895e3a5..17d6f7c 100644
--- a/core/applib/src/main/java/org/apache/isis/applib/services/eventbus/ActionDomainEvent.java
+++ b/core/applib/src/main/java/org/apache/isis/applib/services/eventbus/ActionDomainEvent.java
@@ -46,19 +46,49 @@ public abstract class ActionDomainEvent<S> extends AbstractInteractionEvent<S> {
     //endregion
 
     //region > constructors
+
+    /**
+     * If used then the framework will set state via (non-API) setters.
+     *
+     * <p>
+     *     Recommended because it reduces the amount of boilerplate in the domain object classes.
+     * </p>
+     */
+    public ActionDomainEvent() {
+    }
+
+    /**
+     * @deprecated - the {@link #ActionDomainEvent() no-arg constructor} is recommended instead, to reduce boilerplate.
+     */
+    @Deprecated
     public ActionDomainEvent(
             final S source,
             final Identifier identifier) {
         super(source, identifier);
     }
 
+    /**
+     * @deprecated - the {@link #ActionDomainEvent() no-arg constructor} is recommended instead, to reduce boilerplate.
+     */
+    @Deprecated
     public ActionDomainEvent(
             final S source,
             final Identifier identifier,
             final Object... arguments) {
-        this(source, identifier, arguments != null? Arrays.asList(arguments): Collections.emptyList());
+        this(source, identifier,
+                asList(arguments));
     }
 
+    private static List<Object> asList(final Object[] arguments) {
+        return arguments != null
+                ? Arrays.asList(arguments)
+                : Collections.emptyList();
+    }
+
+    /**
+     * @deprecated - the {@link #ActionDomainEvent() no-arg constructor} is recommended instead, to reduce boilerplate.
+     */
+    @Deprecated
     public ActionDomainEvent(
             final S source,
             final Identifier identifier,

http://git-wip-us.apache.org/repos/asf/isis/blob/c5aeadd2/core/applib/src/main/java/org/apache/isis/applib/services/eventbus/CollectionDomainEvent.java
----------------------------------------------------------------------
diff --git a/core/applib/src/main/java/org/apache/isis/applib/services/eventbus/CollectionDomainEvent.java b/core/applib/src/main/java/org/apache/isis/applib/services/eventbus/CollectionDomainEvent.java
index 9b6d567..c91daa7 100644
--- a/core/applib/src/main/java/org/apache/isis/applib/services/eventbus/CollectionDomainEvent.java
+++ b/core/applib/src/main/java/org/apache/isis/applib/services/eventbus/CollectionDomainEvent.java
@@ -43,6 +43,21 @@ public abstract class CollectionDomainEvent<S,T> extends AbstractInteractionEven
     //endregion
 
     //region > constructors
+
+    /**
+     * If used then the framework will set state via (non-API) setters.
+     *
+     * <p>
+     *     Recommended because it reduces the amount of boilerplate in the domain object classes.
+     * </p>
+     */
+    public CollectionDomainEvent() {
+    }
+
+    /**
+     * @deprecated - the {@link #CollectionDomainEvent() no-arg constructor} is recommended instead, to reduce boilerplate.
+     */
+    @Deprecated
     public CollectionDomainEvent(
             final S source,
             final Identifier identifier,
@@ -51,6 +66,10 @@ public abstract class CollectionDomainEvent<S,T> extends AbstractInteractionEven
         this.of = of;
     }
 
+    /**
+     * @deprecated - the {@link #CollectionDomainEvent() no-arg constructor} is recommended instead, to reduce boilerplate.
+     */
+    @Deprecated
     public CollectionDomainEvent(
             final S source,
             final Identifier identifier,

http://git-wip-us.apache.org/repos/asf/isis/blob/c5aeadd2/core/applib/src/main/java/org/apache/isis/applib/services/eventbus/PropertyDomainEvent.java
----------------------------------------------------------------------
diff --git a/core/applib/src/main/java/org/apache/isis/applib/services/eventbus/PropertyDomainEvent.java b/core/applib/src/main/java/org/apache/isis/applib/services/eventbus/PropertyDomainEvent.java
index 76a2883..b641276 100644
--- a/core/applib/src/main/java/org/apache/isis/applib/services/eventbus/PropertyDomainEvent.java
+++ b/core/applib/src/main/java/org/apache/isis/applib/services/eventbus/PropertyDomainEvent.java
@@ -39,12 +39,31 @@ public abstract class PropertyDomainEvent<S,T> extends AbstractInteractionEvent<
     //endregion
 
     //region > constructors
+
+    /**
+     * If used then the framework will set state via (non-API) setters.
+     *
+     * <p>
+     *     Recommended because it reduces the amount of boilerplate in the domain object classes.
+     * </p>
+     */
+    public PropertyDomainEvent() {
+    }
+
+    /**
+     * @deprecated - the {@link #PropertyDomainEvent() no-arg constructor} is recommended instead, to reduce boilerplate.
+     */
+    @Deprecated
     public PropertyDomainEvent(
             final S source,
             final Identifier identifier) {
         super(source, identifier);
     }
 
+    /**
+     * @deprecated - the {@link #PropertyDomainEvent() no-arg constructor} is recommended instead, to reduce boilerplate.
+     */
+    @Deprecated
     public PropertyDomainEvent(
             final S source,
             final Identifier identifier,

http://git-wip-us.apache.org/repos/asf/isis/blob/c5aeadd2/core/metamodel/src/main/java/org/apache/isis/core/metamodel/facets/DomainEventHelper.java
----------------------------------------------------------------------
diff --git a/core/metamodel/src/main/java/org/apache/isis/core/metamodel/facets/DomainEventHelper.java b/core/metamodel/src/main/java/org/apache/isis/core/metamodel/facets/DomainEventHelper.java
index 2744478..c5729f7 100644
--- a/core/metamodel/src/main/java/org/apache/isis/core/metamodel/facets/DomainEventHelper.java
+++ b/core/metamodel/src/main/java/org/apache/isis/core/metamodel/facets/DomainEventHelper.java
@@ -21,6 +21,7 @@ package org.apache.isis.core.metamodel.facets;
 
 import java.lang.reflect.Constructor;
 import java.lang.reflect.InvocationTargetException;
+import java.util.Arrays;
 import java.util.Collections;
 import java.util.List;
 
@@ -135,7 +136,24 @@ public class DomainEventHelper {
             final Identifier identifier,
             final S source,
             final Object... arguments) throws InstantiationException, IllegalAccessException, IllegalArgumentException, InvocationTargetException, NoSuchMethodException, SecurityException {
+
         final Constructor<?>[] constructors = type.getConstructors();
+
+        // no-arg constructor
+        for (final Constructor<?> constructor : constructors) {
+            final Class<?>[] parameterTypes = constructor.getParameterTypes();
+            if(parameterTypes.length == 0) {
+                final Object event = constructor.newInstance();
+                final ActionDomainEvent<S> ade = (ActionDomainEvent<S>) event;
+
+                ade.setSource(source);
+                ade.setIdentifier(identifier);
+                ade.setArguments(asList(arguments));
+                return ade;
+            }
+        }
+
+
         for (final Constructor<?> constructor : constructors) {
             final Class<?>[] parameterTypes = constructor.getParameterTypes();
             if(parameterTypes.length != 3) {
@@ -155,6 +173,13 @@ public class DomainEventHelper {
         }
         throw new NoSuchMethodException(type.getName()+".<init>(? super " + source.getClass().getName() + ", " + Identifier.class.getName() + ", [Ljava.lang.Object;)");
     }
+
+    // same as in ActionDomainEvent's constructor.
+    private static List<Object> asList(final Object[] arguments) {
+        return arguments != null
+                ? Arrays.asList(arguments)
+                : Collections.emptyList();
+    }
     //endregion
 
     //region > postEventForProperty, newPropertyInteraction
@@ -209,6 +234,22 @@ public class DomainEventHelper {
             final T newValue) throws NoSuchMethodException, SecurityException, InstantiationException, IllegalAccessException, IllegalArgumentException, InvocationTargetException  {
 
         final Constructor<?>[] constructors = type.getConstructors();
+
+        // no-arg constructor
+        for (final Constructor<?> constructor : constructors) {
+            final Class<?>[] parameterTypes = constructor.getParameterTypes();
+            if(parameterTypes.length == 0) {
+                final Object event = constructor.newInstance();
+                final PropertyDomainEvent<S, T> pde = (PropertyDomainEvent<S, T>) event;
+                pde.setSource(source);
+                pde.setIdentifier(identifier);
+                pde.setOldValue(oldValue);
+                pde.setNewValue(newValue);
+                return pde;
+            }
+        }
+
+        // else
         for (final Constructor<?> constructor : constructors) {
             final Class<?>[] parameterTypes = constructor.getParameterTypes();
             if(parameterTypes.length != 4) {
@@ -282,6 +323,21 @@ public class DomainEventHelper {
 
         final Constructor<?>[] constructors = type.getConstructors();
 
+        // no-arg constructor
+        for (final Constructor<?> constructor : constructors) {
+            final Class<?>[] parameterTypes = constructor.getParameterTypes();
+            if(parameterTypes.length ==0) {
+                final Object event = constructor.newInstance();
+                final CollectionDomainEvent<S, T> cde = (CollectionDomainEvent<S, T>) event;
+
+                cde.setSource(source);
+                cde.setIdentifier(identifier);
+                cde.setOf(of);
+                cde.setValue(value);
+                return cde;
+            }
+        }
+
         // search for constructor accepting source, identifier, type, value
         for (final Constructor<?> constructor : constructors) {
             final Class<?>[] parameterTypes = constructor.getParameterTypes();

http://git-wip-us.apache.org/repos/asf/isis/blob/c5aeadd2/example/application/simpleapp/dom/src/main/java/domainapp/dom/simple/SimpleObject.java
----------------------------------------------------------------------
diff --git a/example/application/simpleapp/dom/src/main/java/domainapp/dom/simple/SimpleObject.java b/example/application/simpleapp/dom/src/main/java/domainapp/dom/simple/SimpleObject.java
index 07844c5..b5b8500 100644
--- a/example/application/simpleapp/dom/src/main/java/domainapp/dom/simple/SimpleObject.java
+++ b/example/application/simpleapp/dom/src/main/java/domainapp/dom/simple/SimpleObject.java
@@ -23,7 +23,7 @@ import javax.jdo.annotations.IdentityType;
 import javax.jdo.annotations.VersionStrategy;
 
 import org.apache.isis.applib.DomainObjectContainer;
-import org.apache.isis.applib.Identifier;
+import org.apache.isis.applib.IsisApplibModule;
 import org.apache.isis.applib.annotation.Action;
 import org.apache.isis.applib.annotation.BookmarkPolicy;
 import org.apache.isis.applib.annotation.DomainObject;
@@ -32,7 +32,6 @@ import org.apache.isis.applib.annotation.Editing;
 import org.apache.isis.applib.annotation.Parameter;
 import org.apache.isis.applib.annotation.ParameterLayout;
 import org.apache.isis.applib.annotation.Property;
-import org.apache.isis.applib.annotation.Title;
 import org.apache.isis.applib.services.eventbus.ActionDomainEvent;
 import org.apache.isis.applib.services.i18n.TranslatableString;
 import org.apache.isis.applib.util.ObjectContracts;
@@ -68,86 +67,65 @@ import org.apache.isis.applib.util.ObjectContracts;
 )
 public class SimpleObject implements Comparable<SimpleObject> {
 
+    public static final int NAME_LENGTH = 40;
 
-    //region > identificatiom
     public TranslatableString title() {
         return TranslatableString.tr("Object: {name}", "name", getName());
     }
-    //endregion
 
-    //region > name (property)
 
-    private String name;
-
-    @javax.jdo.annotations.Column(allowsNull="false", length = 40)
-    @Title(sequence="1")
+    public static class NameDomainEvent extends IsisApplibModule.PropertyDomainEvent<SimpleObject,String> {}
+    @javax.jdo.annotations.Column(
+            allowsNull="false",
+            length = NAME_LENGTH
+    )
     @Property(
             editing = Editing.DISABLED
     )
+    private String name;
     public String getName() {
         return name;
     }
-
     public void setName(final String name) {
         this.name = name;
     }
 
-    // endregion
-
-    //region > updateName (action)
-
-    public static class UpdateNameDomainEvent extends ActionDomainEvent<SimpleObject> {
-        public UpdateNameDomainEvent(final SimpleObject source, final Identifier identifier, final Object... arguments) {
-            super(source, identifier, arguments);
-        }
-    }
 
+    public static class UpdateNameDomainEvent extends ActionDomainEvent<SimpleObject> {}
     @Action(
             domainEvent = UpdateNameDomainEvent.class
     )
     public SimpleObject updateName(
-            @Parameter(maxLength = 40)
+            @Parameter(maxLength = NAME_LENGTH)
             @ParameterLayout(named = "New name")
             final String name) {
         setName(name);
         return this;
     }
-
     public String default0UpdateName() {
         return getName();
     }
-
     public TranslatableString validateUpdateName(final String name) {
         return name.contains("!")? TranslatableString.tr("Exclamation mark is not allowed"): null;
     }
 
-    //endregion
 
-    //region > version (derived property)
-//    public Long getVersionSequence() {
-//        return (Long) JDOHelper.getVersion(this);
-//    }
+    /**
+     * version (derived property)
+     */
     public java.sql.Timestamp getVersionSequence() {
         return (java.sql.Timestamp) JDOHelper.getVersion(this);
     }
-    //endregion
 
-    //region > compareTo
 
     @Override
     public int compareTo(final SimpleObject other) {
         return ObjectContracts.compare(this, other, "name");
     }
 
-    //endregion
-
-    //region > injected services
 
     @javax.inject.Inject
     @SuppressWarnings("unused")
     private DomainObjectContainer container;
 
-    //endregion
-
-
 }