package gov.nasa.jpl.mbee.mdk.systems_reasoner.actions;
import com.nomagic.magicdraw.copypaste.CopyPasting;
import com.nomagic.magicdraw.core.Application;
import com.nomagic.magicdraw.openapi.uml.SessionManager;
import com.nomagic.magicdraw.ui.dialogs.MDDialogParentProvider;
import com.nomagic.magicdraw.ui.dialogs.SelectElementInfo;
import com.nomagic.magicdraw.ui.dialogs.SelectElementTypes;
import com.nomagic.magicdraw.ui.dialogs.selection.ElementSelectionDlg;
import com.nomagic.magicdraw.ui.dialogs.selection.ElementSelectionDlgFactory;
import com.nomagic.magicdraw.ui.dialogs.selection.SelectionMode;
import com.nomagic.uml2.ext.jmi.helpers.ModelHelper;
import com.nomagic.uml2.ext.magicdraw.auxiliaryconstructs.mdmodels.Model;
import com.nomagic.uml2.ext.magicdraw.classes.mdkernel.*;
import gov.nasa.jpl.mbee.mdk.util.Utils;
import java.awt.*;
import java.awt.event.ActionEvent;
import java.lang.Class;
import java.util.ArrayList;
import java.util.List;
public class SpecializeStructureAction extends SRAction {
/**
*
*/
private static final long serialVersionUID = 1L;
public static final List<Class<? extends Classifier>> UNSPECIALIZABLE_CLASSIFIERS = new ArrayList<Class<? extends Classifier>>();
static {
UNSPECIALIZABLE_CLASSIFIERS.add(DataType.class);
UNSPECIALIZABLE_CLASSIFIERS.add(PrimitiveType.class);
}
private final boolean recursionMode;
private final boolean individualMode;
private Classifier classifier;
private ArrayList<Namespace> recursionList;
private boolean isValidationMode = false;
public SpecializeStructureAction(final Classifier classifier, boolean isValidationMode, String id, boolean isRecursive, boolean isIndividual) {
super(id, classifier);
this.classifier = classifier;
recursionList = new ArrayList<>();
this.isValidationMode = isValidationMode;
this.recursionMode = isRecursive;
this.individualMode = isIndividual;
}
@Override
public void actionPerformed(ActionEvent e) {
final List<java.lang.Class<?>> types = new ArrayList<>();
types.add(com.nomagic.uml2.ext.magicdraw.classes.mdkernel.Class.class);
types.add(com.nomagic.uml2.ext.magicdraw.classes.mdkernel.Package.class);
types.add(Model.class);
final Frame dialogParent = MDDialogParentProvider.getProvider().getDialogParent();
final ElementSelectionDlg dlg = ElementSelectionDlgFactory.create(dialogParent);
dlg.setTitle("Select container for generated elements:");
final SelectElementTypes set = new SelectElementTypes(null, types, null, null);
final SelectElementInfo sei = new SelectElementInfo(true, false, Application.getInstance().getProject().getModel().getOwner(), true);
ElementSelectionDlgFactory.initSingle(dlg, set, sei, classifier.getOwner());
dlg.setSelectionMode(SelectionMode.SINGLE_MODE);
if (!isValidationMode) {
dlg.setVisible(true);
}
if (isValidationMode || dlg.isOkClicked() && dlg.getSelectedElement() != null && dlg.getSelectedElement() instanceof Namespace) {
SessionManager.getInstance().createSession("Create BST");
Namespace container;
if (isValidationMode) {
container = (Namespace) classifier.getOwner();
}
else {
container = (Namespace) dlg.getSelectedElement();
}
Classifier specific = createSpecialClassifier(container, new ArrayList<RedefinableElement>(), new ArrayList<Classifier>());
SessionManager.getInstance().closeSession();
checkAssociationsForInheritance(specific, classifier);
}
}
public Classifier createSpecialClassifier(Namespace container, List<RedefinableElement> traveled, List<Classifier> visited) {
for (final Class<? extends Classifier> c : UNSPECIALIZABLE_CLASSIFIERS) {
if (c.isAssignableFrom(classifier.getClass())) {
// Application.getInstance().getGUILog()
// .log("[WARNING] " + (structuralFeature != null ? structuralFeature.getQualifiedName() : "< >") + " is a " + c.getSimpleName() + ", which is not specializable.");
return null;
}
}
if (visited.contains(classifier)) {
}
Classifier specific = (Classifier) CopyPasting.copyPasteElement(classifier, container);
visited.add(specific);
visited.add(classifier);
Utils.createGeneralization(classifier, specific);
for (final NamedElement ne : specific.getInheritedMember()) { // Exclude Classifiers for now -> Should Aspect Blocks be Redefined?
if (ne instanceof RedefinableElement && !((RedefinableElement) ne).isLeaf() && !(ne instanceof Classifier)) {
final RedefinableElement redefEl = (RedefinableElement) ne;
SetOrCreateRedefinableElementAction action = new SetOrCreateRedefinableElementAction(specific, redefEl, traveled, recursionMode, null, individualMode);
SetOrCreateRedefinableElementAction.redefineAttribute(specific, redefEl, recursionMode, traveled, visited, individualMode);
}
}
return specific;
}
private void deleteDiagrams(Namespace specific, ArrayList<Diagram> diagrams) {
for (NamedElement ne : specific.getOwnedMember()) {
if (ne instanceof Diagram) {
diagrams.add((Diagram) ne);
}
else if (ne instanceof Namespace) {
for (NamedElement nam : ((Namespace) ne).getOwnedMember()) {
deleteDiagrams((Namespace) nam, diagrams);
}
}
}
}
private void checkAssociationsForInheritance(Classifier classifier, Classifier general) {
assocRule:
for (Element child : classifier.getOwnedElement()) {
if (child instanceof Property) {
Type partType = ((Property) child).getType();
for (Element superChild : general.getOwnedElement()) {
if (superChild instanceof Property) {
Type superPartType = ((Property) superChild).getType();
if (partType != null) {
if (partType.equals(superPartType)) {
if (hasAnAssociation(superChild)) {
if (hasInheritanceFromTo(((Property) child).getAssociation(), ((Property) superChild).getAssociation())) {
break assocRule;
}
else {
AddInheritanceToAssociationAction action = new AddInheritanceToAssociationAction(((Property) child).getAssociation(), ((Property) superChild).getAssociation());
action.actionPerformed(null);
}
}
}
else if (partType instanceof Classifier) {
if (((Classifier) partType).getGeneral().contains(superPartType)) {
if (hasInheritanceFromTo(((Property) child).getAssociation(), ((Property) superChild).getAssociation())) {
break assocRule;
}
else {
AddInheritanceToAssociationAction action = new AddInheritanceToAssociationAction(((Property) child).getAssociation(), ((Property) superChild).getAssociation());
action.actionPerformed(null);
}
}
}
}
}
}
}
}
}
private boolean hasAnAssociation(Element superChild) {
return ((Property) superChild).getAssociation() != null;
}
private boolean hasInheritanceFromTo(Classifier classifier, Classifier general) {
if (classifier != null) {
return ModelHelper.getGeneralClassifiersRecursivelly(classifier).contains(general);
}
else {
return false;
}
}
}