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

org.robobinding.codegen.presentationmodel.processor.PresentationModelInfoBuilder Maven / Gradle / Ivy

Go to download

A set of RoboBinding Code Generation tools by utilizing Java annotation processors

There is a newer version: 0.8.14
Show newest version
package org.robobinding.codegen.presentationmodel.processor;

import java.util.Collection;
import java.util.List;
import java.util.Map;
import java.util.Set;

import org.robobinding.annotation.DependsOnStateOf;
import org.robobinding.annotation.ItemPresentationModel;
import org.robobinding.binder.PresentationModelObjectLoader;
import org.robobinding.codegen.apt.element.GetterElement;
import org.robobinding.codegen.apt.element.MethodElement;
import org.robobinding.codegen.apt.element.SetterElement;
import org.robobinding.codegen.apt.element.WrappedTypeElement;
import org.robobinding.codegen.presentationmodel.DataSetPropertyInfo;
import org.robobinding.codegen.presentationmodel.EventMethodInfo;
import org.robobinding.codegen.presentationmodel.PresentationModelInfo;
import org.robobinding.codegen.presentationmodel.PropertyDependencyInfo;
import org.robobinding.codegen.presentationmodel.PropertyInfo;

import com.google.common.collect.Maps;
import com.google.common.collect.Sets;

/**
 * @since 1.0
 * @author Cheng Wei
 * 
 */
public class PresentationModelInfoBuilder {

	private final WrappedTypeElement typeElement;
	private final boolean dataSetPropertyEnabled;
	private final String presentationModelObjectTypeName;
	
	private final Set propertyNames;
	private final Map propertyBuilders;
	private final Map dataSetProperties;
	private final Set propertyDependencies;
	private final Map eventMethods;
	private final Map methods;
	
	private final PresentationModelErrors errors;

	
	public PresentationModelInfoBuilder(WrappedTypeElement typeElement, 
			String presentationModelObjectTypeName, boolean dataSetPropertyEnabled) {
		this.typeElement = typeElement;
		this.dataSetPropertyEnabled = dataSetPropertyEnabled;
		this.presentationModelObjectTypeName = presentationModelObjectTypeName;
		
		propertyNames = Sets.newHashSet();
		propertyBuilders = Maps.newHashMap();
		dataSetProperties = Maps.newHashMap();
		propertyDependencies = Sets.newHashSet();
		eventMethods = Maps.newHashMap();
		methods = Maps.newHashMap();
		
		errors = new PresentationModelErrors(typeElement.qName());
	}

	public PresentationModelInfo build() {
		List methods = typeElement.methodsRecursively(new PresentationModelMethodFilter());
		classifyMethods(methods);
		
		processDataSetProperties();
		processProperties();
		validateDependencies();
		
		errors.assertNoErrors();
		return createPresentationModelInfo();
	}

	private void classifyMethods(List methods) {
		for(MethodElement method : methods) {
			if(method.isGetter()) {
				addGetter(method.asGetter());
			} else if(method.isSetter()) {
				addSetter(method.asSetter());
			} else if(isEventMethod(method)){//the rest are event methods.
				addEventMethod(method);
				addMethod(method);
			} else {
				addMethod(method);
			}
		}
		
	}

	private void addGetter(GetterElement getter) {
		String propertyName = getter.propertyName();
		
		if(isDataSetProperty(getter)) {
			ItemPresentationModelAnnotationMirror annotation = new ItemPresentationModelAnnotationMirror(
					getter.getAnnotation(ItemPresentationModel.class));
			DataSetPropertyInfoBuilder dataSetProperty = new DataSetPropertyInfoBuilder(getter, 
					annotation, itemPresentationModelObjectTypeNameOf(annotation));
			dataSetProperties.put(propertyName, dataSetProperty);
		} else {
			PropertyInfoBuilder propertyBuilder = getFromPropertyBuilders(propertyName);
			propertyBuilder.setGetter(getter);
		}
		
		if(getter.hasAnnotation(DependsOnStateOf.class)) {
			addDependency(propertyName, getter);
		}

		propertyNames.add(propertyName);
	}

	private boolean isDataSetProperty(GetterElement getter) {
		return dataSetPropertyEnabled && getter.hasAnnotation(ItemPresentationModel.class);
	}

	private String itemPresentationModelObjectTypeNameOf(ItemPresentationModelAnnotationMirror annotation) {
		return PresentationModelObjectLoader.getItemObjectClassName(annotation.itemPresentationModelTypeBinaryName());
	}

	private PropertyInfoBuilder getFromPropertyBuilders(String propertyName) {
		if(!propertyBuilders.containsKey(propertyName)) {
			PropertyInfoBuilder propertyBuilder = new PropertyInfoBuilder(propertyName);
			propertyBuilders.put(propertyName, propertyBuilder);
		}
		
		return propertyBuilders.get(propertyName);
	}
	
	private void addDependency(String propertyName, GetterElement getter) {
		DependsOnStateOfAnnotationMirror annotation = new DependsOnStateOfAnnotationMirror(
				getter.getAnnotation(DependsOnStateOf.class));
		if(annotation.hasDependentProperty()) {
			PropertyDependencyInfo dependencyInfo = new PropertyDependencyInfo(propertyName, annotation.dependentProperties());
			propertyDependencies.add(dependencyInfo);
		}
	}
	
	private void addSetter(SetterElement setter) {
		String propertyName = setter.propertyName();
		PropertyInfoBuilder propertyBuilder = getFromPropertyBuilders(propertyName);
		propertyBuilder.setSetter(setter);
		
		propertyNames.add(propertyName);
	}

	private boolean isEventMethod(MethodElement method) {
		return method.hasParameter() ? method.firstParameterType().isDeclaredType() : true;
	}
	
	private void addEventMethod(MethodElement method) {
		eventMethods.put(method.methodName(), method);
	}
	
	private void addMethod(MethodElement method) {
		methods.put(method.methodName(), method);
	}

	private void processDataSetProperties() {
		for(DataSetPropertyInfoBuilder dataSetProperty : dataSetProperties.values()) {
			try {
				dataSetProperty.supplyRequiredMethodsFrom(methods);
			} catch(RuntimeException e) {
				errors.addPropertyError(e.getMessage());
			}
		}
		
		removeDataSetPropertyRelatedMethods(dataSetProperties.values());
	}
	
	private void removeDataSetPropertyRelatedMethods(Collection dataSetProperties) {
		for(DataSetPropertyInfoBuilder dataSetProperty : dataSetProperties) {
			propertyBuilders.remove(dataSetProperty.propertyName());

			eventMethods.remove(dataSetProperty.factoryMethod());
			eventMethods.remove(dataSetProperty.viewTypeSelector());
		}
	}

	private void processProperties() {
		for(PropertyInfoBuilder builder : propertyBuilders.values()) {
			try {
				builder.validateGetterSetterTypeConsistency();
			} catch(RuntimeException e) {
				errors.addPropertyError(e.getMessage());
			}
		}
	}

	private void validateDependencies() {
		DependencyValidation validation = new DependencyValidation(propertyNames);
		for(PropertyDependencyInfo propertyDependency : propertyDependencies) {
			try {
				validation.validate(propertyDependency.property(), propertyDependency.dependentProperties());
			} catch(RuntimeException e) {
				errors.addPropertyDependencyError(e.getMessage());
			}
		}
	}
	
	private PresentationModelInfo createPresentationModelInfo() {
		return new PresentationModelInfo(typeElement.qName(), presentationModelObjectTypeName,
				buildProperties(), buildDataSetProperties(), 
				propertyDependencies, buildEventMethods());
	}

	private Set buildProperties() {
		Set properties = Sets.newHashSet();
		for(PropertyInfoBuilder builder : propertyBuilders.values()) {
			PropertyInfoImpl property = builder.build();
			properties.add(property);
		}
		return properties;
	}
	
	private Set buildDataSetProperties() {
		Set result = Sets.newHashSet();
		for(DataSetPropertyInfoBuilder dataSetProperty : dataSetProperties.values()) {
			result.add(dataSetProperty.build());
		}
		return result;
	}
	
	private Set buildEventMethods() {
		Set result = Sets.newHashSet();
		for(MethodElement method : eventMethods.values()) {
			result.add(new EventMethodInfoImpl(method));
		}
		return result;
	}
}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy