Index: trunk/autoquest-plugin-http/src/main/java/de/ugoe/cs/autoquest/plugin/http/SOAPUtils.java
===================================================================
--- trunk/autoquest-plugin-http/src/main/java/de/ugoe/cs/autoquest/plugin/http/SOAPUtils.java	(revision 1994)
+++ trunk/autoquest-plugin-http/src/main/java/de/ugoe/cs/autoquest/plugin/http/SOAPUtils.java	(revision 2003)
@@ -23,4 +23,6 @@
 import java.util.List;
 import java.util.Set;
+import java.util.Stack;
+import java.util.logging.Level;
 
 import javax.xml.transform.Transformer;
@@ -41,4 +43,5 @@
 import de.ugoe.cs.autoquest.plugin.http.eventcore.SimpleSOAPEventType;
 import de.ugoe.cs.autoquest.plugin.http.eventcore.SimpleSOAPEventType.CallType;
+import de.ugoe.cs.util.console.Console;
 
 /**
@@ -690,4 +693,112 @@
     /**
      * <p>
+     * Drops all requests without responses as well as invalid request/response orders. Only the
+     * part of the sequence before the first invalid occurrence is kept.
+     * </p>
+     * 
+     * @param sequences
+     *            sequences where the invalid pairs are dropped
+     * @return sequences with only valid and complete interactions
+     */
+    public static Collection<List<Event>> dropInvalidResponseRequestPairs(Collection<List<Event>> sequences)
+    {
+        Collection<List<Event>> validSequences = new LinkedList<>();
+        int i = 0;
+        for (List<Event> sequence : sequences) {
+            List<Event> validSequence = dropInvalidResponseRequestPairs(sequence);
+            if (validSequence.isEmpty() ||
+                (validSequence.size() <= 2 && validSequence.get(0) == Event.STARTEVENT))
+            {
+                Console.traceln(Level.INFO, "dropped sequence " + i +
+                    ": empty after removal of invalid request/response pairs");
+            }
+            validSequences.add(validSequence);
+            i++;
+        }
+        return validSequences;
+    }
+
+    /**
+     * <p>
+     * Drops all requests without responses as well as invalid request/response orders. Only the
+     * part of the sequence before the first invalid occurrence is kept.
+     * </p>
+     * 
+     * @param sequence
+     *            sequence where the invalid pairs are dropped
+     * @return sequence with only valid and complete interactions
+     */
+    public static List<Event> dropInvalidResponseRequestPairs(List<Event> sequence) {
+        Stack<SimpleSOAPEventType> unrespondedRequests = new Stack<>();
+        boolean hasStartEvent = false;
+        int lastValidIndex = 0;
+        int i = 0;
+        for (Event event : sequence) {
+            if (event == Event.STARTEVENT) {
+                hasStartEvent = true;
+                lastValidIndex = i;
+            }
+            else if (event.getType() instanceof SimpleSOAPEventType) {
+                SimpleSOAPEventType currentEventType = (SimpleSOAPEventType) event.getType();
+                if (SOAPUtils.isSOAPRequest(event)) {
+                    unrespondedRequests.push(currentEventType);
+                }
+                else if (SOAPUtils.isSOAPResponse(event)) {
+                    if (unrespondedRequests.empty()) {
+                        break; // found a response without previous request; sequence invalid from
+                               // here
+                    }
+                    else {
+                        SimpleSOAPEventType lastRequest = unrespondedRequests.peek();
+                        if (isRequestResponseMatch(lastRequest, currentEventType)) {
+                            unrespondedRequests.pop();
+                            if (unrespondedRequests.empty()) {
+                                lastValidIndex = i;
+                            }
+                        }
+                    }
+
+                }
+            }
+            i++;
+        }
+        List<Event> validSequence = new LinkedList<>(sequence.subList(0, lastValidIndex + 1));
+        if (hasStartEvent) {
+            validSequence.add(Event.ENDEVENT);
+        }
+        return validSequence;
+    }
+
+    /**
+     * <p>
+     * Checks if two {@link SimpleSOAPEventType} types are equal except their {@link CallType},
+     * which must be {@value CallType#REQUEST} for the first parameter and {@link CallType#RESPONSE}
+     * for the second parameter.
+     * </p>
+     * 
+     * @param request
+     *            request soap event
+     * @param response
+     *            response soap event
+     * @return true if they are a matching request/response pair
+     */
+    public static boolean isRequestResponseMatch(SimpleSOAPEventType request,
+                                                 SimpleSOAPEventType response)
+    {
+        if (request == null && response == null) {
+            return true;
+        }
+        if ((request != null && response == null) || (request == null && response != null)) {
+            return false;
+        }
+        return request.getCallType().equals(CallType.REQUEST) &&
+            response.getCallType().equals(CallType.RESPONSE) &&
+            HTTPUtils.equals(request.getCalledMethod(), response.getCalledMethod()) &&
+            HTTPUtils.equals(request.getServiceName(), response.getServiceName()) &&
+            HTTPUtils.equals(request.getClientName(), response.getClientName());
+    }
+
+    /**
+     * <p>
      * prevent instantiation
      * </p>
