From b0baeb30e881308e671765e1b3eee8ad0a48ca58 Mon Sep 17 00:00:00 2001 From: dlamoris Date: Tue, 12 Sep 2023 17:48:17 -0700 Subject: [PATCH 01/19] Update README.md removed outdated badges --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index ad8c2d090..53ff70cf6 100644 --- a/README.md +++ b/README.md @@ -1,6 +1,6 @@ # Cameo Model Development Kit (MDK) -[![GitHub release (latest SemVer)](https://img.shields.io/github/v/release/Open-MBEE/mdk?label=download)](https://github.com/Open-MBEE/mdk/releases/latest) [![Maven Central](https://img.shields.io/maven-central/v/org.openmbee.mdk.magic/mdk)](https://search.maven.org/artifact/org.openmbee.mdk.magic/mdk) [![Jira](https://img.shields.io/badge/issues-jira-blue)](https://openmbee.atlassian.net/browse/MDK) [![CircleCI](https://circleci.com/gh/Open-MBEE/mdk.svg?style=shield)](https://circleci.com/gh/Open-MBEE/mdk) [![Language grade: Java](https://img.shields.io/lgtm/grade/java/g/Open-MBEE/mdk.svg?logo=lgtm&logoWidth=18)](https://lgtm.com/projects/g/Open-MBEE/mdk/context:java) +[![GitHub release (latest SemVer)](https://img.shields.io/github/v/release/Open-MBEE/mdk?label=download)](https://github.com/Open-MBEE/mdk/releases/latest) [![Maven Central](https://img.shields.io/maven-central/v/org.openmbee.mdk.magic/mdk)](https://search.maven.org/artifact/org.openmbee.mdk.magic/mdk) [![CircleCI](https://circleci.com/gh/Open-MBEE/mdk.svg?style=shield)](https://circleci.com/gh/Open-MBEE/mdk) Cameo MDK is a plugin for [Cameo Systems Modeler](https://www.nomagic.com/products/cameo-systems-modeler) and other No Magic environment bundles that’s primary purposes are to sync models with the [MMS](https://github.com/Open-MBEE/mms-alfresco) and implement the [DocGen](src/main/dist/manual) language, which allows modelers to dynamically generate documents in a model-based approach using the view and viewpoint concept. From 3c859b3f3bbea4bf4ca53ef7d90535c5b4c0d598 Mon Sep 17 00:00:00 2001 From: dlamoris Date: Tue, 12 Sep 2023 17:51:33 -0700 Subject: [PATCH 02/19] Update README.md --- README.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index 53ff70cf6..84b97a11a 100644 --- a/README.md +++ b/README.md @@ -12,8 +12,8 @@ The latest user documentation can be accessed online: https://mdk.readthedocs.io ## Prerequisites -* [Cameo Systems Modeler (CSM)](https://www.nomagic.com/products/cameo-systems-modeler) or another No Magic environment bundle that includes the [SysML plugin](https://www.nomagic.com/product-addons/magicdraw-addons/sysml-plugin) - * The latest Cameo MDK is compatible with **19.0 SP3** and **19.0 SP4**. Compatibility for previous versions of Cameo MDK can be found in the [compatibility matrices](https://github.com/Open-MBEE/open-mbee.github.io/wiki/Compatibilities). +* [Cameo Systems Modeler (CSM)](https://www.nomagic.com/products/cameo-systems-modeler) or another No Magic environment bundle that includes the [SysML plugin](https://www.nomagic.com/product-addons/magicdraw-addons/sysml-plugin) (Only CSM has been tested) + * The latest Cameo MDK is compatible with **2022x Refresh1**. Compatibility for previous versions of Cameo MDK can be found in the [compatibility matrices](https://github.com/Open-MBEE/open-mbee.github.io/wiki/Compatibilities). * [Model Management System (MMS)](https://www.openmbee.org/projects.html#mms) * The Cameo MDK (5.0+) is compatible with MMS **4.x**. Compatibility for previous version of Cameo MDK can be found in the [compatibility matrices](https://github.com/Open-MBEE/open-mbee.github.io/wiki/Compatibilities). From 332ea4699a7f7801a496b9dcfb4b8c08d74c2ba0 Mon Sep 17 00:00:00 2001 From: sebastianvranovsky Date: Thu, 19 Oct 2023 09:44:23 +0200 Subject: [PATCH 03/19] MDK Export --- .../org/openmbee/mdk/MDKConfigurator.java | 33 ++ .../ExportToJsonRecursivelyAction.java | 91 ++++ .../mdk/api/incubating/MDKConstants.java | 5 + .../java/org/openmbee/mdk/emf/BulkExport.java | 48 ++ .../mdk/fileexport/ContextExportLevel.java | 30 ++ .../fileexport/ElementContextProvider.java | 316 ++++++++++++ .../mdk/fileexport/FileExportRunner.java | 465 ++++++++++++++++++ .../options/EnvironmentOptionsResources.java | 24 + .../openmbee/mdk/options/MDKOptionsGroup.java | 186 +++++++ .../mdk/options/MDKProjectOptionsGroup.java | 99 ++++ .../mdk/options/ProjectOptionsResources.java | 24 + .../org/openmbee/mdk/util/MdkExportUtils.java | 37 ++ 12 files changed, 1358 insertions(+) create mode 100644 src/main/java/org/openmbee/mdk/actions/ExportToJsonRecursivelyAction.java create mode 100644 src/main/java/org/openmbee/mdk/emf/BulkExport.java create mode 100644 src/main/java/org/openmbee/mdk/fileexport/ContextExportLevel.java create mode 100644 src/main/java/org/openmbee/mdk/fileexport/ElementContextProvider.java create mode 100644 src/main/java/org/openmbee/mdk/fileexport/FileExportRunner.java create mode 100644 src/main/java/org/openmbee/mdk/options/EnvironmentOptionsResources.java create mode 100644 src/main/java/org/openmbee/mdk/options/MDKOptionsGroup.java create mode 100644 src/main/java/org/openmbee/mdk/options/MDKProjectOptionsGroup.java create mode 100644 src/main/java/org/openmbee/mdk/options/ProjectOptionsResources.java create mode 100644 src/main/java/org/openmbee/mdk/util/MdkExportUtils.java diff --git a/src/main/java/org/openmbee/mdk/MDKConfigurator.java b/src/main/java/org/openmbee/mdk/MDKConfigurator.java index ac5fd0f12..0b350102e 100644 --- a/src/main/java/org/openmbee/mdk/MDKConfigurator.java +++ b/src/main/java/org/openmbee/mdk/MDKConfigurator.java @@ -17,6 +17,7 @@ import com.nomagic.uml2.ext.magicdraw.classes.mdkernel.Element; import com.nomagic.uml2.ext.magicdraw.classes.mdkernel.NamedElement; import com.nomagic.uml2.ext.magicdraw.mdprofiles.Stereotype; +import org.openmbee.mdk.actions.ExportToJsonRecursivelyAction; import org.openmbee.mdk.docgen.actions.ValidateAllViewsAction; import org.openmbee.mdk.docgen.actions.ValidateViewAction; import org.openmbee.mdk.docgen.actions.PreviewDocumentAction; @@ -120,6 +121,30 @@ private void addElementActions(ActionsManager manager, Element e, List Stereotype sysmlviewpoint = sysml.viewpoint().getStereotype(); Stereotype elementGroupStereotype = sysml.elementGroup().getStereotype(); + { + ActionsCategory exportCategory = myCategory(manager, "MDK_JSON_Serialization", "MDK JSON Export"); + + if (es != null) { + ExportToJsonRecursivelyAction elementOnly = ExportToJsonRecursivelyAction.exportElementOnly(es); + if (manager.getActionFor(elementOnly.getID()) == null) { + exportCategory.addAction(elementOnly); + } + ExportToJsonRecursivelyAction exportElementHierarchy = ExportToJsonRecursivelyAction.exportElementHierarchy(es); + if (manager.getActionFor(exportElementHierarchy.getID()) == null) { + exportCategory.addAction(exportElementHierarchy); + } + } else if (e != null) { + ExportToJsonRecursivelyAction elementOnly = ExportToJsonRecursivelyAction.exportElementOnly(e); + if (manager.getActionFor(elementOnly.getID()) == null) { + exportCategory.addAction(elementOnly); + } + ExportToJsonRecursivelyAction exportElementHierarchy = ExportToJsonRecursivelyAction.exportElementHierarchy(e); + if (manager.getActionFor(exportElementHierarchy.getID()) == null) { + exportCategory.addAction(exportElementHierarchy); + } + } + } + ActionsCategory modelLoad = myCategory(manager, "MMSContext", "MMS"); if (!TicketUtils.isTicketSet(project)) { ActionsCategory login = getCategory(manager, "LoginOption", "LoginOption", modelLoad); @@ -361,5 +386,13 @@ public void configure(ActionsManager manager) { migrateCategory.setNested(true); category.addAction(migrateCategory); migrateCategory.addAction(new GroupsMigrationAction()); + + { + MDActionsCategory exportCategory = new MDActionsCategory(MDKConfigurator.class.getSimpleName() + "-Serialization", "MDK JSON"); + exportCategory.setNested(true); + category.addAction(exportCategory); + + exportCategory.addAction(ExportToJsonRecursivelyAction.exportEntirePrimaryModel()); + } } } diff --git a/src/main/java/org/openmbee/mdk/actions/ExportToJsonRecursivelyAction.java b/src/main/java/org/openmbee/mdk/actions/ExportToJsonRecursivelyAction.java new file mode 100644 index 000000000..2e715c2f0 --- /dev/null +++ b/src/main/java/org/openmbee/mdk/actions/ExportToJsonRecursivelyAction.java @@ -0,0 +1,91 @@ +package org.openmbee.mdk.actions; + +import com.nomagic.magicdraw.actions.MDAction; +import com.nomagic.magicdraw.core.Application; +import com.nomagic.magicdraw.core.Project; +import com.nomagic.ui.ProgressStatusRunner; +import com.nomagic.uml2.ext.magicdraw.classes.mdkernel.Element; +import org.openmbee.mdk.util.MdkExportUtils; +import org.openmbee.mdk.emf.BulkExport; +import org.openmbee.mdk.fileexport.FileExportRunner; +import org.openmbee.mdk.fileexport.FileExportRunner.FileFormat; + +import java.awt.event.ActionEvent; +import java.io.File; +import java.util.Collection; +import java.util.Collections; +import java.util.function.Function; + +public class ExportToJsonRecursivelyAction extends MDAction { + + public static ExportToJsonRecursivelyAction exportEntirePrimaryModel() { + return new ExportToJsonRecursivelyAction(p -> Collections.singleton(p.getPrimaryModel()), BulkExport.DEPTH_INFINITE, FileExportRunner.FileFormat.MODEL, "Export entire (primary) model to .mdkmodel file"); + } + + public static ExportToJsonRecursivelyAction exportElementOnly(Element e) { + return new ExportToJsonRecursivelyAction(p -> Collections.singleton(e), BulkExport.DEPTH_NO_DESCENT, FileFormat.FRAGMENT, "Export element (without contained elements) to .mdkfragment file"); + } + public static ExportToJsonRecursivelyAction exportElementHierarchy(Element e) { + return new ExportToJsonRecursivelyAction(p -> Collections.singleton(e), BulkExport.DEPTH_INFINITE, FileFormat.TREE, "Export containment subtree to .mdktree file"); + } + + public static ExportToJsonRecursivelyAction exportElementOnly(Collection es) { + return new ExportToJsonRecursivelyAction(p -> es, BulkExport.DEPTH_NO_DESCENT, FileFormat.FRAGMENT, "Export selected elements (without contained elements) to .mdkfragment file"); + } + public static ExportToJsonRecursivelyAction exportElementHierarchy(Collection es) { + return new ExportToJsonRecursivelyAction(p -> es, BulkExport.DEPTH_INFINITE, FileFormat.TREE, "Export selected containment subtrees to .mdktree file"); + } + + public static final String DEFAULT_ID = "ExportToJsonRecursively"; + + final Function> rootsProvider; + final int depth; + final String title; + private FileFormat format; + + + + /** + * @param selectedRootElements null if entire primary model is to be exported + */ + public ExportToJsonRecursivelyAction(Function> rootsProvider, int depth, FileFormat format, String title) { + super( +// DEFAULT_ID, + String.format("%s_depth%d", + DEFAULT_ID, + // selectedRootElements.stream() + // .map(Element::getID) + // .map(Object::toString) + // .collect(Collectors.joining("_")), + depth + ), + title, null, null + ); + this.rootsProvider = rootsProvider; + this.depth = depth; + this.format = format; + this.title = title; + } + + + @Override + public void actionPerformed(ActionEvent e) { + Project project = Application.getInstance().getProject(); + if (project != null) { + Collection rootElements = rootsProvider.apply(project); + File folderSelection = MdkExportUtils.chooseFolder(project); + if (folderSelection != null) exportIntoFolder(folderSelection, project, rootElements); + } + } + + /** + * @param folderSelection + */ + private void exportIntoFolder(File folderSelection, Project project, Collection rootElements) { + FileExportRunner exportRunner = new FileExportRunner(rootElements, project, depth, format, folderSelection); + ProgressStatusRunner.runWithProgressStatus(exportRunner, title, true, 0); + } + + + +} diff --git a/src/main/java/org/openmbee/mdk/api/incubating/MDKConstants.java b/src/main/java/org/openmbee/mdk/api/incubating/MDKConstants.java index df51b6efd..9e6d07081 100644 --- a/src/main/java/org/openmbee/mdk/api/incubating/MDKConstants.java +++ b/src/main/java/org/openmbee/mdk/api/incubating/MDKConstants.java @@ -21,8 +21,13 @@ public class MDKConstants { TAGGED_VALUE_ID_SEPARATOR = "_asi-slot-", SLOT_VALUE_ID_SEPARATOR = SLOT_ID_SEPARATOR.substring(0, SLOT_ID_SEPARATOR.length() - 1) + "value-", TYPE_KEY = "type", + TYPE_ID_KEY = TYPE_KEY + ID_KEY_SUFFIX, NAME_KEY = "name", + FQN_KEY = "fullyQualifiedName", + LABEL_KEY = "label", ID_KEY = "id", + PROJECT_NAME = "projectName", + PROJECT_ID = "project" + ID_KEY_SUFFIX, PARENT_REF_ID_KEY = "parentRef" + ID_KEY_SUFFIX, OWNER_ID_KEY = UMLPackage.Literals.ELEMENT__OWNER.getName() + ID_KEY_SUFFIX, INSTANCE_ID_KEY = UMLPackage.Literals.INSTANCE_VALUE__INSTANCE.getName() + ID_KEY_SUFFIX, diff --git a/src/main/java/org/openmbee/mdk/emf/BulkExport.java b/src/main/java/org/openmbee/mdk/emf/BulkExport.java new file mode 100644 index 000000000..5040c1798 --- /dev/null +++ b/src/main/java/org/openmbee/mdk/emf/BulkExport.java @@ -0,0 +1,48 @@ +package org.openmbee.mdk.emf; + +import com.fasterxml.jackson.databind.node.ObjectNode; +import com.nomagic.magicdraw.core.Project; +import com.nomagic.uml2.ext.magicdraw.classes.mdkernel.Element; +import com.nomagic.uml2.ext.magicdraw.classes.mdkernel.Package; +import org.openmbee.mdk.api.incubating.convert.Converters; +import org.openmbee.mdk.util.Pair; + +import java.util.stream.Stream; + +/** + * + * Original implementation lifted from ManualSyncRunner::collectClientElementsRecursively() by igomes + * + */ +public class BulkExport { + + public static final int DEPTH_INFINITE = -1; + public static final int DEPTH_NO_DESCENT = 0; + + public static Stream> exportElementsRecursively(Project project, Element element, int depth) { + ObjectNode jsonObject = Converters.getElementToJsonConverter().apply(element, project); + if (jsonObject == null) { + return Stream.empty(); + } + Stream> result = Stream.of( + new Pair<>(element, jsonObject) + ); + if (depth != DEPTH_NO_DESCENT) { + int childDepth = depth - 1; + result = Stream.concat(result, element.getOwnedElement().stream() + .flatMap(elementChild -> exportElementsRecursively(project, elementChild, childDepth)) + ); + } + if (element.equals(project.getPrimaryModel())) { + + final Package primaryModel = project.getPrimaryModel(); + + result = Stream.concat(result, project.getModels().stream() + .filter(attachedModel -> attachedModel != primaryModel) + .flatMap(attachedModel -> exportElementsRecursively(project, attachedModel, DEPTH_NO_DESCENT)) + ); + } + return result; + } + +} diff --git a/src/main/java/org/openmbee/mdk/fileexport/ContextExportLevel.java b/src/main/java/org/openmbee/mdk/fileexport/ContextExportLevel.java new file mode 100644 index 000000000..f6353dd6b --- /dev/null +++ b/src/main/java/org/openmbee/mdk/fileexport/ContextExportLevel.java @@ -0,0 +1,30 @@ +package org.openmbee.mdk.fileexport; + +public enum ContextExportLevel { + None(0), Direct(1), Transitive(2), Containment(3); + + private final int value; + private ContextExportLevel(int value) { + this.value = value; + } + + public int getValue() { + return value; + } + + public boolean isNoneIncluded() { + return getValue() >= None.getValue(); + } + + public boolean isDirectIncluded() { + return getValue() >= Direct.getValue(); + } + + public boolean isTransitiveIncluded() { + return getValue() >= Transitive.getValue(); + } + + public boolean isContainmentIncluded() { + return getValue() >= Containment.getValue(); + } +} diff --git a/src/main/java/org/openmbee/mdk/fileexport/ElementContextProvider.java b/src/main/java/org/openmbee/mdk/fileexport/ElementContextProvider.java new file mode 100644 index 000000000..69cffa2ed --- /dev/null +++ b/src/main/java/org/openmbee/mdk/fileexport/ElementContextProvider.java @@ -0,0 +1,316 @@ +package org.openmbee.mdk.fileexport; + +import com.fasterxml.jackson.databind.node.ArrayNode; +import com.fasterxml.jackson.databind.node.ObjectNode; +import com.fasterxml.jackson.databind.node.TextNode; +import com.nomagic.ci.persistence.IAttachedProject; +import com.nomagic.ci.persistence.IProject; +import com.nomagic.magicdraw.core.ProjectUtilities; +import com.nomagic.magicdraw.sysml.util.SysMLProfile; +import com.nomagic.uml2.ext.jmi.helpers.ModelHelper; +import com.nomagic.uml2.ext.jmi.helpers.StereotypesHelper; +import com.nomagic.uml2.ext.magicdraw.auxiliaryconstructs.mdmodels.Model; +import com.nomagic.uml2.ext.magicdraw.classes.mdkernel.*; +import com.nomagic.uml2.ext.magicdraw.compositestructures.mdinternalstructures.Connector; +import com.nomagic.uml2.ext.magicdraw.metadata.UMLPackage; +import org.openmbee.mdk.api.incubating.MDKConstants; +import org.openmbee.mdk.api.stream.MDKCollectors; +import org.openmbee.mdk.emf.EMFExporter; +import org.openmbee.mdk.json.JacksonUtils; +import org.eclipse.emf.ecore.EStructuralFeature; + +import java.util.Arrays; +import java.util.Collection; +import java.util.HashSet; +import java.util.Set; +import java.util.stream.Stream; + +/** + * @author Armin Zavada + * + * Based on code from EMFExporter by igomes + * + */ +public class ElementContextProvider { + + private final Set exportedElements = new HashSet<>(); + private Set contextElements = null; + private final ContextExportLevel contextExportLevel; + + public ElementContextProvider(ContextExportLevel contextExportLevel) { + this.contextExportLevel = contextExportLevel; + } + + public void registerExportedElement(Element element) { + if (element == null || contextExportLevel == ContextExportLevel.None) { + return; + } + + exportedElements.add(element); + } + + public Stream getAggregatedContextElements() { + if (contextExportLevel == ContextExportLevel.None) { + return Stream.empty(); + } + + if (contextElements == null) { + contextElements = new HashSet<>(); + exportedElements.stream().flatMap(this::getContextElements).forEach(this::processContextElement); + } + + return contextElements.stream().map(this::mapToJson); + } + + private ObjectNode mapToJson(Element element) { + ObjectNode objectNode = JacksonUtils.getObjectMapper().createObjectNode(); + + objectNode.put(MDKConstants.ID_KEY, EMFExporter.getEID(element)); + objectNode.put(MDKConstants.TYPE_KEY, element.eClass().getName()); + objectNode.put(MDKConstants.DOCUMENTATION_KEY, ModelHelper.getComment(element)); + objectNode.put(MDKConstants.LABEL_KEY, element.getHumanName()); + + if (element instanceof NamedElement) { + objectNode.put(MDKConstants.NAME_KEY, ((NamedElement) element).getName()); + objectNode.put(MDKConstants.FQN_KEY, ((NamedElement) element).getQualifiedName()); + } + + if (contextExportLevel.isTransitiveIncluded()) { + if (element instanceof TypedElement) { + objectNode.put(MDKConstants.TYPE_ID_KEY, EMFExporter.getEID(((TypedElement) element).getType())); + } + + ArrayNode applied = StereotypesHelper.getStereotypes(element).stream().map(stereotype -> + TextNode.valueOf(EMFExporter.getEID(stereotype)) + ).collect(MDKCollectors.toArrayNode()); + objectNode.set(MDKConstants.APPLIED_STEREOTYPE_IDS_KEY, applied); + } + + IProject iProject = ProjectUtilities.getProjectFor(element); + + if ( + contextExportLevel.isContainmentIncluded() // include containment information + && element.getOwner() != null // we have an owner + && !exportedElements.contains(element.getOwner()) // our owner is not in the primary model + ) { + // Simply add owner id + objectNode.put(MDKConstants.OWNER_ID_KEY, EMFExporter.getEID(element.getOwner())); + } else { + // Either we omit hierarchy, this is a root object, or owner is inside the primary model + // In either case, we consider this element a root object in context-space + objectNode.put(MDKConstants.PROJECT_NAME, iProject.getName()); + objectNode.put(MDKConstants.PROJECT_ID, iProject.getProjectID()); + } + + return objectNode; + } + + private Stream getContextElements(Element element) { + if (!contextExportLevel.isDirectIncluded()) { + return Stream.empty(); + } + + return Stream.concat( + getElementContext(element), + getFeatureContext(element) + ); + } + + private Stream getElementContext(Element element) { + return Arrays.stream(ElementContextAggregator.values()) + .flatMap(aggregator -> + aggregator.function.apply(element) + ); + } + + private Stream getFeatureContext(Element element) { + return element.eClass().getEAllStructuralFeatures().stream() + .flatMap(feature -> + Arrays.stream( + FeatureContextAggregator.values() + ).filter(aggregator -> + aggregator.predicate.test(element, feature) + ).findFirst().map(aggregator -> + aggregator.function.apply(element, feature) + ).orElse(Stream.empty()) + ); + } + + private Stream getAdditionalContextElements(Element element) { + Stream stream = Stream.empty(); + + if (element instanceof TypedElement) { + stream = Stream.concat(stream, Stream.of(((TypedElement) element).getType())); + } else if (element instanceof Enumeration) { + stream = Stream.concat(stream, ((Enumeration)element).getOwnedLiteral().stream()); + } else if (element instanceof Model) { + stream = Stream.concat(stream, element.getOwnedElement().stream()); + } + if (contextExportLevel.isContainmentIncluded() && element.getOwner() != null) { + stream = Stream.concat(stream, Stream.of(element.getOwner())); + } + + stream = Stream.concat(stream, StereotypesHelper.getStereotypes(element).stream()); + + return stream; + } + + private void processContextElement(Element element) { + if (element == null || exportedElements.contains(element) || isSerializedElement(element)) { + return; + } + + if (contextElements.add(element) && contextExportLevel.isTransitiveIncluded()) { + getAdditionalContextElements(element).forEach(this::processContextElement); + } + } + + private enum ElementContextAggregator { + APPLIED_STEREOTYPE( + (element) -> { + return StereotypesHelper.getStereotypes(element).stream(); + } + ), + MOUNT( + (element) -> { + if (!ProjectUtilities.isAttachedProjectRoot(element)) { + return Stream.empty(); + } + IProject iProject = ProjectUtilities.getProjectFor(element); + if (!(iProject instanceof IAttachedProject)) { + return Stream.empty(); + } + // TODO: get attached project primary model as element + return Stream.empty(); + } + ); + + private final ElementContextFunction function; + + private ElementContextAggregator(ElementContextFunction function) { + this.function = function; + } + + public ElementContextFunction getFunction() { + return function; + } + + } + + private enum FeatureContextAggregator { + ID( + (element, eStructuralFeature) -> eStructuralFeature == element.eClass().getEIDAttribute(), + EMPTY_CONTEXT_FUNCTION + ), + OWNER( + (element, eStructuralFeature) -> UMLPackage.Literals.ELEMENT__OWNER == eStructuralFeature, + EMPTY_CONTEXT_FUNCTION + ), + OWNING( + (element, eStructuralFeature) -> eStructuralFeature.getName().startsWith("owning"), + EMPTY_CONTEXT_FUNCTION + ), + OWNED( + (element, eStructuralFeature) -> eStructuralFeature.getName().startsWith("owned") && !eStructuralFeature.isOrdered(), + EMPTY_CONTEXT_FUNCTION + ), + NESTED( + (element, eStructuralFeature) -> eStructuralFeature.getName().startsWith("nested"), + EMPTY_CONTEXT_FUNCTION + ), + PACKAGED_ELEMENT( + (element, eStructuralFeature) -> UMLPackage.Literals.PACKAGE__PACKAGED_ELEMENT == eStructuralFeature || UMLPackage.Literals.COMPONENT__PACKAGED_ELEMENT == eStructuralFeature, + EMPTY_CONTEXT_FUNCTION + ), + CONNECTOR__END( + (element, eStructuralFeature) -> UMLPackage.Literals.CONNECTOR__END == eStructuralFeature, + (element, eStructuralFeature) -> { + Connector connector = (Connector) element; + Stream nestedEnds = connector.getEnd().stream() + .filter(connectorEnd -> + StereotypesHelper.hasStereotype(connectorEnd, SysMLProfile.NESTEDCONNECTOREND_STEREOTYPE) + ).flatMap(connectorEnd -> + StereotypesHelper.getStereotypePropertyValue(connectorEnd, SysMLProfile.NESTEDCONNECTOREND_STEREOTYPE, SysMLProfile.ELEMENTPROPERTYPATH_PROPERTYPATH_PROPERTY).stream() + ).map(o -> + o instanceof ElementValue ? ((ElementValue) o).getElement() : o + ); + Stream ends = connector.getEnd().stream().map(end -> + end.getRole() + ); + + return Stream.concat(nestedEnds, ends); + } + ), + VALUE_SPECIFICATION__EXPRESSION( + (element, eStructuralFeature) -> eStructuralFeature == UMLPackage.Literals.VALUE_SPECIFICATION__EXPRESSION, + EMPTY_CONTEXT_FUNCTION + ), + UML_CLASS( + (element, eStructuralFeature) -> eStructuralFeature == UMLPackage.Literals.CLASSIFIER__UML_CLASS || eStructuralFeature == UMLPackage.Literals.PROPERTY__UML_CLASS || eStructuralFeature == UMLPackage.Literals.OPERATION__UML_CLASS, + EMPTY_CONTEXT_FUNCTION + ), + GENERIC( + (element, eStructuralFeature) -> true, + (element, eStructuralFeature) -> { + if (!eStructuralFeature.isChangeable() || eStructuralFeature.isVolatile() || eStructuralFeature.isTransient() || eStructuralFeature.isUnsettable() || eStructuralFeature.isDerived() || eStructuralFeature.getName().startsWith("_")) { + return Stream.empty(); + } + return getFlatStructuralFeatureStream(element, eStructuralFeature); + } + ); + + private final FeatureContextFunction function; + private final FeatureContextPredicate predicate; + + private FeatureContextAggregator(FeatureContextPredicate predicate, FeatureContextFunction function) { + this.predicate = predicate; + this.function = function; + } + + public FeatureContextFunction getFunction() { + return function; + } + + public FeatureContextPredicate getPredicate() { + return predicate; + } + + } + + private static final FeatureContextFunction EMPTY_CONTEXT_FUNCTION = (element, eStructuralFeature) -> Stream.empty(); + + private static boolean isSerializedElement(Element element) { + return element instanceof ValueSpecification; + } + + private static Stream getFlatStructuralFeatureStream(Element element, EStructuralFeature eStructuralFeature) { + Object slot = element.eGet(eStructuralFeature); + Stream stream; + + if (slot == null) { + stream = Stream.empty(); + } else if (slot instanceof Collection) { + stream = ((Collection) slot).stream(); + } else { + stream = Stream.of(slot); + } + + return stream.filter(Element.class::isInstance).map(Element.class::cast); + } + + @FunctionalInterface + interface FeatureContextPredicate { + boolean test(Element element, EStructuralFeature structuralFeature); + } + + @FunctionalInterface + interface FeatureContextFunction { + Stream apply(Element element, EStructuralFeature eStructuralFeature); + } + + @FunctionalInterface + interface ElementContextFunction { + Stream apply(Element element); + } + +} diff --git a/src/main/java/org/openmbee/mdk/fileexport/FileExportRunner.java b/src/main/java/org/openmbee/mdk/fileexport/FileExportRunner.java new file mode 100644 index 000000000..fc0258687 --- /dev/null +++ b/src/main/java/org/openmbee/mdk/fileexport/FileExportRunner.java @@ -0,0 +1,465 @@ +package org.openmbee.mdk.fileexport; + +import com.fasterxml.jackson.annotation.JsonProperty; +import com.fasterxml.jackson.annotation.JsonRootName; +import com.fasterxml.jackson.core.JsonFactory; +import com.fasterxml.jackson.core.JsonGenerationException; +import com.fasterxml.jackson.core.JsonGenerator; +import com.fasterxml.jackson.databind.JsonMappingException; +import com.fasterxml.jackson.databind.ObjectMapper; +import com.fasterxml.jackson.databind.ObjectWriter; +import com.fasterxml.jackson.databind.SerializationFeature; +import com.fasterxml.jackson.databind.node.ObjectNode; +import com.nomagic.magicdraw.core.Application; +import com.nomagic.magicdraw.core.Project; +import com.nomagic.magicdraw.core.options.EnvironmentOptions; +import com.nomagic.magicdraw.export.image.ImageExporter; +import com.nomagic.magicdraw.uml.Finder; +import com.nomagic.magicdraw.uml.symbols.DiagramPresentationElement; +import com.nomagic.task.ProgressStatus; +import com.nomagic.task.RunnableWithProgress; +import com.nomagic.uml2.ext.magicdraw.classes.mdkernel.Diagram; +import com.nomagic.uml2.ext.magicdraw.classes.mdkernel.Element; +import org.openmbee.mdk.emf.BulkExport; +import org.openmbee.mdk.json.JacksonUtils; +import org.openmbee.mdk.options.MDKOptionsGroup; +import org.openmbee.mdk.options.MDKProjectOptionsGroup; +import org.openmbee.mdk.util.Pair; + +import java.io.*; +import java.time.Duration; +import java.time.Instant; +import java.util.*; +import java.util.stream.Collectors; +import java.util.stream.Stream; +import java.util.zip.ZipEntry; +import java.util.zip.ZipOutputStream; + +/** + * + * Based on code from ManualSyncRunner by igomes + * + */ +public class FileExportRunner implements RunnableWithProgress { + + /** + * + */ + private static final String MDZIP_EXTENSION = ".mdzip"; + private static final String MDXML_EXTENSION = ".mdxml"; + + private final Collection rootElements; + private final Project project; + private final int depth; + private final File outputFolder; + + private final ObjectWriter jsonWriter = JacksonUtils.getObjectMapper().writerWithDefaultPrettyPrinter(); + private final FileFormat fileFormat; + private final Boolean exportDiagramMappings; + + public enum FileFormat { + MODEL, + TREE, + FRAGMENT, + ZIP; + + public String getExtension() { + return "mdk" + this.name().toLowerCase(); + } + } + + public FileExportRunner(Collection rootElements, Project project, int depth, FileFormat fileFormat, + File outputFolder) { + this.rootElements = rootElements; + this.project = project; + this.depth = depth; + this.fileFormat = fileFormat; + this.outputFolder = outputFolder; + this.exportDiagramMappings = null; + } + + public FileExportRunner(Collection rootElements, Project project, int depth, FileFormat fileFormat, + File outputFolder, boolean exportDiagramMappings) { + this.rootElements = rootElements; + this.project = project; + this.depth = depth; + this.fileFormat = fileFormat; + this.outputFolder = outputFolder; + this.exportDiagramMappings = exportDiagramMappings; + } + + + @Override + public void run(ProgressStatus progressStatus) { + ContextExportLevel contextExportLevel = ContextExportLevel.None; + ElementContextProvider contextProvider = new ElementContextProvider(contextExportLevel); + + String depthDescriptionText = depth == 0 ? "without contents" + : (depth > 0 ? ("up to depth " + depth) : "and all contents"); + String exportDescriptionText = "Exporting to JSON " + rootElements.size() + " " + ((depth != 0) ? "root " : "") + + "element" + (rootElements.size() != 1 ? "s " : " ") + depthDescriptionText; + Application.getInstance().getGUILog().log("[INFO] " + exportDescriptionText); + Application.getInstance().getGUILog() + .log(String.format("[INFO] Using Context export level: '%s'", contextExportLevel.toString())); + + Instant startInstant = Instant.now(); + + progressStatus.setDescription(exportDescriptionText); + progressStatus.setIndeterminate(false); + progressStatus.setMax(rootElements.size()); + progressStatus.setCurrent(0); + + Set usedNames = new HashSet<>(); + + try { + + for (Element rootElement : rootElements) { + + String name = rootElement.getHumanName(); + File outputFile; + if (FileFormat.ZIP == fileFormat) + outputFile = getOutputFile(usedNames, rootElement, project.getName()); + else + outputFile = getOutputFile(usedNames, rootElement, name); + + Application.getInstance().getGUILog().log(String.format("[INFO] Exporting element '%s' %s to file %s", + name, depthDescriptionText, outputFile.getPath().toString())); + + Stream> elements = BulkExport.exportElementsRecursively(project, rootElement, + depth); + + if (fileFormat == FileFormat.ZIP) { + Class[] types = new Class[] { Diagram.class }; + Collection diagramPresentationElements = Finder.byTypeRecursively() + .find(project.getPrimaryModel(), types).stream().map(Diagram.class::cast) + .map(project::getDiagram).collect(Collectors.toList()); + + progressStatus.setMax(progressStatus.getMax() + diagramPresentationElements.size()); + + try (FileOutputStream fileOutputStream = new FileOutputStream(outputFile); + ZipOutputStream zipOutputStream = new ZipOutputStream(fileOutputStream, + java.nio.charset.StandardCharsets.UTF_8)) { + + exportDiagramsToZip(diagramPresentationElements, zipOutputStream, progressStatus); + extractDiagramInfoToZip(diagramPresentationElements, zipOutputStream); + writeDataToZip(progressStatus, contextProvider, zipOutputStream, elements); + + } + } else { + writeDataToFile(progressStatus, contextProvider, outputFile, elements); + } + + progressStatus.increase(); + + if (progressStatus.isCancel()) { + Application.getInstance().getGUILog().log("[INFO] JSON export cancelled by user."); + return; + } + } + + Instant endInstant = Instant.now(); + final Duration elapsed = Duration.between(startInstant, endInstant); + Application.getInstance().getGUILog().log( + String.format("[INFO] JSON export finished successfully in %d seconds.", elapsed.getSeconds())); + + } catch (IOException ioEx) { + handleIOException(ioEx); + } + + } + + private void writeDataToZip(ProgressStatus progressStatus, ElementContextProvider contextProvider, + ZipOutputStream zipOutputStream, Stream> elements) throws IOException { + + ZipEntry zipEntry = new ZipEntry("project." + FileFormat.MODEL.getExtension()); + zipOutputStream.putNextEntry(zipEntry); + + try (PrintWriter filePrinter = new PrintWriter(zipOutputStream)) { + writeData(progressStatus, contextProvider, elements, filePrinter); + } + } + + private void writeDataToFile(ProgressStatus progressStatus, ElementContextProvider contextProvider, File outputFile, + Stream> elements) throws IOException { + try (PrintWriter filePrinter = new PrintWriter(outputFile, "UTF-8")) { + writeData(progressStatus, contextProvider, elements, filePrinter); + } + } + + private void writeData(ProgressStatus progressStatus, ElementContextProvider contextProvider, + Stream> elements, PrintWriter filePrinter) throws IOException { + filePrinter.println("{"); + + int writtenCount = writeElementsToFile(progressStatus, filePrinter, elements, contextProvider); + + Application.getInstance().getGUILog() + .log(String.format("[INFO] Written %d element(s) to file.", writtenCount)); + + filePrinter.println(","); + + writtenCount = writeContextElementsToFile(progressStatus, filePrinter, contextProvider); + + filePrinter.println("}"); + + Application.getInstance().getGUILog() + .log(String.format("[INFO] Written %d context element(s) to file.", writtenCount)); + } + + private File getOutputFile(Set usedNames, Element rootElement, String name) { + File outputFile; + + if ((FileFormat.MODEL == fileFormat) + && project.getPrimaryModel().equals(rootElement)) { + outputFile = wholeProjectFileName(usedNames); + } else { + outputFile = getOutputFile(name, usedNames); + } + + return outputFile; + } + + private int writeContextElementsToFile(ProgressStatus progressStatus, PrintWriter filePrinter, + ElementContextProvider contextProvider) throws IOException { + prefixSequence(filePrinter, "contextElements"); + + Iterator contextElements = contextProvider.getAggregatedContextElements().iterator(); + + int count = 0; + while (!progressStatus.isCancel() && contextElements.hasNext()) { + if (count++ != 0) { + midfixSequence(filePrinter); + } + + final ObjectNode element = contextElements.next(); + + String jsonString = jsonWriter.writeValueAsString(element); + + filePrinter.print(jsonString); + } + + postfixSequence(filePrinter); + + return count; + } + + private ObjectMapper setupJsonObjectMapper() { + JsonFactory jsonFactory = new JsonFactory(); + jsonFactory.configure(JsonGenerator.Feature.AUTO_CLOSE_TARGET, false); + + ObjectMapper mapper = new ObjectMapper(jsonFactory); + mapper.enable(SerializationFeature.INDENT_OUTPUT); + mapper.enable(SerializationFeature.WRAP_ROOT_VALUE); + + return mapper; + } + + private void extractDiagramInfoToZip(Collection diagrams, + ZipOutputStream zipOutputStream) throws IOException { + + ObjectMapper mapper = setupJsonObjectMapper(); + + extractPresentationElementsMapping(diagrams, zipOutputStream, mapper); + + ZipEntry zipEntry = new ZipEntry("diagramInfo.mdkdiagrams"); + zipOutputStream.putNextEntry(zipEntry); + + Map rootElement = new HashMap(); + Collection diagramToJsonList = new ArrayList(); + diagrams.forEach(diag -> { + diagramToJsonList.add(new DiagramBean(diag)); + }); + rootElement.put("diagrams", diagramToJsonList); + mapper.disable(SerializationFeature.WRAP_ROOT_VALUE); + + mapper.writeValue(zipOutputStream, rootElement); + + } + + private void extractPresentationElementsMapping(Collection diagrams, + ZipOutputStream zipOutputStream, ObjectMapper mapper) + throws IOException, JsonGenerationException, JsonMappingException { + + if (MDKOptionsGroup.getMDKOptions().isExportMdkzipDiagramElementsMappingEnabled() + && this.exportDiagramMappings == null) { + + writePresentationElementsToZip(diagrams, zipOutputStream, mapper); + } else if (this.exportDiagramMappings) { + writePresentationElementsToZip(diagrams, zipOutputStream, mapper); + } + } + + private void writePresentationElementsToZip(Collection diagrams, + ZipOutputStream zipOutputStream, ObjectMapper mapper) + throws IOException, JsonGenerationException, JsonMappingException { + for (DiagramPresentationElement diag : diagrams) { + + ZipEntry diagramMappingEntry = new ZipEntry("diagrams/" + getDiagramExportName(diag) + ".mdkmapping"); + zipOutputStream.putNextEntry(diagramMappingEntry); + mapper.writeValue(zipOutputStream, new DiagramMapping(diag)); +} + } + + private void exportDiagramsToZip(Collection diagrams, ZipOutputStream zipOutputStream, + ProgressStatus progressStatus) throws FileNotFoundException, IOException { + + Iterator diagramIterator = diagrams.iterator(); + Application application = Application.getInstance(); + EnvironmentOptions options = application.getEnvironmentOptions(); + + boolean useSvg = options.getGeneralOptions().isUseSVGTextTag(); + options.getGeneralOptions().setUseSVGTextTag(true); + try { + while (!progressStatus.isCancel() && diagramIterator.hasNext()) { + progressStatus.increase(); + DiagramPresentationElement currentDiagram = diagramIterator.next(); + + String diagramExportName = getDiagramExportName(currentDiagram); + File diagramFile = new File(diagramExportName); + diagramFile.createNewFile(); + + ImageExporter.export(currentDiagram, ImageExporter.SVG, diagramFile); + + ZipEntry zipEntry = new ZipEntry("diagrams/" + diagramFile.getName() + ".svg"); + zipOutputStream.putNextEntry(zipEntry); + + try (FileInputStream fileInputStream = new FileInputStream(diagramFile)) { + byte[] bytes = new byte[1024]; + int length; + while ((length = fileInputStream.read(bytes)) >= 0) { + zipOutputStream.write(bytes, 0, length); + } + } + + diagramFile.delete(); + } + } finally { + options.getGeneralOptions().setUseSVGTextTag(useSvg); + } + } + + private String getDiagramExportName(DiagramPresentationElement currentDiagram) { + + return currentDiagram.getName().replaceAll("[^\\p{IsAlphabetic}\\p{Digit}-_]", "_") + "_" + + currentDiagram.getID(); + } + + private int writeElementsToFile(ProgressStatus progressStatus, PrintWriter targetFileWriter, + Stream> exportedElementsStream, ElementContextProvider elementContextProvider) + throws IOException { + prefixSequence(targetFileWriter, "elements"); + + Iterator> exportedElementsIterator = exportedElementsStream.iterator(); + + int count = 0; + while (!progressStatus.isCancel() && exportedElementsIterator.hasNext()) { + if (count++ != 0) { + midfixSequence(targetFileWriter); + } + + final Pair exportedElement = exportedElementsIterator.next(); + + elementContextProvider.registerExportedElement(exportedElement.getKey()); + String jsonString = jsonWriter.writeValueAsString(exportedElement.getValue()); + + targetFileWriter.print(jsonString); + } + + postfixSequence(targetFileWriter); + + return count; + } + + private void prefixSequence(PrintWriter filePrinter, String arrayName) { + filePrinter.println("\"" + arrayName + "\" : ["); + } + + private void postfixSequence(PrintWriter filePrinter) { + filePrinter.println("\n]"); + } + + private void midfixSequence(PrintWriter filePrinter) { + filePrinter.println(","); + } + + private File getOutputFile(String originalName, Set usedNames) { + String rootName = originalName.replaceAll("[^\\p{IsAlphabetic}\\p{Digit}-_]", "_"); + if (rootName.isEmpty()) + rootName = "export"; + String name = rootName; + int postFix = 0; + while (!usedNames.add(name)) { + name = String.format("%s_%04d", rootName, postFix++); + } + + return new File(outputFolder, name + "." + fileFormat.getExtension()); + } + + public File wholeProjectFileName(Set usedNames) { + if (project.isRemote()) { + return getOutputFile(project.getName(), usedNames); + } else { + String projectName = project.getFileName(); + if (projectName.endsWith(MDZIP_EXTENSION)) { + projectName = projectName.substring(0, projectName.length() - MDZIP_EXTENSION.length()); + } else if (projectName.endsWith(MDXML_EXTENSION)) { + projectName = projectName.substring(0, projectName.length() - MDXML_EXTENSION.length()); + } + String outputFileName = projectName + "." + fileFormat.getExtension(); + File outputFile = new File(outputFileName); + return outputFile; + } + } + + private void handleIOException(Throwable ioEx) { + Application.getInstance().getGUILog() + .log("[ERROR] An error occurred while exporting model as JSON, aborting. Reason: " + ioEx.getMessage()); + ioEx.printStackTrace(); + } + + private class DiagramBean { + @JsonProperty("id") + private String id; + @JsonProperty("name") + private String name; + @JsonProperty("parent_id") + private String parentId; + @JsonProperty("type") + private String type; + + public DiagramBean(DiagramPresentationElement diagram) { + + this.id = diagram.getID(); + this.name = diagram.getHumanName(); + + if (diagram.getDiagram().getContext() == null) { + + this.parentId = diagram.getDiagram().getOwner().getID(); + } else { + + this.parentId = diagram.getDiagram().getContext().getID(); + } + this.type = diagram.getHumanType(); + + } + } + + @JsonRootName("diagram") + private class DiagramMapping { + @JsonProperty("id") + private String diagramID; + + @JsonProperty("representedElementsRecursively") + private Collection representedElementsRecursively; + + public DiagramMapping(DiagramPresentationElement diag) { + this.diagramID = diag.getID(); + this.representedElementsRecursively = diag.collectPresentationElementsRecursively().stream().filter(elem-> elem.getElement()!=null) + .map(elem -> elem.getElement().getID()).collect(Collectors.toList()); + } + + } + + + + +} diff --git a/src/main/java/org/openmbee/mdk/options/EnvironmentOptionsResources.java b/src/main/java/org/openmbee/mdk/options/EnvironmentOptionsResources.java new file mode 100644 index 000000000..2df0dab01 --- /dev/null +++ b/src/main/java/org/openmbee/mdk/options/EnvironmentOptionsResources.java @@ -0,0 +1,24 @@ +package org.openmbee.mdk.options; + +import com.nomagic.magicdraw.resources.ResourceManager; + +public class EnvironmentOptionsResources { + public static final String BUNDLE_NAME = "gov.nasa.jpl.mbee.mdk.options.EnvironmentOptionsResources"; + + /** + * Constructs this resource handler. + */ + private EnvironmentOptionsResources() { + // do nothing. + } + + /** + * Gets resource by key. + * + * @param key key by which to get the resource. + * @return translated resource. + */ + public static String getString(String key) { + return ResourceManager.getStringFor(key, BUNDLE_NAME, EnvironmentOptionsResources.class.getClassLoader()); + } +} \ No newline at end of file diff --git a/src/main/java/org/openmbee/mdk/options/MDKOptionsGroup.java b/src/main/java/org/openmbee/mdk/options/MDKOptionsGroup.java new file mode 100644 index 000000000..6007c6024 --- /dev/null +++ b/src/main/java/org/openmbee/mdk/options/MDKOptionsGroup.java @@ -0,0 +1,186 @@ +package org.openmbee.mdk.options; + +import com.nomagic.magicdraw.core.Application; +import com.nomagic.magicdraw.core.options.AbstractPropertyOptionsGroup; +import com.nomagic.magicdraw.properties.*; +import com.nomagic.magicdraw.ui.ImageMap16; +import org.openmbee.mdk.util.MDUtils; + +import javax.swing.*; +import java.io.File; + +public class MDKOptionsGroup extends AbstractPropertyOptionsGroup { + + public static final String ID = "options.mdk"; + public static final String GROUP = "GROUP"; + private static MDKOptionsGroup tempInstance = null; + + public static final String LOG_JSON_ID = "LOG_JSON_ID", + PERSIST_CHANGELOG_ID = "PERSIST_CHANGELOG_ID", + ENABLE_CHANGE_LISTENER_ID = "ENABLE_CHANGE_LISTENER_ID", + ENABLE_COORDINATED_SYNC_ID = "ENABLE_COORDINATED_SYNC_ID", + CUSTOM_USER_SCRIPT_DIRECTORIES_ID = "CUSTOM_USER_SCRIPT_DIRECTORIES_ID", + DOCBOOK_TO_PDF_STYLESHEET = "DOCBOOK_TO_PDF_STYLESHEET", + EXPORT_MDKZIP_DIAGRAM_ELEMENTS_MAPPING = "EXPORT_MDKZIP_DIAGRAM_ELEMENTS_MAPPING"; + + public MDKOptionsGroup() { + super(ID); + } + + public static MDKOptionsGroup getMDKOptions() { + MDKOptionsGroup group = (MDKOptionsGroup) Application.getInstance().getEnvironmentOptions().getGroup(ID); + if (group == null) { + if (tempInstance == null) { + tempInstance = new MDKOptionsGroup(); + } + return tempInstance; + } + return group; + } + + public boolean isLogJson() { + if (MDUtils.isDeveloperMode()) { + return true; + } + Property p = getProperty(LOG_JSON_ID); + return (Boolean) p.getValue(); + } + + public void setLogJson(boolean value) { + BooleanProperty property = new BooleanProperty(LOG_JSON_ID, value); + property.setResourceProvider(PROPERTY_RESOURCE_PROVIDER); + property.setGroup(GROUP); + addProperty(property, true); + } + + public boolean isPersistChangelog() { + Property p = getProperty(PERSIST_CHANGELOG_ID); + return (Boolean) p.getValue(); + } + + public void setPersistChangelog(boolean value) { + BooleanProperty property = new BooleanProperty(PERSIST_CHANGELOG_ID, value); + property.setResourceProvider(PROPERTY_RESOURCE_PROVIDER); + property.setGroup(GROUP); + if (MDUtils.isDeveloperMode()) { + addProperty(property, true); + } + else { + addInvisibleProperty(property); + } + } + + public boolean isChangeListenerEnabled() { + Property p = getProperty(ENABLE_CHANGE_LISTENER_ID); + return (Boolean) p.getValue(); + } + + public void setChangeListenerEnabled(boolean value) { + BooleanProperty property = new BooleanProperty(ENABLE_CHANGE_LISTENER_ID, value); + property.setResourceProvider(PROPERTY_RESOURCE_PROVIDER); + property.setGroup(GROUP); + if (MDUtils.isDeveloperMode()) { + addProperty(property, true); + } + else { + addInvisibleProperty(property); + } + } + + public boolean isCoordinatedSyncEnabled() { + Property p = getProperty(ENABLE_COORDINATED_SYNC_ID); + return (Boolean) p.getValue(); + } + + public void setCoordinatedSyncEnabled(boolean value) { + BooleanProperty property = new BooleanProperty(ENABLE_COORDINATED_SYNC_ID, value); + property.setResourceProvider(PROPERTY_RESOURCE_PROVIDER); + property.setGroup(GROUP); + if (MDUtils.isDeveloperMode()) { + addProperty(property, true); + } + else { + addInvisibleProperty(property); + } + } + + public File[] getCustomUserScriptDirectories() { + Property p = getProperty(CUSTOM_USER_SCRIPT_DIRECTORIES_ID); + String val = p.getValueStringRepresentation(); + if (val == null || val.isEmpty()) { + return null; + } + File[] dirs = new File[getNumberOfCustomUserScriptDirectories()]; + for (int i = 0; i < getNumberOfCustomUserScriptDirectories(); i++) { + dirs[i] = new File(val.split(File.pathSeparator)[i]); + } + return dirs; + } + + public int getNumberOfCustomUserScriptDirectories() { + Property p = getProperty(CUSTOM_USER_SCRIPT_DIRECTORIES_ID); + String val = p.getValueStringRepresentation(); + if (val == null || val.isEmpty()) { + return 0; + } + return val.split(File.pathSeparator).length; + + } + + public void setUserScriptDirectory(String path) { + StringProperty property = new StringProperty(CUSTOM_USER_SCRIPT_DIRECTORIES_ID, path); + property.setResourceProvider(PROPERTY_RESOURCE_PROVIDER); + property.setGroup(GROUP); + addProperty(property, true); + } + + + public String getDocBookToPDFStyleSheet() { + Property p = getProperty(DOCBOOK_TO_PDF_STYLESHEET); + return (String) p.getValue(); + } + + public void setDocBookToPDFStyleSheet(String value) { + FileProperty property = new FileProperty(DOCBOOK_TO_PDF_STYLESHEET, value, FileProperty.FILES_ONLY); + property.setResourceProvider(PROPERTY_RESOURCE_PROVIDER); + property.setGroup(GROUP); + addProperty(property, true); + } + + public void setExportMdkzipDiagramElementsMapping(Boolean value) { + BooleanProperty property = new BooleanProperty(EXPORT_MDKZIP_DIAGRAM_ELEMENTS_MAPPING, value); + property.setResourceProvider(PROPERTY_RESOURCE_PROVIDER); + property.setGroup(GROUP); + addProperty(property, true); + } + + public boolean isExportMdkzipDiagramElementsMappingEnabled() { + Property p = getProperty(EXPORT_MDKZIP_DIAGRAM_ELEMENTS_MAPPING); + return (Boolean) p.getValue(); + } + + public static final PropertyResourceProvider PROPERTY_RESOURCE_PROVIDER = (key, property) -> EnvironmentOptionsResources.getString(key); + + @Override + public void setDefaultValues() { + setLogJson(false); + setPersistChangelog(true); + setChangeListenerEnabled(true); + setCoordinatedSyncEnabled(true); + setUserScriptDirectory(""); + setDocBookToPDFStyleSheet(""); + setExportMdkzipDiagramElementsMapping(true); + } + + private static final String MDK_OPTIONS_NAME = "MDK_OPTIONS_NAME"; + + @Override + public String getName() { + return EnvironmentOptionsResources.getString(MDK_OPTIONS_NAME); + } + + @Override + public Icon getGroupIcon() { + return ImageMap16.SETTINGS; + } +} diff --git a/src/main/java/org/openmbee/mdk/options/MDKProjectOptionsGroup.java b/src/main/java/org/openmbee/mdk/options/MDKProjectOptionsGroup.java new file mode 100644 index 000000000..71a4e1e8c --- /dev/null +++ b/src/main/java/org/openmbee/mdk/options/MDKProjectOptionsGroup.java @@ -0,0 +1,99 @@ +package org.openmbee.mdk.options; + +import com.nomagic.magicdraw.core.Project; +import com.nomagic.magicdraw.core.options.ProjectOptions; +import com.nomagic.magicdraw.core.options.ProjectOptionsConfigurator; +import com.nomagic.magicdraw.properties.BooleanProperty; +import com.nomagic.magicdraw.properties.ChoiceProperty; +import com.nomagic.magicdraw.properties.Property; +import com.nomagic.magicdraw.properties.PropertyResourceProvider; +import org.openmbee.mdk.fileexport.ContextExportLevel; + +import java.util.Arrays; + +public class MDKProjectOptionsGroup implements ProjectOptionsConfigurator { + + public static final String PROPERTYGROUP_MDK = "PROPERTYGROUP_MDK"; + + public static final String PROPERTY_AUTOSAVE_MDKMODEL = "PROPERTY_AUTOSAVE_MDKMODEL_ID"; + public static final String PROPERTY_AUTOSAVE_MDKZIP = "PROPERTY_AUTOSAVE_MDKZIP_ID"; + public static final String PROPERTY_CONTEXT_EXPORT_LEVEL = "PROPERTY_CONTEXT_EXPORT_LEVEL_ID"; + + public static final PropertyResourceProvider PROPERTY_RESOURCE_PROVIDER = (key, property) -> ProjectOptionsResources.getString(key); + + public static boolean isAutosaveMDKModel(Project project) { + Property property = project.getOptions().getProperty(ProjectOptions.PROJECT_GENERAL_PROPERTIES, PROPERTY_AUTOSAVE_MDKMODEL); + if (property != null) { + return (boolean) property.getValue(); + } else { + return false; + } + + } + + public static boolean isAutosaveMDKZip(Project project) { + Property property = project.getOptions().getProperty(ProjectOptions.PROJECT_GENERAL_PROPERTIES, PROPERTY_AUTOSAVE_MDKZIP); + if (property != null) { + return (boolean) property.getValue(); + } else { + return false; + } + + } + + public static ContextExportLevel getContextExportLevel(Project project) { + Property property = project.getOptions().getProperty(ProjectOptions.PROJECT_GENERAL_PROPERTIES, PROPERTY_CONTEXT_EXPORT_LEVEL); + if (property != null) { + return ContextExportLevel.valueOf(property.getValueStringRepresentation()); + } else { + return ContextExportLevel.None; + } + } + + @Override + public void afterLoad(ProjectOptions arg0) { + + } + + @Override + public void configure(ProjectOptions projectOptions) { + setAutosaveProperty(projectOptions); + + setAutosaveMdkzipProperty(projectOptions); + + setContextExportLevelProperty(projectOptions); + } + + private void setAutosaveProperty(ProjectOptions projectOptions) { + Property autosaveProperty = projectOptions.getProperty(ProjectOptions.PROJECT_GENERAL_PROPERTIES, PROPERTY_AUTOSAVE_MDKMODEL); + if (autosaveProperty == null) { + autosaveProperty = new BooleanProperty(PROPERTY_AUTOSAVE_MDKMODEL, false); + autosaveProperty.setGroup(PROPERTYGROUP_MDK); + autosaveProperty.setResourceProvider(PROPERTY_RESOURCE_PROVIDER); + projectOptions.addProperty(ProjectOptions.PROJECT_GENERAL_PROPERTIES, autosaveProperty); + } + } + + private void setAutosaveMdkzipProperty(ProjectOptions projectOptions) { + Property autosaveMdkzipProperty = projectOptions.getProperty(ProjectOptions.PROJECT_GENERAL_PROPERTIES, PROPERTY_AUTOSAVE_MDKZIP); + if (autosaveMdkzipProperty == null) { + autosaveMdkzipProperty = new BooleanProperty(PROPERTY_AUTOSAVE_MDKZIP, false); + autosaveMdkzipProperty.setGroup(PROPERTYGROUP_MDK); + autosaveMdkzipProperty.setResourceProvider(PROPERTY_RESOURCE_PROVIDER); + projectOptions.addProperty(ProjectOptions.PROJECT_GENERAL_PROPERTIES, autosaveMdkzipProperty); + } + } + + private void setContextExportLevelProperty(ProjectOptions projectOptions) { + Property contextExportLevelProperty = projectOptions.getProperty(ProjectOptions.PROJECT_GENERAL_PROPERTIES, PROPERTY_CONTEXT_EXPORT_LEVEL); + if (contextExportLevelProperty == null) { + + contextExportLevelProperty = new ChoiceProperty(PROPERTY_CONTEXT_EXPORT_LEVEL, "", Arrays.asList(ContextExportLevel.values())); + contextExportLevelProperty.setGroup(PROPERTYGROUP_MDK); + contextExportLevelProperty.setResourceProvider(PROPERTY_RESOURCE_PROVIDER); + contextExportLevelProperty.setValue(ContextExportLevel.Containment); + projectOptions.addProperty(ProjectOptions.PROJECT_GENERAL_PROPERTIES, contextExportLevelProperty); + } + } + +} diff --git a/src/main/java/org/openmbee/mdk/options/ProjectOptionsResources.java b/src/main/java/org/openmbee/mdk/options/ProjectOptionsResources.java new file mode 100644 index 000000000..07e585dfa --- /dev/null +++ b/src/main/java/org/openmbee/mdk/options/ProjectOptionsResources.java @@ -0,0 +1,24 @@ +package org.openmbee.mdk.options; + +import com.nomagic.magicdraw.resources.ResourceManager; + +public class ProjectOptionsResources { + public static final String BUNDLE_NAME = "gov.nasa.jpl.mbee.mdk.options.ProjectOptionsResources"; + + /** + * Constructs this resource handler. + */ + private ProjectOptionsResources() { + // do nothing. + } + + /** + * Gets resource by key. + * + * @param key key by which to get the resource. + * @return translated resource. + */ + public static String getString(String key) { + return ResourceManager.getStringFor(key, BUNDLE_NAME, ProjectOptionsResources.class.getClassLoader()); + } +} \ No newline at end of file diff --git a/src/main/java/org/openmbee/mdk/util/MdkExportUtils.java b/src/main/java/org/openmbee/mdk/util/MdkExportUtils.java new file mode 100644 index 000000000..59620d9b0 --- /dev/null +++ b/src/main/java/org/openmbee/mdk/util/MdkExportUtils.java @@ -0,0 +1,37 @@ +package org.openmbee.mdk.util; + +import com.nomagic.magicdraw.core.Project; +import com.nomagic.magicdraw.ui.dialogs.MDDialogParentProvider; + +import javax.swing.*; +import java.awt.*; +import java.io.File; + +public class MdkExportUtils { + + private MdkExportUtils() {} + + /** + * @param project + * @return selected folder, or null if cancelled + */ + public static File chooseFolder(Project project) { + Window dialogParent = MDDialogParentProvider.getProvider().getDialogOwner(); + JFileChooser folderChooser = new JFileChooser(); + folderChooser.setFileSelectionMode(JFileChooser.DIRECTORIES_ONLY); + folderChooser.setDialogTitle("Select folder to export into"); + + if (!project.isRemote()) { + File projectLocation = new File(project.getFileName()); + File projectFolder = projectLocation.getParentFile(); + folderChooser.setSelectedFile(projectFolder); + } + + + int result = folderChooser.showDialog(dialogParent, "Select"); + File selectedFolder = folderChooser.getSelectedFile(); + File folderSelection = (result == JFileChooser.APPROVE_OPTION ) ? selectedFolder : null; + return folderSelection; + } + +} From dd5a425a313faf1b75902b93e4f1a675d4f0b96d Mon Sep 17 00:00:00 2001 From: Enquier Date: Mon, 25 Mar 2024 15:34:58 -0600 Subject: [PATCH 04/19] Initial Commit for 2021 R2,2022 R1&R2 compatibility --- .gitignore | 2 + README.md | 6 +- build.gradle | 34 ++- buildProfiles/example.properties | 28 -- buildProfiles/opensource.properties | 7 +- gradle/wrapper/gradle-wrapper.jar | Bin 56177 -> 59203 bytes gradle/wrapper/gradle-wrapper.properties | 2 +- gradlew | 282 +++++++++++------- gradlew.bat | 43 +-- .../mdk/docgen/ViewViewpointValidator.java | 4 +- .../org/openmbee/mdk/emf/EMFBulkImporter.java | 77 ++++- .../openmbee/mdk/http/ServerException.java | 2 +- .../options/MDKEnvironmentOptionsGroup.java | 4 +- 13 files changed, 314 insertions(+), 177 deletions(-) delete mode 100644 buildProfiles/example.properties diff --git a/.gitignore b/.gitignore index f1f04c412..c9e1a7893 100644 --- a/.gitignore +++ b/.gitignore @@ -21,3 +21,5 @@ venv/* *.groovy libz mddocs +bin +.run diff --git a/README.md b/README.md index ad8c2d090..9e1baf69d 100644 --- a/README.md +++ b/README.md @@ -1,6 +1,6 @@ # Cameo Model Development Kit (MDK) -[![GitHub release (latest SemVer)](https://img.shields.io/github/v/release/Open-MBEE/mdk?label=download)](https://github.com/Open-MBEE/mdk/releases/latest) [![Maven Central](https://img.shields.io/maven-central/v/org.openmbee.mdk.magic/mdk)](https://search.maven.org/artifact/org.openmbee.mdk.magic/mdk) [![Jira](https://img.shields.io/badge/issues-jira-blue)](https://openmbee.atlassian.net/browse/MDK) [![CircleCI](https://circleci.com/gh/Open-MBEE/mdk.svg?style=shield)](https://circleci.com/gh/Open-MBEE/mdk) [![Language grade: Java](https://img.shields.io/lgtm/grade/java/g/Open-MBEE/mdk.svg?logo=lgtm&logoWidth=18)](https://lgtm.com/projects/g/Open-MBEE/mdk/context:java) +[![GitHub release (latest SemVer)](https://img.shields.io/github/v/release/Open-MBEE/mdk?label=download)](https://github.com/Open-MBEE/mdk/releases/latest) [![Maven Central](https://img.shields.io/maven-central/v/org.openmbee.mdk.magic/mdk)](https://search.maven.org/artifact/org.openmbee.mdk.magic/mdk) [![CircleCI](https://circleci.com/gh/Open-MBEE/mdk.svg?style=shield)](https://circleci.com/gh/Open-MBEE/mdk) Cameo MDK is a plugin for [Cameo Systems Modeler](https://www.nomagic.com/products/cameo-systems-modeler) and other No Magic environment bundles that’s primary purposes are to sync models with the [MMS](https://github.com/Open-MBEE/mms-alfresco) and implement the [DocGen](src/main/dist/manual) language, which allows modelers to dynamically generate documents in a model-based approach using the view and viewpoint concept. @@ -12,8 +12,8 @@ The latest user documentation can be accessed online: https://mdk.readthedocs.io ## Prerequisites -* [Cameo Systems Modeler (CSM)](https://www.nomagic.com/products/cameo-systems-modeler) or another No Magic environment bundle that includes the [SysML plugin](https://www.nomagic.com/product-addons/magicdraw-addons/sysml-plugin) - * The latest Cameo MDK is compatible with **19.0 SP3** and **19.0 SP4**. Compatibility for previous versions of Cameo MDK can be found in the [compatibility matrices](https://github.com/Open-MBEE/open-mbee.github.io/wiki/Compatibilities). +* [Cameo Systems Modeler (CSM)](https://www.nomagic.com/products/cameo-systems-modeler) or another No Magic environment bundle that includes the [SysML plugin](https://www.nomagic.com/product-addons/magicdraw-addons/sysml-plugin) (Only CSM has been tested) + * The latest Cameo MDK is compatible with **2021x Refresh2** thru **2022x Refresh2**. Compatibility for previous versions of Cameo MDK can be found in the [compatibility matrices](https://github.com/Open-MBEE/open-mbee.github.io/wiki/Compatibilities). * [Model Management System (MMS)](https://www.openmbee.org/projects.html#mms) * The Cameo MDK (5.0+) is compatible with MMS **4.x**. Compatibility for previous version of Cameo MDK can be found in the [compatibility matrices](https://github.com/Open-MBEE/open-mbee.github.io/wiki/Compatibilities). diff --git a/build.gradle b/build.gradle index 613d6e7cd..b2b9a7036 100644 --- a/build.gradle +++ b/build.gradle @@ -13,6 +13,7 @@ buildscript { } dependencies { classpath "io.github.gradle-nexus:publish-plugin:1.0.0" + classpath group: "com.jfrog.artifactory", name: 'com.jfrog.artifactory.gradle.plugin', version: '5.1.9' classpath group: 'org.openjfx', name: 'javafx-plugin', version: '0.0.14' } } @@ -24,10 +25,12 @@ plugins { id 'java' id 'distribution' id 'org.openjfx.javafxplugin' version '0.0.14' + id 'com.jfrog.artifactory' version '5.1.9' } String buildProfile = project.getProperties().getOrDefault('buildProfile', 'opensource') String buildTag = project.getProperties().get('buildTag') + if (buildTag != null && !buildTag.isEmpty() && buildTag != version) { throw new GradleException('Version mismatch: ' + buildTag + ' vs ' + version) } @@ -66,6 +69,7 @@ else { String docbookNameVersion = 'docbook-xsl-1.79.1' String fopNameVersion = 'fop-1.1' + // In this section you declare where to find the dependencies of your project repositories { mavenCentral() @@ -207,6 +211,7 @@ dependencies { // Other dependencies we're unable to resolve via standard repositories + // Handle build all-in-one profile workflow if (profiles['nomagicDeps'] != null) { def mdDeps = parser.parseText(profiles['nomagicDeps'].toString()) mdDeps.each { @@ -214,6 +219,7 @@ dependencies { preImplementation group: "${dep.group}", name: "${dep.name}", version: "${dep.version}", classifier: "${dep.classifier != null ? dep.classifier : ''}", ext: "${dep.ext}" } } + // Default Dev Workflow, this will only correctly pull from the local ./libz flatDir else { preImplementation group: 'com.nomagic', name: 'democsm', version: '2022xRefresh1', classifier: 'Cameo_Systems_Modeler_2022x_Refresh1_HF1_no_install', ext: 'zip' // preCompile group: 'com.nomagic', name: 'sysml', version: '2021x', classifier: 'SysML_Plugin_2021x', ext: 'zip' @@ -231,7 +237,7 @@ dependencies { // This ensures classpath load order to match the MagicDraw provided order and then includes extras needed for non-OpenAPI stuff. // This was necessary because of the Application class stubbing that was done in the chromium libraries. implementation files(classpathLibraries.collect { 'build/dependency-cache/extracted/magicdraw/' + it }) - implementation fileTree(dir: 'build/dependency-cache/extracted/magicdraw', include: ['lib/**/*.jar', 'plugins/**/*.jar'], exclude: ([classpathLibraries, ['plugins/com.nomagic.collaborator.publisher/**/*.jar', 'plugins/com.nomagic.magicdraw.emfuml2xmi*/**/*.jar', 'plugins/com.nomagic.magicdraw.automaton/lib/engines/**/*.jar', 'plugins/tomsawyer/**/*.jar', 'plugins/com.intercax.syndeia.md/**/*.jar']]).flatten()) + implementation fileTree(dir: 'build/dependency-cache/extracted/magicdraw', include: ['lib/**/*.jar', 'plugins/**/*.jar'], exclude: ([classpathLibraries, ['plugins/com.nomagic.conceptmodeler/**/*jar', 'plugins/com.nomagic.magicdraw.xmiexporter/**/*jar', 'plugins/com.nomagic.collaborator.publisher/**/*.jar', 'plugins/com.nomagic.magicdraw.emfuml2xmi*/**/*.jar', 'plugins/com.nomagic.magicdraw.automaton/lib/engines/**/*.jar', 'plugins/tomsawyer/**/*.jar', 'plugins/com.intercax.syndeia.md/**/*.jar']]).flatten()) implementation fileTree(dir: 'lib', include: ['**/*.jar']) implementation files("build/dependency-cache/extracted/fop/jars/${fopNameVersion}.jar", 'build/dependency-cache/extracted/fop/jars/xmlgraphics-commons-1.5.jar') if (profiles["implementationFiles"] != null) { @@ -249,8 +255,7 @@ dependencies { javafx { version = "11.0.2" modules = [ 'javafx.controls', 'javafx.fxml', 'javafx.swing' ] - platform = 'win' - configurations = ['preImplementation'] + platform = 'linux' } task extractDependencies { @@ -310,7 +315,9 @@ task extractDependencies { from zipTree(archive) into 'build/dependency-cache/extracted/magicdraw' } + } + delete 'build/dependency-cache/extracted/magicdraw/plugins/com.nomagic.conceptmodeler' } } compileJava.dependsOn extractDependencies @@ -590,6 +597,27 @@ nexusPublishing { } } +artifactoryPublish { + publications('mavenJava') + +} + +artifactoryPublish.dependsOn distZip + +artifactory { + publish { + contextUrl = project.property('artifactoryUrl') as String + repository { + repoKey = project.property('artifactoryRepository') + username = project.getProperties().get('artifactoryUsername').toString() + password = project.getProperties().get('artifactoryPassword').toString() + } + } + if (buildNumber != null && !buildNumber.isEmpty()) { + clientConfig.info.setBuildNumber(buildNumber) + } +} + installDist { destinationDir = file('build/plugin') doLast { diff --git a/buildProfiles/example.properties b/buildProfiles/example.properties deleted file mode 100644 index 052b5e1ad..000000000 --- a/buildProfiles/example.properties +++ /dev/null @@ -1,28 +0,0 @@ -#/* Example Properties -# -#* This file serves as a reference for defining custom profiles for building MDK. You are not required to use any of -#* these properties to build MDK, any property if undefined will just cause the build script to use the defaults in build.gradle and -#* opensource.properties files -#/* -#Specifies the desired classpath for MD/Cameo related resources, copy paste from /bin/.properties and find replace \: for ',' -classpathLibraries = "lib/patch.jar,lib/brand.jar,lib/brand_api.jar,lib/md.jar,lib/md_api.jar,lib/md_common.jar,lib/md_common_api.jar,lib/md_common_test.jar,lib/tw_common.jar,lib/tw_common_api.jar,lib/launcher.jar,lib/activation.jar,lib/annotation.jar,lib/batik.jar,lib/bridj-0.7.0.jar,lib/bundles/ch.qos.logback.classic_1.2.3.jar,lib/bundles/ch.qos.logback.core_1.2.3.jar,lib/bundles/cmof_1.4.0.202006020804/cmof14.jar,lib/bundles/cmof_1.4.0.202006020804/tas.jar,lib/bundles/com.esotericsoftware.kryo_2.22.0.201401231130.jar,lib/bundles/com.google.guava_18.0.0.jar,lib/bundles/com.nomagic.annotations_1.0.0/com.nomagic.annotation-1.0.jar,lib/bundles/com.nomagic.ci.binary_17.0.5.v20200602-0758.jar,lib/bundles/com.nomagic.ci.metamodel.project_17.0.5.v20200602-0758.jar,lib/bundles/com.nomagic.ci.persistence.local_17.0.5.v20200602-0758.jar,lib/bundles/com.nomagic.ci.persistence_17.0.5.v20200602-0758.jar,lib/bundles/com.nomagic.ci.services_17.0.5.v20200602-0758.jar,lib/bundles/com.nomagic.ci_17.0.5.v20200602-0758.jar,lib/bundles/com.nomagic.magicdraw.ce_18.1.0.202006020804.jar,lib/bundles/com.nomagic.magicdraw.core.diagram_18.1.0.202006020804.jar,lib/bundles/com.nomagic.magicdraw.core.project.options_18.1.0.202006020804.jar,lib/bundles/com.nomagic.magicdraw.core_1.0.0.202006020804.jar,lib/bundles/com.nomagic.magicdraw.esi.binary.metamodel_18.1.0.202006020804.jar,lib/bundles/com.nomagic.magicdraw.esi.esiproject_18.1.0.202006020804.jar,lib/bundles/com.nomagic.magicdraw.esi.uuidmap_18.1.0.202006020804.jar,lib/bundles/com.nomagic.magicdraw.foundation_2.0.0.202006020804.jar,lib/bundles/com.nomagic.magicdraw.osgi.fragment_1.0.0.202006020804.jar,lib/bundles/com.nomagic.magicdraw.security_18.3.0.202006020804.jar,lib/bundles/com.nomagic.magicdraw.uml2_2.5.1.202006020804.jar,lib/bundles/com.nomagic.magicdraw_17.0.5.202006020804.jar,lib/bundles/com.teamdev.jxbrowser.chromium.internal.linux64_6.24.1.jar,lib/bundles/com.teamdev.jxbrowser.chromium.internal.mac_6.24.1.jar,lib/bundles/com.teamdev.jxbrowser.chromium.internal.win32_6.24.1.jar,lib/bundles/com.teamdev.jxbrowser.chromium.internal.win64_6.24.1.jar,lib/bundles/com.teamdev.jxbrowser.chromium_6.24.1.jar,lib/bundles/com.typesafe.config_1.3.0.jar,lib/bundles/com.typesafe.sslconfig_0.2.2.jar,lib/bundles/de.schlichtherle.truezip_7.4.3.v20200602-0758/lib/truezip-driver-zip-7.4.3.jar,lib/bundles/de.schlichtherle.truezip_7.4.3.v20200602-0758/lib/truezip-kernel-7.4.3.jar,lib/bundles/gnu.trove_3.0.3/lib/trove-3.0.3.jar,lib/bundles/io.aeron.client_1.7.0.jar,lib/bundles/io.aeron.driver_1.7.0.jar,lib/bundles/io.dropwizard.metrics.core_3.1.2.jar,lib/bundles/io.dropwizard.metrics.graphite_3.1.2.jar,lib/bundles/io.netty.buffer_4.1.21.Final.jar,lib/bundles/io.netty.codec_4.1.21.Final.jar,lib/bundles/io.netty.common_4.1.21.Final.jar,lib/bundles/io.netty.handler_4.1.21.Final.jar,lib/bundles/io.netty.resolver_4.1.21.Final.jar,lib/bundles/io.netty.transport_4.1.21.Final.jar,lib/bundles/javax.jmi_1.0.0.202006020804/javax_jmi-1_0-fr.jar,lib/bundles/joda-time_2.9.1.jar,lib/bundles/lz4-java_1.3.0.jar,lib/bundles/org.agrona_0.9.12.jar,lib/bundles/org.apache.commons.codec_1.9.0.v20170208-1614.jar,lib/bundles/org.apache.commons.collections_3.2.1.jar,lib/bundles/org.apache.commons.compress_1.3.0.jar,lib/bundles/org.apache.commons.io_2.4.0.jar,lib/bundles/org.apache.commons.lang_2.6.0.v201404270220.jar,lib/bundles/org.apache.commons.logging_1.1.1.v201101211721.jar,lib/bundles/org.apache.felix.scr_2.0.10.v20170501-2007.jar,lib/bundles/org.apache.httpcomponents.httpclient_4.5.3.jar,lib/bundles/org.apache.httpcomponents.httpcore_4.4.6.v20170210-0925.jar,lib/bundles/org.apache.log4j_1.2.15.v201005080500.jar,lib/bundles/org.apache.servicemix.bundles.jsr305_2.0.1.1.jar,lib/bundles/org.apiguardian_1.1.0.v20190826-0900.jar,lib/bundles/org.eclipse.core.contenttype_3.6.0.v20170207-1037.jar,lib/bundles/org.eclipse.core.jobs_3.9.2.v20171030-1027.jar,lib/bundles/org.eclipse.core.runtime_3.13.0.v20170207-1030.jar,lib/bundles/org.eclipse.emf.common_2.13.0.v20170609-0707.jar,lib/bundles/org.eclipse.emf.ecore.xmi_2.13.0.v20170609-0707.jar,lib/bundles/org.eclipse.emf.ecore_2.13.0.v20170609-0707.jar,lib/bundles/org.eclipse.equinox.app_1.3.400.v20150715-1528.jar,lib/bundles/org.eclipse.equinox.common_3.9.0.v20170207-1454.jar,lib/bundles/org.eclipse.equinox.ds_1.5.0.v20170307-1429.jar,lib/bundles/org.eclipse.equinox.preferences_3.7.0.v20170126-2132.jar,lib/bundles/org.eclipse.equinox.registry_3.7.0.v20170222-1344.jar,lib/bundles/org.eclipse.osgi.services_3.6.0.v20170228-1906.jar,lib/bundles/org.eclipse.osgi.util_3.4.0.v20170111-1608.jar,lib/bundles/org.eclipse.osgi_3.12.50.v20170928-1321.jar,lib/bundles/org.eclipse.uml2.common_1.5.0.v200905041045.jar,lib/bundles/org.hamcrest.core_1.3.0.v201303031735.jar,lib/bundles/org.jboss.netty_3.10.6.Final.jar,lib/bundles/org.json_1.0.0.255610281323.jar,lib/bundles/org.junit.jupiter.api_5.5.1.v20190826-0900.jar,lib/bundles/org.junit.jupiter.params_5.5.1.v20190826-0900.jar,lib/bundles/org.junit.platform.commons_1.5.1.v20190826-0900.jar,lib/bundles/org.junit_4.12.0.v201504281640/junit.jar,lib/bundles/org.opentest4j_1.2.0.v20190826-0900.jar,lib/bundles/org.reactivestreams.reactive-streams_1.0.2.jar,lib/bundles/org.uncommons.maths_1.2.2.201301151508/lib/uncommons-maths-1.2.2a.jar,lib/bundles/slf4j.api_1.7.25.jar,lib/com.nomagic.osgi.launcher-17.0.5-SNAPSHOT.jar,lib/commons-compress-1.3.jar,lib/commons-httpclient-3.1.jar,lib/commons-logging-1.0.4.jar,lib/concurrent.jar,lib/EccpressoAll.jar,lib/ehcache-2.10.1.jar,lib/flexlm.jar,lib/graphics/clibwrapper_jiio.jar,lib/graphics/freehep-base.jar,lib/graphics/freehep-graphics2d.jar,lib/graphics/freehep-graphicsio-emf.jar,lib/graphics/freehep-graphicsio-ps.jar,lib/graphics/freehep-graphicsio.jar,lib/graphics/jai_imageio.jar,lib/gson-2.2.4.jar,lib/HTMLEditorLight.jar,lib/hunspell-bridj-1.0.5-SNAPSHOT.jar,lib/javassist.jar,lib/jhall.jar,lib/jide-action.jar,lib/jide-charts.jar,lib/jide-common.jar,lib/jide-components.jar,lib/jide-diff.jar,lib/jide-dock.jar,lib/jide-editor.jar,lib/jide-gantt.jar,lib/jide-grids.jar,lib/jide-shortcut.jar,lib/jimi.jar,lib/jna.jar,lib/jnp-client.jar,lib/jtidy-sources.zip,lib/jtidy.jar,lib/JUnitParams-1.0.1.jar,lib/lucene-analyzers-common-7.5.0.jar,lib/lucene-core-7.5.0.jar,lib/lucene-misc-7.5.0.jar,lib/poi-3.14-20160307.jar,lib/poi-ooxml-3.14-20160307.jar,lib/poi-ooxml-schemas-3.14-20160307.jar,lib/webservice/axis-config.jar,lib/webservice/axis.jar,lib/webservice/commons-discovery-0.2.jar,lib/webservice/jaxrpc.jar,lib/webservice/mdserviceclient.jar,lib/webservice/rsclient.jar,lib/webservice/wsdl4j-1.5.1.jar,lib/xalan.jar,lib/xmlbeans-2.6.0.jar,lib/y.jar" - -#Specify a custom package for magicdraw to download -nomagicDeps = "[{"group": "gov.nasa.jpl.cae.nomagic", "name": "cae-cameo-systems-modeler-core", "version": "4.4.4", "classifier": "linux", "ext": "zip"}]" - -#Specify a custom list of additional non-java dependencies for your build (i.e. if you need JavaFX or FOP). -#Note: the first two are required, the third depends on the version of Java you are using to build (ie. Oracle JDK vs OpenJDK) -compileFiles = build/dependency-cache/extracted/fop/jars/fop-1.1.jar,build/dependency-cache/extracted/fop/jars/xmlgraphics-commons-1.5.jar,build/dependency-cache/extracted/magicdraw/jre/lib/ext/jfxrt.jar - -#If you wish to change the Java package structure group specify it here. Otherwise defaults to org.openmbee -group = "com.yourcompany" - -#If you wish to pull from your own custom repositories specify them here in JSON format -#Note: Setting credentials to true, will allow use of -PartifactoryUsername and -PartifactoryPassword for that repo, they do NOT -#allow specification of custom credentials. -repositories = [{"type": "maven", "url": "", "credentials": true }, {"type": "maven", "url": "", "credentials": true }] - -#For development use of the runJava task, this will let you specify a path to a locally usable JRE for -#Cameo/MD and MDK. Otherwise your machine's JAVA_HOME will be used -executablePath = "" - diff --git a/buildProfiles/opensource.properties b/buildProfiles/opensource.properties index 68bf1ad9a..28bfa7220 100644 --- a/buildProfiles/opensource.properties +++ b/buildProfiles/opensource.properties @@ -1,2 +1,5 @@ -classpathLibraries = lib/classpath.jar -repositories = [{"type": "ivy", "url": "http://download1.nomagic.com/", "layoutPattern": "/[module][revision]/[classifier].[ext]"}] +# classpathLibraries = lib/classpath.jar +# compileFiles = build/dependency-cache/extracted/fop/jars/fop-1.1.jar,build/dependency-cache/extracted/fop/jars/xmlgraphics-commons-1.5.jar +# repositories = [{"type": "ivy", "url": "http://download1.nomagic.com/", "layoutPattern": "/[module][revision]/[classifier].[ext]"}] +# nomagicDeps = [{"group": "com.nomagic", "name": "Cameo_Enterprise_Architecture_2021x_Refresh2_HF5_no_install", "version": "2021xRefresh2_HF5", "classifier": "", "ext": "zip"},{"group": "com.nomagic", "name": "Cameo_Simulation_Toolkit_Plugin_2021x_Refresh2", "version": "2021xRefresh2", "classifier": "", "ext": "zip"}] + \ No newline at end of file diff --git a/gradle/wrapper/gradle-wrapper.jar b/gradle/wrapper/gradle-wrapper.jar index 94336fcae912db8a11d55634156fa011f4686124..e708b1c023ec8b20f512888fe07c5bd3ff77bb8f 100644 GIT binary patch delta 50929 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 delta 48256 zcmY(KV{jlr8?Ce9#YA5-<#)J#`*Ro8i^ z&vRyA8tk?O3_?)`3>+;{$rU{w2Ne|!1myd75D*X{5JdiRFX4ZcM!cXLy76d#bH*t) z&MEf2)2-7tkpJ@zBKW^Y?42wa!T#^P_%-xz{~0h5{2M;z{~eKpQ;wD$0tAE+1_XpY zG2a9uQT`hmz+hr)vZHnh9O6p4s;<-~DDrUpoUlZTYh^n|Inb#y9ZniVtmDHfb(Th!dtVlw zI|D?(8)O&6?>k8li_oRG_Hb6zE0LEYdziBaR~UpTFzCeposa>%J}lDMvlvW^xP8%| z96Qx43ZfpncDxN`(58(>WGn1PirFD|9Oj=kO&DWpH$(F8@GGXe*S{EAiizC%;*6NV zV=P0=6_{R(Z^a;~&5pSSj+@MHUZt(lbxxMdvdQwB(p4VCmgWb&<*3$ZwbO}n*sF~j zEXzH!0ZM!A^K+Wkgb}#~hK&d2Qfu*Hb^1)5M7X~VtITjiDf26fxYo)V(Z}vYmj2@? zEJp_)Gqc!JW?1FsBbVzEQz4F$TsA{~L9Oy`VylzS(z0wJ-GOU`su0VaRkQJ-dfSoV zRV>@ws%(_%Y}S5x3Y#cGiuMCHhh(2QHoK(=v%KPBlvcfy&pH>DmBxCILxCY8Bs$&@ zz!YMqK$I#}zCu+eC}|6Uz8UAJ(nr6keiNekv@3^gPwjzwP33`kjm&P{6r{5fqz{(O zdDI!Hi`E&7`280Z0kSS+6 zGp!fDb())MX-vK6qW+!|rq1F$HlMF8aRqh`XRQ);(^13?68^Rhfjrd<#!mQRw*}VU z+|~r6_r$lbPMz;Rt=X{6|pOXdnBzaK~8X_q;a9a-Qc9=lb!a@Sz}gI| zZJL6Dj_^OCu=vV#n1t0`(yoYk(oKWo>)CA6dJqlN-|&@}IrM{jA_R{KfI}MYK26&N-|4KV*UljZzM zWR4m2h<{L#Uxs5;B6}NOwEW6!fSJ9Y^nEaw5ZPF+>xvlNTn(h&Aug9#edz+n`=O6!9M}l#Qn_XSR1#D zoPfz-}=i6t7_RTu#nA{scW)En-8N=)yVO` zKIzrLkrD!#=Ixqp^u2`F=i4yEZx@P_wB*wM`WM~*I^E^jA_~ID$7B{3c==(A_p{9I zY!~c*&k*&$?PbNuv>Oo=1Vr#(17ZDNQ-n^WS-}F5RrKspgwXiFl7`Hz9M$TUrR{9= zDjF7REq_pen-~krCR(E|lv2wYPPv7`1tuAo?k9GyilYL*1jap}%21@Ww?f<9|8PA| zw>w(^f8UG(y0t14R(SELL4r#+&P}AW&r$obVwjhUE7%lYUha5H%!8|yJ zv}pjFW|E7hDnIBJ10_5E;9tT%hFpiDIbJmM4d~T?HWEUi{>FEK-cY}DP`o;833Hj< z)uw?wQA2}PgY|5s4O6L+S-R7S;1Jn+M!$9mx-%H{LzCXt70}D;uUkd&%A9{!W}~bV z6o<3Xum76^?D~;431q6)JEVSttK3evuvY_Q59$Y)MfUJW0=r1PD~R8?s5L zrqX+tj?ZEm8crOm{dYRAa_F1L`lOhY@%gub5RKeCOLWm{>06huy)n3bffDml6Eb07 zLOZjvLODy6taD#Knpof#!bY)R8pj#2VMAMGalffKShg&C+nES0ye` zmNs^V=OkO(s^F>R1YG1{?WoqEi-9KEBjPVehD6sfnZhucI>%(XhVq^Ny?6e*buOTf zZJQB5Kw|L|^N=ZlY%OR*v=z_4epbya+R;Ipj`UcXaI3aHM~5LaoL;{N$e81US#sZDm?O=+;&-LrAEPWK4eyo87+Udn&iBS?7V)TZ8b&X zA9>p&UPyowas-zXvDst`C zK4_9OvbRtUqHrp*Dm3uW;B{aI?8OlV^=MMf=S#EV4Me}dlx@cQe}NZICy9m7sjJAy zYFUpngI#lwp~W3F^e5>omeay(nT=Yj^p{jI9jXH=%aF5-7qVLR<96qp8_8skCAL3` z`;x>}GGwjTi-(fbU3>9EY*|eciQQp{>bMUaN3O!w#)=Zrz`eHyU&pqn?H9wn=Y%$7 z+5$4Ry9eIipTtQJUGPq?xya(=gU9pT6;QWPBpQZwO|1DP`T-IPqovE-Ne+ggXbGd+Abv0gk7 zSC98$Y#IseEVwbyKKS9p(%pHqIPPA`CZz!WbD1x9iK`Ucdc8>tuG+z6(F|_%{37iM zYB~wUaq=aU(sOl%K%2sxmM@V>~Y3qLSlbT{WZBprPWfJ#pc*Pr6Oz zn;uyoBPz{gG)qW^e&%fM);2Msm*l2}tV1EbiLF|o{OeA19F=aY(wXxpx|A1ZtA3#LGK{qJs;JTIe)}a)K6v9?CP=eYx*4L~e0ZaH~4iFUNH%0;uOiN;)svxvFh z3=fhC4iFnT8%3w9VDuCgoWghB7lA3NWDcYgWysPRpLsqPNC-~s*b;*DAxe;J z4~&uK81`fs)mh}iptvcsCIA|L#DvndNowDyCiZi|UJsfy?UtQHw?@(KDkk7IY$f1( zsLwJZs#a%uZ^gx4vL5QoxQ+c3?;*dMHyR^Yv)SWov)n`VSWob6$n{8;$#lzJm{v4$ zVxom5E^?5n=giBHH%}Vs*COIIq8xz0)k)Ib zq@WMkv>2mq--&~w^Hj9$|3zMEHk&}qWffi+^%FfLoqWJ!ECG2bY8+Xnpu%08&0_6l zGcEY!HXu*Ka|GvblAN}MKQ z48MUx3+fW(3>`E233I*j7Xk4W#;LGWC8C6U6W94WinR{&I2ugp9ULir6xR^Lo;cxj z!TkIh@=i{~u#5B?%Rco58J!Qzj5c#klaHjXOhSK9xth1mC_At`U*j0QW-TQ>J=ewZ zOC%{bc_T%3^wstd?WaNNj#A>ctitdpSuOS8I+M{Na>NNzR_Cud-zm7d)(M`7QzxAZ zX~TG;D)X7vEW*gMoPi zocF2>n@N2#FBAZFPMBBW{R@8v+z6^ZXF3j{f?`Pij}r=Lti8aI->#$l(x>BOo-*uX zYB;y^)H#<^pxJj@JoKKj3rF^reDjOK! z%pcMpy}py-+sCrlmKw`WqC;?)AZPOzYS%aG$(ze+WOh88p9_AiuH~0yE-sxym!zf6 zK8>nOC;0)e7bnZP`ET>VY1)Us&XKjR@RvyP45vg)MjhQyHlx!pRIp)SzMGq5htCZ=K%;tQs&rQN2gRnGbdNK*G zsu}x4lQkxztYMt-!G`6iQJ$c%_VM0rd@9Elm3Rc;2WRq#+i?`w;u5+{?E>u33XS*%4Kcx>WN_v&68A9LL`jW3xZ9Cy1?bXS=0x zSDH>hN@c@P!+6PYt7@~wwUJuC*Q<@tj@Vr0o*eGS-HV) zI_lzluN?MCLQ>Dena=GCp5y!Ei0*XE2!IpVi&@*ILzmX92!hd~sp>=eP3*8c;*`~= z^<)Av{$tp&(=ba=kq>Vbv7$Bbuh$x*0n!JgB#-~SEhX2v1cc9rIyTBFm{{v2JTyR+CQsDs)7+BgnQZGI<^ z|BB-SPrSpX%F3!2mf(^C5n9w~pjeWr}Bq$hjaK%Mk65Ww@3Qku~IJ>1dzBZdZ zZ6o8vdq7Dtw|qA&<`{{|l2ezXkO~g4WVMKAZ)uy+AApU|a`JP(-MyhlD;Ia#cI=`F zL?A#WV+Hhs$}fs%XR14v#rLv@a-_{RYKp2rETlk&i23XOI4e$Wx?k?L z$U9po&Ch-~wW7IsA5{1$t0sORu-Oh)x)#@(uW9$_#AUWCWW}ms<(B?)s_mf^TfKKn z*Pe99Edzi8Go=K((&zTV%x=Kln4RvyKONM6FeW5fjWyxyrMom8#y1VaH>Pr3pyq3v zRQxSmQR)ajGtbr|e9oBg#s;@r$?0EvK-TTA@a6b}`^`tOxKj0`KfKG9vpyBNl)1eB;00-1EZD_dA~@~k2fy${S?^yGno>`PW`9~p zzvW&D_>U}qN;qDtT@y$khj|v_HhzZH*_oeaPIX7Mwq0AqsV6NrE4O`8Fi&N_0u5e#@!-olUmd1C^TXulTK;5uI zI;c3j!(U>h^-u41SzTHa!CfD7M7xV%ekBYK!Q#|TYzw0MHc{0MYNOod=lV;9Czj{Zrdq|sus*qPKs=Y! zGq&}7h~Y^VHkJa^9*WV3ubc!_wIUipjdtDU#6s>ke0J!>24w-2TVO}geFIhx33(^z zc3dX5As@hdpdg(EJx8^X@?@33D%JINXcK zB{nf&+G`sHxA>O1iZvB~ft58jAWOh2#FbkVM5tk6bdP2e7|Vjl-$%1&RlVUKC8)La z!5Nd2+=d1lbh62!nHG4#!xW+W6}ns znPL$L7e{^}_^-QOOMLzR*zwd}MFX9XARyt1^&~ui`i3*E2KE=e*8KV%x7+4mb;bs_ zl+IXqbrXcLDe8WkW1I<()nVFiXsMO?@UB~HjVg7=$!bMO=vL6;VD_Yz*?ImS*;W>1 z3A_F`;4HiYH<&l8nEGk{-=5vw$VXa($|d-{r`@~XpWnN;dOoh*0g#*T+w!}_Syp|4 zoRuj6qa|mmAleBVZ?+(w#bTdo$C)|WVq+PVGCk%Zb76`WygCa*#g#57ejTc++Wao- zfSh5a@lJ#js6kNaPa5c#GWLUnd5)c^iE7Q>RFoIy?u1^A+h(jqgZKD>Y7a<*l^b~Y z8S9r4!I9JO{DYHF=R%2@69q)XlN_{Dye>;XpP8lQY|`|u+k%Vb6Vy(mM&(v+B$xH7 z0?qQaI>Dv#ucnybAvk-o-o`Xn_X9(E3&}7P-N+px^q_LPu9q?q_aO%LD!(S)D z%61T!os8KGecDsenbx^3rTC{-q&9P54M$@7?PLKx%YBX(gAAkdgHvCPdXf@{)fwk}4LBs$P?mI(?ioI6<2o#Qx>kOM-q#4B zzquKsYD0Uy@8;cUdZq69jcn;@O8*NW((;~am#ytA;i|p0VYYBVf(3(kc%`kE5bRV) z=Y9R>v3F4Pi#R!`(;nk^c+!bz81nn>6MetN06P4P)k}+DfNPT34oO{DX(!u3n%`1k ze7%48<(oC$o8}`NpOkYk2g`gek?siHhI*d0bg|a-6uGmJHp1FZF@B}yB6}8~RIk+z z9Fv&&`*w=(0hPlHB=02^WRiQOe!l**p1ZhJZoc}3y68`m`` zRLEw99xL7o2TTsDuT_#7z10gbWhqJMjhZ?M<#d<6^VbSUTcof6jzs>H$ z;Xq-7q{6K~f*X_+W3XQlVsPex>IrXu_QF=vpxIhzfb4cXl0kFX+zeQvtvYJFu>HAS zG>LAo!gx0crC{!tJjo#yt)Iu)$ z>hE}y#Z;mbCxi~%xh=pf$*Q{*iNf^+zx|@H!$fVlc ziDaIN9LgV_r5}4N;~o5_Z3Mek5xjEeV0kCpqBAXsNM~z*zhwa1h(Ux1g9W-B?SI5! zpA1o-?qnc;2s80UCU%#OE(XJ+qI##Q4s3O87p-uqbb14M1+7nG$B$y6pFo>Xm zstGRjLDRX&L#jqE^yNz}^%KwK6LP%6*-usrQw;k;!k#`5>m=<#B6@e;3d`nXc)DSj>Hy=!Haw(5RvDJl_JG5wUbdu^!Ev1J zg?ImKq5=Z8EF8kx*5tBt$*ZBM=Y$j>7d4pv$^$V-VqzcYA|6?UjS|!~j4}u+cUaV( zmS00g@VN)}BPcC-Vj>KjF+rm6BWzLPY*F97`r`Rz23}A)#5dv);au=2&wcMfz*M4d z!M|Q(DxYUb`|xLdz_xViIv)Nw-4BAjoe^Psjhd(+^5$=QxV}33hzAgSpssuUG_LLC z35)4ga7v1@W8FY2yAY&S`KvN>%dqn>K zjos|0F>tScOd#YR6ZkJ6o~I@Sh~1*v7g+^i(4=)F=TR^%Wf;-I1HOejD1pY`p{1Lm z!wtvag+}9VV1xG(SoFHPc=Fzf7 zb~Xcsv-42L_2nBSD$9-kTF=ol94Uum@YUpUOZ?gx=5jQz$V$S6s_(+BbBW%;AOLG` zdwf27(|M%%7gWTXH{RqseLMME9;F?ZPorDYNEg2I%yECH4(nCcnU?XEWyptb<#?QA zhrSl0xB1xd8|6%uYFjB#3puex^Sr!Cn&Y-LpdDQ0o|^dv*L5rED>|{HL6?bILVJ-p zGyva-GAijYMl^$Y6{19bvD`_5sTrb4o1V0*G8g-;p!TBJI!N*gRkWWLy_RVtPd^p? zh6B8(U4>@bSbm7l5)O<57#hhiOKlrLYA?{ZMPLo6Dn0L~Ilcw_jqYN2L=pZ*+Fs$` z6znWkT(GywSMUoMpVB!48_wZt0!C?JJN%sC>K4@NFp`wSvM!rkCBkj4(r_y71-6&r zt6)1_P2K|A!nm=gKOg4tttDh_f2c7%C{ge(**y#+b+sU%CWP-uJH~Nyn~ArRdO|+2 z{TieS2{cDTq^ba1K|+4Was?ps+WLHO5rLI7w>USQtN=n?f>a8s_y$ckTt&wzRNX=t zW&=#4Qcy!iRH7T9N)aY5Mf7yxj1-BK`a)4AI#-Kuv^MYek1B0yZLGU*sk z4R;*wb*ODdK2x)kfHP_66$uNCxm%8AJ0I5EUD9 zQK-@l7X`#tXi~Rt#)hKFdfwJWaPt=ID`h3x$BrGDIK8%E=HBcl(saHgZ35bT2LKI! z;7o-FXs*hwr;pGO<}Epdf%*+PdghH9y1~Fo*GovzYYFC#@{Qf=8@}gD5${Kh=|d6b zPGVH|^$;T3hvK?Zs;=MR(AC|m38P=Ze(6hkK(6;Ktkj1LdQX4t(H$;&&(O8%2LYgX zBY_U~k|=of)OD4eUnBDV*6~EJ4$Q4AxR%*J3%VQB{$g}d708Dw^s*&ewI3p_k7xHE zM_@^*dq`s|lSm8^%nR#mw8`t@SzJm#QppxyYpm_CA%fM*f}$s(*+2;wtEvVie}oSN z%|UQZn>P<7VJhU{a$5~UJPj=jQJsgom=oe7h<|6DHHj8S0j(4<_aWm%0aii_#cxb? z2?;s&`>vkcdKxe0NSSbsun$xW{XYAQ6Yb8te1bkI^kN_uSx>UPbo0jh!qWQe;>-FL zDsJ1xL}-o4$V3IhGfS4RiGQxO5h!5!XvJ4raN4BJYcw!7-kc6k)bNY_8b{_3@V&KVPq{_DuxJ$rBjVf!O?6O^w&w{daDJChR_tqw|B-lGHc zlOGE`IbpqtkE@`KkXE$5XG+H1x$+%1-jO!ayfJrKq0eB|W7Qx1BUw(|(C%}{xqMVY zV>;|qIK1#_L!Cx{z5h#em{dU;;QYyvy8(GTA8*PEcTN$5gcr2%} zg}}!&zBxNcr&ItPOSKf&iw$3Ts|%0uM^!YP0&Ndn^K`!(__@|usH9#zVN~kLjKTJ3 z#13QSLf1AeX>S8IGAqq#Zy@?*r#B$$FG z-Lw5n$Qge;!O{pdh0n9A|S_-x+=Y-+)>%UWVj2{57E_h0lxv z)1L&xvY!zHpfQf8z=$M|(5whIBgqRp%FrZc$X{SkYAsX3t{P2?=S#A#GR3wr zPF`Gb4l=hkZZ1PzUC$peExr+!7FNEU)K z%LUSqnG7T;A1pt!&5;CTw5jS+)W!48S5qQ2dMgky{R|?NAQ^TbLg7LD!e~L2s~T#) z++)}ZiNE-fSTymhI815fNk6~p8lhPm4sT34p`=?ACYP}qwShKAb8%qKz1KM%EDVyole(~b?4Z}Ab z_W%^XnsKVrSXH5EL?XdNeDZgiwN|&&F((SP)Uee-ML~?7ZB(bS%vHI0$#Po^K9{Lm z&tWmUv1WVgpMc3N4c;)SGcKv!3hYfLF5OjCU;_u{$w^X1`>Mg{?Htz8>M|lSmPR$j zth2|#$pL5Utsve+yiuXs3_`=Ceq}3ky*;=Ay5mnk)YhNG$?QF^40pa&P_%)TfD%HN z2}BL#>Et7?W4Gc}Ck99SPZ+(~)Bc8=i0wYr@NuDv3@(pb>_*PO%gv>ODjv$?qqVM1 zzyiKfBXyt@gJZbxcb3IIG=XhJt`gQ3Wbg0v`1y~ug;@m86HfMd?#R~fJc6ZXKA6>` zsyYGnkrGu4eZqJVdR|6wBZzmj)9D*8-!unZ-;zEsvaX}LqOye7uz7g=d8&C-XU9cs zrBbX~A3$ZfVi`wW)msWTw&NYo5o2+lfRQLi-g1evJkR!*Y1fTqhhN{TZke+EH!k-- z0~uI<#%G=g+h9g#GcA{)=5~qQ`vl@{d7Asgvh32Ax$~vY)0B8$S^0_N=DK&^74MZ% zzxy2oFEH+m1Y>F_1)5`dIGQmqX+X`r>*ywTVqIUdwR)MSeKZu>%zs_)vG4wz0p7t8 z(vRy8Ir;Q~JR_uudJLU!9=jt%Pa?b4f6Vi<-t)7%#y|bDe951ooS)Q+knS2oE?k4a zU(tM0*yROz4GZ!1wavj&_q}Q|0zvRYU+E;U1_nv$IYk`NgZS9Pwem}(k{%pxALR30 zEJ4kx33@0Y%zAcI-oAH=kayqx1&Cu6t`zb~Anb5-sr%GWIsuqQDX!AyMFSeElQ+I- z>KE+^3Z<=z7j)r?5=D_DPwGj9{N_2`F;+ z*e~AEnQ^5g#c5y85UTp8-a#zmhu6msiv$^LF1$g;&s*ti&kz?_+GFNbb>~wpbwTv2y^(u~r2GXSfN6%%9 zeWUCZfp$}n+^`3~Ia>MX*-?8p#6@2%PA~D^y@jabw{t^f{}b%!ehFRV6RUo8wF8XJ zi_KH>O8~VlxBmpp+T&qe(GN&P>5iIBWg38B zqCHLGnXj=7IH6vo@pxU(tl33}(SNOiBmcH3MCGy6_<(r0QHgyE9@!WE5~ue)O1iL? zH+ajva9GOs=TlLghPVUDCv&W{lham#v=p5wlibOIa>sXkS7{;)<)~nu1>=8l4plj$ zUz@bl)}Ze&Xbbltcy4M|ZlJaG_4@Au|Ftb)*RT_dOi&Yp*}MLq>@Uv-B`*L40>Xg= z0z&ei4`{)4sKl(b??AT3t2?d+`rjP3d8)fM$4v?`xp|y(iUwsJt&AW}SgEU|jB$DE z5hf`x7dpA3@DUbc)^X*OhNP5cq?Y}LS|e&!`ucs=S97J1--@gq{>4?jyfa3cz12V176?DP=lz<$HpPA{wpw5hkx@Yn@fOUD z^E{QDXu@06Q<s6(&8nl9 zn7P|EDkv=@WP`++EA*5nw!`C~BZ=y6TA`Lt)X=`>j-jkG_LG%IuW&rGfC50%ey zg5g}vkv`HBE^t~>&n-@i=PA^O#IqAJnF7MBl7k+l*^P~Bv+J`+;+ai7JSi*pqe5yA zaB{tklX_;bHM?|8@z?Qy;SAt+8;t$a9AmOQpAI# zU>9wrRDV`H^#9={zrY=4PaOThYu0~fD}V?<C%?4L4J#j$l z0-Zw^VdQorg!oeW{Y3epHDFK#9muR%i9t&>{&TXc_gpN|Ku)UIzRqGgl#bTVs7sCS z{&CUMZL2t%w1l}P-`g)8+SX?MID@?mBAYlV4!?rl!sFfbOy-wz^1YGoxMfv5(5_Br zwo&zxBbu1gYFG{`Oc3QIUq|L(QlK?sXPZ-P?wA*WxTD*W7N!MvsVmL%EQ^L;d5Hb) z$~e<|njWQeNME1xEczDl4xn-z8#gzE*R^k#j(2k$XV@-=zphBQA53A7NuT06FaL~N zW>+v-S})F#{KDTd zBQ05V-aGS&i|$oOuOd*oL@&REA|^r_N{y;cZ9nu({p9StDT&Bvp4W>%{plB6;n~G$ zn`P=s(;}b>-zJ7L>r4(g`_`PQwId|9XwdCCX17LX*M84zTMpF+9HH5%^6cS6OYe3yFNBNMg&r2>dvx+Mx#1GXZujv@6%pjh^}uO$-z2oYGZruyph)G z0*BQXv7ITeU?hWITdM;Lt#>v8+Idd8iMkwM@tvNK^kX^LK?#m#kkZTqIYOM+v6Dmz zyoirXPAz%4to`@BUT|@M_1|Zl%b}|{dx33*!-5AzEF)^YP7mZckuhgWYLhXsL4<4x zn;#3~mKSXiMN!2kuMPXwWl?4enq4(fF;-Q(0dbLi!%K~A$F>d)2S#P%*i`x1S+tFs z{GHY~iIL}8N(&36gUQS__^I<2w-GQl5?OG3X1Wq3%<7Ptl|?T=o71;SkuX~Sri+nE z^Qrw1ejqi~&481j`lIg_JLp?Ij`xuECPhM<-opU`Q^03Z7RCV<3Zk(lZ-no@V^mlv z6HU&*w_8wzw^g2T!je+z3j||>{36%I-@&IJJno@CqJEGAo58+=o|^l00dqkf;O+?u zyJ4K+$WbV@T1vg&*6|DEzIw5aXct@H4h~@t9?`R)yhF<_erWs@ejqPW+gxhV>4Z}# zWvb?(X}>eDpY}ZhjJjsDADYDucbY+2YcFDnjj0Gb zR{(Z^FqY(m`ufOdzxg8~-iGv}=L_`zH)QY49&H)^{lH^N3j#v)zq&U3zrZb&q3RL- z*O&8wUJR5lQ7@B%sVNFO3K~4IBr7->9GIGqlzu`W?(H9ZGV97_%__ZRwK?wdejzng zlpmnW{5hXoe&wm(F50T>HuHUyg{(Acwo}K|!a!KY1srQ@)8K8`qPVuQVhsIVE zHoE)8#Jplp3QHatp{3rQkTZ)ODXHQ&wv2=m&ZZ@*8SOZPC&l$XQK_*fp87NgsE7BW zR^vtKJFyd<{=?`5`enCL4JPra6pqD{xtDt?MYSkSm=oH~sUf#003u`Z-$h&fVK#mJ zY1&S#>P3&_RC6%QW%mQ4yVe{4PKuX0LfdPJ$GUUJ*E3(@4iUDfaMq80mtEZ^d=%aP?fj&W-s#>e3-Qt6+BEQ59m;@@Ju=dN5v#GNp{mhtH z?BPX;(Gp+PwgNvW31u{Kf+CfZGf%QIRU=zhokwHC2{0cUE}NS-7MH15B$4;RA;BH! z3!Cd@rC1mqhX{A=n>W^+G9zMA#Y7uDV8++X=!OavPpf|H^PsEi)5ZFpVfOfFPS>*f z9XFySK^BPyK=1%2{cizHV$qBvE^60SCD@@!cQ5>QEcS zVuo0|L9P3YeR;p%mLT&o)KVsW$Zj84vg@RC{@RhYY*6x_f$1X`-`FrQ_vOW@TbITd zz%U8}U_s@~CleB*3m!JnV#Xb0HbHe4z8fVIL%QpA)+@>K*-ZI(=;+}#*=s_ou*a>V z{eZs~S@Lm}M$sCH6uy%ne-~^?psu^nmVG+B^$=>49OC9HOQsxmt2`+VKB9&8f{x2{9`>-Xx?!hyESP~@9<{CJZP^;2 zf!x*igbXK3YOal5T_+%8+P)YS0$QK8%G+7P(Ucs(mcmRqxnXX~PR9}r$>TFz6(YGQ zy;ddM^#cVSJEfSNGw{3nuLb4M*=&lH;<+&J{nuN;*^ohc*}(Uoap;YqGIUa}XPZgX zWvIzUc~QeUL|+f|`aI@z5kVlOJ)cSd0d#QG4?N|Oa7os^kP7|Pf{Fm71im}oLHw|4 zn4tK@A8v<7|Da90W;1bJ1MXxVbstBDklSk6&_2!DFEAg^^UOZ$#h@`n{X{0~USw9U z*fDg(T>M|G!{#oHE>~@nb?A07)RNGI5;8~&G^Sz!cuk2B#QQ2zL^AWomER!;iE zimB<68wA7xp$(i8il%35Nl_yT>CD09G$xR;B@?6w+FI2rMd>tCO+QstAk>acGewh` zd`qm0$nvZ}PuobLlJrH$jpPIX)+&*ZJhCcm(8?D{!|Ff$yebH}URa^AtRLph^4G)6 zGIf)D#;&D23Mh-0q{r$AD`jQ&Jil^QIkZ~N9_X%C&P3iMOZl2KN`d(eZa(SQvj^Yb zf~EJTKH2N#BBfJ4^hktCeKesp3unS_`SJpJaySOH_wXM!+4hH-tle4w|IfKs_3es# zyH51*k6qd5T$f1Ck--`rk#ivT;!Ec zb6O|Qx+wv+=2|=Eiuj)&GUv-i+9!OS8sJZH(>+JovZaJcVc>tT6h%Ms?IrxD5${R4 z^(1Dm3qR7P--*zFszYey=?|FzMRU2~A>v>#)|_6#9>Q%H>=}-L!l>mv2QIEGkZl$6 znSyK`U-V}Ot1g35;d|v9KhB-bR7mjfgTlCGm%?4EC@H69^DFTgd!Lz(wqyT11?6&I zi-ENvKm@rb8Z1FoA{6ryO(iKK%CZ_JoXYvfK1y8JZ@^ycfGIvz&q5Ak_~VSNoUmA< z91yk@=ETPMROST66ZoC_@Xv4Hf7gEzX6x(o+@nv) z?Jc85IvlojGPm;&ysq;5>z8NlFCp<65sQZq&4yM6Bzcd#v>8~*WhmMJuQa`eB=;qb zP!cLtyhe-Z#n)J$M8Vg@Y2dggPkrvS);LOpWyPZH#R3?udCHh(yxRd^mYM(Pf-)$7 zlRHU$r7-o0FYxH49kb)R_>uiZyfN(KOq~)%%qJ`ya2s$Z$-A1Ti}^^cOQMzcrt_Ot z6)+*wK2LSHtr)I7``{J`;_YO$#9?A0>Df#h+RIaFQ^`}pUKJ;`4X+%kmx!X>L!hPE zJJKd&=K`XXssb&-dy}rcNSiK|AL5F4s%PCD!hm+a&rS@ z6<-`*l;v^!k7?6{BK{u+Oi@Z*t}R6p`Ru%W+a-+Qzxk1`d@Bm;Oc&L;f#H?&4=#I& zU0#n~iQCL9WI()_<7(7?Q3^~^T2|#>)wWUs;L3U3a^zWj3n2L&Yw-~0sm(ObN~RLN z8u6X>|9AlsMtw8T+ezRDW6$%(@Qr@vygqEmp_vci4WaZO zS)15H`V$?#sKW;m9X%7}OIOT3{Y#myc-yySbPa`ae0Jw_8KKtrHqB(SP7-PxA)F8< zV87ceIVq5nDTtt!%}pOF@Uu5>pGX%Gq14<1Z&YBgG8(mIh3Ki-+|Q4^EV7jqD@9c) ztxj%wEA9r|LchCn1MVD~W@*DrfVQFR9h#D(mbvh%&GEvjAtPB1mLWb}*Hq#-`FShX z>yet9QzN~_yGk+vfgY*yd$VSn>2F*$KwD8Gm%n%UA=y^^&Y1<7B(|`=cWu9HR*Z04 zCBrGxg1BYGOGv69v9jHlv=zU#iU9+9m|jIU-@@8Xgzww63z1lH4;>u@+ZN`2A9e|G z%s;X_-jTe9qX^TC9>s{R(s(o{VXMSfcKGZ$b%q&6FPY*=)MxqYPYl7pk((NbhdJV@*?_4K<$s-zf9yyh;=cp#9K}jCu+e z#q>+n;e-sP^$b*YVMg@ozT{%n_Y7ii=``D(x;1NZe(#goBtmPX)KBnZgzDB@d*3a{ z*^{Xfvg{Rt85O8TRt?`DB+5>9qMdAKme$2SBu??M)A`QfXB{u&1=mV3fNm+%bbLqi zxg)JQU(M(#l*zUE@9$T!H?I6doO7{^r+JqF@^{O}54fTVE^*y~Z;vTf53bHKD9*51 z(`fME?(Xg$+}+*XWpEhWeX!sT!9BRUySo#DyM<-$(xC=|XOsbS>A*xS?coy<|*BPbsh z^19O+e4{bU6iFBB{+`X4Pk&11%!TIXSWsDSM-W$N$KtwB>%1NXTG>aeDd!UQ12P?V zYPYdiJuBWaUKXP^hY@l#tg}w=T9XK#(gKe78f(f_hJ>{E<1&vX0fs9NDoHa(qtKwD z-yU5mi;8BleMhV7-*3}x<8^ZN6K1+jBs19}+x;%}XYQ{qii_kL{nsuyroAB_?rb2- znig0q{W9g_jGD&=^g15jnmjT|fTk`q^$f)#)=DsIRejQ`6-6@Y$ReDx z^@~t0P^T2SQWMsK9#A)!g^e_#4jKFjg|eY>#>$F2V5AlcV;rCW1@2_248^Di(RMh| zV7uMLDR+cWHw=e-JsbMdu>zc}aCF69*!c^0m_a^d?W@7jxBw!DqMaWKKu>T**0%P# zsp`2cyse@+kGM;VxJz=pJ5HqjA4P93UW!dXlrZ0V-B4#&f77?6#!;?dz{Jss5hXQgr*BXn5#$Rd~=~y+nn*xu06- zSRJPV_B(K(vY^?H28di<26jOZs}v|hT_i!Ie?oP1BUYaHICqfm$&-ByXVFhya6!%L z3g<#=IDv-u2$p%uNnfJndn_^uJ3~G;7e-~V-NES-OM0)b5h^MKS!Co7ps6Dxq<8E5*%bmK!=XxwQ1>`+aW^?b#FAbslYu%1A z_to66L16q_EYX~!u0y{=?Kw+Js7~o(#X6{GP!aW>wwUJgILDHg*0}fxkylolqi7ID zL%C<6^Pq`m8)6V|BJA7RfJc>)pj{1^r|acoENjWpj2SAhE91PlC)AnbB@DUPWyH1w zpe~jFW7ADy0d_8NU|cYwd{(2ZIY^uQHXF&|AgnLIm@^R?{2hHMNw6L-4PY*u{NVWn zBWXVHg9(0x3~WK)^Tl3Vi@JU%3Gf)meWV*|>6O;%lgTUE5h=7HOZv$D2WCITk(nDI z;}d9u+w}t&8ZCE*@rwR|i`RzZ`zZ<>+QhWIFJ!y%2huiQ74^_IBTEMQ$o%wTI(_pU zAEX~WID;@$Qr&s(5i3gP^pPk6THn*nf#Zd=F^$cgWknv_-LH?~b=4d}{>8tyB+KGH zkQ1;GpT_04x#)7YM*VR-o?!>yXsW#O(1w-qMT3!Y zzRl{51J%OJkx4thW5YKbA_)fps8_LL@(jv5?b+JHhvL19ViL>ZnUuM7IDGJ88$z;^ z4-$C^H@J8QA?pFQ+%g`4-tfslyvV$u7(oPszfz-q-+9k)Gru9hMzIGvLU??{Y=fgi z?z$(t5%91lZI?V@KsKuRWGGzG3&KKvjNM=&0cTGki9VnM&Bt~q(Ar*QNU*Kin?Uko z^KmWE+%nIYvRwhGEx+MF(d9@w4AxXAZqSFgEW7KYU=?{gLa0e#n2KBntib zxJyF2Wg9gU$dUY%Yz6EsYQJXuLr_2#cYF&Kf|eYmqdb&5YZS-oNDI_8u6yyc7o2YHw2~=P7O0!)KLKCL`I?!y)zO{*w~EPnBXvDE0n+vt z0-oCg9~{P5m5P|oEm6iO-ioQ>qtDSMq+) zQqIF)zkjUjN~Bve$~Pa#8dvFwQ$Z=L5Z1D2=sXBvNR>&DXdpi!O-!!u8Gl$jDuD7X z>9>rBF5+)*-<6p>(FJD*m^`Q>YkFyunlzOo1uoB+9Jb(xq$PrPwjrWcDXjm>(1;z_ zYp53A(ggap8TGr!%}y|-5AIIp1AIe}@FD=0d3$wl*WZzMi_jwE(1XUSqw6NiE`A&; zx*WB%L1YIB(4Z5Xw2+5_213wH4fWv9q|WS&;@ZofS57Rg`ZSAg=$xl9Vz(N4%Tb^P+t+LoLy=oPMS)s}Q# znC69HyyRXDMFX3n3By3QpesTR&Xfg*S3W=Rw|aKG}6$52RKrFm{A#~$c@5v z^3S;u3wbLx&DSN)@m|rN|B!UR+b%M9;uY z2lNL`Jh|Whf{AwA6Sot@D10E=w5#FIXdAA*(lhvnX$2VggBDObgBEZL0 z0u*tEtaWQna^DD|ZRI;Zq;ED#IKYLB1PPIvT6ogEcj088s{ToP{%Bm0wRqlcRn=?wU zWmOiX)t=S^jV-?(M=v&IZZ!PT=DheVnaO6oN#V(z+JUUCAgp0rJ8iI?^Kt^*_CoK~*^G16cIv~;K-C|KgDvSq#Anl{gKscM8CszG3rhynPR~h} zR>ZOR=_HxIpJwkgURSb@j!G~a{HjAZfR$Ks%sAS00|GH5Q*tgaPi@F|D?xz@)ZYoDUV6lrf!8zv6VQ=a(wv7u|f!276Fg@w^?> zqdA$MvpSXjUYXQiTbA&2zjjc8*+z4YT3a`yhsVpbfh{NLtVoZ=HGsgKp0A>ASr3EQ zs_ROnV{W}Ip|@1&vwsIxulZsJaE*5Aw%n!P&+}0Z&w?)P0_U%tH^Nou&Unq{CvhpI zMDohi*_Ov!&g@Ire2vtETicJM0bB-zTKTghHG-ODTr07K#CghNVI=*XMYUU_rxL%F zy^=EQHdbjiIZC+*2k6?8khL9qF}_L5u*U|ldYSxv%Be@BZsq}|3sJzM?Md((Rh}C- z;4wF#sdpBWh;|%IW@Ul?4VbC-po7b>BTr+GKW36>~eUQtViPQ0T zKF#bfbg8nCCAtT;sE3YcndB4R=TC>5#RMyNtRS;5HT;numnCNQD&GXBrS4Dz`W?Kb zxP6ag0&Qn}bU59m^>db&K4xoth=a-i{;J8pkARVLZA)Mb{#a&9bdTM01cfn%Qv(_0 z-HBOMO@>Z%YBj#*9@g04HdE+e6+e52&z82^qr=o&SimQL=a2vav4D2b$oHlmm*0Q+ z4v_3V@*8GLfDjh-`QbZrM^BaVxl}~P(JTT}QG_~y&*gTRvkp8f{hJK;R$FzGzI0p>h zhW#Ot)zsX{O-Yjc2o(VI7sb&3jG?6)p+9O$4su(ZWGD(KDX3V^Hr|<&)Te)=kHKeF z!kPoo#5AC+&<4inL{A|3mD7(jTBFkl#nURSk7O(J8P}%^_Q-vF>FnJf-)ocx83=HV* z^_)r^7e&yH93D#F4-#&I zNR6K+QRaL+oLzZ;NOo!50}$1nuRJVa>W@xoEh|22>|QX`{t>NLjyT31@aUeo!GM5U zN{0)BSOLWOpQQKuY(kRnn!{G#?*x1^Zy~S@oFr}kO4S`U0ApQY$19=})Xdt3U-^_| z&j3_KW%M{+2U!6W$1A8}qdj>u!S zjOL@lU%#uX9euMe?Y8F=*v$ysE0m1Dm^xo|UF5ys zZ{G$E=sRQMh@dEYK)U+`E zamnzI5{Um;)K-ty>}RaUuB4RK!?dM=lBJ34S{37=k{aMW8;knk^cYa9lry~=(GB=3 zU&j7O`Q4&a$fHzvjIVh|D2fzrj_+sHR|eZL^u2JZ?n>_Y{5VhoQ`*x7+saVBb_GMq zfHg)_gWm^#E_USugJyTVi3Vm*(Mi)}s9oEFF=kww8O9^1W`j&w!7xuK-9us*(%^ldh0O1h zrjl5u932@(_S&^@{qz(=YKKFpZ`6$Zm@;eYu968=>$+T(8%cvc({oyu_Av+}vu;+L zAj>RL_hR?5WjbdTb;OlAvI9xUgh$MD?~zgQ(k6zd7bMWiY%^w%F(#L#<(=Z3c!sfY zj)kwik3HirE5ZRb8{nP(^2(WXquLARmU{(nreS+AHDMuM>;Oau-E;zPdo^zwVt`Z& zL8Cxs^q)HDOu0yaB;(ghmL$=0Ip4xOX5=cIR~~xuc@#PssUVEESGx6>Dwp@`pG!_} z8+a(%Z3sq`OIxZi9;#MW%cnIdmY*8i5U~Ec2j_hl0trX&1f+iWg15*tF?E|2`z*OA z)*E~$RcUf}4B-|15NDej2~0tP$X{Z2Hx8Iwu5<)v9Yu-;uzxq;{kWX?hNBHlHr0G9 z)x60Yt2Q7ahV3^RI|y@#YK{2rG&hxT|uSS#Ou>$2Jrl`<&cW}+pq7bk5ItHEd42%&40Zp7{^?J9zetD}gtLyZt3al|PnjKkF zIwgR8)n5qE<#z533B!Nl`sUa#Cgg)^xobiI7$J!_!2rNAozI3rM@OmLmhk);2g(@O-WX3$~m-O z{75+JiQ$5t**PFJgl2ZG*p+}TBf-e-hWw<3wramDl<8X)#_17LI&j=KDvW5nWOyY0 z&zr=h96n6a*RtTtH&Bf=Kk#$I>W@es7`Q}rbW?=0Ds-NVS9$a=)AAqt_^x4%1hiVN zo=byDB~fuv%Eo40o-*;EF4?BWhtdXtc}C)vc+=etl@U zn{)Kg2Q{KNmfF1F`vaM0(#CH$*mE~i=pUY(mxDRz{MJv`TK{ok3TWJEpY0efojPmX z#B5sqq(6F$?8@|o&|*Dz{5>ZZ0UIZzi)-~`P6n5mW3GGK72bg?IV zrV0Ke4TK`|Ba=W4@ZD|fKM9>dFoJz&!8xJkS1c18XTM!|MP?BsJ|n9*F*6tp;Xxf7 za|(KATXPv4izky*$z;=!SLFzU8@Jsf8JAD8Y7MU3M+*_C9eTKu_7@~hLkUK3dDj<+ zvlHzU-9p{2o&f@q+JDHvtdZF`enTG~U}6oD(!JIUKW{Aniy9|kmrW##(+U)~NMy6Q z2Pb(SxQ=n671?JS?L<3l!J}XbVMs1z1EZk-VVOcA#x|Oab{LOmF8$40K9d^qhbx4+ zCR}o&NG`pItZiZ_VuNgEGdPJixTW86==dUB~qu$9r$Y&<<+I`FxqwHwoN>HtsvJ5M*%_l+0c6r>Z9 zERP{O=ib{_Zo;+in>~2}SiM;9a)WjfolK!p6zY2qWZNX9kqc;0ok>dDK#Kh-(oTs% zJ<3ibr*!2Qb~LQrrbtg|?a+nh!52j$qN6IXxyblu=0>h{^*&d-c}|d}%T}GVNL+UH&h` zd^4kpi4bK)`Ad9(Q_>n5^3v~@_*)GQZ`QWuTD`YPmxtE2b-?^eAljVRuRzdkc&-+b zni>K`+FAv+0^>%m`;5#-JK733qulGtT6X64wC{eo%z2xOgJ^F!(N>0a9!rY6rh~8v zjd%M>z-lf(V{TzVMrLl2+`~b;h--X>ja!f9Y&re{M2qA^pHuiMKve5QcgCKS9ls$~f&Vpl1v8`H6 znz7+%L>_Z%2rMb?)qdBCH6f1KsXp3M333DY4NiCqA@BYrU>V6iy?K2B9WH_fF zbtV1JVrn^2-S}HwjZ*!_QJAeZzqzIaxW`JeZmNBF2{Td7F1%zPchxi)i2b=wY8&w- zS6Cf43ZKJQ-8->A$LkZ8{x*c|j>!SC-C8Cc7z64^^!DIG86kzzR|DhPCg1)XeW7T=UQo=~4l6=cyaJWwn1XuHEzcY54svx9C(Q3ALiv z?BeWC7)j%vMZ*vu{*f*DhufNq|G4H6i*A+mmT0TSx2)BqL9rV%q_v=IFvygnhc_pW zL7Bbnk&CLjUakqWhVJQdaBIPr+fo`P=~gWKh|aOu0q&Ye54$~6J=`QuK@MgAQuyWg z3r?DcPeOJ#$wif_A;7`JpQ31it1JukfkI+%;g0jUnth1GFqCV_-BbW@jQMZdwRsL$T3n#juA&)xPxd2W?uYEUr_bZ>xqu$49nm+YnE=NA z%@!NN<7tPf#R(fj=?33fxorQYb8)2Vz+rFLfxB|N_^`?olng0nukW00C{_%>)&M+* zVSw~J%|`k)8bUi3B-1XGcuZR46xltG=46ov4+C^=U+~@^?LTOTybPU_{ia836^yt5 z4oKGi$Rb<^A|1Gq*pwl9js-|B{h z^vzgX)~)O=8Uf2|uWr_V8aM0uJjAlMX1O9(kM4?rPzn32;)F2n#;kE!qnVudO0Mi_ z^F3#hua&rcT+wG9g_|-iJ3+p6=xVEB5%pP@SCpZGJTV>D7(>D~Z7e^4Zx%eE18H(r zr^779)vHOt&HISI8uZ%{H9kobZBfa|;v-wJgCo=DX?q?yT&$e|#{kpPGLOMlq~g?Uy8mSC6{S3m<;$Dn(%>=QUBXr4?zR{5}w(DaN)#555-A z6^|uV=m5*HjMM{gwyp31LokD#y%rd_jKVMwoH7T}2JTwTR&^b723p1^|4?GSDl5UK zu-P>i1%q@Rh<>60uX)(=NXYaWY>74^#vnZ(htV5XMS5~hNFHuBCBdr;ZOg?VS-BFU zkZRtkDu@-=bm3(PWe`D=-!ijUP0!Hk@AZz%d24xi7JX@Pv9>fQ7Ky zMMFqZ_|?bR)&*h8-egp9#2~fVFK+~abOZsSL}R*b=W-MI_G5ekJ$FLnsUg1epq2p_ z} z5zbY+7w{wH^u7ytgi|*%wyMm)1XXTL?=b4i#(F4=xCdSdVw(^7J`XNh(UOD~AYDow zxk7&P=cuWofrZ$WC9l|Ewt{-xlrDFw10pVnzT5_JlA?wrBSQy()m+a*`4Fotdx+H! zQ6O!8MAnate#_RcAEc$q))jqPCJvrB=G76gGHm%d^ql|0uBz!e)(# zzSPbM{e7${+r62u4~fPwyht`wkJ0PdG9h0+#o<37OU|8FwIggm&|e!&zR1dwn9 zCdki=3Am+&uYvNpWey6nK%hWFDZorz3@sLSkh3eGDOns2M^=Egq4#Li=@(s%>%d2R z6@I?t?S5+R7QZ17^nVndFIsNPN~E$crX4vv44BMG*qPk?nYHuza>NaGwWkLs)=Fur z(of=eXCl*2=tr@~H1GGuYP1DP>}v?cta>y?0_NTCs+qqy_aNlST$^+u;0xmPp7=G6 zMZk~|xxPq|b)(b|p=2*0ZT+;m9@#%f>@WPeg7eDOUQnI#>75 z1|(IVjsN*wOD^6K4-vB7%TkM1Syf_)rnn)#1RvUz@Ud=tnLvWs);oNT%c{lp3=p?f zVPk(D)*z8sR1Y%F%CDwPQ)u-f38wU%V!3e**ylPgRXnI6C3jS*4h!5%gNdtT+o9mp zLy%mXi}__y!htVbUpAR4FAE{3mi*W>00fk1FQ?H_$~8J*tF{_&_`gy}w99B@q80K` zc}iCCn*F{Rj)@nc<7}8@o|bVBsm4C3bNBPEX=#}DHu0goE56oWR#_BGc7BL_P96_c zX3$Wt4%Ztr8~4^^#)&>Se(%tVca1RKw{qWe90}APTiUEC1>(tS@w9liS`D+*6DQQ5@4;fnRzyZg3hxC^c zDt`h1-_|2#{NVarn9HjkE7U*KKCh*P=WiFP9BK|^EDz|b2~F1~p~LxdvBnskjt1Yd zN1%V8c-c9h+`J0(S?zlxfB+?w`;QBLtf12f^{rne$OevpB!T z*n~>2>VW(AlS8!zlGbu&WoePQNL7kbTKII@?+BqzphQ73{ml?>peRQils_nxDVn}j z+!vg5vk0T};Pv;?wG+bC{Eqx_4HJ4TvKGGgZVGOpzS|x7dst%RIgp%k-~SON{9kbq zJ`+c{&SYCb*ILgHmSdZt0k^PN7q@wJvX`&r81dZPWRG9p|AZ+T8JxpB&*otN`!5fk z|F&=NZ$$Qw0SCuu%nC39|Nk@qAuEwS5Wh44vq4CK%s?5>1x<{9hdgO!F%&px)RST~ z@e0lx9P%;)D5XuffyFX#%F6ajs5C7}7UA>WrFUrxo{acdC1t%|JL+YXOt0AO=QF2g zv>&-uqqpj=?UC*~3mrQjmt8yl(^p?G1R?O`MgbPz#c((b#gAtv7|E*|8rwxiyTWTS zB1x1F5r|Y9BPBU3io?e=(MmP|ThM&iOjA`==PGh2=4XV7z#bX=Y#Jq{B2WW&b-wQ+ zHvHw~BAw{wEjMF4FS%Xi6EJ+gpFMjSo>uMmm~`Y~zZ~q@n!1Z& zb89lmRFcu~B<5XXdoxKvPo~lIBn5kECRdaB_$-LLZAgMMi)f*7y_j(D7+==TTTSj) zT3Q+k&U|A#Cj%+oT_|xghguGIQ{Of&+`lA!UGx&NNpTk!L-w*EZV{ez)i~Ux#i8{z zMBrhzyPr=&R_oO4w`Nx=+UIKMoTZ&d_x{voH*cBKD#Yn|eyBf3bNOzSr3{<^3;n5$ znif9CF)uYy(;->Qf=l4x12Yd?5IE9 zVs`{8?r1bhMCnDjYnrD%g#zo4&B;1*&Qhitf6$Ls(cg%*TN=t-CD=;{SB8uM%fRe) zMrF*u{d$Z3y!|rGb-gt3TqcdNzcD*QF5p|Dq-s~&N_Gu8M?}=Fg{Enq!H8w8YaPR5 z6EOT@l~&u??lTPY0}7E2^NnG0RaoMcFey;XRAy4I+7aLlhckk6N|29yQ;8i9LW5_n z+pa%E`_i9f`&P*A)5!wY)VsQzrvopofX5Vq@~i>MWs*#uz18=G@Z{UEGgZxkK%2SgOjVI==brFU?7 zL}biDMYD7)LgN~g{5Qe+11}qA8_qB;{tz)lJro5R-;f}t%?_{S7AAoFGX@AtLe>QR z7(q|`R2jy#sT)W zEvk}ceKt(7iu!5_hobDDNfPM2uag^jH%QX&75|O%i%^@m!xp&tPU%-#u@bjV_QEsea+0#b)rk zTZ$5@C9~(?&$MT}&~(Tbfgq0s!Lz;1eW+yTDyGp2ACeEQ9v_ksmwxcJDXcXs;-XX^ zYkaeZbzn#`%2kB6AU?JxMZ+=b^17u|G01YCwD4%Z$}F`n7kaIciy)uO(3~|KcQ>(2 z`$O@W*0sEWbM{ujb9}frwyX^McwdGL8nU9uE|0K(Ryg}NCQIT4bbvs#s z>0NXrDAH0*>06Fz9^;Yh_~yoV@aa9z#1GFsr}h&nHPv%mr3K(R;owJ$tABL_)SsRL6uTqg@p) ziYvHQaJ7qo%W@CH@&g8V^((TZN@ld8Jqb3u9pqX*lFXv4aTg(2PYTD1hu0Rf`ujR-q2H2-J zcgpp<7r9yJmrOwZ)=~@2Ksg>xD{N{|W^mPr$~zf~1{3XE$aE+zcKZt}6M-T7N0oq? z^9$L0NXe?sobB=ZGe2V)@3QyKzO6bPI+fdvo&J{}5ZZsAc?}HycPfxzVCNvA2zelb zJpx8(wC7;-EJ9aQphS~;n{36r|?4P_l`W}{#@9%dH_<^wVWPB)&MU-TP=q9Ktn*d{sC#YCBoRj1?GN?f) zdH4*pyA#c6Fi2TSvhwiH^FGXAg9w!fm7{$1a4 zy{!XL@J1`VYKF#VPCA{7>Q+qhpKa*z3H)eC-qKEKnN%`aUO|M!;hHYN`Xfcabw2dSHJHv~M246v zdC3}SQ(bIzgd2vP)FEpXY6YB(a@2S34`TvvRGc(1>{X-2N;E&MO(zMDYLD+!=2mym zt5(7EABoET0`r^o7^!XskO(8a9SP`Acns{7vE_Yq37gdx-Bm2HxxW_hqQ)A&#-ZF_ ztmQ}G$jY1u{{+5jxSOJC%c@(ca?xYQsaqOMp zSRGG09S2@P;IO(8aIlKDio0h{ddz~V5_ndkw(DYW$l$f;w<1j;-WjomAd~qcg`j{# z5;v=k17vfQ9naYR*^GERGO{TC>YLGiP2sWscS`8lfd(PRpaK_^F-AUr5Uy zK?weVkWx?>$%^U+J0^~9j%t{p-@;e1Rect{FLmAVEQ*#YjxHQXJnrSFCAB39Kg@9^ zc(UmRJjwQ*ariIqErB$S@{GmAVRdGi_GlXtUh-<#g{u92p!@mtkmo!KjoQC$|!X+x!h| zkkC@yQrIS?rXMPyecPvF25=bDuI5=y;kXtttz!v`m>ExI2=I-iis&HYU~DKKGo_37 zg^n$j&g~;WIZ4#u_tS3+Zf<-&}iJ0c8 zLx0>~N(E~QNg;294!0zdZ#XXydS^pG$e7{+1t@{@z}-ldWwE7IrMn|1NPT##bU^9{ z^s29<8X$Ii7#m9|)g@i?YMJSYekrkS|J$S+wRRVfdto+hv4AR2n1zR;4<{L7O3Q_%8q`Gfk!&%fQdbho z!0jC-B)UVEV-ry<5Bhg5zf%Z&`+jj>a~K$f#P)OYKEdPZa?5unSJ1Z^`0wo;0Sp(1 zEj)=|B##mo^^ih8jdVXc*20fq5MGnA>ZXqxt;QAj`<%^uGtt=%EKgQDJ!ymyH)J(Y zIT3Z(3QZ_o+5FU#2q$ipVZdvl9aZAC2)RruR5=obK$Ev>*hwI> zTMcX&b>lnxh%j!rHuE{oVc}8}CmOQWv2?@?qA(P68Eb_x)RpXWFe!k+^<|$KGo_Al zFE_aMnp12sK^uB!S1-KEsg(b?#YT{;L;C*SL=Ar0G`on7o#MMvovBt9V9UKmXzm`E zMl#(ZDye5Gvoy;5hnAI(cP=B_1oon`MLD3{E*?rj1e$NgD{n9PDs35gZC3gTjwqc1 zcr#TY&K%g8LZ6_aCk%U97d3fPE4al4Y$Kv2n29p!Dw|(CFGI)V70ZWfbSF~U{Ut2{PTUF%_9Stt7=&7zI#M4MUo%$7#RHt?g2a<9@nE0 zyh!cPQWUEtFKAbsuc{Q6YeAUym11w!8Xz}VzV!q4h~PfHm^^>t{$q9pjYLJ$2sV=4 z^O+T(FkdYq{McQ}{bzVJcls?3a*^(4kQrq^>hL>+@SJw<+r8k}$*T8#y*Cta4chNV z3u-1gFjmFBRj{JP-0T_lL|5grAMCY!$&)kj0=GhzWDV%Mfb>!4P#mTyXfHQN z+_@17fNI7N;nEUHp(hz{&_@N-1MJQC_CD^OXAENW9e3IMfrB+gaG{_*#+d{4BX*fA zTuO!kpNl*+`!}6o#rOT}I-qYcf2HdGTNMI+2(V1FMjhl%7@ERip9*Abbeyt{`li?I z<|;48)kh-#GN9y&I9u}zXJECZ7XMdeC>d-xgKLY52L{wMf&_9fn}KNF$riVBc|7|1)Xu`*-%Lew~81Ux`EVzmtYqGBr@aY2gQo|G8f)+;=1!{Cs6y*@Bls#c}Wg zbxagET2*-IUp_k&8+Aj?mCb55TF=OB&a`MSgFk_xG{lW98tSUBXfRik)7{?ePMvQr zZxIP#TsI^L=$?%kb8_%c_YIDP#RC@T8t9zpPq_1X^QnDYVukA4X3{O4LB<&u(po?P zV#3GJ^&`OuvatA-lW8I?)vE(zHZMy5@FT1ziH(P_^NAlsF^>7g{Px}vQu;T&YKWQ} zfG}I$%_nF|feSBNYh+Afp8iYzd8)spo-ply$&a{>yrhEeH^Z0N!Fl+%DJ+1HZ9Ox+G}J3dUY`%&g`*|%Djy3yNnS} zR*io|=2f)JEe>#RFXAr$gPuw}8!wm$Nm}lCC<~Via{p^2wvoBmsi3}A!>#InBX0{B zigLy08xzG!XIL%QvkqLJ{8Y3s`F=-b?UC^Lbdqb90L40KR2*pncx}Qt-me5UoHs|* zl!eyJ)H(Mx&!tnigluY0gEXRGF!u9cx!SPXSYP7ZjmEZ@e9|^{K9^#D7WiE?6 zLZ^@YCIhon3GAll=;zTv<&$YquFfH;@4CnORZ{;5GK;1XEe)2etNohPGhgG@{@Q)g zjbby?ykN}7(WKj@^Zxc=yocvhgFa)rI7dr)lBfKE@A47ho<@>YsV+>aQFH}$c4H)d zSm^3K3*|UOkuZvP1GPGYP9quEXsD(=44*^o%s*JWuV}sEO!;>w-$ko@oXjyqc{DUKk_qm#+FhG+&m+I;K z+Jfll+Ua`QN`HTS!Zrf89vMTyLt!ouK_HFoprjCm&CjFdL(cME?H5Z1Mt~o4Q)GxB z%C=I6A{d8#4FIR2i&tQX;aHYdlP;Rz1Gnk-x>2z9gGh)F3*eB$>L8KtrpZYKqDL}r zZb)*C$3Z1t@Je^rv7uJpZ@k+9-5AWfGH}cdr*de9Y1h$#_TTy1ZSMKf94RO|WmB3# zH1}%`IGIbSUw4T{XkBt(X{xn?wynUg=HX-?yL4Wbe7u`TM{Dl#v}zqr&=E5>%_9SB zHt?H@Qh2MJ8TudrSxwY4g$NpL1L4vf#a}X;nJ_~t*rvlL0Ge5IsK1J9A((kqi^0B_+VH(UfS_b9(6V@!zJ3JMX1$m>vig--A(etuKHv}Fe*XA3vVgYWg2>BnR!qX?-$1u7xdfEHH%B@ z0NKq&`ym#>A(h|O(Y7>aeAWeeZiU~M9oMUdMjJnPdM~?}4v+{iwAXBC)_e0C8Oci# zD_hvCe~S44^<(Hgv(nJ`i&S9Z5+9)BO7Y?l3jQiCQX8^t+8D31 zv|(QcBIc=Hj6KJ)J`<3u)jf?%4buz=g&&{|L#OxwhbRsZvQb(Og$)}ZF4(IsX+`f` zXEUt;3a}hgrNhun*=rw?Uo*N#GSvb=2ZY6=9>kBVP)BFH7}`xpI)hVs*QQdWq%#YN zEjp=@U!zOQ+TN<{Xo@{{m06jii)9E&OJ07N?(2x0>8^ixbH<8!vu*enizv4Yhcx_# zn{KCpv~?!mjLo0^{)Eu37&gsxSYa^Omh^O8iFL4e4fsw`ModR9cFHN8UvhUiP0)LC zWuUY5>F%FqDA^Lgyiu%t|AM@D`x^e2+7>{idG=vH9zMKX7ZHxDuH8YlFaviSgF3_GIWy6`K>f*Yz;bLNJBB zVN{IJAsqMtY7}kZ@Iq9Kh%8Bxuq-JQL@j7ZWwaVH+tZB7deHDt;^|%^HfcRRrYSM7 zVkm$C6-JrfP^!oaQVV^?6{9}D-2`*DX7vifb0`&qM2?WL~%$(vVV6$_9< zAbP$_+a2Qe^_Dk?nbp(Z!AxPDep zf|HzNJDlQs($m$xs0$9^K5YBY+a(Z=PVoFEx_CX_*5SrO)AxMiF;m@Ik-;Yq^0`yq zNZkf(0*N6a_4*?hb@;!1+34D>xh6tyr|Q(lY$*Ha`+V>cet+=N1SPun&J7F;P?B=l zyPG{Sf6|`ny|JKYnU;bI;3Pzhl6FTzsF_tm84v#9n{~hdK>81XRpW5xa6lljRI?R8 zWe}Y|Vq3e2XT`uCkw8|gj)yRXvMq#75k^vJfoIyR5wnTMXcu1}#lfCPVrmcg?|N}D zUd^29d0O#qNn(xEv|9Lm=Bf!%A#h!hI)W$aWnXT5#EGV2XP@bYFns7~l{O&X^DSYO zIbc}k2B90fXP^2eD@F^Z;5QJ|aQ!XXjnu;!)p1ZE^jxODZe?nXJmrljuI|p|qW7*9 z_xJP9`pAY0jAiLl{xCGS^MC)VuCIWKV`*MT0v*gF_$? z+}+)R1t$<3{!QNd-5c&b|LoawW@qZ@>Y1*dsqLnPbiLVuOP=4oa+T#pus-trjbReD39 z4QVJAwn(utUE8sxBrNu%uhaWyufG&Q-=Wto-vBhs$Zu z07gg;wm+C~()mi`2)JBd3e_=h)850F$&xSt@CeNkg-Hm9;Yy(*pU6=;lfkE&reZ-! znY^7AvyBzBYwMFjzLjQz}`=o$>O(s{f1!N8-?um3~EW3a@uQxp&@$0?;rTYY-c~J2?Y%~+Lg3e4QcsK7XvrT z>Uxjem>7$~!dOo$B@SW*n)K$;V!*r%xVp-)S}i6gfwF@fxBUu0jsvJu8riD5*wc%| zQHcWe9~3Q&fIV)Ud_698e`c%&}zUP%H?tY6o}EYK_tY&lr^c@sC};D`75;%ZPnV~940IuX}6FlIwH z%(U7OR04V@9l^2vUfanGcuAhqLKGqhqpbG7aq=c!x;AN65@N!~X>>e5DWS+JgdNmk zAqqSVg`>hubB-ns^S2*nT@0jp%WLk$D9(7}9iC5M@a&LNwX%p!v7kk40T~L;1o5HE z6xK^RWiraZT5+?+D_@pBpi}81A%}&@E=8C}b zLZu1x^d8}t-r$$Yn)6Q}8y*7L@c+EQ+$|&^M-C3aP6;#`=YOI(S4nSAHiGTj$!co* z)lfDb+u(gTsUk&C=Wu6L!1q z;ttc!71A(Uk1miuR-`%PD;@in^!;~0#-~Prbv*S71Y);x<7H&WZU|KqUPvvye0dGW zc_!(Igc#OJa$(BCT(KP?T2CBi>rxa`^VYW6&*}We$Fx&V>TfXtnvKi(<`o$iJ*w{@ zr&ZOZUda$zuvQlkTezN>=5O*QNe)iuh~w^OL&A^|xulLF~a zh@mto`2@$LKB#A!s^sFCsVqnA%!$k@33^WmNyt*Zr~@@a?q}k$o@C9@^hp-Yk*GNq z*nUK1Y4_1ADpv_+>nL7fGeR?r2ZM+jM1FBSLdI{~%l$6bG_9=@0~APyiuqlm6s0~( z7+mvJY6SNYeUwHwouTIoLNIkvm&|+;-b+Ryv?ZFyxWyha`GCS&TSvhrg*CYE@Y1x| zt+wtvL8e^^GHvePe{^!U2m#3&e;M}NqzV^K^^mWK(-3?#+Z&Wf*fGl#217Qnt$sFp zbD8N&{5jtoYh5)#EmDOMbU!6A;;ACo}ScKX5n9kMNC`cMrp(}0^h+j17?D758W-2eLgFm!eSpg!y5WR~+%GWGYoUS}iEw+5p zmb&2;$r6PQq7~>3jkZ9fpSSf@9{!1ncW96Dz>AwfYr6^H9bMaTXR(zGWxyq3UM6Z1 zoaT=6v^a`@6^GxZVO@zT`|#BaH}YBV5kSbWPtYyhG&e~i6$jN&HTFmX`>wyUZHWt7 zK=(JG9h7C-fmDJXactrAH_lk7F)N7o?eeL@;i zD#=)PvHEF%Wzld*&n2xfu}rv8TDG9*V7pQ9H+8VDH1?u;V%94A4*>&c^-SZLB>vC` zjQkQ?=-y+b4&&~nbA{{_z3ojbOj&Pu+r#JLcu)cTEcXGlKkG2vXboQ%z#m}QH?isT z5he!jL9Fyb-YQOZo+MD1HPW=+8@bb)lIjv#XqL7CEGtWr%s@WhTRQY=?>c&jDqm;t*Am+E@fR< zUFq{Y2cYSK;=;(#QQ-~t1Fs+5Whe1Q9NMYvD-p7uBY{kQk8#0NpOY2ghYkqGXeA-G zg|kiLZn4pBDzTq+>QkAlrg*Jdi1zd+2%*WKkZWU(Blt(42lm>yq?l8ow)K4E(sEH1;Z|IIy%h)p^ z_>I8j2E0qz37FgAL#JknhELvHS`Iu)=ov435QZ1CBO0unM0YppU?AW}Z}~pSNJ0@+ zQ-6&-W&ls{O*QfA5v!VpDH`sq2C=!GD@mNQ_Up~9ug@!>?gPvV&Q2#eg_UpCm zxs3=&Ry$TiS3wc zK4YeM6+tER{f0o`?9+JIrhK6$|OJ+`f3g+r>@dmILQ%^D3!;?O7r=*PEDub3s)s z!tn?qc6lt_ZC$}$q)^k|>Lo-$`dEwVlewm&4WxBvJC(tv=GIOKsRacKwk3B_Xg>w4 zXrlq&O)qz4Coh~OSJ0f6$Y=#r+xMm79X|8k>iHHeOiKM9B=tcL2fo%MYIOw`iVKc_ z+dU2a5(fn^ zx(dAd65aWnm+C>-WDUcYZ79Uc?lS z%y0zlbb4aDzPF2?sa;}nZe2f*XjdBFo2fJ*u;tW`k8F%Gr@$xD;#?qQypaqdARfS> z*iBLeu8MA!HX}|N;<_YRCr@K%IC&Fl%H$Rv%Z&2`?)C%L%E&!2XVMAwm_9U?`SY0G zk&3^l^LG?&`DB4hoTkBTXg|87h$cGwsonuNaG)Y;8r$o<(=1nP@`I9iRaR9^SD`t1 z{esUj0k-lA#3GBr8L{hZtKnjbO3?YnZM-O$Uc4xI3L98xiyTxcmPV3UCk-J&=3Gp9 zm>5MIEELxT6J^+rn0Uvg0cj=wruDw_nafB8*|rbJw*PTC7q_thS?cS*oX)2cyC%^C zLo#^@m_XS3fFy9y0oVWrQXRHl(@^nsrUKmFsb4Q=`m=8t%s%H(XbREocigz!Eyvo?#79%lYmSrt^ly#Pr2f!Xl+E(&i0^Y!VUhWbv?Y6Av40 z!tfDgnL37ZH34mYQAVZat#i|Jli54M*gmhlLT&WLcv`!fidLP z99l;sJzN=lQN4wNRNUSTSM!j;GIUkW3UpX;`PH0in|IeJbP>UM7-0EOJ$$_=sUBB1 zpTJ9ykg#xR5OX4vmugmEmrQ9Dyrt{)RB22!U59FJO96<%z7`OsAn>{ECUGbuitH<= z-fEscPVVCO3DYEJ@bJ0NK$1fYKNGxXOx~HfJ%kE90En<(&L0=kccl>Y-sQkHh%U1N z#vH!1J|f8$&3{Q*|I}!=_^!Bor45nIki^UoH;%J{#rEenZPWk_H;7@RqY0s!&#A`w zFru2794vrHM6o-MHN^7g7BQ{F-fm-@7JFSpwJ*Bx z8owthgJ*(~n_Ns=1XHx2iM81nE{^PC{^ z4*J6#R#`3Ub$LU+xl&$S8R(hf{!_lJM7s1CS=j*a34tOqSh0~d0u7U>gc-*3Rggdg z!#qp(ef&0`tS^|H04Az#Y?M2!%rTa|6h)I`7>DAw6qeA|B=#t)6>5H*9i&qe%J@4h7;N&;K zSLu7WHMWS2sS@j&Wt^iQ9%&5I>fsWluT{9AMvRX5Up}8(U?@JpfNZ!GG=anR_XLj6 zH&mcNB@zIt>7$Fvin5`t`n5UB2Wbvg(q*&}qMz;op>DKIyN&F3!na#dR6;i}H&VFc zc8jJ#kXBRK#MhapzI&O=>j3|!SB_xwl34s)&I^MD*4uE|x}doW6lZ3?gZ^sRbnoq8 zL-(#cDedFCDgHK`Yr!j#ONgIIt($KksYP#>vUvcbHzRSdAtrfbN>|3Hb#*uTvPy2R zP$h_n8$ajawUASW2JF3lwSFADT@x?%j&!tKv8V}dOxyRs$M)mRzR6Ko;wSyn>?ox! zq+o)UFWR@xGxnKi7yhoeiKy0vI%7SknxecR=0>T?vR5{3N_!aTYVJ<_>Pf8q}Cn4C@8()50ZE>3$>weB7 zWB3NA`RF#Y;K0dvgjo}p7=mTwkp8o|6#&8aJ;x^~&GFO2H@M}fj8;vCRp@ILtn&?d zgN-3F$ht0o*6X_(!+q2f}Y1GR-Xa&3S(i?#|=0*uafQ;w5%bED=@&;5ZUqqix(T1h*3)S1oX&XRK$8G#00+ zz#mu+gaLc78DeDKvJZ}7778kEH92MMP_g-{c1K#dNFsUY*w+LDpAnSh za3LW7;Sh@kvr5?nS&BVq%0>8ZO951q02I{FMNs_e2C0nd-oT=qBcQ4zQlh}-l7*8M z6=`7ThB$9XAYgwJnlrLp*jBy_hY$AibZ>B~q;YC;&ju zYVAo?1X$4B*G4yw#jTxMee*PJCp~hD<~GZNmO!)Jlq}VVJMmIEd<7yS#)Y7J%^$HFNB1*&-wu%$_=jm>tXSHgD zTc0I{tc&VDw#MBS7e!(7LfKck%mXm)NpOBFhPiB78_P5zdFA^9GaJQT#{Fyg$)}l`OgO-~B<7cW zbaQAet-feyEkq}vWSympMr!^NGT-5ER!)9F9h8pd?6Dpi4|;x zk7er-fT!~d;1qVY$fS&|VV?k8?J!!{wi9cPD!e{vA2))hqZ#2qtXd9(Yfu;Q5f zVi)$thfupJfH|H`Vk<2K59>Ltjz>X5pDZpICqqXMnI7;*BHLeiYzHXCnu|a| zmnw9>=-2)i4+;%nGO;ysammv0GEACnc+MKRP-yqH4FD@(Kt&sr1tS&Jh7gC60ShwJ z?jgOEh7L{VVMpDHm3wEMH&+B@V`IfRYkepQR zJ-#gy;xQu{;y(~SvesyO8MQ~~HmEWpAnI5ex1cpko8Oq$TnwQ#s2+-mAJ?jL4$JE> zxmmj=kYeu{HRx>tF+(fVyX9t6%6(O9Rh9a1dD|3So4tito%zj$USyqOU>Iw7CH#+V5fZE@5p z7oWDRe+OP=m5ZM>{rf!vRF?Rbf@-xcPQmjM`& z`(6Q-MY*!}-=QGFY)3&>B~D$vx~`Rus=VA&L?Uc$T%2@^RF3bUn<9X%L>3SF?qNJd z=zySlk))(D@5GgSRbQU4(UqtGam;wkEK=7{IG7jQw%eY=K^=t?sJogCqITs&?OaLZ zD8m$BF1nd$tgG*W8;3VXwl?vcZ{M*dcN@hPc!FH)+I-7EaNsdV zZEy$ti4n$J8}J}c=jynAINn`f5KmnbNoOYhwU4s_9jYu^09HBDHKnG?AehKv*UAha zP?KG$37K=QF2V^WUnRSd-!yD7#`+}ZIVal{E?T-5ZFZcPge(P4Eyg_)5!-Z(0S6xC zT$SxCo>Z&+Q(naRut|U>QKRrSyXMFu`IYgOYE zyzFcW9U7f!s*4TNClqaZ=&){%YH@^sSgF}lz7pnvo+UED%4RY`C(KeEPSfHG^Ti@? zA+;WfL8~dmapey~UZSoDKJ!&yi8^PVsz&g3B_0v^5EdV7%}rZ*YMsY%AG!v+EMOg; z5D-Zd$2cg)oWsCd$k9yC7-?jH%?xPpi=%uvwGuv9X+O@^l>4(|1In9@b5TM7Y2K_U ze3?%^XO711W!mTVhYRiRvZijp@fm07ty_=F#0T2C?;)9J)QYRj;Hb4TSD7T(#HWQ^ zhDw}g5jnV*YqTdbaoHhzDT4~cX{+xt1=;U-_UOhCLc4f#1!N-AO2lul;zvKikMv1P z)u(f&h@RF!P$+0QGaU5`A$V*8>=6u<3w+KgjWyS?QX!4)R{G*!%T*<;VzmcW!@!Go}TeGbA_~&z;*hPP4n1|db7FKc{&-PDe0|q>Wcl~>V=owNdmJrpjPQ8x{@qb zzbrZiLP@I5g+z-Ms^4JZ{WpK(VtuV)YfOV4p*iu0mLbOJ;WP*<%an?%@A;F`Gl?)s zQ`^wR(kwIiwNjSzK^JCn?PM?vyrl%^@kdSH$}c`q8UXJZZ~035$uE$$+9<=4>YreE zNJ<%Ri+!V#b+K;LMJ_b^0N~Y8OI*m>EH2@0n(O!CUe_wK0_HNQzWi1euhhEvk5j}U z*#yIA+Mde?68m=|5Y?;;Cf}5R5>k*u6y#5Ib!@FO+{QX@056g#*ORFcZ?i)T2BuR4 zrsD*mwo(Mj$;RFh(7(2T%!UY05uk3;y=WuYrRu#)`iv`G(Wu@-QpYH%I!Grq5H!!&S+GLys7o@19#!_bJ4~alt;ls@_wi zrKLX+TZ3zc0U@|M!P6+WsE8%851+(=hj;pDqGv0>vdz(hWlfW((s{`h!DB;FOuzP9 zbDQnJwT9#orY&B651>n$XGUj%0InaRlLgbx0U_8*kz+w`VWkh<#yq?iC&!w3)h>(c zQ4L~_*H_HnaFAX$0gf^Q+n}T6@$(YO&e|th&a#!yMHMrNT04+ge3lF~p$2R;lewqo zUO|yO%hSFz=h=^&Olen(Is9S)TXh0=dx%JiFuo8t)^^N1@mEtj0?ztMqlhz_d1km_27%Sl}n7d<@LVzWPoc7+Gf(MD0dKb{`;lF*j|aZ?B0D z?+0JYA}9~Qi}wzQ8iTGAnEiAUUIaO#_J=DaT+_QNgjlrYP`D+tW_4m%uf5v_?iMPONsu%_`_@8q~w z8+aJbhX}39w(&w6^AU3>;p|Tzhr80yWvn!O`mlcjFl;5R4jYvw*iyV>f|dAJY%OjE zjH*4-b}bV0a+0{o6h7RY!jTsA#zGai%Y6qgLTd{`kYq1V>j)C2EU9|{fbAK{K5Qnn!E_iawn{!~jqBoNMAw?5o-4X#S>g|N8yX`GQ>7`_0%y+kdr z?ZZb!1e`+@O32bl5rLkoYUd;KXO`!i+`T!B?{~bTBLz4f$j%wwhFr;lahWCq=mY_7 zklo*XSlT{T1fHg#BJK3EBv!*Vt@|MsK*D?@1aJ;v`w|z}2qgO}arY6#mpo)Y1lmUn zzE2RunJ?7t=XM?J&iv`Ioe9AcmgJ8dF@D?^j90zB91}s&oDB)&=ydI{_||1FU-gqO z3967ry*_mP>__T7-KY;yIuq42#;9v{v6~NCA;#ggrK_c|Vw@%P)?(mi zl}gWV{Z>l_-ureiTQO;Lu3CG02bJ(Ok!ZD4d`H=xqI*(x$DB(`CmRixW~X%a?zU^0 zn)S&?i24{+Se~JMDtd0{O-rUmyciu?#SUPnYh|t5vLYm<%g&a7T5iA@7f*|noG~WU z+;VO_MEweV)PuP%j&9#2S=>$4w`wjB$>>R>wFR>fNxV(>5Sc`5i2oFAewi;3+L_|C zz=S?Y7h(xiJ&H%DQNu$`R9K+oM@ew6A4Y1{J&{x=5|hvVcG|tb$egdH-`{Y-WDiI( z*rvJ_v`-e^a=%45iDz%7rw%*#XxxE+J2M%_FOA#k}BxY34mX6DQVtB%@gr&_uW$SRRMVh+n$BUtx?-_R65t)Cz$Lwd3novIYirS|^ zHBqW-q%OhDboBkPw1T;;2E*7jiXUPzPeL1Nf6~T2Z9;Lt@z^!M7j#Z9U zGKi_uOh897$eUAk1-iJaobH-DZR^@BsLrH0yz4Vdi$jayhV!Y3 zzrj0!hAxB8F6qzM03h8)Rfnr7cNWUf zoiP>JWXipk^5`k0-yQc&p^g3&g%l`#N0PE_7ZTN+zEEY%pXwtV+hIh2zw#*57DUVz zD=doYFaBBYgb(%9I+k;$C~EB@ANn<(cXLyb(_Fj^A0V3qzUiXxhV?1d#fDa8{9~@- zF0zzxrxNZ(i}Nc$8~|Y0c(dd65RKQ&B1hCU9`RtW`xDJS?}v)nyzS4}><;;Z+qfQS zi)sU>u>>bF%56dKcV?SeIBRktSq#4GUt#!ApCb-n$ovRL0uZ2uX0`!y;w7Kr(|pnP z&;pc90{iytwV3m|r{gerMy+M3x!8Tv`aCY4hGj-n_U+25rvVXNr-(k@Q1m_%JrhgX zr~2wo&~3N$TFHdn#g~zYy%CWWeeCBX&h$9$8QkinZ~de2TCm)%o}!)H&4{TKwMayX z@Au7sPlSpc(fR9i`!%?i8k}qWXlvVYADsw=W@>7}m()LvJ-|LID&6xcuDDmAK0!Qx zbaJ44ilVMmwg=Gq$E;gMrLYM7ELwN}@C0!E0zQX#GL2)l(c}yt>JGDd-KtcY-~xEe z=9a>Cc)PdToLW-q>)h7XzI8*U)zJD?@EpZm3!~X$*7MSBQzpssiOAM&sDmz{BD=2u zmY|ah%O5`e1MraXaXu%c@}cnyekBY#hux!?)%>*S~s$IABVm2ZT_E)%2NZ&bdw^JRaoj-@^+ z_Y?3-?id6t5As0dv?nU&MUo2MQWX0mj$2{u-&mk15grtL0LafkYaGpjmlrq+E}mww zQCHHPZ9LD6nLeR2;tym_KPLdQZnrD=hf&;%9fV{A7p<@09mgz>_WKmqSWlRm-;Ent z`|s1Z3&OOXp6{yjx}-7AE=gTJe4^|c1b+C&Y&mbiA{40nMeI;}_{qARw&2L*Xs<4= z?$i)~)O&2+5tf;CRPC109Q$~cN!pxUWrkei@b z0;5fy=m`b`r6Qo1-4D)U05b8LdSHp!D7>xIJ@rtioG~(tF0mc(9EHN1fg_#pg_CCa#!bzjo7{dr) zah~ZZP`#z5qR!9HJhL&~tQmxTp6JAH+n|$+-EaHuAvf^5413n> zvFMnxX{!&3>)b!8O{}n%-{0*Pw!IZDCWX%Ef-}tX;+OtjdJ-fk^0Py z-0y2{sA)As)^p#n7Us5OhW6e9$S|dRFXPtM1rt&TfsH~x7;Kb9Ytl3x#Cw&pQdC*? zQ!DI5qJkxD%NLMi&h0x0thC@$><}%~3Q}k%|(Pm-ON9Vq$rk z+*6z*r^N-<_+crIw9x(~fRoP()0w>wPE9^w7ybsK%L+;Aj2-Q>$drtr@Nn$>L=*%j zu_wQ!r|@fQp6DQWqJfeVf)IC4PdT|=M)Gj;d}t+ z_7b*Z<@d~^Fu}9mREUjbLb71}XardtD!kPg$&V)lp775w^LE(Fg;(Zzj_RZ z3AvRZ$M_xLZI$+1tqJWmT7eQF3hr>3r(8Fky^SY6Es{<1I~jW@m!pKC1N9Y#RtQYU zZD;X}HAxp8>SVnXIzY)dWJ@xa?Xj{Z(~#6>F^YzQBRz+oGpR;=9TM(Ic1e{w$pYeI zXXNLyXG4Sr$Yo4AExcJck3x3$BR)a4E6jHfZ3zl?i0v05jaN|U={2>D_L2J;zQ!n! zTz3kp(Aik7u6MY%Av$k`ep-%4P!cE=g|g$qD;}5-1BM#UQUUI;Ncr1&xpC!SYyF(~ zt8a<7?#_yT?Fa|rwa4Y=T!7`ulfowRS5s-`Qp};G>5H7b7RBhsC_j0#ib9T2PAhqu zTWo>(A@KYgojXl)>@V`TM{CN1KJ&C^#89uGi|6_T)3V zvv|4^YA9-QfWuRU$__6%XkMCUbxYqyr`aB1$k8O-n|nWOF@KbTg&3KmfS50yxX7EB zJvZzC;@GJz3W!>jC@I!pI=wg8MBQOGQl^RF-8_o=n}fu`G5 zcjOb^cpu82qEikG0})H<7dUwd(Trm-x<#X5&l&62l2`&?_t%Ss?(@uU^AVr~jgMNy zpVFOVy%WQ)JKONI92lH=BYno;;;1cc|GLXZUyNh%lMk*>aUzn>PC2JuE&OZ7%4hPH z=rDWl2mmjMO({Mq1xgXN)0}ythF7=u3LsN9 zbC>D51eD%UFK1sz(pDBl$@nLfW48$p9cFMz96%-~gAii8!y9W9WfMcs7kMFE_=v_x zX&uHLnwC1IEeawr(?0N+*{ZJ5ID=D>VnH9-K#IrJ#OiT%1Bsb`^qW?aE`H0JQq|I+ zDYg!V6m{veWLQr?{;7%nxrfh*Yxmcp+AVB;t5heX&Q|5YpC>V7IXm2Ic}(QYsN6Ia z;sB57$Dd%UmH0|egspQEtg92aiAC$=Wj;{v01A;^@UrvxrX#dJt3+cLU}0fF5+b1QKN}8c*VxU<)|AoN%*4#f(Ur;3*}>7w z+11L-g^ zp@I+;P4UN;1=@FTw)j6CzbgSh3y=3pr1P(H7S2Ydwq}2dAfx{}|MzzEE6o$bzpF{c zqd?CEia%n82LogLTlUuuF*xvimV^4&)&F%zHHk`k3qWUPL0|G;B7bkW(7*r&Okg`K z%6}BhJDav6gQor8fG&ySZ@{meV3@x^a6r0w!ao%q!tL5NfHG6X5rTn{zQF9j{e^)A zM$IF<0yRiADK6qaB8xbGpI@5C|FcY5@51gjPyloUNSgg00BCOz_cvykjO0I+&-ytC z=?$uUD5&x;@6H?v2!szzTfqHO3DsslD2pv9S`lP$psC$IwhVHRJOe0w$p6d;VUZM6 zxA+1qe+0H>k;k@IRn`at-{uIhfx41}Uz<0LLuhxZf=jQ>S}X|^DFT;S0v?JtGcYro2P>jd0PA^>Wy5&Sxq;g1W9 zTl?Lf&cBb3`6K_k{J-f6f8~06QND`nZ_MlU7dG&Mtm=h)o;OII9B8$U_-Fn9ri=nL z<;(iV`23ddSSP0X<1zAr`Q}CW+`#j-|50Q8j|T_oKNj$UWaI^wA@H}Z#~A$ofL@Rc zya2_7{s#Tnp!@TJUMviMAukpIk{1RleS6V>FP6W(kZ+9tT|RT>e=GH3z0nI$J@7Z^ zO$jt;`4QH?mAzQZ@dDS8@;9z>3-iwldJz`?0yCTbH%6ui_20T)1Yf_vO=tXtL;KI& zei7CB5|sTH2obox{i1>|q6lALdh>o`guY?@c|k8?$zI446#kY6R1^LCVqV1Dyuj#| zfG}i0_#K2lb^JYE0dhEAb{nzJz_T8jzn|qcJHPs6a2GIshy7Qd?EU?_v=>M^A@Hj& z{yMfc`R7~8w;y;l$^Y+u`qIJqvxZ88Aa{pK3)F}H&$;>2HTmV-{Ilf_{{LMaWjQF& U8xRzz3Hlg-SPvdRvS48U4;~n9q5uE@ diff --git a/gradle/wrapper/gradle-wrapper.properties b/gradle/wrapper/gradle-wrapper.properties index ee0ddce8b..d355f4c4f 100644 --- a/gradle/wrapper/gradle-wrapper.properties +++ b/gradle/wrapper/gradle-wrapper.properties @@ -1,5 +1,5 @@ distributionBase=GRADLE_USER_HOME distributionPath=wrapper/dists -distributionUrl=https\://services.gradle.org/distributions/gradle-6.9.3-all.zip +distributionUrl=https\://services.gradle.org/distributions/gradle-6.9.3-bin.zip zipStoreBase=GRADLE_USER_HOME zipStorePath=wrapper/dists diff --git a/gradlew b/gradlew index cccdd3d51..1b6c78733 100755 --- a/gradlew +++ b/gradlew @@ -1,78 +1,129 @@ -#!/usr/bin/env sh +#!/bin/sh + +# +# Copyright © 2015-2021 the original authors. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# https://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# ############################################################################## -## -## Gradle start up script for UN*X -## +# +# Gradle start up script for POSIX generated by Gradle. +# +# Important for running: +# +# (1) You need a POSIX-compliant shell to run this script. If your /bin/sh is +# noncompliant, but you have some other compliant shell such as ksh or +# bash, then to run this script, type that shell name before the whole +# command line, like: +# +# ksh Gradle +# +# Busybox and similar reduced shells will NOT work, because this script +# requires all of these POSIX shell features: +# * functions; +# * expansions «$var», «${var}», «${var:-default}», «${var+SET}», +# «${var#prefix}», «${var%suffix}», and «$( cmd )»; +# * compound commands having a testable exit status, especially «case»; +# * various built-in commands including «command», «set», and «ulimit». +# +# Important for patching: +# +# (2) This script targets any POSIX shell, so it avoids extensions provided +# by Bash, Ksh, etc; in particular arrays are avoided. +# +# The "traditional" practice of packing multiple parameters into a +# space-separated string is a well documented source of bugs and security +# problems, so this is (mostly) avoided, by progressively accumulating +# options in "$@", and eventually passing that to Java. +# +# Where the inherited environment variables (DEFAULT_JVM_OPTS, JAVA_OPTS, +# and GRADLE_OPTS) rely on word-splitting, this is performed explicitly; +# see the in-line comments for details. +# +# There are tweaks for specific operating systems such as AIX, CygWin, +# Darwin, MinGW, and NonStop. +# +# (3) This script is generated from the Groovy template +# https://github.com/gradle/gradle/blob/master/subprojects/plugins/src/main/resources/org/gradle/api/internal/plugins/unixStartScript.txt +# within the Gradle project. +# +# You can find Gradle at https://github.com/gradle/gradle/. +# ############################################################################## # Attempt to set APP_HOME + # Resolve links: $0 may be a link -PRG="$0" -# Need this for relative symlinks. -while [ -h "$PRG" ] ; do - ls=`ls -ld "$PRG"` - link=`expr "$ls" : '.*-> \(.*\)$'` - if expr "$link" : '/.*' > /dev/null; then - PRG="$link" - else - PRG=`dirname "$PRG"`"/$link" - fi +app_path=$0 + +# Need this for daisy-chained symlinks. +while + APP_HOME=${app_path%"${app_path##*/}"} # leaves a trailing /; empty if no leading path + [ -h "$app_path" ] +do + ls=$( ls -ld "$app_path" ) + link=${ls#*' -> '} + case $link in #( + /*) app_path=$link ;; #( + *) app_path=$APP_HOME$link ;; + esac done -SAVED="`pwd`" -cd "`dirname \"$PRG\"`/" >/dev/null -APP_HOME="`pwd -P`" -cd "$SAVED" >/dev/null + +APP_HOME=$( cd "${APP_HOME:-./}" && pwd -P ) || exit APP_NAME="Gradle" -APP_BASE_NAME=`basename "$0"` +APP_BASE_NAME=${0##*/} # Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. -DEFAULT_JVM_OPTS="" +DEFAULT_JVM_OPTS='"-Xmx64m" "-Xms64m"' # Use the maximum available, or set MAX_FD != -1 to use that value. -MAX_FD="maximum" +MAX_FD=maximum warn () { echo "$*" -} +} >&2 die () { echo echo "$*" echo exit 1 -} +} >&2 # OS specific support (must be 'true' or 'false'). cygwin=false msys=false darwin=false nonstop=false -case "`uname`" in - CYGWIN* ) - cygwin=true - ;; - Darwin* ) - darwin=true - ;; - MINGW* ) - msys=true - ;; - NONSTOP* ) - nonstop=true - ;; +case "$( uname )" in #( + CYGWIN* ) cygwin=true ;; #( + Darwin* ) darwin=true ;; #( + MSYS* | MINGW* ) msys=true ;; #( + NONSTOP* ) nonstop=true ;; esac CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar + # Determine the Java command to use to start the JVM. if [ -n "$JAVA_HOME" ] ; then if [ -x "$JAVA_HOME/jre/sh/java" ] ; then # IBM's JDK on AIX uses strange locations for the executables - JAVACMD="$JAVA_HOME/jre/sh/java" + JAVACMD=$JAVA_HOME/jre/sh/java else - JAVACMD="$JAVA_HOME/bin/java" + JAVACMD=$JAVA_HOME/bin/java fi if [ ! -x "$JAVACMD" ] ; then die "ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME @@ -81,7 +132,7 @@ Please set the JAVA_HOME variable in your environment to match the location of your Java installation." fi else - JAVACMD="java" + JAVACMD=java which java >/dev/null 2>&1 || die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. Please set the JAVA_HOME variable in your environment to match the @@ -89,84 +140,95 @@ location of your Java installation." fi # Increase the maximum file descriptors if we can. -if [ "$cygwin" = "false" -a "$darwin" = "false" -a "$nonstop" = "false" ] ; then - MAX_FD_LIMIT=`ulimit -H -n` - if [ $? -eq 0 ] ; then - if [ "$MAX_FD" = "maximum" -o "$MAX_FD" = "max" ] ; then - MAX_FD="$MAX_FD_LIMIT" - fi - ulimit -n $MAX_FD - if [ $? -ne 0 ] ; then - warn "Could not set maximum file descriptor limit: $MAX_FD" - fi - else - warn "Could not query maximum file descriptor limit: $MAX_FD_LIMIT" - fi +if ! "$cygwin" && ! "$darwin" && ! "$nonstop" ; then + case $MAX_FD in #( + max*) + MAX_FD=$( ulimit -H -n ) || + warn "Could not query maximum file descriptor limit" + esac + case $MAX_FD in #( + '' | soft) :;; #( + *) + ulimit -n "$MAX_FD" || + warn "Could not set maximum file descriptor limit to $MAX_FD" + esac fi -# For Darwin, add options to specify how the application appears in the dock -if $darwin; then - GRADLE_OPTS="$GRADLE_OPTS \"-Xdock:name=$APP_NAME\" \"-Xdock:icon=$APP_HOME/media/gradle.icns\"" -fi +# Collect all arguments for the java command, stacking in reverse order: +# * args from the command line +# * the main class name +# * -classpath +# * -D...appname settings +# * --module-path (only if needed) +# * DEFAULT_JVM_OPTS, JAVA_OPTS, and GRADLE_OPTS environment variables. + +# For Cygwin or MSYS, switch paths to Windows format before running java +if "$cygwin" || "$msys" ; then + APP_HOME=$( cygpath --path --mixed "$APP_HOME" ) + CLASSPATH=$( cygpath --path --mixed "$CLASSPATH" ) + + JAVACMD=$( cygpath --unix "$JAVACMD" ) -# For Cygwin, switch paths to Windows format before running java -if $cygwin ; then - APP_HOME=`cygpath --path --mixed "$APP_HOME"` - CLASSPATH=`cygpath --path --mixed "$CLASSPATH"` - JAVACMD=`cygpath --unix "$JAVACMD"` - - # We build the pattern for arguments to be converted via cygpath - ROOTDIRSRAW=`find -L / -maxdepth 1 -mindepth 1 -type d 2>/dev/null` - SEP="" - for dir in $ROOTDIRSRAW ; do - ROOTDIRS="$ROOTDIRS$SEP$dir" - SEP="|" - done - OURCYGPATTERN="(^($ROOTDIRS))" - # Add a user-defined pattern to the cygpath arguments - if [ "$GRADLE_CYGPATTERN" != "" ] ; then - OURCYGPATTERN="$OURCYGPATTERN|($GRADLE_CYGPATTERN)" - fi # Now convert the arguments - kludge to limit ourselves to /bin/sh - i=0 - for arg in "$@" ; do - CHECK=`echo "$arg"|egrep -c "$OURCYGPATTERN" -` - CHECK2=`echo "$arg"|egrep -c "^-"` ### Determine if an option - - if [ $CHECK -ne 0 ] && [ $CHECK2 -eq 0 ] ; then ### Added a condition - eval `echo args$i`=`cygpath --path --ignore --mixed "$arg"` - else - eval `echo args$i`="\"$arg\"" + for arg do + if + case $arg in #( + -*) false ;; # don't mess with options #( + /?*) t=${arg#/} t=/${t%%/*} # looks like a POSIX filepath + [ -e "$t" ] ;; #( + *) false ;; + esac + then + arg=$( cygpath --path --ignore --mixed "$arg" ) fi - i=$((i+1)) + # Roll the args list around exactly as many times as the number of + # args, so each arg winds up back in the position where it started, but + # possibly modified. + # + # NB: a `for` loop captures its iteration list before it begins, so + # changing the positional parameters here affects neither the number of + # iterations, nor the values presented in `arg`. + shift # remove old arg + set -- "$@" "$arg" # push replacement arg done - case $i in - (0) set -- ;; - (1) set -- "$args0" ;; - (2) set -- "$args0" "$args1" ;; - (3) set -- "$args0" "$args1" "$args2" ;; - (4) set -- "$args0" "$args1" "$args2" "$args3" ;; - (5) set -- "$args0" "$args1" "$args2" "$args3" "$args4" ;; - (6) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" ;; - (7) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" ;; - (8) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" ;; - (9) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" "$args8" ;; - esac fi -# Escape application args -save () { - for i do printf %s\\n "$i" | sed "s/'/'\\\\''/g;1s/^/'/;\$s/\$/' \\\\/" ; done - echo " " -} -APP_ARGS=$(save "$@") - -# Collect all arguments for the java command, following the shell quoting and substitution rules -eval set -- $DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS "\"-Dorg.gradle.appname=$APP_BASE_NAME\"" -classpath "\"$CLASSPATH\"" org.gradle.wrapper.GradleWrapperMain "$APP_ARGS" - -# by default we should be in the correct project dir, but when run from Finder on Mac, the cwd is wrong -if [ "$(uname)" = "Darwin" ] && [ "$HOME" = "$PWD" ]; then - cd "$(dirname "$0")" -fi +# Collect all arguments for the java command; +# * $DEFAULT_JVM_OPTS, $JAVA_OPTS, and $GRADLE_OPTS can contain fragments of +# shell script including quotes and variable substitutions, so put them in +# double quotes to make sure that they get re-expanded; and +# * put everything else in single quotes, so that it's not re-expanded. + +set -- \ + "-Dorg.gradle.appname=$APP_BASE_NAME" \ + -classpath "$CLASSPATH" \ + org.gradle.wrapper.GradleWrapperMain \ + "$@" + +# Use "xargs" to parse quoted args. +# +# With -n1 it outputs one arg per line, with the quotes and backslashes removed. +# +# In Bash we could simply go: +# +# readarray ARGS < <( xargs -n1 <<<"$var" ) && +# set -- "${ARGS[@]}" "$@" +# +# but POSIX shell has neither arrays nor command substitution, so instead we +# post-process each arg (as a line of input to sed) to backslash-escape any +# character that might be a shell metacharacter, then use eval to reverse +# that process (while maintaining the separation between arguments), and wrap +# the whole thing up as a single "set" statement. +# +# This will of course break if any of these variables contains a newline or +# an unmatched quote. +# + +eval "set -- $( + printf '%s\n' "$DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS" | + xargs -n1 | + sed ' s~[^-[:alnum:]+,./:=@_]~\\&~g; ' | + tr '\n' ' ' + )" '"$@"' exec "$JAVACMD" "$@" diff --git a/gradlew.bat b/gradlew.bat index e95643d6a..ac1b06f93 100644 --- a/gradlew.bat +++ b/gradlew.bat @@ -1,3 +1,19 @@ +@rem +@rem Copyright 2015 the original author or authors. +@rem +@rem Licensed under the Apache License, Version 2.0 (the "License"); +@rem you may not use this file except in compliance with the License. +@rem You may obtain a copy of the License at +@rem +@rem https://www.apache.org/licenses/LICENSE-2.0 +@rem +@rem Unless required by applicable law or agreed to in writing, software +@rem distributed under the License is distributed on an "AS IS" BASIS, +@rem WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +@rem See the License for the specific language governing permissions and +@rem limitations under the License. +@rem + @if "%DEBUG%" == "" @echo off @rem ########################################################################## @rem @@ -13,15 +29,18 @@ if "%DIRNAME%" == "" set DIRNAME=. set APP_BASE_NAME=%~n0 set APP_HOME=%DIRNAME% +@rem Resolve any "." and ".." in APP_HOME to make it shorter. +for %%i in ("%APP_HOME%") do set APP_HOME=%%~fi + @rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. -set DEFAULT_JVM_OPTS= +set DEFAULT_JVM_OPTS="-Xmx64m" "-Xms64m" @rem Find java.exe if defined JAVA_HOME goto findJavaFromJavaHome set JAVA_EXE=java.exe %JAVA_EXE% -version >NUL 2>&1 -if "%ERRORLEVEL%" == "0" goto init +if "%ERRORLEVEL%" == "0" goto execute echo. echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. @@ -35,7 +54,7 @@ goto fail set JAVA_HOME=%JAVA_HOME:"=% set JAVA_EXE=%JAVA_HOME%/bin/java.exe -if exist "%JAVA_EXE%" goto init +if exist "%JAVA_EXE%" goto execute echo. echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME% @@ -45,28 +64,14 @@ echo location of your Java installation. goto fail -:init -@rem Get command-line arguments, handling Windows variants - -if not "%OS%" == "Windows_NT" goto win9xME_args - -:win9xME_args -@rem Slurp the command line arguments. -set CMD_LINE_ARGS= -set _SKIP=2 - -:win9xME_args_slurp -if "x%~1" == "x" goto execute - -set CMD_LINE_ARGS=%* - :execute @rem Setup the command line set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar + @rem Execute Gradle -"%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %CMD_LINE_ARGS% +"%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %* :end @rem End local scope for the variables with windows NT shell diff --git a/src/main/java/org/openmbee/mdk/docgen/ViewViewpointValidator.java b/src/main/java/org/openmbee/mdk/docgen/ViewViewpointValidator.java index 34801718f..51a0df975 100644 --- a/src/main/java/org/openmbee/mdk/docgen/ViewViewpointValidator.java +++ b/src/main/java/org/openmbee/mdk/docgen/ViewViewpointValidator.java @@ -85,8 +85,8 @@ public ViewViewpointValidator(Set elements, Project project, boolean re exposeStereotype = SysMLProfile.getInstanceByProject(project).expose().getStereotype(); visited = new HashSet<>(); - activityEdgeFactory = new ActivityEdgeFactory(); - directedGraph = new DefaultDirectedGraph<>(Element.class); + this.activityEdgeFactory = new ActivityEdgeFactory(); + this.directedGraph = new DefaultDirectedGraph<>(Element.class); } public boolean isFailed() { diff --git a/src/main/java/org/openmbee/mdk/emf/EMFBulkImporter.java b/src/main/java/org/openmbee/mdk/emf/EMFBulkImporter.java index ab9ca63c0..e80b0b29f 100644 --- a/src/main/java/org/openmbee/mdk/emf/EMFBulkImporter.java +++ b/src/main/java/org/openmbee/mdk/emf/EMFBulkImporter.java @@ -2,11 +2,13 @@ import com.fasterxml.jackson.databind.JsonNode; import com.fasterxml.jackson.databind.node.ObjectNode; +import com.nomagic.magicdraw.core.Application; import com.nomagic.magicdraw.core.Project; import com.nomagic.magicdraw.openapi.uml.ReadOnlyElementException; import com.nomagic.magicdraw.openapi.uml.SessionManager; import com.nomagic.magicdraw.uml.transaction.RepositoryModelValidator; import com.nomagic.task.ProgressStatus; +import com.nomagic.uml2.cache.ModelRepositoryCacheValidator; import com.nomagic.uml2.ext.magicdraw.classes.mdkernel.Element; import com.nomagic.uml2.transaction.ModelValidationResult; import org.openmbee.mdk.api.incubating.MDKConstants; @@ -22,6 +24,9 @@ import org.eclipse.emf.ecore.EObject; import org.eclipse.emf.ecore.util.EcoreUtil; +import java.lang.reflect.Constructor; +import java.lang.reflect.InvocationTargetException; +import java.lang.reflect.Method; import java.text.NumberFormat; import java.util.*; import java.util.function.BiFunction; @@ -62,7 +67,9 @@ public Changelog> apply(Collection String initialProgressStatusDescription = null; long initialProgressStatusCurrent = 0; boolean initialProgressStatusIndeterminate = false; - RepositoryModelValidator validator = new RepositoryModelValidator(); + //uncomment for 2021x + //RepositoryModelValidator validator = new RepositoryModelValidator(project); + RepositoryModelValidator validator = getValidator(project); if (progressStatus != null) { initialProgressStatusDescription = progressStatus.getDescription(); @@ -181,7 +188,7 @@ protected BiFunction getIdToElementConverter() { System.err.println("[FAILED 1.5] Could not create " + sysmlId); } Element element = Converters.getIdToElementConverter().apply(sysmlId, project); - failedElementMap.put(new Pair<>(element != null && !element.isInvalid() && !project.isDisposed(element) ? element : null, objectNode), exception); + failedElementMap.put(new Pair<>(element != null && !isElementInvalid(element) && !project.isDisposed(element) ? element : null, objectNode), exception); objectNodes.remove(objectNode); continue bulkImport; } @@ -216,7 +223,7 @@ protected BiFunction getIdToElementConverter() { System.err.println("[FAILED 2] Could not import " + sysmlId); } Element element = Converters.getIdToElementConverter().apply(sysmlId, project); - failedElementMap.put(new Pair<>(element != null && !element.isInvalid() && !project.isDisposed(element) ? element : null, objectNode), exception); + failedElementMap.put(new Pair<>(element != null && !isElementInvalid(element) && !project.isDisposed(element) ? element : null, objectNode), exception); iterator.remove(); continue bulkImport; } @@ -248,18 +255,18 @@ protected BiFunction getIdToElementConverter() { if (MDUtils.isDeveloperMode()) { System.err.println("[FAILED 3] " + result.toString()); } - failedElementMap.put(new Pair<>(element != null && !element.isInvalid() && !project.isDisposed(element) ? element : null, objectNode), new ImportException(element, objectNode, "Element failed validation after importing. Reason: " + result.getReason())); + failedElementMap.put(new Pair<>(element != null && !isElementInvalid(element) && !project.isDisposed(element) ? element : null, objectNode), new ImportException(element, objectNode, "Element failed validation after importing. Reason: " + result.getReason())); objectNodes.remove(objectNode); continue bulkImport; } - if (element.isInvalid()) { + if (isElementInvalid(element)) { if (MDUtils.isDeveloperMode()) { JsonNode sysmlIdJsonNode = objectNode.get(MDKConstants.ID_KEY); String sysmlId = sysmlIdJsonNode != null && sysmlIdJsonNode.isTextual() ? sysmlIdJsonNode.asText() : "<>"; System.err.println("[FAILED 4] Could not create " + sysmlId); } - failedElementMap.put(new Pair<>(element != null && !element.isInvalid() && !project.isDisposed(element) ? element : null, objectNode), new ImportException(element, objectNode, "Element was found to be invalid after importing.")); + failedElementMap.put(new Pair<>(element != null && !isElementInvalid(element) && !project.isDisposed(element) ? element : null, objectNode), new ImportException(element, objectNode, "Element was found to be invalid after importing.")); objectNodes.remove(objectNode); continue bulkImport; } @@ -333,4 +340,62 @@ public Map, Exception> getFailedElementMap() { public Map getNonEquivalentElements() { return nonEquivalentElements; } + + // //Shim for 2022x R2 until we can figure out if it's still ncessary + // public static boolean isElementInvalid(Element element) { + // //For 2021x and earlier + // //return element.isInvalid(); + // return false; + // } + + // Is Element Invalid Shim for versions earlier that 2021x + private static boolean isElementInvalid(Element element) { + + String className = "Element"; + String instanceMethodName = "isInvalid"; + Class[] formalParameters = {}; + Object[] effectiveParameters = new Object[] {}; + String packageName = "com.nomagic.uml2.ext.magicdraw.classes.mdkernel"; + try { + Class clazz = Class.forName(packageName + "." + className); + Method method = clazz.getMethod(instanceMethodName, formalParameters); + return (boolean) method.invoke(element, effectiveParameters); + } catch (NoSuchMethodException e) { + return false; + } catch (Exception e) { + Application.getInstance().getGUILog().log("Error accessing Cameo API (EMFBulkImporter.Shims)"); + return false; + } + } + + private static RepositoryModelValidator getValidator(Project project) { + String className = "RepositoryModelValidator"; + String packageName = "com.nomagic.magicdraw.uml.transaction"; + Class[] formalParameters = { Project.class }; + Object[] effectiveParameters = new Object[] { project }; + try { + Class clazz = Class.forName(packageName + "." + className); + try { + Constructor method = clazz.getConstructor(formalParameters); + return (RepositoryModelValidator) method.newInstance(effectiveParameters); + } catch (NoSuchMethodException e) { + + try { + Constructor[] method = clazz.getConstructors(); + effectiveParameters = new Object[] {}; + return (RepositoryModelValidator) method[0].newInstance(effectiveParameters); + } + catch (Exception ex) { + Application.getInstance().getGUILog().log("Error accessing Cameo API (EMFBulkImporter.Shims)"); + return null; + } + } catch (Exception e) { + Application.getInstance().getGUILog().log("Error accessing Cameo API (EMFBulkImporter.Shims)"); + return null; + } + } catch (Exception e) { + Application.getInstance().getGUILog().log("Error accessing Cameo API (EMFBulkImporter.Shims)"); + return null; + } + } } diff --git a/src/main/java/org/openmbee/mdk/http/ServerException.java b/src/main/java/org/openmbee/mdk/http/ServerException.java index b6dfb1861..bba63265e 100644 --- a/src/main/java/org/openmbee/mdk/http/ServerException.java +++ b/src/main/java/org/openmbee/mdk/http/ServerException.java @@ -1,6 +1,6 @@ package org.openmbee.mdk.http; -import org.apache.commons.text.WordUtils; +import org.apache.commons.lang3.text.WordUtils; import java.lang.reflect.Field; import java.lang.reflect.Modifier; diff --git a/src/main/java/org/openmbee/mdk/options/MDKEnvironmentOptionsGroup.java b/src/main/java/org/openmbee/mdk/options/MDKEnvironmentOptionsGroup.java index 519410363..d07a6e180 100644 --- a/src/main/java/org/openmbee/mdk/options/MDKEnvironmentOptionsGroup.java +++ b/src/main/java/org/openmbee/mdk/options/MDKEnvironmentOptionsGroup.java @@ -2,7 +2,7 @@ import com.nomagic.magicdraw.core.options.AbstractPropertyOptionsGroup; import com.nomagic.magicdraw.properties.*; -import com.nomagic.magicdraw.ui.ImageMap16; +import com.nomagic.magicdraw.ui.Icons; import org.openmbee.mdk.util.MDUtils; import javax.swing.*; @@ -194,6 +194,6 @@ public String getName() { @Override public Icon getGroupIcon() { - return ImageMap16.SETTINGS; + return Icons.SETTINGS; } } From b16d5dfb6074b3a03af95916c0fe18f5c28ce214 Mon Sep 17 00:00:00 2001 From: Enquier Date: Tue, 26 Mar 2024 16:43:29 -0600 Subject: [PATCH 05/19] upgrade fop to fix issue; also remove errors due to NM transcludes --- build.gradle | 33 ++++++++++--------- .../docbook-xsl/fo/mdk-default.xsl | 2 +- .../org/openmbee/mdk/docgen/DocGenUtils.java | 4 +++ .../org/openmbee/mdk/generator/PdfWriter.java | 6 ++-- 4 files changed, 26 insertions(+), 19 deletions(-) diff --git a/build.gradle b/build.gradle index 613d6e7cd..99fb37531 100644 --- a/build.gradle +++ b/build.gradle @@ -64,7 +64,7 @@ else { String docbookNameVersion = 'docbook-xsl-1.79.1' -String fopNameVersion = 'fop-1.1' +String fopNameVersion = 'fop-2.9' // In this section you declare where to find the dependencies of your project repositories { @@ -220,7 +220,7 @@ dependencies { // preCompile group: 'com.nomagic', name: 'cst', version: '2021x', classifier: 'Cameo_Simulation_Toolkit_Plugin_2021x', ext: 'zip' } - preImplementation group: 'org.apache.fop', name: 'fop', version: '1.1', classifier: fopNameVersion + '-bin', ext: 'zip' + preImplementation group: 'org.apache.fop', name: 'fop', version: '2.9', classifier: fopNameVersion + '-bin', ext: 'zip' preImplementation group: 'net.sourceforge.docbook', name: 'docbook-xsl', version: '1.79.1', classifier: docbookNameVersion, ext: 'zip' // JavaFX @@ -233,16 +233,7 @@ dependencies { implementation files(classpathLibraries.collect { 'build/dependency-cache/extracted/magicdraw/' + it }) implementation fileTree(dir: 'build/dependency-cache/extracted/magicdraw', include: ['lib/**/*.jar', 'plugins/**/*.jar'], exclude: ([classpathLibraries, ['plugins/com.nomagic.collaborator.publisher/**/*.jar', 'plugins/com.nomagic.magicdraw.emfuml2xmi*/**/*.jar', 'plugins/com.nomagic.magicdraw.automaton/lib/engines/**/*.jar', 'plugins/tomsawyer/**/*.jar', 'plugins/com.intercax.syndeia.md/**/*.jar']]).flatten()) implementation fileTree(dir: 'lib', include: ['**/*.jar']) - implementation files("build/dependency-cache/extracted/fop/jars/${fopNameVersion}.jar", 'build/dependency-cache/extracted/fop/jars/xmlgraphics-commons-1.5.jar') - if (profiles["implementationFiles"] != null) { - def implementationArray = profiles["implementationFiles"].toString().split(',') - implementationArray.each { - implementation files(it) - } - } - else { - implementation files('build/dependency-cache/extracted/fop/jars/fop-1.1.jar', 'build/dependency-cache/extracted/fop/jars/xmlgraphics-commons-1.5.jar') - } + implementation files("build/dependency-cache/extracted/fop/jars/fop-core-2.9.jar", "build/dependency-cache/extracted/fop/jars/fop-events-2.9.jar", "build/dependency-cache/extracted/fop/jars/fop-util-2.9.jar", 'build/dependency-cache/extracted/fop/jars/xmlgraphics-commons-2.9.jar') } @@ -267,12 +258,11 @@ task extractDependencies { into archive.getParentFile().getAbsolutePath() } copy { - from archive.getParentFile().getAbsolutePath() + '/' + fopNameVersion + '/build/fop.jar' + from fileTree(dir: archive.getParentFile().getAbsolutePath() + '/' + fopNameVersion + '/fop/build', include: '*.jar') into 'build/dependency-cache/extracted/fop/jars' - rename { String fileName -> fopNameVersion + '.jar' } } copy { - from fileTree(dir: archive.getParentFile().getAbsolutePath() + '/' + fopNameVersion + '/lib', include: '*.jar', exclude: 'commons*.jar') + from fileTree(dir: archive.getParentFile().getAbsolutePath() + '/' + fopNameVersion + '/fop/lib', include: '*.jar', exclude: 'commons*.jar') into 'build/dependency-cache/extracted/fop/jars' } copy { //license3rdparty @@ -281,7 +271,7 @@ task extractDependencies { rename { String fileName -> 'apache_fop_license.txt' } } copy { //license3rdparty - from fileTree(dir: archive.getParentFile().getAbsolutePath() + '/' + fopNameVersion + '/lib', include: '*.LICENSE.txt', exclude: 'commons*LICENSE.txt') + from fileTree(dir: archive.getParentFile().getAbsolutePath() + '/' + fopNameVersion + '/fop/lib', include: '*.LICENSE.txt', exclude: 'commons*LICENSE.txt') into 'build/dependency-cache/extracted/fop/license' rename { String fileName -> fileName.replace(".LICENSE.txt", "_license.txt") } } @@ -303,6 +293,11 @@ task extractDependencies { from zipTree(archive) into 'build/dependency-cache/extracted/magicdraw' } + copy { + from 'build/dependency-cache/extracted/magicdraw/plugins/com.nomagic.conceptmodeler' + into 'build/tmp/com.nomagic.conceptmodeler' + } + } } fileTree(dir: 'build/dependency-cache/extracted/magicdraw', include: '*.zip').each { archive -> @@ -311,6 +306,7 @@ task extractDependencies { into 'build/dependency-cache/extracted/magicdraw' } } + delete 'build/dependency-cache/extracted/magicdraw/plugins/com.nomagic.conceptmodeler' } } compileJava.dependsOn extractDependencies @@ -599,6 +595,11 @@ installDist { from 'build/plugin' into 'build/install' } + copy { + from 'build/tmp/com.nomagic.conceptmodeler' + into 'build/install/plugins/com.nomagic.conceptmodeler' + } + delete 'build/tmp/com.nomagic.conceptmodeler' } } diff --git a/src/main/dist/plugins/org.openmbee.mdk/docbook-xsl/fo/mdk-default.xsl b/src/main/dist/plugins/org.openmbee.mdk/docbook-xsl/fo/mdk-default.xsl index 493b2d4bb..046bd7a00 100644 --- a/src/main/dist/plugins/org.openmbee.mdk/docbook-xsl/fo/mdk-default.xsl +++ b/src/main/dist/plugins/org.openmbee.mdk/docbook-xsl/fo/mdk-default.xsl @@ -36,7 +36,7 @@ Version 1.0 - + diff --git a/src/main/java/org/openmbee/mdk/docgen/DocGenUtils.java b/src/main/java/org/openmbee/mdk/docgen/DocGenUtils.java index 9aad6a026..68e810066 100644 --- a/src/main/java/org/openmbee/mdk/docgen/DocGenUtils.java +++ b/src/main/java/org/openmbee/mdk/docgen/DocGenUtils.java @@ -164,6 +164,10 @@ public static String fixString(Object s, boolean convertHtml) { // may want to look at // com.nomagic.magicdraw.uml.RepresentationTextCreator.getRepresentedText if (s instanceof String) { + //Handle noMagic attribute prefixes on tags for mdel cross-refs + if (((String) s).contains("erit")){ + s = ((String) s).replaceAll("erit:[a-z]*=[A-Za-z_\"]*",""); + } if (((String) s).contains("")){ if (convertHtml) { return htmlToXmlEntities((String) s); diff --git a/src/main/java/org/openmbee/mdk/generator/PdfWriter.java b/src/main/java/org/openmbee/mdk/generator/PdfWriter.java index 3bbdcdbc9..2e7d7d5df 100644 --- a/src/main/java/org/openmbee/mdk/generator/PdfWriter.java +++ b/src/main/java/org/openmbee/mdk/generator/PdfWriter.java @@ -68,8 +68,8 @@ protected void document2Pdf() { ClassLoader localClassLoader = Thread.currentThread().getContextClassLoader(); try { - FopFactory fopFactory = FopFactory.newInstance();//fopConfigFile); - + FopFactory fopFactory = FopFactory.newInstance(new File(".").toURI());//fopConfigFile); + //make currentloader to be mainloader (batik, fop, xmlgraphics jar need to be loaded at the same level so images to be embedded in PDF). URL[] urls = new URL[1]; //urls[0] = (new File(ApplicationEnvironment.getInstallRoot() + File.separator + "plugins" + File.separator + "org.openmbee.mdk")).toURI().toURL(); @@ -91,8 +91,10 @@ protected void document2Pdf() { Fop fop = fopFactory.newFop(MimeConstants.MIME_PDF, foUserAgent, pdfOut); // Setup XSLT Transformer transformer = TransformerFactory.newInstance().newTransformer(new StreamSource(docbookXslFo)); + // Pipe the FO events to FOP Result res = new SAXResult(fop.getDefaultHandler()); + //transform Docbook -> XSL-FO -> PDF transformer.transform(docbookSrc, res); From 66764c4e2ef38987150d4582f53afedee4689a52 Mon Sep 17 00:00:00 2001 From: Enquier Date: Mon, 1 Apr 2024 12:45:09 -0600 Subject: [PATCH 06/19] Removing unecessary "isElementInvalid" --- .../org/openmbee/mdk/emf/EMFBulkImporter.java | 56 +++++-------------- 1 file changed, 15 insertions(+), 41 deletions(-) diff --git a/src/main/java/org/openmbee/mdk/emf/EMFBulkImporter.java b/src/main/java/org/openmbee/mdk/emf/EMFBulkImporter.java index e80b0b29f..e06d54df5 100644 --- a/src/main/java/org/openmbee/mdk/emf/EMFBulkImporter.java +++ b/src/main/java/org/openmbee/mdk/emf/EMFBulkImporter.java @@ -188,7 +188,7 @@ protected BiFunction getIdToElementConverter() { System.err.println("[FAILED 1.5] Could not create " + sysmlId); } Element element = Converters.getIdToElementConverter().apply(sysmlId, project); - failedElementMap.put(new Pair<>(element != null && !isElementInvalid(element) && !project.isDisposed(element) ? element : null, objectNode), exception); + failedElementMap.put(new Pair<>(element != null && !project.isDisposed(element) ? element : null, objectNode), exception); objectNodes.remove(objectNode); continue bulkImport; } @@ -223,7 +223,7 @@ protected BiFunction getIdToElementConverter() { System.err.println("[FAILED 2] Could not import " + sysmlId); } Element element = Converters.getIdToElementConverter().apply(sysmlId, project); - failedElementMap.put(new Pair<>(element != null && !isElementInvalid(element) && !project.isDisposed(element) ? element : null, objectNode), exception); + failedElementMap.put(new Pair<>(element != null && !project.isDisposed(element) ? element : null, objectNode), exception); iterator.remove(); continue bulkImport; } @@ -255,21 +255,22 @@ protected BiFunction getIdToElementConverter() { if (MDUtils.isDeveloperMode()) { System.err.println("[FAILED 3] " + result.toString()); } - failedElementMap.put(new Pair<>(element != null && !isElementInvalid(element) && !project.isDisposed(element) ? element : null, objectNode), new ImportException(element, objectNode, "Element failed validation after importing. Reason: " + result.getReason())); - objectNodes.remove(objectNode); - continue bulkImport; - } - - if (isElementInvalid(element)) { - if (MDUtils.isDeveloperMode()) { - JsonNode sysmlIdJsonNode = objectNode.get(MDKConstants.ID_KEY); - String sysmlId = sysmlIdJsonNode != null && sysmlIdJsonNode.isTextual() ? sysmlIdJsonNode.asText() : "<>"; - System.err.println("[FAILED 4] Could not create " + sysmlId); - } - failedElementMap.put(new Pair<>(element != null && !isElementInvalid(element) && !project.isDisposed(element) ? element : null, objectNode), new ImportException(element, objectNode, "Element was found to be invalid after importing.")); + failedElementMap.put(new Pair<>(element != null && !project.isDisposed(element) ? element : null, objectNode), new ImportException(element, objectNode, "Element failed validation after importing. Reason: " + result.getReason())); objectNodes.remove(objectNode); continue bulkImport; } + + // TODO: Need to see if we should/can reimplement this + // if (isElementInvalid(element)) { + // if (MDUtils.isDeveloperMode()) { + // JsonNode sysmlIdJsonNode = objectNode.get(MDKConstants.ID_KEY); + // String sysmlId = sysmlIdJsonNode != null && sysmlIdJsonNode.isTextual() ? sysmlIdJsonNode.asText() : "<>"; + // System.err.println("[FAILED 4] Could not create " + sysmlId); + // } + // failedElementMap.put(new Pair<>(element != null && !project.isDisposed(element) ? element : null, objectNode), new ImportException(element, objectNode, "Element was found to be invalid after importing.")); + // objectNodes.remove(objectNode); + // continue bulkImport; + // } ObjectNode sourceObjectNode = Converters.getElementToJsonConverter().apply(element, project); if (!JsonEquivalencePredicate.getInstance().test(sourceObjectNode, objectNode)) { // currently handled as a warning instead of an error @@ -340,34 +341,7 @@ public Map, Exception> getFailedElementMap() { public Map getNonEquivalentElements() { return nonEquivalentElements; } - - // //Shim for 2022x R2 until we can figure out if it's still ncessary - // public static boolean isElementInvalid(Element element) { - // //For 2021x and earlier - // //return element.isInvalid(); - // return false; - // } - // Is Element Invalid Shim for versions earlier that 2021x - private static boolean isElementInvalid(Element element) { - - String className = "Element"; - String instanceMethodName = "isInvalid"; - Class[] formalParameters = {}; - Object[] effectiveParameters = new Object[] {}; - String packageName = "com.nomagic.uml2.ext.magicdraw.classes.mdkernel"; - try { - Class clazz = Class.forName(packageName + "." + className); - Method method = clazz.getMethod(instanceMethodName, formalParameters); - return (boolean) method.invoke(element, effectiveParameters); - } catch (NoSuchMethodException e) { - return false; - } catch (Exception e) { - Application.getInstance().getGUILog().log("Error accessing Cameo API (EMFBulkImporter.Shims)"); - return false; - } - } - private static RepositoryModelValidator getValidator(Project project) { String className = "RepositoryModelValidator"; String packageName = "com.nomagic.magicdraw.uml.transaction"; From 49f5da285031a89045c8b0d86ff067343c36b07d Mon Sep 17 00:00:00 2001 From: Enquier Date: Mon, 1 Apr 2024 12:48:24 -0600 Subject: [PATCH 07/19] Add new methods to set defaults for Auth chain --- .../mdk/options/MDKEnvironmentOptionsGroup.java | 16 ++++++++++------ .../EnvironmentOptionsResources.properties | 3 ++- 2 files changed, 12 insertions(+), 7 deletions(-) diff --git a/src/main/java/org/openmbee/mdk/options/MDKEnvironmentOptionsGroup.java b/src/main/java/org/openmbee/mdk/options/MDKEnvironmentOptionsGroup.java index d07a6e180..959b0d140 100644 --- a/src/main/java/org/openmbee/mdk/options/MDKEnvironmentOptionsGroup.java +++ b/src/main/java/org/openmbee/mdk/options/MDKEnvironmentOptionsGroup.java @@ -149,11 +149,9 @@ public void setDocBookToPDFStyleSheet(String value) { public List getAuthenticationChain() { - String val = PROPERTY_RESOURCE_PROVIDER.getString(MMS_AUTHENTICATION_CHAIN, null); - if(val == null || val.isEmpty()) { - Property p = getProperty(MMS_AUTHENTICATION_CHAIN); - val = p.getValueStringRepresentation(); - } + //Defaults can now be overridden inside the EnvironmentOptionsResources.properties file using MMS_AUTHENTICATION_CHAIN_DEFAULTS + Property p = getProperty(MMS_AUTHENTICATION_CHAIN); + String val = p.getValueStringRepresentation(); if (val == null || val.isEmpty()) { return new ArrayList<>(); } @@ -175,13 +173,19 @@ public void setAuthenticationChain(String value) { @Override public void setDefaultValues() { + + //Boeing: You can now set the default Auth chain using the EnvironmentOptionsResources.properties file + String authDefault = MDKEnvironmentOptionsGroupResources.getString(MMS_AUTHENTICATION_CHAIN + "_DEFAULT"); + if (authDefault == null || authDefault.isEmpty()) { + authDefault = "org.openmbee.mdk.tickets.BasicAuthAcquireTicketProcessor,org.openmbee.mdk.tickets.AuthenticationChainError"; + } setLogJson(false); setPersistChangelog(true); setChangeListenerEnabled(true); setCoordinatedSyncEnabled(true); setUserScriptDirectory(""); setAuthenticationChain( - "org.openmbee.mdk.tickets.BasicAuthAcquireTicketProcessor,org.openmbee.mdk.tickets.AuthenticationChainError"); + authDefault); setDocBookToPDFStyleSheet(""); } diff --git a/src/main/resources/org/openmbee/mdk/options/EnvironmentOptionsResources.properties b/src/main/resources/org/openmbee/mdk/options/EnvironmentOptionsResources.properties index 1d695351b..96c13ce21 100644 --- a/src/main/resources/org/openmbee/mdk/options/EnvironmentOptionsResources.properties +++ b/src/main/resources/org/openmbee/mdk/options/EnvironmentOptionsResources.properties @@ -10,8 +10,9 @@ CUSTOM_USER_SCRIPT_DIRECTORIES_ID=Custom User Scripts Directories CUSTOM_USER_SCRIPT_DIRECTORIES_ID_DESCRIPTION=Specifies additional directories that custom user scripts can be found in. Multiple directories can be specified, but they must be separated by ";" on Windows systems or ":" on Mac and Linux systems. SHOW_ADVANCED_OPTIONS_ID=Show Advanced Options SHOW_ADVANCED_OPTIONS_ID_DESCRIPTION=Enables advanced features in the MMS menu, such as branch validation. You must restart MagicDraw after enabling this field to see the options in the menu. -MMS_AUTHENTICATION_CHAIN=org.openmbee.mdk.tickets.TWCAcquireTicketProcessor,org.openmbee.mdk.tickets.BasicAuthAcquireTicketProcessor,org.openmbee.mdk.tickets.AuthenticationChainError +MMS_AUTHENTICATION_CHAIN=Set MMS Authentication Chain MMS_AUTHENTICATION_CHAIN_DESCRIPTION=Authentication chain used for getting ticket from MMS4 as defined in above order separated by comma. Error class must be the last. +MMS_AUTHENTICATION_CHAIN_DEFAULT="org.openmbee.mdk.tickets.BasicAuthAcquireTicketProcessor,org.openmbee.mdk.tickets.AuthenticationChainError" DOCBOOK_TO_PDF_STYLESHEET=DocBook to PDF Stylesheet DOCBOOK_TO_PDF_STYLESHEET_DESCRIPTION=Stores the last DocBook to PDF Stylesheet used while converting DocBook to PDF. MDK_OPTIONS_NAME=MDK From b3f9ec81d4b5d83314da7a8912d6b1ca369f0394 Mon Sep 17 00:00:00 2001 From: Enquier Date: Mon, 1 Apr 2024 12:56:46 -0600 Subject: [PATCH 08/19] Add new launcher class and changes to the javafx class loader --- build.gradle | 20 ++++++++----------- src/main/java/org/openmbee/mdk/Launcher.java | 7 +++++++ .../java/org/openmbee/mdk/MDKApplication.java | 4 ++-- src/main/java/org/openmbee/mdk/MDKPlugin.java | 4 ++-- .../openmbee/mdk/json/diff/ui/DiffView.java | 1 + 5 files changed, 20 insertions(+), 16 deletions(-) create mode 100644 src/main/java/org/openmbee/mdk/Launcher.java diff --git a/build.gradle b/build.gradle index 4eb74ed07..639ce33e3 100644 --- a/build.gradle +++ b/build.gradle @@ -246,7 +246,7 @@ dependencies { javafx { version = "11.0.2" modules = [ 'javafx.controls', 'javafx.fxml', 'javafx.swing' ] - platform = 'linux' + platform = 'win' } task extractDependencies { @@ -287,12 +287,6 @@ task extractDependencies { into 'build/dependency-cache/extracted/docbook' } } - else if (archive.getName().startsWith('javafx')) { - copy { - from archive.getAbsoluteFile() - into 'build/dependency-cache/extracted/javafx' - } - } else { copy { from zipTree(archive) @@ -404,10 +398,6 @@ abstract class PreDist extends DefaultTask { from project.jar into "${outputDir}/plugins/${groupName}" } - project.copy { - from "${extractedCache}/javafx" - into "${outputDir}/plugins/${groupName}/javafx" - } project.copy { from project.getTasks().getByName('javadocZip') into "${outputDir}/plugins/${groupName}/javadoc" @@ -644,8 +634,14 @@ task runJava(type: JavaExec) { if (profiles["executablePath"] != null) { executable = profiles["executablePath"] } + debugOptions { + enabled = true + port = 31001 + server = true + suspend = false + } main = 'com.nomagic.magicdraw.Main' - jvmArgs = ['--module-path', 'plugins/org.openmbee.mdk/javafx', '--add-modules', 'javafx.controls,javafx.swing,javafx.fxml', '-Xmx8192M', '-Xss512M', '-DLOCALCONFIG=true', '-DWINCONFIG=true', '-Djsse.enableSNIExtension=true', '-Djava.net.preferIPv4Stack=true', '-Dcom.sun.media.imageio.disableCodecLib=true', '-noverify', '-Dlocal.config.dir.ext=-dev', '-splash:data/splash.png', '-Dmd.class.path=$java.class.path', '-Desi.system.config=data/application.conf', '-Dlogback.configurationFile=data/logback.xml', '-Dsun.locale.formatasdefault=true', '-Djdk.attach.allowAttachSelf=true'] + jvmArgs = ['-Xmx8192M', '-Xss512M', '-DLOCALCONFIG=true', '-DWINCONFIG=true', '-Djsse.enableSNIExtension=true', '-Djava.net.preferIPv4Stack=true', '-Dcom.sun.media.imageio.disableCodecLib=true', '-noverify', '-Dlocal.config.dir.ext=-dev', '-splash:data/splash.png', '-Dmd.class.path=$java.class.path', '-Desi.system.config=data/application.conf', '-Dlogback.configurationFile=data/logback.xml', '-Dsun.locale.formatasdefault=true'] // arguments to pass to the application args 'DEVELOPER' } diff --git a/src/main/java/org/openmbee/mdk/Launcher.java b/src/main/java/org/openmbee/mdk/Launcher.java new file mode 100644 index 000000000..a8ca434a0 --- /dev/null +++ b/src/main/java/org/openmbee/mdk/Launcher.java @@ -0,0 +1,7 @@ +package org.openmbee.mdk; + +public class Launcher { + public static void main(String[] args) { + org.openmbee.mdk.MDKApplication.main(args); + } +} diff --git a/src/main/java/org/openmbee/mdk/MDKApplication.java b/src/main/java/org/openmbee/mdk/MDKApplication.java index a1aeccccf..498df7335 100644 --- a/src/main/java/org/openmbee/mdk/MDKApplication.java +++ b/src/main/java/org/openmbee/mdk/MDKApplication.java @@ -29,7 +29,7 @@ protected static MDKApplication getInstance() { return INSTANCE; } - public static void main(String... args) { - Application.launch(MDKApplication.class); + public static void main(String[] args) { + launch(MDKApplication.class); } } diff --git a/src/main/java/org/openmbee/mdk/MDKPlugin.java b/src/main/java/org/openmbee/mdk/MDKPlugin.java index 0c12ba25e..9ec782705 100644 --- a/src/main/java/org/openmbee/mdk/MDKPlugin.java +++ b/src/main/java/org/openmbee/mdk/MDKPlugin.java @@ -123,9 +123,9 @@ private void initJavaFX() { } new Thread(() -> { try { - Class clazz = Class.forName("org.openmbee.mdk.MDKApplication"); + Class clazz = Class.forName("org.openmbee.mdk.Launcher"); Method method = clazz.getMethod("main", String[].class); - // has to be before invocation since it hangs + //has to be before invocation since it hangs MDKPlugin.JAVAFX_SUPPORTED = true; method.invoke(null, new Object[]{new String[]{}}); } catch (Exception | Error e) { diff --git a/src/main/java/org/openmbee/mdk/json/diff/ui/DiffView.java b/src/main/java/org/openmbee/mdk/json/diff/ui/DiffView.java index f0a5d83d3..6a4fd31d4 100644 --- a/src/main/java/org/openmbee/mdk/json/diff/ui/DiffView.java +++ b/src/main/java/org/openmbee/mdk/json/diff/ui/DiffView.java @@ -11,6 +11,7 @@ public class DiffView extends VBox { public DiffView(JsonNode source, JsonNode target, JsonNode patch) throws IOException { FXMLLoader loader = new FXMLLoader(getClass().getResource("DiffView.fxml")); + loader.setClassLoader(DiffView.class.getClassLoader()); loader.setController(controller = new DiffViewController(source, target, patch)); loader.setRoot(this); loader.load(); From 5a7a90951c55380d673f744f4a779624b49582be Mon Sep 17 00:00:00 2001 From: Doris Lam Date: Mon, 1 Apr 2024 12:07:09 -0700 Subject: [PATCH 09/19] do empty name check --- .../java/org/openmbee/mdk/mms/validation/ElementValidator.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main/java/org/openmbee/mdk/mms/validation/ElementValidator.java b/src/main/java/org/openmbee/mdk/mms/validation/ElementValidator.java index 53e3a659d..6ab065d65 100644 --- a/src/main/java/org/openmbee/mdk/mms/validation/ElementValidator.java +++ b/src/main/java/org/openmbee/mdk/mms/validation/ElementValidator.java @@ -203,7 +203,7 @@ private void addMissingInClientViolation(ObjectNode serverElement) { String type = typeJsonNode != null ? typeJsonNode.asText("Element") : "Element"; JsonNode nameJsonNode = serverElement.get(MDKConstants.NAME_KEY); String name = nameJsonNode != null ? nameJsonNode.asText("<>") : "<>"; - if (name.equals("<>")) { + if (name.equals("<>") || name.equals("")) { name = "<" + id + ">"; } finishViolation(new ValidationRuleViolation(project.getPrimaryModel(), "[MISSING IN CLIENT] " + type + " " + name), id, null, serverElement, null); From edd5a8304528ec17f6db2980bef3d77d37d0685b Mon Sep 17 00:00:00 2001 From: Doris Lam Date: Mon, 1 Apr 2024 12:11:37 -0700 Subject: [PATCH 10/19] add trim --- .../java/org/openmbee/mdk/mms/validation/ElementValidator.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main/java/org/openmbee/mdk/mms/validation/ElementValidator.java b/src/main/java/org/openmbee/mdk/mms/validation/ElementValidator.java index 6ab065d65..c327f41bc 100644 --- a/src/main/java/org/openmbee/mdk/mms/validation/ElementValidator.java +++ b/src/main/java/org/openmbee/mdk/mms/validation/ElementValidator.java @@ -203,7 +203,7 @@ private void addMissingInClientViolation(ObjectNode serverElement) { String type = typeJsonNode != null ? typeJsonNode.asText("Element") : "Element"; JsonNode nameJsonNode = serverElement.get(MDKConstants.NAME_KEY); String name = nameJsonNode != null ? nameJsonNode.asText("<>") : "<>"; - if (name.equals("<>") || name.equals("")) { + if (name.equals("<>") || name.trim().equals("")) { name = "<" + id + ">"; } finishViolation(new ValidationRuleViolation(project.getPrimaryModel(), "[MISSING IN CLIENT] " + type + " " + name), id, null, serverElement, null); From 7a32e2b715357de04d72c2a35cb8a7c97850e7e3 Mon Sep 17 00:00:00 2001 From: Enquier Date: Mon, 1 Apr 2024 13:42:08 -0600 Subject: [PATCH 11/19] add win/mac jars --- build.gradle | 13 +++++++++---- 1 file changed, 9 insertions(+), 4 deletions(-) diff --git a/build.gradle b/build.gradle index 639ce33e3..8f3f66d49 100644 --- a/build.gradle +++ b/build.gradle @@ -230,9 +230,13 @@ dependencies { preImplementation group: 'net.sourceforge.docbook', name: 'docbook-xsl', version: '1.79.1', classifier: docbookNameVersion, ext: 'zip' // JavaFX - //preImplementation group: 'org.openjfx', name: 'javafx-fxml', version: '11.0.2' - //preImplementation group: 'org.openjfx', name: 'javafx-controls', version: '11.0.2' - //preImplementation group: 'org.openjfx', name: 'javafx-swing', version: '11.0.2' + distribution group: 'org.openjfx', name: 'javafx-fxml', version: '11.0.2', classifier: 'win' + distribution group: 'org.openjfx', name: 'javafx-controls', version: '11.0.2', classifier: 'win' + distribution group: 'org.openjfx', name: 'javafx-swing', version: '11.0.2', classifier: 'win' + distribution group: 'org.openjfx', name: 'javafx-fxml', version: '11.0.2', classifier: 'mac' + distribution group: 'org.openjfx', name: 'javafx-controls', version: '11.0.2', classifier: 'mac' + distribution group: 'org.openjfx', name: 'javafx-swing', version: '11.0.2', classifier: 'mac' + // This ensures classpath load order to match the MagicDraw provided order and then includes extras needed for non-OpenAPI stuff. // This was necessary because of the Application class stubbing that was done in the chromium libraries. @@ -246,7 +250,7 @@ dependencies { javafx { version = "11.0.2" modules = [ 'javafx.controls', 'javafx.fxml', 'javafx.swing' ] - platform = 'win' + platform = 'linux' } task extractDependencies { @@ -394,6 +398,7 @@ abstract class PreDist extends DefaultTask { } project.copy { from project.configurations.runtimeClasspath.resolvedConfiguration.resolvedArtifacts.file + from project.configurations.distribution.resolvedConfiguration.resolvedArtifacts.file from 'lib' from project.jar into "${outputDir}/plugins/${groupName}" From acc6a9d33292ecefd2749b39ff61b1606fb0b0a6 Mon Sep 17 00:00:00 2001 From: Doris Lam Date: Mon, 1 Apr 2024 14:43:17 -0700 Subject: [PATCH 12/19] fix authentication chain description in ui --- .../org/openmbee/mdk/options/MDKEnvironmentOptionsGroup.java | 4 ++-- .../mdk/options/EnvironmentOptionsResources.properties | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/src/main/java/org/openmbee/mdk/options/MDKEnvironmentOptionsGroup.java b/src/main/java/org/openmbee/mdk/options/MDKEnvironmentOptionsGroup.java index 959b0d140..94ba0ae0e 100644 --- a/src/main/java/org/openmbee/mdk/options/MDKEnvironmentOptionsGroup.java +++ b/src/main/java/org/openmbee/mdk/options/MDKEnvironmentOptionsGroup.java @@ -166,14 +166,14 @@ public void setAuthenticationChain(String value) { StringProperty property = new StringProperty(MMS_AUTHENTICATION_CHAIN, value); property.setResourceProvider(PROPERTY_RESOURCE_PROVIDER); property.setGroup(GROUP); - addProperty(property, false); + addProperty(property, true); } public static final PropertyResourceProvider PROPERTY_RESOURCE_PROVIDER = (key, property) -> MDKEnvironmentOptionsGroupResources.getString(key); @Override public void setDefaultValues() { - + //Boeing: You can now set the default Auth chain using the EnvironmentOptionsResources.properties file String authDefault = MDKEnvironmentOptionsGroupResources.getString(MMS_AUTHENTICATION_CHAIN + "_DEFAULT"); if (authDefault == null || authDefault.isEmpty()) { diff --git a/src/main/resources/org/openmbee/mdk/options/EnvironmentOptionsResources.properties b/src/main/resources/org/openmbee/mdk/options/EnvironmentOptionsResources.properties index 96c13ce21..09d1b6d15 100644 --- a/src/main/resources/org/openmbee/mdk/options/EnvironmentOptionsResources.properties +++ b/src/main/resources/org/openmbee/mdk/options/EnvironmentOptionsResources.properties @@ -11,7 +11,7 @@ CUSTOM_USER_SCRIPT_DIRECTORIES_ID_DESCRIPTION=Specifies additional directories t SHOW_ADVANCED_OPTIONS_ID=Show Advanced Options SHOW_ADVANCED_OPTIONS_ID_DESCRIPTION=Enables advanced features in the MMS menu, such as branch validation. You must restart MagicDraw after enabling this field to see the options in the menu. MMS_AUTHENTICATION_CHAIN=Set MMS Authentication Chain -MMS_AUTHENTICATION_CHAIN_DESCRIPTION=Authentication chain used for getting ticket from MMS4 as defined in above order separated by comma. Error class must be the last. +MMS_AUTHENTICATION_CHAIN_DESCRIPTION=Authentication chain used for getting ticket from MMS4 as defined in above order separated by comma. Error class must be the last. To use TWC Auth add org.openmbee.mdk.tickets.TWCAcquireTicketProcessor MMS_AUTHENTICATION_CHAIN_DEFAULT="org.openmbee.mdk.tickets.BasicAuthAcquireTicketProcessor,org.openmbee.mdk.tickets.AuthenticationChainError" DOCBOOK_TO_PDF_STYLESHEET=DocBook to PDF Stylesheet DOCBOOK_TO_PDF_STYLESHEET_DESCRIPTION=Stores the last DocBook to PDF Stylesheet used while converting DocBook to PDF. From c46df02e65a241b37e04ab9e1047be6c3d975a22 Mon Sep 17 00:00:00 2001 From: Doris Lam Date: Mon, 1 Apr 2024 15:53:15 -0700 Subject: [PATCH 13/19] update version and fix default auth chain --- gradle.properties | 2 +- .../openmbee/mdk/options/EnvironmentOptionsResources.properties | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/gradle.properties b/gradle.properties index a2c7f2daa..4ec0a3b06 100644 --- a/gradle.properties +++ b/gradle.properties @@ -1,4 +1,4 @@ -version=6.0.0 +version=6.0.1 group=org.openmbee.mdk.magic descriptorFile=MDR_Plugin_Model_Development_Kit_91110_descriptor.xml magicdDrawGroupName=org.openmbee.mdk diff --git a/src/main/resources/org/openmbee/mdk/options/EnvironmentOptionsResources.properties b/src/main/resources/org/openmbee/mdk/options/EnvironmentOptionsResources.properties index 09d1b6d15..9c3460730 100644 --- a/src/main/resources/org/openmbee/mdk/options/EnvironmentOptionsResources.properties +++ b/src/main/resources/org/openmbee/mdk/options/EnvironmentOptionsResources.properties @@ -12,7 +12,7 @@ SHOW_ADVANCED_OPTIONS_ID=Show Advanced Options SHOW_ADVANCED_OPTIONS_ID_DESCRIPTION=Enables advanced features in the MMS menu, such as branch validation. You must restart MagicDraw after enabling this field to see the options in the menu. MMS_AUTHENTICATION_CHAIN=Set MMS Authentication Chain MMS_AUTHENTICATION_CHAIN_DESCRIPTION=Authentication chain used for getting ticket from MMS4 as defined in above order separated by comma. Error class must be the last. To use TWC Auth add org.openmbee.mdk.tickets.TWCAcquireTicketProcessor -MMS_AUTHENTICATION_CHAIN_DEFAULT="org.openmbee.mdk.tickets.BasicAuthAcquireTicketProcessor,org.openmbee.mdk.tickets.AuthenticationChainError" +MMS_AUTHENTICATION_CHAIN_DEFAULT=org.openmbee.mdk.tickets.BasicAuthAcquireTicketProcessor,org.openmbee.mdk.tickets.AuthenticationChainError DOCBOOK_TO_PDF_STYLESHEET=DocBook to PDF Stylesheet DOCBOOK_TO_PDF_STYLESHEET_DESCRIPTION=Stores the last DocBook to PDF Stylesheet used while converting DocBook to PDF. MDK_OPTIONS_NAME=MDK From d667426e237a501ad0fc192c7ec665a4a95f390f Mon Sep 17 00:00:00 2001 From: Doris Lam Date: Mon, 1 Apr 2024 16:20:33 -0700 Subject: [PATCH 14/19] merge option groups --- .../mdk/fileexport/FileExportRunner.java | 6 +- .../options/EnvironmentOptionsResources.java | 24 --- .../options/MDKEnvironmentOptionsGroup.java | 16 +- .../openmbee/mdk/options/MDKOptionsGroup.java | 186 ------------------ 4 files changed, 18 insertions(+), 214 deletions(-) delete mode 100644 src/main/java/org/openmbee/mdk/options/EnvironmentOptionsResources.java delete mode 100644 src/main/java/org/openmbee/mdk/options/MDKOptionsGroup.java diff --git a/src/main/java/org/openmbee/mdk/fileexport/FileExportRunner.java b/src/main/java/org/openmbee/mdk/fileexport/FileExportRunner.java index fc0258687..472e63cfa 100644 --- a/src/main/java/org/openmbee/mdk/fileexport/FileExportRunner.java +++ b/src/main/java/org/openmbee/mdk/fileexport/FileExportRunner.java @@ -22,7 +22,7 @@ import com.nomagic.uml2.ext.magicdraw.classes.mdkernel.Element; import org.openmbee.mdk.emf.BulkExport; import org.openmbee.mdk.json.JacksonUtils; -import org.openmbee.mdk.options.MDKOptionsGroup; +import org.openmbee.mdk.options.MDKEnvironmentOptionsGroup; import org.openmbee.mdk.options.MDKProjectOptionsGroup; import org.openmbee.mdk.util.Pair; @@ -279,9 +279,9 @@ private void extractPresentationElementsMapping(Collection MDKEnvironmentOptionsGroupResources.getString(key); @Override @@ -187,6 +200,7 @@ public void setDefaultValues() { setAuthenticationChain( authDefault); setDocBookToPDFStyleSheet(""); + setExportMdkzipDiagramElementsMapping(true); } private static final String MDK_OPTIONS_NAME = "MDK_OPTIONS_NAME"; diff --git a/src/main/java/org/openmbee/mdk/options/MDKOptionsGroup.java b/src/main/java/org/openmbee/mdk/options/MDKOptionsGroup.java deleted file mode 100644 index 6007c6024..000000000 --- a/src/main/java/org/openmbee/mdk/options/MDKOptionsGroup.java +++ /dev/null @@ -1,186 +0,0 @@ -package org.openmbee.mdk.options; - -import com.nomagic.magicdraw.core.Application; -import com.nomagic.magicdraw.core.options.AbstractPropertyOptionsGroup; -import com.nomagic.magicdraw.properties.*; -import com.nomagic.magicdraw.ui.ImageMap16; -import org.openmbee.mdk.util.MDUtils; - -import javax.swing.*; -import java.io.File; - -public class MDKOptionsGroup extends AbstractPropertyOptionsGroup { - - public static final String ID = "options.mdk"; - public static final String GROUP = "GROUP"; - private static MDKOptionsGroup tempInstance = null; - - public static final String LOG_JSON_ID = "LOG_JSON_ID", - PERSIST_CHANGELOG_ID = "PERSIST_CHANGELOG_ID", - ENABLE_CHANGE_LISTENER_ID = "ENABLE_CHANGE_LISTENER_ID", - ENABLE_COORDINATED_SYNC_ID = "ENABLE_COORDINATED_SYNC_ID", - CUSTOM_USER_SCRIPT_DIRECTORIES_ID = "CUSTOM_USER_SCRIPT_DIRECTORIES_ID", - DOCBOOK_TO_PDF_STYLESHEET = "DOCBOOK_TO_PDF_STYLESHEET", - EXPORT_MDKZIP_DIAGRAM_ELEMENTS_MAPPING = "EXPORT_MDKZIP_DIAGRAM_ELEMENTS_MAPPING"; - - public MDKOptionsGroup() { - super(ID); - } - - public static MDKOptionsGroup getMDKOptions() { - MDKOptionsGroup group = (MDKOptionsGroup) Application.getInstance().getEnvironmentOptions().getGroup(ID); - if (group == null) { - if (tempInstance == null) { - tempInstance = new MDKOptionsGroup(); - } - return tempInstance; - } - return group; - } - - public boolean isLogJson() { - if (MDUtils.isDeveloperMode()) { - return true; - } - Property p = getProperty(LOG_JSON_ID); - return (Boolean) p.getValue(); - } - - public void setLogJson(boolean value) { - BooleanProperty property = new BooleanProperty(LOG_JSON_ID, value); - property.setResourceProvider(PROPERTY_RESOURCE_PROVIDER); - property.setGroup(GROUP); - addProperty(property, true); - } - - public boolean isPersistChangelog() { - Property p = getProperty(PERSIST_CHANGELOG_ID); - return (Boolean) p.getValue(); - } - - public void setPersistChangelog(boolean value) { - BooleanProperty property = new BooleanProperty(PERSIST_CHANGELOG_ID, value); - property.setResourceProvider(PROPERTY_RESOURCE_PROVIDER); - property.setGroup(GROUP); - if (MDUtils.isDeveloperMode()) { - addProperty(property, true); - } - else { - addInvisibleProperty(property); - } - } - - public boolean isChangeListenerEnabled() { - Property p = getProperty(ENABLE_CHANGE_LISTENER_ID); - return (Boolean) p.getValue(); - } - - public void setChangeListenerEnabled(boolean value) { - BooleanProperty property = new BooleanProperty(ENABLE_CHANGE_LISTENER_ID, value); - property.setResourceProvider(PROPERTY_RESOURCE_PROVIDER); - property.setGroup(GROUP); - if (MDUtils.isDeveloperMode()) { - addProperty(property, true); - } - else { - addInvisibleProperty(property); - } - } - - public boolean isCoordinatedSyncEnabled() { - Property p = getProperty(ENABLE_COORDINATED_SYNC_ID); - return (Boolean) p.getValue(); - } - - public void setCoordinatedSyncEnabled(boolean value) { - BooleanProperty property = new BooleanProperty(ENABLE_COORDINATED_SYNC_ID, value); - property.setResourceProvider(PROPERTY_RESOURCE_PROVIDER); - property.setGroup(GROUP); - if (MDUtils.isDeveloperMode()) { - addProperty(property, true); - } - else { - addInvisibleProperty(property); - } - } - - public File[] getCustomUserScriptDirectories() { - Property p = getProperty(CUSTOM_USER_SCRIPT_DIRECTORIES_ID); - String val = p.getValueStringRepresentation(); - if (val == null || val.isEmpty()) { - return null; - } - File[] dirs = new File[getNumberOfCustomUserScriptDirectories()]; - for (int i = 0; i < getNumberOfCustomUserScriptDirectories(); i++) { - dirs[i] = new File(val.split(File.pathSeparator)[i]); - } - return dirs; - } - - public int getNumberOfCustomUserScriptDirectories() { - Property p = getProperty(CUSTOM_USER_SCRIPT_DIRECTORIES_ID); - String val = p.getValueStringRepresentation(); - if (val == null || val.isEmpty()) { - return 0; - } - return val.split(File.pathSeparator).length; - - } - - public void setUserScriptDirectory(String path) { - StringProperty property = new StringProperty(CUSTOM_USER_SCRIPT_DIRECTORIES_ID, path); - property.setResourceProvider(PROPERTY_RESOURCE_PROVIDER); - property.setGroup(GROUP); - addProperty(property, true); - } - - - public String getDocBookToPDFStyleSheet() { - Property p = getProperty(DOCBOOK_TO_PDF_STYLESHEET); - return (String) p.getValue(); - } - - public void setDocBookToPDFStyleSheet(String value) { - FileProperty property = new FileProperty(DOCBOOK_TO_PDF_STYLESHEET, value, FileProperty.FILES_ONLY); - property.setResourceProvider(PROPERTY_RESOURCE_PROVIDER); - property.setGroup(GROUP); - addProperty(property, true); - } - - public void setExportMdkzipDiagramElementsMapping(Boolean value) { - BooleanProperty property = new BooleanProperty(EXPORT_MDKZIP_DIAGRAM_ELEMENTS_MAPPING, value); - property.setResourceProvider(PROPERTY_RESOURCE_PROVIDER); - property.setGroup(GROUP); - addProperty(property, true); - } - - public boolean isExportMdkzipDiagramElementsMappingEnabled() { - Property p = getProperty(EXPORT_MDKZIP_DIAGRAM_ELEMENTS_MAPPING); - return (Boolean) p.getValue(); - } - - public static final PropertyResourceProvider PROPERTY_RESOURCE_PROVIDER = (key, property) -> EnvironmentOptionsResources.getString(key); - - @Override - public void setDefaultValues() { - setLogJson(false); - setPersistChangelog(true); - setChangeListenerEnabled(true); - setCoordinatedSyncEnabled(true); - setUserScriptDirectory(""); - setDocBookToPDFStyleSheet(""); - setExportMdkzipDiagramElementsMapping(true); - } - - private static final String MDK_OPTIONS_NAME = "MDK_OPTIONS_NAME"; - - @Override - public String getName() { - return EnvironmentOptionsResources.getString(MDK_OPTIONS_NAME); - } - - @Override - public Icon getGroupIcon() { - return ImageMap16.SETTINGS; - } -} From 6bfa127cf43a5e6d34b4c0889a7ab310f0d868a6 Mon Sep 17 00:00:00 2001 From: Doris Lam Date: Mon, 1 Apr 2024 17:11:16 -0700 Subject: [PATCH 15/19] cleanup project option group --- .../mdk/fileexport/FileExportRunner.java | 1 - .../mdk/options/MDKProjectOptions.java | 69 +++++++++++-- .../mdk/options/MDKProjectOptionsGroup.java | 99 ------------------- .../mdk/options/ProjectOptionsResources.java | 24 ----- .../EnvironmentOptionsResources.properties | 2 + .../ProjectOptionsResources.properties | 8 +- 6 files changed, 70 insertions(+), 133 deletions(-) delete mode 100644 src/main/java/org/openmbee/mdk/options/MDKProjectOptionsGroup.java delete mode 100644 src/main/java/org/openmbee/mdk/options/ProjectOptionsResources.java diff --git a/src/main/java/org/openmbee/mdk/fileexport/FileExportRunner.java b/src/main/java/org/openmbee/mdk/fileexport/FileExportRunner.java index 472e63cfa..a40a11818 100644 --- a/src/main/java/org/openmbee/mdk/fileexport/FileExportRunner.java +++ b/src/main/java/org/openmbee/mdk/fileexport/FileExportRunner.java @@ -23,7 +23,6 @@ import org.openmbee.mdk.emf.BulkExport; import org.openmbee.mdk.json.JacksonUtils; import org.openmbee.mdk.options.MDKEnvironmentOptionsGroup; -import org.openmbee.mdk.options.MDKProjectOptionsGroup; import org.openmbee.mdk.util.Pair; import java.io.*; diff --git a/src/main/java/org/openmbee/mdk/options/MDKProjectOptions.java b/src/main/java/org/openmbee/mdk/options/MDKProjectOptions.java index 2c1fc1f7d..57a3634cf 100644 --- a/src/main/java/org/openmbee/mdk/options/MDKProjectOptions.java +++ b/src/main/java/org/openmbee/mdk/options/MDKProjectOptions.java @@ -5,20 +5,24 @@ import com.nomagic.magicdraw.core.ProjectUtilities; import com.nomagic.magicdraw.core.options.ProjectOptions; import com.nomagic.magicdraw.properties.BooleanProperty; +import com.nomagic.magicdraw.properties.ChoiceProperty; import com.nomagic.magicdraw.properties.Property; import com.nomagic.magicdraw.properties.StringProperty; import com.nomagic.uml2.ext.jmi.helpers.StereotypesHelper; import com.nomagic.uml2.ext.magicdraw.classes.mdkernel.Element; import org.apache.http.client.utils.URIBuilder; +import org.openmbee.mdk.fileexport.ContextExportLevel; import javax.swing.*; import java.net.URISyntaxException; +import java.util.Arrays; +import java.util.List; import java.util.Optional; public class MDKProjectOptions { public static final String ID = "options.project.mdk"; - public static final String GROUP = "PROJECT_GENERAL_PROPERTIES"; + public static final String GROUP = ProjectOptions.PROJECT_GENERAL_PROPERTIES; public static final String MMS_HOST_URL="MMS_HOST_URL", MMS_BASE_PATH="MMS_BASE_PATH", VE_HOST_URL="VE_HOST_URL", @@ -27,7 +31,10 @@ public class MDKProjectOptions { ENABLE_OPENMBEE_INTEGRATION = "ENABLE_OPENMBEE_INTEGRATION", MDK_MMS_URL = "MDK_MMS_URL", MDK_VE_URL = "MDK_VE_URL", - MDK_MIGRATE_STEREOTYPE = "MDK_MIGRATE_STEREOTYPE"; + MDK_MIGRATE_STEREOTYPE = "MDK_MIGRATE_STEREOTYPE", + PROPERTY_AUTOSAVE_MDKMODEL = "PROPERTY_AUTOSAVE_MDKMODEL", + PROPERTY_AUTOSAVE_MDKZIP = "PROPERTY_AUTOSAVE_MDKZIP", + PROPERTY_CONTEXT_EXPORT_LEVEL = "PROPERTY_CONTEXT_EXPORT_LEVEL"; public MDKProjectOptions() { } @@ -39,6 +46,9 @@ public static void init(ProjectOptions var0) { MDKProjectOptions.setOption(var0, VE_HOST_URL,""); MDKProjectOptions.setOption(var0, VE_BASE_PATH,""); MDKProjectOptions.setOption(var0, MDK_MIGRATE_STEREOTYPE, true); + MDKProjectOptions.setOption(var0, PROPERTY_AUTOSAVE_MDKMODEL, false); + MDKProjectOptions.setOption(var0, PROPERTY_AUTOSAVE_MDKZIP, false); + MDKProjectOptions.setOption(var0, PROPERTY_CONTEXT_EXPORT_LEVEL, Arrays.asList(ContextExportLevel.values()), ContextExportLevel.Containment); } public static void setOption(ProjectOptions var0, String projectOption, String newValue) { @@ -67,9 +77,52 @@ else if ((boolean)var1.getValue() != newValue) { } } + public static void setOption(ProjectOptions var0, String projectOption, List choices, T newValue) { + Property var1 = var0.getProperty(MDKProjectOptions.GROUP, projectOption); + if (var1 == null) { + ChoiceProperty var2 = new ChoiceProperty(projectOption, "", choices); + var2.setGroup(MDKProjectOptions.MDK_PROJECT_OPTIONS_GROUP); + var2.setResourceProvider(MDKPropertyResourceProvider.getInstance()); + var2.setValue(newValue); + var0.addProperty(MDKProjectOptions.GROUP, var2); + } + else if (!var1.getValue().equals(newValue)) { + var1.setValue(newValue); + } + } + + public static boolean isAutosaveMDKModel(Project project) { + Property property = project.getOptions().getProperty(ProjectOptions.PROJECT_GENERAL_PROPERTIES, PROPERTY_AUTOSAVE_MDKMODEL); + if (property != null) { + return (boolean) property.getValue(); + } else { + return false; + } + + } + + public static boolean isAutosaveMDKZip(Project project) { + Property property = project.getOptions().getProperty(ProjectOptions.PROJECT_GENERAL_PROPERTIES, PROPERTY_AUTOSAVE_MDKZIP); + if (property != null) { + return (boolean) property.getValue(); + } else { + return false; + } + + } + + public static ContextExportLevel getContextExportLevel(Project project) { + Property property = project.getOptions().getProperty(ProjectOptions.PROJECT_GENERAL_PROPERTIES, PROPERTY_CONTEXT_EXPORT_LEVEL); + if (property != null) { + return ContextExportLevel.valueOf(property.getValueStringRepresentation()); + } else { + return ContextExportLevel.None; + } + } + public static boolean getMbeeEnabled(Project project) { if (project != null) { - Property mmsEnabledProperty = project.getOptions().getProperty("PROJECT_GENERAL_PROPERTIES", ENABLE_OPENMBEE_INTEGRATION); + Property mmsEnabledProperty = project.getOptions().getProperty(ProjectOptions.PROJECT_GENERAL_PROPERTIES, ENABLE_OPENMBEE_INTEGRATION); if (mmsEnabledProperty instanceof BooleanProperty) { return ((BooleanProperty) mmsEnabledProperty).getBoolean(); } @@ -79,7 +132,7 @@ public static boolean getMbeeEnabled(Project project) { public static String getMmsHost(Project project) { if (project != null) { - Property mmsHostProperty = project.getOptions().getProperty("PROJECT_GENERAL_PROPERTIES", MMS_HOST_URL); + Property mmsHostProperty = project.getOptions().getProperty(ProjectOptions.PROJECT_GENERAL_PROPERTIES, MMS_HOST_URL); if (mmsHostProperty instanceof StringProperty) { return ((StringProperty) mmsHostProperty).getString(); } @@ -89,7 +142,7 @@ public static String getMmsHost(Project project) { public static String getMmsBasePath(Project project) { if (project != null) { - Property mmsBasePathProperty = project.getOptions().getProperty("PROJECT_GENERAL_PROPERTIES", MMS_BASE_PATH); + Property mmsBasePathProperty = project.getOptions().getProperty(ProjectOptions.PROJECT_GENERAL_PROPERTIES, MMS_BASE_PATH); if (mmsBasePathProperty instanceof StringProperty) { return ((StringProperty) mmsBasePathProperty).getString(); } @@ -99,7 +152,7 @@ public static String getMmsBasePath(Project project) { public static String getVeHost(Project project) { if (project != null) { - Property veHostProperty = project.getOptions().getProperty("PROJECT_GENERAL_PROPERTIES", VE_HOST_URL); + Property veHostProperty = project.getOptions().getProperty(ProjectOptions.PROJECT_GENERAL_PROPERTIES, VE_HOST_URL); if (veHostProperty instanceof StringProperty) { return ((StringProperty) veHostProperty).getString(); } @@ -109,7 +162,7 @@ public static String getVeHost(Project project) { public static String getVeBasePath(Project project) { if (project != null) { - Property veBasePathProperty = project.getOptions().getProperty("PROJECT_GENERAL_PROPERTIES", VE_BASE_PATH); + Property veBasePathProperty = project.getOptions().getProperty(ProjectOptions.PROJECT_GENERAL_PROPERTIES, VE_BASE_PATH); if (veBasePathProperty instanceof StringProperty) { return ((StringProperty) veBasePathProperty).getString(); } @@ -182,7 +235,7 @@ public static URIBuilder getVeUrl(Project project) { public static boolean isMigrationAllowed(Project project) { if (project != null) { - Property migrate = project.getOptions().getProperty("PROJECT_GENERAL_PROPERTIES", MDK_MIGRATE_STEREOTYPE); + Property migrate = project.getOptions().getProperty(ProjectOptions.PROJECT_GENERAL_PROPERTIES, MDK_MIGRATE_STEREOTYPE); if (migrate instanceof BooleanProperty) { return ((BooleanProperty) migrate).getBoolean(); } diff --git a/src/main/java/org/openmbee/mdk/options/MDKProjectOptionsGroup.java b/src/main/java/org/openmbee/mdk/options/MDKProjectOptionsGroup.java deleted file mode 100644 index 71a4e1e8c..000000000 --- a/src/main/java/org/openmbee/mdk/options/MDKProjectOptionsGroup.java +++ /dev/null @@ -1,99 +0,0 @@ -package org.openmbee.mdk.options; - -import com.nomagic.magicdraw.core.Project; -import com.nomagic.magicdraw.core.options.ProjectOptions; -import com.nomagic.magicdraw.core.options.ProjectOptionsConfigurator; -import com.nomagic.magicdraw.properties.BooleanProperty; -import com.nomagic.magicdraw.properties.ChoiceProperty; -import com.nomagic.magicdraw.properties.Property; -import com.nomagic.magicdraw.properties.PropertyResourceProvider; -import org.openmbee.mdk.fileexport.ContextExportLevel; - -import java.util.Arrays; - -public class MDKProjectOptionsGroup implements ProjectOptionsConfigurator { - - public static final String PROPERTYGROUP_MDK = "PROPERTYGROUP_MDK"; - - public static final String PROPERTY_AUTOSAVE_MDKMODEL = "PROPERTY_AUTOSAVE_MDKMODEL_ID"; - public static final String PROPERTY_AUTOSAVE_MDKZIP = "PROPERTY_AUTOSAVE_MDKZIP_ID"; - public static final String PROPERTY_CONTEXT_EXPORT_LEVEL = "PROPERTY_CONTEXT_EXPORT_LEVEL_ID"; - - public static final PropertyResourceProvider PROPERTY_RESOURCE_PROVIDER = (key, property) -> ProjectOptionsResources.getString(key); - - public static boolean isAutosaveMDKModel(Project project) { - Property property = project.getOptions().getProperty(ProjectOptions.PROJECT_GENERAL_PROPERTIES, PROPERTY_AUTOSAVE_MDKMODEL); - if (property != null) { - return (boolean) property.getValue(); - } else { - return false; - } - - } - - public static boolean isAutosaveMDKZip(Project project) { - Property property = project.getOptions().getProperty(ProjectOptions.PROJECT_GENERAL_PROPERTIES, PROPERTY_AUTOSAVE_MDKZIP); - if (property != null) { - return (boolean) property.getValue(); - } else { - return false; - } - - } - - public static ContextExportLevel getContextExportLevel(Project project) { - Property property = project.getOptions().getProperty(ProjectOptions.PROJECT_GENERAL_PROPERTIES, PROPERTY_CONTEXT_EXPORT_LEVEL); - if (property != null) { - return ContextExportLevel.valueOf(property.getValueStringRepresentation()); - } else { - return ContextExportLevel.None; - } - } - - @Override - public void afterLoad(ProjectOptions arg0) { - - } - - @Override - public void configure(ProjectOptions projectOptions) { - setAutosaveProperty(projectOptions); - - setAutosaveMdkzipProperty(projectOptions); - - setContextExportLevelProperty(projectOptions); - } - - private void setAutosaveProperty(ProjectOptions projectOptions) { - Property autosaveProperty = projectOptions.getProperty(ProjectOptions.PROJECT_GENERAL_PROPERTIES, PROPERTY_AUTOSAVE_MDKMODEL); - if (autosaveProperty == null) { - autosaveProperty = new BooleanProperty(PROPERTY_AUTOSAVE_MDKMODEL, false); - autosaveProperty.setGroup(PROPERTYGROUP_MDK); - autosaveProperty.setResourceProvider(PROPERTY_RESOURCE_PROVIDER); - projectOptions.addProperty(ProjectOptions.PROJECT_GENERAL_PROPERTIES, autosaveProperty); - } - } - - private void setAutosaveMdkzipProperty(ProjectOptions projectOptions) { - Property autosaveMdkzipProperty = projectOptions.getProperty(ProjectOptions.PROJECT_GENERAL_PROPERTIES, PROPERTY_AUTOSAVE_MDKZIP); - if (autosaveMdkzipProperty == null) { - autosaveMdkzipProperty = new BooleanProperty(PROPERTY_AUTOSAVE_MDKZIP, false); - autosaveMdkzipProperty.setGroup(PROPERTYGROUP_MDK); - autosaveMdkzipProperty.setResourceProvider(PROPERTY_RESOURCE_PROVIDER); - projectOptions.addProperty(ProjectOptions.PROJECT_GENERAL_PROPERTIES, autosaveMdkzipProperty); - } - } - - private void setContextExportLevelProperty(ProjectOptions projectOptions) { - Property contextExportLevelProperty = projectOptions.getProperty(ProjectOptions.PROJECT_GENERAL_PROPERTIES, PROPERTY_CONTEXT_EXPORT_LEVEL); - if (contextExportLevelProperty == null) { - - contextExportLevelProperty = new ChoiceProperty(PROPERTY_CONTEXT_EXPORT_LEVEL, "", Arrays.asList(ContextExportLevel.values())); - contextExportLevelProperty.setGroup(PROPERTYGROUP_MDK); - contextExportLevelProperty.setResourceProvider(PROPERTY_RESOURCE_PROVIDER); - contextExportLevelProperty.setValue(ContextExportLevel.Containment); - projectOptions.addProperty(ProjectOptions.PROJECT_GENERAL_PROPERTIES, contextExportLevelProperty); - } - } - -} diff --git a/src/main/java/org/openmbee/mdk/options/ProjectOptionsResources.java b/src/main/java/org/openmbee/mdk/options/ProjectOptionsResources.java deleted file mode 100644 index 07e585dfa..000000000 --- a/src/main/java/org/openmbee/mdk/options/ProjectOptionsResources.java +++ /dev/null @@ -1,24 +0,0 @@ -package org.openmbee.mdk.options; - -import com.nomagic.magicdraw.resources.ResourceManager; - -public class ProjectOptionsResources { - public static final String BUNDLE_NAME = "gov.nasa.jpl.mbee.mdk.options.ProjectOptionsResources"; - - /** - * Constructs this resource handler. - */ - private ProjectOptionsResources() { - // do nothing. - } - - /** - * Gets resource by key. - * - * @param key key by which to get the resource. - * @return translated resource. - */ - public static String getString(String key) { - return ResourceManager.getStringFor(key, BUNDLE_NAME, ProjectOptionsResources.class.getClassLoader()); - } -} \ No newline at end of file diff --git a/src/main/resources/org/openmbee/mdk/options/EnvironmentOptionsResources.properties b/src/main/resources/org/openmbee/mdk/options/EnvironmentOptionsResources.properties index 9c3460730..66024146a 100644 --- a/src/main/resources/org/openmbee/mdk/options/EnvironmentOptionsResources.properties +++ b/src/main/resources/org/openmbee/mdk/options/EnvironmentOptionsResources.properties @@ -15,5 +15,7 @@ MMS_AUTHENTICATION_CHAIN_DESCRIPTION=Authentication chain used for getting ticke MMS_AUTHENTICATION_CHAIN_DEFAULT=org.openmbee.mdk.tickets.BasicAuthAcquireTicketProcessor,org.openmbee.mdk.tickets.AuthenticationChainError DOCBOOK_TO_PDF_STYLESHEET=DocBook to PDF Stylesheet DOCBOOK_TO_PDF_STYLESHEET_DESCRIPTION=Stores the last DocBook to PDF Stylesheet used while converting DocBook to PDF. +EXPORT_MDKZIP_DIAGRAM_ELEMENTS_MAPPING=Export Diagram Elements Mapping +EXPORT_MDKZIP_DIAGRAM_ELEMENTS_MAPPING_DESCRIPTION=TBD MDK_OPTIONS_NAME=MDK GROUP=MDK diff --git a/src/main/resources/org/openmbee/mdk/options/ProjectOptionsResources.properties b/src/main/resources/org/openmbee/mdk/options/ProjectOptionsResources.properties index 45d4c211a..8112fc6ee 100644 --- a/src/main/resources/org/openmbee/mdk/options/ProjectOptionsResources.properties +++ b/src/main/resources/org/openmbee/mdk/options/ProjectOptionsResources.properties @@ -15,4 +15,10 @@ MDK_PROJECT_OPTIONS_GROUP_DESCRIPTION=Settings for configuring MDK's connection MMS_GROUP=Model Management System (MMS) MMS_GROUP_DESCRIPTION=Configure Model Management System (MMS) settings VE_GROUP=View Editor -VE_GROUP_DESCRIPTION=Configure View Editor settings \ No newline at end of file +VE_GROUP_DESCRIPTION=Configure View Editor settings +PROPERTY_AUTOSAVE_MDKMODEL=Autosave MDK Model Json +PROPERTY_AUTOSAVE_MDKMODE_DESCRIPTION=TBD +PROPERTY_AUTOSAVE_MDKZIP=Autosave MDK Zip +PROPERTY_AUTOSAVE_MDKZIP_DESCRIPTION=TBD +PROPERTY_CONTEXT_EXPORT_LEVEL=Export Context Level +PROPERTY_CONTEXT_EXPORT_LEVEL_DESCRIPTION=TBD From 67a0e93103060763b4082eaa4be88c4ac01d9c96 Mon Sep 17 00:00:00 2001 From: Doris Lam Date: Mon, 1 Apr 2024 17:23:40 -0700 Subject: [PATCH 16/19] fix typo --- .../org/openmbee/mdk/options/ProjectOptionsResources.properties | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main/resources/org/openmbee/mdk/options/ProjectOptionsResources.properties b/src/main/resources/org/openmbee/mdk/options/ProjectOptionsResources.properties index 8112fc6ee..10eb3e8d0 100644 --- a/src/main/resources/org/openmbee/mdk/options/ProjectOptionsResources.properties +++ b/src/main/resources/org/openmbee/mdk/options/ProjectOptionsResources.properties @@ -17,7 +17,7 @@ MMS_GROUP_DESCRIPTION=Configure Model Management System (MMS) settings VE_GROUP=View Editor VE_GROUP_DESCRIPTION=Configure View Editor settings PROPERTY_AUTOSAVE_MDKMODEL=Autosave MDK Model Json -PROPERTY_AUTOSAVE_MDKMODE_DESCRIPTION=TBD +PROPERTY_AUTOSAVE_MDKMODEL_DESCRIPTION=TBD PROPERTY_AUTOSAVE_MDKZIP=Autosave MDK Zip PROPERTY_AUTOSAVE_MDKZIP_DESCRIPTION=TBD PROPERTY_CONTEXT_EXPORT_LEVEL=Export Context Level From 1daada0bfa505c96dda835ec9e8275a4021355da Mon Sep 17 00:00:00 2001 From: Doris Lam Date: Tue, 2 Apr 2024 11:24:29 -0700 Subject: [PATCH 17/19] comment out unused project options --- .../java/org/openmbee/mdk/options/MDKProjectOptions.java | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/src/main/java/org/openmbee/mdk/options/MDKProjectOptions.java b/src/main/java/org/openmbee/mdk/options/MDKProjectOptions.java index 57a3634cf..7bca8d77f 100644 --- a/src/main/java/org/openmbee/mdk/options/MDKProjectOptions.java +++ b/src/main/java/org/openmbee/mdk/options/MDKProjectOptions.java @@ -46,9 +46,11 @@ public static void init(ProjectOptions var0) { MDKProjectOptions.setOption(var0, VE_HOST_URL,""); MDKProjectOptions.setOption(var0, VE_BASE_PATH,""); MDKProjectOptions.setOption(var0, MDK_MIGRATE_STEREOTYPE, true); - MDKProjectOptions.setOption(var0, PROPERTY_AUTOSAVE_MDKMODEL, false); - MDKProjectOptions.setOption(var0, PROPERTY_AUTOSAVE_MDKZIP, false); - MDKProjectOptions.setOption(var0, PROPERTY_CONTEXT_EXPORT_LEVEL, Arrays.asList(ContextExportLevel.values()), ContextExportLevel.Containment); + + //below were added by LieberLieber's JSON export but doesn't seem to be used/called anywhere + //MDKProjectOptions.setOption(var0, PROPERTY_AUTOSAVE_MDKMODEL, false); + //MDKProjectOptions.setOption(var0, PROPERTY_AUTOSAVE_MDKZIP, false); + //MDKProjectOptions.setOption(var0, PROPERTY_CONTEXT_EXPORT_LEVEL, Arrays.asList(ContextExportLevel.values()), ContextExportLevel.Containment); } public static void setOption(ProjectOptions var0, String projectOption, String newValue) { From 6a9498a96059139cbe2fb292ee791468add79376 Mon Sep 17 00:00:00 2001 From: Doris Lam Date: Tue, 2 Apr 2024 13:40:22 -0700 Subject: [PATCH 18/19] clean up old lines in gradle build, update csm libz ref to 2022x refresh2 hotfix 1 --- README.md | 2 +- build.gradle | 13 +------------ 2 files changed, 2 insertions(+), 13 deletions(-) diff --git a/README.md b/README.md index d5f649a59..37a9566d4 100644 --- a/README.md +++ b/README.md @@ -1,6 +1,6 @@ # Cameo Model Development Kit (MDK) -[![GitHub release (latest SemVer)](https://img.shields.io/github/v/release/Open-MBEE/mdk?label=download)](https://github.com/Open-MBEE/mdk/releases/latest) [![Maven Central](https://img.shields.io/maven-central/v/org.openmbee.mdk.magic/mdk)](https://search.maven.org/artifact/org.openmbee.mdk.magic/mdk) [![CircleCI](https://circleci.com/gh/Open-MBEE/mdk.svg?style=shield)](https://circleci.com/gh/Open-MBEE/mdk) +[![GitHub release (latest SemVer)](https://img.shields.io/github/v/release/Open-MBEE/mdk?label=download)](https://github.com/Open-MBEE/mdk/releases/latest) [![Maven Central](https://img.shields.io/maven-central/v/org.openmbee.mdk.magic/mdk)](https://search.maven.org/artifact/org.openmbee.mdk.magic/mdk) [![CircleCI](https://circleci.com/gh/Open-MBEE/exec-cameo-mdk.svg?style=shield)](https://circleci.com/gh/Open-MBEE/mdk) Cameo MDK is a plugin for [Cameo Systems Modeler](https://www.nomagic.com/products/cameo-systems-modeler) and other No Magic environment bundles that’s primary purposes are to sync models with the [MMS](https://github.com/Open-MBEE/mms-alfresco) and implement the [DocGen](src/main/dist/manual) language, which allows modelers to dynamically generate documents in a model-based approach using the view and viewpoint concept. diff --git a/build.gradle b/build.gradle index 8f3f66d49..f51e7ca67 100644 --- a/build.gradle +++ b/build.gradle @@ -171,10 +171,6 @@ dependencies { implementation group: 'net.sf.opencsv', name: 'opencsv', version: '2.3' // implementation group: 'com.opencsv', name: 'opencsv', version: '3.8+' - // ActiveMQ - //implementation group: 'org.apache.activemq', name: 'activemq-all', version: '5.9.1' - // implementation group: 'org.apache.activemq', name: 'activemq-all', version: '5.14.0+' - // Jackson implementation group: 'com.fasterxml.jackson.core', name: 'jackson-databind', version: '2.8.3' @@ -192,9 +188,6 @@ dependencies { // Apache Commons CLI implementation group: 'commons-cli', name: 'commons-cli', version: '1.4' - //OpenMBEE MMS Java Client - //implementation group: 'org.openmbee.mms', name: 'mms-java-client', version: '3.4.2' - implementation group: 'com.beust', name: 'jcommander', version: '1.72' // Test Dependencies @@ -221,9 +214,7 @@ dependencies { } // Default Dev Workflow, this will only correctly pull from the local ./libz flatDir else { - preImplementation group: 'com.nomagic', name: 'democsm', version: '2022xRefresh1', classifier: 'Cameo_Systems_Modeler_2022x_Refresh1_HF1_no_install', ext: 'zip' -// preCompile group: 'com.nomagic', name: 'sysml', version: '2021x', classifier: 'SysML_Plugin_2021x', ext: 'zip' -// preCompile group: 'com.nomagic', name: 'cst', version: '2021x', classifier: 'Cameo_Simulation_Toolkit_Plugin_2021x', ext: 'zip' + preImplementation group: 'com.nomagic', name: 'democsm', version: '2022xRefresh2', classifier: 'Cameo_Systems_Modeler_2022x_Refresh2_HF1_no_install', ext: 'zip' } preImplementation group: 'org.apache.fop', name: 'fop', version: '2.9', classifier: fopNameVersion + '-bin', ext: 'zip' @@ -339,7 +330,6 @@ task testsJar(type: Jar, dependsOn: testClasses) { exclude 'org/openmbee/mdk/test/framework/**' exclude 'org/**' exclude 'worker/**' - //include 'gov/nasa/jpl/mbee/mdk/test/tests/**' } task testsHackJar(type: Jar, dependsOn: testClasses) { @@ -349,7 +339,6 @@ task testsHackJar(type: Jar, dependsOn: testClasses) { include 'org/openmbee/mdk/test/framework/**' include 'org/**' include 'worker/**' - //exclude 'gov/nasa/jpl/mbee/mdk/test/tests/**' manifest { attributes( From 566d9f0aa7cd95a88442131f7282c8fc53e87d6d Mon Sep 17 00:00:00 2001 From: Doris Lam Date: Tue, 2 Apr 2024 13:49:06 -0700 Subject: [PATCH 19/19] update version --- gradle.properties | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/gradle.properties b/gradle.properties index 4ec0a3b06..8ab140a8d 100644 --- a/gradle.properties +++ b/gradle.properties @@ -1,4 +1,4 @@ -version=6.0.1 +version=6.1.0 group=org.openmbee.mdk.magic descriptorFile=MDR_Plugin_Model_Development_Kit_91110_descriptor.xml magicdDrawGroupName=org.openmbee.mdk