All Downloads are FREE. Search and download functionalities are using the official Maven repository.

com.googlecode.mjorm.annotations.AnnotationsObjectDescriptorParser Maven / Gradle / Ivy

package com.googlecode.mjorm.annotations;

import java.beans.BeanInfo;
import java.lang.reflect.Method;
import java.lang.reflect.Type;
import java.util.ArrayList;
import java.util.Collection;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import org.bson.types.ObjectId;

import com.googlecode.mjorm.DiscriminatorType;
import com.googlecode.mjorm.MjormException;
import com.googlecode.mjorm.MappingUtil;
import com.googlecode.mjorm.ObjectDescriptor;
import com.googlecode.mjorm.ObjectIdValueGenerator;
import com.googlecode.mjorm.PropertyDescriptor;
import com.googlecode.mjorm.ReflectionUtil;
import com.googlecode.mjorm.ValueGenerator;
import com.googlecode.mjorm.convert.JavaType;

/**
 * "Parses" objects with mapping annotations and
 * returns {@link ObjectDescriptor}s.
 */
public class AnnotationsObjectDescriptorParser {

	/**
	 * Parses the given {@link Class}s and returns {@link ObjectDescriptor}s
	 * for them.
	 * @param classes the classes to parse
	 * @return the {@link ObjectDescriptor}s
	 */
	public List parseClasses(Class... classes) {
		List ret = new ArrayList();
		for (Class clazz : classes) {
			ret.add(parseClass(clazz, ret));
		}
		return ret;
	}

	/**
	 * Parses the given {@link Class}s and returns {@link ObjectDescriptor}s
	 * for them.
	 * @param classes the classes to parse
	 * @return the {@link ObjectDescriptor}s
	 */
	public List parseClasses(Collection> classes) {
		return parseClasses(classes.toArray(new Class[0]));
	}

	/**
	 * Parses the given {@link Class} and returns an {@link ObjectDescriptor}
	 * for it.
	 * @param clazz the class to parse
	 * @return the {@link ObjectDescriptor}
	 */
	private ObjectDescriptor parseClass(Class clazz, List descriptors) {

		// get the entity annotation
		Entity entity = clazz.getAnnotation(Entity.class);
		if (entity==null) {
			throw new MjormException(
				clazz.getName()+" does not have an "+Entity.class.getName()+" annotation");
		}

		// parse entity date
		String discriminatorName = entity.discriminatorName();
		DiscriminatorType discriminatorType = entity.discriminatorType();
		SubClass[] subClasses = entity.subClasses();

		// create an object descriptor
		ObjectDescriptor desc = new ObjectDescriptor();
		desc.setType(clazz);
		desc.setDiscriminatorName(discriminatorName);
		desc.setDiscriminatorType(discriminatorType.toString());

		// get BeanInfo
		BeanInfo info = ReflectionUtil.getBeanInfo(clazz);
		Map methodMap
			= new HashMap();
		for (java.beans.PropertyDescriptor pd : info.getPropertyDescriptors()) {
			methodMap.put(pd.getReadMethod(), pd);
			methodMap.put(pd.getWriteMethod(), pd);
		}

		// get all of the methods
		for (Method method : clazz.getMethods()) {

			// look for the annotations
			Property property = method.getAnnotation(Property.class);
			Id id = method.getAnnotation(Id.class);
			if (property==null) {
				continue;
			}

			// find pd
			java.beans.PropertyDescriptor pd = methodMap.get(method);
			if (pd==null) {
				throw new MjormException(
					method.getName()+" is not not a valid bean method.");
			}

			// "parse" data
			String propField = !property.field().equals("")
				? property.field()
				: pd.getName();
			Type propType = !property.type().equals(void.class)
				? property.type()
				: pd.getReadMethod().getGenericReturnType();
			Type storageType = !property.storageType().equals(void.class)
				? property.storageType()
				: null;
			Class valueGeneratorClass = !property.valueGeneratorClass().equals(void.class)
				? property.valueGeneratorClass()
				: null;
			Type[] genericParameterTypes = property.genericParameterTypes().length>0
				? property.genericParameterTypes()
				: new Type[0];
			boolean propIsIdentifier = (id!=null);
			boolean propIsAutoGen = (id!=null && id.autoGenerated());

			// get the hints
			Map hints = new HashMap();
			if (property.typeConversionHints()!=null) {
				for (TypeConversionHint hint : property.typeConversionHints()) {
					hints.put(hint.name(), hint.stringValue());
				}
			}

			// create the PropertyDescriptor
			PropertyDescriptor prop = new PropertyDescriptor();
			prop.setName(pd.getName());
			prop.setFieldName(propField);
			prop.setGetter(pd.getReadMethod());
			prop.setSetter(pd.getWriteMethod());
			prop.setIdentifier(propIsIdentifier);
			prop.setType(JavaType.fromType(propType));
			prop.setAutoGenerated(propIsAutoGen);
			prop.setConversionHints(hints);
			prop.setGenericParameterTypes(genericParameterTypes);
			if (propIsAutoGen) {
				ValueGenerator valueGenerator = null;
				if (valueGeneratorClass==null) {
					valueGenerator = ObjectIdValueGenerator.INSTANCE;
					storageType =  ObjectId.class;
				} else {
					try {
						valueGenerator = ValueGenerator.class.cast(valueGeneratorClass.newInstance());
					} catch(Exception e) {
						throw new IllegalArgumentException(
							"Unable to create ValueGenerator for "+valueGeneratorClass.getName(), e);
					}
				}
				prop.setValueGenerator(valueGenerator);
			}

			// set the storage type
			if (storageType!=null) {
				prop.setStorageType(JavaType.fromType(storageType));
			}

			// add to descriptor
			desc.addPropertyDescriptor(prop);
		}

		// parse subclasses
		for (SubClass subClassAnot : subClasses) {

			// get discriminator value
			Object discriminatorValue = MappingUtil.parseDiscriminator(
				subClassAnot.discriminiatorValue(), discriminatorType);

			// parse sub class
			ObjectDescriptor subClass = parseClass(subClassAnot.entityClass(), descriptors);

			// add subclass
			desc.addSubClassObjectDescriptor(discriminatorValue, subClass);
			descriptors.add(subClass);
		}

		// return it
		return desc;
	}

}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy