AbstractDomainEntityAccessor.java from Texai at Krugle
Show AbstractDomainEntityAccessor.java syntax highlighted
/*
* AbstractDomainEntityAccessor.java
*
* Created on November 1, 2006, 9:36 AM
*
* Description: Contains the common domain entity annotation gathering methods for use in the
* subclasses for loading and persistence.
*
* Copyright (C) 2006 Stephen L. Reed.
*
* This program is free software; you can redistribute it and/or modify it under the terms
* of the GNU General Public License as published by the Free Software Foundation; either
* version 2 of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
* without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
* See the GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License along with this program;
* if not, write to the Free Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
package org.texai.kb.ejb.session;
import java.lang.annotation.Annotation;
import java.lang.reflect.Field;
import java.util.HashMap;
import java.util.Map;
import java.util.Stack;
import javax.persistence.Id;
import javax.persistence.OrderBy;
import org.apache.log4j.Logger;
import org.texai.kb.Constants;
import org.texai.kb.entity.AtomicTerm;
import org.texai.kb.entity.AbstractReifiedTerm;
import org.texai.kb.persistence.DomainContext;
import org.texai.kb.persistence.DomainEntity;
import org.texai.kb.persistence.DomainProperty;
import org.texai.util.TexaiException;
/**
*
* @author reed
*/
public abstract class AbstractDomainEntityAccessor { // NOPMD
/** the class of the domain entity */
private transient Class domainEntityClass;
/** the instantiated domain entity */
private transient Object domainEntity;
/** the array of package level annotations */
private transient Annotation[] packageLevelAnnotations;
/** the array of type level annotations */
private transient Annotation[] typeLevelAnnotations;
/** the dictionary of field level annotations, field -> Id or DomainProperty annotation */
private transient Map<Field, Annotation> fieldAnnotationDictionary;
/** the dictionary of orderBy annotations, field -> Id or OrderBy annotation */
private transient Map<Field, OrderBy> orderByDictionary;
/** the dictionary of strength fields, field -> strength field */
private transient Map<Field, Field> strengthFieldDictionary;
/** the name of the context into which the class-scoped associations are persisted */
private transient String classPersistenceContextName;
/** the list of context names for which the persist-to context is a subcontext in case of a new persist-to context,
* otherwise an empty list
*/
private transient String[] subContextOfNames;
/** the name of the KB partition into which the class-scoped associations are persisted */
private transient String classKBPartitionName;
/** the KB partition into which the class-scoped associations are persisted */
private transient AtomicTerm classKBPartition;
/** the types of this domain entity */
private transient String[] typeOfs;
/** the super classes of this domain entity */
private transient String[] subClassOfs;
/** the class term name */
private transient String classTermName;
/** the class term */
private transient AtomicTerm classTerm;
/** the stack of abstact domain entity information that allows the session bean to perform recursive method calls */
private transient final Stack<Object> domainEntityInfoStack = new Stack<Object>();
/** the context from which the class-scoped associations are loaded */
private transient AbstractReifiedTerm classPersistenceContext;
/** the instance term */
private transient AtomicTerm instanceTerm;
/**
* Creates a new instance of AbstractDomainEntityAccessor.
*/
protected AbstractDomainEntityAccessor() {
super();
}
/** Returns true if the given object is an annotated domain entity.
*
* @param obj the given object
* @return true if the given object is an annotated domain entity
*/
public boolean isDomainEntity(final Object obj) {
//Preconditions
assert obj != null : "obj must not be null";
return isDomainEntityClass(obj.getClass());
}
/** Returns true if the given object class is an annotated domain entity class.
*
* @param obj the given object clas
* @return true if the given object is an annotated domain entity class
*/
@SuppressWarnings("unchecked")
public boolean isDomainEntityClass(final Class clazz) {
//Preconditions
assert clazz != null : "clazz must not be null";
return clazz.isAnnotationPresent(DomainEntity.class);
}
/** Gathers annotations for the domain entity class. */
protected void gatherAnnotationsForDomainEntityClass() {
//Preconditions
assert domainEntityClass != null : "domainEntityClass must not be null";
packageLevelAnnotations = domainEntityClass.getPackage().getAnnotations();
for (final Annotation annotation : packageLevelAnnotations) {
getLogger().debug(stackLevel() + "package level annotation: " + annotation.toString());
}
typeLevelAnnotations = domainEntityClass.getAnnotations();
for (final Annotation annotation : typeLevelAnnotations) {
getLogger().debug(stackLevel() + "type level annotation: " + annotation.toString());
}
gatherFieldAnnotationDictionary(domainEntityClass);
}
/** Iterates over the package and type level annotations and configures the domain context settings. */
protected void configureDomainContextSettings() {
//Preconditions
assert packageLevelAnnotations != null : "packageLevelAnnotations must not be null";
assert typeLevelAnnotations != null : "typeLevelAnnotations must not be null";
for (final Annotation annotation : packageLevelAnnotations) {
if (annotation instanceof DomainContext) {
final DomainContext domainContext = (DomainContext) annotation;
classPersistenceContextName = domainContext.persistenceContext();
subContextOfNames = domainContext.subContextOf();
classKBPartitionName = domainContext.kbPartition();
break;
}
}
for (final Annotation annotation : typeLevelAnnotations) {
if (annotation instanceof DomainContext) {
final DomainContext domainContext = (DomainContext) annotation;
classPersistenceContextName = domainContext.persistenceContext();
subContextOfNames = domainContext.subContextOf();
classKBPartitionName = domainContext.kbPartition();
break;
}
}
if (classKBPartitionName == null) {
throw new TexaiException("missing kbPartition in the DomainContext annotation on this domain entity " + domainEntityClass);
}
if (classPersistenceContextName != null) {
getLogger().debug(stackLevel() + "classPersistenceContextName: " + classPersistenceContextName);
}
if (subContextOfNames != null) {
for (final String subContextOfName : subContextOfNames) {
getLogger().debug(stackLevel() + "subContextOfName: " + subContextOfName);
}
}
getLogger().debug(stackLevel() + "classKBPartitionName: " + classKBPartitionName);
}
/** Processes the type level annotations to configure the domain entity settings */
protected void configureDomainEntitySettings() {
//Preconditions
assert typeLevelAnnotations != null : "typeLevelAnnotations must not be null";
typeOfs = new String[0];
subClassOfs = new String[0];
for (final Annotation annotation : typeLevelAnnotations) {
if (annotation instanceof DomainEntity) {
final DomainEntity domainEntity = (DomainEntity) annotation;
classTermName = domainEntity.className();
if (classTermName.isEmpty()) {
classTermName = domainEntityClass.getName();
} else {
getLogger().debug(stackLevel() + "className: " + classTermName);
}
typeOfs = domainEntity.typeOf();
subClassOfs = domainEntity.subClassOf();
break;
}
}
for (final String typeOf : typeOfs) {
getLogger().debug(stackLevel() + "typeOf: " + typeOf);
}
for (final String subClassOf : subClassOfs) {
getLogger().debug(stackLevel() + "subClassOf: " + subClassOf);
}
//Postconditions
assert classTermName != null : "classTermName must not be null";
assert !classTermName.isEmpty() : "classTermName must not be an empty string";
}
/** Gathers the field level annotations for the given class and its superclasses, returning them
* as a dictionary, field -> Id or DomainProperty annotation. Also populates the strength field
* dictionary.
*
* @param clazz the given class
*/
private void gatherFieldAnnotationDictionary(final Class clazz) {
//Preconditions
assert clazz != null : "clazz must not be null";
if (! clazz.equals(Object.class)) {
gatherFieldAnnotationDictionary(clazz.getSuperclass());
}
getLogger().debug(stackLevel() + "gathering field annotations for class: " + clazz.getName());
final Field[] fields = clazz.getDeclaredFields();
for (final Field field : fields) {
Annotation annotation = field.getAnnotation(DomainProperty.class);
if (annotation == null) {
annotation = field.getAnnotation(Id.class);
}
if (annotation != null) {
getLogger().debug(stackLevel() + "field: " + field.getName() + " annotation: " + annotation);
fieldAnnotationDictionary.put(field, annotation);
if (annotation instanceof DomainProperty) {
final DomainProperty domainProperty = (DomainProperty) annotation;
final String strengthFieldName = domainProperty.strengthField();
if (!strengthFieldName.isEmpty()) {
Field strengthField = null;
try {
strengthField = clazz.getDeclaredField(strengthFieldName);
} catch (final SecurityException ex) {
throw new TexaiException(ex);
} catch (final NoSuchFieldException ex) {
throw new TexaiException("strengthField not found for " + strengthFieldName, ex);
}
getLogger().debug(stackLevel() + " strengthField: " + strengthField.getName());
strengthFieldDictionary.put(field, strengthField);
}
}
}
annotation = field.getAnnotation(OrderBy.class);
if (annotation != null) {
orderByDictionary.put(field, (OrderBy) annotation);
}
}
}
/** Gets the logger.
*
* @return the logger
*/
abstract Logger getLogger();
/** Gets the domain entity class.
*
* @return the domain entity class
*/
public Class getDomainEntityClass() {
return domainEntityClass;
}
/** Sets the domain entity class.
*
* @param domainEntityClass the domain entity class
*/
public void setDomainEntityClass(final Class domainEntityClass) {
//Preconditions
assert domainEntityClass != null : "domainEntityClass must not be null";
this.domainEntityClass = domainEntityClass;
}
/** Gets the instantiated domain entity.
*
* @return the instantiated domain entity
*/
public Object getDomainEntity() {
return domainEntity;
}
/** Sets the instantiated domain entity.
*
* @param domainEntity the instantiated domain entity
*/
public void setDomainEntity(final Object domainEntity) {
//Preconditions
assert domainEntity != null : Constants.DOMAIN_ENTITY_ERR;
this.domainEntity = domainEntity;
}
/** Gets the array of package level annotations.
*
* @return the array of package level annotations
*/
public Annotation[] getPackageLevelAnnotations() {
return packageLevelAnnotations; // NOPMD
}
/** Gets the array of type level annotations.
*
* @return the array of type level annotations
*/
public Annotation[] getTypeLevelAnnotations() {
return typeLevelAnnotations; // NOPMD
}
/** Gets the dictionary of field level annotations.
*
* @return the dictionary of field level annotations, field -> Id or DomainProperty annotation
*/
public Map<Field, Annotation> getFieldAnnotationDictionary() {
return fieldAnnotationDictionary;
}
/** Gets the dictionary of OrderBy annotations.
*
* @return the dictionary of OrderBy annotations, field -> OrderBy annotation
*/
public Map<Field, OrderBy> getOrderByDictionary() {
return orderByDictionary;
}
/** Gets the dictionary of strength fields, strengthField -> field.
*
* @return the dictionary of strength fields, strengthField -> field
*/
public Map<Field, Field> getStrengthFieldDictionary() {
return strengthFieldDictionary;
}
/** Gets the name of the context into which the class-scoped associations are persisted.
*
* @return the name of the context into which the class-scoped associations are persisted
*/
public String getClassPersistenceContextName() {
return classPersistenceContextName;
}
/** Gets the list of context names for which the persist-to context is a subcontext in case of a new persist-to context,
* otherwise an empty list.
*
* @return the list of context names for which the persist-to context is a subcontext in case of a new persist-to context,
* otherwise an empty list
*/
public String[] getSubContextOfNames() {
return subContextOfNames; // NOPMD
}
/** Gets the name of the KB partition into which the class-scoped associations are persisted.
*
* @return the name of the KB partition into which the class-scoped associations are persisted
*/
public String getKBPartitionName() {
return classKBPartitionName;
}
/** Gets the types of this domain entity.
*
* @return the types of this domain entity
*/
public String[] getTypeOfs() {
return typeOfs; // NOPMD
}
/** Sets the types of this domain entity.
*
* @param typeOfs the types of this domain entity
*/
public void setTypeOfs(final String[] typeOfs) {
this.typeOfs = typeOfs;
}
/** Gets the super classes of this domain entity.
*
* @return the super classes of this domain entity
*/
public String[] getSubClassOfs() {
return subClassOfs; // NOPMD
}
/** Sets the super classes of this domain entity.
*
* @param subClassOfs the super classes of this domain entity
*/
public void setSubClassOfs(final String[] subClassOfs) {
this.subClassOfs = subClassOfs;
}
/** Gets the class term name.
*
* @return the class term name for this domain entity
*/
public String getClassTermName() {
return classTermName;
}
/** Sets the class term name.
*
* @param classTermName the class term name for this domain entity
*/
public void setClassTerm(final String classTermName) {
//Preconditions
assert classTermName != null : "classTermName must not be null";
this.classTermName = classTermName;
}
/** Gets the class term.
*
* @return the class term for this domain entity
*/
public AtomicTerm getClassTerm() {
return classTerm;
}
/** Sets the class term.
*
* @param classTerm the class term for this domain entity
*/
public void setClassTerm(final AtomicTerm classTerm) {
//Preconditions
assert classTerm != null : "classTerm must not be null";
this.classTerm = classTerm;
}
/** Gets the context from which the class-scoped associations are persisted.
*
* @return the context from which the class-scoped associations are persisted
*/
public AbstractReifiedTerm getClassPersistenceContext() {
return classPersistenceContext;
}
/** Sets the context from which the class-scoped associations are persisted.
*
* @param classPersistenceContext the context from which the class-scoped associations are persisted
*/
public void setClassPersistenceContext(final AbstractReifiedTerm classPersistenceContext) {
this.classPersistenceContext = classPersistenceContext;
}
/** Gets the KB partition from which the class-scoped associations are persisted.
*
* @return the KB partition from which the class-scoped associations are persisted
*/
public AtomicTerm getClassKBPartition() {
return classKBPartition;
}
/** Sets the KB partition from which the class-scoped associations are persisted.
*
* @param classLoadFromContext the context from which the class-scoped associations are persisted
*/
public void setClassKBPartition(final AtomicTerm classKBPartition) {
this.classKBPartition = classKBPartition;
}
/** Gets the instance term.
*
* @return the instance term
*/
public AtomicTerm getInstanceTerm() {
return instanceTerm;
}
/** Sets the instance term.
*
* @param instanceTerm the instance term
*/
public void setInstanceTerm(final AtomicTerm instanceTerm) {
this.instanceTerm = instanceTerm;
}
/** Returns the stack level for logging.
*
* @return the stack level for logging.
*/
public String stackLevel() {
//Preconditions
assert domainEntityInfoStack != null : "domainEntityInfoStack must not be null";
return "[" + domainEntityInfoStack.size() + "] ";
}
/** Pushes the current session bean state onto a stack and then intitializes the session state.
*
* @param domainEntity the instantiated domain entity
* @param packageLevelAnnotations the array of package level annotations
* @param typeLevelAnnotations the array of type level annotations
* @param fieldAnnotationDictionary the dictionary of field level annotations, field -> array of annotations
* @param orderByDictionary the dictionary of orderBy annotations, field -> Id or OrderBy annotation
* @param strengthFieldDictionary the dictionary of strength fields, strengthField -> field
* @param classLoadFromContextName the name of the context from which the class-scoped associations are loaded
* @param classPersistToContextName the name of the context into which the class-scoped associations are persisted
* @param subContextOfNames the list of context names for which the persist-to context is a subcontext in case of a new persist-to
* context, otherwise an empty list
* @param typeOfs the types of this domain entity
* @param subClassOfs the super classes of this domain entity
* @param classTermName the class term name
* @param classTerm the class term
*/
protected void saveAbstractSessionState() {
//Preconditions
assert domainEntityInfoStack != null : "domainEntityInfoStack must not be null";
getLogger().debug(stackLevel() + "saving abstract session state");
domainEntityInfoStack.push(new AbstractDomainEntityInfo(
domainEntityClass,
domainEntity,
packageLevelAnnotations,
typeLevelAnnotations,
fieldAnnotationDictionary,
orderByDictionary,
strengthFieldDictionary,
classPersistenceContextName,
subContextOfNames,
classKBPartitionName,
typeOfs,
subClassOfs,
classTermName,
classTerm,
classPersistenceContext,
instanceTerm));
}
/** Initializes the session bean state. */
protected void initializeAbstractSessionState() {
domainEntityClass = null; // NOPMD
domainEntity = null; // NOPMD
packageLevelAnnotations = null; // NOPMD
typeLevelAnnotations = null; // NOPMD
fieldAnnotationDictionary = new HashMap<Field,Annotation>();
orderByDictionary = new HashMap<Field, OrderBy>();
strengthFieldDictionary = new HashMap<Field, Field>();
classPersistenceContextName = null; // NOPMD
subContextOfNames = null; // NOPMD
classKBPartitionName = null; // NOPMD
typeOfs = null; // NOPMD
subClassOfs = null; // NOPMD
classTermName = null; // NOPMD
classTerm = null; // NOPMD
classPersistenceContext = null; // NOPMD
instanceTerm = null; // NOPMD
}
/** Restores the session state following a recursive method call. */
protected void restoreAbstractSessionState() {
//Preconditions
assert domainEntityInfoStack != null : "domainEntityInfoStack must not be null";
final AbstractDomainEntityInfo abstractDomainEntityInfo = (AbstractDomainEntityInfo) domainEntityInfoStack.pop();
domainEntityClass = abstractDomainEntityInfo.domainEntityClass;
domainEntity = abstractDomainEntityInfo.domainEntity;
packageLevelAnnotations = abstractDomainEntityInfo.packageLevelAnnotations;
typeLevelAnnotations = abstractDomainEntityInfo.typeLevelAnnotations;
fieldAnnotationDictionary = abstractDomainEntityInfo.fieldAnnotationDictionary;
orderByDictionary = abstractDomainEntityInfo.orderByDictionary;
strengthFieldDictionary = abstractDomainEntityInfo.strengthFieldDictionary;
classPersistenceContextName = abstractDomainEntityInfo.classPersistenceContextName;
subContextOfNames = abstractDomainEntityInfo.subContextOfNames;
classKBPartitionName = abstractDomainEntityInfo.classKBPartitionName;
typeOfs = abstractDomainEntityInfo.typeOfs;
subClassOfs = abstractDomainEntityInfo.subClassOfs;
classTermName = abstractDomainEntityInfo.classTermName;
classTerm = abstractDomainEntityInfo.classTerm;
classPersistenceContext = abstractDomainEntityInfo.classLoadFromContext;
instanceTerm = abstractDomainEntityInfo.instanceTerm;
getLogger().debug(stackLevel() + "restored abstract session state");
}
/** Contains the session bean state for recursive method calls. */
private class AbstractDomainEntityInfo { // NOPMD
/** the domain entity class */
private final transient Class domainEntityClass; // NOPMD
/** the instantiated domain entity */
private final transient Object domainEntity; // NOPMD
/** the array of package level annotations */
private final transient Annotation[] packageLevelAnnotations; // NOPMD
/** the array of type level annotations */
private final transient Annotation[] typeLevelAnnotations; // NOPMD
/** the dictionary of field level annotations, field -> Id or DomainProperty annotation */
private final transient Map<Field, Annotation> fieldAnnotationDictionary; // NOPMD
/** the dictionary of orderBy annotations, field -> Id or OrderBy annotation */
private final transient Map<Field, OrderBy> orderByDictionary; // NOPMD
/** the dictionary of strength fields, field -> strength field */
private final transient Map<Field, Field> strengthFieldDictionary; // NOPMD
/** the name of the context into which the class-scoped associations are persisted */
private final transient String classPersistenceContextName; // NOPMD
/** the list of context names for which the persist-to context is a subcontext in case of a new persist-to context,
* otherwise an empty list
*/
private final transient String[] subContextOfNames; // NOPMD
/** the name of the KB partition into which the class-scoped associations are persisted */
private final transient String classKBPartitionName; // NOPMD
/** the types of this domain entity */
private final transient String[] typeOfs; // NOPMD
/** the super classes of this domain entity */
private final transient String[] subClassOfs; // NOPMD
/** the class term name */
private final transient String classTermName; // NOPMD
/** the class term */
private final transient AtomicTerm classTerm; // NOPMD
/** the context from which the class-scoped associations are loaded */
private final transient AbstractReifiedTerm classLoadFromContext; // NOPMD
/** the instance term */
private final transient AtomicTerm instanceTerm; // NOPMD
/**
* Creates a new AbstractDomainEntityInfo instance.
*
* @param domainEntityClass the domain entity class
* @param domainEntity the instantiated domain entity
* @param packageLevelAnnotations the array of package level annotations
* @param typeLevelAnnotations the array of type level annotations
* @param fieldAnnotationDictionary the dictionary of field level annotations, field -> Id or DomainProperty annotation
* @param orderByDictionary the dictionary of orderBy annotations, field -> Id or OrderBy annotation
* @param strengthFieldDictionary the dictionary of strength fields, field -> strength field
* @param classPersistenceContextName the name of the context into which the class-scoped associations are persisted
* @param subContextOfNames the list of context names for which the persist-to context is a subcontext in case of a new
* persist-to context, otherwise an empty list
* @param classKBPartitionName the name of the KB partition into which the class-scoped associations are persisted
* @param typeOfs the types of this domain entity
* @param subClassOfs the super classes of this domain entity
* @param classTermName the class term name
* @param classTerm the class term
* @param classLoadFromContext the context from which the class-scoped associations are loaded
* @param instanceTerm the instance term
*/
protected AbstractDomainEntityInfo( // NOPMD
final Class domainEntityClass,
final Object domainEntity,
final Annotation[] packageLevelAnnotations,
final Annotation[] typeLevelAnnotations,
final Map<Field, Annotation> fieldAnnotationDictionary,
final Map<Field, OrderBy> orderByDictionary,
final Map<Field, Field> strengthFieldDictionary,
final String classPersistenceContextName,
final String[] subContextOfNames,
final String classKBPartitionName,
final String[] typeOfs,
final String[] subClassOfs,
final String classTermName,
final AtomicTerm classTerm,
final AbstractReifiedTerm classLoadFromContext,
final AtomicTerm instanceTerm) {
super();
this.domainEntityClass = domainEntityClass;
this.domainEntity = domainEntity;
this.packageLevelAnnotations = packageLevelAnnotations;
this.typeLevelAnnotations = typeLevelAnnotations;
this.fieldAnnotationDictionary = fieldAnnotationDictionary;
this.orderByDictionary = orderByDictionary;
this.strengthFieldDictionary = strengthFieldDictionary;
this.classPersistenceContextName = classPersistenceContextName;
this.subContextOfNames = subContextOfNames;
this.classKBPartitionName = classKBPartitionName;
this.typeOfs = typeOfs;
this.subClassOfs = subClassOfs;
this.classTermName = classTermName;
this.classTerm = classTerm;
this.classLoadFromContext = classLoadFromContext;
this.instanceTerm = instanceTerm;
}
}
}
See more files for this project here