org.eclipse.emf.mwe.core.WorkflowEngine.java Source code

Java tutorial

Introduction

Here is the source code for org.eclipse.emf.mwe.core.WorkflowEngine.java

Source

/*******************************************************************************
 * Copyright (c) 2005 - 2009 committers of openArchitectureWare and others.
 * 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:
 *     committers of openArchitectureWare - initial API and implementation
 *******************************************************************************/
package org.eclipse.emf.mwe.core;

import java.net.URL;
import java.util.Map;
import java.util.jar.Manifest;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.eclipse.emf.common.util.Diagnostic;
import org.eclipse.emf.mwe.core.issues.Issues;
import org.eclipse.emf.mwe.core.issues.IssuesImpl;
import org.eclipse.emf.mwe.core.monitor.NullProgressMonitor;
import org.eclipse.emf.mwe.core.monitor.ProgressMonitor;
import org.eclipse.emf.mwe.internal.core.MWEPlugin;
import org.eclipse.emf.mwe.internal.core.Workflow;
import org.eclipse.emf.mwe.internal.core.ast.util.WorkflowFactory;
import org.eclipse.emf.mwe.internal.core.ast.util.converter.Converter;

public class WorkflowEngine {

    private WorkflowContextDefaultImpl wfContext = new WorkflowContextDefaultImpl();

    private ProgressMonitor monitor;

    private static final Log logger = LogFactory.getLog(WorkflowEngine.class);

    private Map<String, String> params;

    private Workflow workflow;

    /**
     * @param workFlowFile
     * @param monitor
     * @param logger
     * @param params
     */
    public boolean run(final String workFlowFile, final ProgressMonitor theMonitor,
            final Map<String, String> theParams, final Map<String, ?> externalSlotContents) {
        final boolean configOK = prepare(workFlowFile, theMonitor, theParams);
        final Issues issues = new IssuesImpl();
        if (configOK) {
            return executeWorkflow(externalSlotContents, issues);
        }
        return false;
    }

    public boolean prepare(final String workFlowFile, final ProgressMonitor theMonitor,
            final Map<String, String> theParams) {
        if (workFlowFile == null) {
            throw new NullPointerException("workflowFile is null");
        }

        if (theMonitor == null) {
            monitor = new NullProgressMonitor();
        } else {
            monitor = theMonitor;
        }
        params = theParams;

        logger.info("--------------------------------------------------------------------------------------");
        logger.info("EMF Modeling Workflow Engine " + getVersion());
        logger.info("(c) 2005-2009 openarchitectureware.org and contributors");
        logger.info("--------------------------------------------------------------------------------------");
        logger.info("running workflow: " + workFlowFile);
        logger.info("");

        if (logger.isDebugEnabled() && !params.isEmpty()) {
            logger.debug("Params:" + params.toString());
        }
        final Issues issues = new IssuesImpl();

        try {
            final WorkflowFactory factory = getWorkflowFactory();

            // see Bug#155854: WorkflowFactory will throw an
            // IllegalArgumentException which indicates
            // a configuration problem.
            // Detect this very special case
            try {
                workflow = factory.parseInitAndCreate(workFlowFile, params, getConverters(), issues);
            } catch (final IllegalArgumentException illegalArg) {
                if (illegalArg.getMessage().startsWith("Couldn't load file")) {
                    throw new ConfigurationException(illegalArg.getMessage());
                }
                throw illegalArg;
            }
            logIssues(logger, issues);
            if (issues.hasErrors()) {
                logger.error("Workflow interrupted because of configuration errors.");
                return false;
            }
            if (workflow != null) {
                workflow.checkConfiguration(issues);
            }
            logIssues(logger, issues);
            if (issues.hasErrors()) {
                logger.error("Workflow interrupted because of configuration errors.");
                return false;
            }
        } catch (final ConfigurationException ex) {
            logger.fatal(ex.getMessage(), ex);
            logIssues(logger, issues);
            return false;
        }

        return true;

    }

    /**
     * Creates a new workflow factory
     * 
     */
    protected WorkflowFactory getWorkflowFactory() {
        return new WorkflowFactory();
    }

    /**
     * This method delivers the Converter implementations currently used to inject values into the workflow components.
     * 
     * @return A map between injection types and converter implementations. Not <code>null</code>.
     */
    private Map<Class<?>, Converter<?>> getConverters() {
        Map<Class<?>, Converter<?>> result = getCustomConverters();
        final Map<Class<?>, Converter<?>> defaults = WorkflowFactory.getDefaultConverter();
        if (result == null) {
            // go with the default values
            result = defaults;
        } else {
            // add default Converter implementations if we don't have a custom
            // implementation yet
            for (final Map.Entry<Class<?>, Converter<?>> record : defaults.entrySet()) {
                if (!result.containsKey(record.getKey())) {
                    result.put(record.getKey(), record.getValue());
                }
            }
        }
        return result;
    }

    /**
     * Returns a map of custom Converter implementations used for the injection process. If the result is
     * <code>null</code> the default Converter implementations are used. It's not necessary to provide custom Converter
     * implementations for the default types since they will be added if they're missing (f.e. it might be useful to
     * support lists which are splitted using other characters than a comma).
     * 
     * @return A map of custom Converter implementations. Maybe <code>null</code>.
     */
    protected Map<Class<?>, Converter<?>> getCustomConverters() {
        return null;
    }

    public boolean executeWorkflow(final Map<?, ?> externalSlotContents, final Issues issues) {
        try {
            wfContext = new WorkflowContextDefaultImpl();
            addExternalSlotContents(externalSlotContents);
            final long time = System.currentTimeMillis();
            monitor.started(workflow, wfContext);
            workflow.invoke(wfContext, monitor, issues);
            monitor.finished(workflow, wfContext);
            final long duration = System.currentTimeMillis() - time;
            logger.info("workflow completed in " + duration + "ms!");
            if (issues.getErrors().length > 0) {
                return false;
            }
            return true;
        } catch (final Exception e) {
            if (e.getClass().getName().indexOf("Interrupt") > -1) {
                logger.error("Workflow interrupted. Reason: " + e.getMessage());
            } else {
                logger.error(e.getMessage(), e);
            }
        } finally {
            logIssues(logger, issues);
        }
        return false;
    }

    private void addExternalSlotContents(final Map<?, ?> slotContents) {
        if (slotContents == null) {
            return;
        }
        for (final Object name : slotContents.keySet()) {
            final String key = (String) name;
            wfContext.set(key, slotContents.get(key));
        }
    }

    private void logIssues(final Log logger, final Issues issues) {
        // log any configuration warning messages
        final Diagnostic[] issueArray = issues.getIssues();
        for (final Diagnostic issue : issueArray) {
            if (issue.getSeverity() == Diagnostic.ERROR) {
                logger.error(issue.toString());
            }
            if (issue.getSeverity() == Diagnostic.WARNING) {
                logger.warn(issue.toString());
            }
            if (issue.getSeverity() == Diagnostic.INFO) {
                logger.info(issue.toString());
            }
        }
    }

    public WorkflowContext getContext() {
        return wfContext;
    }

    /**
     * Tries to read the exact build version from the Manifest of the core.workflow plugin. Therefore the Manifest file
     * is located and the version is read from the attribute 'Bundle-Version'.
     * 
     * @return The build version string, format "4.1.1, Build 200609291913"
     */
    private String getVersion() {
        try {
            URL url = new URL(MWEPlugin.INSTANCE.getBaseURL() + "META-INF/MANIFEST.MF");
            final Manifest manifest = new Manifest(url.openStream());
            // Original value : "4.1.1.200609291913"
            // Resulting value : "4.1.1, Build 200609291913"
            String version = manifest.getMainAttributes().getValue("Bundle-Version");
            final int lastPoint = version.lastIndexOf('.');
            return version.substring(0, lastPoint) + ", Build " + version.substring(lastPoint + 1);
        } catch (Exception e) {
            logger.warn("Couldn't compute version of mwe.core bundle.", e);
            return "unkown version";
        }
    }

}