diff --git a/build.gradle b/build.gradle index 64b0d734f..7101a162d 100644 --- a/build.gradle +++ b/build.gradle @@ -131,7 +131,7 @@ dependencies { // Other dependencies we're unable to resolve via standard repositories if (buildAccess == 'internal') { - preCompile group: 'gov.nasa.jpl.cae.magicdraw', name: 'cae-magicdraw-core', version: '3.3.2', ext: 'zip' + preCompile group: 'gov.nasa.jpl.cae.magicdraw', name: 'cae-magicdraw-core', version: '3.3.3', ext: 'zip' } else { preCompile group: 'com.nomagic', name: 'magicdraw', version: '185sp3', classifier: 'MagicDraw_185_sp3_no_install', ext: 'zip' diff --git a/gradle.properties b/gradle.properties index 58c24028a..ddcb3591a 100644 --- a/gradle.properties +++ b/gradle.properties @@ -1,4 +1,4 @@ -version=3.3.2 +version=3.3.3 group=org.openmbee.magicdraw.mdk descriptorFile=MDR_Plugin_Model_Development_Kit_91110_descriptor.xml magicdDrawGroupName=gov.nasa.jpl.cae.magicdraw.mdk diff --git a/src/main/java/gov/nasa/jpl/mbee/mdk/MMSSyncPlugin.java b/src/main/java/gov/nasa/jpl/mbee/mdk/MMSSyncPlugin.java index e68ac583f..14efb055c 100644 --- a/src/main/java/gov/nasa/jpl/mbee/mdk/MMSSyncPlugin.java +++ b/src/main/java/gov/nasa/jpl/mbee/mdk/MMSSyncPlugin.java @@ -6,8 +6,8 @@ import com.nomagic.magicdraw.plugins.Plugin; import gov.nasa.jpl.mbee.mdk.mms.sync.coordinated.CoordinatedSyncProjectEventListenerAdapter; import gov.nasa.jpl.mbee.mdk.mms.sync.delta.DeltaSyncProjectEventListenerAdapter; -import gov.nasa.jpl.mbee.mdk.mms.sync.jms.JMSSyncProjectEventListenerAdapter; -import gov.nasa.jpl.mbee.mdk.mms.sync.local.LocalSyncProjectEventListenerAdapter; +import gov.nasa.jpl.mbee.mdk.mms.sync.local.LocalDeltaProjectEventListenerAdapter; +import gov.nasa.jpl.mbee.mdk.mms.sync.mms.MMSDeltaProjectEventListenerAdapter; import gov.nasa.jpl.mbee.mdk.mms.sync.status.SyncStatusProjectEventListenerAdapter; import gov.nasa.jpl.mbee.mdk.util.TaskRunner; @@ -18,8 +18,8 @@ */ public class MMSSyncPlugin extends Plugin { private static MMSSyncPlugin instance; - private LocalSyncProjectEventListenerAdapter localSyncProjectEventListenerAdapter; - private JMSSyncProjectEventListenerAdapter jmsSyncProjectEventListenerAdapter; + private LocalDeltaProjectEventListenerAdapter localDeltaProjectEventListenerAdapter; + private MMSDeltaProjectEventListenerAdapter mmsDeltaProjectEventListenerAdapter; private DeltaSyncProjectEventListenerAdapter deltaSyncProjectEventListenerAdapter; private CoordinatedSyncProjectEventListenerAdapter coordinatedSyncProjectEventListenerAdapter; private SyncStatusProjectEventListenerAdapter syncStatusProjectEventListenerAdapter; @@ -31,12 +31,12 @@ public static MMSSyncPlugin getInstance() { return instance; } - public LocalSyncProjectEventListenerAdapter getLocalSyncProjectEventListenerAdapter() { - return localSyncProjectEventListenerAdapter; + public LocalDeltaProjectEventListenerAdapter getLocalDeltaProjectEventListenerAdapter() { + return localDeltaProjectEventListenerAdapter; } - public JMSSyncProjectEventListenerAdapter getJmsSyncProjectEventListenerAdapter() { - return jmsSyncProjectEventListenerAdapter; + public MMSDeltaProjectEventListenerAdapter getMmsDeltaProjectEventListenerAdapter() { + return mmsDeltaProjectEventListenerAdapter; } public DeltaSyncProjectEventListenerAdapter getDeltaSyncProjectEventListenerAdapter() { @@ -57,8 +57,8 @@ public void init() { Application.getInstance().getProjectsManager().addProjectListener(coordinatedSyncProjectEventListenerAdapter = new CoordinatedSyncProjectEventListenerAdapter()); Application.getInstance().getProjectsManager().addProjectListener(deltaSyncProjectEventListenerAdapter = new DeltaSyncProjectEventListenerAdapter()); // Common and MMS clear their respective inMemoryChangelogs on save, so it needs to go after coordinated and delta which use it. - Application.getInstance().getProjectsManager().addProjectListener(localSyncProjectEventListenerAdapter = new LocalSyncProjectEventListenerAdapter()); - Application.getInstance().getProjectsManager().addProjectListener(jmsSyncProjectEventListenerAdapter = new JMSSyncProjectEventListenerAdapter()); + Application.getInstance().getProjectsManager().addProjectListener(localDeltaProjectEventListenerAdapter = new LocalDeltaProjectEventListenerAdapter()); + Application.getInstance().getProjectsManager().addProjectListener(mmsDeltaProjectEventListenerAdapter = new MMSDeltaProjectEventListenerAdapter()); Application.getInstance().getProjectsManager().addProjectListener(syncStatusProjectEventListenerAdapter = new SyncStatusProjectEventListenerAdapter()); Application.getInstance().addSaveParticipant(coordinatedSyncProjectEventListenerAdapter); diff --git a/src/main/java/gov/nasa/jpl/mbee/mdk/actions/ClassToComponentRefactorWithIDAction.java b/src/main/java/gov/nasa/jpl/mbee/mdk/actions/ClassToComponentRefactorWithIDAction.java index 6f926db08..486bc8185 100644 --- a/src/main/java/gov/nasa/jpl/mbee/mdk/actions/ClassToComponentRefactorWithIDAction.java +++ b/src/main/java/gov/nasa/jpl/mbee/mdk/actions/ClassToComponentRefactorWithIDAction.java @@ -10,8 +10,8 @@ import com.nomagic.uml2.ext.magicdraw.classes.mdkernel.Element; import com.nomagic.uml2.ext.magicdraw.components.mdbasiccomponents.Component; import gov.nasa.jpl.mbee.mdk.api.incubating.convert.Converters; -import gov.nasa.jpl.mbee.mdk.mms.sync.local.LocalSyncProjectEventListenerAdapter; -import gov.nasa.jpl.mbee.mdk.mms.sync.local.LocalSyncTransactionCommitListener; +import gov.nasa.jpl.mbee.mdk.mms.sync.local.LocalDeltaProjectEventListenerAdapter; +import gov.nasa.jpl.mbee.mdk.mms.sync.local.LocalDeltaTransactionCommitListener; import gov.nasa.jpl.mbee.mdk.util.Utils; import java.awt.event.ActionEvent; @@ -35,7 +35,7 @@ public void actionPerformed(ActionEvent e) { if (con == null || !con) { return; } - LocalSyncTransactionCommitListener listener = LocalSyncProjectEventListenerAdapter.getProjectMapping(Application.getInstance().getProject()).getLocalSyncTransactionCommitListener(); + LocalDeltaTransactionCommitListener listener = LocalDeltaProjectEventListenerAdapter.getProjectMapping(Application.getInstance().getProject()).getLocalDeltaTransactionCommitListener(); if (listener != null) { listener.setDisabled(true); } diff --git a/src/main/java/gov/nasa/jpl/mbee/mdk/actions/ComponentToClassRefactorWithIDAction.java b/src/main/java/gov/nasa/jpl/mbee/mdk/actions/ComponentToClassRefactorWithIDAction.java index 012c104e8..7cd501f7f 100644 --- a/src/main/java/gov/nasa/jpl/mbee/mdk/actions/ComponentToClassRefactorWithIDAction.java +++ b/src/main/java/gov/nasa/jpl/mbee/mdk/actions/ComponentToClassRefactorWithIDAction.java @@ -9,8 +9,8 @@ import com.nomagic.uml2.ext.magicdraw.classes.mdkernel.Element; import com.nomagic.uml2.ext.magicdraw.components.mdbasiccomponents.Component; import gov.nasa.jpl.mbee.mdk.api.incubating.convert.Converters; -import gov.nasa.jpl.mbee.mdk.mms.sync.local.LocalSyncProjectEventListenerAdapter; -import gov.nasa.jpl.mbee.mdk.mms.sync.local.LocalSyncTransactionCommitListener; +import gov.nasa.jpl.mbee.mdk.mms.sync.local.LocalDeltaProjectEventListenerAdapter; +import gov.nasa.jpl.mbee.mdk.mms.sync.local.LocalDeltaTransactionCommitListener; import gov.nasa.jpl.mbee.mdk.util.Utils; import java.awt.event.ActionEvent; @@ -34,7 +34,7 @@ public void actionPerformed(ActionEvent e) { if (con == null || !con) { return; } - LocalSyncTransactionCommitListener listener = LocalSyncProjectEventListenerAdapter.getProjectMapping(Application.getInstance().getProject()).getLocalSyncTransactionCommitListener(); + LocalDeltaTransactionCommitListener listener = LocalDeltaProjectEventListenerAdapter.getProjectMapping(Application.getInstance().getProject()).getLocalDeltaTransactionCommitListener(); if (listener != null) { listener.setDisabled(true); } diff --git a/src/main/java/gov/nasa/jpl/mbee/mdk/docgen/table/EditableTable.java b/src/main/java/gov/nasa/jpl/mbee/mdk/docgen/table/EditableTable.java index 46b5fb4e5..358293693 100644 --- a/src/main/java/gov/nasa/jpl/mbee/mdk/docgen/table/EditableTable.java +++ b/src/main/java/gov/nasa/jpl/mbee/mdk/docgen/table/EditableTable.java @@ -231,7 +231,7 @@ private void importFromCsv(CSVReader reader) throws IOException { PropertyEnum whatToChange = null; BaseElement e = Converters.getIdToElementConverter() .apply(props[c], project); - String value = props[c + 1]; + String value = c + 1 < props.length ? props[c + 1] : ""; if (what != null && what.size() > row && what.get(row).size() > col) { whatToChange = what.get(row).get(col); } diff --git a/src/main/java/gov/nasa/jpl/mbee/mdk/emf/EMFExporter.java b/src/main/java/gov/nasa/jpl/mbee/mdk/emf/EMFExporter.java index 36387d5a7..11fe6d897 100644 --- a/src/main/java/gov/nasa/jpl/mbee/mdk/emf/EMFExporter.java +++ b/src/main/java/gov/nasa/jpl/mbee/mdk/emf/EMFExporter.java @@ -110,7 +110,7 @@ public static String getEID(EObject eObject) { return Converters.getIProjectToIdConverter().apply(project.getPrimaryProject()) + MDKConstants.PRIMARY_MODEL_ID_SUFFIX; } - // local projects don't properly maintain the ids of some elements. this id spoofing mitigates that for us, but can mess up the jms sync counts in some cases (annoying, but ultimately harmless) + // local projects don't properly maintain the ids of some elements. this id spoofing mitigates that for us, but can mess up the MMS delta counts in some cases (annoying, but ultimately harmless) // NOTE - this spoofing is replicated in LocalSyncTransactionListener in order to properly add / remove elements in the unsynched queue. any updates here should be replicated there as well. if (element instanceof InstanceSpecification && ((InstanceSpecification) element).getStereotypedElement() != null) { return getEID(((InstanceSpecification) element).getStereotypedElement()) + MDKConstants.APPLIED_STEREOTYPE_INSTANCE_ID_SUFFIX; diff --git a/src/main/java/gov/nasa/jpl/mbee/mdk/emf/EMFImporter.java b/src/main/java/gov/nasa/jpl/mbee/mdk/emf/EMFImporter.java index 0ea002e6c..5106e7071 100644 --- a/src/main/java/gov/nasa/jpl/mbee/mdk/emf/EMFImporter.java +++ b/src/main/java/gov/nasa/jpl/mbee/mdk/emf/EMFImporter.java @@ -234,7 +234,6 @@ else if (eStructuralFeature instanceof EReference) { } String id = jsonNode.asText(); Element referencedElement = getIdToElementConverter().apply(id, project); - System.out.println("[LOOKUP] " + id + " -> " + referencedElement); if (referencedElement == null) { if (strict) { throw new ReferenceException(element, objectNode, "Could not find referenced element " + id + " in model for key \"" + key + "\" in JSON."); diff --git a/src/main/java/gov/nasa/jpl/mbee/mdk/generator/ViewPresentationGenerator.java b/src/main/java/gov/nasa/jpl/mbee/mdk/generator/ViewPresentationGenerator.java index a7c418cd5..37e12210c 100644 --- a/src/main/java/gov/nasa/jpl/mbee/mdk/generator/ViewPresentationGenerator.java +++ b/src/main/java/gov/nasa/jpl/mbee/mdk/generator/ViewPresentationGenerator.java @@ -27,8 +27,8 @@ import gov.nasa.jpl.mbee.mdk.mms.MMSUtils; import gov.nasa.jpl.mbee.mdk.mms.json.JsonEquivalencePredicate; import gov.nasa.jpl.mbee.mdk.mms.json.JsonPatchFunction; -import gov.nasa.jpl.mbee.mdk.mms.sync.local.LocalSyncProjectEventListenerAdapter; -import gov.nasa.jpl.mbee.mdk.mms.sync.local.LocalSyncTransactionCommitListener; +import gov.nasa.jpl.mbee.mdk.mms.sync.local.LocalDeltaProjectEventListenerAdapter; +import gov.nasa.jpl.mbee.mdk.mms.sync.local.LocalDeltaTransactionCommitListener; import gov.nasa.jpl.mbee.mdk.mms.validation.ImageValidator; import gov.nasa.jpl.mbee.mdk.model.DocBookOutputVisitor; import gov.nasa.jpl.mbee.mdk.model.Document; @@ -112,9 +112,6 @@ public void run(ProgressStatus progressStatus) { Map viewMap = new LinkedHashMap<>(); for (Element rootView : rootViews) { - if (MDUtils.isDeveloperMode()) { - //Application.getInstance().getGUILog().log("Generating " + rootView.getHumanName() + " (" + rootView.getLocalID() + ")."); - } // STAGE 1: Calculating view structure progressStatus.setDescription("Calculating view structure"); progressStatus.setCurrent(1); @@ -136,11 +133,16 @@ public void run(ProgressStatus progressStatus) { failure = true; return; } - - DocBookOutputVisitor docBookOutputVisitor = new DocBookOutputVisitor(true); - dge.accept(docBookOutputVisitor); - - SessionManager.getInstance().closeSession(project); + DocBookOutputVisitor docBookOutputVisitor; + try { + docBookOutputVisitor = new DocBookOutputVisitor(true); + dge.accept(docBookOutputVisitor); + } + finally { + if (SessionManager.getInstance().isSessionCreated(project)) { + SessionManager.getInstance().closeSession(project); + } + } DBBook book = docBookOutputVisitor.getBook(); if (book == null) { @@ -222,7 +224,7 @@ public void run(ProgressStatus progressStatus) { return; } - LocalSyncTransactionCommitListener localSyncTransactionCommitListener = LocalSyncProjectEventListenerAdapter.getProjectMapping(project).getLocalSyncTransactionCommitListener(); + LocalDeltaTransactionCommitListener localDeltaTransactionCommitListener = LocalDeltaProjectEventListenerAdapter.getProjectMapping(project).getLocalDeltaTransactionCommitListener(); Set elementsToDelete = new HashSet<>(); // Create the session you intend to cancel to revert all temporary elements. @@ -235,8 +237,8 @@ public void run(ProgressStatus progressStatus) { failure = true; return; } - if (localSyncTransactionCommitListener != null) { - localSyncTransactionCommitListener.setDisabled(true); + if (localDeltaTransactionCommitListener != null) { + localDeltaTransactionCommitListener.setDisabled(true); } // Query existing server-side JSONs for views @@ -761,8 +763,8 @@ public List getEStructuralFeatureOverrides() { if (SessionManager.getInstance().isSessionCreated(project)) { SessionManager.getInstance().cancelSession(project); } - if (localSyncTransactionCommitListener != null) { - localSyncTransactionCommitListener.setDisabled(false); + if (localDeltaTransactionCommitListener != null) { + localDeltaTransactionCommitListener.setDisabled(false); } } diff --git a/src/main/java/gov/nasa/jpl/mbee/mdk/json/JacksonUtils.java b/src/main/java/gov/nasa/jpl/mbee/mdk/json/JacksonUtils.java index 05a091a51..2a7359572 100644 --- a/src/main/java/gov/nasa/jpl/mbee/mdk/json/JacksonUtils.java +++ b/src/main/java/gov/nasa/jpl/mbee/mdk/json/JacksonUtils.java @@ -114,8 +114,7 @@ public static ObjectNode parseJsonObject(JsonParser jsonParser) throws IOExcepti if (current != JsonToken.START_OBJECT) { throw new IOException("Unable to build object from JSON parser."); } - ObjectNode objectNode = getObjectMapper().readTree(jsonParser); - return objectNode; + return getObjectMapper().readTree(jsonParser); } public static ArrayNode parseJsonArray(JsonParser jsonParser, ArrayNode arrayNode) throws IOException { diff --git a/src/main/java/gov/nasa/jpl/mbee/mdk/mms/MMSUtils.java b/src/main/java/gov/nasa/jpl/mbee/mdk/mms/MMSUtils.java index 4049df659..7ba76fd00 100644 --- a/src/main/java/gov/nasa/jpl/mbee/mdk/mms/MMSUtils.java +++ b/src/main/java/gov/nasa/jpl/mbee/mdk/mms/MMSUtils.java @@ -74,8 +74,7 @@ public static AtomicReference getLastException() { return LAST_EXCEPTION; } - public static ObjectNode getElement(Project project, String elementId, ProgressStatus progressStatus) - throws IOException, ServerException, URISyntaxException { + public static ObjectNode getElement(Project project, String elementId, ProgressStatus progressStatus) throws IOException, ServerException, URISyntaxException { Collection elementIds = new ArrayList<>(1); elementIds.add(elementId); File responseFile = getElementsRecursively(project, elementIds, 0, progressStatus); @@ -90,8 +89,7 @@ public static ObjectNode getElement(Project project, String elementId, ProgressS return null; } - public static File getElementRecursively(Project project, String elementId, int depth, ProgressStatus progressStatus) - throws IOException, ServerException, URISyntaxException { + public static File getElementRecursively(Project project, String elementId, int depth, ProgressStatus progressStatus) throws IOException, ServerException, URISyntaxException { Collection elementIds = new ArrayList<>(1); elementIds.add(elementId); return getElementsRecursively(project, elementIds, depth, progressStatus); @@ -106,8 +104,7 @@ public static File getElementRecursively(Project project, String elementId, int * @throws IOException * @throws URISyntaxException */ - public static File getElements(Project project, Collection elementIds, ProgressStatus progressStatus) - throws IOException, ServerException, URISyntaxException { + public static File getElements(Project project, Collection elementIds, ProgressStatus progressStatus) throws IOException, ServerException, URISyntaxException { return getElementsRecursively(project, elementIds, 0, progressStatus); } @@ -121,8 +118,7 @@ public static File getElements(Project project, Collection elementIds, P * @throws IOException * @throws URISyntaxException */ - public static File getElementsRecursively(Project project, Collection elementIds, int depth, ProgressStatus progressStatus) - throws ServerException, IOException, URISyntaxException { + public static File getElementsRecursively(Project project, Collection elementIds, int depth, ProgressStatus progressStatus) throws ServerException, IOException, URISyntaxException { // verify elements if (elementIds == null || elementIds.isEmpty()) { return null; @@ -148,18 +144,15 @@ public static File getElementsRecursively(Project project, Collection el return sendMMSRequest(project, MMSUtils.buildRequest(MMSUtils.HttpRequestType.PUT, requestUri, sendData, ContentType.APPLICATION_JSON)); } - public static String getCredentialsTicket(Project project, String username, String password, ProgressStatus progressStatus) - throws ServerException, IOException, URISyntaxException { + public static String getCredentialsTicket(Project project, String username, String password, ProgressStatus progressStatus) throws ServerException, IOException, URISyntaxException { return getCredentialsTicket(project, null, username, password, progressStatus); } - public static String getCredentialsTicket(String baseUrl, String username, String password, ProgressStatus progressStatus) - throws ServerException, IOException, URISyntaxException { + public static String getCredentialsTicket(String baseUrl, String username, String password, ProgressStatus progressStatus) throws ServerException, IOException, URISyntaxException { return getCredentialsTicket(null, baseUrl, username, password, progressStatus); } - private static String getCredentialsTicket(Project project, String baseUrl, String username, String password, ProgressStatus progressStatus) - throws ServerException, IOException, URISyntaxException { + private static String getCredentialsTicket(Project project, String baseUrl, String username, String password, ProgressStatus progressStatus) throws ServerException, IOException, URISyntaxException { URIBuilder requestUri = MMSUtils.getServiceUri(project, baseUrl); if (requestUri == null) { return null; @@ -190,8 +183,7 @@ private static String getCredentialsTicket(Project project, String baseUrl, Stri return null; } - public static String validateCredentialsTicket(Project project, String ticket, ProgressStatus progressStatus) - throws ServerException, IOException, URISyntaxException { + public static String validateCredentialsTicket(Project project, String ticket, ProgressStatus progressStatus) throws ServerException, IOException, URISyntaxException { URIBuilder requestUri = MMSUtils.getServiceUri(project); if (requestUri == null) { return ""; @@ -225,8 +217,7 @@ public static String validateCredentialsTicket(Project project, String ticket, P * @throws IOException * @throws URISyntaxException */ - public static HttpRequestBase buildImageRequest(URIBuilder requestUri, File sendFile) - throws IOException, URISyntaxException { + public static HttpRequestBase buildImageRequest(URIBuilder requestUri, File sendFile) throws IOException, URISyntaxException { URI requestDest = requestUri.build(); HttpPost requestUpload = new HttpPost(requestDest); EntityBuilder uploadBuilder = EntityBuilder.create(); @@ -247,8 +238,7 @@ public static HttpRequestBase buildImageRequest(URIBuilder requestUri, File send * @throws IOException * @throws URISyntaxException */ - public static HttpRequestBase buildRequest(HttpRequestType type, URIBuilder requestUri, File sendData, ContentType contentType) - throws IOException, URISyntaxException { + public static HttpRequestBase buildRequest(HttpRequestType type, URIBuilder requestUri, File sendData, ContentType contentType) throws IOException, URISyntaxException { // build specified request type // assume that any request can have a body, and just build the appropriate one URI requestDest = requestUri.build(); @@ -294,13 +284,11 @@ public static HttpRequestBase buildRequest(HttpRequestType type, URIBuilder requ * @throws IOException * @throws URISyntaxException */ - public static HttpRequestBase buildRequest(HttpRequestType type, URIBuilder requestUri) - throws IOException, URISyntaxException { + public static HttpRequestBase buildRequest(HttpRequestType type, URIBuilder requestUri) throws IOException, URISyntaxException { return buildRequest(type, requestUri, null, null); } - public static File createEntityFile(Class clazz, ContentType contentType, Collection nodes, JsonBlobType jsonBlobType) - throws IOException { + public static File createEntityFile(Class clazz, ContentType contentType, Collection nodes, JsonBlobType jsonBlobType) throws IOException { File requestFile = File.createTempFile(clazz.getSimpleName() + "-" + contentType.getMimeType().replace('/', '-') + "-", null); if (MDKOptionsGroup.getMDKOptions().isLogJson()) { System.out.println("[INFO] Request Body: " + requestFile.getPath()); @@ -357,13 +345,12 @@ else if (node instanceof String && jsonBlobType == JsonBlobType.ELEMENT_ID) { * @throws IOException * @throws ServerException */ - public static File sendMMSRequest(Project project, HttpRequestBase request, ProgressStatus progressStatus, final ObjectNode responseJson) - throws IOException, ServerException, URISyntaxException { + public static File sendMMSRequest(Project project, HttpRequestBase request, ProgressStatus progressStatus, final ObjectNode responseJson) throws IOException, ServerException, URISyntaxException { final File responseFile = (responseJson == null ? File.createTempFile("Response-", null) : null); final AtomicReference responseBody = new AtomicReference<>(); final AtomicReference responseCode = new AtomicReference<>(); - String requestSummary = "MMS Request [" + request.getMethod() + "] " + request.getURI().toString(); + String requestSummary = "[INFO] MMS Request [" + request.getMethod() + "] " + request.getURI().toString(); System.out.println(requestSummary); if (MDUtils.isDeveloperMode()) { Application.getInstance().getGUILog().log(requestSummary); @@ -376,7 +363,7 @@ public static File sendMMSRequest(Project project, HttpRequestBase request, Prog CloseableHttpResponse response = httpclient.execute(request); InputStream inputStream = response.getEntity().getContent()) { responseCode.set(response.getStatusLine().getStatusCode()); - String responseSummary = "MMS Response [" + request.getMethod() + "]: " + responseCode.get() + " " + request.getURI().toString(); + String responseSummary = "[INFO] MMS Response [" + request.getMethod() + "]: " + responseCode.get() + " " + request.getURI().toString(); System.out.println(responseSummary); if (MDUtils.isDeveloperMode()) { Application.getInstance().getGUILog().log(responseSummary); @@ -449,13 +436,11 @@ public static File sendMMSRequest(Project project, HttpRequestBase request, Prog return responseFile; } - public static File sendMMSRequest(Project project, HttpRequestBase request) - throws IOException, ServerException, URISyntaxException { + public static File sendMMSRequest(Project project, HttpRequestBase request) throws IOException, ServerException, URISyntaxException { return sendMMSRequest(project, request, null, null); } - public static File sendMMSRequest(Project project, HttpRequestBase request, ProgressStatus progressStatus) - throws IOException, ServerException, URISyntaxException { + public static File sendMMSRequest(Project project, HttpRequestBase request, ProgressStatus progressStatus) throws IOException, ServerException, URISyntaxException { return sendMMSRequest(project, request, progressStatus, null); } @@ -558,8 +543,7 @@ else if (ProjectUtilities.isStandardSystemProfile(project.getPrimaryProject())) return urlString.trim(); } - public static String getMmsOrg(Project project) - throws IOException, URISyntaxException, ServerException { + public static String getMmsOrg(Project project) throws IOException, URISyntaxException, ServerException { URIBuilder uriBuilder = getServiceProjectsUri(project); File responseFile = sendMMSRequest(project, buildRequest(HttpRequestType.GET, uriBuilder)); try (JsonParser responseParser = JacksonUtils.getJsonFactory().createParser(responseFile)) { diff --git a/src/main/java/gov/nasa/jpl/mbee/mdk/mms/actions/DetailedSyncStatusAction.java b/src/main/java/gov/nasa/jpl/mbee/mdk/mms/actions/DetailedSyncStatusAction.java index f3a6c798c..1093c5399 100644 --- a/src/main/java/gov/nasa/jpl/mbee/mdk/mms/actions/DetailedSyncStatusAction.java +++ b/src/main/java/gov/nasa/jpl/mbee/mdk/mms/actions/DetailedSyncStatusAction.java @@ -1,6 +1,5 @@ package gov.nasa.jpl.mbee.mdk.mms.actions; -import com.fasterxml.jackson.databind.node.ObjectNode; import com.nomagic.magicdraw.core.Application; import com.nomagic.magicdraw.core.Project; import com.nomagic.uml2.ext.magicdraw.classes.mdkernel.Element; @@ -8,10 +7,9 @@ import gov.nasa.jpl.mbee.mdk.api.incubating.convert.Converters; import gov.nasa.jpl.mbee.mdk.mms.sync.delta.SyncElement; import gov.nasa.jpl.mbee.mdk.mms.sync.delta.SyncElements; -import gov.nasa.jpl.mbee.mdk.mms.sync.jms.JMSMessageListener; -import gov.nasa.jpl.mbee.mdk.mms.sync.jms.JMSSyncProjectEventListenerAdapter; -import gov.nasa.jpl.mbee.mdk.mms.sync.local.LocalSyncProjectEventListenerAdapter; -import gov.nasa.jpl.mbee.mdk.mms.sync.local.LocalSyncTransactionCommitListener; +import gov.nasa.jpl.mbee.mdk.mms.sync.local.LocalDeltaProjectEventListenerAdapter; +import gov.nasa.jpl.mbee.mdk.mms.sync.local.LocalDeltaTransactionCommitListener; +import gov.nasa.jpl.mbee.mdk.mms.sync.mms.MMSDeltaProjectEventListenerAdapter; import gov.nasa.jpl.mbee.mdk.systems_reasoner.actions.SRAction; import gov.nasa.jpl.mbee.mdk.util.Changelog; import gov.nasa.jpl.mbee.mdk.util.Utils; @@ -75,6 +73,9 @@ public void actionPerformed(@CheckForNull ActionEvent actionEvent) { validationRule.getViolations().clear(); } Project project = Application.getInstance().getProject(); + if (project == null) { + return; + } for (SyncElement.Type syncElementType : SyncElement.Type.values()) { Collection syncElements = SyncElements.getAllByType(project, syncElementType); for (SyncElement syncElement : syncElements) { @@ -89,21 +90,18 @@ public void actionPerformed(@CheckForNull ActionEvent actionEvent) { } } for (Changelog.ChangeType changeType : Changelog.ChangeType.values()) { - LocalSyncTransactionCommitListener localSyncTransactionCommitListener = LocalSyncProjectEventListenerAdapter.getProjectMapping(project).getLocalSyncTransactionCommitListener(); - if (localSyncTransactionCommitListener != null) { + LocalDeltaTransactionCommitListener localDeltaTransactionCommitListener = LocalDeltaProjectEventListenerAdapter.getProjectMapping(project).getLocalDeltaTransactionCommitListener(); + if (localDeltaTransactionCommitListener != null) { ValidationRule validationRule = validationRuleMap.get(SyncElement.Type.LOCAL).get(changeType); - for (Map.Entry entry : localSyncTransactionCommitListener.getInMemoryLocalChangelog().get(changeType).entrySet()) { + for (Map.Entry entry : localDeltaTransactionCommitListener.getInMemoryLocalChangelog().get(changeType).entrySet()) { Element element = entry.getValue(); validationRule.addViolation(element, "Source: [" + SyncElement.Type.LOCAL.name() + "] | Type: [" + changeType.name() + "]" + (element != null && !project.isDisposed(element) ? "" : " | " + entry.getKey())); } } - JMSMessageListener jmsMessageListener = JMSSyncProjectEventListenerAdapter.getProjectMapping(project).getJmsMessageListener(); - if (jmsMessageListener != null) { - ValidationRule validationRule = validationRuleMap.get(SyncElement.Type.MMS).get(changeType); - for (Map.Entry entry : jmsMessageListener.getInMemoryJMSChangelog().get(changeType).entrySet()) { - Element element = Converters.getIdToElementConverter().apply(entry.getKey(), project); - validationRule.addViolation(new ValidationRuleViolation(element, "Source: [" + SyncElement.Type.MMS.name() + "] | Type: [" + changeType.name() + "]")); - } + ValidationRule validationRule = validationRuleMap.get(SyncElement.Type.MMS).get(changeType); + for (Map.Entry entry : MMSDeltaProjectEventListenerAdapter.getProjectMapping(project).getInMemoryChangelog().get(changeType).entrySet()) { + Element element = Converters.getIdToElementConverter().apply(entry.getKey(), project); + validationRule.addViolation(new ValidationRuleViolation(element, "Source: [" + SyncElement.Type.MMS.name() + "] | Type: [" + changeType.name() + "]")); } } diff --git a/src/main/java/gov/nasa/jpl/mbee/mdk/mms/actions/MMSLoginAction.java b/src/main/java/gov/nasa/jpl/mbee/mdk/mms/actions/MMSLoginAction.java index f95838a10..5bb6b5f5f 100644 --- a/src/main/java/gov/nasa/jpl/mbee/mdk/mms/actions/MMSLoginAction.java +++ b/src/main/java/gov/nasa/jpl/mbee/mdk/mms/actions/MMSLoginAction.java @@ -4,13 +4,15 @@ import com.nomagic.magicdraw.actions.MDAction; import com.nomagic.magicdraw.core.Application; import com.nomagic.magicdraw.core.Project; -import com.nomagic.magicdraw.esi.EsiUtils; -import com.nomagic.magicdraw.teamwork.application.TeamworkUtils; -import gov.nasa.jpl.mbee.mdk.mms.sync.jms.JMSSyncProjectEventListenerAdapter; +import gov.nasa.jpl.mbee.mdk.http.ServerException; +import gov.nasa.jpl.mbee.mdk.mms.sync.mms.MMSDeltaProjectEventListenerAdapter; +import gov.nasa.jpl.mbee.mdk.util.TaskRunner; import gov.nasa.jpl.mbee.mdk.util.TicketUtils; import gov.nasa.jpl.mbee.mdk.util.Utils; import java.awt.event.ActionEvent; +import java.io.IOException; +import java.net.URISyntaxException; public class MMSLoginAction extends MDAction { private static final long serialVersionUID = 1L; @@ -30,17 +32,24 @@ public static boolean loginAction(Project project) { Utils.showPopupMessage("Please open the project you would like to log in to MMS for first."); return false; } - if (project.isRemote() && (TeamworkUtils.getLoggedUserName() == null && EsiUtils.getTeamworkService().getConnectedUser() == null)) { + /* + if (project.isRemote() && EsiUtils.getTeamworkService().getConnectedUser() == null) { Utils.showPopupMessage("Please login in to Teamwork Cloud before logging in to MMS."); return false; } + */ if (!TicketUtils.acquireMmsTicket(project)) { return false; } ActionsStateUpdater.updateActionsState(); + TaskRunner.runWithProgressStatus(progressStatus -> { + try { + MMSDeltaProjectEventListenerAdapter.getProjectMapping(project).update(); + } catch (URISyntaxException | IOException | ServerException e) { + e.printStackTrace(); + } + }, "MMS Fetch", false, TaskRunner.ThreadExecutionStrategy.POOLED, false); Application.getInstance().getGUILog().log("[INFO] MMS login complete."); - JMSSyncProjectEventListenerAdapter.closeJMS(project); - JMSSyncProjectEventListenerAdapter.initializeJMS(project); return true; } diff --git a/src/main/java/gov/nasa/jpl/mbee/mdk/mms/actions/MMSLogoutAction.java b/src/main/java/gov/nasa/jpl/mbee/mdk/mms/actions/MMSLogoutAction.java index 8e0efab60..e7968dab1 100644 --- a/src/main/java/gov/nasa/jpl/mbee/mdk/mms/actions/MMSLogoutAction.java +++ b/src/main/java/gov/nasa/jpl/mbee/mdk/mms/actions/MMSLogoutAction.java @@ -4,7 +4,6 @@ import com.nomagic.magicdraw.actions.MDAction; import com.nomagic.magicdraw.core.Application; import com.nomagic.magicdraw.core.Project; -import gov.nasa.jpl.mbee.mdk.mms.sync.jms.JMSSyncProjectEventListenerAdapter; import gov.nasa.jpl.mbee.mdk.mms.sync.status.SyncStatusConfigurator; import gov.nasa.jpl.mbee.mdk.util.TicketUtils; @@ -27,10 +26,6 @@ public static void logoutAction(Project project) { TicketUtils.clearTicket(project); Application.getInstance().getGUILog().log("[INFO] MMS logout complete."); ActionsStateUpdater.updateActionsState(); - if (!JMSSyncProjectEventListenerAdapter.getProjectMapping(project).getJmsMessageListener().isDisabled()) { - JMSSyncProjectEventListenerAdapter.closeJMS(project); - Application.getInstance().getGUILog().log("[WARNING] " + project.getName() + " - Reverting to offline mode. All changes will be saved in the model until reconnected. Reason: You must be logged into MMS."); - } SyncStatusConfigurator.getSyncStatusAction().update(); } diff --git a/src/main/java/gov/nasa/jpl/mbee/mdk/mms/actions/UpdateClientElementAction.java b/src/main/java/gov/nasa/jpl/mbee/mdk/mms/actions/UpdateClientElementAction.java index 35cec6f72..20a02b784 100644 --- a/src/main/java/gov/nasa/jpl/mbee/mdk/mms/actions/UpdateClientElementAction.java +++ b/src/main/java/gov/nasa/jpl/mbee/mdk/mms/actions/UpdateClientElementAction.java @@ -27,8 +27,8 @@ import gov.nasa.jpl.mbee.mdk.json.JacksonUtils; import gov.nasa.jpl.mbee.mdk.mms.json.JsonPatchFunction; import gov.nasa.jpl.mbee.mdk.mms.sync.delta.SyncElement; -import gov.nasa.jpl.mbee.mdk.mms.sync.local.LocalSyncProjectEventListenerAdapter; -import gov.nasa.jpl.mbee.mdk.mms.sync.local.LocalSyncTransactionCommitListener; +import gov.nasa.jpl.mbee.mdk.mms.sync.local.LocalDeltaProjectEventListenerAdapter; +import gov.nasa.jpl.mbee.mdk.mms.sync.local.LocalDeltaTransactionCommitListener; import gov.nasa.jpl.mbee.mdk.util.Changelog; import gov.nasa.jpl.mbee.mdk.util.Pair; import gov.nasa.jpl.mbee.mdk.util.Utils; @@ -148,7 +148,7 @@ public void actionPerformed(@CheckForNull ActionEvent actionEvent) { @Override public void run(ProgressStatus progressStatus) { validationSuite.getValidationRules().forEach(validationRule -> validationRule.getViolations().clear()); - LocalSyncTransactionCommitListener localSyncTransactionCommitListener = LocalSyncProjectEventListenerAdapter.getProjectMapping(project).getLocalSyncTransactionCommitListener(); + LocalDeltaTransactionCommitListener localDeltaTransactionCommitListener = LocalDeltaProjectEventListenerAdapter.getProjectMapping(project).getLocalDeltaTransactionCommitListener(); elementsToUpdate = (elementsToUpdate == null ? Collections.emptyList() : elementsToUpdate); elementsToDelete = (elementsToDelete == null ? Collections.emptyList() : elementsToDelete); if (elementsToUpdate.isEmpty() && elementsToDelete.isEmpty()) { @@ -183,8 +183,8 @@ public void run(ProgressStatus progressStatus) { elementsToUpdate.removeAll(elementsToNotUpdate); boolean initialAutoNumbering = Application.getInstance().getProject().getOptions().isAutoNumbering(); Application.getInstance().getProject().getOptions().setAutoNumbering(false); - if (localSyncTransactionCommitListener != null) { - localSyncTransactionCommitListener.setDisabled(true); + if (localDeltaTransactionCommitListener != null) { + localDeltaTransactionCommitListener.setDisabled(true); } try { if (!elementsToUpdate.isEmpty()) { @@ -282,6 +282,9 @@ public void onFailure() { + ((entryElement == null || Project.isElementDisposed(entryElement)) && entryException != null ? " -" : "") + (entryException != null ? " " + (entryException instanceof ReadOnlyElementException ? "Element is not editable." : entryException.getMessage()) : "")); addUpdateElementActions(validationRuleViolation, entryElement, entryId, entryObjectNode); (entryException instanceof ReadOnlyElementException ? editableValidationRule : failedChangeValidationRule).addViolation(validationRuleViolation); + if (entryException != null && !(entryException instanceof ReadOnlyElementException)) { + entryException.printStackTrace(); + } failedChangelog.addChange(entryId, entryObjectNode, entryElement != null && !Project.isElementDisposed(entryElement) ? Changelog.ChangeType.UPDATED : Changelog.ChangeType.CREATED); } for (Map.Entry entry : emfBulkImporter.getNonEquivalentElements().entrySet()) { @@ -320,8 +323,8 @@ public void onFailure() { } } finally { Application.getInstance().getProject().getOptions().setAutoNumbering(initialAutoNumbering); - if (localSyncTransactionCommitListener != null) { - localSyncTransactionCommitListener.setDisabled(false); + if (localDeltaTransactionCommitListener != null) { + localDeltaTransactionCommitListener.setDisabled(false); } } if (validationSuite.hasErrors()) { diff --git a/src/main/java/gov/nasa/jpl/mbee/mdk/mms/jms/JMSUtils.java b/src/main/java/gov/nasa/jpl/mbee/mdk/mms/jms/JMSUtils.java deleted file mode 100644 index 6e15939c2..000000000 --- a/src/main/java/gov/nasa/jpl/mbee/mdk/mms/jms/JMSUtils.java +++ /dev/null @@ -1,225 +0,0 @@ -package gov.nasa.jpl.mbee.mdk.mms.jms; - -import com.fasterxml.jackson.core.JsonParseException; -import com.fasterxml.jackson.databind.JsonMappingException; -import com.fasterxml.jackson.databind.JsonNode; -import com.fasterxml.jackson.databind.node.ArrayNode; -import com.fasterxml.jackson.databind.node.ObjectNode; -import com.nomagic.magicdraw.core.Application; -import com.nomagic.magicdraw.core.Project; -import gov.nasa.jpl.mbee.mdk.api.incubating.convert.Converters; -import gov.nasa.jpl.mbee.mdk.http.ServerException; -import gov.nasa.jpl.mbee.mdk.json.JacksonUtils; -import gov.nasa.jpl.mbee.mdk.mms.MMSUtils; -import org.apache.activemq.ActiveMQConnectionFactory; -import org.apache.http.client.utils.URIBuilder; - -import javax.jms.*; -import javax.naming.Context; -import javax.naming.InitialContext; -import javax.naming.NamingException; -import java.io.IOException; -import java.net.URISyntaxException; -import java.util.Hashtable; - -/** - * Created by igomes on 6/29/16. - */ -public class JMSUtils { - - private static final int JMS_PORT = 61616; - private static final String JMS_S = "tcp"; - - public static final String MSG_SELECTOR_PROJECT_ID = "projectId", - MSG_SELECTOR_REF_ID = "refId"; - - // Members to look up MMS using JNDI - // TODO: If any other context factories are used, need to add those JARs into class path (e.g., for weblogic) - public static String JMS_CTX_FACTORY = "org.apache.activemq.jndi.ActiveMQInitialContextFactory", - JMS_CONN_FACTORY = "ConnectionFactory", - JMS_USERNAME, - JMS_PASSWORD, - JMS_TOPIC = "master"; - - private static InitialContext initialContext = null; - - /** - * Gets MMS JNDI connection details from the MMS server - * - * @return JSONObject of the connection details - * @throws JsonMappingException - * @throws IOException - * @throws JsonParseException - */ - public static ObjectNode getJmsConnectionDetails(Project project) - throws IOException, ServerException, URISyntaxException { - ObjectNode responseJson = JacksonUtils.getObjectMapper().createObjectNode(); - URIBuilder requestUri = MMSUtils.getServiceUri(project); - if (requestUri == null) { - return responseJson; - } - requestUri.setPath(requestUri.getPath() + "/connection/jms"); - MMSUtils.sendMMSRequest(project, MMSUtils.buildRequest(MMSUtils.HttpRequestType.GET, requestUri), null, responseJson); -// File responseFile = MMSUtils.sendMMSRequest(project, MMSUtils.buildRequest(MMSUtils.HttpRequestType.GET, requestUri)); -// try (JsonParser jsonParser = JacksonUtils.getJsonFactory().createParser(responseFile)) { -// return JacksonUtils.parseJsonObject(jsonParser); -// } - return responseJson; - } - - // Varies by current project - public static JMSInfo getJMSInfo(Project project) throws ServerException { - ObjectNode jmsJson = null; - try { - jmsJson = getJmsConnectionDetails(project); - } catch (IOException e) { - Application.getInstance().getGUILog().log("[ERROR]: Unable to acquire JMS Connection information."); - e.printStackTrace(); - } catch (URISyntaxException e) { - Application.getInstance().getGUILog().log("[ERROR]: Unexpected error occurred when trying to build MMS URL. Reason: " + e.getMessage()); - e.printStackTrace(); - } - String url = ingestJson(jmsJson); - boolean isFromService = (url != null); - if (url == null) { - url = MMSUtils.getServerUrl(project); - try { - URIBuilder uri = new URIBuilder(url); - uri.setPort(JMS_PORT); - uri.setScheme(JMS_S); - uri.setPath(""); - url = uri.build().toString(); - } catch (URISyntaxException e) { - e.printStackTrace(); - } - } - return new JMSInfo(url, isFromService); - } - - /** - * Ingests JSON data generated from MMS server and populates JNDI members - * - * @return URL string of connector - */ - protected static String ingestJson(ObjectNode jsonInput) { - if (jsonInput == null) { - return null; - } - ArrayNode conns = null; - JsonNode valueNode; - if ((valueNode = jsonInput.get("connections")) != null && valueNode.isArray()) { - conns = (ArrayNode) valueNode; - } - ObjectNode json = null; - if (conns != null) { - // just grab first connection - for (int ii = 0; ii < conns.size(); ii++) { - json = (ObjectNode) conns.get(ii); - JsonNode value; - if ((value = json.get("eventType")) != null && value.isTextual() && value.asText().equals("DELTA")) { - break; - } - } - } - else { - json = jsonInput; - } - String result = null; - if (json != null) { - if ((valueNode = json.get("uri")) != null && valueNode.isTextual()) { - result = valueNode.asText(); - } - if ((valueNode = json.get("connFactory")) != null && valueNode.isTextual()) { - JMS_CONN_FACTORY = valueNode.asText(); - } - if ((valueNode = json.get("ctxFactory")) != null && valueNode.isTextual()) { - JMS_CTX_FACTORY = valueNode.asText(); - } - if ((valueNode = json.get("password")) != null && valueNode.isTextual()) { - JMS_PASSWORD = valueNode.asText(); - } - if ((valueNode = json.get("username")) != null && valueNode.isTextual()) { - JMS_USERNAME = valueNode.asText(); - } - if ((valueNode = json.get("topicName")) != null && valueNode.isTextual()) { - JMS_TOPIC = valueNode.asText(); - } - } - return result; - } - - - public static InitialContext getInitialContext() { - return initialContext; - } - - /** - * Create a connection factory based on JNDI values - * - * @return - */ - public static ConnectionFactory createConnectionFactory(JMSInfo jmsInfo) { - boolean isFromService = jmsInfo.isFromService(); - String url = jmsInfo.getUrl(); - Hashtable properties = new Hashtable<>(); - properties.put(Context.INITIAL_CONTEXT_FACTORY, JMS_CTX_FACTORY); - properties.put(Context.PROVIDER_URL, url); - if (JMS_USERNAME != null && JMS_PASSWORD != null) { - properties.put(Context.SECURITY_PRINCIPAL, JMS_USERNAME); - properties.put(Context.SECURITY_CREDENTIALS, JMS_PASSWORD); - } - initialContext = null; - try { - initialContext = new InitialContext(properties); - } catch (NamingException ne) { - // FIXME: getting java.lang.ClassNotFoundException: org.apache.activemq.jndi.ActiveMQInitialContextFactory - // works in debugging from Eclipse - somehow classpath doesn't work - // plugin has the activemq-all reference, as workaround set to false for now - isFromService = false; - } - - if (!isFromService) { - return new ActiveMQConnectionFactory(url); - } - else { - try { - return (ConnectionFactory) initialContext.lookup(JMS_CONN_FACTORY); - } catch (NamingException ne) { - ne.printStackTrace(System.err); - return null; - } - } - } - - public static String constructSelectorString(String projectID, String workspaceID) { - StringBuilder selectorBuilder = new StringBuilder(); - - //selectorBuilder.append("(").append(MSG_SELECTOR_REF_ID).append("='").append(workspaceID).append("')"); - - selectorBuilder.append("(").append(MSG_SELECTOR_PROJECT_ID).append(" = '").append(projectID).append("')") - .append(" AND ").append("((").append(MSG_SELECTOR_REF_ID).append(" = '").append(workspaceID).append("') OR (").append(MSG_SELECTOR_REF_ID).append(" = '").append(workspaceID).append("_mdk").append("'))"); - - String outputMsgSelector = selectorBuilder.toString(); - selectorBuilder.delete(0, selectorBuilder.length()); - - return outputMsgSelector; - } - - public static class JMSInfo { - private final String url; - private final boolean isFromService; - - public JMSInfo(String url, boolean isFromService) { - this.url = url; - this.isFromService = isFromService; - } - - public String getUrl() { - return url; - } - - public boolean isFromService() { - return isFromService; - } - } -} diff --git a/src/main/java/gov/nasa/jpl/mbee/mdk/mms/sync/coordinated/CoordinatedSyncProjectEventListenerAdapter.java b/src/main/java/gov/nasa/jpl/mbee/mdk/mms/sync/coordinated/CoordinatedSyncProjectEventListenerAdapter.java index 5ced930e0..837ec7184 100644 --- a/src/main/java/gov/nasa/jpl/mbee/mdk/mms/sync/coordinated/CoordinatedSyncProjectEventListenerAdapter.java +++ b/src/main/java/gov/nasa/jpl/mbee/mdk/mms/sync/coordinated/CoordinatedSyncProjectEventListenerAdapter.java @@ -1,7 +1,5 @@ package gov.nasa.jpl.mbee.mdk.mms.sync.coordinated; -import com.fasterxml.jackson.core.JsonProcessingException; -import com.fasterxml.jackson.databind.node.ObjectNode; import com.nomagic.ci.persistence.IProject; import com.nomagic.magicdraw.core.Application; import com.nomagic.magicdraw.core.Project; @@ -11,22 +9,12 @@ import com.nomagic.magicdraw.core.project.ProjectEventListenerAdapter; import com.nomagic.ui.ProgressStatusRunner; import com.nomagic.uml2.ext.jmi.helpers.StereotypesHelper; -import gov.nasa.jpl.mbee.mdk.api.incubating.convert.Converters; -import gov.nasa.jpl.mbee.mdk.json.JacksonUtils; import gov.nasa.jpl.mbee.mdk.mms.actions.MMSLoginAction; -import gov.nasa.jpl.mbee.mdk.mms.jms.JMSUtils; import gov.nasa.jpl.mbee.mdk.mms.sync.delta.DeltaSyncRunner; -import gov.nasa.jpl.mbee.mdk.mms.sync.delta.SyncElements; -import gov.nasa.jpl.mbee.mdk.mms.sync.jms.JMSMessageListener; -import gov.nasa.jpl.mbee.mdk.mms.sync.jms.JMSSyncProjectEventListenerAdapter; import gov.nasa.jpl.mbee.mdk.options.MDKOptionsGroup; -import gov.nasa.jpl.mbee.mdk.util.MDUtils; import gov.nasa.jpl.mbee.mdk.util.TicketUtils; import javax.annotation.CheckForNull; -import javax.jms.JMSException; -import javax.jms.Message; -import javax.jms.TextMessage; import java.util.Map; import java.util.concurrent.ConcurrentHashMap; @@ -58,7 +46,7 @@ public void projectPreSaved(Project project, boolean savedInServer) { if ((project.isRemote() && !savedInServer) || !StereotypesHelper.hasStereotype(project.getPrimaryModel(), "ModelManagementSystem") || CoordinatedSyncProjectEventListenerAdapter.getProjectMapping(project).isDisabled() - || JMSSyncProjectEventListenerAdapter.getProjectMapping(project).getJmsMessageListener().isDisabled()) { + || !TicketUtils.isTicketSet(project)) { // skip csync return; } @@ -67,46 +55,8 @@ public void projectPreSaved(Project project, boolean savedInServer) { } @Override - @SuppressWarnings("unchecked") public void projectSaved(Project project, boolean savedInServer) { - CoordinatedSyncProjectMapping coordinatedSyncProjectMapping = getProjectMapping(project); - if (coordinatedSyncProjectMapping.isDisabled() || deltaSyncRunner == null || deltaSyncRunner.isFailure()) { - // CSync isn't running, so return - return; - } - JMSSyncProjectEventListenerAdapter.JMSSyncProjectMapping jmsSyncProjectMapping = JMSSyncProjectEventListenerAdapter.getProjectMapping(project); - JMSMessageListener jmsMessageListener = jmsSyncProjectMapping.getJmsMessageListener(); - - // ACKNOWLEDGE LAST MMS MESSAGE TO CLEAR OWN QUEUE - - Message lastMessage; - if (jmsMessageListener != null && (lastMessage = jmsMessageListener.getLastMessage()) != null) { - try { - lastMessage.acknowledge(); - } catch (JMSException | IllegalStateException e) { - e.printStackTrace(); - } - } - // NOTIFY OTHER USERS OF PROCESSED ELEMENTS - - if (!deltaSyncRunner.getSuccessfulJmsChangelog().isEmpty()) { - ObjectNode teamworkCommittedMessage = JacksonUtils.getObjectMapper().createObjectNode(); - teamworkCommittedMessage.put("source", "magicdraw"); - teamworkCommittedMessage.put("sender", TicketUtils.getUsername(project)); - teamworkCommittedMessage.set("synced", SyncElements.buildJson(deltaSyncRunner.getSuccessfulJmsChangelog())); - try { - TextMessage successfulTextMessage = jmsSyncProjectMapping.getSession().createTextMessage(JacksonUtils.getObjectMapper().writeValueAsString(teamworkCommittedMessage)); - successfulTextMessage.setStringProperty(JMSUtils.MSG_SELECTOR_PROJECT_ID, Converters.getIProjectToIdConverter().apply(project.getPrimaryProject())); - successfulTextMessage.setStringProperty(JMSUtils.MSG_SELECTOR_REF_ID, MDUtils.getBranchId(project) + "_mdk"); - jmsSyncProjectMapping.getMessageProducer().send(successfulTextMessage); - int syncCount = deltaSyncRunner.getSuccessfulJmsChangelog().flattenedSize(); - Application.getInstance().getGUILog().log("[INFO] Notified other clients of " + syncCount + " locally updated element" + (syncCount != 1 ? "s" : "") + "."); - } catch (JMSException | JsonProcessingException | RuntimeException e) { - e.printStackTrace(); - Application.getInstance().getGUILog().log("[ERROR] Failed to notify other clients of synced elements. This could result in redundant local updates. Reason: " + e.getMessage()); - } - } } public static CoordinatedSyncProjectMapping getProjectMapping(Project project) { @@ -149,8 +99,7 @@ public boolean isReadyForCommit(IProject iProject, @CheckForNull String s) { if (CoordinatedSyncProjectEventListenerAdapter.getProjectMapping(project).isDisabled()) { return true; } - if (JMSSyncProjectEventListenerAdapter.getProjectMapping(project).getJmsMessageListener().isDisabled()) { - new Thread(() -> MMSLoginAction.loginAction(project)).start(); + if (!TicketUtils.isTicketSet(project) && !MMSLoginAction.loginAction(project)) { Application.getInstance().getGUILog().log("[WARNING] You must be logged in to MMS to synchronize the commit. Skipping commit. Please login to MMS and then commit again."); if (s != null && !s.isEmpty()) { Application.getInstance().getGUILog().log("[INFO] Recovered commit message:
" + s + "
"); diff --git a/src/main/java/gov/nasa/jpl/mbee/mdk/mms/sync/delta/DeltaSyncProjectEventListenerAdapter.java b/src/main/java/gov/nasa/jpl/mbee/mdk/mms/sync/delta/DeltaSyncProjectEventListenerAdapter.java index 7bf304f0e..e4a4da44a 100644 --- a/src/main/java/gov/nasa/jpl/mbee/mdk/mms/sync/delta/DeltaSyncProjectEventListenerAdapter.java +++ b/src/main/java/gov/nasa/jpl/mbee/mdk/mms/sync/delta/DeltaSyncProjectEventListenerAdapter.java @@ -6,10 +6,9 @@ import com.nomagic.magicdraw.openapi.uml.SessionManager; import com.nomagic.uml2.ext.jmi.helpers.StereotypesHelper; import gov.nasa.jpl.mbee.mdk.json.JacksonUtils; -import gov.nasa.jpl.mbee.mdk.mms.sync.jms.JMSMessageListener; -import gov.nasa.jpl.mbee.mdk.mms.sync.jms.JMSSyncProjectEventListenerAdapter; -import gov.nasa.jpl.mbee.mdk.mms.sync.local.LocalSyncProjectEventListenerAdapter; -import gov.nasa.jpl.mbee.mdk.mms.sync.local.LocalSyncTransactionCommitListener; +import gov.nasa.jpl.mbee.mdk.mms.sync.local.LocalDeltaProjectEventListenerAdapter; +import gov.nasa.jpl.mbee.mdk.mms.sync.local.LocalDeltaTransactionCommitListener; +import gov.nasa.jpl.mbee.mdk.mms.sync.mms.MMSDeltaProjectEventListenerAdapter; import gov.nasa.jpl.mbee.mdk.options.MDKOptionsGroup; import gov.nasa.jpl.mbee.mdk.util.Changelog; @@ -17,16 +16,6 @@ import java.util.Map; import java.util.function.Function; -/* - * This class is responsible for taking action when a project is opened. - * This class does the following when instantiated: - * 1. Create a transaction manager - * 2. Create a TransactionCommitListener object - * 3. Add the listener to the transaction manager object - * 4. Create a MMS topic and connection to that topic - * 5. Store that connection so we keep track of the connections to MMS. - * - */ public class DeltaSyncProjectEventListenerAdapter extends ProjectEventListenerAdapter { private static final Map>> CHANGELOG_FUNCTIONS = new HashMap<>(2); @@ -36,23 +25,21 @@ public class DeltaSyncProjectEventListenerAdapter extends ProjectEventListenerAd for (SyncElement syncElement : SyncElements.getAllByType(project, SyncElement.Type.LOCAL)) { combinedPersistedChangelog = combinedPersistedChangelog.and(SyncElements.buildChangelog(syncElement)); } - LocalSyncTransactionCommitListener localSyncTransactionCommitListener = LocalSyncProjectEventListenerAdapter.getProjectMapping(project).getLocalSyncTransactionCommitListener(); - if (localSyncTransactionCommitListener == null) { + LocalDeltaTransactionCommitListener localDeltaTransactionCommitListener = LocalDeltaProjectEventListenerAdapter.getProjectMapping(project).getLocalDeltaTransactionCommitListener(); + if (localDeltaTransactionCommitListener == null) { return combinedPersistedChangelog; } - return combinedPersistedChangelog.and(localSyncTransactionCommitListener.getInMemoryLocalChangelog(), (key, element) -> null); + return combinedPersistedChangelog.and(localDeltaTransactionCommitListener.getInMemoryLocalChangelog(), (key, element) -> null); }); + /* CHANGELOG_FUNCTIONS.put(SyncElement.Type.MMS, project -> { Changelog combinedPersistedChangelog = new Changelog<>(); for (SyncElement syncElement : SyncElements.getAllByType(project, SyncElement.Type.MMS)) { combinedPersistedChangelog = combinedPersistedChangelog.and(SyncElements.buildChangelog(syncElement)); } - JMSMessageListener jmsMessageListener = JMSSyncProjectEventListenerAdapter.getProjectMapping(project).getJmsMessageListener(); - if (jmsMessageListener == null) { - return combinedPersistedChangelog; - } - return combinedPersistedChangelog.and(jmsMessageListener.getInMemoryJMSChangelog(), (key, objectNode) -> null); + return combinedPersistedChangelog.and(MMSDeltaProjectEventListenerAdapter.getProjectMapping(project).getInMemoryChangelog()); }); + */ } @Override @@ -69,7 +56,7 @@ public void projectPreSaved(Project project, boolean savedInServer) { private static void persistChanges(Project project) { - LocalSyncTransactionCommitListener listener = LocalSyncProjectEventListenerAdapter.getProjectMapping(project).getLocalSyncTransactionCommitListener(); + LocalDeltaTransactionCommitListener listener = LocalDeltaProjectEventListenerAdapter.getProjectMapping(project).getLocalDeltaTransactionCommitListener(); if (listener != null) { listener.setDisabled(true); } diff --git a/src/main/java/gov/nasa/jpl/mbee/mdk/mms/sync/delta/DeltaSyncRunner.java b/src/main/java/gov/nasa/jpl/mbee/mdk/mms/sync/delta/DeltaSyncRunner.java index b94130ada..18d03ffe3 100644 --- a/src/main/java/gov/nasa/jpl/mbee/mdk/mms/sync/delta/DeltaSyncRunner.java +++ b/src/main/java/gov/nasa/jpl/mbee/mdk/mms/sync/delta/DeltaSyncRunner.java @@ -4,6 +4,7 @@ import com.fasterxml.jackson.core.JsonProcessingException; import com.fasterxml.jackson.databind.JsonNode; import com.fasterxml.jackson.databind.node.ObjectNode; +import com.google.common.collect.Iterables; import com.nomagic.magicdraw.core.Application; import com.nomagic.magicdraw.core.Project; import com.nomagic.magicdraw.core.ProjectUtilities; @@ -20,14 +21,12 @@ import gov.nasa.jpl.mbee.mdk.mms.MMSUtils; import gov.nasa.jpl.mbee.mdk.mms.actions.MMSLoginAction; import gov.nasa.jpl.mbee.mdk.mms.actions.UpdateClientElementAction; -import gov.nasa.jpl.mbee.mdk.mms.sync.jms.JMSMessageListener; -import gov.nasa.jpl.mbee.mdk.mms.sync.jms.JMSSyncProjectEventListenerAdapter; -import gov.nasa.jpl.mbee.mdk.mms.sync.local.LocalSyncProjectEventListenerAdapter; -import gov.nasa.jpl.mbee.mdk.mms.sync.local.LocalSyncTransactionCommitListener; +import gov.nasa.jpl.mbee.mdk.mms.sync.local.LocalDeltaProjectEventListenerAdapter; +import gov.nasa.jpl.mbee.mdk.mms.sync.local.LocalDeltaTransactionCommitListener; +import gov.nasa.jpl.mbee.mdk.mms.sync.mms.MMSDeltaProjectEventListenerAdapter; import gov.nasa.jpl.mbee.mdk.mms.validation.BranchValidator; import gov.nasa.jpl.mbee.mdk.mms.validation.ElementValidator; import gov.nasa.jpl.mbee.mdk.mms.validation.ProjectValidator; -import gov.nasa.jpl.mbee.mdk.options.MDKOptionsGroup; import gov.nasa.jpl.mbee.mdk.util.*; import gov.nasa.jpl.mbee.mdk.validation.ValidationSuite; import org.apache.http.client.methods.HttpRequestBase; @@ -49,7 +48,7 @@ public class DeltaSyncRunner implements RunnableWithProgress { private boolean failure = true; private Changelog failedLocalChangelog = new Changelog<>(); - private Changelog failedJmsChangelog = new Changelog<>(), successfulJmsChangelog = new Changelog<>(); + private Changelog failedMmsChangelog = new Changelog<>(), successfulMmsChangelog = new Changelog<>(); private List vss = new ArrayList<>(); @@ -68,14 +67,12 @@ public void run(ProgressStatus progressStatus) { return; } try { - if (!TicketUtils.isTicketValid(project, progressStatus)) { + if (!TicketUtils.isTicketValid(project, progressStatus) && !MMSLoginAction.loginAction(project)) { Utils.guilog("[WARNING] You are not logged in to MMS. Skipping sync. All changes will be persisted in the model and re-attempted in the next sync."); - new Thread(() -> MMSLoginAction.loginAction(project)).start(); return; } } catch (IOException | URISyntaxException | ServerException e) { Utils.guilog("[ERROR] An error occurred while validating credentials. Credentials will be cleared. Skipping sync. All changes will be persisted in the model and re-attempted in the next sync. Reason: " + e.getMessage()); - new Thread(() -> MMSLoginAction.loginAction(project)).start(); return; } @@ -103,13 +100,13 @@ public void run(ProgressStatus progressStatus) { return; } - LocalSyncTransactionCommitListener listener = LocalSyncProjectEventListenerAdapter.getProjectMapping(project).getLocalSyncTransactionCommitListener(); + LocalDeltaTransactionCommitListener listener = LocalDeltaProjectEventListenerAdapter.getProjectMapping(project).getLocalDeltaTransactionCommitListener(); // UPDATE LOCKS ILockProjectService lockService = EsiUtils.getLockService(project); if (lockService == null) { - Application.getInstance().getGUILog().log("[ERROR] Teamwork Cloud lock service unavailable. Skipping sync. All changes will be re-attempted in the next sync."); + Application.getInstance().getGUILog().log("[ERROR] Teamwork Cloud lock service is unavailable. Skipping sync. All changes will be re-attempted in the next sync."); return; } @@ -124,40 +121,21 @@ public void run(ProgressStatus progressStatus) { listener.setDisabled(false); } - // LOCK SYNC FOLDER + // UPDATE MMS CHANGELOG - //listener.setDisabled(true); - //SyncElements.lockSyncFolder(project); - //listener.setDisabled(false); - - // DOWNLOAD MMS MESSAGES IF ASYNC CONSUMER IS DISABLED - - JMSSyncProjectEventListenerAdapter.JMSSyncProjectMapping jmsSyncProjectMapping = JMSSyncProjectEventListenerAdapter.getProjectMapping(Application.getInstance().getProject()); - JMSMessageListener jmsMessageListener = jmsSyncProjectMapping.getJmsMessageListener(); - if (jmsMessageListener == null) { - if (MDKOptionsGroup.getMDKOptions().isChangeListenerEnabled()) { - Application.getInstance().getGUILog().log("[WARNING] Not connected to MMS queue. Skipping sync. All changes will be re-attempted in the next sync."); - } - return; - } - - /*if (jmsSyncProjectMapping.isDisabled()) { - jmsSyncProjectMapping.setDisabled(!JMSSyncProjectEventListenerAdapter.initDurable(project, jmsSyncProjectMapping)); - List textMessages = jmsSyncProjectMapping.getAllTextMessages(true); - if (textMessages == null) { - Utils.guilog("[ERROR] Could not get changes from MMS. Please check your network connection and try again."); - failure = true; + try { + if (!MMSDeltaProjectEventListenerAdapter.getProjectMapping(project).update()) { + Application.getInstance().getGUILog().log("[WARNING] MMS history is unavailable. Skipping sync. All changes will be re-attempted in the next sync."); return; } - for (TextMessage textMessage : textMessages) { - jmsMessageListener.onMessage(textMessage); - } - }*/ + } catch (URISyntaxException | IOException | ServerException e) { + Application.getInstance().getGUILog().log("[ERROR] An error occurred while updating MMS history. Credentials will be cleared. Skipping sync. All changes will be persisted in the model and re-attempted in the next sync. Reason: " + e.getMessage()); + e.printStackTrace(); + } // BUILD COMPLETE LOCAL CHANGELOG Changelog persistedLocalChangelog = new Changelog<>(); - //JSONObject persistedLocalChanges = DeltaSyncProjectEventListenerAdapter.getUpdatesOrFailed(Application.getInstance().getProject(), "update"); Collection persistedLocalSyncElements = SyncElements.getAllByType(project, SyncElement.Type.LOCAL); for (SyncElement syncElement : persistedLocalSyncElements) { persistedLocalChangelog = persistedLocalChangelog.and(SyncElements.buildChangelog(syncElement), (key, value) -> Converters.getIdToElementConverter().apply(key, project)); @@ -171,26 +149,25 @@ public void run(ProgressStatus progressStatus) { // BUILD COMPLETE MMS CHANGELOG - Changelog persistedJmsChangelog = new Changelog<>(); - Collection persistedJmsSyncElements = SyncElements.getAllByType(project, SyncElement.Type.MMS); - //JSONObject persistedJmsChanges = DeltaSyncProjectEventListenerAdapter.getUpdatesOrFailed(Application.getInstance().getProject(), "jms"); - for (SyncElement syncElement : persistedJmsSyncElements) { - persistedJmsChangelog = persistedJmsChangelog.and(SyncElements.buildChangelog(syncElement)); + Changelog persistedMmsChangelog = new Changelog<>(); + Collection persistedMmsSyncElements = SyncElements.getAllByType(project, SyncElement.Type.MMS); + for (SyncElement syncElement : persistedMmsSyncElements) { + persistedMmsChangelog = persistedMmsChangelog.and(SyncElements.buildChangelog(syncElement)); } - Changelog jmsChangelog = persistedJmsChangelog.and(jmsMessageListener.getInMemoryJMSChangelog(), (key, objectNode) -> null); + Changelog mmsChangelog = persistedMmsChangelog.and(MMSDeltaProjectEventListenerAdapter.getProjectMapping(project).getInMemoryChangelog(), (key, objectNode) -> null); - Map jmsCreated = jmsChangelog.get(Changelog.ChangeType.CREATED), - jmsUpdated = jmsChangelog.get(Changelog.ChangeType.UPDATED), - jmsDeleted = jmsChangelog.get(Changelog.ChangeType.DELETED); + Map mmsCreated = mmsChangelog.get(Changelog.ChangeType.CREATED), + mmsUpdated = mmsChangelog.get(Changelog.ChangeType.UPDATED), + mmsDeleted = mmsChangelog.get(Changelog.ChangeType.DELETED); - Set elementIdsToGet = new HashSet<>(jmsUpdated.keySet()); - elementIdsToGet.addAll(jmsCreated.keySet()); - if (shouldUpdate && !jmsChangelog.isEmpty()) { - int size = jmsChangelog.flattenedSize(); + Set elementIdsToGet = new HashSet<>(mmsUpdated.keySet()); + elementIdsToGet.addAll(mmsCreated.keySet()); + if (shouldUpdate && !mmsChangelog.isEmpty()) { + int size = mmsChangelog.flattenedSize(); Application.getInstance().getGUILog().log("[INFO] Getting " + size + " changed element" + (size != 1 ? "s" : "") + " from the MMS."); } - Map jmsJsons = new HashMap<>(elementIdsToGet.size()); + Map mmsJsons = new HashMap<>(elementIdsToGet.size()); // Get latest json for element added/changed from MMS @@ -231,7 +208,7 @@ public void run(ProgressStatus progressStatus) { continue; } String webId = jsonNode.get(MDKConstants.ID_KEY).asText(); - jmsJsons.put(webId, (ObjectNode) jsonNode); + mmsJsons.put(webId, (ObjectNode) jsonNode); } } @@ -240,23 +217,23 @@ public void run(ProgressStatus progressStatus) { progressStatus.setDescription("Detecting conflicts"); Map, Changelog.Change>> conflictedChanges = new LinkedHashMap<>(), unconflictedChanges = new LinkedHashMap<>(); - localChangelog.findConflicts(jmsChangelog, (change, change2) -> change != null && change2 != null, conflictedChanges, unconflictedChanges); + localChangelog.findConflicts(mmsChangelog, (change, change2) -> change != null && change2 != null, conflictedChanges, unconflictedChanges); // MAP CHANGES TO ACTIONABLE GROUPS Map localElementsToPost = new LinkedHashMap<>(localCreated.size() + localUpdated.size()); Set deleteElements = new HashSet<>(localDeleted.size()); - Map jmsElementsToCreateLocally = new LinkedHashMap<>(jmsCreated.size()); - Map> jmsElementsToUpdateLocally = new LinkedHashMap<>(jmsUpdated.size()); - Map jmsElementsToDeleteLocally = new LinkedHashMap<>(jmsDeleted.size()); + Map mmsElementsToCreateLocally = new LinkedHashMap<>(mmsCreated.size()); + Map> mmsElementsToUpdateLocally = new LinkedHashMap<>(mmsUpdated.size()); + Map mmsElementsToDeleteLocally = new LinkedHashMap<>(mmsDeleted.size()); // only one side of the pair will have a value when unconflicted for (Map.Entry, Changelog.Change>> unconflictedEntry : unconflictedChanges.entrySet()) { String id = unconflictedEntry.getKey(); Changelog.Change localChange = unconflictedEntry.getValue().getKey(); - Changelog.Change jmsChange = unconflictedEntry.getValue().getValue() != null ? - new Changelog.Change<>(jmsJsons.get(id), unconflictedEntry.getValue().getValue().getType()) : null; + Changelog.Change mmsChange = unconflictedEntry.getValue().getValue() != null ? + new Changelog.Change<>(mmsJsons.get(id), unconflictedEntry.getValue().getValue().getType()) : null; if (shouldCommit && localChange != null) { Element element = localChange.getChanged(); @@ -278,10 +255,10 @@ public void run(ProgressStatus progressStatus) { break; } } - else if (shouldUpdate && jmsChange != null) { - ObjectNode objectNode = jmsChange.getChanged(); + else if (shouldUpdate && mmsChange != null) { + ObjectNode objectNode = mmsChange.getChanged(); Element element = Converters.getIdToElementConverter().apply(id, project); - switch (jmsChange.getType()) { + switch (mmsChange.getType()) { case CREATED: if (objectNode == null) { Application.getInstance().getGUILog().log("[INFO] Attempted to create element " + id + " locally, but it no longer exists on the MMS. Skipping."); @@ -291,7 +268,7 @@ else if (shouldUpdate && jmsChange != null) { Application.getInstance().getGUILog().log("[INFO] Attempted to create element " + id + " locally, but it already exists. Skipping."); continue; } - jmsElementsToCreateLocally.put(id, objectNode); + mmsElementsToCreateLocally.put(id, objectNode); break; case UPDATED: if (objectNode == null) { @@ -306,10 +283,10 @@ else if (shouldUpdate && jmsChange != null) { if (MDUtils.isDeveloperMode()) { Application.getInstance().getGUILog().log("[INFO] Attempted to update element " + id + " locally, but it is locked by someone else. Skipping."); } - failedJmsChangelog.addChange(id, null, Changelog.ChangeType.UPDATED); + failedMmsChangelog.addChange(id, null, Changelog.ChangeType.UPDATED); continue; } - jmsElementsToUpdateLocally.put(id, new Pair<>(objectNode, element)); + mmsElementsToUpdateLocally.put(id, new Pair<>(objectNode, element)); break; case DELETED: if (element == null) { @@ -320,10 +297,10 @@ else if (shouldUpdate && jmsChange != null) { if (MDUtils.isDeveloperMode()) { Application.getInstance().getGUILog().log("[INFO] Attempted to delete element " + id + " locally, but it is locked by someone else. Skipping."); } - failedJmsChangelog.addChange(id, null, Changelog.ChangeType.DELETED); + failedMmsChangelog.addChange(id, null, Changelog.ChangeType.DELETED); continue; } - jmsElementsToDeleteLocally.put(id, element); + mmsElementsToDeleteLocally.put(id, element); break; } } @@ -410,17 +387,17 @@ else if (shouldUpdate && jmsChange != null) { listener.setDisabled(true); // Create and update maps are mutually exclusive at this point, so this is safe. If they weren't then the ordering may be messed up. - List jmsElementsToCreateOrUpdateLocally = new ArrayList<>(jmsElementsToCreateLocally.size() + jmsElementsToUpdateLocally.size()); - jmsElementsToCreateOrUpdateLocally.addAll(jmsElementsToCreateLocally.values()); - jmsElementsToUpdateLocally.values().forEach(pair -> jmsElementsToCreateOrUpdateLocally.add(pair.getKey())); + List mmsElementsToCreateOrUpdateLocally = new ArrayList<>(mmsElementsToCreateLocally.size() + mmsElementsToUpdateLocally.size()); + mmsElementsToCreateOrUpdateLocally.addAll(mmsElementsToCreateLocally.values()); + mmsElementsToUpdateLocally.values().forEach(pair -> mmsElementsToCreateOrUpdateLocally.add(pair.getKey())); UpdateClientElementAction updateClientElementAction = new UpdateClientElementAction(project); - updateClientElementAction.setElementsToUpdate(jmsElementsToCreateOrUpdateLocally); - updateClientElementAction.setElementsToDelete(jmsElementsToDeleteLocally.values().stream().map(Converters.getElementToIdConverter()).filter(id -> id != null).filter(id -> !id.isEmpty()).collect(Collectors.toList())); + updateClientElementAction.setElementsToUpdate(mmsElementsToCreateOrUpdateLocally); + updateClientElementAction.setElementsToDelete(mmsElementsToDeleteLocally.values().stream().map(Converters.getElementToIdConverter()).filter(Objects::nonNull).filter(id -> !id.isEmpty()).collect(Collectors.toList())); updateClientElementAction.run(progressStatus); - failedJmsChangelog = failedJmsChangelog.and(updateClientElementAction.getFailedChangelog(), (id, objectNode) -> null); - successfulJmsChangelog = updateClientElementAction.getSuccessfulChangelog(); + failedMmsChangelog = failedMmsChangelog.and(updateClientElementAction.getFailedChangelog(), (id, objectNode) -> null); + successfulMmsChangelog = updateClientElementAction.getSuccessfulChangelog(); listener.setDisabled(false); } @@ -429,23 +406,23 @@ else if (shouldUpdate && jmsChange != null) { progressStatus.setDescription("Finishing up"); Set localConflictedElements = new HashSet<>(); - Set jmsConflictedElements = new HashSet<>(); + Set mmsConflictedElements = new HashSet<>(); for (Map.Entry, Changelog.Change>> conflictedEntry : conflictedChanges.entrySet()) { String id = conflictedEntry.getKey(); Changelog.Change localChange = conflictedEntry.getValue().getKey(); - Changelog.Change jmsChange = conflictedEntry.getValue().getValue() != null ? - new Changelog.Change<>(jmsJsons.get(id), conflictedEntry.getValue().getValue().getType()) : null; + Changelog.Change mmsChange = conflictedEntry.getValue().getValue() != null ? + new Changelog.Change<>(mmsJsons.get(id), conflictedEntry.getValue().getValue().getType()) : null; if (localChange != null && localChange.getChanged() != null && !project.isDisposed(localChange.getChanged())) { localConflictedElements.add(localChange.getChanged()); } - if (jmsChange != null && jmsChange.getChanged() != null) { - jmsConflictedElements.add(jmsChange.getChanged()); + if (mmsChange != null && mmsChange.getChanged() != null) { + mmsConflictedElements.add(mmsChange.getChanged()); } } - ElementValidator elementValidator = new ElementValidator("CSync Conflict Validation", ElementValidator.buildElementPairs(localConflictedElements, project), jmsConflictedElements, project); + ElementValidator elementValidator = new ElementValidator("CSync Conflict Validation", ElementValidator.buildElementPairs(localConflictedElements, project), mmsConflictedElements, project); elementValidator.run(progressStatus); 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."); @@ -458,28 +435,43 @@ else if (shouldUpdate && jmsChange != null) { continue; } Changelog.Change localChange = conflictedEntry.getValue().getKey(); - Changelog.Change jmsChange = conflictedEntry.getValue().getValue() != null ? - new Changelog.Change<>(jmsJsons.get(id), conflictedEntry.getValue().getValue().getType()) : null; + Changelog.Change mmsChange = conflictedEntry.getValue().getValue() != null ? + new Changelog.Change<>(mmsJsons.get(id), conflictedEntry.getValue().getValue().getType()) : null; if (localChange != null && (localChange.getChanged() != null || Changelog.ChangeType.DELETED.equals(localChange.getType()))) { failedLocalChangelog.addChange(conflictedEntry.getKey(), localChange.getChanged(), localChange.getType()); } - if (jmsChange != null && (jmsChange.getChanged() != null || Changelog.ChangeType.DELETED.equals(jmsChange.getType()))) { - failedJmsChangelog.addChange(conflictedEntry.getKey(), null, jmsChange.getType()); + if (mmsChange != null && (mmsChange.getChanged() != null || Changelog.ChangeType.DELETED.equals(mmsChange.getType()))) { + failedMmsChangelog.addChange(conflictedEntry.getKey(), null, mmsChange.getType()); } } } // CLEAR IN-MEMORY AND PERSIST UNPROCESSED & FAILURES - listener.getInMemoryLocalChangelog().clear(); - jmsMessageListener.getInMemoryJMSChangelog().clear(); - listener.setDisabled(true); if (!SessionManager.getInstance().isSessionCreated()) { SessionManager.getInstance().createSession("Delta Sync Changelog Persistence"); } + MMSDeltaProjectEventListenerAdapter.MMSDeltaProjectMapping mmsDeltaProjectMapping = MMSDeltaProjectEventListenerAdapter.getProjectMapping(project); + String commitId = !mmsDeltaProjectMapping.getInMemoryCommits().isEmpty() ? Iterables.getLast(mmsDeltaProjectMapping.getInMemoryCommits()) : mmsDeltaProjectMapping.getLastSyncedCommitId(); + if (commitId != null) { + ObjectNode mmsCommitObjectNode = JacksonUtils.getObjectMapper().createObjectNode(); + mmsCommitObjectNode.put("branchId", MDUtils.getBranchId(project)); + mmsCommitObjectNode.put("commitId", commitId); + + try { + SyncElements.setByType(project, SyncElement.Type.MMS_COMMIT, JacksonUtils.getObjectMapper().writeValueAsString(mmsCommitObjectNode)); + } catch (JsonProcessingException e) { + e.printStackTrace(); + } + } + + listener.getInMemoryLocalChangelog().clear(); + MMSDeltaProjectEventListenerAdapter.getProjectMapping(project).getInMemoryChangelog().clear(); + MMSDeltaProjectEventListenerAdapter.getProjectMapping(project).getInMemoryCommits().clear(); + Changelog unprocessedLocalChangelog = new Changelog<>(); if (!shouldCommit) { unprocessedLocalChangelog = unprocessedLocalChangelog.and(localChangelog, (s, element) -> null); @@ -497,13 +489,13 @@ else if (shouldUpdate && jmsChange != null) { e.printStackTrace(); } - Changelog unprocessedJmsChangelog = new Changelog<>(); + Changelog unprocessedMmsChangelog = new Changelog<>(); if (!shouldUpdate) { - unprocessedJmsChangelog = unprocessedJmsChangelog.and(jmsChangelog); + unprocessedMmsChangelog = unprocessedMmsChangelog.and(mmsChangelog); } - unprocessedJmsChangelog = unprocessedJmsChangelog.and(failedJmsChangelog); + unprocessedMmsChangelog = unprocessedMmsChangelog.and(failedMmsChangelog); try { - SyncElements.setByType(project, SyncElement.Type.MMS, JacksonUtils.getObjectMapper().writeValueAsString(SyncElements.buildJson(unprocessedJmsChangelog))); + SyncElements.setByType(project, SyncElement.Type.MMS, JacksonUtils.getObjectMapper().writeValueAsString(SyncElements.buildJson(unprocessedMmsChangelog))); } catch (JsonProcessingException e) { e.printStackTrace(); } @@ -515,8 +507,8 @@ else if (shouldUpdate && jmsChange != null) { failure = false; } - public Changelog getSuccessfulJmsChangelog() { - return successfulJmsChangelog; + public Changelog getSuccessfulMmsChangelog() { + return successfulMmsChangelog; } public boolean isFailure() { diff --git a/src/main/java/gov/nasa/jpl/mbee/mdk/mms/sync/delta/SyncElement.java b/src/main/java/gov/nasa/jpl/mbee/mdk/mms/sync/delta/SyncElement.java index ecd2973e3..11e5148b9 100644 --- a/src/main/java/gov/nasa/jpl/mbee/mdk/mms/sync/delta/SyncElement.java +++ b/src/main/java/gov/nasa/jpl/mbee/mdk/mms/sync/delta/SyncElement.java @@ -24,7 +24,8 @@ public Type getType() { public enum Type { LOCAL, - MMS; + MMS, + MMS_COMMIT; private String prefix; diff --git a/src/main/java/gov/nasa/jpl/mbee/mdk/mms/sync/delta/SyncElements.java b/src/main/java/gov/nasa/jpl/mbee/mdk/mms/sync/delta/SyncElements.java index f62f3c421..1c927d93b 100644 --- a/src/main/java/gov/nasa/jpl/mbee/mdk/mms/sync/delta/SyncElements.java +++ b/src/main/java/gov/nasa/jpl/mbee/mdk/mms/sync/delta/SyncElements.java @@ -20,6 +20,7 @@ import gov.nasa.jpl.mbee.mdk.api.incubating.convert.Converters; import gov.nasa.jpl.mbee.mdk.json.JacksonUtils; import gov.nasa.jpl.mbee.mdk.util.Changelog; +import gov.nasa.jpl.mbee.mdk.util.MDUtils; import java.io.IOException; import java.time.ZonedDateTime; @@ -52,7 +53,7 @@ public static Collection getAllByType(Project project, SyncElement. if (syncPackage == null) { return Collections.emptyList(); } - return syncPackage.getPackagedElement().stream().filter(element -> element.getName().startsWith(type.getPrefix())).map(element -> new SyncElement(element, type)).collect(Collectors.toList()); + return syncPackage.getPackagedElement().stream().filter(element -> element.getName().matches(type.getPrefix() + "_\\d.*")).map(element -> new SyncElement(element, type)).collect(Collectors.toList()); } public static SyncElement setByType(Project project, SyncElement.Type type, String comment) { @@ -78,11 +79,11 @@ public static SyncElement setByType(Project project, SyncElement.Type type, Stri } LiteralString literalString = project.getElementsFactory().createLiteralStringInstance(); - literalString.setID(literalString.getID() + MDKConstants.SYNC_SYSML_ID_SUFFIX); + literalString.setLocalID(literalString.getLocalID() + MDKConstants.SYNC_SYSML_ID_SUFFIX); literalString.setValue(comment); InstanceSpecification instanceSpecification = project.getElementsFactory().createInstanceSpecificationInstance(); - instanceSpecification.setID(instanceSpecification.getID() + MDKConstants.SYNC_SYSML_ID_SUFFIX); + instanceSpecification.setLocalID(instanceSpecification.getLocalID() + MDKConstants.SYNC_SYSML_ID_SUFFIX); instanceSpecification.setOwningPackage(syncPackage); instanceSpecification.setName(type.toString().toLowerCase() + "_" + ZonedDateTime.now().format(DATE_TIME_FORMATTER)); instanceSpecification.setSpecification(literalString); @@ -106,11 +107,11 @@ public static Changelog buildChangelog(SyncElement syncElement) { return buildChangelog(changelog, syncElement); } - public static Changelog buildChangelog(Changelog changelog, SyncElement syncElement) { + public static String getValue(SyncElement syncElement) { InstanceSpecification syncInstance; String body; if (syncElement == null || syncElement.getElement() == null) { - return new Changelog<>(); + return null; } else if (syncElement.getElement() instanceof InstanceSpecification && (syncInstance = (InstanceSpecification) syncElement.getElement()).getSpecification() instanceof LiteralString) { body = ((LiteralString) syncInstance.getSpecification()).getValue(); @@ -118,6 +119,14 @@ else if (syncElement.getElement() instanceof InstanceSpecification && (syncInsta else { body = ModelHelper.getComment(syncElement.getElement()); } + return body; + } + + public static Changelog buildChangelog(Changelog changelog, SyncElement syncElement) { + if (syncElement == null || syncElement.getElement() == null) { + return new Changelog<>(); + } + String body = getValue(syncElement); if (body != null) { try { JsonNode jsonNode = JacksonUtils.getObjectMapper().readTree(body); diff --git a/src/main/java/gov/nasa/jpl/mbee/mdk/mms/sync/jms/JMSMessageListener.java b/src/main/java/gov/nasa/jpl/mbee/mdk/mms/sync/jms/JMSMessageListener.java deleted file mode 100644 index 0d1a58137..000000000 --- a/src/main/java/gov/nasa/jpl/mbee/mdk/mms/sync/jms/JMSMessageListener.java +++ /dev/null @@ -1,225 +0,0 @@ -package gov.nasa.jpl.mbee.mdk.mms.sync.jms; - -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.esi.EsiUtils; -import com.nomagic.uml2.ext.magicdraw.classes.mdkernel.Element; -import gov.nasa.jpl.mbee.mdk.api.incubating.MDKConstants; -import gov.nasa.jpl.mbee.mdk.api.incubating.convert.Converters; -import gov.nasa.jpl.mbee.mdk.emf.EMFImporter; -import gov.nasa.jpl.mbee.mdk.json.ImportException; -import gov.nasa.jpl.mbee.mdk.json.JacksonUtils; -import gov.nasa.jpl.mbee.mdk.mms.actions.MMSLogoutAction; -import gov.nasa.jpl.mbee.mdk.mms.sync.delta.SyncElements; -import gov.nasa.jpl.mbee.mdk.mms.sync.status.SyncStatusConfigurator; -import gov.nasa.jpl.mbee.mdk.options.MDKOptionsGroup; -import gov.nasa.jpl.mbee.mdk.util.Changelog; -import gov.nasa.jpl.mbee.mdk.util.MDUtils; -import gov.nasa.jpl.mbee.mdk.util.TicketUtils; - -import javax.jms.*; -import java.io.IOException; -import java.util.*; -import java.util.concurrent.atomic.AtomicBoolean; - -public class JMSMessageListener implements MessageListener, ExceptionListener { - private static final Map CHANGE_MAPPING = new LinkedHashMap<>(4); - - static { - CHANGE_MAPPING.put("addedElements", Changelog.ChangeType.CREATED); - CHANGE_MAPPING.put("deletedElements", Changelog.ChangeType.DELETED); - CHANGE_MAPPING.put("movedElements", Changelog.ChangeType.UPDATED); - CHANGE_MAPPING.put("updatedElements", Changelog.ChangeType.UPDATED); - } - - private final AtomicBoolean disabled = new AtomicBoolean(true); - private final AtomicBoolean exceptionHandlerRunning = new AtomicBoolean(); - private int reconnectionAttempts = 0; - - private final Project project; - private final Changelog inMemoryJMSChangelog = new Changelog<>(); - - { - if (MDUtils.isDeveloperMode()) { - inMemoryJMSChangelog.setShouldLogChanges(true); - } - } - - public void setDisabled(boolean disabled) { - synchronized (this.disabled) { - this.disabled.set(disabled); - } - } - - public boolean isDisabled() { - synchronized (this.disabled) { - return (disabled.get() || !MDKOptionsGroup.getMDKOptions().isChangeListenerEnabled()); - } - } - - private Message lastMessage; - - public boolean isExceptionHandlerRunning() { - synchronized (this.exceptionHandlerRunning) { - return exceptionHandlerRunning.get(); - } - } - - JMSMessageListener(Project project) { - this.project = project; - } - - @Override - public void onMessage(Message message) { - if (isDisabled()) { - return; - } - lastMessage = message; - if (!(message instanceof TextMessage)) { - return; - } - final String text; - try { - text = ((TextMessage) message).getText(); - } catch (JMSException e) { - e.printStackTrace(); - return; - } - if (MDKOptionsGroup.getMDKOptions().isLogJson()) { - System.out.println("MMS TextMessage for " + Converters.getIProjectToIdConverter().apply(project.getPrimaryProject()) + " -" + System.lineSeparator() + text); - } - JsonNode messageJsonNode; - try { - messageJsonNode = JacksonUtils.getObjectMapper().readTree(text); - } catch (IOException e) { - e.printStackTrace(); - return; - } - if (!messageJsonNode.isObject()) { - return; - } - - JsonNode refsJsonNode = messageJsonNode.get("refs"), - syncedJsonNode = messageJsonNode.get("synced"), - sourceJsonNode = messageJsonNode.get("source"), - senderJsonNode = messageJsonNode.get("sender"); - - if (refsJsonNode != null && refsJsonNode.isObject()) { - if (sourceJsonNode != null && sourceJsonNode.isTextual() && sourceJsonNode.asText().startsWith("magicdraw")) { - return; - } - for (Map.Entry entry : CHANGE_MAPPING.entrySet()) { - JsonNode changeJsonNode = refsJsonNode.get(entry.getKey()); - if (changeJsonNode == null || !changeJsonNode.isArray()) { - continue; - } - for (JsonNode sysmlIdJsonNode : changeJsonNode) { - if (!sysmlIdJsonNode.isTextual() || sysmlIdJsonNode.asText().isEmpty()) { - continue; - } - String id = sysmlIdJsonNode.asText(); - try { - ObjectNode elementJsonNode = JacksonUtils.getObjectMapper().createObjectNode(); - elementJsonNode.put(MDKConstants.ID_KEY, id); - if (EMFImporter.PreProcessor.SYSML_ID_VALIDATION.getFunction().apply(elementJsonNode, project, false, project.getPrimaryModel()) == null) { - continue; - } - } catch (ImportException ignored) { - continue; - } - inMemoryJMSChangelog.addChange(id, null, entry.getValue()); - } - SyncStatusConfigurator.getSyncStatusAction().update(); - } - } - else if (syncedJsonNode != null && syncedJsonNode.isObject()) { - if (senderJsonNode != null && senderJsonNode.isTextual() && senderJsonNode.asText().equals(TicketUtils.getUsername(project))) { - return; - } - Changelog syncedChangelog = SyncElements.buildChangelog((ObjectNode) syncedJsonNode); - if (syncedChangelog.isEmpty()) { - return; - } - Collection ignoredIds; - if (project.isRemote()) { - ignoredIds = new HashSet<>(); - Collection locks = EsiUtils.getLockService(project).getLockedByMe(); - for (Element lock : locks) { - ignoredIds.add(lock.getLocalID()); - } - } - else { - ignoredIds = Collections.emptyList(); - } - for (Changelog.ChangeType changeType : Changelog.ChangeType.values()) { - Map inMemoryJMSChanges = inMemoryJMSChangelog.get(changeType); - Set keys = syncedChangelog.get(changeType).keySet(); - keys.removeAll(ignoredIds); - keys.forEach(inMemoryJMSChanges::remove); - } - int size = syncedChangelog.flattenedSize(); - if (MDUtils.isDeveloperMode()) { - Application.getInstance().getGUILog().log("[INFO] " + project.getName() + " - Cleared up to " + size + " MMS element change" + (size != 1 ? "s" : "") + " as a result of another client syncing the model."); - } - SyncStatusConfigurator.getSyncStatusAction().update(); - } - } - - public Changelog getInMemoryJMSChangelog() { - return inMemoryJMSChangelog; - } - - public Message getLastMessage() { - return lastMessage; - } - - @Override - public void onException(JMSException exception) { - if (exceptionHandlerRunning.get()) { - return; - } - exceptionHandlerRunning.set(true); - try { - Application.getInstance().getGUILog().log("[WARNING] " + project.getName() + " - Lost connection with MMS. Please check your network configuration."); - JMSSyncProjectEventListenerAdapter.getProjectMapping(project).getJmsMessageListener().setDisabled(true); - while (shouldAttemptToReconnect()) { - int delay = Math.min(600, (int) Math.pow(2, reconnectionAttempts++)); - Application.getInstance().getGUILog().log("[INFO] " + project.getName() + " - Attempting to reconnect to MMS in " + delay + " second" + (delay != 1 ? "s" : "") + "."); - try { - Thread.sleep(delay * 1000); - } catch (InterruptedException ignored) { - } - if (!exceptionHandlerRunning.get()) { - break; - } - if (shouldAttemptToReconnect()) { - JMSSyncProjectEventListenerAdapter.closeJMS(project); - JMSSyncProjectEventListenerAdapter.initializeJMS(project); - } - } - } catch (RuntimeException e) { - Application.getInstance().getGUILog().log("[WARNING] " + project.getName() + " - An unexpected error occurred. Reason: " + e.getMessage()); - e.printStackTrace(); - } finally { - if (!JMSSyncProjectEventListenerAdapter.getProjectMapping(project).getJmsMessageListener().isDisabled()) { - reconnectionAttempts = 0; - Application.getInstance().getGUILog().log("[INFO] " + project.getName() + " - Successfully reconnected to MMS after dropped connection."); - } - else { - Application.getInstance().getGUILog().log("[WARNING] " + project.getName() + " - Failed to reconnect to MMS after dropped connection. Please manually login to MMS, or close and re-open the project, to re-initiate."); - MMSLogoutAction.logoutAction(project); - } - - reconnectionAttempts = 0; - exceptionHandlerRunning.set(false); - } - } - - private boolean shouldAttemptToReconnect() { - return !project.isProjectClosed() && TicketUtils.isTicketSet(project) - && JMSSyncProjectEventListenerAdapter.shouldEnableJMS(project) - && JMSSyncProjectEventListenerAdapter.getProjectMapping(project).getJmsMessageListener().isDisabled(); - } -} diff --git a/src/main/java/gov/nasa/jpl/mbee/mdk/mms/sync/jms/JMSSyncProjectEventListenerAdapter.java b/src/main/java/gov/nasa/jpl/mbee/mdk/mms/sync/jms/JMSSyncProjectEventListenerAdapter.java deleted file mode 100644 index f1f25048f..000000000 --- a/src/main/java/gov/nasa/jpl/mbee/mdk/mms/sync/jms/JMSSyncProjectEventListenerAdapter.java +++ /dev/null @@ -1,316 +0,0 @@ -package gov.nasa.jpl.mbee.mdk.mms.sync.jms; - -import com.nomagic.magicdraw.core.Application; -import com.nomagic.magicdraw.core.Project; -import com.nomagic.magicdraw.core.ProjectUtilities; -import com.nomagic.magicdraw.core.project.ProjectEventListenerAdapter; -import com.nomagic.magicdraw.esi.EsiUtils; -import com.nomagic.uml2.ext.jmi.helpers.StereotypesHelper; -import gov.nasa.jpl.mbee.mdk.api.incubating.convert.Converters; -import gov.nasa.jpl.mbee.mdk.http.ServerException; -import gov.nasa.jpl.mbee.mdk.mms.actions.MMSLoginAction; -import gov.nasa.jpl.mbee.mdk.mms.jms.JMSUtils; -import gov.nasa.jpl.mbee.mdk.options.MDKOptionsGroup; -import gov.nasa.jpl.mbee.mdk.util.MDUtils; -import gov.nasa.jpl.mbee.mdk.util.TicketUtils; - -import javax.jms.*; -import javax.naming.NameNotFoundException; -import java.lang.IllegalStateException; -import java.util.ArrayList; -import java.util.List; -import java.util.Map; -import java.util.concurrent.ConcurrentHashMap; - -public class JMSSyncProjectEventListenerAdapter extends ProjectEventListenerAdapter { - private static final String ERROR_STRING = "Reverting to offline mode. All changes will be saved in the model until reconnected."; - private static final Map projectMappings = new ConcurrentHashMap<>(); - - // Cannot rely on this being called when MagicDraw programmatically reloads a project, which makes the old Project stale. - // Mitigating by moving all logic to mapping constructor, but this leaves gaps where events may not be captured. - @Override - public void projectOpened(final Project project) { - closeJMS(project); - getProjectMapping(project); - if (shouldEnableJMS(project)) { - new Thread(() -> { - if (TicketUtils.isTicketSet(project)) { - initializeJMS(project); - } - else if (!MMSLoginAction.loginAction(project) && project.isRemote()) { - Application.getInstance().getGUILog().log("[WARNING] Not logged in to MMS. You must be logged in to MMS prior to committing."); - // loginAction contains a call to initializeJMS on a successful ticket get - } - }).start(); - } - } - - @Override - public void projectClosed(Project project) { - closeJMS(project); - projectMappings.remove(project); - } - - @Override - public void projectReplaced(Project oldProject, Project newProject) { - projectClosed(oldProject); - projectOpened(newProject); - } - - @Override - public void projectSaved(Project project, boolean savedInServer) { - JMSSyncProjectMapping jmsSyncProjectMapping = getProjectMapping(project); - - JMSMessageListener jmsMessageListener = jmsSyncProjectMapping.getJmsMessageListener(); - if (jmsMessageListener != null) { - jmsMessageListener.getInMemoryJMSChangelog().clear(); - } - } - - public static boolean shouldEnableJMS(Project project) { - String url; - return (project.getPrimaryModel() != null && project.isRemote() - && MDKOptionsGroup.getMDKOptions().isChangeListenerEnabled() - && StereotypesHelper.hasStereotype(project.getPrimaryModel(), "ModelManagementSystem")) - && (url = ((String) StereotypesHelper.getStereotypePropertyFirst(project.getPrimaryModel(), "ModelManagementSystem", "MMS URL"))) != null - && !url.isEmpty(); - } - - public static void initializeJMS(Project project) { - JMSSyncProjectMapping jmsSyncProjectMapping = getProjectMapping(project); - if (jmsSyncProjectMapping == null || jmsSyncProjectMapping.getJmsMessageListener() == null || !jmsSyncProjectMapping.getJmsMessageListener().isDisabled()) { - return; - } - if (!shouldEnableJMS(project)) { - jmsSyncProjectMapping.getJmsMessageListener().setDisabled(true); - return; - } - boolean initialized = initDurable(project); - jmsSyncProjectMapping.getJmsMessageListener().setDisabled(!initialized); - } - - public static void closeJMS(Project project) { - JMSSyncProjectMapping jmsSyncProjectMapping = projectMappings.get(project); - if (jmsSyncProjectMapping == null) { - return; - } - try { - if (jmsSyncProjectMapping.getMessageConsumer() != null) { - jmsSyncProjectMapping.getMessageConsumer().close(); - } - if (jmsSyncProjectMapping.getSession() != null) { - jmsSyncProjectMapping.getSession().close(); - } - if (jmsSyncProjectMapping.getConnection() != null) { - jmsSyncProjectMapping.getConnection().close(); - } - } catch (JMSException e) { - e.printStackTrace(); - } - } - - private static boolean initDurable(Project project) { - String projectId = Converters.getIProjectToIdConverter().apply(project.getPrimaryProject()); - String workspaceId; - try { - workspaceId = MDUtils.getBranchId(project); - } catch (RuntimeException e) { - e.printStackTrace(); - Application.getInstance().getGUILog().log("[WARNING] " + project.getName() + " - " + ERROR_STRING + " Reason: " + e.getMessage()); - return false; - } - - // verify logged in to appropriate places - if (!TicketUtils.isTicketSet(project)) { - Application.getInstance().getGUILog().log("[WARNING] " + project.getName() + " - " + ERROR_STRING + " Reason: You must be logged into MMS."); - return false; - } - if (ProjectUtilities.isFromEsiServer(project.getPrimaryProject())) { - if (!com.nomagic.magicdraw.teamwork2.esi.EsiSessionUtil.isLoggedIn()) { - Application.getInstance().getGUILog().log("[WARNING] " + project.getName() + " - " + ERROR_STRING + " Reason: You must be logged into Teamwork Cloud."); - return false; - } - } - - // get jms connection info and connect - JMSUtils.JMSInfo jmsInfo; - try { - jmsInfo = JMSUtils.getJMSInfo(project); - } catch (ServerException | IllegalArgumentException | IllegalStateException e) { - e.printStackTrace(); - Application.getInstance().getGUILog().log("[WARNING] " + project.getName() + " - " + ERROR_STRING + " Reason: " + e.getMessage()); - return false; - } - String url = (jmsInfo != null ? jmsInfo.getUrl() : null); - if (url == null) { - Application.getInstance().getGUILog().log("[WARNING] " + project.getName() + " - " + ERROR_STRING + " Reason: Cannot get server URL."); - return false; - } - if (workspaceId == null) { - Application.getInstance().getGUILog().log("[WARNING] " + project.getName() + " - " + ERROR_STRING + " Reason: Cannot get the MMS branch that corresponds to this project's branch."); - return false; - } - if (ProjectUtilities.isFromEsiServer(project.getPrimaryProject())) { - String user = EsiUtils.getLoggedUserName(); - if (user == null) { - Application.getInstance().getGUILog().log("[ERROR] You must be logged into Teamwork Cloud. MMS sync will not start."); - return false; - } - } - - JMSSyncProjectMapping jmsSyncProjectMapping = getProjectMapping(project); - try { - ConnectionFactory connectionFactory = JMSUtils.createConnectionFactory(jmsInfo); - if (connectionFactory == null) { - Application.getInstance().getGUILog().log("[WARNING] " + project.getName() + " - " + ERROR_STRING + " Reason: Failed to create JMS connection factory."); - return false; - } - String username = TicketUtils.getUsername(project); - if (username == null) { - Application.getInstance().getGUILog().log("[WARNING] " + project.getName() + " - " + ERROR_STRING + " Reason: Cannot get MMS username."); - return false; - } - String subscriberId = projectId + "-" + workspaceId + "-" + username; // weblogic can't have '/' in id - - JMSMessageListener jmsMessageListener = jmsSyncProjectMapping.getJmsMessageListener(); - - Connection connection = connectionFactory.createConnection(); - //((WLConnection) connection).setReconnectPolicy(JMSConstants.RECONNECT_POLICY_ALL); - connection.setExceptionListener(jmsMessageListener); - connection.setClientID(subscriberId); - Session session = connection.createSession(false, Session.CLIENT_ACKNOWLEDGE); - - Topic topic = null; - try { - if (JMSUtils.getInitialContext() != null) { - topic = (Topic) JMSUtils.getInitialContext().lookup(JMSUtils.JMS_TOPIC); - } - } catch (NameNotFoundException ignored) { - // do nothing; just means topic hasn't been created yet - } - if (topic == null) { - topic = session.createTopic(JMSUtils.JMS_TOPIC); - } - String messageSelector = JMSUtils.constructSelectorString(projectId, workspaceId); - MessageConsumer consumer = session.createDurableSubscriber(topic, subscriberId, messageSelector, true); - consumer.setMessageListener(jmsMessageListener); - - MessageProducer producer = session.createProducer(topic); - - connection.start(); - - jmsSyncProjectMapping.setConnection(connection); - jmsSyncProjectMapping.setSession(session); - jmsSyncProjectMapping.setMessageConsumer(consumer); - jmsSyncProjectMapping.setMessageProducer(producer); - - // get everything that's already in the queue without blocking startup - /*new Thread() { - @Override - public void run() { - List textMessages = jmsSyncProjectMapping.getAllTextMessages(false); - if (textMessages != null) { - for (TextMessage textMessage : textMessages) { - jmsSyncProjectMapping.getJmsMessageListener().onMessage(textMessage); - } - } - } - }.start();*/ - - Application.getInstance().getGUILog().log("[INFO] " + project.getName() + " - MMS sync initiated."); - return true; - } catch (Exception e) { - e.printStackTrace(); - jmsSyncProjectMapping.getJmsMessageListener().setDisabled(true); - Application.getInstance().getGUILog().log("[WARNING] " + project.getName() + " - " + ERROR_STRING + " Reason: " + e.getMessage()); - return false; - } - } - - public static JMSSyncProjectMapping getProjectMapping(Project project) { - JMSSyncProjectMapping jmsSyncProjectMapping = projectMappings.get(project); - if (jmsSyncProjectMapping == null) { - projectMappings.put(project, jmsSyncProjectMapping = new JMSSyncProjectMapping(project)); - } - return jmsSyncProjectMapping; - } - - public static class JMSSyncProjectMapping { - private Connection connection; - private Session session; - private MessageConsumer messageConsumer; - private JMSMessageListener jmsMessageListener; - private MessageProducer messageProducer; - - public JMSSyncProjectMapping(Project project) { - jmsMessageListener = new JMSMessageListener(project); - } - - public Connection getConnection() { - return connection; - } - - public void setConnection(Connection connection) { - this.connection = connection; - } - - public Session getSession() { - return session; - } - - public void setSession(Session session) { - this.session = session; - } - - public MessageConsumer getMessageConsumer() { - return messageConsumer; - } - - public void setMessageConsumer(MessageConsumer messageConsumer) { - this.messageConsumer = messageConsumer; - } - - public JMSMessageListener getJmsMessageListener() { - return jmsMessageListener; - } - - public MessageProducer getMessageProducer() { - return messageProducer; - } - - public void setMessageProducer(MessageProducer messageProducer) { - this.messageProducer = messageProducer; - } - - @Deprecated - public List getAllTextMessages(boolean shouldAcknowledge) { - boolean print = MDKOptionsGroup.getMDKOptions().isLogJson(); - List textMessages = new ArrayList<>(); - Message message; - try { - while (getMessageConsumer() != null && (message = getMessageConsumer().receive(10000)) != null) { - if (!(message instanceof TextMessage)) { - continue; - } - TextMessage textMessage = (TextMessage) message; - if (print) { - System.out.println("From MMS: " + textMessage.getText()); - } - textMessages.add(textMessage); - - if (shouldAcknowledge) { - try { - message.acknowledge(); - } catch (JMSException e) { - e.printStackTrace(); - } - } - } - } catch (JMSException e) { - e.printStackTrace(); - return null; - } - return textMessages; - } - } -} diff --git a/src/main/java/gov/nasa/jpl/mbee/mdk/mms/sync/local/LocalSyncProjectEventListenerAdapter.java b/src/main/java/gov/nasa/jpl/mbee/mdk/mms/sync/local/LocalDeltaProjectEventListenerAdapter.java similarity index 73% rename from src/main/java/gov/nasa/jpl/mbee/mdk/mms/sync/local/LocalSyncProjectEventListenerAdapter.java rename to src/main/java/gov/nasa/jpl/mbee/mdk/mms/sync/local/LocalDeltaProjectEventListenerAdapter.java index be55dec57..9a34ce7f1 100644 --- a/src/main/java/gov/nasa/jpl/mbee/mdk/mms/sync/local/LocalSyncProjectEventListenerAdapter.java +++ b/src/main/java/gov/nasa/jpl/mbee/mdk/mms/sync/local/LocalDeltaProjectEventListenerAdapter.java @@ -10,7 +10,7 @@ /** * Created by igomes on 6/28/16. */ -public class LocalSyncProjectEventListenerAdapter extends ProjectEventListenerAdapter { +public class LocalDeltaProjectEventListenerAdapter extends ProjectEventListenerAdapter { private static final Map projectMappings = new ConcurrentHashMap<>(); @Override @@ -24,7 +24,7 @@ public void projectCreated(Project project) { public void projectOpened(Project project) { closeLocalCommitListener(project); if (project.isRemote()) { - ((MDTransactionManager) project.getRepository().getTransactionManager()).addTransactionCommitListenerIncludingUndoAndRedo(getProjectMapping(project).getLocalSyncTransactionCommitListener()); + ((MDTransactionManager) project.getRepository().getTransactionManager()).addTransactionCommitListenerIncludingUndoAndRedo(getProjectMapping(project).getLocalDeltaTransactionCommitListener()); } } @@ -43,18 +43,18 @@ public void projectReplaced(Project oldProject, Project newProject) { @Override public void projectSaved(Project project, boolean savedInServer) { LocalSyncProjectMapping localSyncProjectMapping = getProjectMapping(project); - LocalSyncTransactionCommitListener listener = localSyncProjectMapping.getLocalSyncTransactionCommitListener(); + LocalDeltaTransactionCommitListener listener = localSyncProjectMapping.getLocalDeltaTransactionCommitListener(); if (listener == null) { projectOpened(project); - listener = LocalSyncProjectEventListenerAdapter.getProjectMapping(project).getLocalSyncTransactionCommitListener(); + listener = LocalDeltaProjectEventListenerAdapter.getProjectMapping(project).getLocalDeltaTransactionCommitListener(); } listener.getInMemoryLocalChangelog().clear(); } private static void closeLocalCommitListener(Project project) { LocalSyncProjectMapping localSyncProjectMapping = projectMappings.get(project); - if (localSyncProjectMapping != null && localSyncProjectMapping.getLocalSyncTransactionCommitListener() != null) { - project.getRepository().getTransactionManager().removeTransactionCommitListener(localSyncProjectMapping.getLocalSyncTransactionCommitListener()); + if (localSyncProjectMapping != null && localSyncProjectMapping.getLocalDeltaTransactionCommitListener() != null) { + project.getRepository().getTransactionManager().removeTransactionCommitListener(localSyncProjectMapping.getLocalDeltaTransactionCommitListener()); } } @@ -63,21 +63,21 @@ public static LocalSyncProjectMapping getProjectMapping(Project project) { if (localSyncProjectMapping == null) { projectMappings.put(project, localSyncProjectMapping = new LocalSyncProjectMapping(project)); if (project.isRemote()) { - ((MDTransactionManager) project.getRepository().getTransactionManager()).addTransactionCommitListenerIncludingUndoAndRedo(localSyncProjectMapping.getLocalSyncTransactionCommitListener()); + ((MDTransactionManager) project.getRepository().getTransactionManager()).addTransactionCommitListenerIncludingUndoAndRedo(localSyncProjectMapping.getLocalDeltaTransactionCommitListener()); } } return localSyncProjectMapping; } public static class LocalSyncProjectMapping { - private LocalSyncTransactionCommitListener localSyncTransactionCommitListener; + private LocalDeltaTransactionCommitListener localDeltaTransactionCommitListener; public LocalSyncProjectMapping(Project project) { - localSyncTransactionCommitListener = new LocalSyncTransactionCommitListener(project); + localDeltaTransactionCommitListener = new LocalDeltaTransactionCommitListener(project); } - public LocalSyncTransactionCommitListener getLocalSyncTransactionCommitListener() { - return localSyncTransactionCommitListener; + public LocalDeltaTransactionCommitListener getLocalDeltaTransactionCommitListener() { + return localDeltaTransactionCommitListener; } } diff --git a/src/main/java/gov/nasa/jpl/mbee/mdk/mms/sync/local/LocalSyncTransactionCommitListener.java b/src/main/java/gov/nasa/jpl/mbee/mdk/mms/sync/local/LocalDeltaTransactionCommitListener.java similarity index 98% rename from src/main/java/gov/nasa/jpl/mbee/mdk/mms/sync/local/LocalSyncTransactionCommitListener.java rename to src/main/java/gov/nasa/jpl/mbee/mdk/mms/sync/local/LocalDeltaTransactionCommitListener.java index bcd201ac0..30124372d 100644 --- a/src/main/java/gov/nasa/jpl/mbee/mdk/mms/sync/local/LocalSyncTransactionCommitListener.java +++ b/src/main/java/gov/nasa/jpl/mbee/mdk/mms/sync/local/LocalDeltaTransactionCommitListener.java @@ -30,7 +30,7 @@ * * @author igomes */ -public class LocalSyncTransactionCommitListener implements TransactionCommitListener { +public class LocalDeltaTransactionCommitListener implements TransactionCommitListener { private static final ExecutorService EXECUTOR_SERVICE = Executors.newSingleThreadExecutor(); private static final List IGNORED_PROPERTY_CHANGE_EVENT_NAMES = Arrays.asList( PropertyNames.PACKAGED_ELEMENT, @@ -52,7 +52,7 @@ public class LocalSyncTransactionCommitListener implements TransactionCommitList } } - public LocalSyncTransactionCommitListener(Project project) { + public LocalDeltaTransactionCommitListener(Project project) { this.project = project; } diff --git a/src/main/java/gov/nasa/jpl/mbee/mdk/mms/sync/mms/MMSDeltaProjectEventListenerAdapter.java b/src/main/java/gov/nasa/jpl/mbee/mdk/mms/sync/mms/MMSDeltaProjectEventListenerAdapter.java new file mode 100644 index 000000000..51e3837f9 --- /dev/null +++ b/src/main/java/gov/nasa/jpl/mbee/mdk/mms/sync/mms/MMSDeltaProjectEventListenerAdapter.java @@ -0,0 +1,301 @@ +package gov.nasa.jpl.mbee.mdk.mms.sync.mms; + +import com.fasterxml.jackson.core.JsonParser; +import com.fasterxml.jackson.core.JsonToken; +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.core.project.ProjectEventListenerAdapter; +import com.nomagic.magicdraw.esi.EsiUtils; +import com.nomagic.magicdraw.teamwork2.locks.ILockProjectService; +import com.nomagic.uml2.ext.jmi.helpers.StereotypesHelper; +import gov.nasa.jpl.mbee.mdk.api.incubating.MDKConstants; +import gov.nasa.jpl.mbee.mdk.api.incubating.convert.Converters; +import gov.nasa.jpl.mbee.mdk.emf.EMFImporter; +import gov.nasa.jpl.mbee.mdk.http.ServerException; +import gov.nasa.jpl.mbee.mdk.json.ImportException; +import gov.nasa.jpl.mbee.mdk.json.JacksonUtils; +import gov.nasa.jpl.mbee.mdk.mms.MMSUtils; +import gov.nasa.jpl.mbee.mdk.mms.actions.MMSLoginAction; +import gov.nasa.jpl.mbee.mdk.mms.sync.delta.SyncElement; +import gov.nasa.jpl.mbee.mdk.mms.sync.delta.SyncElements; +import gov.nasa.jpl.mbee.mdk.mms.sync.status.SyncStatusConfigurator; +import gov.nasa.jpl.mbee.mdk.util.Changelog; +import gov.nasa.jpl.mbee.mdk.util.MDUtils; +import gov.nasa.jpl.mbee.mdk.util.TaskRunner; +import gov.nasa.jpl.mbee.mdk.util.TicketUtils; +import org.apache.http.client.utils.URIBuilder; + +import java.io.File; +import java.io.IOException; +import java.net.URISyntaxException; +import java.text.NumberFormat; +import java.util.*; +import java.util.concurrent.ConcurrentHashMap; +import java.util.concurrent.ScheduledFuture; +import java.util.concurrent.TimeUnit; +import java.util.stream.Collectors; + +public class MMSDeltaProjectEventListenerAdapter extends ProjectEventListenerAdapter { + private static final Map projectMappings = new ConcurrentHashMap<>(); + + @Override + public void projectOpened(Project project) { + if (!project.isRemote()) { + return; + } + projectClosed(project); + getProjectMapping(project).setScheduledFuture(TaskRunner.scheduleWithProgressStatus(progressStatus -> { + try { + getProjectMapping(project).update(); + } catch (URISyntaxException | IOException | ServerException e) { + e.printStackTrace(); + } + }, "MMS Fetch", false, TaskRunner.ThreadExecutionStrategy.POOLED, false, (r, ses) -> ses.scheduleAtFixedRate(r, 0, 1, TimeUnit.MINUTES))); + if (StereotypesHelper.hasStereotype(project.getPrimaryModel(), "ModelManagementSystem")) { + MMSLoginAction.loginAction(project); + } + } + + @Override + public void projectClosed(Project project) { + getProjectMapping(project).getInMemoryCommits().clear(); + getProjectMapping(project).getInMemoryChangelog().clear(); + SyncStatusConfigurator.getSyncStatusAction().update(); + + ScheduledFuture scheduledFuture = getProjectMapping(project).getScheduledFuture(); + if (scheduledFuture != null) { + scheduledFuture.cancel(true); + } + projectMappings.remove(project); + } + + @Override + public void projectReplaced(Project project, Project project1) { + projectClosed(project); + projectOpened(project1); + } + + @Override + public void projectCreated(Project project) { + projectOpened(project); + } + + public static MMSDeltaProjectMapping getProjectMapping(Project project) { + MMSDeltaProjectMapping projectMapping = projectMappings.get(project); + if (projectMapping == null) { + projectMappings.put(project, projectMapping = new MMSDeltaProjectMapping(project)); + } + return projectMapping; + } + + @Override + public void projectSaved(Project project, boolean b) { + // Need to clear out changes after TWC update so we don't repeat. + // Example: MD1 and MD2 have a project open. MMS has unsynced changes. MD1 syncs and commits. MD2 still has these changes in memory and re-syncs the elements. + // Unfortunately there is no projectUpdated hook, but projects are saved + // MDUMLCS-26866 Add projectUpdated event to ProjectEventListener + projectClosed(project); + } + + public static class MMSDeltaProjectMapping { + private static final Map CHANGE_MAPPING = new LinkedHashMap<>(3); + + static { + CHANGE_MAPPING.put("added", Changelog.ChangeType.CREATED); + CHANGE_MAPPING.put("deleted", Changelog.ChangeType.DELETED); + CHANGE_MAPPING.put("updated", Changelog.ChangeType.UPDATED); + } + + private final Project project; + private ScheduledFuture scheduledFuture; + + private Set inMemoryCommits = new LinkedHashSet<>(); + private Changelog inMemoryChangelog = new Changelog<>(); + private String lastSyncedCommitId; + + public MMSDeltaProjectMapping(Project project) { + this.project = project; + } + + public ScheduledFuture getScheduledFuture() { + return scheduledFuture; + } + + public void setScheduledFuture(ScheduledFuture scheduledFuture) { + this.scheduledFuture = scheduledFuture; + } + + public Set getInMemoryCommits() { + return inMemoryCommits; + } + + public Changelog getInMemoryChangelog() { + return inMemoryChangelog; + } + + public synchronized String getLastSyncedCommitId() { + return lastSyncedCommitId; + } + + public String getLastSyncedMmsCommit() throws RuntimeException { + String branchId = MDUtils.getBranchId(project); + return SyncElements.getAllByType(project, SyncElement.Type.MMS_COMMIT).stream().map(SyncElements::getValue).map(s -> { + try { + return JacksonUtils.getObjectMapper().readTree(s); + } catch (IOException e) { + e.printStackTrace(); + } + return null; + }).filter(json -> { + if (json == null || !json.isObject()) { + return false; + } + JsonNode branchIdNode = json.get("branchId"); + if (branchIdNode == null || !branchIdNode.isTextual()) { + return false; + } + return branchId.equals(branchIdNode.asText()); + }).map(json -> json.get("commitId")).filter(commitIdNode -> commitIdNode != null && commitIdNode.isTextual()).map(JsonNode::asText).findAny().orElse(null); + } + + public synchronized boolean update() throws URISyntaxException, IOException, ServerException, IllegalStateException { + if (!project.isRemote()) { + return false; + } + if (!TicketUtils.isTicketSet(project)) { + inMemoryCommits.clear(); + inMemoryChangelog.clear(); + SyncStatusConfigurator.getSyncStatusAction().update(); + return false; + } + + lastSyncedCommitId = getLastSyncedMmsCommit(); + Deque commitIdDeque = new ArrayDeque<>(); + int exponent = 0; + + doWhile: + do { + commitIdDeque.clear(); + int limit = (int) Math.pow(10, exponent++); + + URIBuilder commitsUriBuilder = MMSUtils.getServiceProjectsRefsUri(project); + commitsUriBuilder.setPath(commitsUriBuilder.getPath() + "/" + MDUtils.getBranchId(project) + "/commits"); + commitsUriBuilder.setParameter("limit", Integer.toString(limit)); + File responseFile = MMSUtils.sendMMSRequest(project, MMSUtils.buildRequest(MMSUtils.HttpRequestType.GET, commitsUriBuilder)); + + JsonToken current; + try (JsonParser jsonParser = JacksonUtils.getJsonFactory().createParser(responseFile)) { + current = jsonParser.nextToken(); + if (current != JsonToken.START_OBJECT) { + throw new IllegalStateException(); + } + current = jsonParser.nextToken(); + if (current != JsonToken.FIELD_NAME || !jsonParser.getCurrentName().equals("commits")) { + throw new IllegalStateException(); + } + current = jsonParser.nextToken(); + if (current != JsonToken.START_ARRAY) { + throw new IllegalStateException(); + } + JsonNode value; + int size = 0; + while (jsonParser.nextToken() == JsonToken.START_OBJECT) { + String id; + ObjectNode objectNode = JacksonUtils.parseJsonObject(jsonParser); + if ((value = objectNode.get(MDKConstants.ID_KEY)) != null && value.isTextual()) { + id = value.asText(); + if (lastSyncedCommitId == null) { + lastSyncedCommitId = id; + } + if (lastSyncedCommitId.equals(id)) { + break doWhile; + } + if (inMemoryCommits.contains(id)) { + break doWhile; + } + commitIdDeque.addFirst(id); + } + size++; + } + if (size < limit) { + break; + } + } + } while (true); + + if (commitIdDeque.isEmpty()) { + return true; + } + + ILockProjectService lockService; + Set lockedElementIds = project.isRemote() && (lockService = EsiUtils.getLockService(project)) != null ? lockService.getLockedByMe().stream().map(Converters.getElementToIdConverter()).collect(Collectors.toSet()) : Collections.emptySet(); + + while (!commitIdDeque.isEmpty()) { + String commitId = commitIdDeque.removeFirst(); + URIBuilder uriBuilder = MMSUtils.getServiceProjectsUri(project); + uriBuilder.setPath(uriBuilder.getPath() + "/" + Converters.getIProjectToIdConverter().apply(project.getPrimaryProject()) + "/commits/" + commitId); + File responseFile = MMSUtils.sendMMSRequest(project, MMSUtils.buildRequest(MMSUtils.HttpRequestType.GET, uriBuilder)); + + try (JsonParser jsonParser = JacksonUtils.getJsonFactory().createParser(responseFile)) { + ObjectNode objectNode = JacksonUtils.parseJsonObject(jsonParser); + if (objectNode == null) { + throw new IllegalStateException(); + } + JsonNode jsonNode; + if ((jsonNode = objectNode.get("commits")) == null || !jsonNode.isArray() || jsonNode.size() == 0) { + throw new IllegalStateException(); + } + jsonNode = jsonNode.get(0); + JsonNode sourceJsonNode = jsonNode.get("source"); + boolean isSyncingCommit = sourceJsonNode != null && sourceJsonNode.isTextual() && "magicdraw".equalsIgnoreCase(sourceJsonNode.asText()); + int size = 0; + for (Map.Entry entry : CHANGE_MAPPING.entrySet()) { + JsonNode changesJsonArray = jsonNode.get(entry.getKey()); + if (changesJsonArray == null || !changesJsonArray.isArray()) { + throw new IllegalStateException(); + } + for (JsonNode changeJsonObject : changesJsonArray) { + if (!changeJsonObject.isObject()) { + throw new IllegalStateException(); + } + JsonNode idJsonNode = changeJsonObject.get(MDKConstants.ID_KEY); + if (!idJsonNode.isTextual() || idJsonNode.asText().isEmpty()) { + continue; + } + String elementId = idJsonNode.asText(); + try { + ObjectNode elementJsonNode = JacksonUtils.getObjectMapper().createObjectNode(); + elementJsonNode.put(MDKConstants.ID_KEY, elementId); + if (EMFImporter.PreProcessor.SYSML_ID_VALIDATION.getFunction().apply(elementJsonNode, project, false, project.getPrimaryModel()) == null) { + continue; + } + } catch (ImportException ignored) { + continue; + } + if (isSyncingCommit) { + if (lockedElementIds.contains(elementId)) { + continue; + } + for (Changelog.ChangeType changeType : Changelog.ChangeType.values()) { + inMemoryChangelog.get(changeType).remove(elementId); + } + } + else { + inMemoryChangelog.addChange(elementId, null, entry.getValue()); + } + size++; + } + } + if (MDUtils.isDeveloperMode()) { + Application.getInstance().getGUILog().log("[INFO] " + project.getName() + " - " + (isSyncingCommit ? "Removed" : "Added") + " " + NumberFormat.getInstance().format(size) + " MMS element change" + (size != 1 ? "s" : "") + " for commit " + commitId + "."); + } + } + inMemoryCommits.add(commitId); + } + SyncStatusConfigurator.getSyncStatusAction().update(); + return true; + } + } +} diff --git a/src/main/java/gov/nasa/jpl/mbee/mdk/mms/sync/status/actions/SyncStatusAction.java b/src/main/java/gov/nasa/jpl/mbee/mdk/mms/sync/status/actions/SyncStatusAction.java index 4971695ef..57fb2351a 100644 --- a/src/main/java/gov/nasa/jpl/mbee/mdk/mms/sync/status/actions/SyncStatusAction.java +++ b/src/main/java/gov/nasa/jpl/mbee/mdk/mms/sync/status/actions/SyncStatusAction.java @@ -2,13 +2,14 @@ import com.nomagic.magicdraw.core.Application; import com.nomagic.magicdraw.core.Project; +import com.nomagic.ui.ProgressStatusRunner; import gov.nasa.jpl.mbee.mdk.MDKPlugin; +import gov.nasa.jpl.mbee.mdk.http.ServerException; import gov.nasa.jpl.mbee.mdk.mms.sync.delta.SyncElement; import gov.nasa.jpl.mbee.mdk.mms.sync.delta.SyncElements; -import gov.nasa.jpl.mbee.mdk.mms.sync.jms.JMSMessageListener; -import gov.nasa.jpl.mbee.mdk.mms.sync.jms.JMSSyncProjectEventListenerAdapter; -import gov.nasa.jpl.mbee.mdk.mms.sync.local.LocalSyncProjectEventListenerAdapter; -import gov.nasa.jpl.mbee.mdk.mms.sync.local.LocalSyncTransactionCommitListener; +import gov.nasa.jpl.mbee.mdk.mms.sync.local.LocalDeltaProjectEventListenerAdapter; +import gov.nasa.jpl.mbee.mdk.mms.sync.local.LocalDeltaTransactionCommitListener; +import gov.nasa.jpl.mbee.mdk.mms.sync.mms.MMSDeltaProjectEventListenerAdapter; import gov.nasa.jpl.mbee.mdk.mms.sync.status.ui.SyncStatusFrame; import gov.nasa.jpl.mbee.mdk.systems_reasoner.actions.SRAction; import gov.nasa.jpl.mbee.mdk.util.Changelog; @@ -16,6 +17,8 @@ import javax.annotation.CheckForNull; import javax.swing.*; import java.awt.event.ActionEvent; +import java.io.IOException; +import java.net.URISyntaxException; import java.text.NumberFormat; /** @@ -52,31 +55,31 @@ public void update() { totalPersistedLocalChangedCount = new int[]{0}, totalLocalChangedCount = new int[]{0}, - inMemoryJmsCreatedCount = new int[]{0}, - inMemoryJmsUpdatedCount = new int[]{0}, - inMemoryJmsDeletedCount = new int[]{0}, + inMemoryMmsCreatedCount = new int[]{0}, + inMemoryMmsUpdatedCount = new int[]{0}, + inMemoryMmsDeletedCount = new int[]{0}, - persistedJmsCreatedCount = new int[]{0}, - persistedJmsUpdatedCount = new int[]{0}, - persistedJmsDeletedCount = new int[]{0}, + persistedMmsCreatedCount = new int[]{0}, + persistedMmsUpdatedCount = new int[]{0}, + persistedMmsDeletedCount = new int[]{0}, - totalJmsCreatedCount = new int[]{0}, - totalJmsUpdatedCount = new int[]{0}, - totalJmsDeletedCount = new int[]{0}, + totalMmsCreatedCount = new int[]{0}, + totalMmsUpdatedCount = new int[]{0}, + totalMmsDeletedCount = new int[]{0}, - totalInMemoryJmsChangedCount = new int[]{0}, - totalPersistedJmsChangedCount = new int[]{0}, - totalJmsChangedCount = new int[]{0}, + totalInMemoryMmsChangedCount = new int[]{0}, + totalPersistedMmsChangedCount = new int[]{0}, + totalMmsChangedCount = new int[]{0}, totalChangedCount = new int[]{0}; final NumberFormat numberFormat = NumberFormat.getIntegerInstance(); Project project = Application.getInstance().getProject(); if (project != null && !project.isClosing() && !project.isProjectClosed()) { - LocalSyncTransactionCommitListener localSyncTransactionCommitListener = LocalSyncProjectEventListenerAdapter.getProjectMapping(project).getLocalSyncTransactionCommitListener(); - if (localSyncTransactionCommitListener != null) { - inMemoryLocalCreatedCount[0] = localSyncTransactionCommitListener.getInMemoryLocalChangelog().get(Changelog.ChangeType.CREATED).size(); - inMemoryLocalUpdatedCount[0] = localSyncTransactionCommitListener.getInMemoryLocalChangelog().get(Changelog.ChangeType.UPDATED).size(); - inMemoryLocalDeletedCount[0] = localSyncTransactionCommitListener.getInMemoryLocalChangelog().get(Changelog.ChangeType.DELETED).size(); + LocalDeltaTransactionCommitListener localDeltaTransactionCommitListener = LocalDeltaProjectEventListenerAdapter.getProjectMapping(project).getLocalDeltaTransactionCommitListener(); + if (localDeltaTransactionCommitListener != null) { + inMemoryLocalCreatedCount[0] = localDeltaTransactionCommitListener.getInMemoryLocalChangelog().get(Changelog.ChangeType.CREATED).size(); + inMemoryLocalUpdatedCount[0] = localDeltaTransactionCommitListener.getInMemoryLocalChangelog().get(Changelog.ChangeType.UPDATED).size(); + inMemoryLocalDeletedCount[0] = localDeltaTransactionCommitListener.getInMemoryLocalChangelog().get(Changelog.ChangeType.DELETED).size(); } totalInMemoryLocalChangedCount[0] = inMemoryLocalCreatedCount[0] + inMemoryLocalUpdatedCount[0] + inMemoryLocalDeletedCount[0]; @@ -90,26 +93,23 @@ public void update() { totalPersistedLocalChangedCount[0] = persistedLocalCreatedCount[0] + persistedLocalUpdatedCount[0] + persistedLocalDeletedCount[0]; totalLocalChangedCount[0] = totalInMemoryLocalChangedCount[0] + totalPersistedLocalChangedCount[0]; - JMSMessageListener jmsMessageListener = JMSSyncProjectEventListenerAdapter.getProjectMapping(project).getJmsMessageListener(); - if (jmsMessageListener != null) { - inMemoryJmsCreatedCount[0] = jmsMessageListener.getInMemoryJMSChangelog().get(Changelog.ChangeType.CREATED).size(); - inMemoryJmsUpdatedCount[0] = jmsMessageListener.getInMemoryJMSChangelog().get(Changelog.ChangeType.UPDATED).size(); - inMemoryJmsDeletedCount[0] = jmsMessageListener.getInMemoryJMSChangelog().get(Changelog.ChangeType.DELETED).size(); - } - totalInMemoryJmsChangedCount[0] = inMemoryJmsCreatedCount[0] + inMemoryJmsUpdatedCount[0] + inMemoryJmsDeletedCount[0]; + inMemoryMmsCreatedCount[0] = MMSDeltaProjectEventListenerAdapter.getProjectMapping(project).getInMemoryChangelog().get(Changelog.ChangeType.CREATED).size(); + inMemoryMmsUpdatedCount[0] = MMSDeltaProjectEventListenerAdapter.getProjectMapping(project).getInMemoryChangelog().get(Changelog.ChangeType.UPDATED).size(); + inMemoryMmsDeletedCount[0] = MMSDeltaProjectEventListenerAdapter.getProjectMapping(project).getInMemoryChangelog().get(Changelog.ChangeType.DELETED).size(); + totalInMemoryMmsChangedCount[0] = inMemoryMmsCreatedCount[0] + inMemoryMmsUpdatedCount[0] + inMemoryMmsDeletedCount[0]; for (SyncElement mmsSyncElement : SyncElements.getAllByType(project, SyncElement.Type.MMS)) { SyncElements.buildChangelog(mmsPersistedChangelog, mmsSyncElement); } - persistedJmsCreatedCount[0] += mmsPersistedChangelog.get(Changelog.ChangeType.CREATED).size(); - persistedJmsUpdatedCount[0] += mmsPersistedChangelog.get(Changelog.ChangeType.UPDATED).size(); - persistedJmsDeletedCount[0] += mmsPersistedChangelog.get(Changelog.ChangeType.DELETED).size(); + persistedMmsCreatedCount[0] += mmsPersistedChangelog.get(Changelog.ChangeType.CREATED).size(); + persistedMmsUpdatedCount[0] += mmsPersistedChangelog.get(Changelog.ChangeType.UPDATED).size(); + persistedMmsDeletedCount[0] += mmsPersistedChangelog.get(Changelog.ChangeType.DELETED).size(); - totalPersistedJmsChangedCount[0] = persistedJmsCreatedCount[0] + persistedJmsUpdatedCount[0] + persistedJmsDeletedCount[0]; - totalJmsChangedCount[0] = totalInMemoryJmsChangedCount[0] + totalPersistedJmsChangedCount[0]; + totalPersistedMmsChangedCount[0] = persistedMmsCreatedCount[0] + persistedMmsUpdatedCount[0] + persistedMmsDeletedCount[0]; + totalMmsChangedCount[0] = totalInMemoryMmsChangedCount[0] + totalPersistedMmsChangedCount[0]; } - totalChangedCount[0] = totalLocalChangedCount[0] + totalJmsChangedCount[0]; + totalChangedCount[0] = totalLocalChangedCount[0] + totalMmsChangedCount[0]; SwingUtilities.invokeLater(() -> { setName(NAME + ": " + numberFormat.format(totalChangedCount[0])); MDKPlugin.updateMainToolbarCategory(); @@ -120,9 +120,9 @@ public void update() { totalLocalUpdatedCount[0] = inMemoryLocalUpdatedCount[0] + persistedLocalUpdatedCount[0]; totalLocalDeletedCount[0] = inMemoryLocalDeletedCount[0] + persistedLocalDeletedCount[0]; - totalJmsCreatedCount[0] = inMemoryJmsCreatedCount[0] + persistedJmsCreatedCount[0]; - totalJmsUpdatedCount[0] = inMemoryJmsUpdatedCount[0] + persistedJmsUpdatedCount[0]; - totalJmsDeletedCount[0] = inMemoryJmsDeletedCount[0] + persistedJmsDeletedCount[0]; + totalMmsCreatedCount[0] = inMemoryMmsCreatedCount[0] + persistedMmsCreatedCount[0]; + totalMmsUpdatedCount[0] = inMemoryMmsUpdatedCount[0] + persistedMmsUpdatedCount[0]; + totalMmsDeletedCount[0] = inMemoryMmsDeletedCount[0] + persistedMmsDeletedCount[0]; SwingUtilities.invokeLater(() -> { getSyncStatusFrame().getInMemoryLocalCreatedLabel().setText(numberFormat.format(inMemoryLocalCreatedCount[0])); @@ -141,21 +141,21 @@ public void update() { getSyncStatusFrame().getTotalPersistedLocalChangedLabel().setText(numberFormat.format(totalPersistedLocalChangedCount[0])); getSyncStatusFrame().getTotalLocalChangedLabel().setText(numberFormat.format(totalLocalChangedCount[0])); - getSyncStatusFrame().getInMemoryJmsCreatedLabel().setText(numberFormat.format(inMemoryJmsCreatedCount[0])); - getSyncStatusFrame().getInMemoryJmsUpdatedLabel().setText(numberFormat.format(inMemoryJmsUpdatedCount[0])); - getSyncStatusFrame().getInMemoryJmsDeletedLabel().setText(numberFormat.format(inMemoryJmsDeletedCount[0])); + getSyncStatusFrame().getInMemoryMmsCreatedLabel().setText(numberFormat.format(inMemoryMmsCreatedCount[0])); + getSyncStatusFrame().getInMemoryMmsUpdatedLabel().setText(numberFormat.format(inMemoryMmsUpdatedCount[0])); + getSyncStatusFrame().getInMemoryMmsDeletedLabel().setText(numberFormat.format(inMemoryMmsDeletedCount[0])); - getSyncStatusFrame().getPersistedJmsCreatedLabel().setText(numberFormat.format(persistedJmsCreatedCount[0])); - getSyncStatusFrame().getPersistedJmsUpdatedLabel().setText(numberFormat.format(persistedJmsUpdatedCount[0])); - getSyncStatusFrame().getPersistedJmsDeletedLabel().setText(numberFormat.format(persistedJmsDeletedCount[0])); + getSyncStatusFrame().getPersistedMmsCreatedLabel().setText(numberFormat.format(persistedMmsCreatedCount[0])); + getSyncStatusFrame().getPersistedMmsUpdatedLabel().setText(numberFormat.format(persistedMmsUpdatedCount[0])); + getSyncStatusFrame().getPersistedMmsDeletedLabel().setText(numberFormat.format(persistedMmsDeletedCount[0])); - getSyncStatusFrame().getTotalJmsCreatedLabel().setText(numberFormat.format(totalJmsCreatedCount[0])); - getSyncStatusFrame().getTotalJmsUpdatedLabel().setText(numberFormat.format(totalJmsUpdatedCount[0])); - getSyncStatusFrame().getTotalJmsDeletedLabel().setText(numberFormat.format(totalJmsDeletedCount[0])); + getSyncStatusFrame().getTotalMmsCreatedLabel().setText(numberFormat.format(totalMmsCreatedCount[0])); + getSyncStatusFrame().getTotalMmsUpdatedLabel().setText(numberFormat.format(totalMmsUpdatedCount[0])); + getSyncStatusFrame().getTotalMmsDeletedLabel().setText(numberFormat.format(totalMmsDeletedCount[0])); - getSyncStatusFrame().getTotalInMemoryJmsChangedLabel().setText(numberFormat.format(totalInMemoryJmsChangedCount[0])); - getSyncStatusFrame().getTotalPersistedJmsChangedLabel().setText(numberFormat.format(totalPersistedJmsChangedCount[0])); - getSyncStatusFrame().getTotalJmsChangedLabel().setText(numberFormat.format(totalJmsChangedCount[0])); + getSyncStatusFrame().getTotalInMemoryMmsChangedLabel().setText(numberFormat.format(totalInMemoryMmsChangedCount[0])); + getSyncStatusFrame().getTotalPersistedMmsChangedLabel().setText(numberFormat.format(totalPersistedMmsChangedCount[0])); + getSyncStatusFrame().getTotalMmsChangedLabel().setText(numberFormat.format(totalMmsChangedCount[0])); }); } } @@ -175,7 +175,20 @@ public void actionPerformed(@CheckForNull ActionEvent actionEvent) { else { getSyncStatusFrame().toFront(); } - update(); + Project project = Application.getInstance().getProject(); + if (project != null) { + ProgressStatusRunner.runWithProgressStatus(progressStatus -> { + progressStatus.setIndeterminate(true); + try { + progressStatus.setDescription("Fetching MMS changes"); + MMSDeltaProjectEventListenerAdapter.getProjectMapping(project).update(); + progressStatus.setDescription("Updating table"); + update(); + } catch (URISyntaxException | IOException | ServerException e) { + e.printStackTrace(); + } + }, "Sync Status Update", false, 0); + } } @Override diff --git a/src/main/java/gov/nasa/jpl/mbee/mdk/mms/sync/status/ui/SyncStatusFrame.form b/src/main/java/gov/nasa/jpl/mbee/mdk/mms/sync/status/ui/SyncStatusFrame.form index 4c2ddaf55..ce6adc892 100644 --- a/src/main/java/gov/nasa/jpl/mbee/mdk/mms/sync/status/ui/SyncStatusFrame.form +++ b/src/main/java/gov/nasa/jpl/mbee/mdk/mms/sync/status/ui/SyncStatusFrame.form @@ -60,7 +60,7 @@ - + @@ -69,7 +69,7 @@ - + @@ -78,7 +78,7 @@ - + @@ -114,7 +114,7 @@ - + @@ -123,7 +123,7 @@ - + @@ -132,7 +132,7 @@ - + @@ -255,7 +255,7 @@ - + @@ -265,7 +265,7 @@ - + @@ -275,7 +275,7 @@ - + @@ -381,7 +381,7 @@ - + @@ -391,7 +391,7 @@ - + @@ -401,7 +401,7 @@ - + diff --git a/src/main/java/gov/nasa/jpl/mbee/mdk/mms/sync/status/ui/SyncStatusFrame.java b/src/main/java/gov/nasa/jpl/mbee/mdk/mms/sync/status/ui/SyncStatusFrame.java index d4e651516..9ce628c5f 100644 --- a/src/main/java/gov/nasa/jpl/mbee/mdk/mms/sync/status/ui/SyncStatusFrame.java +++ b/src/main/java/gov/nasa/jpl/mbee/mdk/mms/sync/status/ui/SyncStatusFrame.java @@ -25,18 +25,18 @@ public class SyncStatusFrame extends JFrame { private JLabel totalInMemoryLocalChangedLabel; private JLabel totalPersistedLocalChangedLabel; private JLabel totalLocalChangedLabel; - private JLabel inMemoryJmsCreatedLabel; - private JLabel inMemoryJmsUpdatedLabel; - private JLabel inMemoryJmsDeletedLabel; - private JLabel persistedJmsCreatedLabel; - private JLabel persistedJmsUpdatedLabel; - private JLabel persistedJmsDeletedLabel; - private JLabel totalJmsCreatedLabel; - private JLabel totalJmsUpdatedLabel; - private JLabel totalJmsDeletedLabel; - private JLabel totalInMemoryJmsChangedLabel; - private JLabel totalPersistedJmsChangedLabel; - private JLabel totalJmsChangedLabel; + private JLabel inMemoryMmsCreatedLabel; + private JLabel inMemoryMmsUpdatedLabel; + private JLabel inMemoryMmsDeletedLabel; + private JLabel persistedMmsCreatedLabel; + private JLabel persistedMmsUpdatedLabel; + private JLabel persistedMmsDeletedLabel; + private JLabel totalMmsCreatedLabel; + private JLabel totalMmsUpdatedLabel; + private JLabel totalMmsDeletedLabel; + private JLabel totalInMemoryMmsChangedLabel; + private JLabel totalPersistedMmsChangedLabel; + private JLabel totalMmsChangedLabel; private JButton detailsButton; public JPanel getRootPanel() { @@ -91,52 +91,52 @@ public JLabel getTotalLocalChangedLabel() { return totalLocalChangedLabel; } - public JLabel getInMemoryJmsCreatedLabel() { - return inMemoryJmsCreatedLabel; + public JLabel getInMemoryMmsCreatedLabel() { + return inMemoryMmsCreatedLabel; } - public JLabel getInMemoryJmsUpdatedLabel() { - return inMemoryJmsUpdatedLabel; + public JLabel getInMemoryMmsUpdatedLabel() { + return inMemoryMmsUpdatedLabel; } - public JLabel getInMemoryJmsDeletedLabel() { - return inMemoryJmsDeletedLabel; + public JLabel getInMemoryMmsDeletedLabel() { + return inMemoryMmsDeletedLabel; } - public JLabel getPersistedJmsCreatedLabel() { - return persistedJmsCreatedLabel; + public JLabel getPersistedMmsCreatedLabel() { + return persistedMmsCreatedLabel; } - public JLabel getPersistedJmsUpdatedLabel() { - return persistedJmsUpdatedLabel; + public JLabel getPersistedMmsUpdatedLabel() { + return persistedMmsUpdatedLabel; } - public JLabel getPersistedJmsDeletedLabel() { - return persistedJmsDeletedLabel; + public JLabel getPersistedMmsDeletedLabel() { + return persistedMmsDeletedLabel; } - public JLabel getTotalJmsCreatedLabel() { - return totalJmsCreatedLabel; + public JLabel getTotalMmsCreatedLabel() { + return totalMmsCreatedLabel; } - public JLabel getTotalJmsUpdatedLabel() { - return totalJmsUpdatedLabel; + public JLabel getTotalMmsUpdatedLabel() { + return totalMmsUpdatedLabel; } - public JLabel getTotalJmsDeletedLabel() { - return totalJmsDeletedLabel; + public JLabel getTotalMmsDeletedLabel() { + return totalMmsDeletedLabel; } - public JLabel getTotalInMemoryJmsChangedLabel() { - return totalInMemoryJmsChangedLabel; + public JLabel getTotalInMemoryMmsChangedLabel() { + return totalInMemoryMmsChangedLabel; } - public JLabel getTotalPersistedJmsChangedLabel() { - return totalPersistedJmsChangedLabel; + public JLabel getTotalPersistedMmsChangedLabel() { + return totalPersistedMmsChangedLabel; } - public JLabel getTotalJmsChangedLabel() { - return totalJmsChangedLabel; + public JLabel getTotalMmsChangedLabel() { + return totalMmsChangedLabel; } public JButton getDetailsButton() { @@ -231,33 +231,33 @@ public void actionPerformed(ActionEvent e) { gbc.weighty = 1.0; gbc.insets = new Insets(3, 3, 3, 3); panel1.add(persistedLocalDeletedLabel, gbc); - persistedJmsCreatedLabel = new JLabel(); - persistedJmsCreatedLabel.setText("4"); + persistedMmsCreatedLabel = new JLabel(); + persistedMmsCreatedLabel.setText("4"); gbc = new GridBagConstraints(); gbc.gridx = 8; gbc.gridy = 4; gbc.weightx = 1.0; gbc.weighty = 1.0; gbc.insets = new Insets(3, 3, 3, 3); - panel1.add(persistedJmsCreatedLabel, gbc); - persistedJmsUpdatedLabel = new JLabel(); - persistedJmsUpdatedLabel.setText("5"); + panel1.add(persistedMmsCreatedLabel, gbc); + persistedMmsUpdatedLabel = new JLabel(); + persistedMmsUpdatedLabel.setText("5"); gbc = new GridBagConstraints(); gbc.gridx = 9; gbc.gridy = 4; gbc.weightx = 1.0; gbc.weighty = 1.0; gbc.insets = new Insets(3, 3, 3, 3); - panel1.add(persistedJmsUpdatedLabel, gbc); - persistedJmsDeletedLabel = new JLabel(); - persistedJmsDeletedLabel.setText("6"); + panel1.add(persistedMmsUpdatedLabel, gbc); + persistedMmsDeletedLabel = new JLabel(); + persistedMmsDeletedLabel.setText("6"); gbc = new GridBagConstraints(); gbc.gridx = 10; gbc.gridy = 4; gbc.weightx = 1.0; gbc.weighty = 1.0; gbc.insets = new Insets(3, 3, 3, 3); - panel1.add(persistedJmsDeletedLabel, gbc); + panel1.add(persistedMmsDeletedLabel, gbc); inMemoryLocalCreatedLabel = new JLabel(); inMemoryLocalCreatedLabel.setText("6"); gbc = new GridBagConstraints(); @@ -285,33 +285,33 @@ public void actionPerformed(ActionEvent e) { gbc.weighty = 1.0; gbc.insets = new Insets(3, 3, 3, 3); panel1.add(inMemoryLocalDeletedLabel, gbc); - inMemoryJmsCreatedLabel = new JLabel(); - inMemoryJmsCreatedLabel.setText("3"); + inMemoryMmsCreatedLabel = new JLabel(); + inMemoryMmsCreatedLabel.setText("3"); gbc = new GridBagConstraints(); gbc.gridx = 8; gbc.gridy = 3; gbc.weightx = 1.0; gbc.weighty = 1.0; gbc.insets = new Insets(3, 3, 3, 3); - panel1.add(inMemoryJmsCreatedLabel, gbc); - inMemoryJmsUpdatedLabel = new JLabel(); - inMemoryJmsUpdatedLabel.setText("2"); + panel1.add(inMemoryMmsCreatedLabel, gbc); + inMemoryMmsUpdatedLabel = new JLabel(); + inMemoryMmsUpdatedLabel.setText("2"); gbc = new GridBagConstraints(); gbc.gridx = 9; gbc.gridy = 3; gbc.weightx = 1.0; gbc.weighty = 1.0; gbc.insets = new Insets(3, 3, 3, 3); - panel1.add(inMemoryJmsUpdatedLabel, gbc); - inMemoryJmsDeletedLabel = new JLabel(); - inMemoryJmsDeletedLabel.setText("1"); + panel1.add(inMemoryMmsUpdatedLabel, gbc); + inMemoryMmsDeletedLabel = new JLabel(); + inMemoryMmsDeletedLabel.setText("1"); gbc = new GridBagConstraints(); gbc.gridx = 10; gbc.gridy = 3; gbc.weightx = 1.0; gbc.weighty = 1.0; gbc.insets = new Insets(3, 3, 3, 3); - panel1.add(inMemoryJmsDeletedLabel, gbc); + panel1.add(inMemoryMmsDeletedLabel, gbc); final JLabel label3 = new JLabel(); label3.setFont(new Font(label3.getFont().getName(), Font.BOLD, 14)); label3.setText("Unsynced Local Changes"); @@ -431,36 +431,36 @@ public void actionPerformed(ActionEvent e) { gbc.weighty = 1.0; gbc.insets = new Insets(3, 3, 3, 3); panel1.add(totalLocalDeletedLabel, gbc); - totalJmsCreatedLabel = new JLabel(); - totalJmsCreatedLabel.setFont(new Font(totalJmsCreatedLabel.getFont().getName(), Font.BOLD, totalJmsCreatedLabel.getFont().getSize())); - totalJmsCreatedLabel.setText("7"); + totalMmsCreatedLabel = new JLabel(); + totalMmsCreatedLabel.setFont(new Font(totalMmsCreatedLabel.getFont().getName(), Font.BOLD, totalMmsCreatedLabel.getFont().getSize())); + totalMmsCreatedLabel.setText("7"); gbc = new GridBagConstraints(); gbc.gridx = 8; gbc.gridy = 6; gbc.weightx = 1.0; gbc.weighty = 1.0; gbc.insets = new Insets(3, 3, 3, 3); - panel1.add(totalJmsCreatedLabel, gbc); - totalJmsUpdatedLabel = new JLabel(); - totalJmsUpdatedLabel.setFont(new Font(totalJmsUpdatedLabel.getFont().getName(), Font.BOLD, totalJmsUpdatedLabel.getFont().getSize())); - totalJmsUpdatedLabel.setText("7"); + panel1.add(totalMmsCreatedLabel, gbc); + totalMmsUpdatedLabel = new JLabel(); + totalMmsUpdatedLabel.setFont(new Font(totalMmsUpdatedLabel.getFont().getName(), Font.BOLD, totalMmsUpdatedLabel.getFont().getSize())); + totalMmsUpdatedLabel.setText("7"); gbc = new GridBagConstraints(); gbc.gridx = 9; gbc.gridy = 6; gbc.weightx = 1.0; gbc.weighty = 1.0; gbc.insets = new Insets(3, 3, 3, 3); - panel1.add(totalJmsUpdatedLabel, gbc); - totalJmsDeletedLabel = new JLabel(); - totalJmsDeletedLabel.setFont(new Font(totalJmsDeletedLabel.getFont().getName(), Font.BOLD, totalJmsDeletedLabel.getFont().getSize())); - totalJmsDeletedLabel.setText("7"); + panel1.add(totalMmsUpdatedLabel, gbc); + totalMmsDeletedLabel = new JLabel(); + totalMmsDeletedLabel.setFont(new Font(totalMmsDeletedLabel.getFont().getName(), Font.BOLD, totalMmsDeletedLabel.getFont().getSize())); + totalMmsDeletedLabel.setText("7"); gbc = new GridBagConstraints(); gbc.gridx = 10; gbc.gridy = 6; gbc.weightx = 1.0; gbc.weighty = 1.0; gbc.insets = new Insets(3, 3, 3, 3); - panel1.add(totalJmsDeletedLabel, gbc); + panel1.add(totalMmsDeletedLabel, gbc); final JSeparator separator1 = new JSeparator(); separator1.setOrientation(1); gbc = new GridBagConstraints(); @@ -563,36 +563,36 @@ public void actionPerformed(ActionEvent e) { gbc.anchor = GridBagConstraints.SOUTH; gbc.insets = new Insets(3, 3, 3, 3); panel1.add(label13, gbc); - totalInMemoryJmsChangedLabel = new JLabel(); - totalInMemoryJmsChangedLabel.setFont(new Font(totalInMemoryJmsChangedLabel.getFont().getName(), Font.BOLD, totalInMemoryJmsChangedLabel.getFont().getSize())); - totalInMemoryJmsChangedLabel.setText("6"); + totalInMemoryMmsChangedLabel = new JLabel(); + totalInMemoryMmsChangedLabel.setFont(new Font(totalInMemoryMmsChangedLabel.getFont().getName(), Font.BOLD, totalInMemoryMmsChangedLabel.getFont().getSize())); + totalInMemoryMmsChangedLabel.setText("6"); gbc = new GridBagConstraints(); gbc.gridx = 12; gbc.gridy = 3; gbc.weightx = 1.0; gbc.weighty = 1.0; gbc.insets = new Insets(3, 3, 3, 3); - panel1.add(totalInMemoryJmsChangedLabel, gbc); - totalPersistedJmsChangedLabel = new JLabel(); - totalPersistedJmsChangedLabel.setFont(new Font(totalPersistedJmsChangedLabel.getFont().getName(), Font.BOLD, totalPersistedJmsChangedLabel.getFont().getSize())); - totalPersistedJmsChangedLabel.setText("15"); + panel1.add(totalInMemoryMmsChangedLabel, gbc); + totalPersistedMmsChangedLabel = new JLabel(); + totalPersistedMmsChangedLabel.setFont(new Font(totalPersistedMmsChangedLabel.getFont().getName(), Font.BOLD, totalPersistedMmsChangedLabel.getFont().getSize())); + totalPersistedMmsChangedLabel.setText("15"); gbc = new GridBagConstraints(); gbc.gridx = 12; gbc.gridy = 4; gbc.weightx = 1.0; gbc.weighty = 1.0; gbc.insets = new Insets(3, 3, 3, 3); - panel1.add(totalPersistedJmsChangedLabel, gbc); - totalJmsChangedLabel = new JLabel(); - totalJmsChangedLabel.setFont(new Font(totalJmsChangedLabel.getFont().getName(), Font.BOLD, totalJmsChangedLabel.getFont().getSize())); - totalJmsChangedLabel.setText("21"); + panel1.add(totalPersistedMmsChangedLabel, gbc); + totalMmsChangedLabel = new JLabel(); + totalMmsChangedLabel.setFont(new Font(totalMmsChangedLabel.getFont().getName(), Font.BOLD, totalMmsChangedLabel.getFont().getSize())); + totalMmsChangedLabel.setText("21"); gbc = new GridBagConstraints(); gbc.gridx = 12; gbc.gridy = 6; gbc.weightx = 1.0; gbc.weighty = 1.0; gbc.insets = new Insets(3, 3, 3, 3); - panel1.add(totalJmsChangedLabel, gbc); + panel1.add(totalMmsChangedLabel, gbc); final JSeparator separator7 = new JSeparator(); separator7.setOrientation(1); gbc = new GridBagConstraints(); diff --git a/src/main/java/gov/nasa/jpl/mbee/mdk/mms/validation/ElementValidator.java b/src/main/java/gov/nasa/jpl/mbee/mdk/mms/validation/ElementValidator.java index d23e49aac..ec9c31318 100644 --- a/src/main/java/gov/nasa/jpl/mbee/mdk/mms/validation/ElementValidator.java +++ b/src/main/java/gov/nasa/jpl/mbee/mdk/mms/validation/ElementValidator.java @@ -101,13 +101,14 @@ public void run(ProgressStatus progressStatus) { if (current != JsonToken.START_OBJECT) { throw new IOException("Unable to build object from JSON parser."); } - while (current != JsonToken.END_OBJECT) { + while (current != null && current != JsonToken.END_OBJECT) { current = jsonParser.nextToken(); String keyName; if (current != null && (keyName = jsonParser.getCurrentName()) != null && keyName.equals("elements") && (current = jsonParser.nextToken()) == JsonToken.START_ARRAY) { current = jsonParser.nextToken(); JsonNode value; - while (current != JsonToken.END_ARRAY) { + while (current != null && current != JsonToken.END_ARRAY) { + //current = jsonParser.nextToken(); if (current == JsonToken.START_OBJECT) { String id; ObjectNode currentServerElement = JacksonUtils.parseJsonObject(jsonParser); diff --git a/src/main/java/gov/nasa/jpl/mbee/mdk/model/GenericTable.java b/src/main/java/gov/nasa/jpl/mbee/mdk/model/GenericTable.java index 7d59be489..07ad05e8c 100644 --- a/src/main/java/gov/nasa/jpl/mbee/mdk/model/GenericTable.java +++ b/src/main/java/gov/nasa/jpl/mbee/mdk/model/GenericTable.java @@ -14,8 +14,8 @@ import com.nomagic.uml2.ext.magicdraw.classes.mdkernel.NamedElement; import gov.nasa.jpl.mbee.mdk.docgen.DocGenProfile; import gov.nasa.jpl.mbee.mdk.docgen.docbook.*; -import gov.nasa.jpl.mbee.mdk.mms.sync.local.LocalSyncProjectEventListenerAdapter; -import gov.nasa.jpl.mbee.mdk.mms.sync.local.LocalSyncTransactionCommitListener; +import gov.nasa.jpl.mbee.mdk.mms.sync.local.LocalDeltaProjectEventListenerAdapter; +import gov.nasa.jpl.mbee.mdk.mms.sync.local.LocalDeltaTransactionCommitListener; import gov.nasa.jpl.mbee.mdk.util.DependencyMatrixTool; import gov.nasa.jpl.mbee.mdk.util.GeneratorUtils; import gov.nasa.jpl.mbee.mdk.util.MatrixUtil; @@ -50,7 +50,7 @@ public List visit(boolean forViewEditor, String outputDir) { } // We really shouldn't be using Application.getInstance().getProject() here, but the context is already lost somewhere upstream :/ // dgElement won't always be there and there is no guarantee that it or the exposed element(s) aren't from a library - LocalSyncTransactionCommitListener listener = LocalSyncProjectEventListenerAdapter.getProjectMapping(Application.getInstance().getProject()).getLocalSyncTransactionCommitListener(); + LocalDeltaTransactionCommitListener listener = LocalDeltaProjectEventListenerAdapter.getProjectMapping(Application.getInstance().getProject()).getLocalDeltaTransactionCommitListener(); listener.setDisabled(true); try { int tableCount = 0; diff --git a/src/main/java/gov/nasa/jpl/mbee/mdk/util/TaskRunner.java b/src/main/java/gov/nasa/jpl/mbee/mdk/util/TaskRunner.java index d54a3e0ae..7ad6e9d81 100644 --- a/src/main/java/gov/nasa/jpl/mbee/mdk/util/TaskRunner.java +++ b/src/main/java/gov/nasa/jpl/mbee/mdk/util/TaskRunner.java @@ -17,8 +17,11 @@ import java.util.concurrent.locks.Condition; import java.util.concurrent.locks.Lock; import java.util.concurrent.locks.ReentrantLock; +import java.util.function.BiFunction; public class TaskRunner { + private static final ScheduledExecutorService scheduledExecutorService = Executors.newScheduledThreadPool(0); + public static Future runWithProgressStatus(Runnable runnable, String title, ThreadExecutionStrategy strategy) { return runWithProgressStatus(runnable, title, strategy, false); } @@ -90,6 +93,10 @@ public static Future runWithProgressStatus(RunnableWithProgress runnableWithP return future; } + public static ScheduledFuture scheduleWithProgressStatus(RunnableWithProgress runnableWithProgress, String title, boolean allowCancel, ThreadExecutionStrategy strategy, boolean silent, BiFunction scheduleFunction) { + return scheduleFunction.apply(() -> runWithProgressStatus(runnableWithProgress, title, allowCancel, strategy, silent), scheduledExecutorService); + } + public enum ThreadExecutionStrategy { SINGLE(new ThreadPoolExecutor(0, 1, 60L, TimeUnit.SECONDS, new LinkedBlockingQueue<>())), POOLED(new ThreadPoolExecutor(Math.min(Runtime.getRuntime().availableProcessors(), 4), 4, 60L, TimeUnit.SECONDS, new LinkedBlockingQueue<>())), diff --git a/src/main/java/gov/nasa/jpl/mbee/mdk/util/TicketUtils.java b/src/main/java/gov/nasa/jpl/mbee/mdk/util/TicketUtils.java index 60d862403..70c52a6a5 100644 --- a/src/main/java/gov/nasa/jpl/mbee/mdk/util/TicketUtils.java +++ b/src/main/java/gov/nasa/jpl/mbee/mdk/util/TicketUtils.java @@ -4,7 +4,6 @@ import com.nomagic.magicdraw.core.Application; import com.nomagic.magicdraw.core.Project; import com.nomagic.task.ProgressStatus; -import com.nomagic.task.RunnableWithProgress; import com.nomagic.ui.ProgressStatusRunner; import gov.nasa.jpl.mbee.mdk.http.ServerException; import gov.nasa.jpl.mbee.mdk.json.JacksonUtils; @@ -21,8 +20,7 @@ import java.io.IOException; import java.net.URISyntaxException; import java.util.HashMap; -import java.util.concurrent.Executors; -import java.util.concurrent.ScheduledExecutorService; +import java.util.concurrent.ScheduledFuture; import java.util.concurrent.TimeUnit; public class TicketUtils { @@ -197,9 +195,8 @@ public static void setUsernameAndPassword(String user, String pass) { public static void clearTicket(Project project) { password = ""; TicketMapping removed = ticketMappings.remove(project); - // kill auto-renewal in removed - if (removed != null) { - removed.getTicketRenewer().shutdown(); + if (removed != null && removed.getScheduledFuture() != null) { + removed.getScheduledFuture().cancel(true); } } @@ -265,45 +262,38 @@ private static boolean acquireTicket(Project project, String pass) { } private static class TicketMapping { - final private String ticket; - final private String username; - private ScheduledExecutorService ticketRenewer; + private final String ticket; + private final String username; + private final ScheduledFuture scheduledFuture; TicketMapping(Project project, String username, String ticket) { this.ticket = ticket; this.username = username; - this.ticketRenewer = Executors.newScheduledThreadPool(1); - // intentionally catching exceptions here, to avoid scheduled thread suspension - final Runnable renewTicket = () -> { - // try/catching here to prevent service being disabled for future calls + this.scheduledFuture = TaskRunner.scheduleWithProgressStatus(progressStatus -> { try { - try { - boolean isValid = isTicketValid(project, null); - if (!isValid) { - Application.getInstance().getGUILog().log("[INFO] MMS credentials are expired or invalid."); - MMSLogoutAction.logoutAction(project); - } - } catch (IOException | URISyntaxException | ServerException e) { - Application.getInstance().getGUILog().log("[ERROR] An error occurred while checking ticket validity. Ticket will be retained for re-validation. Reason: " + e.getMessage()); - e.printStackTrace(); + boolean isValid = isTicketValid(project, progressStatus); + if (!isValid) { + Application.getInstance().getGUILog().log("[INFO] MMS credentials are expired or invalid."); + MMSLogoutAction.logoutAction(project); } + } catch (IOException | URISyntaxException | ServerException e) { + Application.getInstance().getGUILog().log("[ERROR] An error occurred while checking ticket validity. Ticket will be retained for re-validation. Reason: " + e.getMessage()); + e.printStackTrace(); } catch (Exception ignored) { } - }; - this.ticketRenewer.scheduleAtFixedRate(renewTicket, TICKET_RENEWAL_INTERVAL, TICKET_RENEWAL_INTERVAL, TimeUnit.SECONDS); + }, "Checking MMS ticket", false, TaskRunner.ThreadExecutionStrategy.NONE, false, (runnable, service) -> service.scheduleAtFixedRate(runnable, TICKET_RENEWAL_INTERVAL, TICKET_RENEWAL_INTERVAL, TimeUnit.SECONDS)); } public String getTicket() { - return this.ticket; + return ticket; } public String getUsername() { - return this.username; + return username; } - public ScheduledExecutorService getTicketRenewer() { - return this.ticketRenewer; + public ScheduledFuture getScheduledFuture() { + return scheduledFuture; } - } } diff --git a/src/main/java/gov/nasa/jpl/mbee/mdk/util/Utils.java b/src/main/java/gov/nasa/jpl/mbee/mdk/util/Utils.java index 08f021cd9..e7526d4be 100644 --- a/src/main/java/gov/nasa/jpl/mbee/mdk/util/Utils.java +++ b/src/main/java/gov/nasa/jpl/mbee/mdk/util/Utils.java @@ -25,7 +25,6 @@ import com.nomagic.uml2.ext.magicdraw.classes.mdkernel.*; import com.nomagic.uml2.ext.magicdraw.classes.mdkernel.Class; import com.nomagic.uml2.ext.magicdraw.classes.mdkernel.Package; -import com.nomagic.uml2.ext.magicdraw.components.mdbasiccomponents.Component; import com.nomagic.uml2.ext.magicdraw.mdprofiles.Stereotype; import com.nomagic.uml2.impl.ElementsFactory; import gov.nasa.jpl.mbee.mdk.api.incubating.MDKConstants; @@ -38,8 +37,8 @@ import gov.nasa.jpl.mbee.mdk.emf.EmfUtils; import gov.nasa.jpl.mbee.mdk.generator.CollectFilterParser; import gov.nasa.jpl.mbee.mdk.generator.DocumentValidator; -import gov.nasa.jpl.mbee.mdk.mms.sync.local.LocalSyncProjectEventListenerAdapter; -import gov.nasa.jpl.mbee.mdk.mms.sync.local.LocalSyncTransactionCommitListener; +import gov.nasa.jpl.mbee.mdk.mms.sync.local.LocalDeltaProjectEventListenerAdapter; +import gov.nasa.jpl.mbee.mdk.mms.sync.local.LocalDeltaTransactionCommitListener; import gov.nasa.jpl.mbee.mdk.ocl.GetCallOperation; import gov.nasa.jpl.mbee.mdk.ocl.GetCallOperation.CallReturnType; import gov.nasa.jpl.mbee.mdk.ocl.OclEvaluator; @@ -2788,7 +2787,7 @@ public static boolean recommendUpdateFromRemote(Project project, String add) { if (reply == null || !reply) { return false; } - LocalSyncTransactionCommitListener listener = LocalSyncProjectEventListenerAdapter.getProjectMapping(project).getLocalSyncTransactionCommitListener(); + LocalDeltaTransactionCommitListener listener = LocalDeltaProjectEventListenerAdapter.getProjectMapping(project).getLocalDeltaTransactionCommitListener(); if (listener != null) { listener.setDisabled(true); } diff --git a/src/main/java/gov/nasa/jpl/mbee/mdk/validation/RuleViolationAction.java b/src/main/java/gov/nasa/jpl/mbee/mdk/validation/RuleViolationAction.java index 3f72e92a5..cf941a1af 100644 --- a/src/main/java/gov/nasa/jpl/mbee/mdk/validation/RuleViolationAction.java +++ b/src/main/java/gov/nasa/jpl/mbee/mdk/validation/RuleViolationAction.java @@ -7,8 +7,8 @@ import com.nomagic.magicdraw.openapi.uml.ReadOnlyElementException; import com.nomagic.magicdraw.openapi.uml.SessionManager; import com.nomagic.magicdraw.validation.RuleViolationResult; -import gov.nasa.jpl.mbee.mdk.mms.sync.local.LocalSyncProjectEventListenerAdapter; -import gov.nasa.jpl.mbee.mdk.mms.sync.local.LocalSyncTransactionCommitListener; +import gov.nasa.jpl.mbee.mdk.mms.sync.local.LocalDeltaProjectEventListenerAdapter; +import gov.nasa.jpl.mbee.mdk.mms.sync.local.LocalDeltaTransactionCommitListener; import gov.nasa.jpl.mbee.mdk.util.Utils; import javax.swing.*; @@ -79,7 +79,7 @@ protected void doAfterSuccess() { } protected void executeMany(Collection annos, String sessionName) { - LocalSyncTransactionCommitListener listener = LocalSyncProjectEventListenerAdapter.getProjectMapping(Application.getInstance().getProject()).getLocalSyncTransactionCommitListener(); + LocalDeltaTransactionCommitListener listener = LocalDeltaProjectEventListenerAdapter.getProjectMapping(Application.getInstance().getProject()).getLocalDeltaTransactionCommitListener(); if (listener != null) { listener.setDisabled(true); } @@ -115,7 +115,7 @@ protected void executeMany(Collection annos, String sessionName) { } protected void execute(String sessionName) { - LocalSyncTransactionCommitListener listener = LocalSyncProjectEventListenerAdapter.getProjectMapping(Application.getInstance().getProject()).getLocalSyncTransactionCommitListener(); + LocalDeltaTransactionCommitListener listener = LocalDeltaProjectEventListenerAdapter.getProjectMapping(Application.getInstance().getProject()).getLocalDeltaTransactionCommitListener(); if (listener != null) { listener.setDisabled(true); } diff --git a/src/test/java/gov/nasa/jpl/mbee/mdk/MMSSyncPluginTest.java b/src/test/java/gov/nasa/jpl/mbee/mdk/MMSSyncPluginTest.java index 87af67984..ff26b2477 100644 --- a/src/test/java/gov/nasa/jpl/mbee/mdk/MMSSyncPluginTest.java +++ b/src/test/java/gov/nasa/jpl/mbee/mdk/MMSSyncPluginTest.java @@ -28,13 +28,13 @@ public void getInstance() { } @Test - public void getLocalSyncProjectEventListenerAdapter() { - assertTrue("MMSSyncPlugin shall return a LocalSyncProjectEventListenerAdapter.", plugin != null && MMSSyncPlugin.getInstance().getLocalSyncProjectEventListenerAdapter() != null); + public void getLocalDeltaProjectEventListenerAdapter() { + assertTrue("MMSSyncPlugin shall return a LocalDeltaProjectEventListenerAdapter.", plugin != null && MMSSyncPlugin.getInstance().getLocalDeltaProjectEventListenerAdapter() != null); } @Test - public void getJmsSyncProjectEventListenerAdapter() { - assertTrue("MMSSyncPlugin shall return a JmsSyncProjectEventListenerAdapter.", plugin != null && MMSSyncPlugin.getInstance().getJmsSyncProjectEventListenerAdapter() != null); + public void getMmsSyncProjectEventListenerAdapter() { + assertTrue("MMSSyncPlugin shall return a MmsDeltaProjectEventListenerAdapter.", plugin != null && MMSSyncPlugin.getInstance().getMmsDeltaProjectEventListenerAdapter() != null); } @Test