package gov.nasa.jpl.mbee.mdk.actions;
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.uml2.ext.jmi.helpers.StereotypesHelper;
import com.nomagic.uml2.ext.magicdraw.classes.mdkernel.*;
import com.nomagic.uml2.ext.magicdraw.classes.mdkernel.Class;
import com.nomagic.uml2.ext.magicdraw.mdprofiles.Stereotype;
import gov.nasa.jpl.mbee.mdk.api.incubating.convert.Converters;
import gov.nasa.jpl.mbee.mdk.util.Utils;
import gov.nasa.jpl.mbee.mdk.mms.MMSUtils;
import gov.nasa.jpl.mbee.mdk.ui.ViewEditorLinkForm;
import org.apache.http.client.utils.URIBuilder;
import javax.swing.*;
import java.awt.*;
import java.awt.event.ActionEvent;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import java.io.IOException;
import java.net.URI;
import java.net.URISyntaxException;
import java.util.*;
import java.util.List;
public class MMSViewLinkAction extends MDAction {
private static final long serialVersionUID = 1L;
private Collection<Element> targetElements;
private Project project;
public static final String DEFAULT_ID = "ViewLink";
public MMSViewLinkAction(Collection<Element> elements) {
super(DEFAULT_ID, "Open in View Editor", null, null);
this.targetElements = elements;
this.project = Project.getProject(elements.iterator().next());
}
public MMSViewLinkAction(Element element) {
super(DEFAULT_ID, "Open in View Editor", null, null);
this.targetElements = new ArrayList<>();
this.targetElements.add(element);
this.project = Project.getProject(element);
}
@Override
public void actionPerformed(ActionEvent e) {
Stereotype documentStereotype = Utils.getDocumentStereotype(project);
Stereotype viewStereotype = Utils.getViewStereotype(project);
for (Element element : targetElements) {
if (!StereotypesHelper.hasStereotypeOrDerived(element, viewStereotype)
&& !StereotypesHelper.hasStereotypeOrDerived(element, documentStereotype)) {
continue;
}
Project project = Project.getProject(element);
// build url
URIBuilder uriBase = MMSUtils.getServiceUri(project);
if (uriBase == null) {
Application.getInstance().getGUILog().log("[ERROR] Unable to retrieve MMS information from model stereotype. Cancelling view open.");
return;
}
//projects/PROJECT-ID_5_17_16_1_31_54_PM_5fc737b6_154bba92ecd_4cc1_cae_tw_jpl_nasa_gov_127_0_0_1/master/documents/_18_5_83a025f_1491339810716_846504_4332/views/_18_5_83a025f_1491339810716_846504_4332
// include this in the host portion of the uri. not technically correct, but it prevents the # from being converted and breaking things
uriBase.setHost(uriBase.getHost() + "/alfresco/mmsapp/mms.html#");
String uriPath = "/projects/" + Converters.getIProjectToIdConverter().apply(project.getPrimaryProject());
String branchName = EsiUtils.getCurrentBranch(project.getPrimaryProject()).getName();
uriPath += "/" + (branchName.equals("trunk") ? "master" : branchName);
// collect document parents from hierarchy
Set<Element> documents = new HashSet<>();
ArrayList<Element> viewChain = new ArrayList<>();
viewChain.add(element);
for (int i = 0; i < viewChain.size(); i++) {
if (StereotypesHelper.hasStereotype(viewChain.get(i), documentStereotype)) {
documents.add(viewChain.get(i));
}
// create set of hierarchy children so we can ignore those ends and only climb the hierarchy
Set<Element> childViews = new HashSet<>();
for (Property prop : ((Class) viewChain.get(i)).getOwnedAttribute()) {
if (!(prop.getType() instanceof Class)) {
continue;
}
Class type = (Class) prop.getType();
if (type == null || !(StereotypesHelper.hasStereotypeOrDerived(type, viewStereotype)
|| StereotypesHelper.hasStereotypeOrDerived(type, documentStereotype))) {
continue;
}
childViews.add(type);
}
// check each association end, if it's a non-child view/document then add it to chain for further processing
for (Relationship relation : viewChain.get(i).get_relationshipOfRelatedElement()) {
if (!(relation instanceof Association)) {
continue;
}
Element assocEnd = ((Association) relation).getMemberEnd().get(0).getOwner();
if (!StereotypesHelper.hasStereotypeOrDerived(assocEnd, viewStereotype)
&& !StereotypesHelper.hasStereotypeOrDerived(assocEnd, documentStereotype)) {
continue;
}
if (!childViews.contains(assocEnd) && !viewChain.contains(assocEnd)) {
viewChain.add(assocEnd);
}
}
}
// build links
if (documents.size() > 1) {
// build multiple links
String label = "";
List<JButton> linkButtons = new ArrayList<>();
try {
if (!documents.isEmpty()) {
label = "Documents containing " + element.getHumanName() + ":";
for (Element doc : documents) {
if (doc.equals(element)) {
uriPath += "/documents/" + Converters.getElementToIdConverter().apply(element);
}
else {
uriPath += "/documents/" + Converters.getElementToIdConverter().apply(doc) + "/views/" + Converters.getElementToIdConverter().apply(element);
}
JButton button = new ViewButton(doc.getHumanName(), uriBase.setPath(uriPath).build());
linkButtons.add(button);
}
}
} catch (URISyntaxException se) {
Application.getInstance().getGUILog().log("[ERROR] Exception occurred while generating View Editor links for " + element.getHumanName() + ". Unable to proceed.");
return;
}
// and display
ViewEditorLinkForm viewLinkForm = new ViewEditorLinkForm(label, linkButtons);
viewLinkForm.setVisible(true);
}
else {
// build single link
uriPath += "/documents/" + Converters.getElementToIdConverter().apply(element) + "/views/" + Converters.getElementToIdConverter().apply(element);
// just open it if possible
if (Desktop.isDesktopSupported()) {
try {
if (documents.size() == 0) {
Application.getInstance().getGUILog().log("[INFO] " + element.getHumanName()
+ " does not belong to a document hierarchy. Opening view in View Editor without document context.");
}
Desktop.getDesktop().browse(uriBase.setPath(uriPath).build());
} catch (URISyntaxException | IOException e1) {
Application.getInstance().getGUILog().log("[ERROR] Exception occurred while opening the View Editor page. Link: " + uriBase.toString());
e1.printStackTrace();
}
}
else {
Application.getInstance().getGUILog().log("[WARNING] Java is unable to open links on your computer. Link: " + uriBase.toString());
}
}
}
}
private class ViewButton extends JButton {
private URI uri;
ViewButton(String text, URI uri) {
super(text);
setup(uri);
this.setMaximumSize(new Dimension(280, 18));
}
void setup(URI u) {
uri = u;
setToolTipText(uri.toString());
addMouseListener(new MouseAdapter() {
public void mouseClicked(MouseEvent e) {
open(uri);
}
});
}
private void open(URI uri) {
if (Desktop.isDesktopSupported()) {
Desktop desktop = Desktop.getDesktop();
try {
desktop.browse(uri);
} catch (IOException e) {
Application.getInstance().getGUILog().log("[ERROR] Exception occurred while opening the View Editor page. Link: " + uri.toString());
}
}
else {
Application.getInstance().getGUILog().log("[WARNING] Java is unable to open links on your computer. Link: " + uri.toString());
}
}
}
}