/*******************************************************************************
* Copyright (c) 2010-2015 Henshin developers. 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:
* TU Berlin, University of Luxembourg, SES S.A.
*******************************************************************************/
package de.tub.tfs.henshin.tgg.interpreter.gui;
import java.lang.reflect.Field;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.Iterator;
import java.util.LinkedList;
import java.util.List;
import java.util.Queue;
import java.util.Vector;
import org.eclipse.core.commands.AbstractHandler;
import org.eclipse.core.commands.ExecutionEvent;
import org.eclipse.core.commands.ExecutionException;
import org.eclipse.core.commands.IHandler;
import org.eclipse.core.resources.IContainer;
import org.eclipse.core.resources.IFile;
import org.eclipse.core.resources.IResource;
import org.eclipse.core.resources.ResourcesPlugin;
import org.eclipse.core.runtime.CoreException;
import org.eclipse.core.runtime.IPath;
import org.eclipse.core.runtime.IProgressMonitor;
import org.eclipse.core.runtime.IStatus;
import org.eclipse.core.runtime.Path;
import org.eclipse.core.runtime.Status;
import org.eclipse.core.runtime.jobs.Job;
import org.eclipse.core.runtime.preferences.IEclipsePreferences;
import org.eclipse.core.runtime.preferences.InstanceScope;
import org.eclipse.emf.common.util.EList;
import org.eclipse.emf.common.util.URI;
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.jface.viewers.ISelection;
import org.eclipse.jface.viewers.IStructuredSelection;
import org.eclipse.swt.SWT;
import org.eclipse.swt.widgets.Event;
import org.eclipse.ui.handlers.HandlerUtil;
import de.tub.tfs.henshin.tgg.TGG;
import de.tub.tfs.henshin.tgg.interpreter.util.TggUtil;
import de.tub.tfs.muvitor.ui.utils.EMFModelManager;
public class LoadHandler extends AbstractHandler implements IHandler {
public static final String henshinExt = "henshin";
protected static List<String> trFileNames = new Vector<String>();
protected static IFile trFile;
protected static List<TGG> trSystems = new ArrayList<TGG>();
protected static Job loadGrammarJob = null;
protected static Queue<IFile> loadQueue = new LinkedList<IFile>();
protected static HashMap<String,Long> cacheTimes = new HashMap<String, Long>();
protected static HashMap<String,EList<EObject>> cacheFiles = new HashMap<String,EList<EObject>>();
public static List<String> getTrFileNames() {
return trFileNames;
}
public static List<TGG> getTrSystems() {
return trSystems;
}
private static void loadCachedQueue() {
// saves plugin preferences at the workspace level
try {
IEclipsePreferences prefs = InstanceScope.INSTANCE.getNode("lu.uni.snt.scope2spell.gui"); // does all the above behind the scenes
int entries = prefs.getInt("CachedQueueEntries",0);
for (int i = 0; i < entries; i++) {
String locationString = prefs.get("CachedLoadQueue_" + i,null);
if (locationString != null){
IPath p = Path.fromOSString(locationString);
IFile iFile = ResourcesPlugin.getWorkspace().getRoot().getFile(p);
if (!iFile.exists()){
iFile = ResourcesPlugin.getWorkspace().getRoot().getFile(p.makeAbsolute());
IPath fullPath = iFile.getFullPath();
Field field = fullPath.getClass().getDeclaredField("device");
field.setAccessible(true);
field.set(fullPath, p.getDevice());
}
loadQueue.add(iFile);
trFileNames.add(iFile.getName());
}
}
// prefs are automatically flushed during a plugin's "super.stop()".
///prefs.flush();
} catch(Exception e) {
//TODO write a real exception handler.
e.printStackTrace();
}
}
private static void saveCachedQueue() {
// saves plugin preferences at the workspace level
try {
IEclipsePreferences prefs = InstanceScope.INSTANCE.getNode("lu.uni.snt.scope2spell.gui"); // does all the above behind the scenes
prefs.putInt("CachedQueueEntries",loadQueue.size());
int idx = 0;
for (IFile iFile : loadQueue) {
prefs.put("CachedLoadQueue_" + idx,iFile.getFullPath().toString());
idx++;
}
// prefs are automatically flushed during a plugin's "super.stop()".
prefs.flush();
} catch(Exception e) {
//TODO write a real exception handler.
e.printStackTrace();
}
}
public static void updateGrammars(){
EMFModelManager manager = EMFModelManager.createModelManager(henshinExt);
manager.cleanUp();
TggUtil.initClassConversions();
if (loadQueue.isEmpty()){
loadCachedQueue();
}
trSystems.clear();
final ResourceSet resSet = new ResourceSetImpl();
setLoadGrammarJob(new Job("Loading Triple Graph Grammar") {
protected IStatus run(IProgressMonitor monitor) {
try {
monitor.beginTask("Updating Triple Graph Grammars", loadQueue.size());
monitor.subTask("Preparing");
boolean useCache = false;
Iterator<IFile> loadQueueIt = loadQueue.iterator();
while (loadQueueIt.hasNext()) {
trFile = loadQueueIt.next();
monitor.subTask("Loading " + trFile.getName());
String trFilePath = trFile.getFullPath().toString();
URI trURI = URI.createPlatformResourceURI(trFilePath,
true);
EList<EObject> modules;
if (cacheTimes.get(trFilePath) != null && trFile.getModificationStamp() <= (Long)cacheTimes.get(trFilePath)){
modules = cacheFiles.get(trFilePath);
useCache = true;
} else {
Resource resource = resSet.getResource(trURI, false);
if (resource != null)
resource.unload();
try {
modules = resSet.getResource(trURI, true).getContents();
} catch (Exception ex){
trURI = URI.createFileURI(trFilePath);
modules = resSet.getResource(trURI, true).getContents();
}
cacheTimes.put(trFilePath, trFile.getModificationStamp());
cacheFiles.put(trFilePath, modules);
}
if (modules.size() > 0)
trSystems.add((TGG) modules.get(0));
monitor.worked(1);
System.out.println("Grammar " + trFile.getName() + " was loaded successfully.");
}
if (useCache){
System.out.println("Only changed modules have been loaded.");
System.out.println("Hold Shift while clicking the Load button to clear cache.");
}
} finally {
monitor.done();
}
return Status.OK_STATUS;
}
});
getLoadGrammarJob().setRule(new LoadSchedulingRule());
getLoadGrammarJob().schedule();
getLoadGrammarJob().wakeUp();
}
public static Job getLoadGrammarJob() {
return loadGrammarJob;
}
public static void setLoadGrammarJob(Job loadGrammarJob) {
LoadHandler.loadGrammarJob = loadGrammarJob;
}
public Object execute(ExecutionEvent event) throws ExecutionException {
if (event != null && event.getTrigger() instanceof Event){
int shift = SWT.SHIFT & ((Event)event.getTrigger()).stateMask;
if (shift != 0){// press shift while clicking button to clear cache
cacheTimes.clear();
cacheFiles.clear();
}
}
// clear all lists from possible previous execution
loadQueue.clear();
trSystems.clear();
trFileNames.clear();
// Find grammar files to load:
ISelection sel = HandlerUtil.getCurrentSelection(event);
if (sel != null && sel instanceof IStructuredSelection) {
IStructuredSelection structSel = (IStructuredSelection) sel;
@SuppressWarnings("unchecked")
Iterator<Object> it = structSel.iterator();
for (;it.hasNext();) {
Object obj = it.next();
if (obj instanceof IFile) {
IFile file = (IFile) obj;
if (file.getFileExtension().equals(henshinExt)) {
loadQueue.add(file);
}
}
if (obj instanceof IContainer) {
IResource[] resArr;
try {
resArr = ((IContainer) obj).members();
for (int i=0; i<resArr.length; i++) {
if (resArr[i] instanceof IFile) {
IFile file = (IFile) resArr[i];
if (file.getFileExtension().equals(henshinExt)) {
loadQueue.add(file);
}
}
}
} catch (CoreException e) {
e.printStackTrace();
}
}
for(IFile f:loadQueue){
trFileNames.add(f.getName());
}
}
}
saveCachedQueue();
System.out.println("Registered Grammars will be loaded when needed.");
return null;
}
}