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 2013/09/12 14:52:52 UTC

git commit: ISIS-528: handle domain objects new'ed up rather than through newTransientInstance()

Updated Branches:
  refs/heads/master f52e9d941 -> edfc5f5f7


ISIS-528: handle domain objects new'ed up rather than through newTransientInstance()


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

Branch: refs/heads/master
Commit: edfc5f5f70dbc0b742a2c01ca1b9d6dc73a87725
Parents: f52e9d9
Author: Dan Haywood <da...@apache.org>
Authored: Thu Sep 12 13:52:27 2013 +0100
Committer: Dan Haywood <da...@apache.org>
Committed: Thu Sep 12 13:52:27 2013 +0100

----------------------------------------------------------------------
 .../isis/applib/AbstractContainedObject.java    |  63 +++++++++--
 .../isis/applib/DomainObjectContainer.java      | 109 ++++++++++++++++---
 .../container/DomainObjectContainerDefault.java |  22 +++-
 3 files changed, 166 insertions(+), 28 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/isis/blob/edfc5f5f/core/applib/src/main/java/org/apache/isis/applib/AbstractContainedObject.java
----------------------------------------------------------------------
diff --git a/core/applib/src/main/java/org/apache/isis/applib/AbstractContainedObject.java b/core/applib/src/main/java/org/apache/isis/applib/AbstractContainedObject.java
index d5307cd..c6dbea2 100644
--- a/core/applib/src/main/java/org/apache/isis/applib/AbstractContainedObject.java
+++ b/core/applib/src/main/java/org/apache/isis/applib/AbstractContainedObject.java
@@ -37,7 +37,39 @@ import org.apache.isis.applib.security.UserMemento;
  */
 public abstract class AbstractContainedObject {
 
-    // {{ factory methods
+    /**
+     * Create a new instance of the specified class, but do not persist it.
+     *
+     * <p>
+     * It is recommended that the object be initially instantiated using
+     * this method, though the framework will also handle the case when 
+     * the object is simply <i>new()</i>ed up.  The benefits of using
+     * {@link #newTransientInstance(Class)} are:
+     * <ul>
+     * <li>any services will be injected into the object immediately
+     *     (otherwise they will not be injected until the framework
+     *     becomes aware of the object, typically when it is 
+     *     {@link #persist(Object) persist}ed</li>
+     * <li>the default value for any properties (usually as specified by 
+     *     <tt>default<i>Xxx</i>()</tt> supporting methods) will not be
+     *     used</li>
+     * <li>the <tt>created()</tt> callback will not be called.
+     * </ul>
+     * 
+     * <p>
+     * The corollary is: if your code never uses <tt>default<i>Xxx</i>()</tt> 
+     * supporting methods or the <tt>created()</tt> callback, then you can
+     * alternatively just <i>new()</i> up the object rather than call this
+     * method. 
+
+     * <p>
+     * If the type is annotated with {@link Aggregated}, then as per
+     * {@link #newAggregatedInstance(Object, Class)}.  Otherwise will be an
+     * aggregate root.
+     * 
+     * @see #newPersistentInstance(Class)
+     * @see #newAggregatedInstance(Object, Class)
+     */
     @Hidden
     protected <T> T newTransientInstance(final Class<T> ofType) {
         return getContainer().newTransientInstance(ofType);
@@ -257,7 +289,8 @@ public abstract class AbstractContainedObject {
     // //////////////////////////////////////
 
     /**
-     * Whether the provided object is persistent.
+     * Determines if the specified object is persistent (that it is stored
+     * permanently outside of the virtual machine).
      */
     @Hidden
     protected boolean isPersistent(final Object domainObject) {
@@ -265,12 +298,20 @@ public abstract class AbstractContainedObject {
     }
 
     /**
-     * Save provided object to the persistent object store.
+     * Persist the specified transient object.
      * 
      * <p>
-     * If the object {@link #isPersistent(Object) is persistent} already, then
-     * will throw an exception.
+     * It is recommended that the object be initially instantiated using
+     * {@link #newTransientInstance(Class)}.  However, the framework will also
+     * handle the case when the object is simply <i>new()</i>ed up.  See
+     * {@link #newTransientInstance(Class)} for more information.
      * 
+     * <p>
+     * Throws an exception if object is already persistent, or if the object
+     * is not yet known to the framework.
+     * 
+     * @see #newTransientInstance(Class)
+     * @see #isPersistent(Object)
      * @see #persistIfNotAlready(Object)
      */
     @Hidden
@@ -280,10 +321,16 @@ public abstract class AbstractContainedObject {
     }
 
     /**
-     * Saves the object, but only if not already {@link #isPersistent()
-     * persistent}.
+     * Persist the specified object (or do nothing if already persistent).
      * 
-     * @see #isPersistent()
+     * <p>
+     * It is recommended that the object be initially instantiated using
+     * {@link #newTransientInstance(Class)}.  However, the framework will also
+     * handle the case when the object is simply <i>new()</i>ed up.  See
+     * {@link #newTransientInstance(Class)} for more information.
+     *
+     * @see #newTransientInstance(Class)
+     * @see #isPersistent(Object)
      * @see #persist(Object)
      */
     @Hidden

http://git-wip-us.apache.org/repos/asf/isis/blob/edfc5f5f/core/applib/src/main/java/org/apache/isis/applib/DomainObjectContainer.java
----------------------------------------------------------------------
diff --git a/core/applib/src/main/java/org/apache/isis/applib/DomainObjectContainer.java b/core/applib/src/main/java/org/apache/isis/applib/DomainObjectContainer.java
index afe968e..0c06b7f 100644
--- a/core/applib/src/main/java/org/apache/isis/applib/DomainObjectContainer.java
+++ b/core/applib/src/main/java/org/apache/isis/applib/DomainObjectContainer.java
@@ -29,8 +29,9 @@ import org.apache.isis.applib.query.Query;
 import org.apache.isis.applib.security.UserMemento;
 
 /**
- * Represents a container that the domain objects work within. It provides
- * access to the persistence mechanism and user interface.
+ * A domain service that acts as a framework's container for managing the 
+ * domain objects, and which provides functionality to those domain objects
+ * in order that they might interact or have knowledge of with the "outside world".
  */
 public interface DomainObjectContainer {
 
@@ -38,6 +39,10 @@ public interface DomainObjectContainer {
     // titleOf
     // ////////////////////////////////////////////////////////////////
 
+    /**
+     * Return the title of the object, as rendered in the UI by the 
+     * Isis viewers.
+     */
     String titleOf(Object domainObject);
 
     // ////////////////////////////////////////////////////////////////
@@ -50,7 +55,14 @@ public interface DomainObjectContainer {
      * <p>
      * This forces the lazy loading mechanism to load the object if it is not
      * already loaded.
+     * 
+     * <p>
+     * This method has been deprecated because lazy loading is now typically performed
+     * by the framework, rather than by application code.
+     * 
+     * @deprecated
      */
+    @Deprecated
     void resolve(Object domainObject);
 
     /**
@@ -60,13 +72,27 @@ public interface DomainObjectContainer {
      * <p>
      * This forces the lazy loading mechanism to load the object if it is not
      * already loaded.
+     * 
+     * <p>
+     * This method has been deprecated because lazy loading is now typically performed
+     * by the framework, rather than by application code.
+     * 
+     * @deprecated
      */
+    @Deprecated
     void resolve(Object domainObject, Object field);
 
     /**
      * Flags that the specified object's state has changed and its changes need
      * to be saved.
+     * 
+     * <p>
+     * This method has been deprecated because object dirtying is now typically performed
+     * by the framework, rather than by application code.
+     * 
+     * @deprecated
      */
+    @Deprecated
     void objectChanged(Object domainObject);
 
     // ////////////////////////////////////////////////////////////////
@@ -103,7 +129,29 @@ public interface DomainObjectContainer {
 
     /**
      * Create a new instance of the specified class, but do not persist it.
-     * 
+     *
+     * <p>
+     * It is recommended that the object be initially instantiated using
+     * this method, though the framework will also handle the case when 
+     * the object is simply <i>new()</i>ed up.  The benefits of using
+     * {@link #newTransientInstance(Class)} are:
+     * <ul>
+     * <li>any services will be injected into the object immediately
+     *     (otherwise they will not be injected until the framework
+     *     becomes aware of the object, typically when it is 
+     *     {@link #persist(Object) persist}ed</li>
+     * <li>the default value for any properties (usually as specified by 
+     *     <tt>default<i>Xxx</i>()</tt> supporting methods) will not be
+     *     used</li>
+     * <li>the <tt>created()</tt> callback will not be called.
+     * </ul>
+     * 
+     * <p>
+     * The corollary is: if your code never uses <tt>default<i>Xxx</i>()</tt> 
+     * supporting methods or the <tt>created()</tt> callback, then you can
+     * alternatively just <i>new()</i> up the object rather than call this
+     * method. 
+
      * <p>
      * If the type is annotated with {@link Aggregated}, then as per
      * {@link #newAggregatedInstance(Object, Class)}.  Otherwise will be an
@@ -117,19 +165,41 @@ public interface DomainObjectContainer {
     /**
      * Create a new instance that will be persisted as part of the specified
      * parent (ie will be a part of a larger aggregate).
+     * 
+     * <p>
+     * <b>Note:</b> not every objectstore implementation supports the concept
+     * of aggregated instances.
      */
     <T> T newAggregatedInstance(Object parent, Class<T> ofType);
 
     /**
      * Returns a new instance of the specified class that will have been
      * persisted.
+     * 
+     * <p>
+     * This method has been deprecated because in almost all cases the
+     * workflow is to {@link #newTransientInstance(Class)}, populate the object
+     * (eg with the arguments to an action) and then to 
+     * {@link #persist(Object) persist) the object.  It is exceptionally rare for
+     * an object to be created, and with no further data required - be in a state
+     * to be persisted immediately.
+     *  
+     * @deprecated
      */
+    @Deprecated
     <T> T newPersistentInstance(final Class<T> ofType);
 
     /**
-     * Returns a new instance of the specified class that has the sane persisted
-     * state as the specified object.
+     * Returns a new instance of the specified class that has the same persisted
+     * state (either transient or persisted) as the provided object.
+     * 
+     * <p>
+     * This method has been deprecated because it is a rare use case, causing
+     * unnecessary interface bloat for very little gain.
+     * 
+     * @deprecated
      */
+    @Deprecated
     <T> T newInstance(final Class<T> ofType, final Object object);
 
     // ////////////////////////////////////////////////////////////////
@@ -166,22 +236,34 @@ public interface DomainObjectContainer {
     boolean isPersistent(Object domainObject);
 
     /**
-     * Make the specified transient object persistent.
+     * Persist the specified transient object.
+     * 
+     * <p>
+     * It is recommended that the object be initially instantiated using
+     * {@link #newTransientInstance(Class)}.  However, the framework will also
+     * handle the case when the object is simply <i>new()</i>ed up.  See
+     * {@link #newTransientInstance(Class)} for more information.
      * 
      * <p>
-     * Throws an exception if object is already persistent.
+     * Throws an exception if object is already persistent, or if the object
+     * is not yet known to the framework.
      * 
+     * @see #newTransientInstance(Class)
      * @see #isPersistent(Object)
      * @see #persistIfNotAlready(Object)
      */
-    void persist(Object transientDomainObject);
+    void persist(Object domainObject);
 
     /**
-     * Make the specified object persistent if not already.
+     * Persist the specified object (or do nothing if already persistent).
      * 
      * <p>
-     * Does nothing otherwise.
-     * 
+     * It is recommended that the object be initially instantiated using
+     * {@link #newTransientInstance(Class)}.  However, the framework will also
+     * handle the case when the object is simply <i>new()</i>ed up.  See
+     * {@link #newTransientInstance(Class)} for more information.
+     *
+     * @see #newTransientInstance(Class)
      * @see #isPersistent(Object)
      * @see #persist(Object)
      */
@@ -262,9 +344,6 @@ public interface DomainObjectContainer {
 
     /**
      * Get the details about the current user.
-     * 
-     * @uml.property name="user"
-     * @uml.associationEnd
      */
     UserMemento getUser();
 
@@ -437,6 +516,8 @@ public interface DomainObjectContainer {
      */
     <T> T firstMatch(Query<T> query);
 
+    // //////////////////////////////////////
+
     /**
      * Find the only instance of the specified type (including subtypes) that
      * has the specified title.

http://git-wip-us.apache.org/repos/asf/isis/blob/edfc5f5f/core/metamodel/src/main/java/org/apache/isis/core/metamodel/services/container/DomainObjectContainerDefault.java
----------------------------------------------------------------------
diff --git a/core/metamodel/src/main/java/org/apache/isis/core/metamodel/services/container/DomainObjectContainerDefault.java b/core/metamodel/src/main/java/org/apache/isis/core/metamodel/services/container/DomainObjectContainerDefault.java
index 52dbf7b..6b3f1ee 100644
--- a/core/metamodel/src/main/java/org/apache/isis/core/metamodel/services/container/DomainObjectContainerDefault.java
+++ b/core/metamodel/src/main/java/org/apache/isis/core/metamodel/services/container/DomainObjectContainerDefault.java
@@ -132,7 +132,7 @@ public class  DomainObjectContainerDefault implements DomainObjectContainer, Que
     }
 
     /**
-     * Returns a new instance of the specified class that has the sane persisted
+     * Returns a new instance of the specified class that has the same persisted
      * state as the specified object.
      */
     @Override
@@ -236,19 +236,29 @@ public class  DomainObjectContainerDefault implements DomainObjectContainer, Que
         return adapter.representsPersistent();
     }
 
+    /**
+     * {@inheritDoc}
+     */
     @Override
-    public void persist(final Object transientObject) {
-        final ObjectAdapter adapter = getAdapterManager().getAdapterFor(transientObject);
-        // TODO check aggregation is supported
+    public void persist(final Object domainObject) {
+        final ObjectAdapter adapter = getAdapterManager().adapterFor(domainObject);
+
+        if(adapter == null) {
+            throw new PersistFailedException("Object not known to framework; instantiate using newTransientInstance(...) rather than simply new'ing up.");
+        }
         if (adapter.isParented()) {
+            // TODO check aggregation is supported
             return;
         }
-        if (isPersistent(transientObject)) {
-            throw new PersistFailedException("Object already persistent: " + adapter);
+        if (isPersistent(domainObject)) {
+            throw new PersistFailedException("Object already persistent; OID=" + adapter.getOid());
         }
         getObjectPersistor().makePersistent(adapter);
     }
 
+    /**
+     * {@inheritDoc}
+     */
     @Override
     public void persistIfNotAlready(final Object object) {
         if (isPersistent(object)) {