/******************************************************************************* * Copyright (c) 2006-2012 * Software Technology Group, Dresden University of Technology * DevBoost GmbH, Berlin, Amtsgericht Charlottenburg, HRB 140026 * * 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: * Software Technology Group - TU Dresden, Germany; * DevBoost GmbH - Berlin, Germany * - initial API and implementation ******************************************************************************/ package org.reuseware.coconut.compositionprogram.diagram.edit.parts.syntax; import java.util.ArrayList; import java.util.Collections; import java.util.LinkedHashMap; import java.util.List; import java.util.Map; import org.eclipse.core.resources.IResource; import org.eclipse.core.resources.ResourcesPlugin; import org.eclipse.draw2d.IFigure; import org.eclipse.draw2d.MarginBorder; import org.eclipse.draw2d.RoundedRectangle; import org.eclipse.draw2d.StackLayout; 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.URIConverter; import org.eclipse.gmf.runtime.draw2d.ui.mapmode.IMapMode; import org.eclipse.gmf.runtime.gef.ui.figures.DefaultSizeNodeFigure; import org.eclipse.gmf.runtime.gef.ui.figures.NodeFigure; import org.eclipse.jface.resource.ImageDescriptor; import org.eclipse.jface.resource.ImageRegistry; import org.eclipse.swt.graphics.Image; import org.eclipse.ui.PlatformUI; import org.reuseware.coconut.compositionprogram.CompositionProgram; import org.reuseware.coconut.compositionprogram.FragmentInstance; import org.reuseware.coconut.compositionprogram.PortInstance; import org.reuseware.coconut.compositionprogram.diagram.part.CompositionprogramDiagramEditorPlugin; import org.reuseware.coconut.fragment.CompositionInterface; import org.reuseware.coconut.fragment.Fragment; import org.reuseware.coconut.resource.sokan.util.SokanReuseResourceUtil; import org.reuseware.coconut.reuseextension.CompositionLanguageSyntaxSpecification; import org.reuseware.coconut.reuseextension.FragmentRole2SyntaxBinding; import org.reuseware.coconut.reuseextension.PortType2SyntaxBinding; import org.reuseware.coconut.reuseextension.SyntaxDerivationRule; import org.reuseware.coconut.reuseextension.evaluator.EvaluatorUtil; import org.reuseware.coconut.reuseextensionactivator.Argument; import org.reuseware.coconut.reuseextensionactivator.ReuseExtensionActivator; /** * Manager class to apply customized syntax to elements in a UCPI diagram * according to composition language syntax specification activated in * the context of the shown composition program. */ public final class SyntaxManager { /** * The singleton instance of the syntax manager. */ public static final SyntaxManager INSTANCE = new SyntaxManager(); private SyntaxManager() { } private NodeFigure createNodePlate(ElementSyntax elementSyntax, boolean parentVisible, IMapMode mapMode) { if (elementSyntax.isVisible() && parentVisible) { return new DefaultSizeNodeFigure( mapMode.DPtoLP(elementSyntax.getWidth()), mapMode.DPtoLP(elementSyntax.getHeight())); } else { return new DefaultSizeNodeFigure( mapMode.DPtoLP(0), mapMode.DPtoLP(0)); } } protected IFigure createNodeShape(ElementSyntax elementSyntax, IMapMode mapMode) { IFigure figure = null; if (elementSyntax.isVisible()) { figure = new IconNodeFigure(); figure.setSize(elementSyntax.getWidth(), elementSyntax.getHeight()); figure.setBorder(new MarginBorder(mapMode.DPtoLP(3), mapMode.DPtoLP(3), mapMode.DPtoLP(3), mapMode.DPtoLP(3))); } else { //create a figure anyway such that the generated GMF code can behave as usual figure = new RoundedRectangle(); figure.setVisible(false); } return figure; } /** * Creates a figure for a fragment instances by taking syntax specifications * in context into account. * * @param fragmentInstance the fragment instances for which a figure is needed * @param mapMode to calculate with correct units * @return the figure */ public NodeFigure createFragmentInstanceFigure(FragmentInstance fragmentInstance, IMapMode mapMode) { if (fragmentInstance == null || fragmentInstance.eIsProxy()) { return null; } for (ElementSyntax elementSyntax : findSyntax(fragmentInstance)) { NodeFigure figure = createNodePlate(elementSyntax, true, mapMode); figure.setLayoutManager(new StackLayout()); IFigure shape = createNodeShape(elementSyntax, mapMode); figure.add(shape); return figure; } return null; } /** * @param fragmentInstance the fragment instance to display * @return the icon for the fragment instance * (according to syntax specifications in context) */ public Image getIcon(FragmentInstance fragmentInstance) { String icon = null; String pluginID = null; URI basePath = null; for (ElementSyntax elementSyntax : findSyntax(fragmentInstance)) { Fragment fragment = fragmentInstance.getFragment(); if (fragment != null && !fragment.getContents().isEmpty()) { icon = elementSyntax.getIcon(); Resource resource = fragment.getContents().get(0).eResource(); if (resource != null) { URIConverter uriConverter = resource.getResourceSet().getURIConverter(); URI normalizedURI = uriConverter.normalize(resource.getURI()); basePath = normalizedURI.trimSegments(fragment.getUFI().size()); if (normalizedURI.isPlatformPlugin()) { pluginID = normalizedURI.segment(1); } } } //for now, only consider the first syntax found break; } ImageRegistry imageRegistry = CompositionprogramDiagramEditorPlugin.getInstance( ).getImageRegistry(); Image image = null; if (icon == null || "".equals(icon)) { List<String> ufi = fragmentInstance.getUFI(); if (!fragmentInstance.getUFI().isEmpty()) { String fileName = ufi.get(ufi.size() - 1); image = imageRegistry.get(fileName); if (image == null) { ImageDescriptor desc = PlatformUI.getWorkbench().getEditorRegistry().getImageDescriptor( fileName); image = desc.createImage(); imageRegistry.put(fileName, image); } } } else { image = imageRegistry.get(icon); if (image == null && basePath != null) { ImageDescriptor imageDescriptor = null; String fullIconPath = basePath.appendSegments(icon.split("/")).toPlatformString(true); if (pluginID != null) { //trim plugin ID fullIconPath = fullIconPath.substring(pluginID.length() + 1); imageDescriptor = CompositionprogramDiagramEditorPlugin.imageDescriptorFromPlugin(pluginID, fullIconPath); imageRegistry.put(icon, imageDescriptor); } else { if (fullIconPath != null) { IResource iconFile = ResourcesPlugin.getWorkspace().getRoot().findMember( fullIconPath); if (iconFile != null) { String iconPath = iconFile.getRawLocation().toString(); imageRegistry.put( icon, new Image(null, iconPath)); } } } image = imageRegistry.get(icon); } } return image; } private List<ElementSyntax> findSyntax(EObject element) { if (element == null || element.eResource() == null || element.eResource().getResourceSet() == null) { return Collections.emptyList(); } List<ElementSyntax> resultList = new ArrayList<ElementSyntax>(); ResourceSet rs = element.eResource().getResourceSet(); if (element instanceof PortInstance) { PortInstance portInstance = (PortInstance) element; CompositionProgram compositionProgram = portInstance.getFragmentInstance().getCompositionProgram(); Fragment fragment = portInstance.getFragmentInstance().getFragment(); if (compositionProgram != null && fragment != null) { List<ReuseExtensionActivator> activatorList = SokanReuseResourceUtil.findReuseExtensionActivators( compositionProgram.getUCPI(), rs); for (ReuseExtensionActivator activator : activatorList) { if (activator.getReuseExtension() instanceof CompositionLanguageSyntaxSpecification) { CompositionLanguageSyntaxSpecification clSyntax = (CompositionLanguageSyntaxSpecification) activator.getReuseExtension(); Map<String, String> args = new LinkedHashMap<String, String>(); for (Argument arg : activator.getArguments()) { args.put(arg.getParameter(), arg.getValue()); } for (FragmentRole2SyntaxBinding fragmentRoleBinding : clSyntax.getFragmentRoleBindings()) { for (PortType2SyntaxBinding portTypeBinding : fragmentRoleBinding.getPortTypeBindings()) { if (portTypeBinding.getPortType().equals(portInstance.port().getPortTypeBinding().getPortType())) { resultList.add(createElementSyntax(portTypeBinding, fragment, args)); } } } } } } } if (element instanceof FragmentInstance) { FragmentInstance fragmentInstance = (FragmentInstance) element; CompositionProgram compositionProgram = fragmentInstance.getCompositionProgram(); Fragment fragment = fragmentInstance.getFragment(); if (compositionProgram != null && fragment != null) { List<ReuseExtensionActivator> activatorList = SokanReuseResourceUtil.findReuseExtensionActivators( compositionProgram.getUCPI(), rs); for (ReuseExtensionActivator activator : activatorList) { if (activator.getReuseExtension() instanceof CompositionLanguageSyntaxSpecification) { CompositionLanguageSyntaxSpecification clSyntax = (CompositionLanguageSyntaxSpecification) activator.getReuseExtension(); Map<String, String> args = new LinkedHashMap<String, String>(); for (Argument arg : activator.getArguments()) { args.put(arg.getParameter(), arg.getValue()); } for (FragmentRole2SyntaxBinding fragmentRoleBinding : clSyntax.getFragmentRoleBindings()) { if (fragmentInstance.getFragment() != null) { for (CompositionInterface ci : fragmentInstance.getFragment().getCompositionInterfaces()) { if (fragmentRoleBinding.getFragmentRole().equals(ci.getRoleBinding().getFragmentRole())) { resultList.add(createElementSyntax(fragmentRoleBinding, fragment, args)); } } } } } } } } return resultList; } private ElementSyntax createElementSyntax( SyntaxDerivationRule syntaxDerivationRule, Fragment fragment, Map<String, String> args) { if (fragment == null || fragment.getContents().isEmpty()) { return null; } boolean visible = true; if (syntaxDerivationRule.getVisibleExpression() != null) { visible = EvaluatorUtil.eval( fragment.getUFI(), fragment.getContents().get(0), syntaxDerivationRule.getVisibleExpression(), args); } boolean labelVisible = false; if (syntaxDerivationRule instanceof PortType2SyntaxBinding) { labelVisible = EvaluatorUtil.eval( fragment.getUFI(), fragment.getContents().get(0), ((PortType2SyntaxBinding) syntaxDerivationRule).getLabelExpression(), args); } int width = EvaluatorUtil.deriveInt( fragment.getUFI(), fragment.getContents().get(0), syntaxDerivationRule.getWidthExpression(), args); int height = EvaluatorUtil.deriveInt( fragment.getUFI(), fragment.getContents().get(0), syntaxDerivationRule.getHeightExpression(), args); String icon = EvaluatorUtil.derive( fragment.getUFI(), fragment.getContents().get(0), syntaxDerivationRule.getIconExpression(), args); return new ElementSyntax(visible, labelVisible, width, height, icon); } /** * * @param portInstance the port instance to display * @return true if the label of the port instance should be hidden * (according to syntax specifications in context) */ public boolean showPortLabel(PortInstance portInstance) { if (portInstance == null) { return false; } if (portInstance.port() == null) { return false; } boolean declaredVisibility = true; for (ElementSyntax elementSyntax : findSyntax(portInstance)) { declaredVisibility = declaredVisibility && elementSyntax.isLabelVisible() && elementSyntax.isVisible(); } for (ElementSyntax elementSyntax : findSyntax(portInstance.getFragmentInstance())) { declaredVisibility = declaredVisibility && elementSyntax.isVisible(); } return declaredVisibility; } /** * * @param portInstance the port instance to display * @return true if the port instance itself should be hidden * (according to syntax specifications in context) */ public boolean showPort(PortInstance portInstance) { if (portInstance == null) { return false; } if (!showFragment(portInstance.getFragmentInstance())) { return false; } //if the port is not typed (anymore) it has to be shown if (portInstance.port() == null) { return true; } boolean declaredVisibility = true; for (ElementSyntax portSyntax : findSyntax(portInstance)) { for (ElementSyntax fragmentSyntax : findSyntax(portInstance.getFragmentInstance())) { declaredVisibility = declaredVisibility && fragmentSyntax.isVisible(); declaredVisibility = declaredVisibility && portSyntax.isVisible(); } } return declaredVisibility; } /** * * @param fragmentInstance the fragment instance to display * @return true if the fragment instance should be hidden * (according to syntax specifications in context) */ public boolean showFragment(FragmentInstance fragmentInstance) { boolean declaredVisibility = true; for (ElementSyntax desc : findSyntax(fragmentInstance)) { declaredVisibility = declaredVisibility && desc.isVisible(); } return declaredVisibility; } }