| /******************************************************************************* |
| * Copyright (c) 2004-2008 Istvan Rath and Daniel Varro |
| * 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: |
| * Istvan Rath - initial API and implementation |
| *******************************************************************************/ |
| |
| package org.eclipse.viatra2.frameworkgui.content.transformation;
|
|
|
| import java.util.ArrayList; |
| import java.util.Collection; |
| import java.util.HashMap; |
| import java.util.HashSet; |
| import java.util.Iterator; |
| import java.util.List; |
| import java.util.Map; |
| import java.util.Set; |
| import java.util.Vector; |
| |
| import org.eclipse.emf.ecore.EObject; |
| import org.eclipse.emf.ecore.EStructuralFeature.Setting; |
| import org.eclipse.emf.ecore.util.EcoreUtil; |
| import org.eclipse.emf.ecore.util.EcoreUtil.UsageCrossReferencer; |
| import org.eclipse.jface.action.IAction; |
| import org.eclipse.jface.action.IContributionItem; |
| import org.eclipse.swt.graphics.Image; |
| import org.eclipse.ui.views.properties.IPropertySource2; |
| import org.eclipse.viatra2.framework.IFramework; |
| import org.eclipse.viatra2.framework.IMachineSetChangedListener; |
| import org.eclipse.viatra2.frameworkgui.FrameworkGUIPlugin; |
| import org.eclipse.viatra2.frameworkgui.actions.extend.ContributedActionContainer; |
| import org.eclipse.viatra2.frameworkgui.content.FrameworkContainer; |
| import org.eclipse.viatra2.frameworkgui.content.IFrameworkContentProviderExtension; |
| import org.eclipse.viatra2.frameworkgui.content.ITreeObject; |
| import org.eclipse.viatra2.frameworkgui.content.ITreeParent; |
| import org.eclipse.viatra2.frameworkgui.views.FrameworkTreeView; |
| import org.eclipse.viatra2.gtasmmodel.gtasm.metamodel.asm.core.GTASMElement; |
| import org.eclipse.viatra2.gtasmmodel.gtasm.metamodel.asm.definitions.ASMFunction; |
| import org.eclipse.viatra2.gtasmmodel.gtasm.metamodel.asm.definitions.Machine; |
| import org.eclipse.viatra2.gtasmmodel.gtasm.metamodel.asm.definitions.Rule; |
| import org.eclipse.viatra2.gtasmmodel.gtasm.metamodel.asm.simpleRules.CallRule; |
| import org.eclipse.viatra2.gtasmmodel.gtasm.metamodel.asm.simpleRules.GTRuleInvocation; |
| import org.eclipse.viatra2.gtasmmodel.gtasm.metamodel.asm.simpleRules.RuleUpdateASMFunction; |
| import org.eclipse.viatra2.gtasmmodel.gtasm.metamodel.asm.terms.ASMFunctionInvocation; |
| import org.eclipse.viatra2.gtasmmodel.gtasm.metamodel.asm.terms.GTPatternCall; |
| import org.eclipse.viatra2.gtasmmodel.gtasm.metamodel.gt.GTPattern; |
| import org.eclipse.viatra2.gtasmmodel.gtasm.metamodel.gt.GTRule; |
| import org.eclipse.viatra2.lpgparser.modelbuilder.VTCLModelResolver; |
|
|
| public class TransformationContent
|
| implements IFrameworkContentProviderExtension, IMachineSetChangedListener, ITreeParent
|
| {
|
|
|
| private RunModelAction runAction;
|
|
|
| private DeleteModelAction deleteAction;
|
|
|
| private SaveModelAction saveAction;
|
|
|
| private SaveTransformationAction saveTransformationAction;
|
|
|
| private Vector<IAction> actions; |
| |
| private CrossReferenceManager xrefman;
|
|
|
| public Collection<IAction> getActions()
|
| {
|
| ArrayList<IAction> r = new ArrayList<IAction>();
|
| r.add(saveTransformationAction);
|
| return r;
|
| }
|
|
|
| public Collection<IContributionItem> getContributionItems()
|
| {
|
| return null;
|
| }
|
|
|
| public ITreeObject getTopLevelEntry()
|
| {
|
| return this;
|
| }
|
|
|
| private FrameworkTreeView viewer;
|
| private IFramework fw;
|
| private FrameworkContainer cont;
|
|
|
| //private HashSet<ContributedActionContainer> contributedActions = new HashSet<ContributedActionContainer>();
|
|
|
| private void processContributedActions(FrameworkTreeView ftv)
|
| {
|
| for (ContributedActionContainer c : FrameworkGUIPlugin.getDefault().getContributedActions())
|
| {
|
| if (c.enablesFor.equals(Machine.class))
|
| {
|
| c.action.setupInternals(ftv);
|
| //contributedActions.add(c);
|
| actions.add(c.action);
|
| }
|
| }
|
| }
|
|
|
| public void init(FrameworkTreeView fv, IFramework f, FrameworkContainer c)
|
| {
|
| viewer = fv; this.fw = f; cont = c;
|
| runAction = new RunModelAction(fv);
|
| deleteAction = new DeleteModelAction(fv);
|
| saveAction = new SaveModelAction(fv);
|
| saveTransformationAction = new SaveTransformationAction(fv); |
| xrefman = new CrossReferenceManager();
|
|
|
| processContributedActions(fv);
|
|
|
| actions.add(runAction);
|
| actions.add(deleteAction);
|
| actions.add(saveAction);
|
|
|
| //actions.add(saveTransformationAction);
|
| initMachines();
|
| f.addMachineSetListener(this);
|
|
|
| brokenRefs = new HashMap<EObject, Collection<Setting>>();
|
| }
|
|
|
| private Map<Object, ITreeObject> machines;
|
|
|
| public TransformationContent()
|
| {
|
| machines = new HashMap<Object, ITreeObject>();
|
| actions = new Vector<IAction>();
|
| }
|
|
|
| public void dispose()
|
| {
|
| fw.removeMachineSetListener(this);
|
| }
|
|
|
| public Set<ITreeObject> getChildren()
|
| {
|
| return new HashSet<ITreeObject>(machines.values());
|
| }
|
|
|
| public boolean hasChildren()
|
| {
|
| return !machines.isEmpty();
|
| }
|
|
|
| public FrameworkContainer getFrameworkContainer()
|
| {
|
| return cont;
|
| }
|
|
|
| public Image getLabelImage()
|
| {
|
| // TODO
|
| return null;
|
| }
|
|
|
| public String getLabelText()
|
| {
|
| return "Program models";
|
| }
|
|
|
| public ITreeParent getParent()
|
| {
|
| return cont;
|
| }
|
|
|
| public IPropertySource2 getPropertySource()
|
| {
|
| // TODO
|
| return null;
|
| }
|
|
|
| protected static Image machine_image = FrameworkGUIPlugin.getImageDescriptor("icons/machine_transparent.png").createImage();
|
|
|
| public class MachineDummy implements ITreeObject
|
| {
|
|
|
| public MachineDummy(Machine m)
|
| {
|
| machine = m;
|
| if (m.getModule()!=null)
|
| moduleName = m.getModule().getName();
|
| else
|
| moduleName = "";
|
| }
|
|
|
| public Machine getMachine()
|
| {
|
| return machine;
|
| }
|
|
|
| Machine machine;
|
|
|
| String moduleName;
|
|
|
| MachinePropertySource propertySource;
|
|
|
| public FrameworkContainer getFrameworkContainer() {
|
| return cont;
|
| }
|
|
|
| public Image getLabelImage()
|
| {
|
| return machine_image;
|
| }
|
|
|
| public String getLabelText()
|
| { |
| String s = ""; |
| if (xrefman.hasUnresolvedReferences(machine.getFqn())) { |
| s = " [UNRESOLVED]"; |
| }
|
| return machine.getFqn()+" ("+moduleName+")"+s;
|
| }
|
|
|
| public ITreeParent getParent()
|
| {
|
| return TransformationContent.this;
|
| }
|
|
|
| public IPropertySource2 getPropertySource() {
|
| if (propertySource == null)
|
| propertySource = new MachinePropertySource(machine);
|
| return propertySource;
|
| }
|
|
|
| public Collection<IContributionItem> getContributionItems() {
|
| return null;
|
| }
|
|
|
| public Collection<IAction> getActions()
|
| {
|
| return actions;
|
| }
|
|
|
| public IAction getDoubleClickAction() {
|
| return runAction;
|
| }
|
|
|
| }
|
|
|
| private void initMachines()
|
| {
|
| for (Object _m : fw.getMachines())
|
| {
|
| if (_m instanceof Machine)
|
| machines.put(_m, new MachineDummy((Machine)_m));
|
| }
|
| }
|
|
|
| public void machineAdded(Object machine)
|
| {
|
| if (machine instanceof Machine) {
|
| resolveBrokenLinks((Machine) machine);
|
| machines.put(machine , new MachineDummy((Machine)machine)); |
| xrefman.checkResolvedReference(((Machine)machine).getFqn());
|
| }
|
| viewer.refreshViewer(this);
|
| }
|
|
|
| public void machineRemoved(Object machine)
|
| {
|
| if (machine instanceof Machine) {
|
| recordBrokenLinks((Machine) machine);
|
| machines.remove(machine); |
| xrefman.checkUnresolvedReference(((Machine)machine).getFqn());
|
| }
|
| viewer.refreshViewer(this);
|
| }
|
|
|
| public IAction getDoubleClickAction() {
|
| return null;
|
| }
|
|
|
| // -- Added by Daniel Varro to record broken references --
|
| private Map<EObject, Collection<Setting>> brokenRefs;
|
|
|
| /**
|
| * This method records all links which will be broken due to the removal
|
| * of removedMachine
|
| * @param removedMachine : the {@link Machine} to be removed
|
| */
|
| protected void recordBrokenLinks(Machine removedMachine) {
|
| List<GTASMElement> defsToResolve = new ArrayList<GTASMElement>();
|
| List<Machine> machinesToSearch = new ArrayList<Machine>(); |
|
|
| for (int i = 0; i < removedMachine.getAsmFunctionDefinitions().size(); i++) {
|
| ASMFunction asmFun = removedMachine.getAsmFunctionDefinitions().get(i);
|
| defsToResolve.add(asmFun);
|
| }
|
|
|
| for (int i = 0; i < removedMachine.getAsmRuleDefinitions().size(); i++) {
|
| Rule asmRule = removedMachine.getAsmRuleDefinitions().get(i);
|
| defsToResolve.add(asmRule);
|
| }
|
|
|
| for (int i = 0; i < removedMachine.getGtPatternDefinitions().size(); i++) {
|
| GTPattern gtPatt = removedMachine.getGtPatternDefinitions().get(i);
|
| defsToResolve.add(gtPatt);
|
| }
|
|
|
| for (int i = 0; i < removedMachine.getGtRuleDefinitions().size(); i++) {
|
| GTRule gtRule = removedMachine.getGtRuleDefinitions().get(i);
|
| defsToResolve.add(gtRule);
|
| }
|
|
|
| // Recording machines of interest (disregarding the machine to be removed)
|
| for (Object obj : fw.getMachines()) {
|
| Machine machine = (Machine) obj;
|
| if (machine != removedMachine) {
|
| machinesToSearch.add(machine);
|
| }
|
| }
|
|
|
| // Recording cross references
|
| if (!machinesToSearch.isEmpty() && !defsToResolve.isEmpty()) {
|
| brokenRefs.putAll( UsageCrossReferencer.findAll(defsToResolve, machinesToSearch));
|
| }
|
|
|
| // Removing cross references leading out from the machine to be removed
|
| removeLinksFromRemovedMachine(removedMachine);
|
| }
|
|
|
| protected void removeLinksFromRemovedMachine (Machine removedMachine) { |
| // toRemove is a collection of Settings (i.e. a representation of a value held by a feature of an object) |
| Collection<Setting> toRemove = new ArrayList<Setting>(); |
| // if there are broken references recorded by the framework
|
| if (brokenRefs != null) {
|
| toRemove.clear();
|
| Iterator<Collection<Setting>> it = brokenRefs.values().iterator();
|
| while (it.hasNext()) {
|
| Collection<Setting> settings = it.next();
|
| for (Setting setting : settings) {
|
| GTASMElement element = (GTASMElement) setting.getEObject(); |
| // Check if removed machine is a parent / ancestor of element
|
| if (EcoreUtil.isAncestor(removedMachine, element)) { |
| // Schedule the setting for removal
|
| toRemove.add(setting); |
| }
|
| // Unset the feature of the object |
| setting.unset(); |
| }
|
| if (!toRemove.isEmpty()) {
|
| settings.removeAll(toRemove);
|
| }
|
| }
|
| Collection<EObject> brokenRefsToRemove = new ArrayList<EObject>(); |
| Iterator<EObject> it2 = brokenRefs.keySet().iterator(); |
| while (it2.hasNext()) { |
| EObject nextKey = it2.next(); |
| if (brokenRefs.get(nextKey).isEmpty()) { |
| brokenRefsToRemove.add(nextKey); |
| } |
| |
| } |
| for (EObject nextObject : brokenRefsToRemove) { |
| brokenRefs.remove(nextObject); |
| } |
| }
|
| }
|
|
|
| protected void resolveBrokenLinks(Machine addedMachine) {
|
| Collection<Setting> toRemove = new ArrayList<Setting>();
|
| if (brokenRefs != null) {
|
| for (Collection<Setting> settings : brokenRefs.values()){
|
| toRemove.clear();
|
| for (Setting setting : settings) {
|
| //GTASMElement element = (GTASMElement) setting.getEObject();
|
| //System.out.println("Resolving " + element.getFqn() + ":" + element.getClass().getCanonicalName());
|
| GTASMElement result = resolveGTASMElement(setting);
|
| if (result != null) {
|
| toRemove.add(setting);
|
| }
|
| }
|
| if (!toRemove.isEmpty()) {
|
| settings.removeAll(toRemove);
|
| }
|
| //brokenRefs.remove(arg0);
|
| } |
| |
| Collection<EObject> brokenRefsToRemove = new ArrayList<EObject>(); |
| Iterator<EObject> it2 = brokenRefs.keySet().iterator(); |
| while (it2.hasNext()) { |
| EObject nextKey = it2.next(); |
| if (brokenRefs.get(nextKey).isEmpty()) { |
| brokenRefsToRemove.add(nextKey); |
| } |
| |
| } |
| for (EObject nextObject : brokenRefsToRemove) { |
| brokenRefs.remove(nextObject); |
| } |
| }
|
| }
|
|
|
|
|
| protected GTASMElement resolveGTASMElement(Setting setting) {
|
| EObject refObject = setting.getEObject();
|
| VTCLModelResolver fModelResolver = new VTCLModelResolver();
|
| if (refObject instanceof CallRule) {
|
| CallRule asmRuleInvoc = (CallRule) refObject;
|
| return fModelResolver.reportAsmRuleInvocResolutionError(asmRuleInvoc, null, fw);
|
| }
|
| else if (refObject instanceof GTPatternCall) {
|
| GTPatternCall pattCall = (GTPatternCall) refObject;
|
| return fModelResolver.reportGtPatternCallResolutionError(pattCall, null, fw);
|
| }
|
| else if (refObject instanceof GTRuleInvocation) {
|
| GTRuleInvocation gtInvoc = (GTRuleInvocation) refObject;
|
| return fModelResolver.reportGtRuleResolutionError(gtInvoc, null, fw);
|
| }
|
| else if (refObject instanceof ASMFunctionInvocation) {
|
| ASMFunctionInvocation funInvoc = (ASMFunctionInvocation) refObject;
|
| return fModelResolver.reportFunInvocResolutionError(funInvoc, null, fw);
|
| }
|
| else if (refObject instanceof RuleUpdateASMFunction) {
|
| RuleUpdateASMFunction updateRule = (RuleUpdateASMFunction) refObject;
|
| return fModelResolver.reportAsmFunUpdateResolutionError(updateRule, null, fw);
|
|
|
| }
|
| else {
|
| return null;
|
| }
|
|
|
| }
|
|
|
| }
|