CollaborationsFactoryMDRImpl.java
/* $Id$
*****************************************************************************
* Copyright (c) 2009,2010 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:
* bobtarling
* Tom Morris
*****************************************************************************
*
* Some portions of this file was previously release using the BSD License:
*/
// Copyright (c) 1996-2007 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.Collection;
import java.util.Iterator;
import javax.jmi.reflect.InvalidObjectException;
import org.argouml.model.CollaborationsFactory;
import org.argouml.model.InvalidElementException;
import org.argouml.model.Model;
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.CollaborationsPackage;
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.Link;
import org.omg.uml.foundation.core.Classifier;
import org.omg.uml.foundation.core.Namespace;
import org.omg.uml.foundation.core.Operation;
import org.omg.uml.foundation.datatypes.AggregationKind;
import org.omg.uml.foundation.datatypes.AggregationKindEnum;
/**
* Factory to create UML classes for the UML BehaviorialElements::Collaborations
* package.<p>
*
* @since ARGO0.19.5
* @author Ludovic Maître
* @author Tom Morris
* @author Thierry Lach (did derivation from NSUML implementation)
*/
class CollaborationsFactoryMDRImpl extends AbstractUmlModelFactoryMDR
implements CollaborationsFactory {
/**
* The model implementation.
*/
private MDRModelImplementation modelImpl;
/**
* Don't allow instantiation.
*
* @param implementation
* To get other helpers and factories.
*/
CollaborationsFactoryMDRImpl(MDRModelImplementation implementation) {
modelImpl = implementation;
}
public AssociationEndRole createAssociationEndRole() {
AssociationEndRole myAssociationEndRole =
getCollabPkg().getAssociationEndRole().createAssociationEndRole();
super.initialize(myAssociationEndRole);
return myAssociationEndRole;
}
private CollaborationsPackage getCollabPkg() {
return modelImpl.getUmlPackage().getCollaborations();
}
public AssociationRole createAssociationRole() {
AssociationRole myAssociationRole =
getCollabPkg().getAssociationRole().createAssociationRole();
super.initialize(myAssociationRole);
return myAssociationRole;
}
public ClassifierRole createClassifierRole() {
return createLifeline();
}
public Collaboration createCollaboration() {
Collaboration myCollaboration =
getCollabPkg().getCollaboration().createCollaboration();
super.initialize(myCollaboration);
return myCollaboration;
}
public CollaborationInstanceSet createCollaborationInstanceSet() {
CollaborationInstanceSet obj =
getCollabPkg().getCollaborationInstanceSet()
.createCollaborationInstanceSet();
super.initialize(obj);
return obj;
}
public Interaction createInteraction() {
Interaction myInteraction =
getCollabPkg().getInteraction().createInteraction();
super.initialize(myInteraction);
return myInteraction;
}
public InteractionInstanceSet createInteractionInstanceSet() {
InteractionInstanceSet obj =
getCollabPkg().getInteractionInstanceSet()
.createInteractionInstanceSet();
super.initialize(obj);
return obj;
}
public ClassifierRole createLifeline() {
ClassifierRole myClassifierRole =
getCollabPkg().getClassifierRole().createClassifierRole();
super.initialize(myClassifierRole);
return myClassifierRole;
}
public Message createMessage() {
Message myMessage =
getCollabPkg().getMessage().createMessage();
super.initialize(myMessage);
return myMessage;
}
public ClassifierRole buildClassifierRole(Object collaboration) {
Collaboration myCollaboration = (Collaboration) collaboration;
ClassifierRole classifierRole = createClassifierRole();
classifierRole.setNamespace(myCollaboration);
modelImpl.getCoreHelper().setMultiplicity(classifierRole, 1, 1);
return classifierRole;
}
public Object buildCollaboration(Object handle) {
Namespace namespace = (Namespace) handle;
Collaboration modelelement = createCollaboration();
modelelement.setNamespace(namespace);
modelelement.setName("newCollaboration");
modelelement.setAbstract(false);
return modelelement;
}
public Object buildCollaboration(Object namespace,
Object representedElement) {
if (!(namespace instanceof Namespace)) {
throw new IllegalArgumentException("Argument is not "
+ "a namespace");
}
if (representedElement instanceof Classifier
|| representedElement instanceof Operation) {
Collaboration collaboration =
(Collaboration) buildCollaboration(namespace);
if (representedElement instanceof Classifier) {
collaboration.
setRepresentedClassifier((Classifier) representedElement);
return collaboration;
}
if (representedElement instanceof Operation) {
collaboration.
setRepresentedOperation((Operation) representedElement);
return collaboration;
}
}
throw new IllegalArgumentException("Represented element must be"
+ " Collaboration or Operation");
}
public Interaction buildInteraction(Object handle) {
Collaboration collab = (Collaboration) handle;
Interaction inter = createInteraction();
inter.setContext(collab);
inter.setName("newInteraction");
return inter;
}
public ClassifierRole buildLifeline(Object collaboration) {
Collaboration myCollaboration = (Collaboration) collaboration;
ClassifierRole classifierRole = createClassifierRole();
classifierRole.setNamespace(myCollaboration);
modelImpl.getCoreHelper().setMultiplicity(classifierRole, 1, 1);
return classifierRole;
}
public AssociationEndRole buildAssociationEndRole(Object atype) {
ClassifierRole type = (ClassifierRole) atype;
AssociationEndRole end = createAssociationEndRole();
end.setParticipant(type);
return end;
}
public AssociationRole buildAssociationRole(Object from, Object to) {
return buildAssociationRole((ClassifierRole) from, (ClassifierRole) to);
}
/**
* Internal type-checked version of buildAssociationRole.
*/
private AssociationRole buildAssociationRole(ClassifierRole from,
ClassifierRole to) {
Collaboration collaboration = (Collaboration) from.getNamespace();
if (collaboration == null
|| !collaboration.equals(to.getNamespace())) {
throw new IllegalArgumentException("ClassifierRoles must be in"
+ " same non-null namespace");
}
AssociationRole role = createAssociationRole();
role.setNamespace(collaboration);
// The 4-arg version of this method depends on this ordering.
// Don't change it!
role.getConnection().add(buildAssociationEndRole(from));
role.getConnection().add(buildAssociationEndRole(to));
return role;
}
@Deprecated
public AssociationRole buildAssociationRole(Object from, Object agg1, Object to,
Object agg2, Boolean unidirectional) {
if (unidirectional == null) {
return buildAssociationRole(from, agg1, to, agg2, false);
} else {
return buildAssociationRole(from, agg1, to, agg2,
unidirectional.booleanValue());
}
}
public AssociationRole buildAssociationRole(Object from, Object agg1,
Object to, Object agg2, boolean unidirectional) {
AggregationKind ak1 = checkAggregationKind(agg1);
AggregationKind ak2 = checkAggregationKind(agg2);
AssociationRole role = buildAssociationRole((ClassifierRole) from,
(ClassifierRole) to);
AssociationEndRole end =
(AssociationEndRole) role.getConnection().get(0);
end.setAggregation(ak1);
end.setNavigable(!unidirectional);
end = (AssociationEndRole) role.getConnection().get(1);
end.setAggregation(ak2);
end.setNavigable(true); // probably redundant - just in case
return role;
}
/**
* Checks that aggregationKind is valid and promotes null
* to AK_NONE.
* @param aggregationKind Candidate AggregationKind or null
* @return valid checked AggregationKind
*/
private AggregationKind checkAggregationKind(Object aggregationKind) {
if (aggregationKind == null) {
aggregationKind = AggregationKindEnum.AK_NONE;
}
return (AggregationKind) aggregationKind;
}
public AssociationRole buildAssociationRole(Object link) {
if (!(link instanceof Link)) {
throw new IllegalArgumentException("Argument is not a link");
}
Object from = modelImpl.getCoreHelper().getSource(link);
Object to = modelImpl.getCoreHelper().getDestination(link);
Object classifierRoleFrom =
modelImpl.getFacade().getClassifiers(from).iterator().next();
Object classifierRoleTo =
modelImpl.getFacade().getClassifiers(to).iterator().next();
Object collaboration =
modelImpl.getFacade().getNamespace(classifierRoleFrom);
if (collaboration != modelImpl.getFacade().getNamespace(
classifierRoleTo)) {
throw new IllegalStateException("ClassifierRoles do not belong "
+ "to the same collaboration");
}
if (collaboration == null) {
throw new IllegalStateException("Collaboration may not be "
+ "null");
}
AssociationRole associationRole = createAssociationRole();
modelImpl.getCoreHelper().setNamespace(associationRole, collaboration);
modelImpl.getCoreHelper().addLink(associationRole, link);
return associationRole;
}
/**
* Builds a message within some interaction related to some assocationrole.
* The message is added as the last in the interaction sequence.
* Furthermore, the message is added as the last to the list of messages
* already attached to the role. Effectively, the already attached messages
* become predecessors of this message.
* TODO: This sets the activator as a side effect. However it is impossible
* to determine the activator at this stage as we don't yet know what the
* action will be of the message we're creating. See issue 5692.
*
* @param inter
* The Interaction.
* @param role
* The Association Role.
* @return The newly created Message.
*/
private Message buildMessageInteraction(Interaction inter,
AssociationRole role) {
assert inter != null : "An interaction must be provided";
assert role != null : "An association role must be provided";
Message message = createMessage();
inter.getMessage().add(message);
message.setCommunicationConnection(role);
if (role.getConnection().size() == 2) {
message.setSender((ClassifierRole) role.getConnection().get(0)
.getParticipant());
message.setReceiver((ClassifierRole) role.getConnection().get(1)
.getParticipant());
Collection<Message> messages =
Model.getFacade().getReceivedMessages(message.getSender());
Message lastMsg = lastMessage(messages, message);
if (lastMsg != null) {
message.setActivator(lastMsg);
messages = Model.getFacade().getActivatedMessages(lastMsg);
} else {
messages = Model.getFacade().getSentMessages(
message.getSender());
}
lastMsg = lastMessage(messages, message);
if (lastMsg != null) {
message.getPredecessor().add(findEnd(lastMsg));
}
}
return message;
}
/**
* Finds the last message in the collection not equal to null and not equal
* to m.
*
* @param c
* A collection containing exclusively Messages.
* @param m
* A Message.
* @return The last message in the collection, or null.
*/
private Message lastMessage(Collection<Message> c, Message m) {
Message last = null;
for (Message msg : c) {
if (msg != null && msg != m) {
last = msg;
}
}
return last;
}
/**
* Walks the tree of successors to m rooted until a leaf is found. The leaf
* is the returned. If m is itself a leaf, then m is returned.
*
* @param m A Message.
* @return The last message in one branch of the tree rooted at m.
*/
private Message findEnd(Message m) {
while (true) {
Collection<Message> c = Model.getFacade().getSuccessors(m);
Iterator<Message> it = c.iterator();
if (!it.hasNext()) {
return m;
}
m = it.next();
}
}
public Message buildMessage(Object acollab, Object arole) {
if (!(arole instanceof AssociationRole)) {
throw new IllegalArgumentException(
"An association role must be supplied - got " + arole);
}
try {
if (acollab instanceof Collaboration) {
return buildMessageCollab((Collaboration) acollab,
(AssociationRole) arole);
}
if (acollab instanceof Interaction) {
return buildMessageInteraction((Interaction) acollab,
(AssociationRole) arole);
}
throw new IllegalArgumentException("No valid object " + acollab);
} catch (InvalidObjectException e) {
throw new InvalidElementException(e);
}
}
private Message buildMessageCollab(Collaboration collab,
AssociationRole role) {
Interaction inter = null;
if (collab.getInteraction().size() == 0) {
inter = buildInteraction(collab);
} else {
inter = (Interaction) (collab.getInteraction().toArray())[0];
}
return buildMessageInteraction(inter, role);
}
public Message buildActivator(Object owner, Object interaction) {
Message theOwner = (Message) owner;
Interaction theInteraction;
if (interaction == null) {
theInteraction = theOwner.getInteraction();
} else {
theInteraction = (Interaction) interaction;
}
if (interaction == null) {
throw new IllegalArgumentException();
}
Message activator = createMessage();
activator.setInteraction(theInteraction);
theOwner.setActivator(activator);
return activator;
}
/**
* @param elem
* the associationendrole
*/
void deleteAssociationEndRole(Object elem) {
if (!(elem instanceof AssociationEndRole)) {
throw new IllegalArgumentException();
}
}
/**
* @param elem
* the associationrole
*/
void deleteAssociationRole(Object elem) {
AssociationRole role = (AssociationRole) elem;
for (Message message : role.getMessage()) {
modelImpl.getUmlFactory().delete(message);
}
}
/**
* @param elem
* the UML element to be deleted
*/
void deleteClassifierRole(Object elem) {
ClassifierRole cr = (ClassifierRole) elem;
// delete Messages which have this as sender or receiver
CollaborationsPackage cPkg = ((org.omg.uml.UmlPackage) cr
.refOutermostPackage()).getCollaborations();
modelImpl.getUmlHelper().deleteCollection(
cPkg.getAMessageSender().getMessage(cr));
modelImpl.getUmlHelper().deleteCollection(
cPkg.getAReceiverMessage().getMessage(cr));
// TODO: delete Collaborations where this is the last ClassifierRole?
// Object owner = cr.refImmediateComposite();
// if (owner instanceof Collaboration) {
// Collection ownedElements = ((Collaboration) owner)
// .getOwnedElement();
// if (ownedElements.size() == 1 && ownedElements.contains(cr))
// nsmodel.getUmlFactory().delete(owner);
// }
}
/**
* @param elem
* the UML element to be delete
*/
void deleteCollaboration(Object elem) {
if (!(elem instanceof Collaboration)) {
throw new IllegalArgumentException();
}
}
/**
* @param elem
* the UML element to be delete
*/
void deleteCollaborationInstanceSet(Object elem) {
if (!(elem instanceof CollaborationInstanceSet)) {
throw new IllegalArgumentException();
}
// InteractionInstanceSets will get deleted automatically
// because they are associated by composition
}
/**
* @param elem
* the UML element to be delete
*/
void deleteInteraction(Object elem) {
if (!(elem instanceof Interaction)) {
throw new IllegalArgumentException();
}
}
/**
* @param elem
* the UML element to be delete
*/
void deleteInteractionInstanceSet(Object elem) {
if (!(elem instanceof InteractionInstanceSet)) {
throw new IllegalArgumentException();
}
}
/**
* @param elem
* the UML element to be delete
*/
void deleteMessage(Object elem) {
Message message = (Message) elem;
// If this is the only message contained in the Interaction
// we delete the Interaction
Interaction i = message.getInteraction();
if (i != null && i.getMessage().size() == 1) {
modelImpl.getUmlFactory().delete(i);
}
}
}