ca.tnt.ldaputils.annotations.processing
Class LdapEntityHandler

Package class diagram package LdapEntityHandler
java.lang.Object
  extended by ca.tnt.ldaputils.annotations.processing.LdapEntityHandler
All Implemented Interfaces:
IAnnotationHandler
Direct Known Subclasses:
LdapEntityBinder, LdapEntityLoader

public abstract class LdapEntityHandler
extends Object
implements IAnnotationHandler

IAnnotationHandler abstract implementation that processes LPA annotations for the purpose of providing a base Class for other LdapEntity annotation processing handlers.

This class was engineered in such a way; wait, back the truck up just a bit (hehe). Let's face it, this class was HACKED together in such a way that allows subclassing; DOC more about that later.

Created : 03/01/11 1:38 AM MST

Author:
Trenton D. Adams

Field Summary
protected  Object entity
          The LdapEntity annotated object instance.
protected  LdapManager manager
          Manager instance that is calling the handler
 
Constructor Summary
LdapEntityHandler()
           
 
Method Summary
 Class getAnnotatedClass()
          It is expected that this handler has a reference to the object it wants to operate on.
 Class<? extends Annotation> getAnnotationClass()
          This is the primary Annotation (with target ElementType.TYPE) that this handler expects the annotated Class to be annotated with.
protected  Object getReferencedEntity(Class entityClass, String dnReference, Object attributeValue)
          Retrieves the referenced dn, given the dnReference (see LdapAttribute.referencedDNMethod() for more information) and the attributeValue, and creates a new LdapEntity object.
protected static boolean isMultiValued(Class fieldType)
          Simply determines if this is a multi valued field.
 void noAnnotation(Class annotatedClass)
          Called if no annotation on a particular class exists.
protected  boolean preProcessAnnotation(LdapEntity annotation, Class annotatedClass)
          Does annotation pre-processing, in case the subclass wants to do something special before anything is processed.
protected  Object processAggregate(Field field, Class annotatedClass, Class<?> aggClass, LdapAttribute attrAnnotation)
          WARNING! WARNING! WARNING! It is not recommended that you override this method.
 boolean processAnnotation(Annotation annotation, Class annotatedClass)
          WARNING! WARNING! WARNING! It is not recommended that you override this method.
protected abstract  Object processAttribute(Field field, LdapAttribute attrAnnotation)
          Simple attribute processing.
protected abstract  void processDN(Class annotatedClass, Field field)
          Processing for DN annotation
protected abstract  Object processForeignAggregate(Field field, Class<?> aggClass, String dnReference, LdapAttribute attrAnnotation)
          Called to process a foreign aggregate.
protected  void processLdapAttribute(Class annotatedClass, Field field)
          WARNING! WARNING! WARNING! It is not recommended that you override this method.
protected abstract  void processLdapAttributes(Field field)
          Processing for LdapAttribute annotation where name is '*'
protected abstract  Object processLocalAggregate(Field field, Class<?> aggClass, LdapAttribute attrAnnotation)
          Do what you need to for the local aggregate.
protected  void processManager(Field field)
          Handles injecting the manager.
protected  boolean validateDN(Class annotatedClass, Field field)
          WARNING! WARNING! WARNING! It is not recommended that you override this method.
protected  boolean validateObjectClasses(LdapEntity annotation, Attributes attributes)
          Validates object classes for the entity.
 
Methods inherited from class java.lang.Object
clone, equals, finalize, getClass, hashCode, notify, notifyAll, toString, wait, wait, wait
 
Methods inherited from interface ca.tnt.ldaputils.annotations.processing.IAnnotationHandler
setManager, validateProcessing
 

Field Detail

entity

protected Object entity
The LdapEntity annotated object instance.


manager

protected LdapManager manager
Manager instance that is calling the handler

Constructor Detail

LdapEntityHandler

public LdapEntityHandler()
Method Detail

isMultiValued

protected static boolean isMultiValued(Class fieldType)
Simply determines if this is a multi valued field. We assume it is if it is not either a String or a byte array. These are the only supported return types for attribute values from Sun's LDAP provider; therefore if someone has declared something else, it must be a collection of some sort, or their own type

REQUIRED_FEATURE support other LDAP providers (issue-7) We'll have to figure something else out if we want to work with other LDAP JNDI service providers in the future.

Parameters:
fieldType - the field's type
Returns:
true if it is a multi valued field, false otherwise

processAnnotation

public boolean processAnnotation(Annotation annotation,
                                 Class annotatedClass)
WARNING! WARNING! WARNING! It is not recommended that you override this method. It makes the basic calls to all the LdapEntity related annotation methods, such as processManager(java.lang.reflect.Field), processDN(java.lang.Class, java.lang.reflect.Field), and processLdapAttribute(java.lang.Class, java.lang.reflect.Field),

Specified by:
processAnnotation in interface IAnnotationHandler
Parameters:
annotation - the annotation
annotatedClass - the field to process
Returns:
true if annotation processing was successful

preProcessAnnotation

protected boolean preProcessAnnotation(LdapEntity annotation,
                                       Class annotatedClass)
Does annotation pre-processing, in case the subclass wants to do something special before anything is processed. We implement the default here, which is to return true.

Parameters:
annotation - the annotation being processed
annotatedClass - the annotated class with the annotation
Returns:
true if nothing went wrong during processing

validateObjectClasses

protected boolean validateObjectClasses(LdapEntity annotation,
                                        Attributes attributes)
Validates object classes for the entity.

CRITICAL is this needed in the abstract class? If so, I'm thinking it should be abstract?

Override for a subclassed annotation processor. In some cases, just return true for the subclass, if you have nothing to do.

Parameters:
annotation - the LdapEntity annotation instance for the class
attributes - the attributes to validate against
Returns:
whether the object classes are valid or not

processManager

protected void processManager(Field field)
                       throws IllegalAccessException
Handles injecting the manager.

CRITICAL - okay, bad code, probably shouldn't be assuming manager is available, when no constructors are called with it.

Parameters:
field - the field to inject the manager to
Throws:
IllegalAccessException - if java policies prevent access to fields via reflection

processLdapAttributes

protected abstract void processLdapAttributes(Field field)
                                       throws IllegalAccessException
Processing for LdapAttribute annotation where name is '*'

Parameters:
field - the field the annotation is on
Throws:
IllegalAccessException - if java policies prevent access to fields via reflection

processDN

protected abstract void processDN(Class annotatedClass,
                                  Field field)
                           throws IllegalAccessException,
                                  NoSuchMethodException
Processing for DN annotation

Parameters:
annotatedClass - class of the annotated object
field - the field the annotation is on
Throws:
IllegalAccessException - if java policies prevent access to fields via reflection
NoSuchMethodException - if the LdapAttribute.referencedDNMethod() is the name of a method that does not exist

validateDN

protected boolean validateDN(Class annotatedClass,
                             Field field)
                      throws NoSuchMethodException
WARNING! WARNING! WARNING! It is not recommended that you override this method. In fact, we may make it so that you can't in the future. You've been warned!

Validates that the class is annotated with DN, and that the property getter is available.

CRITICAL ldap entities REQUIRE dn setter too (issue-17)

Parameters:
annotatedClass - the LdapEntity annotated class
field - the field annotated with DN
Returns:
true if the DN validation was successful
Throws:
NoSuchMethodException - if the LdapAttribute.referencedDNMethod() is the name of a method that does not exist

processLdapAttribute

protected void processLdapAttribute(Class annotatedClass,
                                    Field field)
                             throws IllegalAccessException,
                                    NamingException,
                                    InvocationTargetException,
                                    NoSuchMethodException,
                                    InstantiationException
WARNING! WARNING! WARNING! It is not recommended that you override this method. We do checks to determine what is classified as a regular attribute field vs an aggregatized one (I'm making a new word, leave me alone), and call either processAttribute(Field, LdapAttribute) or processAggregate(Field, Class, Class, LdapAttribute). We also handle the field injection.

Processing for LdapAttribute annotation.

DOC move this to the appropriate subclass if needed, when we're done.

If the LdapEntity annotated Class is an instanceof TypeHandler, the TypeHandler.processValues(List, Class) will be called for all aggregate fields, instead of the normal type processing that goes on, described by LdapAttribute

Parameters:
annotatedClass - the class of the annotated object
field - the field the annotation is on
Throws:
IllegalAccessException - if java policies prevent access to fields via reflection
InvocationTargetException - an exception occured during the call to the method defined by LdapAttribute.referencedDNMethod()
NoSuchMethodException - if the LdapAttribute.referencedDNMethod() is the name of a method that does not exist
NamingException - general JNDI exception wrapper for any errors that occur in the directory
InstantiationException - if an error occurs creating an aggregate instance
ClassCastException - if you use a supported collection that is not parameterized, such as SortedSet, instead of SortedSet<String>, for example.

processAttribute

protected abstract Object processAttribute(Field field,
                                           LdapAttribute attrAnnotation)
                                    throws NamingException,
                                           IllegalAccessException
Simple attribute processing. Called when we're doing with attributes only, and not aggregates.

Note, the object returned should be null if you are not attempting to inject anything into this field. That may be the case if you are implementing a handler to "read" from the instance, rather than write to it.

Parameters:
field - the field being processed
attrAnnotation - the LdapAttribute annotation instance being processed
Returns:
the value for the field
Throws:
NamingException - general JNDI exception wrapper for any errors that occur in the directory
IllegalAccessException - if java policies prevent access to fields via reflection

processAggregate

protected Object processAggregate(Field field,
                                  Class annotatedClass,
                                  Class<?> aggClass,
                                  LdapAttribute attrAnnotation)
                           throws InstantiationException,
                                  IllegalAccessException,
                                  NoSuchMethodException,
                                  InvocationTargetException,
                                  NamingException
WARNING! WARNING! WARNING! It is not recommended that you override this method. We do checks to determine if we need to process a local or foreign aggregate, and validate the dn for the foreign aggregates.

Process aggregates, and call the processForeignAggregate(Field, Class, String, LdapAttribute) or the processLocalAggregate(Field, Class, LdapAttribute) as appropriate.

Parameters:
field - the field being processed
annotatedClass - the annotated LdapEntity class
aggClass - the aggregate class as defined by LdapAttribute.aggregateClass()
attrAnnotation - the LdapAttribute annotation instance being processed
Returns:
the aggregate instance
Throws:
IllegalAccessException - if java policies prevent access to fields via reflection
InstantiationException - if an error occurs creating an aggregate instance
NoSuchMethodException - if the LdapAttribute.referencedDNMethod() is the name of a method that does not exist
InvocationTargetException - an exception occured during the call to the method defined by LdapAttribute.referencedDNMethod()
NamingException - general JNDI exception wrapper for any errors that occur in the directory

getReferencedEntity

protected Object getReferencedEntity(Class entityClass,
                                     String dnReference,
                                     Object attributeValue)
                              throws InvalidNameException
Retrieves the referenced dn, given the dnReference (see LdapAttribute.referencedDNMethod() for more information) and the attributeValue, and creates a new LdapEntity object.

Parameters:
entityClass - the java class of the LdapEntity
dnReference - the dn reference with a '?' bind parameter
attributeValue - the value of the attribute to escape, and inject into dnReference before conversion to an LdapName
Returns:
the LdapEntity object
Throws:
InvalidNameException - if an error occurs creating the LdapName.

getAnnotatedClass

public Class getAnnotatedClass()
Description copied from interface: IAnnotationHandler
It is expected that this handler has a reference to the object it wants to operate on. The AnnotationProcessor also needs access to this object in order to determine annotations on it.

Specified by:
getAnnotatedClass in interface IAnnotationHandler
Returns:
the object to traverse the Class tree for.

getAnnotationClass

public Class<? extends Annotation> getAnnotationClass()
Description copied from interface: IAnnotationHandler
This is the primary Annotation (with target ElementType.TYPE) that this handler expects the annotated Class to be annotated with. If the annotated class is annotated with this annotation, this indicates that this handler supports the Class being processed. If this handler does not support the Class being processed, the handler will never be called.

Specified by:
getAnnotationClass in interface IAnnotationHandler
Returns:
the annotation class that this handler supports

noAnnotation

public void noAnnotation(Class annotatedClass)
Description copied from interface: IAnnotationHandler
Called if no annotation on a particular class exists. The handler can do what it wants with it. It may be that we need annotated classes at only certain levels of the object tree, but not others. So, the handler could, for example, require that only the top level object has annotations, while the super classes do not need them. Or, perhaps it requires it the other way around, for some reason.

Specified by:
noAnnotation in interface IAnnotationHandler
Parameters:
annotatedClass - the class, in the object tree of IAnnotationHandler.getAnnotatedClass(), that the annotation was NOT found on.

processForeignAggregate

protected abstract Object processForeignAggregate(Field field,
                                                  Class<?> aggClass,
                                                  String dnReference,
                                                  LdapAttribute attrAnnotation)
                                           throws NamingException,
                                                  IllegalAccessException
Called to process a foreign aggregate. It's up to the subclass to do what it likes. Returning null indicates the subclass does not want anything stored in the LdapEntity annotated instance, but is instead reading from the instance.

Tip on implementing: aggregates are stored in one of two ways.

  1. directly into an aggregate object, if you know that it's a single valued attribute, or your business practise makes it always single valued.
  2. in a collection of aggregate objects, of some sort. e.g. SortedSet<MyAggregateClass> myAggregates
Therefore, the easiest way to determine if it's a single aggregate, is to check the field type, against the LdapAttribute.aggregateClass() by asking if they are equal. See the LdapEntityLoader source for an example.

Parameters:
field - the field being processed
aggClass - the aggregate class as defined by LdapAttribute.aggregateClass()
dnReference - the "properly" formatted dn, with bind parameter, as returned by the LdapAttribute.referencedDNMethod() method
attrAnnotation - the LdapAttribute annotation instance being processed
Returns:
the new aggregate instance, or collection of aggregate instances; subclasses may also return null
Throws:
NamingException - general JNDI exception wrapper for any errors that occur in the directory
IllegalAccessException - if java policies prevent access to fields via reflection

processLocalAggregate

protected abstract Object processLocalAggregate(Field field,
                                                Class<?> aggClass,
                                                LdapAttribute attrAnnotation)
                                         throws IllegalAccessException,
                                                InstantiationException,
                                                NamingException
Do what you need to for the local aggregate. Returning null indicates the subclass does not want anything stored in the LdapEntity annotated instance, but is instead reading from the instance.

A local aggregate is an aggregate object which will be injected into the object field, which has requested it via LdapAttribute.aggregateClass(), and is also using the existing LDAP entry's attributes as a basis for the object. See the documentation on LdapAttribute.aggregateClass() for more information.

Parameters:
field - the field being processed
aggClass - the aggregate class, if needed.
attrAnnotation - the LdapAttribute annotation instance being processed
Returns:
the new fieldValue if one is needed; subclasses may also return null
Throws:
IllegalAccessException - if java policies prevent access to fields via reflection
InstantiationException - if an error occurs creating an aggregate instance
NamingException - general JNDI exception wrapper for any errors that occur in the directory