org.yakindu.sct.generator.builder.SCTBuilder.java Source code

Java tutorial

Introduction

Here is the source code for org.yakindu.sct.generator.builder.SCTBuilder.java

Source

/**
 * Copyright (c) 2011 committers of YAKINDU 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 YAKINDU - initial API and implementation
 */
package org.yakindu.sct.generator.builder;

import java.util.Map;
import java.util.Set;

import org.eclipse.core.resources.IMarker;
import org.eclipse.core.resources.IProject;
import org.eclipse.core.resources.IResource;
import org.eclipse.core.resources.IResourceDelta;
import org.eclipse.core.resources.IResourceDeltaVisitor;
import org.eclipse.core.resources.IResourceVisitor;
import org.eclipse.core.resources.IncrementalProjectBuilder;
import org.eclipse.core.runtime.CoreException;
import org.eclipse.core.runtime.IProgressMonitor;
import org.eclipse.core.runtime.IStatus;
import org.eclipse.core.runtime.Platform;
import org.eclipse.core.runtime.Status;
import org.eclipse.emf.common.util.URI;
import org.eclipse.emf.common.util.WrappedException;
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.jface.preference.IPreferenceStore;
import org.yakindu.sct.generator.core.GeneratorActivator;
import org.yakindu.sct.model.sgen.GeneratorEntry;
import org.yakindu.sct.model.sgen.GeneratorModel;
import org.yakindu.sct.model.sgraph.Statechart;

import com.google.common.base.Predicate;
import com.google.common.collect.Iterables;
import com.google.common.collect.Sets;

/**
 * 
 * @author andreas muelder - Initial contribution and API
 * 
 */
public class SCTBuilder extends IncrementalProjectBuilder {

    // TODO Remove dependency to fileextension and read referenced elements from
    // genmodels instead.
    private static final String SCT_FILE_EXTENSION = "sct";
    private static final String SGEN_FILE_EXTENSION = "sgen";
    public static final String BUILDER_ID = "org.yakindu.sct.builder.SCTBuilder";

    private final class ElementRefGenerator implements Predicate<GeneratorEntry> {

        private final URI uri;

        private ElementRefGenerator(EObject eobject) {
            if (EcoreUtil.getURI(eobject) != null) {
                uri = EcoreUtil.getURI(eobject);
            } else {
                uri = null;
            }
        }

        public boolean apply(GeneratorEntry input) {
            return uri != null && input.getElementRef() != null && !input.getElementRef().eIsProxy()
                    && uri.equals(EcoreUtil.getURI(input.getElementRef()));
        }
    }

    class DeltaVisitor implements IResourceDeltaVisitor {
        private Set<IResource> buildSgens = Sets.newHashSet();

        public boolean visit(IResourceDelta delta) throws CoreException {
            IResource resource = delta.getResource();
            switch (delta.getKind()) {
            case IResourceDelta.ADDED:
                // handle added resource
                doIt(resource, buildSgens);
                break;
            case IResourceDelta.REMOVED:
                // handle removed resource
                break;
            case IResourceDelta.CHANGED:
                // handle changed resource
                doIt(resource, buildSgens);
                break;
            }
            // return true to continue visiting children.
            return true;
        }
    }

    class SimpleResourceVisitor implements IResourceVisitor {
        private Set<IResource> buildSgens = Sets.newHashSet();

        public boolean visit(IResource resource) {
            doIt(resource, buildSgens);
            // return true to continue visiting children.
            return true;
        }
    }

    @Override
    protected IProject[] build(int kind, @SuppressWarnings("rawtypes") Map args, IProgressMonitor monitor)
            throws CoreException {

        IPreferenceStore store = BuilderActivator.getDefault().getPreferenceStore();
        boolean generateAutomatical = store.getBoolean(GeneratorActivator.PREF_GENERATE_AUTOMATICALLY);

        if (generateAutomatical) {
            if (kind == FULL_BUILD) {
                fullBuild(monitor);
            } else {
                IResourceDelta delta = getDelta(getProject());
                if (delta == null) {
                    fullBuild(monitor);
                } else {
                    incrementalBuild(delta, monitor);
                }
            }
        }
        return null;
    }

    protected void fullBuild(final IProgressMonitor monitor) throws CoreException {
        try {
            getProject().accept(new SimpleResourceVisitor());
        } catch (CoreException e) {
        }
    }

    protected void incrementalBuild(IResourceDelta delta, IProgressMonitor monitor) throws CoreException {
        delta.accept(new DeltaVisitor());
    }

    /**
     * Build the Statecharts inside this sgen-file or find all sgen-files for
     * the statechart in the resource and build them.
     * 
     * @param changedResource
     *            Resource to check, if it can be build.
     * @param buildSgens
     *            Contains a set of already build sgen files. Accepted
     *            sgen-files are added inside this method.
     */
    public void doIt(final IResource changedResource, final Set<IResource> buildSgens) {
        if (changedResource.getType() != IResource.FILE) {
            return;
        }
        if (SGEN_FILE_EXTENSION.equals(changedResource.getFileExtension())
                && !buildSgens.contains(changedResource)) {
            if (hasError(changedResource)) {
                logGenmodelError(changedResource.getFullPath().toString());
            } else {
                buildSgens.add(changedResource);
                executeGenmodelGenerator(changedResource);
            }
        } else if (SCT_FILE_EXTENSION.equals(changedResource.getFileExtension())) {
            // TODO rely on indexed genmodel and referenced objects uri
            final Statechart statechart = loadFromResource(changedResource);
            if (statechart == null)
                return;
            try {
                changedResource.getProject().accept(new IResourceVisitor() {

                    public boolean visit(IResource resource) throws CoreException {
                        if (IResource.FILE == resource.getType()
                                && SGEN_FILE_EXTENSION.equals(resource.getFileExtension())
                                && !buildSgens.contains(resource)
                                && isGenmodelForStatechart(resource, statechart)) {
                            // TODO: would be good to filter the config for the
                            // statechart so only the sct that changed is
                            // build
                            if (hasError(changedResource)) {
                                logStatechartError(changedResource.getFullPath().toString());
                            } else {
                                if (hasError(resource)) {
                                    logGenmodelError(resource.getFullPath().toString());
                                } else {
                                    buildSgens.add(resource);
                                    executeGenmodelGenerator(resource);
                                }
                            }
                        }
                        return true;
                    }
                });
            } catch (CoreException e) {
                e.printStackTrace();
            }

        }
    }

    private boolean hasError(IResource resource) {
        IMarker[] findMarkers = null;
        try {
            findMarkers = resource.findMarkers(IMarker.PROBLEM, true, IResource.DEPTH_INFINITE);
            for (IMarker iMarker : findMarkers) {
                Integer attribute = (Integer) iMarker.getAttribute(IMarker.SEVERITY);
                if (attribute.intValue() == IMarker.SEVERITY_ERROR) {
                    return true;
                }
            }
        } catch (CoreException e) {
            e.printStackTrace();
        }
        return false;
    }

    protected void executeGenmodelGenerator(IResource resource) {
        new EclipseContextGeneratorExecutorLookup()
                .executeGenerator(resource.getProject().getFile(resource.getProjectRelativePath()));
    }

    protected void logGenmodelError(String resource) {
        Status status = new Status(Status.WARNING, BUILDER_ID,
                String.format("Cannot execute Genmodel %s. The file contains errors.", resource));
        Platform.getLog(BuilderActivator.getDefault().getBundle()).log(status);
    }

    protected void logStatechartError(final String resource) {
        Status status = new Status(Status.WARNING, BUILDER_ID,
                String.format("Cannot generate Code for Statechart %s. The file contains errors.", resource));
        Platform.getLog(BuilderActivator.getDefault().getBundle()).log(status);
    }

    private boolean isGenmodelForStatechart(IResource genmodelResource, final Statechart statechart) {
        GeneratorModel genModel = loadFromResource(genmodelResource);
        return genModel != null && !genModel.getEntries().isEmpty()
                && Iterables.any(genModel.getEntries(), new ElementRefGenerator(statechart));
    }

    @SuppressWarnings("unchecked")
    private <TYPE extends EObject> TYPE loadFromResource(IResource res) {
        URI uri = URI.createPlatformResourceURI(res.getFullPath().toString(), true);
        ResourceSet set = new ResourceSetImpl();
        Resource emfResource = null;
        try {
            emfResource = set.getResource(uri, true);
        } catch (WrappedException e) {
            Platform.getLog(BuilderActivator.getDefault().getBundle()).log(new Status(IStatus.WARNING,
                    GeneratorActivator.PLUGIN_ID, "Resource " + uri + " can not be loaded by builder", e));
            return null;
        }
        if (emfResource.getErrors().size() > 0 || emfResource.getContents().size() == 0)
            return null;
        return (TYPE) emfResource.getContents().get(0);
    }

}