package gov.nasa.jpl.mbee.mdk.systems_reasoner.actions; import com.nomagic.magicdraw.annotation.Annotation; import com.nomagic.magicdraw.copypaste.CopyPasting; import com.nomagic.magicdraw.core.Application; import com.nomagic.task.ProgressStatus; import com.nomagic.uml2.ext.magicdraw.classes.mdkernel.*; import gov.nasa.jpl.mbee.mdk.validation.GenericRuleViolationAction; import java.util.*; public class CreateSlotsAction extends GenericRuleViolationAction { /** * ADD CIRCULAR REFERENCE DETECTION */ private static final long serialVersionUID = 1L; private static final String DEFAULT_NAME = "Create Slots"; private InstanceSpecification instance; private boolean recurse, deleteSlots, deleteChildInstances; private String name; private ProgressStatus progressStatus; public CreateSlotsAction(final InstanceSpecification instance) { this(instance, false, false, false); } public CreateSlotsAction(final InstanceSpecification instance, final boolean recurse, final boolean deleteSlots, final boolean deleteChildInstances) { this(instance, recurse, deleteSlots, deleteChildInstances, DEFAULT_NAME); } public CreateSlotsAction(final InstanceSpecification instance, final boolean recurse, final boolean deleteSlots, final boolean deleteChildInstances, final String name) { super(name); this.instance = instance; this.recurse = recurse; this.deleteSlots = deleteSlots; this.deleteChildInstances = deleteChildInstances; this.name = name; } public static List<InstanceSpecification> getChildInstancesRecursively(final Slot slot) { final List<InstanceSpecification> instances = new ArrayList<InstanceSpecification>(); for (final ValueSpecification vs : slot.getValue()) { InstanceSpecification instance; if (vs instanceof InstanceValue && (instance = ((InstanceValue) vs).getInstance()) != null) { instances.add(instance); for (final Slot childSlot : instance.getSlot()) { instances.addAll(getChildInstancesRecursively(childSlot)); } } } return instances; } public static List<Property> collectSlottableProperties(final Classifier classifier) { final List<Property> properties = new ArrayList<Property>(); properties.addAll(classifier.getAttribute()); for (final NamedElement inheritedMember : classifier.getInheritedMember()) { boolean toAdd = true; for (final Property property : properties) { if (property.hasRedefinedElement() && property.getRedefinedElement().contains(inheritedMember)) { toAdd = false; break; } } if (toAdd && inheritedMember instanceof Property) { properties.add((Property) inheritedMember); } } return properties; } public static Map<Property, Slot> createSlots(final InstanceSpecification instance, final boolean recurse, final boolean deleteSlots, final boolean deleteChildInstances, final ProgressStatus progressStatus) { if (progressStatus != null) { progressStatus.setIndeterminate(true); } if (deleteSlots && instance.hasSlot()) { for (final Slot slot : instance.getSlot()) { if (deleteChildInstances) { for (final InstanceSpecification is : getChildInstancesRecursively(slot)) { is.dispose(); } } } for (final Slot slot : instance.getSlot()) { slot.dispose(); } } return createSlots(instance, recurse, new HashMap<Classifier, InstanceSpecification>()); } public static Map<Property, Slot> createSlots(final InstanceSpecification instance, final boolean recurse, final Map<Classifier, InstanceSpecification> traveled) { final Map<Property, Slot> propertySlotMapping = new HashMap<Property, Slot>(); final Map<Property, Slot> implicitCache = new HashMap<Property, Slot>(); for (final Classifier classifier : instance.getClassifier()) { int loop = 0; final List<Property> properties = collectSlottableProperties(classifier); for (final Slot slot : instance.getSlot()) { if (slot.getDefiningFeature() != null) { properties.remove(slot.getDefiningFeature()); } } while (!properties.isEmpty() && loop++ < 100) { //System.out.print("Loop: " + ++loop + " : " + properties.size() + " - "); /*for (final Property property : properties) { System.out.print(property.getQualifiedName() + ", "); } System.out.println();*/ final ListIterator<Property> propertyIterator = properties.listIterator(); while (propertyIterator.hasNext()) { final Property property = propertyIterator.next(); final List<Property> subsettingProperties = new ArrayList<Property>(); if (property.has_propertyOfSubsettedProperty()) { for (final Property subsettingProperty : property.get_propertyOfSubsettedProperty()) { if (subsettingProperty.getClassifier() != null && subsettingProperty.getClassifier().equals(classifier)) { subsettingProperties.add(subsettingProperty); } } } if (!subsettingProperties.isEmpty()) { /*System.out.println("I AM SUBSETTED: " + property.getQualifiedName()); for (final Property subsettingProperty : property.get_propertyOfSubsettedProperty()) { System.out.println(subsettingProperty.getQualifiedName()); }*/ boolean missingDependency = false; for (final Property subsettingProperty : subsettingProperties) { if (!implicitCache.containsKey(subsettingProperty)) { //System.out.println("Missing property! " + subsettingProperty.getQualifiedName() + " : " + property.getQualifiedName()); missingDependency = true; break; } } if (missingDependency) { /*System.out.println("Cache [" + implicitCache.size() + "]: "); for (final Map.Entry<Property, Slot> entrySet : implicitCache.entrySet()) { System.out.println("[" + entrySet.getKey().getQualifiedName() + "]=" + entrySet.getValue().getID()); } if (traveled.contains(property)) { System.out.println("REMOVING " + property.getQualifiedName()); propertyIterator.remove(); } System.out.println("CONTINUING " + property.getQualifiedName());*/ continue; } final Slot slot = Application.getInstance().getProject().getElementsFactory().createSlotInstance(); slot.setDefiningFeature(property); for (final Property subsettingProperty : subsettingProperties) { for (final ValueSpecification vs : implicitCache.get(subsettingProperty).getValue()) { final ValueSpecification clonedValueSpec = (ValueSpecification) CopyPasting.copyPasteElement(vs, slot, false); slot.getValue().add(clonedValueSpec); } } slot.setOwningInstance(instance); } //else if (classifier.getAttribute().contains(property)) { else { final Slot slot = createSlot(property, instance, recurse, traveled); //System.out.println("Created " + slot.getDefiningFeature().getQualifiedName() + " [" + implicitCache.size() + "]"); propertySlotMapping.put(property, slot); implicitCache.put(property, slot); for (final Property redefinedProperty : flattenRedefinedProperties(property)) { implicitCache.put(redefinedProperty, slot); } //System.out.println("New Cache Size: " + implicitCache.size()); } propertyIterator.remove(); } } } return propertySlotMapping; } public static List<Property> flattenRedefinedProperties(final Property property) { final List<Property> redefinedProperties = new ArrayList<Property>(); for (final Property redefinedProperty : property.getRedefinedProperty()) { redefinedProperties.addAll(flattenRedefinedProperties(redefinedProperty)); } return redefinedProperties; } public static Slot createSlot(final Property property, final InstanceSpecification instance, final boolean recurse, final Map<Classifier, InstanceSpecification> traveled) { final Slot slot = Application.getInstance().getProject().getElementsFactory().createSlotInstance(); slot.setDefiningFeature(property); createValueSpecification(property, instance, slot, recurse, traveled); slot.setOwningInstance(instance); return slot; } public static ValueSpecification createValueSpecification(final Property property, final InstanceSpecification instance, final Slot slot, final boolean recurse, final Map<Classifier, InstanceSpecification> traveled) { if (property.getDefaultValue() != null) { final ValueSpecification clonedValue = (ValueSpecification) CopyPasting.copyPasteElement(property.getDefaultValue(), slot, false); slot.getValue().add(clonedValue); return clonedValue; } else if (property.getType() != null && property.getType() instanceof Classifier) { //System.out.println("Nested Instance: " + property.getQualifiedName()); final InstanceSpecification nestedInstance = CreateInstanceAction.createInstance(property, instance, recurse, traveled); if (nestedInstance == null) { //System.out.println("Nested instance is null."); return null; } final InstanceValue instanceValue = Application.getInstance().getProject().getElementsFactory().createInstanceValueInstance(); instanceValue.setInstance(nestedInstance); instanceValue.setOwner(slot); slot.getValue().add(instanceValue); return instanceValue; } return null; } @Override public void run() { if (!instance.isEditable()) { Application.getInstance().getGUILog().log(instance.getQualifiedName() + " is not editable. Skipping slots creation."); return; } createSlots(instance, recurse, deleteSlots, deleteChildInstances, progressStatus); } public void actionPerformed(java.awt.event.ActionEvent e) { super.actionPerformed(e); ValidateAction.validate(instance); } @Override public void execute(Collection<Annotation> annotations) { super.execute(annotations); ValidateAction.validate(instance); } @Override public String getName() { return name; } @Override public String getSessionName() { return name; } }