Index: trunk/autoquest-plugin-uml/src/main/java/de/ugoe/cs/autoquest/plugin/uml/UMLUtils.java
===================================================================
--- trunk/autoquest-plugin-uml/src/main/java/de/ugoe/cs/autoquest/plugin/uml/UMLUtils.java	(revision 1604)
+++ trunk/autoquest-plugin-uml/src/main/java/de/ugoe/cs/autoquest/plugin/uml/UMLUtils.java	(revision 1624)
@@ -24,8 +24,18 @@
 
 import org.eclipse.emf.common.util.EList;
+import org.eclipse.uml2.uml.Association;
+import org.eclipse.uml2.uml.Class;
 import org.eclipse.uml2.uml.Comment;
+import org.eclipse.uml2.uml.Element;
+import org.eclipse.uml2.uml.Interaction;
+import org.eclipse.uml2.uml.Lifeline;
+import org.eclipse.uml2.uml.Message;
+import org.eclipse.uml2.uml.MessageOccurrenceSpecification;
+import org.eclipse.uml2.uml.Model;
+import org.eclipse.uml2.uml.Operation;
 import org.eclipse.uml2.uml.Region;
 import org.eclipse.uml2.uml.StateMachine;
 import org.eclipse.uml2.uml.Transition;
+import org.eclipse.uml2.uml.UMLPackage;
 import org.eclipse.uml2.uml.Vertex;
 
@@ -36,5 +46,5 @@
 /**
  * <p>
- * TODO comment
+ * Utilities for working with UML.
  * </p>
  * 
@@ -43,6 +53,22 @@
 public class UMLUtils {
 
-    public static List<Event> createUMLTransitionSequence(List<Event> sequence, StateMachine stateMachine) {
-        List<List<Transition>> matchingSequences = determineMatchingTransitionSequences(sequence, stateMachine);
+    /**
+     * <p>
+     * Creates a sequence of events with {@link UMLTransitionType} as event type from a given
+     * sequence of events with the {@link SOAPEventType}, by matching the sequences to a state
+     * machine.
+     * </p>
+     * 
+     * @param sequence
+     *            SOAP sequences
+     * @param stateMachine
+     *            the state machine
+     * @return create UML sequences
+     */
+    public static List<Event> createUMLTransitionSequence(List<Event> sequence,
+                                                          StateMachine stateMachine)
+    {
+        List<List<Transition>> matchingSequences =
+            determineMatchingTransitionSequences(sequence, stateMachine);
 
         if (matchingSequences.size() != 1) {
@@ -56,28 +82,43 @@
         return umlEventSequence;
     }
-    
-    public static void convertStateMachineToUsageProfile(Collection<List<Event>> sequences, StateMachine stateMachine) {
+
+    /**
+     * <p>
+     * Uses a sequences of events with the {@link UMLTransitionType} to determine the transition
+     * probabilities for the state machine.
+     * </p>
+     * 
+     * @param sequences
+     *            UML sequences
+     * @param stateMachine
+     *            state machine to be converted to a usage profile
+     */
+    public static void convertStateMachineToUsageProfile(Collection<List<Event>> sequences,
+                                                         StateMachine stateMachine)
+    {
         // create state->outgoings hashmap
-        Map<Vertex, Map<Transition,Integer>> stateMap = new HashMap<>();
-        for( Region region : stateMachine.getRegions() ) {
-            for( Vertex state : region.getSubvertices() ) {
-                stateMap.put(state, new HashMap<Transition,Integer>());
-            }
-        }
-        
+        Map<Vertex, Map<Transition, Integer>> stateMap = new HashMap<>();
+        for (Region region : stateMachine.getRegions()) {
+            for (Vertex state : region.getSubvertices()) {
+                stateMap.put(state, new HashMap<Transition, Integer>());
+            }
+        }
+
         // create counters for each transition
-        for( List<Event> sequence : sequences) {
-            for( Event event : sequence ) {
-                if( event.getType() instanceof UMLTransitionType ) {
+        for (List<Event> sequence : sequences) {
+            for (Event event : sequence) {
+                if (event.getType() instanceof UMLTransitionType) {
                     Transition transition = ((UMLTransitionType) event.getType()).getTransition();
-                    Map<Transition,Integer> transitionMap = stateMap.get(transition.getSource());
+                    Map<Transition, Integer> transitionMap = stateMap.get(transition.getSource());
                     Integer value = transitionMap.get(transition);
-                    if( value==null ) {
+                    if (value == null) {
                         value = 0;
                     }
-                    transitionMap.put(transition, value+1);
-                } else {
-                    throw new RuntimeException("Wrong event type. Only UMLTransitionType supported but was: " +
-                            event.getType().getClass().getName());
+                    transitionMap.put(transition, value + 1);
+                }
+                else {
+                    throw new RuntimeException(
+                                               "Wrong event type. Only UMLTransitionType supported but was: " +
+                                                   event.getType().getClass().getName());
                 }
             }
@@ -85,33 +126,48 @@
 
         // calculate probabilities
-        for( Region region : stateMachine.getRegions() ) {
-            for( Vertex state : region.getSubvertices() ) {
-                Map<Transition,Integer> transitionMap = stateMap.get(state);
+        for (Region region : stateMachine.getRegions()) {
+            for (Vertex state : region.getSubvertices()) {
+                Map<Transition, Integer> transitionMap = stateMap.get(state);
                 int totalCount = 0;
-                for( Entry<Transition,Integer> entry : transitionMap.entrySet() ) {
+                for (Entry<Transition, Integer> entry : transitionMap.entrySet()) {
                     totalCount += entry.getValue();
                 }
-                if( totalCount!=0 ) {
-                    for( Transition transition : state.getOutgoings() ) {
+                if (totalCount != 0) {
+                    for (Transition transition : state.getOutgoings()) {
                         double prob = 0.0d;
-                        if( transitionMap.containsKey(transition)) {
-                            prob = ((double) transitionMap.get(transition))/totalCount;
+                        if (transitionMap.containsKey(transition)) {
+                            prob = ((double) transitionMap.get(transition)) / totalCount;
                         }
                         Comment comment = transition.createOwnedComment();
-                        comment.setBody("" + prob );
-                    }
-                } else {
+                        comment.setBody("" + prob);
+                    }
+                }
+                else {
                     // system has never been in this state, all transitions equally likely
                     int numOutgoings = state.getOutgoings().size();
-                    for( Transition transition : state.getOutgoings() ) {
+                    for (Transition transition : state.getOutgoings()) {
                         Comment comment = transition.createOwnedComment();
-                        comment.setBody("" + (1.0d/numOutgoings) );
-                    }
-                }
-            }
-        }
-    }
-    
-    public static List<List<Transition>> determineMatchingTransitionSequences(List<Event> sequence, StateMachine stateMachine) {
+                        comment.setBody("" + (1.0d / numOutgoings));
+                    }
+                }
+            }
+        }
+    }
+
+    /**
+     * <p>
+     * Determines all matching {@link Transition} sequences in a state machine for a given sequence
+     * of SOAP events.
+     * </p>
+     * 
+     * @param sequence
+     *            SOAP sequence
+     * @param stateMachine
+     *            the state machine
+     * @return all matching {@link Transition} sequences
+     */
+    public static List<List<Transition>> determineMatchingTransitionSequences(List<Event> sequence,
+                                                                              StateMachine stateMachine)
+    {
         EList<Region> regions = stateMachine.getRegions();
         EList<Vertex> states = null;
@@ -175,12 +231,130 @@
             }
             else {
-                throw new RuntimeException("Wrong event type. Only UMLTransitionType supported but was: " +
-                    event.getType().getClass().getName());
+                throw new RuntimeException(
+                                           "Wrong event type. Only UMLTransitionType supported but was: " +
+                                               event.getType().getClass().getName());
             }
         }
         return matchingSequences;
     }
-    
-    private static List<Transition> matchTransitions(List<Transition> transitions, SOAPEventType eventType)
+
+    /**
+     * <p>
+     * Extends a given model with an interaction that represents an observed sequence. 
+     * </p>
+     *
+     * @param sequence sequence that is added as sequence diagram
+     * @param model UML model to which the interaction is added
+     * @param interactionName name of the interaction
+     */
+    public static void createInteractionFromEventSequence(List<Event> sequence, Model model, String interactionName)
+    {
+        Map<String, Class> classMap = new HashMap<>();
+
+        EList<Element> elements = model.getOwnedElements();
+        for (Element element : elements) {
+            if (element instanceof Class) {
+                classMap.put(((Class) element).getName(), (Class) element);
+            }
+        }
+
+        Interaction interaction =
+            (Interaction) model
+                .createPackagedElement(interactionName, UMLPackage.Literals.INTERACTION);
+
+        Lifeline userLifeline = interaction.createLifeline("user");
+
+        int i = 0;
+        for (Event event : sequence) {
+            if (event.getType() instanceof SOAPEventType) {
+                SOAPEventType eventType = (SOAPEventType) event.getType();
+                String serviceName = eventType.getServiceName();
+                String methodName = eventType.getCalledMethod();
+                Class targetClass = classMap.get(serviceName);
+                if (targetClass == null) {
+                    throw new RuntimeException(
+                                               "Could not find class in the UML model that belong to the service: " +
+                                                   serviceName);
+                }
+
+                Lifeline targetLifeline = interaction.getLifeline(serviceName);
+                if (targetLifeline == null) {
+                    targetLifeline = interaction.createLifeline(serviceName);
+                    Association association =
+                        (Association) model.getPackagedElement("user_" + serviceName, true,
+                                                               UMLPackage.Literals.ASSOCIATION,
+                                                               true);
+                    targetLifeline
+                        .setRepresents(association.getMemberEnd(serviceName,
+                                                                classMap.get(serviceName)));
+                }
+                MessageOccurrenceSpecification sendFragment =
+                    (MessageOccurrenceSpecification) interaction
+                        .createFragment(i + ":" + methodName + "_sendFragment",
+                                        UMLPackage.Literals.MESSAGE_OCCURRENCE_SPECIFICATION);
+                MessageOccurrenceSpecification recvFragment =
+                    (MessageOccurrenceSpecification) interaction
+                        .createFragment(i + ":" + methodName + "_recvFragment",
+                                        UMLPackage.Literals.MESSAGE_OCCURRENCE_SPECIFICATION);
+
+                sendFragment.setCovered(userLifeline);
+                recvFragment.setCovered(targetLifeline);
+
+                Message message = interaction.createMessage(methodName);
+                message.setSignature(getOperationFromName(targetClass.getOperations(), methodName));
+                message.setSendEvent(sendFragment);
+                message.setReceiveEvent(recvFragment);
+
+                sendFragment.setMessage(message);
+                recvFragment.setMessage(message);
+            }
+            else {
+                throw new RuntimeException(
+                                           "Wrong event type. Only SOAPEventType supported but was: " +
+                                               event.getType().getClass().getName());
+            }
+            i++;
+        }
+    }
+
+    /**
+     * <p>
+     * Fetches an operation using only its name from a list of operations. Returns the first match
+     * found or null if no match is found.
+     * </p>
+     * 
+     * @param operations
+     *            list of operations
+     * @param name
+     *            name of the operation
+     * @return first matching operation; null if no match is found
+     */
+    private static Operation getOperationFromName(EList<Operation> operations, String name) {
+        if (name == null) {
+            throw new IllegalArgumentException("name of the operation must not be null");
+        }
+        if (operations != null) {
+            for (Operation operation : operations) {
+                if (operation.getName() != null && operation.getName().equals(name)) {
+                    return operation;
+                }
+            }
+        }
+        return null;
+    }
+
+    /**
+     * <p>
+     * Determines which transitions match a given {@link SOAPEventType}.
+     * </p>
+     * 
+     * @param transitions
+     *            the transitions
+     * @param eventType
+     *            the SOAP event
+     * @return matching transitions
+     */
+    private static List<Transition> matchTransitions(List<Transition> transitions,
+                                                     SOAPEventType eventType)
     {
         List<Transition> matching = new LinkedList<>();
@@ -194,4 +368,4 @@
         return matching;
     }
-    
+
 }
