package br.uem.din.architectureEvolution.helpers;

import java.net.URL;
import java.util.List;

import com.sdmetrics.model.MetaModel;
import com.sdmetrics.model.MetaModelElement;
import com.sdmetrics.model.Model;
import com.sdmetrics.model.ModelElement;
import com.sdmetrics.model.XMIReader;
import com.sdmetrics.model.XMITransformations;
import com.sdmetrics.util.XMLParser;

import static br.uem.din.architectureEvolution.helpers.ElementTypeNames.*;

public class ModelHelper {
	
	private XMLParser parser;
	private final MetaModel metaModel;
	private final XMITransformations trans;
	private final ClassLoader classLoader = getClass().getClassLoader();

	protected ModelHelper(String metaModelURL, String xmiTransURL)
			throws Exception {		
		this.parser = new XMLParser();
		this.metaModel = getMetaModel(findResource(metaModelURL));
		this.trans = getTransformationModel(findResource(xmiTransURL));		
	}

	public MetaModel getMetaModel(String metaModelURL) throws Exception {
		MetaModel metaModel = new MetaModel();
		parser.parse(metaModelURL, metaModel.getSAXParserHandler());
		return metaModel;
	}

	public XMITransformations getTransformationModel(String xmiTransURL)
			throws Exception {
		XMITransformations trans = new XMITransformations(metaModel);
		parser.parse(xmiTransURL, trans.getSAXParserHandler());
		return trans;
	}

	public Model getModel(String xmiFile) throws Exception {
		Model model = new Model(metaModel);
		XMIReader xmiReader = new XMIReader(trans, model);
		parser.parse(xmiFile, xmiReader);

		return model;
	}

	public List<ModelElement> getAllClasses(Model model) {
		return getElementsByType(model, CLASS);
	}

	public List<ModelElement> getAllComponents(Model model) {
		return getElementsByType(model, COMPONENT);
	}

	public List<ModelElement> getAllInterfaces(Model model) {
		return getElementsByType(model, INTERFACE);
	}

	public List<ModelElement> getAllGeneralizations(Model model) {
		return getElementsByType(model, GENERALIZATION);
	}

	public List<ModelElement> getAllAbstractions(Model model) {
		return getElementsByType(model, ABSTRACTION);
	}
	
	public List<ModelElement> getAllComments(Model model) {
		return getElementsByType(model, COMMENT);
	}

	public List<ModelElement> getAllAssociations(Model model) {
		return getElementsByType(model, ASSOCIATION);
	}
	
	public List<ModelElement> getAllDependencies(Model model) {
		return getElementsByType(model, DEPENDENCY);
	}

	private List<ModelElement> getElementsByType(Model model, String type) {
		for (MetaModelElement element : metaModel)
			if (element.getName().equalsIgnoreCase(type))
				return model.getElements(element);
		return null;
	}
	
	public String findResource(String resourceURL){
		URL resource = classLoader.getResource(resourceURL);
		
		if (resource == null) return null;
		
		return resource.toString();		
	}
}
