/*
 * This file has been developed at the University of Munich, Chair for Programming & Software Engineering.
 * 
 * This file is licensed under the Eclipse Public License (EPL) 1.0
 * 
 */
package eu.uml4soa.utbm.vnserver;

import java.util.ArrayList;
import java.util.List;

import org.eclipse.emf.common.util.EList;
import org.eclipse.emf.common.util.TreeIterator;
import org.eclipse.emf.common.util.URI;
import org.eclipse.emf.ecore.EObject;
import org.eclipse.emf.ecore.resource.Resource;
import org.eclipse.emf.ecore.resource.ResourceSet;
import org.eclipse.emf.ecore.resource.impl.ResourceSetImpl;
import org.eclipse.emf.ecore.util.EcoreUtil;
import org.eclipse.uml2.uml.BehavioredClassifier;
import org.eclipse.uml2.uml.Class;
import org.eclipse.uml2.uml.Model;
import org.eclipse.uml2.uml.ProtocolStateMachine;
import org.eclipse.uml2.uml.Stereotype;

/**
 * Some abstract methods for two server checker classes.
 * 
 */
public abstract class AbstractChecker {

	private String fFileName;

	private String fLeftName;

	private String fRightName;

	private String fResult;

	private String fTheory;

	public AbstractChecker(String theory, String fileName) {
		fFileName= fileName;
		fTheory= theory;
	}

	public String getTheory() {
		return fTheory;
	}

	public void setLeft(String left) {
		fLeftName= left;
	}

	public String getFileName() {
		return fFileName;
	}

	public String getResult() {
		return fResult;
	}

	public String getLeftName() {
		return fLeftName;
	}

	public void setRight(String right) {
		fRightName= right;
	}

	public String getRightName() {
		return fRightName;
	}

	public void setResult(String result) {
		fResult= result;
	}

	public Model loadModel() {
		URI fileURI= URI.createFileURI(fFileName);
		ResourceSet resourceSet= new ResourceSetImpl();
		Resource res= resourceSet.getResource(fileURI, true);
		EList<EObject> contents= res.getContents();
		Model model= (Model) contents.get(0);
		return model;
	}

	/**
	 * The name is the fully qualified name of the state machine. The last
	 * segment is the state machine itself, the one before the class, etc.
	 * 
	 * Separator is "::"
	 * 
	 * @param model
	 * @param name
	 * @return
	 */
	protected ProtocolStateMachine getPSM(Model model, String name) {

		int lastSep= name.lastIndexOf("::");

		String psmName= name.substring(lastSep + 2);
		String className= name.substring(0, lastSep);

		List<ProtocolStateMachine> allStateMachines= getAllPSMs(model);
		for (ProtocolStateMachine protocolStateMachine : allStateMachines) {

			org.eclipse.uml2.uml.Class owner= null;
			BehavioredClassifier context= protocolStateMachine.getContext();
			if (context instanceof Class)
				owner= (Class) context;
			else if (protocolStateMachine.getOwner() instanceof Class) {
				owner= (Class) protocolStateMachine.getOwner();
			} else
				continue;

			// The first suffix is missing in MagicDraw...
			String ownerName= owner.getQualifiedName();
			ownerName= ownerName.substring(ownerName.indexOf("::") + 2);


			if (protocolStateMachine.getName().equals(psmName) && ownerName.equals(className)) {
				return protocolStateMachine;
			}
		}

		return null;
	}

	private List<ProtocolStateMachine> getAllPSMs(Model model) {

		List<ProtocolStateMachine> psms= new ArrayList<ProtocolStateMachine>();

		TreeIterator<Object> allContents= EcoreUtil.getAllContents(model, true);
		while (allContents.hasNext()) {
			Object next= allContents.next();
			if (next instanceof ProtocolStateMachine)
				psms.add((ProtocolStateMachine) next);
		}

		return psms;
	}


	protected Class getParticipant(Model model, String name) {

		List<Class> allclasses= getAllParticipants(model);

		for (Class class1 : allclasses) {

			// The first suffix is missing in MagicDraw...
			String ownerName= class1.getQualifiedName();
			ownerName= ownerName.substring(ownerName.indexOf("::") + 2);

			if (ownerName.equals(name))
				return class1;
		}

		return null;
	}

	private List<Class> getAllParticipants(Model model) {

		List<Class> clazzes= new ArrayList<Class>();

		TreeIterator<Object> allContents= EcoreUtil.getAllContents(model, true);
		while (allContents.hasNext()) {
			Object next= allContents.next();
			if (next instanceof Class && hasStereotype((Class) next, "participant"))
				clazzes.add((Class) next);
		}

		return clazzes;
	}

	private boolean hasStereotype(Class next, String string) {

		EList<Stereotype> appliedStereotypes= next.getAppliedStereotypes();
		for (Stereotype stereotype : appliedStereotypes) {
			if (stereotype.getName().equals(string))
				return true;
		}

		return false;
	}



}
