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

net.sf.nakeduml.feature.TransformationProcess Maven / Gradle / Ivy

The newest version!
package net.sf.nakeduml.feature;

import java.lang.reflect.Field;
import java.util.HashSet;
import java.util.Iterator;
import java.util.List;
import java.util.Set;

/**
 * This class will become the entry point for the entire transformation process
 * 
 * 
 * @author abarnard
 * 
 */
public class TransformationProcess {
	Set models = new HashSet();
	Set> actualClasses = new HashSet>();
	@SuppressWarnings({ "unchecked", "rawtypes" })
	public void execute(NakedUmlConfig config, Object sourceModel, Set> proposedStepClasses) {
		replaceModels(sourceModel);
		Phases phases = new Phases();
		this.actualClasses = ensurePresenceOfDependencies(proposedStepClasses);
		phases.initializeFromClasses(getPhaseClassesFor(actualClasses));
		List> phaseList = phases.getExecutionUnits();
		for (TransformationPhase phase : phaseList) {
			setInputModelsFor(phase);
			phase.initialize(config);
			Class> class1 = (Class) phase.getClass();
			Steps steps  = new Steps();
			steps.initializeFromClasses(getStepsForPhase(class1,actualClasses));
			List featuresFor = steps.getExecutionUnits();
			System.out.println("Executing phase " + phase.getClass() + " .... ");
			long time = System.currentTimeMillis();
			Object[] execute = phase.execute(featuresFor);
			replaceModels(execute);
			System.out.println("Executing phase " + phase.getClass() + " took " + (System.currentTimeMillis() - time) + "ms");
		}
	}


	private Set> getStepsForPhase(
			Class> phaseClass, Set> stepClasses) {
		Set> results = new HashSet>();
		for (Class stepClass : stepClasses) {
			if(stepClass.getAnnotation(StepDependency.class).phase()==phaseClass){
				results.add(stepClass);
			}
		}
		return results;
	}


	private Set>> getPhaseClassesFor(
			Set> stepClasses) {
		Set>> phaseClasses = new HashSet>>();
		for (Class t : stepClasses) {
			Class> phaseClass = t.getAnnotation(StepDependency.class).phase();
			phaseClasses.add(phaseClass);
		}
		return phaseClasses;
	}

	private void setInputModelsFor(TransformationPhase phase) {
		Field[] fields = getFields(phase);
		for (Field field : fields) {
			if (field.isAnnotationPresent(InputModel.class)) {
				field.setAccessible(true);
				Object existingModel = findModel(field.getType());
				try {
					if (existingModel == null) {
						existingModel = createModel(phase, field);
					}
					field.set(phase, existingModel);
				} catch (IllegalAccessException e) {
					throw new RuntimeException(e);
				} catch (InstantiationException e) {
					throw new RuntimeException(e);
				}
			}
		}
	}

	private Object createModel(TransformationPhase phase, Field field) throws InstantiationException,
			IllegalAccessException {
		Class modelClass = field.getType();
		if (modelClass.isInterface()) {
			Class[] implementationClass = field.getAnnotation(InputModel.class).implementationClass();
			if (implementationClass.length == 1) {
				modelClass = implementationClass[0];
			} else {
				throw new IllegalStateException("No existing model found of type " + field.getType() + " to provide input for the phase  "
						+ phase.getClass()
						+ ". Could not instantiate it because it is an interface. Please use the 'implementationClass' attribute.");
			}
		}
		Object model = modelClass.newInstance();
		this.models.add(model);
		return model;
	}

	private Field[] getFields(TransformationPhase phase) {
		return phase.getClass().getDeclaredFields();
	}

	private void replaceModels(Object... models) {
		for (Object newModel : models) {
			Iterator iter = this.models.iterator();
			inner: while (iter.hasNext()) {
				Object oldModel = iter.next();
				if (newModel.getClass().isInstance(oldModel)) {
					iter.remove();
					break inner;
				}
			}
			this.models.add(newModel);
		}
	}

	@SuppressWarnings("unchecked")
	public  T findModel(Class currentClass) {
		for (Object model : models) {
			if (currentClass.isInstance(model)) {
				return (T) model;
			}
		}
		return null;
	}
	public Set> ensurePresenceOfDependencies(Set> selectedFeatures) {
		try {
			for (Class c : selectedFeatures) {
				ensureRequiredDependenciesPresent(c);
			}
			return actualClasses;
		} catch (Exception e) {
			throw new RuntimeException(e);
		}
	}
	
	private void ensureRequiredDependenciesPresent(Class stepClass) throws IllegalAccessException, InstantiationException {
		if (!actualClasses.contains(stepClass)) {
			actualClasses.add(stepClass);
			for (Class c : stepClass.getAnnotation(StepDependency.class).requires()) {
				ensureRequiredDependenciesPresent(c);
			}
		}
	}
}