/**
 * File:    ATLTransformation.java
 * Created: 04.03.2008
 *
 *
/*******************************************************************************
 * Copyright (c) 2005-2011  Open Wide (www.openwide.fr)
 * 
 *
 * All rights reserved. This program and the accompanying materials
 * are made available under the terms of the Eclipse Public License v1.0
 * which accompanies this distribution, and is available at
 * http://www.eclipse.org/legal/epl-v10.html
 *
 * Contributors:
 *    Mickael Istria, Open Wide, Lyon, France
 *      - creation and implementation
 *******************************************************************************/

package org.eclipse.jwt.transformations.bpmn.internal;

import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.InputStream;
import java.net.MalformedURLException;
import java.net.URL;
import java.util.Collections;
import java.util.HashMap;
import java.util.Map;

import org.eclipse.emf.common.util.URI;
import org.eclipse.jwt.transformations.api.TransformationException;
import org.eclipse.m2m.atl.drivers.emf4atl.ASMEMFModel;
import org.eclipse.m2m.atl.drivers.emf4atl.AtlEMFModelHandler;
import org.eclipse.m2m.atl.engine.vm.AtlLauncher;
import org.eclipse.m2m.atl.engine.vm.AtlModelHandler;
import org.eclipse.m2m.atl.engine.vm.ModelLoader;

/**
 * Should implement a template method pattern...
 */
@SuppressWarnings("unused")
public class ATLTransformation
{

	private static ATLTransformation instance = null;

	private final static String resourcePath = "/org/eclipse/jwt/transformations/bpmn/internal/resources/"; //$NON-NLS-1$

	private AtlEMFModelHandler modelHandler;
	private InputStream JWT_ModelResource;
	private InputStream BPMN_ModelResource;
	// private URL JWT2BPMN_TransfoResource;
	private URL BPMN2JWT_TransfoResource;
	private ASMEMFModel xmlMetamodel;
	private ASMEMFModel jwtMetamodel;
	private ASMEMFModel bpmnMetamodel;

	private URL JWT2BPMN_Pool_TransfoResource;
	// private URL JWT2BPMN_Sub_TransfoResource;

	private ModelLoader modelLoader;


	static public ATLTransformation getInstance()
	{
		if (instance == null)
			instance = new ATLTransformation();
		return instance;
	}


	private void createResources() throws TransformationException
	{
		if (BPMN_ModelResource == null || BPMN2JWT_TransfoResource == null
				|| JWT2BPMN_Pool_TransfoResource == null)
		{
			modelHandler = (AtlEMFModelHandler) AtlModelHandler
					.getDefault(AtlModelHandler.AMH_EMF);
			modelLoader = modelHandler.createModelLoader();

			String mm_path = "/org/eclipse/jwt/meta/ecore/JWTMetaModel.ecore";

			JWT_ModelResource = getClass().getResourceAsStream(mm_path);//$NON-NLS-1$
			BPMN_ModelResource = getClass().getResourceAsStream(
					resourcePath + "bpmn.ecore");//$NON-NLS-1$

			// be aware: there is no JWT2BPMN.asm and no Jwt2BpmnAllInSub.asm
			// right now!!
			// JWT2BPMN_TransfoResource = ATLTransformation.class
			//		.getResource("resources/JWT2BPMN.asm");//$NON-NLS-1$
			JWT2BPMN_Pool_TransfoResource = ATLTransformation.class
					.getResource(resourcePath + "Jwt2BpmnAllInPool.asm");//$NON-NLS-1$
			// JWT2BPMN_Sub_TransfoResource = ATLTransformation.class
			//		.getResource("resources/Jwt2BpmnAllInSub.asm");//$NON-NLS-1$
			BPMN2JWT_TransfoResource = ATLTransformation.class.getResource(resourcePath
					+ "BPMN2JWT.asm");//$NON-NLS-1$

			// check
			if (JWT2BPMN_Pool_TransfoResource == null)
				JWT2BPMN_Pool_TransfoResource = getClass().getResource(
						resourcePath + "Jwt2BpmnAllInPool.asm");//$NON-NLS-1$
			if (JWT2BPMN_Pool_TransfoResource == null)
				throw new TransformationException("JWT2BPMN_Pool_TransfoResource is null");//$NON-NLS-1$

			// check
			if (BPMN2JWT_TransfoResource == null)
				BPMN2JWT_TransfoResource = getClass().getResource(
						resourcePath + "BPMN2JWT.asm");//$NON-NLS-1$
			if (BPMN2JWT_TransfoResource == null)
				throw new TransformationException("BPMN2JWT_TransfoResource is null");//$NON-NLS-1$

			try
			{
				BPMN2JWT_TransfoResource.openStream().close();
			}
			catch (Exception ex)
			{
				throw new TransformationException(
						"error opening transformation resource stream", ex);//$NON-NLS-1$
			}
		}
	}


	private Map<String, Object> getMetamodels() throws TransformationException
	{
		Map<String, Object> models = new HashMap<String, Object>();

		if (jwtMetamodel == null)
		{
			try
			{
				createResources();
				jwtMetamodel = (ASMEMFModel) modelLoader.loadModel(
						"jwt", modelLoader.getMOF(), JWT_ModelResource);//$NON-NLS-1$
				bpmnMetamodel = (ASMEMFModel) modelLoader.loadModel(
						"bpmn", modelLoader.getMOF(), BPMN_ModelResource);//$NON-NLS-1$
			}
			catch (IOException ex)
			{
				throw new TransformationException(ex.getMessage(), ex);
			}
		}

		models.put("jwt", jwtMetamodel);//$NON-NLS-1$
		models.put("bpmn", bpmnMetamodel);//$NON-NLS-1$
		return models;
	}


	public void jwt2bpmn(String inFilePath, String outFilePath)
			throws TransformationException, FileNotFoundException, IOException
	{
		Map<String, Object> models = getMetamodels();

		// get/create models
		ASMEMFModel jwtInputModel = (ASMEMFModel) modelLoader.loadModel(
				"IN", jwtMetamodel, new FileInputStream(inFilePath));//$NON-NLS-1$
		ASMEMFModel bpmnOutputModel = (ASMEMFModel) modelLoader.newModel(
				"OUT", URI.createFileURI(outFilePath).toString(), bpmnMetamodel);//$NON-NLS-1$
		// load models
		models.put("IN", jwtInputModel);//$NON-NLS-1$
		models.put("OUT", bpmnOutputModel);//$NON-NLS-1$
		// launch

		if (BPMN2JWT_TransfoResource == null)
			throw new MalformedURLException("transformation resource is null");//$NON-NLS-1$

		AtlLauncher.getDefault().launch(this.JWT2BPMN_Pool_TransfoResource,
				Collections.EMPTY_MAP, models, Collections.EMPTY_MAP,
				Collections.EMPTY_LIST, Collections.EMPTY_MAP);

		modelLoader.save(bpmnOutputModel, new File(outFilePath).toURI().toURL()
				.toString());
	}


	public void bpmn2jwt(String inFilePath, String outFilePath)
			throws TransformationException, MalformedURLException, IOException
	{
		Map<String, Object> models = getMetamodels();

		// get/create models
		ASMEMFModel bpmnInputModel = (ASMEMFModel) modelLoader.loadModel(
				"IN", bpmnMetamodel, new FileInputStream(inFilePath));//$NON-NLS-1$
		ASMEMFModel jwtOutputModel = (ASMEMFModel) modelLoader.newModel(
				"OUT", URI.createFileURI(outFilePath).toString(), jwtMetamodel);//$NON-NLS-1$
		// load models
		models.put("IN", bpmnInputModel);//$NON-NLS-1$
		models.put("OUT", jwtOutputModel);//$NON-NLS-1$

		// launch
		if (BPMN2JWT_TransfoResource == null)
			throw new MalformedURLException("transformation resource is null");//$NON-NLS-1$

		AtlLauncher.getDefault().launch(this.BPMN2JWT_TransfoResource,
				Collections.EMPTY_MAP, models, Collections.EMPTY_MAP,
				Collections.EMPTY_LIST, Collections.EMPTY_MAP);

		modelLoader
				.save(jwtOutputModel, new File(outFilePath).toURI().toURL().toString());
	}
}
