UmlFactoryMDRImpl.java
/* $Id$
*****************************************************************************
* Copyright (c) 2009-2012 Contributors - see below
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
* http://www.eclipse.org/legal/epl-v10.html
*
* Contributors:
* Bob Tarling
* Luis Sergio Oliveira (euluis)
* Thomas Neustupny
*****************************************************************************
*
* Some portions of this file was previously release using the BSD License:
*/
// Copyright (c) 1996-2009 The Regents of the University of California. All
// Rights Reserved. Permission to use, copy, modify, and distribute this
// software and its documentation without fee, and without a written
// agreement is hereby granted, provided that the above copyright notice
// and this paragraph appear in all copies. This software program and
// documentation are copyrighted by The Regents of the University of
// California. The software program and documentation are supplied "AS
// IS", without any accompanying services from The Regents. The Regents
// does not warrant that the operation of the program will be
// uninterrupted or error-free. The end-user understands that the program
// was developed for research purposes and is advised not to rely
// exclusively on the program for any reason. IN NO EVENT SHALL THE
// UNIVERSITY OF CALIFORNIA BE LIABLE TO ANY PARTY FOR DIRECT, INDIRECT,
// SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES, INCLUDING LOST PROFITS,
// ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN IF
// THE UNIVERSITY OF CALIFORNIA HAS BEEN ADVISED OF THE POSSIBILITY OF
// SUCH DAMAGE. THE UNIVERSITY OF CALIFORNIA SPECIFICALLY DISCLAIMS ANY
// WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
// MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE SOFTWARE
// PROVIDED HEREUNDER IS ON AN "AS IS" BASIS, AND THE UNIVERSITY OF
// CALIFORNIA HAS NO OBLIGATIONS TO PROVIDE MAINTENANCE, SUPPORT,
// UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
package org.argouml.model.mdr;
import java.util.ArrayList;
import java.util.Collection;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.logging.Level;
import java.util.logging.Logger;
import javax.jmi.reflect.InvalidObjectException;
import javax.jmi.reflect.RefObject;
import org.argouml.model.Defaults;
import org.argouml.model.DummyModelCommand;
import org.argouml.model.IllegalModelElementConnectionException;
import org.argouml.model.InvalidElementException;
import org.argouml.model.MetaTypes;
import org.argouml.model.Model;
import org.argouml.model.UmlFactory;
import org.omg.uml.behavioralelements.activitygraphs.ActionState;
import org.omg.uml.behavioralelements.activitygraphs.ActivityGraph;
import org.omg.uml.behavioralelements.activitygraphs.CallState;
import org.omg.uml.behavioralelements.activitygraphs.ClassifierInState;
import org.omg.uml.behavioralelements.activitygraphs.ObjectFlowState;
import org.omg.uml.behavioralelements.activitygraphs.Partition;
import org.omg.uml.behavioralelements.activitygraphs.SubactivityState;
import org.omg.uml.behavioralelements.collaborations.AssociationEndRole;
import org.omg.uml.behavioralelements.collaborations.AssociationRole;
import org.omg.uml.behavioralelements.collaborations.ClassifierRole;
import org.omg.uml.behavioralelements.collaborations.Collaboration;
import org.omg.uml.behavioralelements.collaborations.CollaborationInstanceSet;
import org.omg.uml.behavioralelements.collaborations.Interaction;
import org.omg.uml.behavioralelements.collaborations.InteractionInstanceSet;
import org.omg.uml.behavioralelements.collaborations.Message;
import org.omg.uml.behavioralelements.commonbehavior.Action;
import org.omg.uml.behavioralelements.commonbehavior.ActionSequence;
import org.omg.uml.behavioralelements.commonbehavior.Argument;
import org.omg.uml.behavioralelements.commonbehavior.AttributeLink;
import org.omg.uml.behavioralelements.commonbehavior.CallAction;
import org.omg.uml.behavioralelements.commonbehavior.ComponentInstance;
import org.omg.uml.behavioralelements.commonbehavior.CreateAction;
import org.omg.uml.behavioralelements.commonbehavior.DataValue;
import org.omg.uml.behavioralelements.commonbehavior.DestroyAction;
import org.omg.uml.behavioralelements.commonbehavior.Instance;
import org.omg.uml.behavioralelements.commonbehavior.Link;
import org.omg.uml.behavioralelements.commonbehavior.LinkEnd;
import org.omg.uml.behavioralelements.commonbehavior.LinkObject;
import org.omg.uml.behavioralelements.commonbehavior.NodeInstance;
import org.omg.uml.behavioralelements.commonbehavior.Reception;
import org.omg.uml.behavioralelements.commonbehavior.ReturnAction;
import org.omg.uml.behavioralelements.commonbehavior.SendAction;
import org.omg.uml.behavioralelements.commonbehavior.Signal;
import org.omg.uml.behavioralelements.commonbehavior.Stimulus;
import org.omg.uml.behavioralelements.commonbehavior.SubsystemInstance;
import org.omg.uml.behavioralelements.commonbehavior.TerminateAction;
import org.omg.uml.behavioralelements.commonbehavior.UmlException;
import org.omg.uml.behavioralelements.commonbehavior.UninterpretedAction;
import org.omg.uml.behavioralelements.statemachines.CallEvent;
import org.omg.uml.behavioralelements.statemachines.ChangeEvent;
import org.omg.uml.behavioralelements.statemachines.CompositeState;
import org.omg.uml.behavioralelements.statemachines.Event;
import org.omg.uml.behavioralelements.statemachines.FinalState;
import org.omg.uml.behavioralelements.statemachines.Guard;
import org.omg.uml.behavioralelements.statemachines.Pseudostate;
import org.omg.uml.behavioralelements.statemachines.SignalEvent;
import org.omg.uml.behavioralelements.statemachines.SimpleState;
import org.omg.uml.behavioralelements.statemachines.State;
import org.omg.uml.behavioralelements.statemachines.StateMachine;
import org.omg.uml.behavioralelements.statemachines.StateVertex;
import org.omg.uml.behavioralelements.statemachines.StubState;
import org.omg.uml.behavioralelements.statemachines.SubmachineState;
import org.omg.uml.behavioralelements.statemachines.SynchState;
import org.omg.uml.behavioralelements.statemachines.TimeEvent;
import org.omg.uml.behavioralelements.statemachines.Transition;
import org.omg.uml.behavioralelements.usecases.Actor;
import org.omg.uml.behavioralelements.usecases.Extend;
import org.omg.uml.behavioralelements.usecases.ExtensionPoint;
import org.omg.uml.behavioralelements.usecases.Include;
import org.omg.uml.behavioralelements.usecases.UseCase;
import org.omg.uml.behavioralelements.usecases.UseCaseInstance;
import org.omg.uml.foundation.core.Abstraction;
import org.omg.uml.foundation.core.Artifact;
import org.omg.uml.foundation.core.AssociationClass;
import org.omg.uml.foundation.core.AssociationEnd;
import org.omg.uml.foundation.core.Attribute;
import org.omg.uml.foundation.core.BehavioralFeature;
import org.omg.uml.foundation.core.Binding;
import org.omg.uml.foundation.core.Classifier;
import org.omg.uml.foundation.core.Comment;
import org.omg.uml.foundation.core.Component;
import org.omg.uml.foundation.core.Constraint;
import org.omg.uml.foundation.core.DataType;
import org.omg.uml.foundation.core.Dependency;
import org.omg.uml.foundation.core.Element;
import org.omg.uml.foundation.core.ElementResidence;
import org.omg.uml.foundation.core.Enumeration;
import org.omg.uml.foundation.core.EnumerationLiteral;
import org.omg.uml.foundation.core.Feature;
import org.omg.uml.foundation.core.Flow;
import org.omg.uml.foundation.core.GeneralizableElement;
import org.omg.uml.foundation.core.Generalization;
import org.omg.uml.foundation.core.Interface;
import org.omg.uml.foundation.core.Method;
import org.omg.uml.foundation.core.ModelElement;
import org.omg.uml.foundation.core.Namespace;
import org.omg.uml.foundation.core.Node;
import org.omg.uml.foundation.core.Operation;
import org.omg.uml.foundation.core.Parameter;
import org.omg.uml.foundation.core.Permission;
import org.omg.uml.foundation.core.PresentationElement;
import org.omg.uml.foundation.core.Primitive;
import org.omg.uml.foundation.core.ProgrammingLanguageDataType;
import org.omg.uml.foundation.core.Relationship;
import org.omg.uml.foundation.core.Stereotype;
import org.omg.uml.foundation.core.StructuralFeature;
import org.omg.uml.foundation.core.TagDefinition;
import org.omg.uml.foundation.core.TaggedValue;
import org.omg.uml.foundation.core.TemplateArgument;
import org.omg.uml.foundation.core.TemplateParameter;
import org.omg.uml.foundation.core.UmlAssociation;
import org.omg.uml.foundation.core.UmlClass;
import org.omg.uml.foundation.core.Usage;
import org.omg.uml.modelmanagement.ElementImport;
import org.omg.uml.modelmanagement.Subsystem;
import org.omg.uml.modelmanagement.UmlPackage;
/**
* Root factory for UML model element instance creation.<p>
*
* @since ARGO0.19.5
* @author Ludovic Maître
* based on NSUML implementation by:
* @author Thierry Lach
*/
class UmlFactoryMDRImpl extends AbstractUmlModelFactoryMDR implements
UmlFactory {
/**
* The logger.
*/
private static final Logger LOG =
Logger.getLogger(UmlFactoryMDRImpl.class.getName());
/**
* The model implementation.
*/
private MDRModelImplementation modelImpl;
/**
* The meta types factory.
*/
private MetaTypes metaTypes;
/**
* A map of valid connections keyed by the connection type. The constructor
* builds this from the data in the VALID_CONNECTIONS array
*/
private Map<Class<?>, List<Class<?>[]>> validConnectionMap =
new HashMap<Class<?>, List<Class<?>[]>>();
/**
* A map of the valid model elements that are valid to be contained
* by other model elements.
*/
private HashMap<Class<?>, Class<?>[]> validContainmentMap =
new HashMap<Class<?>, Class<?>[]>();
/**
* The instance that we are deleting.
*/
private Set<RefObject> elementsToBeDeleted = new HashSet<RefObject>();
/**
* Ordered list of elements to be deleted.
*/
private List<RefObject> elementsInDeletionOrder =
new ArrayList<RefObject>();
/**
* The top object is the first object given to the UmlFactory when calling
* the delete method.
*/
private Object top;
/**
* The mutex for this class.
*/
private Object lock = new Byte[0];
/**
* An array of valid connections, the combination of connecting class and
* node classes must exist as a row in this list to be considered valid.
* <ul>
* <li>The 1st column is the connecting element.
* <li>The 2nd column is the "from" element type.
* <li>The 3rd column is the "to" element type.
* The 3rd column is optional, if not given then it is assumed to be
* the same as the "from" element.
* <li>The existence of a 4th column indicates that the connection is valid
* in one direction only.
* </ul>
* TODO: This encodes not only what is legal in UML, but also what ArgoUML
* knows how to create, so not all legal connections are included. Probably
* should be split into two pieces: 1) legal UML (here) and 2) supported (in
* ArgoUML application someplace) - tfm - 20060325<p>
* See also issue 3863.<p>
*
* Most of these are subtypes of Relationship which includes Association,
* Dependency, Flow, Generalization, Extend, and Include. Dependency
* includes Binding, Abstraction, Usage, and Permission. AssociationRole and
* AssociationClass are Associations. The remaining items (Link, Transition,
* AssociationEnd, Message) are non-Relationship types which ArgoUML treats
* as connections/edges.
*/
// TODO: This should be built by reflection from the metamodel - tfm
// Update for UML 1.4 metamodel if not replaced by reflection
private static final Class<?>[][] VALID_CONNECTIONS = {
{Generalization.class, GeneralizableElement.class, },
{Dependency.class, ModelElement.class, },
// Although Usage & Permission are Dependencies, they need to
// be include separately because of the way lookup works
{Usage.class, ModelElement.class, },
{Permission.class, ModelElement.class, },
// The following is specifically for Realizations
{Abstraction.class, UmlClass.class, Interface.class, null, },
// The next 3 restrictions for Abstraction seem to be Argo specific
// not something the UML spec requires - tfm - 20070215
{Abstraction.class, UmlClass.class, UmlClass.class, null, },
{Abstraction.class, UmlPackage.class, UmlPackage.class, null, },
{Abstraction.class, Component.class, Interface.class, null, },
{UmlAssociation.class, Classifier.class, },
{AssociationRole.class, ClassifierRole.class, },
{Extend.class, UseCase.class, },
{Include.class, UseCase.class, },
{Link.class, Instance.class, },
{Transition.class, StateVertex.class, },
{AssociationClass.class, UmlClass.class, },
{AssociationEnd.class, Classifier.class, UmlAssociation.class, },
{Message.class, ClassifierRole.class },
};
/**
* Package-private constructor.
*
* @param implementation
* To get other helpers and factories.
*/
UmlFactoryMDRImpl(MDRModelImplementation implementation) {
modelImpl = implementation;
metaTypes = modelImpl.getMetaTypes();
buildValidConnectionMap();
buildValidContainmentMap();
}
private void buildValidConnectionMap() {
// A list of valid connections between elements, the
// connection type first and then the elements to be connected
for (int i = 0; i < VALID_CONNECTIONS.length; ++i) {
final Class<?> connection = VALID_CONNECTIONS[i][0];
List<Class<?>[]> validItems = validConnectionMap.get(connection);
if (validItems == null) {
validItems = new ArrayList<Class<?>[]>();
validConnectionMap.put(connection, validItems);
}
if (VALID_CONNECTIONS[i].length < 3) {
// If there isn't a 3rd column then this represents a connection
// of elements of the same type.
Class<?>[] modeElementPair = new Class[2];
modeElementPair[0] = VALID_CONNECTIONS[i][1];
modeElementPair[1] = VALID_CONNECTIONS[i][1];
validItems.add(modeElementPair);
} else {
// If there is a 3rd column then this represents a connection
// of between 2 different types of element.
Class<?>[] modeElementPair = new Class[2];
modeElementPair[0] = VALID_CONNECTIONS[i][1];
modeElementPair[1] = VALID_CONNECTIONS[i][2];
validItems.add(modeElementPair);
// If the array hasn't been flagged to indicate otherwise
// swap elements the elements and add again.
if (VALID_CONNECTIONS[i].length < 4) {
Class<?>[] reversedModeElementPair = new Class[2];
reversedModeElementPair[0] = VALID_CONNECTIONS[i][2];
reversedModeElementPair[1] = VALID_CONNECTIONS[i][1];
validItems.add(reversedModeElementPair);
}
}
}
}
/**
* Initializes the validContainmentMap based on the rules for
* valid containment of elements.
*
* @author Scott Roberts
*/
private void buildValidContainmentMap() {
validContainmentMap.clear();
validContainmentMap.put(ModelElement.class,
new Class<?>[] {
TemplateParameter.class
});
// specifies valid elements for a Model to contain
validContainmentMap.put(org.omg.uml.modelmanagement.Model.class,
new Class<?>[] {
TemplateParameter.class,
ComponentInstance.class, NodeInstance.class
});
// specifies valid elements for a Model to contain
validContainmentMap.put(AssociationEnd.class,
new Class<?>[] {
Attribute.class
});
// specifies valid elements for a Package to contain
validContainmentMap.put(UmlPackage.class,
new Class<?>[] {
TemplateParameter.class,
UmlPackage.class, Actor.class,
UseCase.class, UmlClass.class,
Interface.class, Component.class,
Node.class, Stereotype.class,
Enumeration.class, DataType.class,
UmlException.class, Signal.class
});
// specifies valid elements for a class to contain
validContainmentMap.put(UmlClass.class,
new Class<?>[] {
TemplateParameter.class,
Attribute.class, Operation.class,
UmlClass.class, Reception.class
});
// specifies valid elements for a classifier to contain
validContainmentMap.put(Classifier.class,
new Class<?>[] {
TemplateParameter.class
});
// specifies valid elements for an Interface to contain
validContainmentMap.put(Interface.class,
new Class<?>[] {
TemplateParameter.class,
Operation.class, Reception.class
});
// specifies valid elements for a Signal to contain
validContainmentMap.put(Signal.class,
new Class<?>[] {
TemplateParameter.class,
Operation.class, Attribute.class
});
// specifies valid elements for an Actor to contain
validContainmentMap.put(Actor.class,
new Class<?>[] {
TemplateParameter.class,
Operation.class,
Reception.class
});
// specifies valid elements for a Use Case to contain
validContainmentMap.put(UseCase.class,
new Class<?>[] {
TemplateParameter.class,
ExtensionPoint.class, Attribute.class,
Operation.class, Reception.class
});
// specifies valid elements for a Use Case to contain
validContainmentMap.put(Extend.class,
new Class<?>[] {
TemplateParameter.class,
ExtensionPoint.class
});
// specifies valid elements for a Component to contain
validContainmentMap.put(Component.class,
new Class<?>[] {
TemplateParameter.class,
Reception.class,
Operation.class
});
// specifies valid elements for a Node to contain
validContainmentMap.put(Node.class,
new Class<?>[] {
TemplateParameter.class,
Operation.class,
Reception.class
});
// specifies valid elements for a Enumeration to contain
validContainmentMap.put(Enumeration.class,
new Class<?>[] {
TemplateParameter.class,
EnumerationLiteral.class, Operation.class
});
// specifies valid elements for a DataType to contain
validContainmentMap.put(DataType.class,
new Class<?>[] {
TemplateParameter.class,
Operation.class,
Reception.class
});
// specifies valid elements for a Operation to contain
validContainmentMap.put(Operation.class,
new Class<?>[] {
TemplateParameter.class,
Parameter.class,
Signal.class,
Method.class
});
// specifies valid elements for an Event to contain
validContainmentMap.put(Event.class,
new Class<?>[] {
TemplateParameter.class,
Parameter.class
});
// specifies valid elements for an ObjectFlowState to contain
validContainmentMap.put(ObjectFlowState.class,
new Class<?>[] {
TemplateParameter.class,
Parameter.class
});
// specifies valid elements for an AssociationRole to contain
validContainmentMap.put(AssociationRole.class,
new Class<?>[] {
TemplateParameter.class,
Message.class
});
// specifies valid elements for an AssociationRole to contain
validContainmentMap.put(CallAction.class,
new Class<?>[] {
TemplateParameter.class,
Argument.class
});
// specifies valid elements for an AssociationRole to contain
validContainmentMap.put(UninterpretedAction.class,
new Class<?>[] {
TemplateParameter.class,
Argument.class
});
// specifies valid elements for an AssociationRole to contain
validContainmentMap.put(ReturnAction.class,
new Class<?>[] {
TemplateParameter.class,
Argument.class
});
// specifies valid elements for an AssociationRole to contain
validContainmentMap.put(DestroyAction.class,
new Class<?>[] {
TemplateParameter.class,
Argument.class
});
// specifies valid elements for an AssociationRole to contain
validContainmentMap.put(SendAction.class,
new Class<?>[] {
TemplateParameter.class,
Argument.class
});
// specifies valid elements for an AssociationRole to contain
validContainmentMap.put(TerminateAction.class,
new Class<?>[] {
TemplateParameter.class,
Argument.class
});
// specifies valid elements for an AssociationRole to contain
validContainmentMap.put(ActionSequence.class,
new Class<?>[] {
TemplateParameter.class, Argument.class,
CallAction.class, ReturnAction.class, CreateAction.class,
DestroyAction.class, SendAction.class,
TerminateAction.class, UninterpretedAction.class,
ActionSequence.class,
});
// specifies valid elements for an AssociationRole to contain
validContainmentMap.put(Transition.class,
new Class<?>[] {
TemplateParameter.class,
Guard.class,
CallAction.class, ReturnAction.class,
CreateAction.class, DestroyAction.class, SendAction.class, TerminateAction.class, UninterpretedAction.class, ActionSequence.class,
CallEvent.class, ChangeEvent.class, SignalEvent.class, TimeEvent.class
});
// specifies valid elements for an AssociationRole to contain
validContainmentMap.put(SignalEvent.class,
new Class<?>[] {
Signal.class
});
// specifies valid elements for an AssociationRole to contain
validContainmentMap.put(Reception.class,
new Class<?>[] {
Parameter.class,
TemplateParameter.class
});
// specifies valid elements for an State to contain
validContainmentMap.put(State.class,
new Class<?>[] {
CallEvent.class, ChangeEvent.class, SignalEvent.class,
TimeEvent.class
});
// specifies valid elements for an CallState to contain
validContainmentMap.put(CallState.class,
new Class<?>[] {
CallAction.class,
CallEvent.class, ChangeEvent.class, SignalEvent.class,
TimeEvent.class
});
// specifies valid elements for an SimpleState to contain
validContainmentMap.put(SimpleState.class,
new Class<?>[] {
Transition.class,
CallAction.class, CreateAction.class, DestroyAction.class,
ReturnAction.class, SendAction.class,
TerminateAction.class,
UninterpretedAction.class, ActionSequence.class,
CallEvent.class, ChangeEvent.class, SignalEvent.class,
TimeEvent.class
});
// specifies valid elements for an SimpleState to contain
validContainmentMap.put(FinalState.class,
new Class<?>[] {
Transition.class,
CallAction.class, CreateAction.class, DestroyAction.class,
ReturnAction.class, SendAction.class, TerminateAction.class,
UninterpretedAction.class, ActionSequence.class
});
// specifies valid elements for an SubactivityState to contain
validContainmentMap.put(SubactivityState.class,
new Class<?>[] {
Transition.class,
CallAction.class, CreateAction.class, DestroyAction.class,
ReturnAction.class, SendAction.class, TerminateAction.class,
UninterpretedAction.class, ActionSequence.class,
CallEvent.class, ChangeEvent.class, SignalEvent.class,
TimeEvent.class
});
// specifies valid elements for an ActionState to contain
validContainmentMap.put(ActionState.class,
new Class<?>[] {
CallAction.class, CreateAction.class, DestroyAction.class,
ReturnAction.class, SendAction.class, TerminateAction.class,
UninterpretedAction.class, ActionSequence.class,
CallEvent.class, ChangeEvent.class, SignalEvent.class,
TimeEvent.class
});
// specifies valid elements for an ActionState to contain
validContainmentMap.put(CompositeState.class,
new Class<?>[] {
Transition.class,
Pseudostate.class, SynchState.class, StubState.class,
CompositeState.class, SimpleState.class,
FinalState.class,
SubmachineState.class,
CallAction.class, CreateAction.class, DestroyAction.class,
ReturnAction.class, SendAction.class,
TerminateAction.class,
UninterpretedAction.class, ActionSequence.class
});
}
public Object buildConnection(Object elementType, Object fromElement,
Object fromStyle, Object toElement, Object toStyle,
Object unidirectional, Object namespace)
throws IllegalModelElementConnectionException {
if (!isConnectionValid(elementType, fromElement, toElement, true)) {
throw new IllegalModelElementConnectionException("Cannot make a "
+ elementType.getClass().getName() + " between a "
+ fromElement.getClass().getName() + " and a "
+ toElement.getClass().getName());
}
Object connection = null;
boolean uni = (unidirectional instanceof Boolean)
? ((Boolean) unidirectional).booleanValue() : false;
if (elementType == metaTypes.getAssociation()) {
connection =
getCore().buildAssociation(fromElement,
fromStyle, toElement,
toStyle, uni);
} else if (elementType == metaTypes.getAssociationEnd()) {
if (fromElement instanceof UmlAssociation) {
connection =
getCore().buildAssociationEnd(toElement, fromElement);
} else if (fromElement instanceof Classifier) {
connection =
getCore().buildAssociationEnd(fromElement, toElement);
}
} else if (elementType
== metaTypes.getAssociationClass()) {
connection =
getCore().buildAssociationClass(fromElement, toElement);
} else if (elementType == metaTypes.getAssociationRole()) {
connection =
getCollaborations().buildAssociationRole(fromElement,
fromStyle, toElement, toStyle,
((Boolean) unidirectional).booleanValue());
} else if (elementType == metaTypes.getGeneralization()) {
connection = getCore().buildGeneralization(fromElement, toElement);
} else if (elementType == metaTypes.getPackageImport()) {
connection = getCore().buildPackageImport(fromElement, toElement);
} else if (elementType == metaTypes.getUsage()) {
connection = getCore().buildUsage(fromElement, toElement);
} else if (elementType == metaTypes.getGeneralization()) {
connection = getCore().buildGeneralization(fromElement, toElement);
} else if (elementType == metaTypes.getDependency()) {
connection = getCore().buildDependency(fromElement, toElement);
} else if (elementType == metaTypes.getAbstraction()) {
connection =
getCore().buildRealization(fromElement, toElement, namespace);
} else if (elementType == metaTypes.getLink()) {
connection = getCommonBehavior().buildLink(fromElement, toElement);
} else if (elementType == metaTypes.getExtend()) {
// Extend, but only between two use cases. Remember we draw from the
// extension port to the base port.
connection = getUseCases().buildExtend(toElement, fromElement);
} else if (elementType == metaTypes.getInclude()) {
connection = getUseCases().buildInclude(fromElement, toElement);
} else if (elementType == metaTypes.getTransition()) {
connection =
getStateMachines().buildTransition(fromElement, toElement);
}
if (connection == null) {
throw new IllegalModelElementConnectionException("Cannot make a "
+ elementType.getClass().getName() + " between a "
+ fromElement.getClass().getName() + " and a "
+ toElement.getClass().getName());
}
return connection;
}
public Object buildNode(Object elementType) {
if (elementType == metaTypes.getActor()) {
return getUseCases().createActor();
} else if (elementType == metaTypes.getUseCase()) {
return getUseCases().createUseCase();
} else if (elementType == metaTypes.getUMLClass()) {
return getCore().buildClass();
} else if (elementType == metaTypes.getInterface()) {
return getCore().buildInterface();
} else if (elementType == metaTypes.getDataType()) {
return getCore().createDataType();
} else if (elementType == metaTypes.getPackage()) {
return getModelManagement().createPackage();
} else if (elementType == metaTypes.getModel()) {
return getModelManagement().createModel();
} else if (elementType == metaTypes.getInstance()) {
throw new IllegalArgumentException(
"Attempt to instantiate abstract type");
} else if (elementType == metaTypes.getSubsystem()) {
return getModelManagement().createSubsystem();
} else if (elementType == metaTypes.getCallState()) {
return getActivityGraphs().createCallState();
} else if (elementType == metaTypes.getSimpleState()) {
return getStateMachines().createSimpleState();
} else if (elementType == metaTypes.getFinalState()) {
return getStateMachines().createFinalState();
} else if (elementType == metaTypes.getPseudostate()) {
return getStateMachines().createPseudostate();
} else if (elementType == metaTypes.getObjectFlowState()) {
return getActivityGraphs().createObjectFlowState();
} else if (elementType == metaTypes.getActionState()) {
return getActivityGraphs().createActionState();
} else if (elementType == metaTypes.getSubactivityState()) {
return getActivityGraphs().createSubactivityState();
} else if (elementType == metaTypes.getPartition()) {
return getActivityGraphs().createPartition();
} else if (elementType == metaTypes.getStubState()) {
return getStateMachines().createStubState();
} else if (elementType == metaTypes.getSubmachineState()) {
return getStateMachines().createSubmachineState();
} else if (elementType == metaTypes.getCompositeState()) {
return getStateMachines().createCompositeState();
} else if (elementType == metaTypes.getSynchState()) {
return getStateMachines().createSynchState();
} else if (elementType == metaTypes.getState()) {
throw new IllegalArgumentException(
"Attempt to instantiate abstract type");
} else if (elementType == modelImpl.getMetaTypes().getSimpleState()) {
return getStateMachines().createSimpleState();
} else if (elementType == metaTypes.getClassifierRole()) {
return getCollaborations().createClassifierRole();
} else if (elementType == metaTypes.getComponent()) {
return getCore().createComponent();
} else if (elementType == metaTypes.getComponentInstance()) {
return getCommonBehavior().createComponentInstance();
} else if (elementType == metaTypes.getNode()) {
return getCore().createNode();
} else if (elementType == metaTypes.getNodeInstance()) {
return getCommonBehavior().createNodeInstance();
} else if (elementType == metaTypes.getObject()) {
return getCommonBehavior().createObject();
} else if (elementType == metaTypes.getComment()) {
return getCore().createComment();
} else if (elementType == metaTypes.getNamespace()) {
throw new IllegalArgumentException(
"Attempt to instantiate abstract type");
} else if (elementType == metaTypes.getOperation()) {
return getCore().createOperation();
} else if (elementType == metaTypes.getEnumeration()) {
return getCore().createEnumeration();
} else if (elementType == metaTypes.getStereotype()) {
return getExtensionMechanisms().createStereotype();
} else if (elementType == metaTypes.getAttribute()) {
return getCore().buildAttribute();
} else if (elementType == metaTypes.getSignal()) {
return getCommonBehavior().createSignal();
} else if (elementType == metaTypes.getException()) {
return getCommonBehavior().createException();
} else if (elementType == metaTypes.getTransition()) {
return getStateMachines().createTransition();
} else if (elementType == metaTypes.getTransition()) {
return getStateMachines().createTransition();
}
throw new IllegalArgumentException(
"Attempted to create unsupported model element type: "
+ elementType);
}
public Object buildNode(Object elementType, Object container, String property, Defaults defaults) {
Object element = buildNode(elementType, container, property);
if (defaults != null) {
final Object type = defaults.getDefaultType(elementType);
final String name = defaults.getDefaultName(elementType);
if (type != null) {
modelImpl.getCoreHelper().setType(element, type);
}
if (name != null) {
modelImpl.getCoreHelper().setName(element, name);
} else {
modelImpl.getCoreHelper().setName(element, "");
}
}
return element;
}
public Object buildNode(Object elementType, Object container, String properyName) {
Object element = null;
// if this is a feature get the owner of that feature
// TODO: Does anything actually make use of this? It can
// cause unexpected behaviour.
if (this.modelImpl.getFacade().isAFeature(container)
&& elementType != metaTypes.getParameter()
&& elementType != metaTypes.getMethod()
&& elementType != metaTypes.getSignal()) {
container = this.modelImpl.getFacade().getOwner(container);
}
// supports implementation of some special elements not
// supported by buildNode
if (elementType == this.metaTypes.getAttribute()) {
element = getCore().buildAttribute2(container, null);
} else if (elementType == this.metaTypes.getOperation()) {
element = getCore().buildOperation(container, null);
} else if (elementType == this.metaTypes.getReception()) {
element = this.modelImpl.getCommonBehaviorFactory().buildReception(container);
} else if (elementType == this.metaTypes.getEnumerationLiteral()) {
element = getCore().buildEnumerationLiteral(null, container);
} else if (elementType == this.metaTypes.getExtensionPoint()) {
element = this.modelImpl.getUseCasesFactory().
buildExtensionPoint(container);
} else if (elementType == this.metaTypes.getTemplateParameter()) {
// TODO: the type of the model element used in a type parameter
// (ie the formal) needs to match the actual parameter that it
// gets replaced with later. This code is going to restrict that
// to always being a Parameter which doesn't seem right, but I
// don't have time to debug it right now. - tfm - 20090608
Parameter param = getCore().createParameter();
param.setName("T"); // default parameter name
element =
modelImpl.getCoreFactory().buildTemplateParameter(container,
param, null);
} else if (elementType == metaTypes.getParameter()) {
element = getCore().buildParameter(container, null);
} else if (elementType == metaTypes.getSignal()) {
element = modelImpl.getCommonBehaviorFactory().buildSignal(container);
} else if (elementType == metaTypes.getMethod()) {
final Operation op = (Operation) container;
element = getCore().buildMethod(op.getName());
modelImpl.getCoreHelper().addMethod(op, element);
modelImpl.getCoreHelper().addFeature(
modelImpl.getFacade().getOwner(op), element);
} else if (elementType == metaTypes.getMessage()) {
Object collaboration = Model.getFacade().getNamespace(container);
element =
Model.getCollaborationsFactory()
.buildMessage(collaboration, container);
} else if (elementType == metaTypes.getArgument()) {
element = Model.getCommonBehaviorFactory().createArgument();
Model.getCommonBehaviorHelper().addActualArgument(container, element);
} else if (elementType == metaTypes.getGuard()) {
element = Model.getStateMachinesFactory().buildGuard(container);
} else if (elementType == metaTypes.getCreateAction()) {
element = Model.getCommonBehaviorFactory().createCreateAction();
setNewAction(container, (Action) element, properyName);
} else if (elementType == metaTypes.getCallAction()) {
element = Model.getCommonBehaviorFactory().createCallAction();
setNewAction(container, (Action) element, properyName);
} else if (elementType == metaTypes.getReturnAction()) {
element = Model.getCommonBehaviorFactory().createReturnAction();
setNewAction(container, (Action) element, properyName);
} else if (elementType == metaTypes.getDestroyAction()) {
element = Model.getCommonBehaviorFactory().createDestroyAction();
setNewAction(container, (Action) element, properyName);
} else if (elementType == metaTypes.getSendAction()) {
element = Model.getCommonBehaviorFactory().createSendAction();
setNewAction(container, (Action) element, properyName);
} else if (elementType == metaTypes.getTerminateAction()) {
element = Model.getCommonBehaviorFactory().createTerminateAction();
setNewAction(container, (Action) element, properyName);
} else if (elementType == metaTypes.getUninterpretedAction()) {
element = Model.getCommonBehaviorFactory().createUninterpretedAction();
setNewAction(container, (Action) element, properyName);
} else if (elementType == metaTypes.getActionSequence()) {
element = Model.getCommonBehaviorFactory().createActionSequence();
setNewAction(container, (Action) element, properyName);
} else if (elementType == metaTypes.getCallEvent()) {
element = Model.getStateMachinesFactory().createCallEvent();
if (container instanceof Transition) {
setNewTrigger((Transition) container, (Event) element);
} else if (container instanceof State) {
setNewDeferrableEvent((State) container, (Event) element);
}
} else if (elementType == metaTypes.getChangeEvent()) {
element = Model.getStateMachinesFactory().createChangeEvent();
if (container instanceof Transition) {
setNewTrigger((Transition) container, (Event) element);
} else if (container instanceof State) {
setNewDeferrableEvent((State) container, (Event) element);
}
} else if (elementType == metaTypes.getSignalEvent()) {
element = Model.getStateMachinesFactory().createSignalEvent();
if (container instanceof Transition) {
setNewTrigger((Transition) container, (Event) element);
} else if (container instanceof State) {
setNewDeferrableEvent((State) container, (Event) element);
}
} else if (elementType == metaTypes.getTimeEvent()) {
element = Model.getStateMachinesFactory().createTimeEvent();
if (container instanceof Transition) {
setNewTrigger((Transition) container, (Event) element);
} else if (container instanceof State) {
setNewDeferrableEvent((State) container, (Event) element);
}
} else if (elementType == metaTypes.getSignal()) {
element = Model.getStateMachinesFactory().buildSignalEvent(container);
} else if (elementType == metaTypes.getPseudostate() && container instanceof CompositeState) {
element = Model.getStateMachinesFactory().buildPseudoState(container);
} else if (elementType == metaTypes.getSynchState() && container instanceof CompositeState) {
element = Model.getStateMachinesFactory().buildSynchState(container);
} else if (elementType == metaTypes.getStubState() && container instanceof CompositeState) {
element = Model.getStateMachinesFactory().buildStubState(container);
} else if (elementType == metaTypes.getCompositeState() && container instanceof CompositeState) {
element = Model.getStateMachinesFactory().buildCompositeState(container);
} else if (elementType == metaTypes.getSimpleState() && container instanceof CompositeState) {
element = Model.getStateMachinesFactory().buildSimpleState(container);
} else if (elementType == metaTypes.getFinalState() && container instanceof CompositeState) {
element = Model.getStateMachinesFactory().buildFinalState(container);
} else if (elementType == metaTypes.getSubmachineState() && container instanceof CompositeState) {
element = Model.getStateMachinesFactory().buildSubmachineState(container);
} else if (elementType == metaTypes.getTransition() && container instanceof State) {
element = Model.getStateMachinesFactory().buildInternalTransition(container);
} else if (elementType == metaTypes.getActivity()) {
element = Model.getActivityGraphsFactory().buildActivityGraph(container);
} else {
// build all other elements using existing buildNode
element = buildNode(elementType);
if (container instanceof Namespace
&& element instanceof Namespace) {
((Namespace) element).setNamespace(
((Namespace) container).getNamespace());
}
this.modelImpl.getCoreHelper().addOwnedElement(container, element);
}
modelImpl.getCoreHelper().setName(element, "");
return element;
}
private void setNewAction(Object container, Action action, String propertyName) {
if (container instanceof Transition) {
((Transition) container).setEffect(action);
} else if (container instanceof State) {
if ("exit".equals(propertyName)) {
((State) container).setExit(action);
} else if ("doActivity".equals(propertyName)) {
((State) container).setDoActivity(action);
} else {
((State) container).setEntry(action);
}
} else if (container instanceof ActionSequence) {
((ActionSequence) container).getAction().add(action);
} else {
throw new IllegalArgumentException("Did not expect a " + container);
}
}
public Object buildNode(Object elementType, Object container) {
return buildNode(elementType, container, (String) null);
}
/**
* Add a newly created event to a trigger
* @param transition
* @param event
*/
private void setNewTrigger(Transition transition, Event event) {
transition.setTrigger(event);
event.setName("");
final StateMachine statemachine = transition.getStateMachine();
final Namespace namespace = statemachine.getNamespace();
event.setNamespace(namespace);
}
/**
* Add a newly created event to a trigger
* @param transition
* @param event
*/
private void setNewDeferrableEvent(final State state, final Event event) {
((State) state).getDeferrableEvent().add((Event) event);
event.setName("");
Object parent = state;
do {
parent = ((RefObject) parent).refImmediateComposite();
} while (!(parent instanceof Namespace));
event.setNamespace((Namespace) parent);
}
public boolean isConnectionType(Object connectionType) {
// If our map has any entries for this type, it's a connection type
return (validConnectionMap.get(connectionType) != null);
}
public boolean isConnectionValid(Object connectionType, Object fromElement,
Object toElement, boolean checkWFR) {
if (Model.getModelManagementHelper().isReadOnly(fromElement)) {
// Don't allow connections to be created from a read only
// model element to any other
// TODO: This should be considered a workaround. It only works
// because, by default, we place newly created relationships in
// the namespace of the fromElement. The correct behavior in
// the presence of read-only elements really depends on the type of
// connection as well as the writeability of both ends.
return false;
}
// Get the list of valid model item pairs for the given connection type
List<Class<?>[]> validItems = validConnectionMap.get(connectionType);
if (validItems == null) {
return false;
}
// See if there's a pair in this list that match the given
// model elements
for (Class<?>[] modeElementPair : validItems) {
if (modeElementPair[0].isInstance(fromElement)
&& modeElementPair[1].isInstance(toElement)) {
if (checkWFR) {
return isConnectionWellformed(
(Class<?>) connectionType,
(ModelElement) fromElement,
(ModelElement) toElement);
} else {
return true;
}
}
}
return false;
}
public boolean isContainmentValid(Object metaType, Object container) {
// find the passed in container in validContainmentMap
for (Class<?> containerType : validContainmentMap.keySet()) {
if (containerType.isInstance(container)) {
// determine if metaType is a valid element for container
Class<?>[] validElements =
validContainmentMap.get(containerType);
for (int eIter = 0; eIter < validElements.length; ++eIter) {
if (metaType == validElements[eIter]) {
return true;
}
}
}
}
return false;
}
/**
* Run through any well formedness rules we wish to enforce for a
* connection.
* @param connectionType
* @param fromElement
* @param toElement
* @return true if the connection satisfies the wellformedness rules
*/
private boolean isConnectionWellformed(
Class<?> connectionType,
ModelElement fromElement,
ModelElement toElement) {
if (fromElement == null || toElement == null) {
return false;
}
if (connectionType == Generalization.class) {
/*
* UML 1.4.2 Spec section 4.5.3.20 [5]
* A GeneralizableElement may only be a child of
* GeneralizableElement of the same kind.
*/
if (fromElement.getClass() != toElement.getClass()) {
return false;
}
}
return true;
}
/**
* Returns the package factory for the UML package
* Foundation::ExtensionMechanisms.
*
* @return the ExtensionMechanisms factory instance.
*/
private ExtensionMechanismsFactoryMDRImpl getExtensionMechanisms() {
return (ExtensionMechanismsFactoryMDRImpl) modelImpl.
getExtensionMechanismsFactory();
}
/**
* Returns the package factory for the UML package Foundation::Core.
*
* @return the Core factory instance.
*/
private CoreFactoryMDRImpl getCore() {
return (CoreFactoryMDRImpl) modelImpl.getCoreFactory();
}
/**
* Returns the package factory for the UML package
* BehavioralElements::CommonBehavior.
*
* @return the CommonBehavior factory instance.
*/
private CommonBehaviorFactoryMDRImpl getCommonBehavior() {
return (CommonBehaviorFactoryMDRImpl) modelImpl.
getCommonBehaviorFactory();
}
/**
* Returns the package factory for the UML package
* BehavioralElements::UseCases.
*
* @return the UseCases factory instance.
*/
private UseCasesFactoryMDRImpl getUseCases() {
return (UseCasesFactoryMDRImpl) modelImpl.getUseCasesFactory();
}
/**
* Returns the package factory for the UML package
* BehavioralElements::StateMachines.
*
* @return the StateMachines factory instance.
*/
private StateMachinesFactoryMDRImpl getStateMachines() {
return (StateMachinesFactoryMDRImpl) modelImpl
.getStateMachinesFactory();
}
/**
* Returns the package factory for the UML package
* BehavioralElements::Collaborations.
*
* @return the Collaborations factory instance.
*/
private CollaborationsFactoryMDRImpl getCollaborations() {
return (CollaborationsFactoryMDRImpl) modelImpl.
getCollaborationsFactory();
}
/**
* Returns the package factory for the UML package
* BehavioralElements::ActivityGraphs.
*
* @return the ActivityGraphs factory instance.
*/
private ActivityGraphsFactoryMDRImpl getActivityGraphs() {
return (ActivityGraphsFactoryMDRImpl) modelImpl.
getActivityGraphsFactory();
}
/**
* Returns the package factory for the UML package ModelManagement.
*
* @return the ModelManagement factory instance.
*/
private ModelManagementFactoryMDRImpl getModelManagement() {
return (ModelManagementFactoryMDRImpl) modelImpl.
getModelManagementFactory();
}
/*
* Delete a model element. Implements 'cascading delete' to make sure
* model is still valid after element has been deleted.<p>
*
* The actual deletion is delegated to delete methods in the rest of the
* factories. For example: a method deleteClass exists on CoreHelper. Delete
* methods as deleteClass should only do those extra actions that are
* necessary for the deletion of the modelelement itself. I.e. deleteClass
* should only take care of things specific to UmlClass.<p>
*
* The delete methods in the UML Factories should not be called directly
* throughout the code! Calls should always refer to this method and never
* call the deleteXXX method on XXXFactory directly. The reason that it is
* possible to call the deleteXXX methods directly is a pure implementation
* detail.<p>
*
* The implementation of this method uses a quite complicated if/then/else
* tree. This is done to provide optimal performance and full compliance to
* the UML 1.4 metamodel. The last remark refers to the fact that the
* UML 1.4 model uses multiple inheritance in several places.
* This has to be taken into account.<p>
*
* TODO: The requirements of the metamodel could probably be better
* determined by reflection on the metamodel. Then each association
* that a deleted element participates in could be reviewed to make sure
* that it meets the requirements and, if not, be deleted. - tfm<p>
*
* Extensions and its children are not taken into account here. They do not
* require extra cleanup actions. Not in the form of a call to the remove
* method as is normal for all children of MBase and not in the form of
* other behaviour we want to implement via this operation.
*
* @param elem
* The element to be deleted
*
* @see org.argouml.model.UmlFactory#delete(java.lang.Object)
*/
public void delete(Object elem) {
if (elem == null) {
throw new IllegalArgumentException("Element may not be null "
+ "in delete");
}
// TODO: Hold lock for entire recursive traversal?
synchronized (lock) {
if (elementsToBeDeleted.contains(elem)) {
return;
}
if (top == null) {
top = elem;
}
elementsToBeDeleted.add((RefObject) elem);
}
if (top == elem) {
LOG.log(Level.FINE, "Set top for cascade delete to {0}", elem);
}
LOG.log(Level.FINE, "Deleting {0}", elem);
// Begin a transaction - we'll do a bunch of reads first
// to collect a set of elements to delete - then delete them all
modelImpl.getRepository().beginTrans(false);
try {
// TODO: Encountering a deleted object during
// any part of this traversal will
// abort the rest of the traversal.
// We probably should do the whole traversal
// in a single MDR transaction.
if (elem instanceof Element) {
getCore().deleteElement(elem);
if (elem instanceof ModelElement) {
getCore().deleteModelElement(elem);
// no else here to make sure Classifier with
// its double inheritance goes ok
if (elem instanceof GeneralizableElement) {
GeneralizableElement ge = (GeneralizableElement) elem;
getCore().deleteGeneralizableElement(ge);
if (elem instanceof Stereotype) {
Stereotype s = (Stereotype) elem;
getExtensionMechanisms().deleteStereotype(s);
}
} // no else here to make sure AssociationClass goes ok
if (elem instanceof Parameter) {
getCore().deleteParameter(elem);
} else if (elem instanceof Constraint) {
getCore().deleteConstraint(elem);
} else if (elem instanceof Relationship) {
deleteRelationship((Relationship) elem);
} else if (elem instanceof AssociationEnd) {
getCore().deleteAssociationEnd(elem);
if (elem instanceof AssociationEndRole) {
getCollaborations().deleteAssociationEndRole(elem);
}
} else if (elem instanceof Comment) {
getCore().deleteComment(elem);
} else if (elem instanceof Action) {
deleteAction(elem);
} else if (elem instanceof AttributeLink) {
getCommonBehavior().deleteAttributeLink(elem);
} else if (elem instanceof Instance) {
deleteInstance((Instance) elem);
} else if (elem instanceof Stimulus) {
getCommonBehavior().deleteStimulus(elem);
} // no else to handle multiple inheritance of linkobject
if (elem instanceof Link) {
getCommonBehavior().deleteLink(elem);
} else if (elem instanceof LinkEnd) {
getCommonBehavior().deleteLinkEnd(elem);
} else if (elem instanceof Interaction) {
getCollaborations().deleteInteraction(elem);
} else if (elem instanceof InteractionInstanceSet) {
getCollaborations().deleteInteractionInstanceSet(elem);
} else if (elem instanceof CollaborationInstanceSet) {
getCollaborations()
.deleteCollaborationInstanceSet(elem);
} else if (elem instanceof Message) {
getCollaborations().deleteMessage(elem);
} else if (elem instanceof ExtensionPoint) {
getUseCases().deleteExtensionPoint(elem);
} else if (elem instanceof StateVertex) {
deleteStateVertex((StateVertex) elem);
}
if (elem instanceof StateMachine) {
getStateMachines().deleteStateMachine(elem);
if (elem instanceof ActivityGraph) {
getActivityGraphs().deleteActivityGraph(elem);
}
} else if (elem instanceof Transition) {
getStateMachines().deleteTransition(elem);
} else if (elem instanceof Guard) {
getStateMachines().deleteGuard(elem);
} else if (elem instanceof TaggedValue) {
getExtensionMechanisms().deleteTaggedValue(elem);
} else if (elem instanceof TagDefinition) {
getExtensionMechanisms().deleteTagDefinition(elem);
}
// else if (elem instanceof MEvent) {
//
// }
} else if (elem instanceof PresentationElement) {
getCore().deletePresentationElement(elem);
}
} else if (elem instanceof TemplateParameter) {
getCore().deleteTemplateParameter(elem);
} else if (elem instanceof TemplateArgument) {
getCore().deleteTemplateArgument(elem);
} else if (elem instanceof ElementImport) {
getModelManagement().deleteElementImport(elem);
} else if (elem instanceof ElementResidence) {
getCore().deleteElementResidence(elem);
}
if (elem instanceof Partition) {
getActivityGraphs().deletePartition(elem);
}
if (elem instanceof Feature) {
deleteFeature((Feature) elem);
} else if (elem instanceof Namespace) {
deleteNamespace((Namespace) elem);
}
} catch (InvalidObjectException e) {
// If we get this with the repository locked, it means our root
// model element was already deleted. Nothing to do...
LOG.log(Level.SEVERE, "Encountered deleted object during delete of " + elem);
} catch (InvalidElementException e) {
// Our wrapped version of the same error
LOG.log(Level.SEVERE, "Encountered deleted object during delete of " + elem);
} finally {
// end our transaction
modelImpl.getRepository().endTrans();
}
synchronized (lock) {
// Elements which will be deleted when their container is deleted
// don't get added to the list of elements to be deleted
// (but we still want to traverse them looking for other elements
// to be deleted)
try {
Object container = ((RefObject) elem).refImmediateComposite();
if (container == null
|| !elementsToBeDeleted.contains(container)
// There is a bug in the version of MDR (20050711) that
// we use that causes it to fail to delete aggregate
// elements which are single valued and where the
// aggregate end is listed second in the association
// defined in the metamodel. For the UML 1.4 metamodel,
// this affects a StateMachine's top StateVertex and
// a Transition's Guard. See issue 4948 & 5227 - tfm
// 20080713
|| (container instanceof StateMachine
&& elem instanceof StateVertex)
|| (container instanceof Transition
&& elem instanceof Guard)) {
elementsInDeletionOrder.add((RefObject) elem);
}
} catch (InvalidObjectException e) {
LOG.log(Level.FINE, "Object already deleted {0}", elem);
}
if (elem == top) {
for (RefObject o : elementsInDeletionOrder) {
// TODO: This doesn't belong here, but it's not a good time
// to move it. Find someplace less obtrusive than this
// inner loop. - tfm
if (o instanceof CompositeState) {
// This enforces the following well-formedness rule.
// <p>Well formedness rule 4.12.3.1 CompositeState
// [4] There have to be at least two composite
// substates in a concurrent composite state.<p>
// If this is broken by deletion of substate then we
// change the parent composite substate to be not
// concurrent.
CompositeState deletedCompositeState =
(CompositeState) o;
try {
CompositeState containingCompositeState =
deletedCompositeState.getContainer();
if (containingCompositeState != null
&& containingCompositeState.
isConcurrent()
&& containingCompositeState.getSubvertex().
size() == 1) {
containingCompositeState.setConcurrent(false);
}
} catch (InvalidObjectException e) {
LOG.log(Level.FINE, "Object already deleted {0}", o);
}
}
try {
o.refDelete();
} catch (InvalidObjectException e) {
LOG.log(Level.FINE, "Object already deleted {0}", o);
}
elementsToBeDeleted.remove(o);
}
top = null;
elementsInDeletionOrder.clear();
if (!elementsToBeDeleted.isEmpty()) {
LOG.log(Level.FINE, "**Skipped deleting {0} elements (probably in a deleted container", elementsToBeDeleted.size());
elementsToBeDeleted.clear();
}
}
}
Model.execute(new DummyModelCommand());
}
public boolean isRemoved(Object o) {
if (!(o instanceof RefObject)) {
throw new IllegalArgumentException(
"Expected JMI RefObject, received " + o);
}
try {
// We don't care about the value - just want to see if it throws
((RefObject) o).refImmediateComposite();
return false;
} catch (InvalidObjectException e) {
return true;
}
}
/**
* Delete a Feature.
*
* @param elem feature to be deleted
*/
private void deleteFeature(Feature elem) {
getCore().deleteFeature(elem);
if (elem instanceof BehavioralFeature) {
getCore().deleteBehavioralFeature(elem);
if (elem instanceof Operation) {
getCore().deleteOperation(elem);
} else if (elem instanceof Method) {
getCore().deleteMethod(elem);
} else if (elem instanceof Reception) {
getCommonBehavior().deleteReception(elem);
}
} else if (elem instanceof StructuralFeature) {
getCore().deleteStructuralFeature(elem);
if (elem instanceof Attribute) {
getCore().deleteAttribute(elem);
}
}
}
/**
* Delete a Namespace.
*
* @param elem namespace to be deleted
*/
private void deleteNamespace(Namespace elem) {
getCore().deleteNamespace(elem);
if (elem instanceof Classifier) {
getCore().deleteClassifier(elem);
if (elem instanceof UmlClass) {
getCore().deleteClass(elem);
if (elem instanceof AssociationClass) {
getCore().deleteAssociationClass(elem);
}
} else if (elem instanceof Interface) {
getCore().deleteInterface(elem);
} else if (elem instanceof DataType) {
getCore().deleteDataType(elem);
if (elem instanceof Primitive) {
getCore().deletePrimitive(elem);
} else if (elem instanceof Enumeration) {
// TODO: Add EnumerationLiteral someplace
getCore().deleteEnumeration(elem);
} else if (elem instanceof ProgrammingLanguageDataType) {
getCore().deleteProgrammingLanguageDataType(elem);
}
} else if (elem instanceof Node) {
getCore().deleteNode(elem);
} else if (elem instanceof Component) {
getCore().deleteComponent(elem);
} else if (elem instanceof Artifact) {
getCore().deleteArtifact(elem);
} else if (elem instanceof Signal) {
getCommonBehavior().deleteSignal(elem);
if (elem instanceof Exception) {
getCommonBehavior().deleteException(elem);
}
} else if (elem instanceof ClassifierRole) {
getCollaborations().deleteClassifierRole(elem);
} else if (elem instanceof UseCase) {
getUseCases().deleteUseCase(elem);
} else if (elem instanceof Actor) {
getUseCases().deleteActor(elem);
} else if (elem instanceof ClassifierInState) {
getActivityGraphs().deleteClassifierInState(elem);
}
} else if (elem instanceof Collaboration) {
getCollaborations().deleteCollaboration(elem);
} else if (elem instanceof UmlPackage) {
getModelManagement().deletePackage(elem);
if (elem instanceof org.omg.uml.modelmanagement.Model) {
getModelManagement().deleteModel(elem);
} else if (elem instanceof Subsystem) {
getModelManagement().deleteSubsystem(elem);
}
}
}
/**
* Delete a Relationship.
*
* @param elem Relationship to be deleted
*/
private void deleteRelationship(Relationship elem) {
getCore().deleteRelationship(elem);
if (elem instanceof Flow) {
getCore().deleteFlow(elem);
} else if (elem instanceof Generalization) {
getCore().deleteGeneralization(elem);
} else if (elem instanceof UmlAssociation) {
getCore().deleteAssociation(elem);
if (elem instanceof AssociationRole) {
getCollaborations().deleteAssociationRole(elem);
}
} else if (elem instanceof Dependency) {
getCore().deleteDependency(elem);
if (elem instanceof Abstraction) {
getCore().deleteAbstraction(elem);
} else if (elem instanceof Binding) {
getCore().deleteBinding(elem);
} else if (elem instanceof Usage) {
getCore().deleteUsage(elem);
} else if (elem instanceof Permission) {
getCore().deletePermission(elem);
}
} else if (elem instanceof Include) {
getUseCases().deleteInclude(elem);
} else if (elem instanceof Extend) {
getUseCases().deleteExtend(elem);
}
}
/**
* Delete an Action.
*
* @param elem the Action to be deleted
*/
private void deleteAction(Object elem) {
getCommonBehavior().deleteAction(elem);
if (elem instanceof ActionSequence) {
getCommonBehavior().deleteActionSequence(elem);
} else if (elem instanceof CreateAction) {
getCommonBehavior().deleteCreateAction(elem);
} else if (elem instanceof CallAction) {
getCommonBehavior().deleteCallAction(elem);
} else if (elem instanceof ReturnAction) {
getCommonBehavior().deleteReturnAction(elem);
} else if (elem instanceof SendAction) {
getCommonBehavior().deleteSendAction(elem);
} else if (elem instanceof TerminateAction) {
getCommonBehavior().deleteTerminateAction(elem);
} else if (elem instanceof UninterpretedAction) {
getCommonBehavior().deleteUninterpretedAction(elem);
} else if (elem instanceof DestroyAction) {
getCommonBehavior().deleteDestroyAction(elem);
}
}
/**
* Delete an Instance.
*
* @param elem the Instance to be deleted.
*/
private void deleteInstance(Instance elem) {
getCommonBehavior().deleteInstance(elem);
if (elem instanceof DataValue) {
getCommonBehavior().deleteDataValue(elem);
} else if (elem instanceof ComponentInstance) {
getCommonBehavior().deleteComponentInstance(elem);
} else if (elem instanceof NodeInstance) {
getCommonBehavior().deleteNodeInstance(elem);
} else if (elem
instanceof
org.omg.uml.behavioralelements.commonbehavior.Object) {
getCommonBehavior().deleteObject(elem);
if (elem instanceof LinkObject) {
getCommonBehavior().deleteLinkObject(elem);
}
} else if (elem instanceof SubsystemInstance) {
getCommonBehavior().deleteSubsystemInstance(elem);
}
if (elem instanceof UseCaseInstance) {
getUseCases().deleteUseCaseInstance(elem);
}
}
/**
* Delete a StateVertex.
*
* @param elem the StateVertex to be deleted
*/
private void deleteStateVertex(StateVertex elem) {
getStateMachines().deleteStateVertex(elem);
if (elem instanceof Pseudostate) {
getStateMachines().deletePseudostate(elem);
} else if (elem instanceof SynchState) {
getStateMachines().deleteSynchState(elem);
} else if (elem instanceof StubState) {
getStateMachines().deleteStubState(elem);
} else if (elem instanceof State) {
getStateMachines().deleteState(elem);
if (elem instanceof CompositeState) {
getStateMachines().deleteCompositeState(elem);
if (elem instanceof SubmachineState) {
getStateMachines().deleteSubmachineState(elem);
if (elem instanceof SubactivityState) {
getActivityGraphs().deleteSubactivityState(elem);
}
}
} else if (elem instanceof SimpleState) {
getStateMachines().deleteSimpleState(elem);
if (elem instanceof ActionState) {
getActivityGraphs().deleteActionState(elem);
if (elem instanceof CallState) {
getActivityGraphs().deleteCallState(elem);
}
} else if (elem instanceof ObjectFlowState) {
getActivityGraphs().deleteObjectFlowState(elem);
}
} else if (elem instanceof FinalState) {
getStateMachines().deleteFinalState(elem);
}
}
}
public void deleteExtent(Object element) {
try {
org.omg.uml.UmlPackage extent =
(org.omg.uml.UmlPackage) ((RefObject) element)
.refOutermostPackage();
LOG.log(Level.FINE, "Removing extent {0}", extent);
modelImpl.deleteExtent(extent);
} catch (InvalidObjectException e) {
throw new InvalidElementException(e);
}
}
public Collection getExtentElements(String name) {
return getExtentPackages(name);
}
public Collection getExtentPackages(String name) {
org.omg.uml.UmlPackage pkg = modelImpl.getExtent(name);
if (pkg == null) {
return null;
}
Collection<Object> packages = pkg.getModelManagement().getUmlPackage().
refAllOfType();
Collection<Object> topLevelPackages = new ArrayList<Object>();
for (Object pack : packages) {
if (Model.getFacade().getNamespace(pack) == null) {
topLevelPackages.add(pack);
}
}
return topLevelPackages;
}
}