Start line:  
End line:  

Snippet Preview

Snippet HTML Code

Stack Overflow Questions
  /*
   * OfficeFloor - http://www.officefloor.net
   * Copyright (C) 2005-2011 Daniel Sagenschneider
   *
   * 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 3 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, see <http://www.gnu.org/licenses/>.
  */
 
 package net.officefloor.plugin.managedobject.clazz;
 
 import java.util.List;
 import java.util.Map;
 import java.util.Set;
 
net.officefloor.frame.spi.managedobject.source.ManagedObjectSource that manages an java.lang.Object via reflection.

Author(s):
Daniel Sagenschneider
 
 public class ClassManagedObjectSource extends
Convenience method to aid in unit testing.

Parameters:
clazz java.lang.Class to instantiate and have dependencies injected.
dependencyNameObjectListing Listing of dependency name and dependency object pairs to be injected.
Returns:
Instance of the java.lang.Class with the dependencies injected.
Throws:
java.lang.Exception If fails to instantiate the instance and inject the dependencies.
 
 	public static <T> T newInstance(Class<T> clazz,
 			Object... dependencyNameObjectListingthrows Exception {
 
 		// Create the map of dependencies
 		Map<StringObjectdependencies = new HashMap<StringObject>();
 		for (int i = 0; i < dependencyNameObjectListing.lengthi += 2) {
 			String name = dependencyNameObjectListing[i].toString();
 			Object dependency = dependencyNameObjectListing[i + 1];
 			dependencies.put(namedependency);
 		}
 
 		// Return the new instance
 		return newInstance(clazzdependencies);
 	}

Convenience method to aid in unit testing.

As many Dependency java.lang.reflect.Field instances will be private they are unlikely to be accessible in unit tests unless a specific constructor is provided. This method enables instantiation and injecting of dependencies to enable unit testing.

Parameters:
clazz java.lang.Class to instantiate and have dependencies injected.
dependencies Map of dependencies by the dependency name. The dependency name is the Dependency java.lang.reflect.Field name. Should two java.lang.reflect.Field instances in the class hierarchy have the same name, the dependency name is qualified with the declaring java.lang.Class name.
Returns:
Instance of the java.lang.Class with the dependencies injected.
Throws:
java.lang.Exception If fails to instantiate the instance and inject the dependencies.
	public static <T> T newInstance(Class<T> clazz,
			Map<StringObjectdependenciesthrows Exception {
		// Instantiate the object
object = clazz.newInstance();
		// Obtain the listing of dependency fields
		List<FielddependencyFields = retrieveDependencyFields(clazz);
		orderFields(dependencyFields);
		// Inject the dependencies
		for (Field dependencyField : dependencyFields) {
			// Obtain the dependency name
			String dependencyName = retrieveDependencyName(dependencyField,
					dependencyFields);
			// Obtain the dependency
			Object dependency = dependencies.get(dependencyName);
			// Inject the dependency
			dependencyField.setAccessible(true);
			dependencyField.set(objectdependency);
		}
		// Obtain the listing of process fields
		List<FieldprocessFields = new ArrayList<Field>(processStructs.size());
		for (ProcessStruct processStruct : processStructs) {
			processFields.add(processStruct.field);
		}
		// Inject the processes
		for (Field processField : processFields) {
			// Obtain the process name (as dependency inject interface)
			String dependencyName = retrieveDependencyName(processField,
					processFields);
			// Obtain the dependency (process interface)
			Object dependency = dependencies.get(dependencyName);
			// Inject the process interface
			processField.setAccessible(true);
			processField.set(objectdependency);
		}
		// Return the instance with dependencies and process interfaces injected
		return object;
	}

Property name providing the java.lang.Class name.
	public static final String CLASS_NAME_PROPERTY_NAME = "class.name";

java.lang.Class of the java.lang.Object being managed.
	private Class<?> objectClass;

DependencyMetaData instances.
ProcessMetaData instances.
Allows overriding the extraction of the dependency java.lang.reflect.Field instances.

Parameters:
objectClass Class to extract dependency java.lang.reflect.Field instances.
Returns:
Listing of java.lang.reflect.Field instances to be dependency injected.
	protected List<FieldextractDependencyFields(Class<?> objectClass) {
		return retrieveDependencyFields(objectClass);
	}

Extracts the DependencyMetaData from the object class.

Parameters:
objectClass Object class to interrogate for the DependencyMetaData instances.
Returns:
DependencyMetaData instances.
	public DependencyMetaData[] extractDependencyMetaData(Class<?> objectClass) {
		// Obtains the ordered dependency fields
		List<FielddependencyFields = this
		orderFields(dependencyFields);
		// Create the dependency meta-data and register the dependencies
		List<DependencyMetaDatadependencyListing = new LinkedList<DependencyMetaData>();
		int dependencyIndex = 0;
		for (Field dependencyField : dependencyFields) {
			// Obtain the name for the dependency
			String dependencyName = retrieveDependencyName(dependencyField,
					dependencyFields);
			// Add the dependency meta-data, ensuring can access field
			dependencyField.setAccessible(true);
			dependencyListing.add(new DependencyMetaData(dependencyName,
					dependencyIndex++, dependencyField));
		}
		DependencyMetaData[] dependencyMetaData = dependencyListing
				.toArray(new DependencyMetaData[dependencyListing.size()]);
		// Return the dependency meta-data
		return dependencyMetaData;
	}
	/*
	 * =================== ManagedObjectSourceService ==========================
	 */
		return "CLASS";
	}
	}
	/*
	 * ==================== AbstractManagedObjectSource ========================
	 */
	protected void loadSpecification(SpecificationContext context) {
	}
	protected void loadMetaData(MetaDataContext<IndexedIndexedcontext)
			throws Exception {
		ManagedObjectSourceContext<IndexedmosContext = context
		// Obtain the class
		String className = mosContext.getProperty();
		this. = mosContext.getClassLoader().loadClass(className);
		// Provide managed object class to indicate coordinating
		// Class is the object type returned from the managed object
		// Create the dependency meta-data and register the dependencies
		this. = this
		for (DependencyMetaData dependency : this.) {
			// Register the dependency
			context.addDependency(dependency.field.getType()).setLabel(
					dependency.name);
		}
		// Obtain the process details
		// Register the processes to be invoked
		for (ProcessStruct processStruct : this.) {
			// Ensure can access field
			processStruct.field.setAccessible(true);
			// Register the process methods for the field
			for (Method processMethod : processStruct.invokeMethods) {
				// Obtain the process name
				String processName = retrieveProcessName(processStruct.field,
						processMethodthis.);
				// Obtain the argument type
				Class<?>[] methodParameters = processMethod.getParameterTypes();
				Class<?> argumentType = (methodParameters.length == 1 ? methodParameters[0]
null);
				// Add the flow
				context.addFlow(argumentType).setLabel(processName);
			}
		}
		// Hold reference to class loader for start method
		this. = mosContext.getClassLoader();
		// Add the object class as extension interface.
		ClassExtensionInterfaceFactory.registerExtensionInterface(context,
	}
	public void start(ManagedObjectExecuteContext<Indexedcontext)
			throws Exception {
		// Create the process meta-data
		List<ProcessMetaDataprocessListing = new LinkedList<ProcessMetaData>();
		int processIndex = 0;
		for (ProcessStruct struct : this.) {
			// Create the map of method name to its process index
			Map<StringIntegerindexes = new HashMap<StringInteger>(
					struct.invokeMethods.length);
			for (Method invokeMethod : struct.invokeMethods) {
				indexes
						.put(invokeMethod.getName(),
								new Integer(processIndex++));
			}
			// Create and add the process meta-data
			processListing.add(new ProcessMetaData(struct.fieldindexes,
					this.context));
		}
		// Only required process meta-data
		this. = processListing.toArray(new ProcessMetaData[0]);
		this. = null// discard as no longer required
		this. = null// discard to allow garbage collection
	}
	protected ManagedObject getManagedObject() throws Throwable {
		// Create an instance of the object
		Object object = this..newInstance();
		// Return a managed object to manage the object
		return new ClassManagedObject(objectthis.,
	}

Retrieves the unique Dependency inject name for java.lang.reflect.Field.

Parameters:
field java.lang.reflect.Field.
allInjectFields Listing of all Dependency inject java.lang.reflect.Field instances.
Returns:
Unique Dependency inject name for the java.lang.reflect.Field.
	private static String retrieveDependencyName(Field injectField,
			List<FieldallInjectFields) {
		// Determine the name for the inject field
		String injectName;
		String fieldInjectName = injectField.getName();
		boolean isAnotherByFieldName = false;
		for (Field field : allInjectFields) {
			if (field != injectField) {
				if (field.getName().equals(fieldInjectName)) {
					// Another field by the same name
					isAnotherByFieldName = true;
				}
			}
		}
		if (!isAnotherByFieldName) {
			// Field name unique so use it
			injectName = fieldInjectName;
else {
			// Field name not unique, so add class name for making unique
			String classInjectName = injectField.getDeclaringClass()
"." + injectField.getName();
			boolean isAnotherByClassName = false;
			for (Field field : allInjectFields) {
				if (field != injectField) {
					String fieldClassName = field.getDeclaringClass()
"." + field.getName();
					if (fieldClassName.equals(classInjectName)) {
						// Another field by same class name
						isAnotherByClassName = true;
					}
				}
			}
			if (!isAnotherByClassName) {
				// Class name unique so use it
				injectName = classInjectName;
else {
				// Use fully qualified name of field
				injectName = injectField.getDeclaringClass().getName() + "."
injectField.getName();
			}
		}
		// Return the inject name
		return injectName;
	}

Retrieves the Dependency java.lang.reflect.Field instances.

Parameters:
clazz java.lang.Class to interrogate for Dependency java.lang.reflect.Field instances.
Returns:
Listing of Dependency java.lang.reflect.Field instances ordered by their names.
	private static List<FieldretrieveDependencyFields(Class<?> clazz) {
		// Create the listing of dependency fields (excluding Object fields)
		List<FielddependencyFields = new LinkedList<Field>();
		Class<?> interrogateClass = clazz;
		while ((interrogateClass != null)
				&& (!Object.class.equals(interrogateClass))) {
			for (Field field : interrogateClass.getDeclaredFields()) {
				if (field.getAnnotation(Dependency.class) != null) {
					// Annotated as a dependency field
					dependencyFields.add(field);
				}
			}
			interrogateClass = interrogateClass.getSuperclass();
		}
		// Return the dependency fields
		return dependencyFields;
	}

Obtains the unique process name.

Parameters:
processInterfaceField java.lang.reflect.Field annotated with ProcessInterface.
processMethod java.lang.reflect.Method of the java.lang.reflect.Field type.
processStructs Details of all ProcessInterface annotated java.lang.reflect.Field instances.
Returns:
Unique process name.
	private static String retrieveProcessName(Field processInterfaceField,
			Method processMethodList<ProcessStructprocessStructs) {
		// Determine the process name
		String processName;
		String methodName = processMethod.getName();
		boolean isAnotherByMethodName = false;
		for (ProcessStruct struct : processStructs) {
			for (Method invokeMethod : struct.invokeMethods) {
				if (processMethod != invokeMethod) {
					if (invokeMethod.getName().equals(methodName)) {
						// Another method by the same name
						isAnotherByMethodName = true;
					}
				}
			}
		}
		if (!isAnotherByMethodName) {
			// Method name unique so use it
			processName = methodName;
else {
			// Method name not unique, so add field name for making unique
			String fieldProcessName = processInterfaceField.getName() + "."
processMethod.getName();
			boolean isAnotherByFieldName = false;
			for (ProcessStruct struct : processStructs) {
				for (Method invokeMethod : struct.invokeMethods) {
					if (processMethod != invokeMethod) {
						String compareName = struct.field.getName() + "."
invokeMethod.getName();
						if (compareName.equals(fieldProcessName)) {
							// Another method by field name
							isAnotherByFieldName = true;
						}
					}
				}
			}
			if (!isAnotherByFieldName) {
				// Field name unique so use it
				processName = fieldProcessName;
else {
				// Use fully qualified name of process method
				processName = processInterfaceField.getDeclaringClass()
"."
processInterfaceField.getName()
"."
processMethod.getName();
			}
		}
		// Return the process name
		return processName;
	}

Retrieves the ClassManagedObjectSource.ProcessStruct instances for the ProcessInterface java.lang.reflect.Field instances ordered by:

  1. field name
  2. simple class name . field name
  3. fully qualified class . field name
with all java.lang.reflect.Method instances of each java.lang.reflect.Field sorted by the java.lang.reflect.Method name.

Ordering is necessary to ensure similar indexes each time loaded.

Parameters:
clazz java.lang.Class to interrogate for ProcessInterface java.lang.reflect.Field instances.
Returns:
Listing of ProcessInterface java.lang.reflect.Field instances ordered by their names.
Throws:
java.lang.Exception Should a ProcessInterface injection type be invalid.
			Class<?> clazzthrows Exception {
		// Create the listing of process fields (excluding Object fields)
		List<FieldprocessFields = new LinkedList<Field>();
		Class<?> interrogateClass = clazz;
		while ((interrogateClass != null)
				&& (!Object.class.equals(interrogateClass))) {
			for (Field field : interrogateClass.getDeclaredFields()) {
				if (field.getType().getAnnotation(FlowInterface.class) != null) {
					// Annotated as a flow interface field
					processFields.add(field);
				}
			}
			interrogateClass = interrogateClass.getSuperclass();
		}
		// Order the fields
		orderFields(processFields);
		// Create the listing of process structs
		List<ProcessStructprocessStructs = new LinkedList<ProcessStruct>();
		for (Field processField : processFields) {
			// Obtain the process field type
			Class<?> type = processField.getType();
			if (!type.isInterface()) {
				throw new Exception(
						"Type for field "
processField.getName()
" must be an interface as the type is annotated with "
" (type=" + type.getName() + ")");
			}
			// Obtain the non Object methods
			List<Methodmethods = new LinkedList<Method>();
			Set<StringmethodNames = new HashSet<String>();
			for (Method method : type.getMethods()) {
				// Ensure not an Object method
				if (Object.class.equals(method.getDeclaringClass())) {
					continue;
				}
				// Ensure the method name is unique for the type
				String methodName = method.getName();
				if (methodNames.contains(methodName)) {
					throw new Exception(
							"May not have duplicate process method names (field="
processField.getName() + ", type="
type.getName() + ", method=" + methodName
")");
				}
				methodNames.add(methodName);
				// Ensure at most only one parameter to the method
				Class<?>[] parameterTypes = method.getParameterTypes();
				if (parameterTypes.length > 1) {
					throw new Exception(
							"Process methods may only have at most one parameter (field="
processField.getName() + ", method="
methodName + ")");
				}
				// Ensure no return from method
				Class<?> returnType = method.getReturnType();
				if ((returnType != null) && (!(..equals(returnType)))) {
					throw new Exception(
							"Process methods may only be void in return type (field="
processField.getName() + ", method="
methodName + ")");
				}
				// Add the valid method
				methods.add(method);
			}
			// Create the sorted array of methods
			Method[] invokeMethods = methods.toArray(new Method[0]);
			Arrays.sort(invokeMethodsnew Comparator<Method>() {
				public int compare(Method aMethod b) {
					return a.getName().compareTo(b.getName());
				}
			});
			// Create and add the process interface details
			processStructs.add(new ProcessStruct(processFieldinvokeMethods));
		}
		// Return the process fields
		return processStructs;
	}

Details of a ProcessInterface on the class.
	private static class ProcessStruct {

java.lang.reflect.Field to inject the ProcessInterface.
		public final Field field;

java.lang.reflect.Method instances to invoke the processes.
		public final Method[] invokeMethods;

Initiate.

Parameters:
field java.lang.reflect.Field to inject the ProcessInterface.
invokeMethods java.lang.reflect.Method instances to invoke the processes.
		public ProcessStruct(Field fieldMethod[] invokeMethods) {
			this. = field;
			this. = invokeMethods;
		}
	}

Orders the java.lang.reflect.Field instances.

Dependency java.lang.reflect.Field instances are ordered by:

  1. field name
  2. simple class name . field name
  3. fully qualified class . field name

Ordering is necessary to ensure similar indexes each time loaded.

Parameters:
fields java.lang.reflect.Field instances to order.
	private static void orderFields(List<Fieldfields) {
		// Sort the fields by field name, then class, then package.
		// This is necessary to keep indexes the same.
		Collections.sort(fieldsnew Comparator<Field>() {
			public int compare(Field aField b) {
				// Compare by field names first
				if (!(a.getName().equals(b.getName()))) {
					// Field names different so compare by them
					return a.getName().compareTo(b.getName());
				}
				// Same field name so use the simple class name
				Class<?> aClass = a.getDeclaringClass();
				Class<?> bClass = b.getDeclaringClass();
				if (!(aClass.getSimpleName().equals(bClass.getSimpleName()))) {
					// Simple class names different so compare by them
					return aClass.getSimpleName().compareTo(
							bClass.getSimpleName());
				}
				// Field and simple class name same so compare by package
				return aClass.getPackage().getName().compareTo(
						bClass.getPackage().getName());
			}
		});
	}
New to GrepCode? Check out our FAQ X