org.openmrs.aop
Class RequiredDataAdvice

java.lang.Object
  extended by org.openmrs.aop.RequiredDataAdvice
All Implemented Interfaces:
org.aopalliance.aop.Advice, org.springframework.aop.BeforeAdvice, org.springframework.aop.MethodBeforeAdvice

public class RequiredDataAdvice
extends java.lang.Object
implements org.springframework.aop.MethodBeforeAdvice

This class provides the AOP around each save, (un)void, and (un)retire method in the service layer so that the required data (like creator, dateChanged, dateVoided, etc) can be set automatically and the developer doesn't have to worry about doing it explicitly in the service impl method.

See /metadata/api/spring/applicationContext-service.xml for the mapping of this bean.

For an Openmrs Service to use this AOP advice class and take advantage of its automatic variable setting, it must have "<ref local="requiredDataInterceptor"/>" in its "preInterceptors".

By default, this should take care of any child collections on the object being acted on. Any child collection of OpenmrsObjects will get "handled" (i.e., void data set up, save data set up, or retire data set up, etc) by the same handler type that the parent object was handled with.

To add a new action to happen for a save* method, create a new class that extends RequiredDataHandler. Add any unique code that needs to be done automatically before the save. See ConceptNameSaveHandler as an example. (The code should be unique because all other SaveHandlers will still be called in addition to your new handler.) Be sure to add the Handler annotation (like "@Handler(supports=YourPojoThatHasUniqueSaveNeeds.class)") to your class so that it is picked up by Spring automatically.

To add a new action for a void* or retire* method, extend the VoidHandler/ RetireHandler class and override the handle method. Do not call super, because that code would then be run twice because both handlers are registered. Be sure to add the Handler annotation (like "@Handler(supports=YourPojoThatHasUniqueSaveNeeds.class)") to your class so that it is picked up by Spring automatically.

Since:
1.5
See Also:
RequiredDataHandler, SaveHandler, VoidHandler

Field Summary
protected static java.util.List<java.lang.String> fieldAccess
           
 
Constructor Summary
RequiredDataAdvice()
           
 
Method Summary
 void before(java.lang.reflect.Method method, java.lang.Object[] args, java.lang.Object target)
           
protected static java.util.Collection<OpenmrsObject> getChildCollection(OpenmrsObject openmrsObject, java.lang.reflect.Field field)
          This method gets a child attribute off of an OpenmrsObject.
protected static boolean isOpenmrsObjectCollection(java.lang.Object arg)
          Checks the given Class to see if it A) is a Collection/Set/ List, and B) contains OpenmrsObjects
static
<H extends RequiredDataHandler>
void
recursivelyHandle(java.lang.Class<H> handlerType, OpenmrsObject openmrsObject, java.lang.String reason)
          Convenience method for #recursivelyHandle(Class, OpenmrsObject, User, Date, String).
static
<H extends RequiredDataHandler>
void
recursivelyHandle(java.lang.Class<H> handlerType, OpenmrsObject openmrsObject, User currentUser, java.util.Date currentDate, java.lang.String other, java.util.List<OpenmrsObject> alreadyHandled)
          This loops over all declared collections on the given object and all declared collections on parent objects to use the given handlerType.
 
Methods inherited from class java.lang.Object
clone, equals, finalize, getClass, hashCode, notify, notifyAll, toString, wait, wait, wait
 

Field Detail

fieldAccess

protected static java.util.List<java.lang.String> fieldAccess
Constructor Detail

RequiredDataAdvice

public RequiredDataAdvice()
Method Detail

before

public void before(java.lang.reflect.Method method,
                   java.lang.Object[] args,
                   java.lang.Object target)
            throws java.lang.Throwable
Specified by:
before in interface org.springframework.aop.MethodBeforeAdvice
Throws:
java.lang.Throwable
See Also:
MethodBeforeAdvice.before(java.lang.reflect.Method, java.lang.Object[], java.lang.Object)
Expected behavior:
not fail on update method with no arguments

recursivelyHandle

public static <H extends RequiredDataHandler> void recursivelyHandle(java.lang.Class<H> handlerType,
                                                                     OpenmrsObject openmrsObject,
                                                                     java.lang.String reason)
Convenience method for #recursivelyHandle(Class, OpenmrsObject, User, Date, String). Calls that method with the current user and the current Date.

Type Parameters:
H - the type of Handler to get (should extend RequiredDataHandler)
Parameters:
handlerType - the type of Handler to get (should extend RequiredDataHandler)
openmrsObject - the object that is being acted upon
reason - an optional second argument that was passed to the service method (usually a void/retire reason)
See Also:
#recursivelyHandle(Class, OpenmrsObject, User, Date, String)

recursivelyHandle

public static <H extends RequiredDataHandler> void recursivelyHandle(java.lang.Class<H> handlerType,
                                                                     OpenmrsObject openmrsObject,
                                                                     User currentUser,
                                                                     java.util.Date currentDate,
                                                                     java.lang.String other,
                                                                     java.util.List<OpenmrsObject> alreadyHandled)
This loops over all declared collections on the given object and all declared collections on parent objects to use the given handlerType.

Type Parameters:
H - the type of Handler to get (should extend RequiredDataHandler)
Parameters:
handlerType - the type of Handler to get (should extend RequiredDataHandler)
openmrsObject - the object that is being acted upon
currentUser - the current user to set recursively on the object
currentDate - the date to set recursively on the object
other - an optional second argument that was passed to the service method (usually a void/retire reason)
alreadyHandled - an optional list of objects that have already been handled and should not be processed again. this is intended to prevent infinite recursion when handling collection properties.
See Also:
HandlerUtil.getHandlersForType(Class, Class)

getChildCollection

protected static java.util.Collection<OpenmrsObject> getChildCollection(OpenmrsObject openmrsObject,
                                                                        java.lang.reflect.Field field)
This method gets a child attribute off of an OpenmrsObject. It usually uses the getter for the attribute, but can use the direct field (even if its private) if told to by the fieldAccess list.

Parameters:
openmrsObject - the object to get the collection off of
field - the name of the field that is the collection
Returns:
the actual collection of objects that is on the given openmrsObject
Expected behavior:
get value of given child collection on given field, be able to get private fields in fieldAccess list, throw APIException if getter method not found

isOpenmrsObjectCollection

protected static boolean isOpenmrsObjectCollection(java.lang.Object arg)
Checks the given Class to see if it A) is a Collection/Set/ List, and B) contains OpenmrsObjects

Parameters:
arg - the actual object being passed in
Returns:
true if it is a Collection of some kind of OpenmrsObject
Expected behavior:
return true if class is openmrsObject list, return true if class is openmrsObject set

OpenMRS-1.7.x

Generated Apr 27 2012 10:06 PM. NOTE - these libraries are in active development and subject to change