package de.ugoe.cs.swe.bnftools.ui.actions; import java.io.ByteArrayInputStream; import java.io.InputStream; import java.util.LinkedList; import org.eclipse.core.internal.resources.File; 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.Path; import org.eclipse.emf.common.util.EList; import org.eclipse.emf.common.util.URI; import org.eclipse.emf.ecore.resource.Resource; import org.eclipse.jface.action.IAction; import org.eclipse.jface.dialogs.InputDialog; import org.eclipse.jface.viewers.ISelection; import org.eclipse.jface.viewers.IStructuredSelection; import org.eclipse.jface.viewers.StructuredSelection; import org.eclipse.jface.viewers.TreePath; import org.eclipse.jface.viewers.TreeSelection; import org.eclipse.ui.PlatformUI; import org.eclipse.ui.actions.ActionDelegate; import org.eclipse.ui.dialogs.ResourceSelectionDialog; import org.eclipse.xtext.parsetree.AbstractNode; import org.eclipse.xtext.parsetree.CompositeNode; import org.eclipse.xtext.parsetree.LeafNode; import org.eclipse.xtext.parsetree.NodeUtil; import org.eclipse.xtext.resource.XtextResource; import org.eclipse.xtext.resource.XtextResourceSet; import de.ugoe.cs.swe.bnftools.ebnf.ExtRule; import de.ugoe.cs.swe.bnftools.ebnf.Import; import de.ugoe.cs.swe.bnftools.ebnf.Rule; import de.ugoe.cs.swe.bnftools.ebnf.impl.EtsiBnfImpl; @SuppressWarnings("restriction") public class GenerateDefaultMergeDSLAction extends ActionDelegate{ private IStructuredSelection selection = StructuredSelection.EMPTY; private IFile file=null; private LinkedList deltas = null; private LinkedList deltaLabels; @Override public void run(IAction action) { TreeSelection treeSelection = (TreeSelection) selection; TreePath[] paths = treeSelection.getPaths(); for (int i = 0; i < paths.length; i++) { TreePath path = paths[i]; IFile f = (IFile) path.getLastSegment(); XtextResourceSet set = new XtextResourceSet(); String fp = f.getFullPath().toString(); URI uri = URI.createPlatformResourceURI(fp,true); Resource resource = set.getResource(uri, true); if (resource instanceof XtextResource) { XtextResource xtextResource = (XtextResource) resource; //if the selected grammar isn't a BNF grammar, return if(!(((EtsiBnfImpl) xtextResource.getParseResult().getRootNode().getElement()).getType()==null|| ((((EtsiBnfImpl) xtextResource.getParseResult().getRootNode().getElement()).getType().equals("/bnf"))))) continue; //create a file to write the new grammar in //TODO: add a validator InputDialog di = new InputDialog(PlatformUI.getWorkbench().getActiveWorkbenchWindow().getShell(), "Name Selection", "Please type a name for the merge grammar.", uri.trimFileExtension().segment(uri.segmentCount()-1) + "_merge.bnf", null); di.open(); if (di.getReturnCode() == InputDialog.CANCEL) return; String fname = di.getValue(); String loc = uri.trimFileExtension().trimSegments(1).toPlatformString(true); loc = loc.concat("/" + fname); IPath filePath = new Path(loc); file = ResourcesPlugin.getWorkspace().getRoot().getFile(filePath); try { if (!file.exists()) { byte[] bytes = ("//Automatically generated merge grammar from: " + uri.trimFileExtension().segment(uri.segmentCount()-1) + '\n').getBytes(); InputStream source = new ByteArrayInputStream(bytes); file.create(source, IResource.NONE, null); } else return; } catch (CoreException e) { e.printStackTrace(); } createNewLine("/merge;" + '\n' + '\n'); // createNewLine("corebnf: " + '\"' + uri.segment(uri.segmentCount()-1) + '\"'+ ";" + '\n'); createNewLine("import " + '\"' + uri.segment(uri.segmentCount()-1) + '\"' + " /core label: Core" + ";" + '\n'); //create a dialog, asking to select the extensions to that grammar (in delta form) //TODO: possibility: auto convert non-delta packages to delta grammars ResourceSelectionDialog di2 = new ResourceSelectionDialog(PlatformUI.getWorkbench().getActiveWorkbenchWindow().getShell(), f.getWorkspace().getRoot(), "Please select the extensions to the grammar!"); di2.open(); Object[] a = di2.getResult(); /* * add each selected delta grammar to a list of grammar * (now checks if it imports the selected grammar) */ deltas = new LinkedList(); deltaLabels = new LinkedList(); int counter=1; for(int p=0; p < a.length; p++) { File b = (File) a[p]; if(!b.getFileExtension().equals("bnf")) continue; URI ur = URI.createFileURI(b.getRawLocation().toPortableString()); Resource res = set.getResource(ur, true); if(res instanceof XtextResource) { XtextResource xres = (XtextResource) res; if(((EtsiBnfImpl) xres.getParseResult().getRootNode().getElement()) .getType()==null) continue; if(((EtsiBnfImpl) xres.getParseResult().getRootNode().getElement()).getType().equals("/delta")) { if(checkImport(xres.getParseResult().getRootNode(), uri.segment(uri.segmentCount()-1))) { deltas.add(xres.getParseResult().getRootNode()); deltaLabels.add("Package" + counter); // createNewLine("package:" + '\"' + res.getURI().segment(res.getURI().segmentCount()-1) + '\"' + ";" + '\n'); createNewLine("import " + '\"' + res.getURI().segment(res.getURI().segmentCount()-1) + '\"' + " /package label: Package" + counter + ";" + '\n'); counter++; } } } } createNewLine('\n' + " global combinator: /and" + '\n' ); //handle the extensions to each rule of the core grammar, if any for(AbstractNode node: NodeUtil.getAllContents( xtextResource.getParseResult().getRootNode())) { if(node.getElement() instanceof Rule) { handleExtensions(node); } } } } } /* * 1. check each rule in every package if it extends the given rule * if it does, add it to a list of rules * If any found: * 2. create a general rule combinator with the rule as a comment * 3. repeat: 3.1 take the rule from the list with the lowest extension point. * 3.2 if its the first extension at that point, create a new hook combinator * 3.3 create a comment with the extension * 3.4 remove it from the list of rules * until no rules remain in the list * */ private void handleExtensions(AbstractNode node) { LinkedList rules = new LinkedList(); String name = ((Rule) node.getElement()).getName().trim(); for(int i=0; i < deltas.size(); i++) { for(AbstractNode node2: NodeUtil.getAllContents(deltas.get(i))){ if(node2.getElement() instanceof ExtRule) if(((ExtRule) node2.getElement()).getName().equals(name)) rules.add(node2); } } AbstractNode old=null; AbstractNode current=null; if(rules.size()!=0) { createNewLine("\n \n" + "// rule combinator: " + name + " /and" + '\n'); createNewLine("// " + removeNewLines(node) + '\n'); boolean start = true; while(rules.size() > 0) { current = selectFirstExtension(rules); int index = deltas.indexOf(current.getParent().getParent()); if(start) { old = current; } /// URI uri = current.getElement().eResource().getURI(); if((((ExtRule) current.getElement()).getRuleext()!=((ExtRule) old.getElement()).getRuleext()) || start) { createNewLine('\n' + "hook combinator: " + name + " (" + ((ExtRule) current.getElement()).getRuleext() + ") " + '\n' + " ( \"" + deltaLabels.get(index) + "\" )" ); start=false; } else { createNewLine(" \n ( \"" + deltaLabels.get(index) + "\" )"); } createNewLine('\n' + "// " + current.serialize().trim() ); old=current; } } } //checks if the grammar, described by compNode imports the given uri private boolean checkImport(CompositeNode compNode, String uri) { Iterable allNodes = NodeUtil.getAllContents(compNode); for(AbstractNode node : allNodes) { if(node.getElement() instanceof Import) if(((Import) node.getElement()).getImportURI().equals(uri)) return true; } return false; } //removes all the lines from the string describing a node private String removeNewLines(AbstractNode node) { EList leaves = node.getLeafNodes(); String temp = ""; for(int i=0; i rules) { AbstractNode first = rules.get(0); int index = 0; for(int i=0; i ((ExtRule) rules.get(i).getElement()).getRuleext()) { first=rules.get(i); index=i; } } rules.remove(index); return first; } //creates a new line in the file private void createNewLine(String rule) { try { if (file.exists()) { byte[] bytes = (rule).getBytes(); InputStream source = new ByteArrayInputStream(bytes); file.appendContents(source, IResource.NONE, null); } } catch (CoreException e) { e.printStackTrace(); } } @Override public void selectionChanged(IAction action, ISelection selection) { if (selection instanceof IStructuredSelection) { this.selection = (IStructuredSelection) selection; } else { this.selection = StructuredSelection.EMPTY; } } }