diff --git a/build.gradle b/build.gradle index a47a85356..ef06b11d4 100644 --- a/build.gradle +++ b/build.gradle @@ -191,6 +191,10 @@ dependencies { implementation group: 'com.beust', name: 'jcommander', version: '1.72' + // jsoup HTML parser library @ https://jsoup.org/ + implementation group: 'org.jsoup', name: 'jsoup', version: '1.17.2' + + // Test Dependencies //testImplementation 'junit:junit:4.11' testImplementation group: 'org.gradle', name: 'gradle-core', version: '6.1.1' @@ -225,10 +229,13 @@ dependencies { 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-graphics', version: '11.0.2', classifier: 'win' + distribution group: 'org.openjfx', name: 'javafx-base', 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' - + distribution group: 'org.openjfx', name: 'javafx-graphics', version: '11.0.2', classifier: 'mac' + distribution group: 'org.openjfx', name: 'javafx-base', 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. @@ -292,7 +299,7 @@ task extractDependencies { 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 -> @@ -300,7 +307,7 @@ task extractDependencies { from zipTree(archive) into 'build/dependency-cache/extracted/magicdraw' } - + } delete 'build/dependency-cache/extracted/magicdraw/plugins/com.nomagic.conceptmodeler' } @@ -579,7 +586,7 @@ nexusPublishing { artifactoryPublish { publications('mavenJava') - + } artifactoryPublish.dependsOn distZip diff --git a/gradle.properties b/gradle.properties index 8ab140a8d..11290532f 100644 --- a/gradle.properties +++ b/gradle.properties @@ -1,4 +1,4 @@ -version=6.1.0 +version=6.1.1 group=org.openmbee.mdk.magic descriptorFile=MDR_Plugin_Model_Development_Kit_91110_descriptor.xml magicdDrawGroupName=org.openmbee.mdk 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 9e6d07081..9ede7bd57 100644 --- a/src/main/java/org/openmbee/mdk/api/incubating/MDKConstants.java +++ b/src/main/java/org/openmbee/mdk/api/incubating/MDKConstants.java @@ -74,6 +74,7 @@ public class MDKConstants { MESSAGES_NODE = "messages", REJECTED_NODE = "rejected", SOURCE_FIELD = "source", + ARCHIVED_FIELD = "_archived", DELETED_FIELD = "deleted", MAGICDRAW_SOURCE_VALUE = "magicdraw", ELEMENT_TYPE_VALUE = "Element", diff --git a/src/main/java/org/openmbee/mdk/emf/EMFExporter.java b/src/main/java/org/openmbee/mdk/emf/EMFExporter.java index 0b59794eb..95fa73359 100644 --- a/src/main/java/org/openmbee/mdk/emf/EMFExporter.java +++ b/src/main/java/org/openmbee/mdk/emf/EMFExporter.java @@ -25,11 +25,15 @@ import org.openmbee.mdk.json.JacksonUtils; import org.openmbee.mdk.util.MDUtils; import org.openmbee.mdk.util.Utils; +import org.w3c.dom.html.HTMLDocument; import org.eclipse.emf.ecore.EDataType; import org.eclipse.emf.ecore.EObject; import org.eclipse.emf.ecore.EReference; import org.eclipse.emf.ecore.EStructuralFeature; import org.eclipse.emf.ecore.util.EcoreUtil; +import org.jsoup.Jsoup; +import org.jsoup.nodes.Document; +import org.jsoup.select.Elements; import java.lang.reflect.Field; import java.lang.reflect.Modifier; @@ -39,6 +43,7 @@ import java.util.function.BiFunction; import java.util.stream.Collectors; import java.io.Reader; +import java.io.StringReader; public class EMFExporter implements BiFunction { @Override @@ -161,7 +166,13 @@ private enum Processor { DOCUMENTATION_PRE( (element, project, objectNode) -> { //Todo: FIgure out how to read this stuff and parse the persistedLocalChangelog = new Changelog<>(); Collection persistedLocalSyncElements = SyncElements.getAllByType(project, SyncElement.Type.LOCAL); for (SyncElement syncElement : persistedLocalSyncElements) { @@ -154,8 +168,10 @@ else if (value instanceof Element) { localUpdated = localChangelog.get(Changelog.ChangeType.UPDATED), localDeleted = localChangelog.get(Changelog.ChangeType.DELETED); + progressStatus.increase(); // BUILD COMPLETE MMS CHANGELOG - + progressStatus.setDescription("Coordinated Sync: Building Server Changelog"); + progressStatus.cancelIfCanceled(); Changelog persistedMmsChangelog = new Changelog<>(); Collection persistedMmsSyncElements = SyncElements.getAllByType(project, SyncElement.Type.MMS); for (SyncElement syncElement : persistedMmsSyncElements) { @@ -177,9 +193,9 @@ else if (value instanceof Element) { Map mmsJsons = new HashMap<>(elementIdsToGet.size()); // Get latest json for element added/changed from MMS - + progressStatus.increase(); if (!elementIdsToGet.isEmpty()) { - progressStatus.setDescription("Getting " + elementIdsToGet.size() + " added/changed element" + (elementIdsToGet.size() != 1 ? "s" : "") + " from MMS"); + progressStatus.setDescription("Coordinated Sync: Getting " + elementIdsToGet.size() + " added/changed element" + (elementIdsToGet.size() != 1 ? "s" : "") + " from MMS"); File responseFile; ObjectNode response; try { @@ -220,8 +236,8 @@ else if (value instanceof Element) { } // NEW CONFLICT DETECTION - - progressStatus.setDescription("Detecting conflicts"); + progressStatus.increase(); + progressStatus.setDescription("Coordinated Sync: Detecting conflicts"); Map, Changelog.Change>> conflictedChanges = new LinkedHashMap<>(), unconflictedChanges = new LinkedHashMap<>(); localChangelog.findConflicts(mmsChangelog, (change, change2) -> change != null && change2 != null, conflictedChanges, unconflictedChanges); @@ -305,13 +321,13 @@ else if (shouldUpdate && mmsChange != null) { } // POINT OF NO RETURN - + progressStatus.increase(); // COMMIT UNCONFLICTED CREATIONS AND UPDATES TO MMS String projectId = Converters.getIProjectToIdConverter().apply(project.getPrimaryProject()); String refId = MDUtils.getBranchId(project); boolean shouldLogNoLocalChanges = shouldCommit; if (shouldCommit && !localElementsToPost.isEmpty()) { - progressStatus.setDescription("Committing creations and updates to MMS"); + progressStatus.setDescription("Coordinated Sync: Committing creations and updates to MMS"); LinkedList postElements = new LinkedList<>(); for (Element element : localElementsToPost.values()) { ObjectNode elementObjectNode = Converters.getElementToJsonConverter().apply(element, project); @@ -345,12 +361,12 @@ else if (shouldUpdate && mmsChange != null) { shouldLogNoLocalChanges = false; } } - + progressStatus.increase(); // COMMIT UNCONFLICTED DELETIONS TO MMS // NEEDS TO BE AFTER LOCAL; EX: MOVE ELEMENT OUT ON MMS, DELETE OWNER LOCALLY, WHAT HAPPENS? if (shouldCommit && shouldCommitDeletes && !deleteElements.isEmpty()) { - progressStatus.setDescription("Committing deletions to MMS"); + progressStatus.setDescription("Coordinated Sync: Committing deletions to MMS"); try { File file = MMSUtils.createEntityFile(this.getClass(), ContentType.APPLICATION_JSON, deleteElements, MMSUtils.JsonBlobType.ELEMENT_ID); HttpRequestBase elementsDeleteRequest = MMSUtils.prepareEndpointBuilderBasicJsonDeleteRequest(MMSElementsEndpoint.builder(), project, file) @@ -373,7 +389,7 @@ else if (shouldUpdate && mmsChange != null) { } // OUTPUT RESULT OF LOCAL CHANGES - + progressStatus.increase(); if (shouldLogNoLocalChanges) { Application.getInstance().getGUILog().log("[INFO] No local changes to commit to MMS."); } @@ -381,7 +397,7 @@ else if (shouldUpdate && mmsChange != null) { // ADD CREATED ELEMENTS LOCALLY FROM MMS // CHANGE UPDATED ELEMENTS LOCALLY FROM MMS // REMOVE DELETED ELEMENTS LOCALLY FROM MMS - + progressStatus.increase(); if (shouldUpdate) { listener.setDisabled(true); @@ -401,8 +417,8 @@ else if (shouldUpdate && mmsChange != null) { } // HANDLE CONFLICTS - - progressStatus.setDescription("Finishing up"); + progressStatus.increase(); + progressStatus.setDescription("Coordinated Sync: Finishing up"); Set localConflictedElements = new HashSet<>(); Set mmsConflictedElements = new HashSet<>(); @@ -422,7 +438,7 @@ else if (shouldUpdate && mmsChange != null) { } ElementValidator elementValidator = new ElementValidator("CSync Conflict Validation", ElementValidator.buildElementPairs(localConflictedElements, project), mmsConflictedElements, project); - elementValidator.run(progressStatus); + ProgressStatusRunner.runWithProgressStatus(elementValidator, "Element Validation", true, 0); if (!elementValidator.getInvalidElements().isEmpty()) { Application.getInstance().getGUILog().log("[INFO] There are potential conflicts in " + elementValidator.getInvalidElements().size() + " element" + (elementValidator.getInvalidElements().size() != 1 ? "s" : "") + " between MMS and local changes. Please resolve them and re-sync."); vss.add(elementValidator.getValidationSuite()); @@ -447,7 +463,7 @@ else if (shouldUpdate && mmsChange != null) { } // CLEAR IN-MEMORY AND PERSIST UNPROCESSED & FAILURES - + progressStatus.increase(); listener.setDisabled(true); Project project = Application.getInstance().getProject(); if (!SessionManager.getInstance().isSessionCreated(project)) { @@ -502,7 +518,7 @@ else if (shouldUpdate && mmsChange != null) { SessionManager.getInstance().closeSession(project); listener.setDisabled(false); - + progressStatus.increase(); // SUCCESS failure = false; } diff --git a/src/main/java/org/openmbee/mdk/mms/sync/manual/ManualSyncRunner.java b/src/main/java/org/openmbee/mdk/mms/sync/manual/ManualSyncRunner.java index 3dd32ebce..66132186d 100644 --- a/src/main/java/org/openmbee/mdk/mms/sync/manual/ManualSyncRunner.java +++ b/src/main/java/org/openmbee/mdk/mms/sync/manual/ManualSyncRunner.java @@ -53,7 +53,8 @@ public void run(ProgressStatus progressStatus) { progressStatus.setIndeterminate(true); ProjectValidator pv = new ProjectValidator(project); - pv.validate(); + + pv.run(progressStatus); if (pv.hasErrors()) { Application.getInstance().getGUILog().log("[ERROR] Project validation could not be completed. Manual validation aborted."); return; @@ -64,8 +65,8 @@ public void run(ProgressStatus progressStatus) { } if (project.isRemote()) { - BranchValidator bv = new BranchValidator(project); - bv.validate(null, false); + BranchValidator bv = new BranchValidator(project, false); + bv.run(null); if (bv.hasErrors()) { Application.getInstance().getGUILog().log("[ERROR] Branch validation could not be completed. Manual validation aborted."); return; diff --git a/src/main/java/org/openmbee/mdk/mms/validation/BranchValidator.java b/src/main/java/org/openmbee/mdk/mms/validation/BranchValidator.java index e59d84562..0ee4f0fd0 100644 --- a/src/main/java/org/openmbee/mdk/mms/validation/BranchValidator.java +++ b/src/main/java/org/openmbee/mdk/mms/validation/BranchValidator.java @@ -13,6 +13,8 @@ import com.nomagic.magicdraw.core.project.ProjectDescriptorsFactory; import com.nomagic.magicdraw.esi.EsiUtils; import com.nomagic.task.ProgressStatus; +import com.nomagic.task.RunnableWithProgress; + import org.openmbee.mdk.actions.ClipboardAction; import org.openmbee.mdk.api.incubating.MDKConstants; import org.openmbee.mdk.api.incubating.convert.Converters; @@ -39,9 +41,10 @@ import java.text.NumberFormat; import java.util.*; -public class BranchValidator { +public class BranchValidator implements RunnableWithProgress { private final Project project; + private boolean allBranches; private boolean errors; private ValidationSuite validationSuite = new ValidationSuite("structure"); // private ValidationRule twcMissingBranchValidationRule = new ValidationRule("Missing in Client", "Branch shall exist in TWC if it exists in MMS.", ViolationSeverity.WARNING); @@ -49,15 +52,16 @@ public class BranchValidator { private ValidationRule branchEquivalenceValidationRule = new ValidationRule("Branch Equivalence", "Branch shall be represented in MagicDraw and MMS equivalently.", ViolationSeverity.ERROR); private ValidationRule mmsBuildingBranchValidationRule = new ValidationRule("Building on Server", "Branch shall be completely built on MMS before it is used.", ViolationSeverity.WARNING); - public BranchValidator(Project project) { + public BranchValidator(Project project, boolean allBranches) { this.project = project; + this.allBranches = allBranches; // validationSuite.addValidationRule(twcMissingBranchValidationRule); validationSuite.addValidationRule(mmsMissingBranchValidationRule); validationSuite.addValidationRule(branchEquivalenceValidationRule); validationSuite.addValidationRule(mmsBuildingBranchValidationRule); } - public void validate(ProgressStatus progressStatus, boolean allBranches) { + public void run(ProgressStatus progressStatus) { if (project == null) { return; } @@ -82,7 +86,7 @@ public void validate(ProgressStatus progressStatus, boolean allBranches) { } Collection targetBranches = null; - if (allBranches) { + if (this.allBranches) { try { ProjectDescriptor projectDescriptor = ProjectDescriptorsFactory.createAnyRemoteProjectDescriptor(project); targetBranches = EsiUtils.getBranches(projectDescriptor); @@ -107,7 +111,7 @@ public void validate(ProgressStatus progressStatus, boolean allBranches) { String entryKey; if ((value = branchJson.get(MDKConstants.ID_KEY)) != null && value.isTextual()) { entryKey = value.asText(); - if (allBranches || entryKey.equals(currentBranch)) { + if (this.allBranches || entryKey.equals(currentBranch)) { clientBranches.put(entryKey, new Pair<>(branch, branchJson)); } } @@ -135,7 +139,7 @@ public void validate(ProgressStatus progressStatus, boolean allBranches) { String entryKey; if ((value = refObjectNode.get(MDKConstants.ID_KEY)) != null && value.isTextual()) { entryKey = value.asText(); - if (allBranches || entryKey.equals(currentBranch)) { + if (this.allBranches || entryKey.equals(currentBranch)) { serverBranches.put(entryKey, refObjectNode); } } @@ -186,7 +190,11 @@ else if (serverBranch == null) { serverBranch.remove(MDKConstants.STATUS_KEY); serverBranch.remove(MDKConstants.PARENT_COMMIT_ID); - clientBranch.getValue().put(MDKConstants.DELETED_FIELD, false); + clientBranch.getValue().put(MDKConstants.ARCHIVED_FIELD, false); + if (serverBranch.get(MDKConstants.DELETED_FIELD) != null) { + serverBranch.set(MDKConstants.ARCHIVED_FIELD, serverBranch.get(MDKConstants.DELETED_FIELD)); + serverBranch.remove(MDKConstants.DELETED_FIELD); + } JsonNode diff = JsonPatchFunction.getInstance().apply(clientBranch.getValue(), serverBranch); if (diff != null && diff.isArray() && diff.size() > 0) { ValidationRuleViolation v = new ValidationRuleViolation(project.getPrimaryModel(), "[BRANCH NOT EQUIVALENT] The Teamwork Cloud branch \"" + clientBranch.getKey().getName() + "\" is not equivalent to the corresponding MMS branch."); diff --git a/src/main/java/org/openmbee/mdk/mms/validation/ProjectValidator.java b/src/main/java/org/openmbee/mdk/mms/validation/ProjectValidator.java index 951059a1b..979522b77 100644 --- a/src/main/java/org/openmbee/mdk/mms/validation/ProjectValidator.java +++ b/src/main/java/org/openmbee/mdk/mms/validation/ProjectValidator.java @@ -9,7 +9,8 @@ import com.nomagic.magicdraw.core.ProjectUtilities; import com.nomagic.magicdraw.esi.EsiUtils; import com.nomagic.magicdraw.esi.EsiUtils.EsiBranchInfo; - +import com.nomagic.task.ProgressStatus; +import com.nomagic.task.RunnableWithProgress; import com.nomagic.magicdraw.teamwork2.ITeamworkService; import com.nomagic.magicdraw.teamwork2.TeamworkService; import org.openmbee.mdk.api.incubating.MDKConstants; @@ -25,7 +26,8 @@ import org.openmbee.mdk.validation.ViolationSeverity; import org.apache.http.client.methods.HttpRequestBase; import org.apache.http.entity.ContentType; -import org.openmbee.mdk.mms.endpoints.MMSProjectsEndpoint; +import org.openmbee.mdk.mms.endpoints.MMSProjectEndpoint; +import org.openmbee.mdk.mms.endpoints.MMSEndpointBuilderConstants; import javax.swing.JOptionPane; import java.io.File; @@ -56,7 +58,7 @@ */ -public class ProjectValidator { +public class ProjectValidator implements RunnableWithProgress { private final Project project; private boolean errors; @@ -102,7 +104,8 @@ public void updateTWCServiceToProject(JsonNode projectJson) { MMSUtils.JsonBlobType.PROJECT); // generate project post request HttpRequestBase request = MMSUtils - .prepareEndpointBuilderBasicJsonPostRequest(MMSProjectsEndpoint.builder(), project, sendData) + .prepareEndpointBuilderBasicJsonPostRequest(MMSProjectEndpoint.builder(), project, sendData) + .addParam(MMSEndpointBuilderConstants.URI_PROJECT_SUFFIX, Converters.getIProjectToIdConverter().apply(project.getPrimaryProject())) .build(); // do project post request MMSUtils.sendMMSRequest(project, request); @@ -130,13 +133,20 @@ public void checkIfTWCServiceChanged(JsonNode projectJson) { } } - public void validate() { + @Override + public void run(ProgressStatus progressStatus) { ObjectNode response; try { - HttpRequestBase projectsRequest = MMSUtils.prepareEndpointBuilderBasicGet(MMSProjectsEndpoint.builder(), project).build(); - File responseFile = MMSUtils.sendMMSRequest(project, projectsRequest); + HttpRequestBase projectRequest = MMSUtils.prepareEndpointBuilderBasicGet(MMSProjectEndpoint.builder(), project) + .addParam(MMSEndpointBuilderConstants.URI_PROJECT_SUFFIX, Converters.getIProjectToIdConverter().apply(project.getPrimaryProject())) + .build(); + if (progressStatus != null) { + progressStatus.setDescription("Retrieving Project(s)"); + progressStatus.setIndeterminate(true); + } + File responseFile = MMSUtils.sendMMSRequest(project, projectRequest); try (JsonParser jsonParser = JacksonUtils.getJsonFactory().createParser(responseFile)) { response = JacksonUtils.parseJsonObject(jsonParser); } diff --git a/src/main/java/org/openmbee/mdk/util/MDUtils.java b/src/main/java/org/openmbee/mdk/util/MDUtils.java index eaa6fcd75..d4d4a159b 100644 --- a/src/main/java/org/openmbee/mdk/util/MDUtils.java +++ b/src/main/java/org/openmbee/mdk/util/MDUtils.java @@ -1,6 +1,5 @@ package org.openmbee.mdk.util; -import com.nomagic.log.LoggerBridge; import com.nomagic.magicdraw.core.Application; import com.nomagic.magicdraw.core.Project; import com.nomagic.magicdraw.core.ProjectUtilities; @@ -10,7 +9,6 @@ import com.nomagic.magicdraw.ui.browser.BrowserTabTree; import com.nomagic.magicdraw.ui.browser.Node; import com.nomagic.magicdraw.uml.BaseElement; -import com.nomagic.magicdraw.uml.symbols.DiagramPaintContext; import com.nomagic.magicdraw.uml.symbols.DiagramPresentationElement; import com.nomagic.magicdraw.uml.symbols.PresentationElement; import com.nomagic.uml2.ext.magicdraw.auxiliaryconstructs.mdmodels.Model; @@ -18,24 +16,15 @@ import com.nomagic.uml2.ext.magicdraw.classes.mdkernel.Slot; import com.nomagic.uml2.ext.magicdraw.classes.mdkernel.TaggedValue; import com.nomagic.uml2.ext.magicdraw.classes.mdkernel.ValueSpecification; -import com.nomagic.utils.CameoUtilities; -import com.nomagic.utils.FileHelper; import org.openmbee.mdk.api.incubating.MDKConstants; import org.openmbee.mdk.api.incubating.convert.Converters; import org.openmbee.mdk.docgen.DocGenUtils; -import org.apache.batik.anim.dom.SAXSVGDocumentFactory; -import org.apache.batik.util.XMLResourceDescriptor; import org.eclipse.emf.ecore.EObject; import org.eclipse.emf.ecore.util.EcoreUtil; -import org.w3c.dom.Document; import javax.annotation.CheckForNull; -import javax.xml.transform.Transformer; import javax.xml.transform.TransformerException; -import javax.xml.transform.TransformerFactory; -import javax.xml.transform.dom.DOMSource; -import javax.xml.transform.stream.StreamResult; import java.awt.event.ActionEvent; import java.io.*; import java.nio.charset.Charset; @@ -44,8 +33,6 @@ import java.util.regex.Matcher; import java.util.regex.Pattern; -import static com.nomagic.magicdraw.uml.DiagramTypeConstants.*; - /** * A collection of utility functions for accessing the MagicDraw (MD) * application.