/*
 * 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.mdd4soa.trans.sde.transform;

import java.io.File;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;

import org.eclipse.bpel.model.Process;
import org.eclipse.core.resources.IContainer;
import org.eclipse.core.resources.IFile;
import org.eclipse.core.resources.IResource;
import org.eclipse.core.runtime.CoreException;
import org.eclipse.core.runtime.NullProgressMonitor;
import org.eclipse.uml2.uml.Activity;
import org.eclipse.wst.wsdl.Definition;

import eu.mdd4soa.smm.exception.InvalidSetupException;
import eu.mdd4soa.smm.exception.TransformerException;
import eu.sensoria_ist.casetool.core.ext.ISensoriaModelHandler;
import eu.sensoria_ist.casetool.core.ext.ISensoriaTool;
import eu.sensoria_ist.casetool.core.ext.SensoriaTool;
import eu.sensoria_ist.casetool.core.ext.SensoriaToolFunction;
import eu.sensoria_ist.casetool.core.ext.SensoriaToolFunctionParameter;
import eu.sensoria_ist.casetool.core.ext.SensoriaToolFunctionReturns;

@SensoriaTool(name= "UML2BPEL/WSDL Converter", description= "Converts a .uml EMF model activity diagram to BPEL and WSDL files.", category= "Transformation")
public class UML2BPELWSDLTransformationService implements ISensoriaTool, ISensoriaModelHandler {

	// Tool functions

	@SensoriaToolFunction(description= "Converts an activity diagram to one BPEL process and several WSDL descriptions.")
	@SensoriaToolFunctionReturns(description= "A list of IFiles with the output.")
	public List<Object> convertToBPELWSDL(@SensoriaToolFunctionParameter(description= "A UML file") IFile model) throws TransformerException {


		Convert2BPELRunner runner= new Convert2BPELRunner();
		runner.setInput(model);

		runner.readInput(new NullProgressMonitor());
		List<Activity> availableActivities= runner.getFlattenedActivities();
		if (availableActivities.size() == 0)
			return null;

		IContainer c= model.getParent();

		runner.setActivitiesToUse(availableActivities);
		runner.setOutputFilePattern("Conversion");
		runner.setOutputDirectory(c);

		runner.perform(new NullProgressMonitor());

		List<Object> outputFiles= runner.getOutputFiles();
		for (Object object : outputFiles) {
			if (object instanceof IFile)
				try {
					((IFile) object).refreshLocal(IResource.DEPTH_ZERO, new NullProgressMonitor());
				} catch (CoreException e) {
				}
		}
		return outputFiles;
	}

	@SensoriaToolFunction(description= "Loads activity diagrams from a UML model")
	@SensoriaToolFunctionReturns(description= "A list of UML activity")
	public List<Activity> loadActivityFromUMLModel(@SensoriaToolFunctionParameter(description= "An .uml model IFile") IFile model)
			throws InvalidSetupException {

		Convert2BPELRunner runner= new Convert2BPELRunner();
		runner.setInput(model);

		runner.readInput(new NullProgressMonitor());

		return runner.getFlattenedActivities();
	}

	@SensoriaToolFunction(description= "Loads activity diagrams from a UML model")
	@SensoriaToolFunctionReturns(description= "An UML activity (assumes one)")
	public Activity loadSingleActivityFromUMLModel(@SensoriaToolFunctionParameter(description= "An .uml model IFile") IFile model)
			throws InvalidSetupException {

		Convert2BPELRunner runner= new Convert2BPELRunner();
		runner.setInput(model);

		runner.readInput(new NullProgressMonitor());
		List<Activity> availableActivities= runner.getFlattenedActivities();
		if (availableActivities.size() > 0)
			return availableActivities.get(0);
		else
			return null;
	}

	@SensoriaToolFunction(description= "Converts an activity diagram to one BPEL process and several WSDL descriptions.")
	@SensoriaToolFunctionReturns(description= "An absolute path to the BPEL process")
	public String convertToBPELandWSDLPath(
			@SensoriaToolFunctionParameter(description= "An UML Activity") Activity activity,
			@SensoriaToolFunctionParameter(description= "The absolute path to the output directory for placing the bpel and wsdl files.") String outputDirectory)
			throws TransformerException, IOException, CoreException {

		File f= new File(outputDirectory);

		Convert2BPELRunner runner= new Convert2BPELRunner();

		List<Activity> avAct= new ArrayList<Activity>();
		avAct.add(activity);

		runner.setActivitiesToUse(avAct);
		runner.setOutputFilePattern(activity.getName());
		runner.setOutputDirectory(f);

		runner.perform(new NullProgressMonitor());

		List<Object> outputFiles= runner.getOutputFiles();
		for (Object object : outputFiles) {
			if (object instanceof IFile)
				try {
					((IFile) object).refreshLocal(IResource.DEPTH_ZERO, new NullProgressMonitor());
				} catch (CoreException e) {
				}
		}

		String result= null;

		for (Object o1 : outputFiles) {
			String res2= null;
			if (o1 instanceof IFile) {
				res2= ((IFile) o1).getLocation().toOSString();
			} else if (o1 instanceof File) {
				res2= ((File) o1).getAbsolutePath();
			}

			if (res2.endsWith("bpel")) {
				result= res2.replace('\\', '/');
				break;
			}
		}

		return result;
	}


	@SensoriaToolFunction(description= "Converts an activity diagram to one BPEL process and several WSDL descriptions.")
	@SensoriaToolFunctionReturns(description= "A list of IFiles with the output.")
	public List<Object> convertToBPELandWSDL(@SensoriaToolFunctionParameter(description= "An UML Activity") Activity activity,
			@SensoriaToolFunctionParameter(description= "The output directory for placing the bpel and wsdl files.") IResource outputDirectory)
			throws TransformerException {

		IContainer c= (IContainer) ( (outputDirectory instanceof IContainer) ? outputDirectory : ((IFile) outputDirectory).getParent());

		Convert2BPELRunner runner= new Convert2BPELRunner();

		List<Activity> avAct= new ArrayList<Activity>();
		avAct.add(activity);

		runner.setActivitiesToUse(avAct);
		runner.setOutputFilePattern(activity.getName());
		runner.setOutputDirectory(c);

		runner.perform(new NullProgressMonitor());

		List<Object> outputFiles= runner.getOutputFiles();
		for (Object object : outputFiles) {
			if (object instanceof IFile)
				try {
					((IFile) object).refreshLocal(IResource.DEPTH_ZERO, new NullProgressMonitor());
				} catch (CoreException e) {
				}
		}
		return outputFiles;
	}

	@SensoriaToolFunction(description= "Converts an activity diagram to one BPEL process.")
	@SensoriaToolFunctionReturns(description= "A BPEL process file")
	public IFile convertToBPEL(@SensoriaToolFunctionParameter(description= "An UML Activity") Activity activity,
			@SensoriaToolFunctionParameter(description= "The output directory for placing the bpel files.") IResource outputDirectory)
			throws TransformerException {

		IContainer c= (IContainer) ( (outputDirectory instanceof IContainer) ? outputDirectory : ((IFile) outputDirectory).getParent());

		Convert2BPELRunner runner= new Convert2BPELRunner();

		List<Activity> avAct= new ArrayList<Activity>();
		avAct.add(activity);

		runner.setActivitiesToUse(avAct);
		runner.setOutputFilePattern(activity.getName());
		runner.setOutputDirectory(c);

		runner.perform(new NullProgressMonitor());

		List<Object> outputFiles= runner.getOutputFiles();
		for (Object object : outputFiles) {
			if (object instanceof IFile)
				try {
					((IFile) object).refreshLocal(IResource.DEPTH_ZERO, new NullProgressMonitor());
				} catch (CoreException e) {
				}
		}
		for (Object object : outputFiles) {
			if (object instanceof IFile && ((IFile) object).getFileExtension().equals("bpel"))
				return (IFile) object;
		}
		return null;
	}

	// Model handling

	@Override
	public List<Class<?>> getHandledModelObjectClasses() {
		List<Class<?>> list= new ArrayList<Class<?>>();
		list.add(IFile.class);
		list.add(Process.class);
		list.add(Definition.class);
		list.add(Activity.class);
		return list;
	}

	@Override
	public String getLabel(Object modelObject) {
		if (modelObject instanceof Process)
			return ((Process) modelObject).getName();
		if (modelObject instanceof Definition)
			return ((Definition) modelObject).getQName().getLocalPart();
		if (modelObject instanceof Activity)
			return ((Activity) modelObject).getName();
		if (modelObject instanceof IFile)
			return ((IFile) modelObject).getName();

		return null;
	}

	@Override
	public String getContent(Object modelObject) {
		return getLabel(modelObject);
	}

	@Override
	public boolean openInUI(Object modelObject) {

		return false;
	}

}
