diff --git a/.gitmodules b/.gitmodules index c1937bf932d29b67f9a370031744dc7e56a35a2c..98ad9897898020a28e3487125bc1928b97aa69f1 100644 --- a/.gitmodules +++ b/.gitmodules @@ -34,3 +34,9 @@ [submodule "org.fortiss.variability/.settings"] path = org.fortiss.variability/.settings url = https://git.fortiss.org/af3/plugin-settings.git +[submodule "org.fortiss.tooling.ext.reuse/.settings"] + path = org.fortiss.tooling.ext.reuse/.settings + url = https://git.fortiss.org/af3/plugin-settings.git +[submodule "org.fortiss.tooling.ext.reuse.ui/.settings"] + path = org.fortiss.tooling.ext.reuse.ui/.settings + url = https://git.fortiss.org/af3/plugin-settings.git diff --git a/org.fortiss.tooling.base.ui/META-INF/MANIFEST.MF b/org.fortiss.tooling.base.ui/META-INF/MANIFEST.MF index 1e4971a47f04654885710d833069031d3d752804..a1387ca8e25f61ee8cd2ea5e5a933ee6f71ba5db 100644 --- a/org.fortiss.tooling.base.ui/META-INF/MANIFEST.MF +++ b/org.fortiss.tooling.base.ui/META-INF/MANIFEST.MF @@ -7,7 +7,8 @@ Bundle-Activator: org.fortiss.tooling.base.ui.ToolingBaseUIActivator Require-Bundle: org.fortiss.tooling.base;bundle-version="2.23.0";visibility:=reexport, org.fortiss.tooling.kernel.ui;bundle-version="2.23.0";visibility:=reexport, org.eclipse.swt, - org.fortiss.tooling.common.ui + org.fortiss.tooling.common.ui, + org.fortiss.tooling.ext.reuse Bundle-ActivationPolicy: lazy Bundle-RequiredExecutionEnvironment: JavaSE-11 Bundle-Vendor: fortiss GmbH diff --git a/org.fortiss.tooling.base.ui/src/org/fortiss/tooling/base/ui/utils/.ratings b/org.fortiss.tooling.base.ui/src/org/fortiss/tooling/base/ui/utils/.ratings index 3f867cc1ad2785fb30df12d20c67c992a0f6bde7..f882273227172e8008c36abd1885ab2c1e9fcbdc 100644 --- a/org.fortiss.tooling.base.ui/src/org/fortiss/tooling/base/ui/utils/.ratings +++ b/org.fortiss.tooling.base.ui/src/org/fortiss/tooling/base/ui/utils/.ratings @@ -1,6 +1,6 @@ AbstractNameEditingSupport.java c57336a0e0da18711a1610ca667dfea76728807f GREEN ActionUtils.java 322f43d4f92f992daef8ac88eb0f9197c840c89b GREEN -ContextMenuUtils.java a55ceed42f2eb88ba263a6fbcb394ddb80b1eda0 GREEN +ContextMenuUtils.java 75af4d1e995f4baba451e608d1a4716f13388dbd GREEN EllipseLayoutUIUtils.java 0af2cfc038661828b1bb8c51c0a3816d453e8313 GREEN FXDNDUtils.java 6ce94e239e68f9e2b3cc0524b072606f4a120076 GREEN FontUtils.java a167a05bdaa8da9853705cc5134f30f6d81bc9f2 GREEN diff --git a/org.fortiss.tooling.base.ui/src/org/fortiss/tooling/base/ui/utils/ContextMenuUtils.java b/org.fortiss.tooling.base.ui/src/org/fortiss/tooling/base/ui/utils/ContextMenuUtils.java index a55ceed42f2eb88ba263a6fbcb394ddb80b1eda0..75af4d1e995f4baba451e608d1a4716f13388dbd 100644 --- a/org.fortiss.tooling.base.ui/src/org/fortiss/tooling/base/ui/utils/ContextMenuUtils.java +++ b/org.fortiss.tooling.base.ui/src/org/fortiss/tooling/base/ui/utils/ContextMenuUtils.java @@ -1,5 +1,5 @@ /*-------------------------------------------------------------------------+ -| Copyright 2019 fortiss GmbH | +| Copyright 2023 fortiss GmbH | | | | Licensed under the Apache License, Version 2.0 (the "License"); | | you may not use this file except in compliance with the License. | @@ -15,9 +15,13 @@ +--------------------------------------------------------------------------*/ package org.fortiss.tooling.base.ui.utils; +import static java.util.Collections.reverse; import static org.fortiss.tooling.base.utils.LayoutModelElementFactory.createPoint; +import static org.fortiss.tooling.ext.reuse.utils.ReuseLibraryUtilsBasics.getNameOfFirstRelatedLibrary; +import static org.fortiss.tooling.ext.reuse.utils.ReuseLibraryUtilsBasics.isCorrectReuseElement; import java.util.ArrayList; +import java.util.Comparator; import java.util.List; import org.eclipse.emf.ecore.EObject; @@ -62,7 +66,6 @@ public final class ContextMenuUtils { IElementCompositionContext context, boolean onlyForEditedObject) { IPrototypeService pers = IPrototypeService.getInstance(); IElementCompositorService ecs = IElementCompositorService.getInstance(); - ICommandStackService css = ICommandStackService.getInstance(); IModelEditor<EObject> activeEditor = IModelEditorBindingService.getInstance().getActiveEditor(); boolean isMenuForEditedObject = @@ -70,31 +73,94 @@ public final class ContextMenuUtils { List<MenuItem> result = new ArrayList<>(); Menu newMenu = new Menu("New ..."); - List<Prototype> protos = pers.getComposablePrototypes(target.getClass()); - for(Prototype p : protos) { - EObject prototypeCopy = p.getPrototypeCopy(); + Menu reuseMenu = new Menu("Reuse ..."); + + List<Prototype> prototypes = pers.getComposablePrototypes(target.getClass()); + List<Prototype> prototypesForNewMenu = new ArrayList<>(); + for(Prototype prototype : prototypes) { + EObject prototypeCopy = prototype.getPrototypeCopy(); // If the context menu is created for the currently edited object, offer all composable // elements. Otherwise (i.e., if context menu is created for a structural element within // the currently edited object), offer only (composable) connectors. if((!onlyForEditedObject || isMenuForEditedObject || prototypeCopy instanceof IConnector) && ecs.canCompose(target, prototypeCopy, context)) { - MenuItem mi = new MenuItem(p.getName()); - mi.setOnAction(evt -> { - css.runAsCommand(target, () -> { - ecs.compose(target, prototypeCopy, context); - }); - }); - newMenu.getItems().add(mi); + if(isCorrectReuseElement(prototypeCopy)) { + MenuItem menuItem = createMenuItemForComposableElement(prototypeCopy, target, + context, prototype.getName()); + String libraryName = getNameOfFirstRelatedLibrary(prototypeCopy); + menuItem.setText("[" + libraryName + "] " + prototype.getName()); + // To prevent that underscores are swallowed up: + menuItem.setMnemonicParsing(false); + reuseMenu.getItems().add(menuItem); + } else { + prototypesForNewMenu.add(prototype); + } } } + + // Sort first by priority and then by name (lexicographical). + prototypesForNewMenu.sort(new Comparator<Prototype>() { + @Override + public int compare(Prototype prototype1, Prototype prototype2) { + int result = prototype1.getPriority() - prototype2.getPriority(); + if(result == 0) { + // Negate integer to have the case that the order <A, B> corresponds to "A is + // greater than B" (= positive) + result = -prototype1.getName().compareTo(prototype2.getName()); + } + return result; + } + }); + // Reverse to get a descending order (highest prio at first / on top). + reverse(prototypesForNewMenu); + + for(Prototype prototype : prototypesForNewMenu) { + EObject prototypeCopy = prototype.getPrototypeCopy(); + MenuItem menuItem = createMenuItemForComposableElement(prototypeCopy, target, context, + prototype.getName()); + // To prevent that underscores are swallowed up: + menuItem.setMnemonicParsing(false); + newMenu.getItems().add(menuItem); + } + if(!newMenu.getItems().isEmpty()) { result.add(newMenu); } + if(!reuseMenu.getItems().isEmpty()) { + result.add(reuseMenu); + } return result; } + /** + * Returns a menu item for the given element with which the element can be composed with the + * given target (in the given context). + * + * @param composableElement + * The element that should be composed. + * @param target + * The target with which the element should be composed. + * @param context + * The context of the composition. + * @param itemName + * The name of the new menu item. + * @return The newly created menu item. + */ + private static MenuItem createMenuItemForComposableElement(EObject composableElement, + EObject target, IElementCompositionContext context, String itemName) { + ICommandStackService css = ICommandStackService.getInstance(); + IElementCompositorService ecs = IElementCompositorService.getInstance(); + MenuItem menuItem = new MenuItem(itemName); + menuItem.setOnAction(evt -> { + css.runAsCommand(target, () -> { + ecs.compose(target, composableElement, context); + }); + }); + return menuItem; + } + /** * Creates the menu populated with composable prototypes. * diff --git a/org.fortiss.tooling.ext.reuse/src/org/fortiss/tooling/ext/reuse/utils/.ratings b/org.fortiss.tooling.ext.reuse/src/org/fortiss/tooling/ext/reuse/utils/.ratings index 0037e17bc479904365d87a17f6aebae128fcc1e4..710fd89bbcd11381e0e04f630ac34c5a65e4ac41 100644 --- a/org.fortiss.tooling.ext.reuse/src/org/fortiss/tooling/ext/reuse/utils/.ratings +++ b/org.fortiss.tooling.ext.reuse/src/org/fortiss/tooling/ext/reuse/utils/.ratings @@ -1,3 +1,3 @@ ReuseLibraryModelElementFactory.java 4ee3eb7449e212643992a3dec6cfb8f4278efb70 GREEN -ReuseLibraryUtilsBasics.java b651b31f6d94ff98a8f965440d662bfc4655c31b GREEN +ReuseLibraryUtilsBasics.java 56ab0cab9189efd7f2408150b471f3c6cc99f30f GREEN ReuseLibraryUtilsManipulation.java 77a646db5a63ba7c61664dbcaf34a9036003fde5 GREEN diff --git a/org.fortiss.tooling.ext.reuse/src/org/fortiss/tooling/ext/reuse/utils/ReuseLibraryUtilsBasics.java b/org.fortiss.tooling.ext.reuse/src/org/fortiss/tooling/ext/reuse/utils/ReuseLibraryUtilsBasics.java index b651b31f6d94ff98a8f965440d662bfc4655c31b..56ab0cab9189efd7f2408150b471f3c6cc99f30f 100644 --- a/org.fortiss.tooling.ext.reuse/src/org/fortiss/tooling/ext/reuse/utils/ReuseLibraryUtilsBasics.java +++ b/org.fortiss.tooling.ext.reuse/src/org/fortiss/tooling/ext/reuse/utils/ReuseLibraryUtilsBasics.java @@ -53,13 +53,14 @@ public class ReuseLibraryUtilsBasics { /** * Returns whether the given element can be used as reuse element. * - * @param element The element that should be checked + * @param element + * The element that should be checked * @return True if the given element can be used as reuse element otherwise * false */ public static boolean hasReusePossibility(EObject element) { - for (Class<? extends EObject> cls : getReuseElementClasses()) { - if (cls.isInstance(element)) { + for(Class<? extends EObject> cls : getReuseElementClasses()) { + if(cls.isInstance(element)) { return true; } } @@ -70,19 +71,21 @@ public class ReuseLibraryUtilsBasics { * Returns whether the given element is a reuse element and has at least one * valid link to a {@link ReuseLibrary}. * - * @param element The element that should be checked + * @param element + * The element that should be checked * @return True if the given element is a reuse element, otherwise false */ public static boolean isCorrectReuseElement(EObject element) { // first, check if it is a (possible) reuse element in general - if (hasReusePossibility(element)) { + if(hasReusePossibility(element)) { // second, check if it has a library reference // (only then it is an actual (active) reuse element) - if (element instanceof IModelElement) { - for (IModelElementSpecification spec : ((IModelElement) element).getSpecifications()) { - if (spec instanceof ReuseElementSpec) { - String libID = ((ReuseElementSpec) spec).getSourceLibUUID(); - if (libID != null && !libID.isEmpty()) { + if(element instanceof IModelElement) { + for(IModelElementSpecification spec : ((IModelElement)element) + .getSpecifications()) { + if(spec instanceof ReuseElementSpec) { + String libID = ((ReuseElementSpec)spec).getSourceLibUUID(); + if(libID != null && !libID.isEmpty()) { return true; } } @@ -96,7 +99,8 @@ public class ReuseLibraryUtilsBasics { * Returns whether the given element is a reuse element and has at least one * valid link to a {@link ReuseLibrary} OR is a {@link ReuseLibrary} itself. * - * @param element The element that should be checked + * @param element + * The element that should be checked * @return True if the given element is a reuse element OR a reuse library, * otherwise false */ @@ -104,10 +108,29 @@ public class ReuseLibraryUtilsBasics { return (element instanceof ReuseLibrary) || isCorrectReuseElement(element); } + /** + * Returns display name of the first {@link ReuseLibrary} that is related to the given reuse + * element. If this is not the case, an empty {@link String} will be returned. This method is + * perfect for reuse elements within reuse libraries, because they have definitely only one + * connected/related library. + * + * @param element + * The reuse element whose library's name is searched + * @return Display name as string or empty string + */ + public static String getNameOfFirstRelatedLibrary(EObject element) { + ReuseElementSpec spec = getFirstReuseSpec(element); + if(spec != null) { + return spec.getSourceLibName(); + } + return ""; + } + /** * Returns display name of given {@link ReuseLibrary} (name and UUID). * - * @param library The target reuse library + * @param library + * The target reuse library * @return Display name as string */ public static String getLibraryIDName(ReuseLibrary library) { @@ -118,8 +141,10 @@ public class ReuseLibraryUtilsBasics { * Returns the current format for displaying name and UUID of * {@link ReuseLibrary}s. * - * @param libraryUUID The UUID of the target library - * @param libraryName The name of the target library + * @param libraryUUID + * The UUID of the target library + * @param libraryName + * The name of the target library * @return Formatted string */ public static String getLibraryIDNameFormat(String libraryUUID, String libraryName) { @@ -131,17 +156,18 @@ public class ReuseLibraryUtilsBasics { * {@link ReuseLibrary}), independent of the type as long as its class was * registered for reuse. * - * @param element The target reuse element + * @param element + * The target reuse element * @return Name as string */ public static String getReuseElementName(EObject element) { - if (element instanceof ReuseLibrary) { - return ((ReuseLibrary) element).getName(); + if(element instanceof ReuseLibrary) { + return ((ReuseLibrary)element).getName(); } String name = IReuseProviderService.getInstance().getReuseElementName(element); - if (name == null) { - if (element instanceof INamedElement) { - name = ((INamedElement) element).getName(); + if(name == null) { + if(element instanceof INamedElement) { + name = ((INamedElement)element).getName(); } else { name = element.toString(); } @@ -153,13 +179,15 @@ public class ReuseLibraryUtilsBasics { * Sets the name of the given reuse element (or {@link ReuseLibrary}), * independent of the type as long as its class was registered for reuse. * - * @param element The target reuse element - * @param name The new name + * @param element + * The target reuse element + * @param name + * The new name * @return True if action was successful, otherwise false */ public static boolean setReuseElementName(EObject element, String name) { - if (element instanceof ReuseLibrary) { - ((ReuseLibrary) element).setName(name); + if(element instanceof ReuseLibrary) { + ((ReuseLibrary)element).setName(name); return true; } return IReuseProviderService.getInstance().setReuseElementName(element, name); @@ -169,18 +197,19 @@ public class ReuseLibraryUtilsBasics { * Returns the comment of the given reuse element (or {@link ReuseLibrary}), * independent of the type as long as its class was registered for reuse. * - * @param element The target reuse element + * @param element + * The target reuse element * @return The requested comment as string */ public static String getReuseElementComment(EObject element) { String comment = null; - if (element instanceof ReuseLibrary) { - comment = ((ReuseLibrary) element).getComment(); + if(element instanceof ReuseLibrary) { + comment = ((ReuseLibrary)element).getComment(); } else { comment = IReuseProviderService.getInstance().getReuseElementComment(element); - if (comment == null) { - if (element instanceof INamedCommentedElement) { - comment = ((INamedCommentedElement) element).getComment(); + if(comment == null) { + if(element instanceof INamedCommentedElement) { + comment = ((INamedCommentedElement)element).getComment(); } } } @@ -191,13 +220,15 @@ public class ReuseLibraryUtilsBasics { * Sets the comment of the given reuse element (or {@link ReuseLibrary}), * independent of the type as long as its class was registered for reuse. * - * @param element The target reuse element - * @param comment The new comment + * @param element + * The target reuse element + * @param comment + * The new comment * @return True if action was successful, otherwise false */ public static boolean setReuseElementComment(EObject element, String comment) { - if (element instanceof ReuseLibrary) { - ((ReuseLibrary) element).setComment(comment); + if(element instanceof ReuseLibrary) { + ((ReuseLibrary)element).setComment(comment); return true; } return IReuseProviderService.getInstance().setReuseElementComment(element, comment); @@ -213,12 +244,13 @@ public class ReuseLibraryUtilsBasics { * {@link ReuseElementSpec}s and thus multiple UUIDs, because they could have * been added to several {@link ReuseLibrary}s. * - * @param element The target reuse element + * @param element + * The target reuse element * @return The requested UUID as string (or empty string) */ public static String getFirstReuseElementUUID(EObject element) { List<String> allUUIDs = getAllReuseElementUUID(element); - if (allUUIDs != null && !allUUIDs.isEmpty()) { + if(allUUIDs != null && !allUUIDs.isEmpty()) { // get(0) is safe due to check above return allUUIDs.get(0); } @@ -233,19 +265,18 @@ public class ReuseLibraryUtilsBasics { * {@link ReuseElementSpec}s and thus multiple UUIDs, because they could have * been added to several {@link ReuseLibrary}s. * - * @param element The target reuse element + * @param element + * The target reuse element * @return The requested UUID as string (or empty string) */ public static List<String> getAllReuseElementUUID(EObject element) { List<String> allUUIDs = new ArrayList<>(); - if (element instanceof ReuseLibrary) { - allUUIDs.add(((ReuseLibrary) element).getLibraryUUID()); + if(element instanceof ReuseLibrary) { + allUUIDs.add(((ReuseLibrary)element).getLibraryUUID()); } else { - if (element instanceof IModelElement) { - List<ReuseElementSpec> specs = getAllReuseSpecs((IModelElement) element); - for (ReuseElementSpec spec : specs) { - allUUIDs.add(spec.getElementUUID()); - } + List<ReuseElementSpec> specs = getAllReuseSpecs(element); + for(ReuseElementSpec spec : specs) { + allUUIDs.add(spec.getElementUUID()); } } return allUUIDs; @@ -257,18 +288,18 @@ public class ReuseLibraryUtilsBasics { * {@link ReuseLibrary}. If such a {@link ReuseElementSpec} does not exist, an * empty {@link String} will be returned. * - * @param element The target reuse element - * @param library The reuse library to which the reuse UUID of the element - * should belong + * @param element + * The target reuse element + * @param library + * The reuse library to which the reuse UUID of the element + * should belong * @return The requested UUID as string (or empty string) */ public static String getReuseElementUUIDForLibrary(EObject element, ReuseLibrary library) { - if (element instanceof IModelElement) { - List<ReuseElementSpec> specs = getAllReuseSpecs((IModelElement) element); - for (ReuseElementSpec spec : specs) { - if (spec.getSourceLibUUID().equals(library.getLibraryUUID())) { - return spec.getElementUUID(); - } + List<ReuseElementSpec> specs = getAllReuseSpecs(element); + for(ReuseElementSpec spec : specs) { + if(spec.getSourceLibUUID().equals(library.getLibraryUUID())) { + return spec.getElementUUID(); } } return ""; @@ -279,19 +310,20 @@ public class ReuseLibraryUtilsBasics { * a specific (given) {@link ReuseLibrary}. If it cannot be found, an empty * {@link String} will be returned. * - * @param element The target reuse element - * @param sourceLibrary The library of the original reuse element for the hash + * @param element + * The target reuse element + * @param sourceLibrary + * The library of the original reuse element for the hash * @return The requested hash code as string (or empty string) */ - public static String getReuseElementHashForLibrary(EObject element, ReuseLibrary sourceLibrary) { + public static String getReuseElementHashForLibrary(EObject element, + ReuseLibrary sourceLibrary) { String libraryUuid = sourceLibrary.getLibraryUUID(); - if (element instanceof IModelElement) { - List<ReuseElementSpec> specs = getAllReuseSpecs((IModelElement) element); - for (ReuseElementSpec spec : specs) { - String referenceLibraryUuid = spec.getSourceLibUUID(); - if (referenceLibraryUuid.equals(libraryUuid)) { - return spec.getElementHash(); - } + List<ReuseElementSpec> specs = getAllReuseSpecs(element); + for(ReuseElementSpec spec : specs) { + String referenceLibraryUuid = spec.getSourceLibUUID(); + if(referenceLibraryUuid.equals(libraryUuid)) { + return spec.getElementHash(); } } return ""; @@ -302,16 +334,15 @@ public class ReuseLibraryUtilsBasics { * {@link ZonedDateTime} as long as it has (already) a {@link ReuseElementSpec}. * If this is not the case, null will be returned. * - * @param element The target reuse element + * @param element + * The target reuse element * @return The requested (update) date (or null) */ public static ZonedDateTime getReuseElementLastUpdate(EObject element) { - if (element instanceof IModelElement) { - List<ReuseElementSpec> specs = getAllReuseSpecs((IModelElement) element); - if (specs != null && !specs.isEmpty()) { - // get(0) is safe due to check above - return specs.get(0).getLastUpdate(); - } + List<ReuseElementSpec> specs = getAllReuseSpecs(element); + if(specs != null && !specs.isEmpty()) { + // get(0) is safe due to check above + return specs.get(0).getLastUpdate(); } return null; } @@ -321,9 +352,11 @@ public class ReuseLibraryUtilsBasics { * {@link String} as long as it has (already) a {@link ReuseElementSpec}. If * this is not the case, an empty {@link String} will be returned. * - * @param element The target reuse element - * @param forDisplay If it should be the format for user display or the one that - * is internally used + * @param element + * The target reuse element + * @param forDisplay + * If it should be the format for user display or the one that + * is internally used * @return The requested (update) date as string (or empty string) */ public static String getReuseElementLastUpdateString(EObject element, boolean forDisplay) { @@ -335,18 +368,19 @@ public class ReuseLibraryUtilsBasics { * Returns the given {@link ZonedDateTime} as formatted {@link String} as long * as it is valid, otherwise an empty {@link String} will be returned. * - * @param date The date - * @param forDisplay If it should be the format for user display or the one that - * is internally used + * @param date + * The date + * @param forDisplay + * If it should be the format for user display or the one that + * is internally used * @return The requested date as string (or empty string) */ public static String getDateAsString(ZonedDateTime date, boolean forDisplay) { - if (date != null) { - if (forDisplay) { + if(date != null) { + if(forDisplay) { return DISPLAY_REUSE_DATE_FORMATTER.format(date); - } else { - return INTERNAL_REUSE_DATE_FORMATTER.format(date); } + return INTERNAL_REUSE_DATE_FORMATTER.format(date); } return ""; } @@ -355,14 +389,14 @@ public class ReuseLibraryUtilsBasics { * Sets the Last Update Date of the given reuse element with the given {link * Date} as long as it has (already) a {@link ReuseElementSpec}. * - * @param element The target reuse element - * @param newDate The new (update) date + * @param element + * The target reuse element + * @param newDate + * The new (update) date */ public static void setReuseElementLastUpdate(EObject element, ZonedDateTime newDate) { - if (element instanceof IModelElement) { - for (ReuseElementSpec spec : getAllReuseSpecs((IModelElement) element)) { - spec.setLastUpdate(newDate); - } + for(ReuseElementSpec spec : getAllReuseSpecs(element)) { + spec.setLastUpdate(newDate); } } @@ -370,7 +404,8 @@ public class ReuseLibraryUtilsBasics { * Sets the Last Update Date of the given reuse element with the current {link * ZonedDateTime} as long as it has (already) a {@link ReuseElementSpec}. * - * @param element The target reuse element + * @param element + * The target reuse element */ public static void setReuseElementLastUpdateNow(EObject element) { setReuseElementLastUpdate(element, ZonedDateTime.now()); @@ -380,32 +415,49 @@ public class ReuseLibraryUtilsBasics { * Returns all {@link ReuseElementSpec}s of the given element to a * {@link ReuseLibrary}. If none exist, an empty list will be returned. * - * @param element The target reuse element + * @param element + * The target reuse element * @return A list of all found reuse specifications (or empty list) */ - public static List<ReuseElementSpec> getAllReuseSpecs(IModelElement element) { + public static List<ReuseElementSpec> getAllReuseSpecs(EObject element) { List<ReuseElementSpec> specs = new ArrayList<>(); - for (IModelElementSpecification spec : element.getSpecifications()) { - if (spec instanceof ReuseElementSpec) { - // (cast is safe due to instance check) - specs.add((ReuseElementSpec) spec); + if(element instanceof IModelElement) { + for(IModelElementSpecification spec : ((IModelElement)element).getSpecifications()) { + if(spec instanceof ReuseElementSpec) { + // (cast is safe due to instance check) + specs.add((ReuseElementSpec)spec); + } } } return specs; } + /** + * Returns the first {@link ReuseElementSpec} of the given element to a + * {@link ReuseLibrary}. If none exist, null will be returned. + * + * @param element + * The target reuse element + * @return The first reuse element specification (or null) + */ + public static ReuseElementSpec getFirstReuseSpec(EObject element) { + List<ReuseElementSpec> specs = getAllReuseSpecs(element); + if(!specs.isEmpty()) { + // get(0) safe due to empty check above + return specs.get(0); + } + return null; + } + /** * Returns the number of all {@link ReuseElementSpec}s of the given element. * - * @param element The target reuse element + * @param element + * The target reuse element * @return Number of all found reuse specifications */ public static int getNumberOfContainedReuseSpecs(EObject element) { - if (element instanceof IModelElement) { - return getAllReuseSpecs((IModelElement) element).size(); - } else { - return 0; - } + return getAllReuseSpecs(element).size(); } /** @@ -413,24 +465,26 @@ public class ReuseLibraryUtilsBasics { * that is linked with the given reuse element inside a library. If none could * be found, null will be returned. * - * @param projectElement The reuse element inside a project from which the reuse - * specification should be selected - * @param libraryElement The reuse element inside a library + * @param projectElement + * The reuse element inside a project from which the reuse + * specification should be selected + * @param libraryElement + * The reuse element inside a library * @return The found/matched reuse specification (or null) */ - public static ReuseElementSpec getReuseSpecLinkedToThisLibraryElement(IModelElement projectElement, - IModelElement libraryElement) { + public static ReuseElementSpec getReuseSpecLinkedToThisLibraryElement( + IModelElement projectElement, IModelElement libraryElement) { List<ReuseElementSpec> projectSpecs = getAllReuseSpecs(projectElement); List<ReuseElementSpec> librarySpecs = getAllReuseSpecs(libraryElement); // elements in library must have only a single specification - if (librarySpecs.size() == 1) { + if(librarySpecs.size() == 1) { // get(0) is safe due to size check above ReuseElementSpec librarySpec = librarySpecs.get(0); - for (ReuseElementSpec specToBeChecked : projectSpecs) { + for(ReuseElementSpec specToBeChecked : projectSpecs) { // both UUIDs (of element and library) must be identical - if (specToBeChecked.getSourceLibUUID().equals(librarySpec.getSourceLibUUID()) - && specToBeChecked.getElementUUID().equals(librarySpec.getElementUUID())) { + if(specToBeChecked.getSourceLibUUID().equals(librarySpec.getSourceLibUUID()) && + specToBeChecked.getElementUUID().equals(librarySpec.getElementUUID())) { return specToBeChecked; } } @@ -457,12 +511,13 @@ public class ReuseLibraryUtilsBasics { * or file name is not correct (as long as it is in the reuse directory and has * the right UUID)! * - * @param libraryUUID The UUID of the requested reuse library + * @param libraryUUID + * The UUID of the requested reuse library * @return The requested reuse library (or null) */ public static ReuseLibrary getLocalReuseLibraryByID(String libraryUUID) { - for (ReuseLibrary library : getAllLocalReuseLibraries()) { - if (libraryUUID.equals(library.getLibraryUUID())) { + for(ReuseLibrary library : getAllLocalReuseLibraries()) { + if(libraryUUID.equals(library.getLibraryUUID())) { return library; } } @@ -477,17 +532,15 @@ public class ReuseLibraryUtilsBasics { * because it does not fetch all libraries - only the one of the first {link * ReuseElementSpec}. * - * @param element The target reuse element + * @param element + * The target reuse element * @return The requested reuse library (or null) */ public static ReuseLibrary getFirstSourceLibraryOfElement(EObject element) { - if (element instanceof IModelElement) { - List<ReuseElementSpec> specList = getAllReuseSpecs((IModelElement) element); - if (specList != null && !specList.isEmpty()) { - // get(0) is safe due to check above - String libraryUUID = specList.get(0).getSourceLibUUID(); - return getLocalReuseLibraryByID(libraryUUID); - } + ReuseElementSpec spec = getFirstReuseSpec(element); + if(spec != null) { + String libraryUUID = spec.getSourceLibUUID(); + return getLocalReuseLibraryByID(libraryUUID); } return null; } @@ -497,19 +550,18 @@ public class ReuseLibraryUtilsBasics { * library in the {link ReuseElementSpec}s of the given reuse element. If no * {link ReuseElementSpec} exists, the return will be an empty list. * - * @param element The target reuse element + * @param element + * The target reuse element * @return All found reuse libraries for the given element (or empty list) */ public static List<ReuseLibrary> getAllSourceLibrariesOfElement(EObject element) { List<ReuseLibrary> foundLibraries = new ArrayList<>(); - if (element instanceof IModelElement) { - List<ReuseElementSpec> reuseSpecs = getAllReuseSpecs((IModelElement) element); - for (ReuseElementSpec reuseSpec : reuseSpecs) { - String libraryUUID = reuseSpec.getSourceLibUUID(); - ReuseLibrary sourceLibrary = getLocalReuseLibraryByID(libraryUUID); - if (sourceLibrary != null) { - foundLibraries.add(sourceLibrary); - } + List<ReuseElementSpec> reuseSpecs = getAllReuseSpecs(element); + for(ReuseElementSpec reuseSpec : reuseSpecs) { + String libraryUUID = reuseSpec.getSourceLibUUID(); + ReuseLibrary sourceLibrary = getLocalReuseLibraryByID(libraryUUID); + if(sourceLibrary != null) { + foundLibraries.add(sourceLibrary); } } return foundLibraries; @@ -520,16 +572,19 @@ public class ReuseLibraryUtilsBasics { * referenced by the given {@link ReuseElementSpec}. Returns null if it could * not be found. * - * @param library The target reuse library - * @param elementUUID The UUID string of the requested element + * @param library + * The target reuse library + * @param elementUUID + * The UUID string of the requested element * @return The requested reuse element (or null) */ public static EObject getElementInsideLibrary(ReuseLibrary library, String elementUUID) { // find original element inside the library by identical UUID - for (EObject libraryElement : library.getReuseElementList()) { - for (IModelElementSpecification spec : ((IModelElement) libraryElement).getSpecifications()) { - if (spec instanceof ReuseElementSpec) { - if (((ReuseElementSpec) spec).getElementUUID().equals(elementUUID)) { + for(EObject libraryElement : library.getReuseElementList()) { + for(IModelElementSpecification spec : ((IModelElement)libraryElement) + .getSpecifications()) { + if(spec instanceof ReuseElementSpec) { + if(((ReuseElementSpec)spec).getElementUUID().equals(elementUUID)) { return libraryElement; } } @@ -543,14 +598,15 @@ public class ReuseLibraryUtilsBasics { * (e.g. an external stored function inside a code specification of a * component). If nothing was found, an empty list is returned. * - * @param element The target reuse element + * @param element + * The target reuse element * @return A list of external elements referencing the target reuse element (or * empty list) */ public static List<EObject> getExternalReferencesOfElement(EObject element) { List<EObject> references = new ArrayList<>(); - for (Class<? extends EObject> referenceClass : getPossibleExternalReferenceClasses()) { - for (EObject reference : getChildrenWithType(element, referenceClass)) { + for(Class<? extends EObject> referenceClass : getPossibleExternalReferenceClasses()) { + for(EObject reference : getChildrenWithType(element, referenceClass)) { references.add(reference); } } @@ -565,8 +621,9 @@ public class ReuseLibraryUtilsBasics { * {@link EObject} was reused based on the origin (i.e., the hash codes are * identical), an empty list will be returned. * - * @param element The element whose reuse origin(s) should be checked for - * updates + * @param element + * The element whose reuse origin(s) should be checked for + * updates * @return List of elements that are reuse origins and were updated in the * meantime */ @@ -575,14 +632,15 @@ public class ReuseLibraryUtilsBasics { List<ReuseLibrary> foundLibraries = getAllSourceLibrariesOfElement(element); - for (ReuseLibrary sourceLibrary : foundLibraries) { + for(ReuseLibrary sourceLibrary : foundLibraries) { String uuid = getReuseElementUUIDForLibrary(element, sourceLibrary); EObject originElementInLib = getElementInsideLibrary(sourceLibrary, uuid); String storedHashForThisLibrary = getReuseElementHashForLibrary(element, sourceLibrary); - String currentHashForThisLibrary = getReuseElementHashForLibrary(originElementInLib, sourceLibrary); + String currentHashForThisLibrary = + getReuseElementHashForLibrary(originElementInLib, sourceLibrary); // if hashes are valid but different, the origin was updated - if (!storedHashForThisLibrary.isEmpty() && !currentHashForThisLibrary.isEmpty()) { - if (!storedHashForThisLibrary.equals(currentHashForThisLibrary)) { + if(!storedHashForThisLibrary.isEmpty() && !currentHashForThisLibrary.isEmpty()) { + if(!storedHashForThisLibrary.equals(currentHashForThisLibrary)) { updatedOrigins.add(originElementInLib); } } diff --git a/org.fortiss.tooling.kernel/src/org/fortiss/tooling/kernel/extension/base/.ratings b/org.fortiss.tooling.kernel/src/org/fortiss/tooling/kernel/extension/base/.ratings index b3f3a1694d6e5ae7cb895ac9185a532103244b4f..4c516a457060838c77cac4fd4603810155745ba2 100644 --- a/org.fortiss.tooling.kernel/src/org/fortiss/tooling/kernel/extension/base/.ratings +++ b/org.fortiss.tooling.kernel/src/org/fortiss/tooling/kernel/extension/base/.ratings @@ -3,6 +3,6 @@ ConstraintViolationBase.java ec66973ab2183623f0cd4a85c59c886dddad6cf6 GREEN DialogMessage.java 8420640e999e4fb15fa644333e5d71e1d16c2559 GREEN ElementCompositorBase.java 7a445e5adde11878fe0515baca8b915287149b28 GREEN MultiViolationConstraintCheckerBase.java 30886a94c99cf8948f64401b1db821abe06e1e6c GREEN -PrototypeProviderBase.java 4625d5ed40d3bcadfc6dda3ed4cc1f3873a23307 GREEN +PrototypeProviderBase.java 7418c494275bf75318504de65e82035535b9e9d8 GREEN TransformationContextChainBase.java 1ef37880ab275778c563928e80ba378fec964cb6 GREEN TransformationProviderBase.java 9e91100cc1f2c8fbd8d41af55aedfea34e02ff71 GREEN diff --git a/org.fortiss.tooling.kernel/src/org/fortiss/tooling/kernel/extension/base/PrototypeProviderBase.java b/org.fortiss.tooling.kernel/src/org/fortiss/tooling/kernel/extension/base/PrototypeProviderBase.java index 4625d5ed40d3bcadfc6dda3ed4cc1f3873a23307..7418c494275bf75318504de65e82035535b9e9d8 100644 --- a/org.fortiss.tooling.kernel/src/org/fortiss/tooling/kernel/extension/base/PrototypeProviderBase.java +++ b/org.fortiss.tooling.kernel/src/org/fortiss/tooling/kernel/extension/base/PrototypeProviderBase.java @@ -21,6 +21,7 @@ import java.util.ArrayList; import java.util.HashMap; import java.util.List; import java.util.Map; +import java.util.OptionalInt; import org.eclipse.emf.ecore.EObject; import org.fortiss.tooling.kernel.extension.IPrototypeProvider; @@ -65,9 +66,13 @@ public abstract class PrototypeProviderBase implements IPrototypeProvider { /** Registers the given {@link EObject} with the given name and category. */ protected final void registerPrototype(String name, EObject prototype, String categoryName) { - Prototype prototypeObject = new Prototype(name, prototype, false); - prototypes.add(prototypeObject); - registerElementInCategory(prototypeObject, categoryName); + registerPrototype(name, prototype, categoryName, false, OptionalInt.empty()); + } + + /** Registers the given {@link EObject} with the given name, category, and priority. */ + protected final void registerPrototype(String name, EObject prototype, String categoryName, + int priority) { + registerPrototype(name, prototype, categoryName, false, OptionalInt.of(priority)); } /** @@ -76,7 +81,27 @@ public abstract class PrototypeProviderBase implements IPrototypeProvider { */ protected final void registerPrimaryPrototype(String name, EObject prototype, String categoryName) { - Prototype prototypeObject = new Prototype(name, prototype, true); + registerPrototype(name, prototype, categoryName, true, OptionalInt.empty()); + } + + /** + * Registers the given {@link EObject} with the given name and priority as primary prototype + * with the given category. + */ + protected final void registerPrimaryPrototype(String name, EObject prototype, + String categoryName, int priority) { + registerPrototype(name, prototype, categoryName, true, OptionalInt.of(priority)); + } + + /** Base method that actually performs the registration of prototypes. */ + private final void registerPrototype(String name, EObject prototype, String categoryName, + boolean primary, OptionalInt priority) { + Prototype prototypeObject; + if(priority.isPresent()) { + prototypeObject = new Prototype(name, prototype, primary, priority.getAsInt()); + } else { + prototypeObject = new Prototype(name, prototype, primary); + } prototypes.add(prototypeObject); registerElementInCategory(prototypeObject, categoryName); } diff --git a/org.fortiss.tooling.kernel/src/org/fortiss/tooling/kernel/extension/data/.ratings b/org.fortiss.tooling.kernel/src/org/fortiss/tooling/kernel/extension/data/.ratings index 767ea0d3844cf1d402af91edace47cdb84a79b5d..d4ee8f44ffc955a01def9b5a7917ee4502ad6103 100644 --- a/org.fortiss.tooling.kernel/src/org/fortiss/tooling/kernel/extension/data/.ratings +++ b/org.fortiss.tooling.kernel/src/org/fortiss/tooling/kernel/extension/data/.ratings @@ -7,7 +7,7 @@ ITransformationContext.java f00a0ab19a410c3ae2fc6256483aeb4207a86395 GREEN LogMessage.java 14204ed9d51b356f50be52362247cfbbe0cbd5c7 GREEN ModelElementTransformationContext.java 5a41bd3a75ce434c3174d50d2fdfab28b66f09f2 GREEN ModelStorageError.java 2aef480044047e960e64811111a7f27310011cc2 GREEN -Prototype.java 5b91ecc45950569a19371470d0e3ae44cca86cf3 GREEN +Prototype.java f4b13f86b7511edacc138053ffb80cecbac70868 GREEN PrototypeCategory.java ca500b4816ed42b9536488669aeab89561d2f08c GREEN TransformationProviderChain.java 67ec6d0b4c23d295323572649606d79f3b897437 GREEN TutorialAtomicStep.java 09c0d6597d542b431b5bbdc790ee9e533d9f77fb GREEN diff --git a/org.fortiss.tooling.kernel/src/org/fortiss/tooling/kernel/extension/data/Prototype.java b/org.fortiss.tooling.kernel/src/org/fortiss/tooling/kernel/extension/data/Prototype.java index 5b91ecc45950569a19371470d0e3ae44cca86cf3..f4b13f86b7511edacc138053ffb80cecbac70868 100644 --- a/org.fortiss.tooling.kernel/src/org/fortiss/tooling/kernel/extension/data/Prototype.java +++ b/org.fortiss.tooling.kernel/src/org/fortiss/tooling/kernel/extension/data/Prototype.java @@ -1,5 +1,5 @@ /*-------------------------------------------------------------------------+ -| Copyright 2011 fortiss GmbH | +| Copyright 2023 fortiss GmbH | | | | Licensed under the Apache License, Version 2.0 (the "License"); | | you may not use this file except in compliance with the License. | @@ -35,36 +35,53 @@ public class Prototype { /** Flag for primary class prototypes. */ private final boolean isPrimary; + /** Stores the priority of the category. Is important for sorting: lower value = lower prio. */ + private final int prototypePriority; + /** Constructor. */ public Prototype(String name, EObject prototype, boolean isPrimary) { this.name = name; this.prototype = prototype; this.isPrimary = isPrimary; + this.prototypePriority = 0; + } + + /** Constructor with priority. */ + public Prototype(String name, EObject prototype, boolean isPrimary, int priority) { + this.name = name; + this.prototype = prototype; + this.isPrimary = isPrimary; + this.prototypePriority = priority; } /** Returns the {@link Prototype}'s name. */ public String getName() { - return name; + return this.name; } /** Returns the {@link Prototype} instance (NOT a copy!). */ public EObject getPrototype() { - return prototype; + return this.prototype; } /** Returns a copy of the {@link Prototype}. This method is potentially expensive. */ public EObject getPrototypeCopy() { - return copy(prototype); + return copy(this.prototype); + } + + /** Returns the priority of the prototype. */ + public int getPriority() { + return this.prototypePriority; } /** {@inheritDoc} */ @Override public String toString() { - return "Prototype for: " + name; + return "Prototype for: " + this.name; } /** Returns whether this {@link Prototype} is a primary one or not. */ public boolean isPrimary() { - return isPrimary; + return this.isPrimary; } }