소스 검색

Refactor lifecycle methods into separate files, so that subclasses can extend specific classes or interfaces to achieve the desired subset of lifecycle capabilities.

Ben Alex 20 년 전
부모
커밋
1455029435

+ 38 - 0
domain/src/main/java/org/acegisecurity/domain/service/CreatableManager.java

@@ -0,0 +1,38 @@
+/* Copyright 2004, 2005 Acegi Technology Pty Limited
+ *
+ * Licensed 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 net.sf.acegisecurity.domain.service;
+
+import net.sf.acegisecurity.domain.PersistableEntity;
+
+/**
+ * Adds a creation method to the <code>ImmutableManager</code>.
+ * 
+ * @author Ben Alex
+ * @version $Id$
+ */
+public interface CreatableManager<E extends PersistableEntity> extends ImmutableManager<E> {
+    //~ Methods ================================================================
+
+    /**
+     * Create a new object, with the current {@link
+     * PersistableEntity#getInternalId()} value being ignored.
+     *
+     * @param value (without the identity property initialized)
+     *
+     * @return the value created (with the identity property initialised)
+     */
+    public E create(E value);
+}

+ 36 - 0
domain/src/main/java/org/acegisecurity/domain/service/CreatableManagerImpl.java

@@ -0,0 +1,36 @@
+/* Copyright 2004, 2005 Acegi Technology Pty Limited
+ *
+ * Licensed 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 net.sf.acegisecurity.domain.service;
+
+import net.sf.acegisecurity.domain.PersistableEntity;
+
+import org.springframework.util.Assert;
+
+/**
+ * Base {@link CreatableManager} implementation.
+ *
+ * @author Ben Alex
+ * @version $Id$
+ */
+public class CreatableManagerImpl<E extends PersistableEntity> extends ImmutableManagerImpl<E> implements CreatableManager<E> {
+	public E create(E value) {
+        Assert.notNull(value);
+		if (logger.isDebugEnabled()) {
+			logger.debug("Creating: " + value);
+		}
+        return dao.create(value);
+    }
+}

+ 226 - 0
domain/src/main/java/org/acegisecurity/domain/service/ImmutableManager.java

@@ -0,0 +1,226 @@
+/* Copyright 2004, 2005 Acegi Technology Pty Limited
+ *
+ * Licensed 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 net.sf.acegisecurity.domain.service;
+
+import net.sf.acegisecurity.domain.PersistableEntity;
+import net.sf.acegisecurity.domain.dao.PaginatedList;
+
+import java.io.Serializable;
+
+import java.util.Collection;
+import java.util.List;
+
+/**
+ * Provides fundamental services layer capabilities for a single concrete {@link
+ * PersistableEntity}, using JDK 1.5 generics.
+ * 
+ * <P>
+ * This interface provides a remoting protocol compliant approach to accessing
+ * services layer logic for a given application. A generics-based services
+ * layer interface decreases development time because the basic CRUD and finder
+ * operations can be specified in a typesafe fashion that reuses superclass
+ * code.
+ * </p>
+ * 
+ * <p>
+ * It is not envisioned that this interface will provide <b>all</b> services layer
+ * functions. The significant value of a services layer is the value-add beyond
+ * simply fronting the DAO or applying validation/binding logic that is better
+ * situated in the domain object or its validator. The type of value-adds
+ * expected to be provided by a services layer include incrementing business
+ * identifiers (eg an invoice number); generating messages for logging/audit
+ * purposes (thus such messages are at a business transaction level of granularity,
+ * instead of DAO/persistence granularity where the overall context of the
+ * the message becomes unclear); updating related domain objects via
+ * their respective services layer beans (eg an invoice services layer bean
+ * would call the general journal services layer bean to create the accrual
+ * accounting entries); making changes to a domain object that requires
+ * logic that is unsuitable to put into a validator because it extends
+ * beyond a single domain object instance or requires access to other persistent
+ * entities (eg computing taxation appliable to an invoice based on a break-down
+ * of each item on the order, its delivery destination, and the customer);
+ * producing messages (eg notify another system the invoice was created or
+ * email the customer via SMTP); provide a layer to locate transaction and 
+ * security configuration; expose a reasonably protocol-independent interface
+ * to the application that can be used by a variety of web services and
+ * client types; ensure any returned objects are eagerly loaded to a well-defined
+ * interface contract etc.
+ * </p>
+ * 
+ * <P>
+ * A single <code>ImmutableManager</code> implementation will typically exist for each
+ * {@link net.sf.acegisecurity.domain.PersistableEntity}, particularly given
+ * a <code>PersistableEntity</code> is allowed to manage multiple
+ * {@link net.sf.acegisecurity.domain.impl.PersistableValue}s.
+ * The particular <code>PersistableEntity</code> an implementation supports
+ * will be expressed by the {@link #supports(Class)} method.
+ * </p>
+ * 
+ * <p>No other part of the Domain subproject relies on this interface. If
+ * you would prefer to write your own services layer interfaces from scratch,
+ * this is not a problem at all.
+ * 
+ * @author Ben Alex
+ * @version $Id$
+ */
+public interface ImmutableManager<E extends PersistableEntity> {
+    //~ Methods ================================================================
+
+    /**
+     * Return all persistent instances, including subclasses.
+     *
+     * @return all persistence instances (an empty <code>List</code> will be
+     *         returned if no matches are found)
+     */
+    public List<E> findAll();
+
+    /**
+     * Find a <code>List</code> of <code>PersistableEntity</code>s, searched by
+     * their identifiers.
+     *
+     * @param ids collection of identifiers to locate
+     *
+     * @return the values with those identifiers (an empty <code>List</code>
+     *         will be returned if no matches are found)
+     */
+    public List<E> findId(Collection<Serializable> ids);
+
+    /**
+     * Load a persistent instance by its identifier, although some properties
+     * may be lazy loaded depending on the underlying DAO implementation and/or
+     * persistence engine mapping document.
+     *
+     * @param id the identifier of the persistent instance desired to be
+     *        retrieved
+     *
+     * @return the request item, or <code>null</code> if not found
+     */
+    public E readId(Serializable id);
+
+	/**
+	 * Loads a persistent instance by its identifier, along with any
+	 * lazy loaded properties associated with that instance.
+	 * 
+     * @param id the identifier of the persistent instance desired to be
+     *        retrieved
+     *
+     * @return the request item, or <code>null</code> if not found
+	 */
+	public E readPopulatedId(Serializable id);
+	
+    /**
+     * Find persistent instances with properties matching those of the passed
+     * <code>PersistableEntity</code>.
+     * 
+     * <P>
+     * Persistent instances are matched on the basis of query by example.
+     * Properties whose value is <code>null</code>, empty
+     * <code>String</code>s, and any <code>Collection</code>s are ignored in
+     * the query by example evaluation.
+     * </p>
+     *
+     * @param value parameters to filter on (the class of this object will
+     * be added to the filter)
+     * @param firstElement the first result (start at zero to obtain all
+     *        results)
+     * @param maxElements the maximum number of results desired for this page
+     *        of the result set
+     *
+     * @return the requested page of the result list (a properly formed
+     *         <code>PaginatedList</code> is returned if no results match)
+     */
+    public PaginatedList<E> scroll(E value, int firstElement,
+        int maxElements);
+
+    /**
+     * Find persistent instances with properties matching those of the passed
+     * <code>PersistableEntity</code>, with a guarantee the returned results
+     * will have each of the <code>value</code> class' immediate properties
+     * initialized.
+     * 
+     * <P>
+     * Persistent instances are matched on the basis of query by example.
+     * Properties whose value is <code>null</code>, empty
+     * <code>String</code>s, and any <code>Collection</code>s are ignored in
+     * the query by example evaluation.
+     * </p>
+     *
+     * @param value parameters to filter on (the class of this object will
+     * be added to the filter)
+     * @param firstElement the first result (start at zero to obtain all
+     *        results)
+     * @param maxElements the maximum number of results desired for this page
+     *        of the result set
+     *
+     * @return the requested page of the result list (a properly formed
+     *         <code>PaginatedList</code> is returned if no results match)
+     */
+    public PaginatedList<E> scrollPopulated(E value, int firstElement,
+        int maxElements);
+
+	/**
+     * Find persistent instances with properties matching those of the passed
+     * <code>PersistableEntity</code>, ignoring the class of the passed
+     * <code>PersistableEntity</code> (useful if you pass a superclass, as you
+     * want to find all subclass instances which match).
+	 * 
+     * @param value parameters to filter on (the class of this object will
+     * NOT be added to the filter)
+     * @param firstElement the first result (start at zero to obtain all
+     *        results)
+     * @param maxElements the maximum number of results desired for this page
+     *        of the result set
+     *
+     * @return the requested page of the result list (a properly formed
+     *         <code>PaginatedList</code> is returned if no results match)
+	 */
+    public PaginatedList<E> scrollWithSubclasses(E value, int firstElement,
+	        int maxElements);
+
+	/**
+     * Find persistent instances with properties matching those of the passed
+     * <code>PersistableEntity</code>, ignoring the class of the passed
+     * <code>PersistableEntity</code> (useful if you pass a superclass, as you
+     * want to find all subclass instances which match). Guarantees the returned 
+     * results will have each of the DAO's <code>supports</code> class' immediate
+     * properties initialized.
+	 * 
+     * @param value parameters to filter on (the class of this object will
+     * NOT be added to the filter)
+     * @param firstElement the first result (start at zero to obtain all
+     *        results)
+     * @param maxElements the maximum number of results desired for this page
+     *        of the result set
+     *
+     * @return the requested page of the result list (a properly formed
+     *         <code>PaginatedList</code> is returned if no results match)
+	 */
+    public PaginatedList<E> scrollPopulatedWithSubclasses(E value, int firstElement,
+	        int maxElements);
+	
+	/**
+     * Indicates whether the DAO instance provides persistence services for the
+     * specified class.
+     *
+     * @param clazz to test, which should be an implementation of
+     *        <code>PersistableEntity</code>
+     *
+     * @return <code>true</code> or <code>false</code>, indicating whether or
+     *         not the passed class is supported by this DAO instance
+     */
+    public boolean supports(Class clazz);
+
+}

+ 155 - 0
domain/src/main/java/org/acegisecurity/domain/service/ImmutableManagerImpl.java

@@ -0,0 +1,155 @@
+/* Copyright 2004, 2005 Acegi Technology Pty Limited
+ *
+ * Licensed 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 net.sf.acegisecurity.domain.service;
+
+import java.io.Serializable;
+import java.util.Collection;
+import java.util.List;
+
+import net.sf.acegisecurity.domain.PersistableEntity;
+import net.sf.acegisecurity.domain.dao.Dao;
+import net.sf.acegisecurity.domain.dao.PaginatedList;
+import net.sf.acegisecurity.domain.util.GenericsUtils;
+
+import org.springframework.beans.factory.InitializingBean;
+import org.springframework.context.support.ApplicationObjectSupport;
+import org.springframework.util.Assert;
+
+/**
+ * Base {@link ImmutableManager} implementation.
+ *
+ * @author Ben Alex
+ * @version $Id$
+ */
+public class ImmutableManagerImpl<E extends PersistableEntity> extends ApplicationObjectSupport implements ImmutableManager<E>, InitializingBean {
+    //~ Instance fields ========================================================
+
+    /** The class that this instance provides services for */
+    private Class supportsClass;
+	private String beanName;
+	
+	protected Dao<E> dao;
+
+    //~ Methods ================================================================
+	
+	public ImmutableManagerImpl() {
+		this.supportsClass = GenericsUtils.getGeneric(getClass());
+		if (supportsClass == null) {
+			if (logger.isWarnEnabled()) {
+				logger.warn("Could not determine the generics type - you will need to set manually");
+			}
+		}
+	}
+
+    public void setSupportsClass(Class supportClass) {
+        this.supportsClass = supportClass;
+    }
+
+    public Class getSupportsClass() {
+        return supportsClass;
+    }
+
+    public Dao<E> getDao() {
+		return dao;
+	}
+
+	public void setDao(Dao<E> dao) {
+		this.dao = dao;
+	}
+
+	/**
+	 * @return the sort order column to be used by default by the scroll methods
+	 */
+	protected String getDefaultSortOrder() {
+		return "id";
+	}
+	
+	/**
+	 * Provides hook for custom subclasses to provide initialization behaviour
+	 * 
+	 * @throws Exception
+	 */
+	protected void doInitManager() throws Exception {}
+	
+	public final void afterPropertiesSet() throws Exception {
+        Assert.notNull(supportsClass, "supportClass is required");
+        Assert.isTrue(PersistableEntity.class.isAssignableFrom(supportsClass),
+        "supportClass is not an implementation of PersistableEntity");
+		Assert.notNull(dao, "Dao is null");
+		Assert.isTrue(dao.supports(supportsClass), "Dao '" + dao + "' does not support '" + supportsClass + "'");
+		doInitManager();
+	}
+
+    public List<E> findAll() {
+        return dao.findAll();
+    }
+
+    public List<E> findId(Collection<Serializable> ids) {
+        Assert.notNull(ids, "Collection of IDs cannot be null");
+        Assert.notEmpty(ids, "There must be some values in the Collection list");
+        return dao.findId(ids);
+    }
+
+    public E readId(Serializable id) {
+        Assert.notNull(id);
+        return dao.readId(id);
+    }
+
+    public E readPopulatedId(Serializable id) {
+		Assert.notNull(id);
+		return dao.readPopulatedId(id);
+	}
+
+	public PaginatedList<E> scroll(E value, int firstElement,
+        int maxElements) {
+        Assert.notNull(value);
+		Assert.isInstanceOf(this.supportsClass, value, "Can only scroll with values this manager supports");
+
+        return dao.scroll(value, firstElement, maxElements, getDefaultSortOrder());
+    }
+
+    public PaginatedList<E> scrollPopulated(E value, int firstElement, int maxElements) {
+        Assert.notNull(value);
+		Assert.isInstanceOf(this.supportsClass, value, "Can only scroll with values this manager supports");
+		
+		return dao.scrollPopulated(value, firstElement, maxElements, getDefaultSortOrder());
+	}
+
+	public PaginatedList<E> scrollWithSubclasses(E value, int firstElement,
+	        int maxElements) {
+	        Assert.notNull(value);
+			Assert.isInstanceOf(this.supportsClass, value, "Can only scroll with values this manager supports");
+
+	        return dao.scrollWithSubclasses(value, firstElement, maxElements, getDefaultSortOrder());
+	    }
+
+	public PaginatedList<E> scrollPopulatedWithSubclasses(E value, int firstElement, int maxElements) {
+        Assert.notNull(value);
+		Assert.isInstanceOf(this.supportsClass, value, "Can only scroll with values this manager supports");
+
+		return dao.scrollPopulatedWithSubclasses(value, firstElement, maxElements, getDefaultSortOrder());
+	}
+
+	public boolean supports(Class clazz) {
+        Assert.notNull(clazz);
+
+        return this.supportsClass.equals(clazz);
+    }
+
+	public void setBeanName(String beanName) {
+		this.beanName = beanName;
+	}
+}

+ 3 - 233
domain/src/main/java/org/acegisecurity/domain/service/Manager.java

@@ -16,250 +16,20 @@
 package net.sf.acegisecurity.domain.service;
 
 import net.sf.acegisecurity.domain.PersistableEntity;
-import net.sf.acegisecurity.domain.dao.PaginatedList;
-
-import java.io.Serializable;
-
-import java.util.Collection;
-import java.util.List;
 
 /**
- * Provides fundamental services layer capabilities for a single concrete {@link
- * PersistableEntity}, using JDK 1.5 generics.
- * 
- * <P>
- * This interface provides a remoting protocol compliant approach to accessing
- * services layer logic for a given application. A generics-based services
- * layer interface decreases development time because the basic CRUD and finder
- * operations can be specified in a typesafe fashion that reuses superclass
- * code.
- * </p>
- * 
- * <p>
- * It is not envisioned that this interface will provide <b>all</b> services layer
- * functions. The significant value of a services layer is the value-add beyond
- * simply fronting the DAO or applying validation/binding logic that is better
- * situated in the domain object or its validator. The type of value-adds
- * expected to be provided by a services layer include incrementing business
- * identifiers (eg an invoice number); generating messages for logging/audit
- * purposes (thus such messages are at a business transaction level of granularity,
- * instead of DAO/persistence granularity where the overall context of the
- * the message becomes unclear); updating related domain objects via
- * their respective services layer beans (eg an invoice services layer bean
- * would call the general journal services layer bean to create the accrual
- * accounting entries); making changes to a domain object that requires
- * logic that is unsuitable to put into a validator because it extends
- * beyond a single domain object instance or requires access to other persistent
- * entities (eg computing taxation appliable to an invoice based on a break-down
- * of each item on the order, its delivery destination, and the customer);
- * producing messages (eg notify another system the invoice was created or
- * email the customer via SMTP); provide a layer to locate transaction and 
- * security configuration; expose a reasonably protocol-independent interface
- * to the application that can be used by a variety of web services and
- * client types; ensure any returned objects are eagerly loaded to a well-defined
- * interface contract etc.
- * </p>
- * 
- * <P>
- * A single <code>Manager</code> implementation will typically exist for each
- * {@link net.sf.acegisecurity.domain.PersistableEntity}, particularly given
- * a <code>PersistableEntity</code> is allowed to manage multiple
- * {@link net.sf.acegisecurity.domain.impl.PersistableValue}s.
- * The particular <code>PersistableEntity</code> an implementation supports
- * will be expressed by the {@link #supports(Class)} method.
- * </p>
- * 
- * <p>No other part of the Domain subproject relies on this interface. If
- * you would prefer to write your own services layer interfaces from scratch,
- * this is not a problem at all.
+ * Adds a deletion method to <code>UpdatableManager</code>, thus providing CRUD
+ * use case support.
  * 
  * @author Ben Alex
  * @version $Id$
  */
-public interface Manager<E extends PersistableEntity> {
+public interface Manager<E extends PersistableEntity> extends UpdatableManager<E> {
     //~ Methods ================================================================
-
-    /**
-     * Create a new object, with the current {@link
-     * PersistableEntity#getInternalId()} value being ignored.
-     *
-     * @param value (without the identity property initialized)
-     *
-     * @return the value created (with the identity property initialised)
-     */
-    public E create(E value);
-
-    /**
-     * Saves an existing object to the persistence layer, or creates a new
-     * object in the persistence layer. Implementations typically rely on
-     * {@link PersistableEntity#getInternalId()} being non-<code>null</code>
-     * to differentiate between persistence instances previous saved and those
-     * requiring initial creation.
-     *
-     * @param value to save or update
-     *
-     * @return the saved or updated (as appropriate) value
-     */
-    public E createOrUpdate(E value);
-
     /**
      * Delete an object.
      *
      * @param value the value to delete
      */
     public void delete(E value);
-
-    /**
-     * Return all persistent instances, including subclasses.
-     *
-     * @return all persistence instances (an empty <code>List</code> will be
-     *         returned if no matches are found)
-     */
-    public List<E> findAll();
-
-    /**
-     * Find a <code>List</code> of <code>PersistableEntity</code>s, searched by
-     * their identifiers.
-     *
-     * @param ids collection of identifiers to locate
-     *
-     * @return the values with those identifiers (an empty <code>List</code>
-     *         will be returned if no matches are found)
-     */
-    public List<E> findId(Collection<Serializable> ids);
-
-    /**
-     * Load a persistent instance by its identifier, although some properties
-     * may be lazy loaded depending on the underlying DAO implementation and/or
-     * persistence engine mapping document.
-     *
-     * @param id the identifier of the persistent instance desired to be
-     *        retrieved
-     *
-     * @return the request item, or <code>null</code> if not found
-     */
-    public E readId(Serializable id);
-
-	/**
-	 * Loads a persistent instance by its identifier, along with any
-	 * lazy loaded properties associated with that instance.
-	 * 
-     * @param id the identifier of the persistent instance desired to be
-     *        retrieved
-     *
-     * @return the request item, or <code>null</code> if not found
-	 */
-	public E readPopulatedId(Serializable id);
-	
-    /**
-     * Find persistent instances with properties matching those of the passed
-     * <code>PersistableEntity</code>.
-     * 
-     * <P>
-     * Persistent instances are matched on the basis of query by example.
-     * Properties whose value is <code>null</code>, empty
-     * <code>String</code>s, and any <code>Collection</code>s are ignored in
-     * the query by example evaluation.
-     * </p>
-     *
-     * @param value parameters to filter on (the class of this object will
-     * be added to the filter)
-     * @param firstElement the first result (start at zero to obtain all
-     *        results)
-     * @param maxElements the maximum number of results desired for this page
-     *        of the result set
-     *
-     * @return the requested page of the result list (a properly formed
-     *         <code>PaginatedList</code> is returned if no results match)
-     */
-    public PaginatedList<E> scroll(E value, int firstElement,
-        int maxElements);
-
-    /**
-     * Find persistent instances with properties matching those of the passed
-     * <code>PersistableEntity</code>, with a guarantee the returned results
-     * will have each of the <code>value</code> class' immediate properties
-     * initialized.
-     * 
-     * <P>
-     * Persistent instances are matched on the basis of query by example.
-     * Properties whose value is <code>null</code>, empty
-     * <code>String</code>s, and any <code>Collection</code>s are ignored in
-     * the query by example evaluation.
-     * </p>
-     *
-     * @param value parameters to filter on (the class of this object will
-     * be added to the filter)
-     * @param firstElement the first result (start at zero to obtain all
-     *        results)
-     * @param maxElements the maximum number of results desired for this page
-     *        of the result set
-     *
-     * @return the requested page of the result list (a properly formed
-     *         <code>PaginatedList</code> is returned if no results match)
-     */
-    public PaginatedList<E> scrollPopulated(E value, int firstElement,
-        int maxElements);
-
-	/**
-     * Find persistent instances with properties matching those of the passed
-     * <code>PersistableEntity</code>, ignoring the class of the passed
-     * <code>PersistableEntity</code> (useful if you pass a superclass, as you
-     * want to find all subclass instances which match).
-	 * 
-     * @param value parameters to filter on (the class of this object will
-     * NOT be added to the filter)
-     * @param firstElement the first result (start at zero to obtain all
-     *        results)
-     * @param maxElements the maximum number of results desired for this page
-     *        of the result set
-     *
-     * @return the requested page of the result list (a properly formed
-     *         <code>PaginatedList</code> is returned if no results match)
-	 */
-    public PaginatedList<E> scrollWithSubclasses(E value, int firstElement,
-	        int maxElements);
-
-	/**
-     * Find persistent instances with properties matching those of the passed
-     * <code>PersistableEntity</code>, ignoring the class of the passed
-     * <code>PersistableEntity</code> (useful if you pass a superclass, as you
-     * want to find all subclass instances which match). Guarantees the returned 
-     * results will have each of the DAO's <code>supports</code> class' immediate
-     * properties initialized.
-	 * 
-     * @param value parameters to filter on (the class of this object will
-     * NOT be added to the filter)
-     * @param firstElement the first result (start at zero to obtain all
-     *        results)
-     * @param maxElements the maximum number of results desired for this page
-     *        of the result set
-     *
-     * @return the requested page of the result list (a properly formed
-     *         <code>PaginatedList</code> is returned if no results match)
-	 */
-    public PaginatedList<E> scrollPopulatedWithSubclasses(E value, int firstElement,
-	        int maxElements);
-	
-	/**
-     * Indicates whether the DAO instance provides persistence services for the
-     * specified class.
-     *
-     * @param clazz to test, which should be an implementation of
-     *        <code>PersistableEntity</code>
-     *
-     * @return <code>true</code> or <code>false</code>, indicating whether or
-     *         not the passed class is supported by this DAO instance
-     */
-    public boolean supports(Class clazz);
-
-    /**
-     * Update an object.
-     *
-     * @param value to update, with the <code>PersistableEntity</code> having a
-     *        non-<code>null</code> identifier
-     *
-     * @return the updated value
-     */
-    public E update(E value);
 }

+ 1 - 160
domain/src/main/java/org/acegisecurity/domain/service/ManagerImpl.java

@@ -15,18 +15,8 @@
 
 package net.sf.acegisecurity.domain.service;
 
-import java.io.Serializable;
-import java.util.Collection;
-import java.util.List;
-
 import net.sf.acegisecurity.domain.PersistableEntity;
-import net.sf.acegisecurity.domain.dao.Dao;
-import net.sf.acegisecurity.domain.dao.PaginatedList;
-import net.sf.acegisecurity.domain.util.GenericsUtils;
 
-import org.springframework.beans.factory.InitializingBean;
-import org.springframework.context.support.ApplicationObjectSupport;
-import org.springframework.transaction.annotation.Transactional;
 import org.springframework.util.Assert;
 
 /**
@@ -35,89 +25,7 @@ import org.springframework.util.Assert;
  * @author Ben Alex
  * @version $Id$
  */
-@Transactional
-public class ManagerImpl<E extends PersistableEntity> extends ApplicationObjectSupport implements Manager<E>, InitializingBean {
-    //~ Instance fields ========================================================
-
-    /** The class that this instance provides services for */
-    private Class supportsClass;
-	private String beanName;
-	
-	protected Dao<E> dao;
-
-    //~ Methods ================================================================
-	
-	public ManagerImpl() {
-		this.supportsClass = GenericsUtils.getGeneric(getClass());
-		if (supportsClass == null) {
-			if (logger.isWarnEnabled()) {
-				logger.warn("Could not determine the generics type - you will need to set manually");
-			}
-		}
-	}
-
-    public void setSupportsClass(Class supportClass) {
-        this.supportsClass = supportClass;
-    }
-
-    public Class getSupportsClass() {
-        return supportsClass;
-    }
-
-    public Dao<E> getDao() {
-		return dao;
-	}
-
-	public void setDao(Dao<E> dao) {
-		this.dao = dao;
-	}
-
-	/**
-	 * @return the sort order column to be used by default by the scroll methods
-	 */
-	protected String getDefaultSortOrder() {
-		return "id";
-	}
-	
-	/**
-	 * Provides hook for custom subclasses to provide initialization behaviour
-	 * 
-	 * @throws Exception
-	 */
-	protected void doInitManager() throws Exception {}
-	
-	public final void afterPropertiesSet() throws Exception {
-        Assert.notNull(supportsClass, "supportClass is required");
-        Assert.isTrue(PersistableEntity.class.isAssignableFrom(supportsClass),
-        "supportClass is not an implementation of PersistableEntity");
-		Assert.notNull(dao, "Dao is null");
-		Assert.isTrue(dao.supports(supportsClass), "Dao '" + dao + "' does not support '" + supportsClass + "'");
-		doInitManager();
-	}
-
-	public E create(E value) {
-        Assert.notNull(value);
-		if (logger.isDebugEnabled()) {
-			logger.debug("Creating: " + value);
-		}
-        return dao.create(value);
-    }
-
-	/**
-	 * Delegates to the appropriate services layer method (not the DAO).
-	 */
-    public E createOrUpdate(E value) {
-        Assert.notNull(value);
-		if (logger.isDebugEnabled()) {
-			logger.debug("CreatingOrUpdating: " + value);
-		}
-		if (value.getInternalId() == null) {
-			return create(value);
-		} else {
-			return update(value);
-		}
-    }
-
+public class ManagerImpl<E extends PersistableEntity> extends UpdatableManagerImpl<E> implements Manager<E> {
     public void delete(E value) {
         Assert.notNull(value);
 		if (logger.isDebugEnabled()) {
@@ -126,71 +34,4 @@ public class ManagerImpl<E extends PersistableEntity> extends ApplicationObjectS
         dao.delete(value);
     }
 
-    public List<E> findAll() {
-        return dao.findAll();
-    }
-
-    public List<E> findId(Collection<Serializable> ids) {
-        Assert.notNull(ids, "Collection of IDs cannot be null");
-        Assert.notEmpty(ids, "There must be some values in the Collection list");
-        return dao.findId(ids);
-    }
-
-    public E readId(Serializable id) {
-        Assert.notNull(id);
-        return dao.readId(id);
-    }
-
-    public E readPopulatedId(Serializable id) {
-		Assert.notNull(id);
-		return dao.readPopulatedId(id);
-	}
-
-	public PaginatedList<E> scroll(E value, int firstElement,
-        int maxElements) {
-        Assert.notNull(value);
-		Assert.isInstanceOf(this.supportsClass, value, "Can only scroll with values this manager supports");
-
-        return dao.scroll(value, firstElement, maxElements, getDefaultSortOrder());
-    }
-
-    public PaginatedList<E> scrollPopulated(E value, int firstElement, int maxElements) {
-        Assert.notNull(value);
-		Assert.isInstanceOf(this.supportsClass, value, "Can only scroll with values this manager supports");
-		
-		return dao.scrollPopulated(value, firstElement, maxElements, getDefaultSortOrder());
-	}
-
-	public PaginatedList<E> scrollWithSubclasses(E value, int firstElement,
-	        int maxElements) {
-	        Assert.notNull(value);
-			Assert.isInstanceOf(this.supportsClass, value, "Can only scroll with values this manager supports");
-
-	        return dao.scrollWithSubclasses(value, firstElement, maxElements, getDefaultSortOrder());
-	    }
-
-	public PaginatedList<E> scrollPopulatedWithSubclasses(E value, int firstElement, int maxElements) {
-        Assert.notNull(value);
-		Assert.isInstanceOf(this.supportsClass, value, "Can only scroll with values this manager supports");
-
-		return dao.scrollPopulatedWithSubclasses(value, firstElement, maxElements, getDefaultSortOrder());
-	}
-
-	public boolean supports(Class clazz) {
-        Assert.notNull(clazz);
-
-        return this.supportsClass.equals(clazz);
-    }
-
-    public E update(E value) {
-        Assert.notNull(value);
-		if (logger.isDebugEnabled()) {
-			logger.debug("Updating: " + value);
-		}
-        return dao.update(value);
-    }
-
-	public void setBeanName(String beanName) {
-		this.beanName = beanName;
-	}
 }

+ 51 - 0
domain/src/main/java/org/acegisecurity/domain/service/UpdatableManager.java

@@ -0,0 +1,51 @@
+/* Copyright 2004, 2005 Acegi Technology Pty Limited
+ *
+ * Licensed 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 net.sf.acegisecurity.domain.service;
+
+import net.sf.acegisecurity.domain.PersistableEntity;
+
+/**
+ * Adds update (but no delete) methods to the <code>CreatableManager</code>.
+ * 
+ * @author Ben Alex
+ * @version $Id$
+ */
+public interface UpdatableManager<E extends PersistableEntity> extends CreatableManager<E> {
+    //~ Methods ================================================================
+
+	/**
+     * Saves an existing object to the persistence layer, or creates a new
+     * object in the persistence layer. Implementations typically rely on
+     * {@link PersistableEntity#getInternalId()} being non-<code>null</code>
+     * to differentiate between persistence instances previous saved and those
+     * requiring initial creation.
+     *
+     * @param value to save or update
+     *
+     * @return the saved or updated (as appropriate) value
+     */
+    public E createOrUpdate(E value);
+
+    /**
+     * Update an object.
+     *
+     * @param value to update, with the <code>PersistableEntity</code> having a
+     *        non-<code>null</code> identifier
+     *
+     * @return the updated value
+     */
+    public E update(E value);
+}

+ 52 - 0
domain/src/main/java/org/acegisecurity/domain/service/UpdatableManagerImpl.java

@@ -0,0 +1,52 @@
+/* Copyright 2004, 2005 Acegi Technology Pty Limited
+ *
+ * Licensed 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 net.sf.acegisecurity.domain.service;
+
+import net.sf.acegisecurity.domain.PersistableEntity;
+
+import org.springframework.util.Assert;
+
+/**
+ * Base {@link UpdatableManager} implementation.
+ *
+ * @author Ben Alex
+ * @version $Id$
+ */
+public class UpdatableManagerImpl<E extends PersistableEntity> extends CreatableManagerImpl<E> implements UpdatableManager<E> {
+
+    public E update(E value) {
+        Assert.notNull(value);
+		if (logger.isDebugEnabled()) {
+			logger.debug("Updating: " + value);
+		}
+        return dao.update(value);
+    }
+    
+    /**
+	 * Delegates to the appropriate services layer method (not the DAO).
+	 */
+    public E createOrUpdate(E value) {
+        Assert.notNull(value);
+		if (logger.isDebugEnabled()) {
+			logger.debug("CreatingOrUpdating: " + value);
+		}
+		if (value.getInternalId() == null) {
+			return create(value);
+		} else {
+			return update(value);
+		}
+    }
+}