/* * Copyright (c) 2004- michael lawley and others. * All rights reserved. This program and the accompanying materials * are made available under the terms of the GNU Lesser General Public License version 2.1 as published by the Free Software Foundation * which accompanies this distribution, and is available by writing to * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA * * Contributors: * michael lawley * * * */ package tefkat.plugin; import java.util.HashSet; import java.util.Iterator; import java.util.List; import java.util.Map; import java.util.Set; import org.eclipse.core.resources.IContainer; import org.eclipse.core.resources.IProject; import org.eclipse.core.resources.IResource; import org.eclipse.core.resources.IResourceDelta; import org.eclipse.core.resources.IncrementalProjectBuilder; import org.eclipse.core.runtime.CoreException; import org.eclipse.core.runtime.IProgressMonitor; import org.eclipse.core.runtime.Platform; import org.eclipse.emf.common.util.URI; import org.eclipse.emf.ecore.resource.Resource; import tefkat.config.TefkatConfig.Configuration; import tefkat.config.TefkatConfig.Model; import tefkat.config.TefkatConfig.TransformationTask; /** * @author lawley * */ public class TefkatBuilder extends IncrementalProjectBuilder { public static final String TEFKAT_GRAMMAR = TefkatPlugin.PLUGIN_ID + ".GrammarFile"; public static final String TEFKAT_MODEL = TefkatPlugin.PLUGIN_ID + ".Model"; public static final String TEFKAT_PACKAGE = TefkatPlugin.PLUGIN_ID + ".Package"; public static final String TEFKAT_CLASS = TefkatPlugin.PLUGIN_ID + ".Class"; private static boolean filechecking = true; static { String value = Platform.getDebugOption("tefkat/trace/filechecking"); if (value != null && value.equalsIgnoreCase("true")) { TefkatBuilder.filechecking = true; } } /* (non-Javadoc) * @see org.eclipse.core.internal.events.InternalBuilder#build(int, java.util.Map, org.eclipse.core.runtime.IProgressMonitor) */ protected IProject[] build(int kind, Map args, IProgressMonitor monitor) throws CoreException { if (TefkatBuilder.filechecking) { System.out.println("Tefkat build..."); } IProject project = getProject(); IResourceDelta delta = getDelta(project); IResourceDelta[] deltas = null; if (null != delta) { deltas = delta.getAffectedChildren(IResourceDelta.ADDED | IResourceDelta.CHANGED); } Resource res = null; try { IResource file = project.findMember(TefkatPlugin.CONFIGURATION_FILE); URI uri = URI.createPlatformResourceURI(file.getFullPath().toString()); res = TefkatPlugin.getPlugin().getResourceSet().getResource(uri, true); if (res.getContents().size() < 1) { return null; } Configuration config = (Configuration) res.getContents().get(0); List transTasks = config.getTransformationTasks(); Set todo = new HashSet(); if (deltas != null) { if (TefkatBuilder.filechecking) { System.out.println("Delta checking:"); } for (int i = 0; i < deltas.length; i++) { IResource resource = deltas[i].getResource(); checkResource(transTasks, resource, todo); } } else { addAllTransformations(transTasks, todo); } if (todo.size() > 0) { doBuild(monitor, project, todo); } if (TefkatBuilder.filechecking) { System.out.println("Tefkat Plugin has been run " + todo.size() + " times."); } } finally { // unload so that subsequent runs see any changes to the config file // TODO FIXME - Need to at least unload the Config Resource, // but probably all the others as well res.unload(); //TefkatPlugin.getPlugin().unloadResources(); } return null; } private void doBuild(IProgressMonitor monitor, IProject project, Set todo) throws CoreException { try { // Count one step for refreshing the workspace // plus, for each task: // one for loading the Resources // four for running the transformation // one for storing the results monitor.beginTask("Tefkat Build", 1 + (6 * todo.size())); for (Iterator itr = todo.iterator(); itr.hasNext(); ) { Object task = itr.next(); if (isInterrupted() || monitor.isCanceled()) { return; } if (task instanceof TransformationTask) { TefkatPlugin.getPlugin().run((TransformationTask) task, monitor); } } monitor.subTask("Find Tefkat Generated files"); project.refreshLocal(IResource.DEPTH_INFINITE, monitor); monitor.worked(1); // needRebuild(); // I don't think we need to call this any more - was calling it because of possible chaining in the tefkat.xmi spec } finally { monitor.done(); } } private void addAllTransformations(List transTasks, Set todo) { for (Iterator itr = transTasks.iterator(); itr.hasNext();) { TransformationTask task = (TransformationTask) itr.next(); if (task.isEnabled()) { todo.add(task); if (TefkatBuilder.filechecking) { System.out.println("\t" + task + "added"); } } } } private void checkResource(List transTasks, IResource resource, Set todo) throws CoreException { if (resource instanceof IContainer) { if (TefkatBuilder.filechecking) { System.out.println("\t" + resource + " checking contents..."); } IContainer folder = (IContainer) resource; IResource[] members = folder.members(); for (int i = 0; i < members.length; i++) { checkResource(transTasks, members[i], todo); } } else { String resourcePath = resource.getProjectRelativePath().toString(); // if the config file has changed, rebuild all if (resourcePath.equals(TefkatPlugin.CONFIGURATION_FILE)) { addAllTransformations(transTasks, todo); return; } URI resourceUri = URI.createURI(resource.getFullPath().toString()); resourceUri = TefkatPlugin.getPlugin().getResourceSet().getURIConverter().normalize(resourceUri); String resourceName = resourceUri.toString(); for (Iterator itr = transTasks.iterator(); itr.hasNext();) { TransformationTask task = (TransformationTask) itr.next(); if (task.isEnabled()) { String transformation = task.getTransformation().getLocationUri(); List sources = task.getSourceModels(); if (TefkatBuilder.filechecking) { System.out.println("\t" + resourceName); } if (resourceName.equals(transformation)) { todo.add(task); if (TefkatBuilder.filechecking) { System.out.println("\t\tAdded " + task); } } else { for (Iterator srcItr = sources.iterator(); srcItr.hasNext(); ) { Model model = (Model) srcItr.next(); if (resourceName.equals(model.getLocationUri())) { todo.add(task); if (TefkatBuilder.filechecking) { System.out.println("\t\tAdded " + task); } break; // no need to continue this inner loop } } } } } } } }