Skip to content

Commit

Permalink
Merge pull request #215 from eMoflon/hotfix/gtl_visualization
Browse files Browse the repository at this point in the history
Hotfix/gtl visualization
  • Loading branch information
maxkratz authored May 6, 2024
2 parents 933c26e + 7a0b2ba commit 7211276
Show file tree
Hide file tree
Showing 6 changed files with 101 additions and 931 deletions.
3 changes: 2 additions & 1 deletion .gitignore
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
**/xtend-gen/*
!**/xtend-gen/*.keep
**/bin/
**/src-gen/*
**/src-gen/*
**/plugin.xml_gen
6 changes: 5 additions & 1 deletion org.emoflon.ibex.common.visualization/META-INF/MANIFEST.MF
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ Import-Package: org.apache.log4j
Require-Bundle: org.moflon.core.ui,
org.eclipse.ui.workbench,
org.eclipse.jface,
org.emoflon.ibex.common.slimgt;bundle-version="1.0.0",
org.emoflon.ibex.common.coremodel,
org.emoflon.ibex.gt.gtmodel,
org.eclipse.emf.ecore.editor,
Expand All @@ -23,4 +24,7 @@ Require-Bundle: org.moflon.core.ui,
org.eclipse.xtext.ui,
org.eclipse.xtext.xbase,
org.moflon.core.utilities,
org.emoflon.ibex.tgg.compiler
org.emoflon.ibex.tgg.compiler,
org.emoflon.ibex.gt.gtl,
org.emoflon.ibex.common,
org.emoflon.ibex.gt
Original file line number Diff line number Diff line change
@@ -1,18 +1,24 @@
package org.emoflon.ibex.common.visualization;

import java.util.Collection;
import java.util.Optional;

import org.eclipse.emf.ecore.EObject;
import org.eclipse.emf.ecore.presentation.EcoreEditor;
import org.eclipse.core.resources.IProject;
import org.eclipse.jface.text.TextSelection;
import org.eclipse.jface.viewers.ISelection;
import org.eclipse.jface.viewers.IStructuredSelection;
import org.eclipse.jface.viewers.TreeSelection;
import org.eclipse.ui.IEditorPart;
import org.emoflon.ibex.common.coremodel.IBeXCoreModel.IBeXPatternSet;
import org.eclipse.xtext.nodemodel.ICompositeNode;
import org.eclipse.xtext.nodemodel.util.NodeModelUtils;
import org.eclipse.xtext.ui.editor.XtextEditor;
import org.emoflon.ibex.common.transformation.SlimGtToIBeXCoreTransformer;
import org.emoflon.ibex.gt.gtl.gTL.EditorFile;
import org.emoflon.ibex.gt.gtl.gTL.SlimRule;
import org.emoflon.ibex.gt.gtl.util.GTLModelFlattener;
import org.emoflon.ibex.gt.gtl.util.GTLResourceManager;
import org.emoflon.ibex.gt.gtmodel.IBeXGTModel.GTModel;
import org.emoflon.ibex.gt.gtmodel.IBeXGTModel.GTPattern;
import org.emoflon.ibex.gt.gtmodel.IBeXGTModel.GTRule;
import org.moflon.core.ui.VisualiserUtilities;
import org.emoflon.ibex.gt.gtmodel.IBeXGTModel.IBeXGTModelFactory;
import org.emoflon.ibex.gt.transformation.GTLtoGTModelTransformer;
import org.moflon.core.ui.visualisation.common.EMoflonDiagramTextProvider;

/**
Expand All @@ -23,69 +29,80 @@ public class IBeXPatternVisualizer implements EMoflonDiagramTextProvider {

@Override
public String getDiagramBody(final IEditorPart editor, final ISelection selection) {
if (selection instanceof IStructuredSelection structuredSelection) {
return visualizeSelection(structuredSelection);
EditorFile editorFile = maybeCast(XtextEditor.class).apply(editor)
.map(file -> file.getDocument().readOnly(doc -> doc.getContents().get(0))) //
.flatMap(maybeCast(EditorFile.class)).get();

IProject project = maybeCast(XtextEditor.class).apply(editor) //
.map(file -> file.getResource().getProject()) //
.get();

TextSelection textSelection = (TextSelection) selection;
for (SlimRule rule : editorFile.getRules()) {
ICompositeNode object = NodeModelUtils.getNode(rule);
if (object.getStartLine() <= textSelection.getStartLine() + 1
&& object.getEndLine() >= textSelection.getEndLine() + 1) {
try {
return visualizeSelection(project, editorFile, rule);
} catch (Exception e) {
e.printStackTrace();
}
}
}

throw new IllegalArgumentException("Invalid selection: " + selection);
try {
return visualizeSelection(project, editorFile, null);
} catch (Exception e) {
e.printStackTrace();
return null;
}
}

/**
* Visualizes the first selected element
*
* @param selection the selection
* @return the PlantUMl code for the visualization
* @throws Exception
*/
private static String visualizeSelection(final IStructuredSelection selection) {
Object element = selection.getFirstElement();

if (isPatternSet(element)) {
return IBeXPatternPlantUMLGenerator.visualizePatternInvocations((IBeXPatternSet) element);
}

if (isPattern(element)) {
return IBeXPatternPlantUMLGenerator.visualizeContextPattern((GTPattern) element);
private static String visualizeSelection(final IProject project, final EditorFile editorFile,
final SlimRule selection) throws Exception {
GTLResourceManager manager = new GTLResourceManager();
GTLModelFlattener flattener = new GTLModelFlattener(manager, editorFile, true);
EditorFile flattened = flattener.getFlattenedModel();
SlimGtToIBeXCoreTransformer<EditorFile, GTModel, IBeXGTModelFactory> transformer = new GTLtoGTModelTransformer(
flattened, project);
GTModel model = transformer.transform();

if (selection != null) {
Optional<GTRule> candidateRule = model.getRuleSet().getRules().stream()
.filter(rule -> rule.getName().equals(selection.getName())).findFirst();
if (candidateRule.isPresent()) {
return IBeXPatternPlantUMLGenerator.visualizeRule(candidateRule.get());
}
Optional<GTPattern> candidatePattern = model.getPatternSet().getPatterns().stream()
.filter(pattern -> pattern.getName().equals(selection.getName()))
.map(pattern -> (GTPattern) pattern).findFirst();
if (candidatePattern.isPresent()) {
return IBeXPatternPlantUMLGenerator.visualizeContextPattern(candidatePattern.get());
}
}

if (isRule(element)) {
return IBeXPatternPlantUMLGenerator.visualizeRule((GTRule) element);
}

throw new IllegalArgumentException("Invalid selection: " + element);
return IBeXPatternPlantUMLGenerator.visualizePatternInvocations(model.getPatternSet());
}

@Override
public boolean supportsEditor(final IEditorPart editor) {
return Optional.of(editor) //
.flatMap(maybeCast(EcoreEditor.class)) //
.map(EcoreEditor::getSelection) //
.flatMap(maybeCast(TreeSelection.class)) //
.map(TreeSelection::getFirstElement) //
.filter(o -> isPatternSet(o) || isPattern(o) || isRule(o)) //
.flatMap(maybeCast(XtextEditor.class)) //
.map(file -> file.getDocument().readOnly(doc -> doc.getContents().get(0))) //
.flatMap(maybeCast(EditorFile.class)) //
.isPresent();
}

@Override
public boolean supportsSelection(ISelection selection) {
Collection<EObject> elements = VisualiserUtilities.extractEcoreSelection(selection);
if (elements == null)
return false;

return elements.stream()
.filter(elt -> elt.eClass().getEPackage().getName().contains("org.emoflon.ibex.patternmodel")).findAny()
.isPresent();
}

private static boolean isPatternSet(final Object object) {
return object instanceof IBeXPatternSet;
}

private static boolean isPattern(final Object object) {
return object instanceof GTPattern;
}

private static boolean isRule(final Object object) {
return object instanceof GTRule;
// Note: If the editor is detected correctly, this must be true anyways!
return true;
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -47,9 +47,9 @@ class IBeXPatternPlantUMLGenerator {
«commonLayoutSettings»
skinparam class {
BorderColor<<SIGNATURE>> «ContextColor»
BorderColor<<CONTEXT>> «ContextColor»
BorderColor<<LOCAL>> «LocalColor»
FontColor<<SIGNATURE>> «ContextColor»
FontColor<<CONTEXT>> «ContextColor»
FontColor<<LOCAL>> «LocalColor»
}
Expand All @@ -68,9 +68,9 @@ class IBeXPatternPlantUMLGenerator {
val packageName = prefix + pattern.name
'''
package "«packageName»" «IF !positive»#FFCCCC«ENDIF» {}
«visualizeNodes(pattern.signatureNodes, 'SIGNATURE', packageName)»
«visualizeNodes(pattern.signatureNodes, 'CONTEXT', packageName)»
«visualizeNodes(pattern.localNodes, 'LOCAL', packageName)»
«visualizeEdges(pattern.edges, ContextColor, packageName)»
«visualizeEdges(pattern.edges, ContextColor, packageName, ''
«var j = 0»
«FOR invocation : pattern.invocations»
«val newPrefix = j++ + "\\
Expand All @@ -87,26 +87,42 @@ class IBeXPatternPlantUMLGenerator {
* Visualizes the create pattern.
*/
static def String visualizeRule(GTRule rule) {
val packageName = rule.name
'''
«commonLayoutSettings»
skinparam class {
BorderColor<<CONTEXT>> «ContextColor»
BorderColor<<CREATE>> «CreateColor»
FontColor<<CONTEXT>> «ContextColor»
BorderColor<<LOCAL>> «LocalColor»
FontColor<<LOCAL>> «LocalColor»
FontColor<<CREATE>> «CreateColor»
BorderColor<<DELETE>> «DeleteColor»
FontColor<<DELETE>> «DeleteColor»
}
«visualizeNodes(rule.allNodes.filter[n | rule.precondition.signatureNodes.contains(n) && rule.postcondition.signatureNodes.contains(n)].toList, 'CONTEXT', ''
«visualizeNodes(rule.creation.nodes, 'CREATE', ''
«visualizeEdges(rule.creation.edges, CreateColor, ''
«visualizeNodes(rule.deletion.nodes, 'DELETE', ''
«visualizeEdges(rule.deletion.edges, DeleteColor, ''
package "«packageName»" {}
«visualizeNodes(rule.precondition.signatureNodes.filter[n | !rule.deletion.nodes.contains(n)].toList, 'CONTEXT', packageName)»
«visualizeNodes(rule.precondition.localNodes.toList, 'LOCAL', packageName)»
«visualizeEdges(rule.precondition.edges.filter[e | !rule.deletion.edges.contains(e)].toList, ContextColor, packageName, ''
«visualizeNodes(rule.creation.nodes, 'CREATE', packageName)»
«visualizeEdges(rule.creation.edges, CreateColor, packageName, '++'
«visualizeNodes(rule.deletion.nodes, 'DELETE', packageName)»
«visualizeEdges(rule.deletion.edges, DeleteColor, packageName, '--'
«var j = 0»
«FOR invocation : rule.precondition.invocations»
«val newPrefix = j++ + "\\
«printPattern(invocation.invocation as GTPattern, newPrefix, invocation.positive)»
«FOR mapEntry : invocation.mapping.entrySet»
"«node(mapEntry.key, packageName)»" #--# "«node(mapEntry.value, newPrefix + invocation.invocation.name)»"
«ENDFOR»
«ENDFOR»
center footer
= Create Pattern «rule.name»
= Rule «rule.name»
end footer
'''
}
Expand All @@ -132,10 +148,10 @@ class IBeXPatternPlantUMLGenerator {
/**
* Outputs the edges.
*/
private static def String visualizeEdges(List<IBeXEdge> edges, String color, String nodePrefix) {
private static def String visualizeEdges(List<IBeXEdge> edges, String color, String nodePrefix, String op) {
'''
«FOR edge : edges»
"«node(edge.source, nodePrefix)»" -[#«color»]-> "«node(edge.target, nodePrefix)»": «» <color:«color»>«edge.type.name»
"«node(edge.source, nodePrefix)»" -[#«color»]-> "«node(edge.target, nodePrefix)»": «» <color:«color»>«op»«edge.type.name»
«ENDFOR»
'''
}
Expand Down
Loading

0 comments on commit 7211276

Please sign in to comment.