Index: branches/autoquest-core-tasktrees-alignment/src/main/java/de/ugoe/cs/autoquest/tasktrees/temporalrelation/SequenceForTaskDetectionRuleAlignment.java
===================================================================
--- branches/autoquest-core-tasktrees-alignment/src/main/java/de/ugoe/cs/autoquest/tasktrees/temporalrelation/SequenceForTaskDetectionRuleAlignment.java	(revision 1656)
+++ branches/autoquest-core-tasktrees-alignment/src/main/java/de/ugoe/cs/autoquest/tasktrees/temporalrelation/SequenceForTaskDetectionRuleAlignment.java	(revision 1657)
@@ -95,11 +95,8 @@
 	 * <p>
 	 * the task handling strategy to be used for comparing tasks during
-	 * iteration detection i.e., after the tasks are
-	 * harmonized
+	 * iteration detection i.e., after the tasks are harmonized
 	 * </p>
 	 */
 	private TaskHandlingStrategy identityTaskHandlingStrategy;
-
-
 
 	/**
@@ -166,6 +163,4 @@
 				.generate(appData.getNumberSequences(), submat, 9);
 
-		
-		
 		// Retrieve all matches reached a specific threshold
 		Console.traceln(Level.INFO, "retrieving significant sequence pieces");
@@ -174,6 +169,7 @@
 					Level.FINEST,
 					"retrieving significant sequence pieces:  "
-							+ Math.round((float) i / (float) appData.getNumberSequences().size()
-									* 100) + "%");
+							+ Math.round((float) i
+									/ (float) appData.getNumberSequences()
+											.size() * 100) + "%");
 			for (int j = 0; j < appData.getNumberSequences().size(); j++) {
 				if (i != j) {
@@ -197,27 +193,29 @@
 					.getFirstSequence().size())
 				continue;
-	
+
 			for (int j = 0; j < appData.getNumberSequences().size(); j++) {
-				LinkedList<Integer> startpositions = appData.getNumberSequences().get(j)
-						.containsPattern(pattern);
+				LinkedList<Integer> startpositions = appData
+						.getNumberSequences().get(j).containsPattern(pattern);
 				if (startpositions.size() > 0) {
 					NumberSequence tempns = appData.getNumberSequences().get(j);
-					
+
 					for (Iterator<Integer> jt = startpositions.iterator(); jt
 							.hasNext();) {
 						int start = jt.next();
-						//TODO: Debug Output
+						// TODO: Debug Output
 						/*
-						System.out.println("Found match ");
-						pattern.getFirstSequence().printSequence();
-						pattern.getSecondSequence().printSequence(); 
-						System.out.println("in sequence " + (j+1) + " at position " + start);
-						for(int k=0;k<tempns.getSequence().length;k++) {
-							System.out.print(k + ": " + tempns.getSequence()[k] + " ");
-							System.out.println(appData.getNumber2Task().get(tempns.getSequence()[k]));
-						}
-						*/
-						pattern.addOccurence(
-								new MatchOccurence(start, j));
+						 * System.out.println("Found match ");
+						 * pattern.getFirstSequence().printSequence();
+						 * pattern.getSecondSequence().printSequence();
+						 * System.out.println("in sequence " + (j+1) +
+						 * " at position " + start); for(int
+						 * k=0;k<tempns.getSequence().length;k++) {
+						 * System.out.print(k + ": " + tempns.getSequence()[k] +
+						 * " ");
+						 * System.out.println(appData.getNumber2Task().get(
+						 * tempns.getSequence()[k])); }
+						 */
+						pattern.addOccurence(new MatchOccurence(start, start
+								+ pattern.size(), j));
 					}
 
@@ -230,42 +228,30 @@
 		Comparator<Match> comparator = new Comparator<Match>() {
 			public int compare(Match m1, Match m2) {
-				return m2.occurenceCount() - m1.occurenceCount(); 
-																	
+				return m2.occurenceCount() - m1.occurenceCount();
+
 			}
 		};
-		//Collections.sort(matchseqs, comparator);
-		
+		// Collections.sort(matchseqs, comparator);
 
 		// TODO: Harmonize matches: finding double matches and merge them
 		/*
-		Console.traceln(Level.INFO, "harmonizing matches");
-		int i=0;
-		
-		while(i<matchseqs.size()) {
-			int j=i;
-			while(j<matchseqs.size()) {
-				if(i!=j) {
-					if(matchseqs.get(i).equals(matchseqs.get(j))) {
-						//matchseqs.get(i).addOccurencesOf(matchseqs.get(j));
-						matchseqs.remove(j);
-					
-						//System.out.println("Sequence " + i);
-						//matchseqs.get(i).getFirstSequence().printSequence();
-						//matchseqs.get(i).getSecondSequence().printSequence();
-						//System.out.println("is equal to sequence " + j);
-						//matchseqs.get(j).getFirstSequence().printSequence();
-						//matchseqs.get(j).getSecondSequence().printSequence();
-						continue;
-					}
-				}
-				j++;
-			}
-			i++;
-		}
-		Collections.sort(matchseqs, comparator);
-		*/
-		
-		
-		// Just printing the results out
+		 * Console.traceln(Level.INFO, "harmonizing matches"); int i=0;
+		 * 
+		 * while(i<matchseqs.size()) { int j=i; while(j<matchseqs.size()) {
+		 * if(i!=j) { if(matchseqs.get(i).equals(matchseqs.get(j))) {
+		 * //matchseqs.get(i).addOccurencesOf(matchseqs.get(j));
+		 * matchseqs.remove(j);
+		 * 
+		 * //System.out.println("Sequence " + i);
+		 * //matchseqs.get(i).getFirstSequence().printSequence();
+		 * //matchseqs.get(i).getSecondSequence().printSequence();
+		 * //System.out.println("is equal to sequence " + j);
+		 * //matchseqs.get(j).getFirstSequence().printSequence();
+		 * //matchseqs.get(j).getSecondSequence().printSequence(); continue; } }
+		 * j++; } i++; } Collections.sort(matchseqs, comparator);
+		 */
+
+		HashMap<Integer, List<MatchOccurence>> replacedOccurences = new HashMap<Integer, List<MatchOccurence>>();
+		// Replace matches in the sessions
 		for (int i = 0; i < matchseqs.size(); i++) {
 			// Every pattern consists of 2 sequences, therefore the minimum
@@ -274,48 +260,103 @@
 			// well
 			if (matchseqs.get(i).occurenceCount() > 2) {
-				
-				ISequence task = matchAsSequence(appData,matchseqs.get(i));
-				for(Iterator<MatchOccurence> it = matchseqs.get(i).getOccurences().iterator();it.hasNext();) {
+
+				ISequence task = matchAsSequence(appData, matchseqs.get(i));
+				invalidOccurence: for (Iterator<MatchOccurence> it = matchseqs
+						.get(i).getOccurences().iterator(); it.hasNext();) {
 					MatchOccurence oc = it.next();
 					System.out.println("Trying to replace sequence: ");
 					matchseqs.get(i).getFirstSequence().printSequence();
 					matchseqs.get(i).getSecondSequence().printSequence();
-					System.out.println(" in session number: " + (oc.getSequenceId()+1) + " at position " + (oc.getStartindex()) + "-" + (oc.getStartindex()+matchseqs.get(i).getFirstSequence().size()));
+					System.out.println(" in session number: "
+							+ (oc.getSequenceId() + 1)
+							+ " at position "
+							+ (oc.getStartindex())
+							+ "-"
+							+ (oc.getStartindex() + matchseqs.get(i)
+									.getFirstSequence().size()));
 					System.out.println();
-					/*
-					System.out.println("Printing session: ");
-					for(int j=0;j<sessions.get(oc.getSequenceId()).size();j++) {
-						System.out.println(j+ ": " + sessions.get(oc.getSequenceId()).get(j));
-					}*/
-					List<ISequenceInstance> sequenceInstances = new LinkedList<ISequenceInstance>();
-					RuleUtils.createNewSubSequenceInRange(sessions.get(oc.getSequenceId()), oc.getStartindex(), oc.getStartindex()+matchseqs.get(i).getFirstSequence().size(), task,	taskFactory, taskBuilder);
-	}
-				//System.out.println(task);
-				//matchseqs.get(i).getFirstSequence().printSequence();
-				//matchseqs.get(i).getSecondSequence().printSequence();
-				//System.out.println("Found pattern "
-				//		+ matchseqs.get(i).occurenceCount() + " times");
+
+					//System.out.println("Printing session: ");
+					for (int j = 0; j < sessions.get(oc.getSequenceId()).size(); j++) {
+					  System.out.println(j + ": "+ sessions.get(oc.getSequenceId()).get(j));
+					}
+
+					// Check if nothing has been replaced in the sequence we
+					// want to replace
+					if (replacedOccurences.get(oc.getSequenceId()) == null) {
+						replacedOccurences.put(oc.getSequenceId(),
+								new LinkedList<MatchOccurence>());
+					} else {
+						// check if we have any replaced occurence with indexes
+						// smaller than ours. If so, we need to adjust our start
+						// and endpoints
+						// of the replacement.
+						// Also do a check if we have replaced this specific
+						// MatchOccurence in this sequence already. Jump to the
+						// next occurence if this is the case.
+						// This is no more neccessary once the matches are
+						// harmonized.
+						for (Iterator<MatchOccurence> jt = replacedOccurences
+								.get(oc.getSequenceId()).iterator(); jt
+								.hasNext();) {
+							MatchOccurence tmpOC = jt.next();
+							if (tmpOC.getStartindex() == oc.getStartindex()) {
+								System.out.println("This position has already been replaced in this iteration");
+								continue invalidOccurence;
+								
+							}
+							if (tmpOC.getStartindex() < oc
+									.getStartindex()) {
+								int diff = tmpOC.getEndindex()
+										- tmpOC.getStartindex();
+								// Just to be sure.
+								if (diff > 0) {
+									System.out.println("Old index: Start: "
+											+ oc.getStartindex() + " End "
+											+ oc.getEndindex());
+									oc.setStartindex(oc.getStartindex() - diff+1);
+									oc.setEndindex(oc.getEndindex() - diff+1);
+									System.out.println("Updated index: Start: "
+											+ oc.getStartindex() + " End "
+											+ oc.getEndindex());
+								} else {
+									Console.traceln(Level.WARNING,
+											"End index of a Match before start. This should never happen");
+								}
+							}
+						}
+					}
+
+					
+					ISequenceInstance sequenceInstances = RuleUtils.createNewSubSequenceInRange(
+							sessions.get(oc.getSequenceId()),
+							oc.getStartindex(), oc.getEndindex(), task,
+							taskFactory, taskBuilder);
+					
+					//Adjust the length of the match regarding to the length of instance. (OptionalInstances may be shorter) 
+					oc.setEndindex(oc.getStartindex()+sequenceInstances.size()-RuleUtils.missedOptionals);
+					replacedOccurences.get(oc.getSequenceId()).add(oc);
+				}
+			
 				System.out.println();
 			}
 		}
-		
 
 		alignments = null;
 
 		do {
-		  
-		  appData.getStopWatch().start("whole loop"); //
-		  detectAndReplaceIterations(appData);
-		 
-		  appData.getStopWatch().start("task replacement"); //
-		  //detectAndReplaceTasks(appData); //
-		  appData.getStopWatch().stop("task replacement"); //
-		  appData.getStopWatch().stop("whole loop");
-		  
-		  appData.getStopWatch().dumpStatistics(System.out); //
-		  appData.getStopWatch().reset();
-		  
-		  } while (appData.detectedAndReplacedTasks());
-		 
+
+			appData.getStopWatch().start("whole loop"); //
+			detectAndReplaceIterations(appData);
+
+			appData.getStopWatch().start("task replacement"); //
+			// detectAndReplaceTasks(appData); //
+			appData.getStopWatch().stop("task replacement"); //
+			appData.getStopWatch().stop("whole loop");
+
+			appData.getStopWatch().dumpStatistics(System.out); //
+			appData.getStopWatch().reset();
+
+		} while (appData.detectedAndReplacedTasks());
 
 		Console.println("created "
@@ -334,6 +375,4 @@
 	}
 
-	
-	
 	/**
 	 * <p>
@@ -363,7 +402,7 @@
 		ITask task;
 		List<IUserSession> sessions = appData.getSessions();
-		for (int j = 0; j< sessions.size();j++) {
+		for (int j = 0; j < sessions.size(); j++) {
 			IUserSession session = sessions.get(j);
-	
+
 			NumberSequence templist = new NumberSequence(session.size());
 
@@ -375,5 +414,5 @@
 					uniqueTasks.addSymbol(taskInstance, taskInstance.getTask());
 					templist.getSequence()[i] = taskInstance.getTask().getId();
-		
+
 				} else {
 					taskBuilder.setTask(taskInstance, task);
@@ -381,9 +420,16 @@
 					unifiedTasks++;
 				}
-				appData.getNumber2Task().put(templist.getSequence()[i], taskInstance.getTask());
+				appData.getNumber2Task().put(templist.getSequence()[i],
+						taskInstance.getTask());
 				
-				//System.out.println("TaskID: " + taskInstance.getTask().getId()+ " Numbersequence: " + templist.getSequence()[i]);
-			}
-			//Each NumberSequence is identified by its id, beginning to count at zero
+				//if(j==1) {
+				//	System.out.println(i + ": TaskID: " +
+				//	taskInstance.getTask().getId()+ " Numbersequence: " +
+				//	templist.getSequence()[i]);
+				//}
+				
+			}
+			// Each NumberSequence is identified by its id, beginning to count
+			// at zero
 			templist.setId(j);
 			appData.getNumberSequences().add(templist);
@@ -528,61 +574,66 @@
 	}
 
-	
-	 ISequence matchAsSequence(RuleApplicationData appData,Match m) {
-	    	
-	    	ISequence sequence = taskFactory.createNewSequence();
-	    	
-	    	int[] first = m.getFirstSequence().getSequence();
-	    	int[] second = m.getSecondSequence().getSequence();
-
-	    	
-	    	//Both sequences of a match are equally long
-	    	for(int i=0;i<m.getFirstSequence().size();i++) {
-	
-	    		//Two gaps aligned to each other: Have not seen it happening so far, just to handle it
-	    		if(first[i]==-1 && second[i]==-1) {
-	    			//TODO: Do nothing?
-	    		}
-	    		//Both events are equal, we can simply add the task referring to the number
-	    		else if(first[i]==second[i]) {
-	    			taskBuilder.addChild(sequence, appData.getNumber2Task().get(first[i]));
-	    		}
-	    		//We have a gap in the first sequence, we need to add the task of the second sequence as optional
-	    		else if(first[i]==-1 && second[i]!=-1) {
-	    			IOptional optional = taskFactory.createNewOptional();
-	    			taskBuilder.setMarkedTask(optional, appData.getNumber2Task().get(second[i]));
-	    			taskBuilder.addChild(sequence,optional);
-	    		}
-	    		//We have a gap in the second sequence, we need to add the task of the first sequence as optional
-	    		else if(first[i]!=-1 && second[i]==-1) {
-	    			IOptional optional = taskFactory.createNewOptional();
-	    			taskBuilder.setMarkedTask(optional, appData.getNumber2Task().get(first[i]));
-	    			taskBuilder.addChild(sequence,optional);
-	    		}
-	    		//Both tasks are unequal, we need to insert a selection here
-	    		else {
-	    			ISelection selection = taskFactory.createNewSelection();
-	    			taskBuilder.addChild(selection, appData.getNumber2Task().get(first[i]));
-	    			taskBuilder.addChild(selection, appData.getNumber2Task().get(second[i]));
-	    			taskBuilder.addChild(sequence,selection);
-	    		}
-	    	}
-	    	
-	    	//TODO: Debug output
-	    	/*
-	    	for (int i =0;i<sequence.getChildren().size();i++) {
-	    		System.out.println(sequence.getChildren().get(i));
-	    	
-	    		if(sequence.getChildren().get(i).getType() == "selection") {
-	    			for(int j=0; j< ((ISelection) sequence.getChildren().get(i)).getChildren().size();j++) {
-	    				System.out.println("\t" +((ISelection) sequence.getChildren().get(i)).getChildren().get(j));
-	    			}
-	    		}
-	    	}
-	    	*/
-			return sequence;
-		}
-	
-	
+	ISequence matchAsSequence(RuleApplicationData appData, Match m) {
+
+		ISequence sequence = taskFactory.createNewSequence();
+
+		int[] first = m.getFirstSequence().getSequence();
+		int[] second = m.getSecondSequence().getSequence();
+
+		// Both sequences of a match are equally long
+		for (int i = 0; i < m.getFirstSequence().size(); i++) {
+
+			// Two gaps aligned to each other: Have not seen it happening so
+			// far, just to handle it
+			if (first[i] == -1 && second[i] == -1) {
+				// TODO: Do nothing?
+			}
+			// Both events are equal, we can simply add the task referring to
+			// the number
+			else if (first[i] == second[i]) {
+				taskBuilder.addChild(sequence,
+						appData.getNumber2Task().get(first[i]));
+			}
+			// We have a gap in the first sequence, we need to add the task of
+			// the second sequence as optional
+			else if (first[i] == -1 && second[i] != -1) {
+				IOptional optional = taskFactory.createNewOptional();
+				taskBuilder.setMarkedTask(optional, appData.getNumber2Task()
+						.get(second[i]));
+				taskBuilder.addChild(sequence, optional);
+			}
+			// We have a gap in the second sequence, we need to add the task of
+			// the first sequence as optional
+			else if (first[i] != -1 && second[i] == -1) {
+				IOptional optional = taskFactory.createNewOptional();
+				taskBuilder.setMarkedTask(optional, appData.getNumber2Task()
+						.get(first[i]));
+				taskBuilder.addChild(sequence, optional);
+			}
+			// Both tasks are unequal, we need to insert a selection here
+			else {
+				ISelection selection = taskFactory.createNewSelection();
+				taskBuilder.addChild(selection,
+						appData.getNumber2Task().get(first[i]));
+				taskBuilder.addChild(selection,
+						appData.getNumber2Task().get(second[i]));
+				taskBuilder.addChild(sequence, selection);
+			}
+		}
+
+		// TODO: Debug output
+		/*
+		 * for (int i =0;i<sequence.getChildren().size();i++) {
+		 * System.out.println(sequence.getChildren().get(i));
+		 * 
+		 * if(sequence.getChildren().get(i).getType() == "selection") { for(int
+		 * j=0; j< ((ISelection)
+		 * sequence.getChildren().get(i)).getChildren().size();j++) {
+		 * System.out.println("\t" +((ISelection)
+		 * sequence.getChildren().get(i)).getChildren().get(j)); } } }
+		 */
+		return sequence;
+	}
+
 	/**
 	 * <p>
@@ -659,5 +710,5 @@
 		appData.getStopWatch().start("detecting tasks");
 
-		//getSequencesOccuringMostOften(appData);
+		// getSequencesOccuringMostOften(appData);
 
 		appData.getStopWatch().stop("detecting tasks");
@@ -667,12 +718,9 @@
 
 		appData.getStopWatch().stop("replacing tasks");
-		
-		//Console.traceln(Level.INFO, "detected and replaced "
-		//		+ appData.getLastFoundTasks().size() + " tasks occuring "
-		//		+ appData.getLastFoundTasks().getOccurrenceCount() + " times");
-	}
-
-	
-
+
+		// Console.traceln(Level.INFO, "detected and replaced "
+		// + appData.getLastFoundTasks().size() + " tasks occuring "
+		// + appData.getLastFoundTasks().getOccurrenceCount() + " times");
+	}
 
 	/**
@@ -684,36 +732,27 @@
 		appData.detectedAndReplacedTasks(false);
 
-	/*
-			Console.traceln(Level.FINER, "replacing tasks occurrences");
-			
-			for (List<ITaskInstance> task : appData.getLastFoundTasks()) {
-				ISequence sequence = taskFactory.createNewSequence();
-
-				Console.traceln(Level.FINEST, "replacing " + sequence.getId()
-						+ ": " + task);
-
-				List<ISequenceInstance> sequenceInstances = replaceTaskOccurrences(
-						task, appData.getSessions(), sequence);
-
-				harmonizeSequenceInstancesModel(sequence, sequenceInstances,
-						task.size());
-				appData.detectedAndReplacedTasks(appData
-						.detectedAndReplacedTasks()
-						|| (sequenceInstances.size() > 0));
-
-				if (sequenceInstances.size() < appData.getLastFoundTasks()
-						.getOccurrenceCount()) {
-					Console.traceln(Level.FINE,
-							sequence.getId()
-									+ ": replaced task only "
-									+ sequenceInstances.size()
-									+ " times instead of expected "
-									+ appData.getLastFoundTasks()
-											.getOccurrenceCount());
-				}
-			}
-			*/
-	}
-
+		/*
+		 * Console.traceln(Level.FINER, "replacing tasks occurrences");
+		 * 
+		 * for (List<ITaskInstance> task : appData.getLastFoundTasks()) {
+		 * ISequence sequence = taskFactory.createNewSequence();
+		 * 
+		 * Console.traceln(Level.FINEST, "replacing " + sequence.getId() + ": "
+		 * + task);
+		 * 
+		 * List<ISequenceInstance> sequenceInstances = replaceTaskOccurrences(
+		 * task, appData.getSessions(), sequence);
+		 * 
+		 * harmonizeSequenceInstancesModel(sequence, sequenceInstances,
+		 * task.size()); appData.detectedAndReplacedTasks(appData
+		 * .detectedAndReplacedTasks() || (sequenceInstances.size() > 0));
+		 * 
+		 * if (sequenceInstances.size() < appData.getLastFoundTasks()
+		 * .getOccurrenceCount()) { Console.traceln(Level.FINE, sequence.getId()
+		 * + ": replaced task only " + sequenceInstances.size() +
+		 * " times instead of expected " + appData.getLastFoundTasks()
+		 * .getOccurrenceCount()); } }
+		 */
+	}
 
 	/**
@@ -847,5 +886,4 @@
 	}
 
-
 	/**
      * 
@@ -853,16 +891,12 @@
 	private static class RuleApplicationData {
 
-		
-		private HashMap<Integer,ITask> number2task;
-		
-		
+		private HashMap<Integer, ITask> number2task;
+
 		private ArrayList<NumberSequence> numberseqs;
-		
+
 		/**
          * 
          */
 		private List<IUserSession> sessions;
-
-
 
 		/**
@@ -887,7 +921,7 @@
 			this.sessions = sessions;
 			numberseqs = new ArrayList<NumberSequence>();
-			number2task = new HashMap<Integer,ITask>();
-			stopWatch= new StopWatch();
-			result =  new RuleApplicationResult();
+			number2task = new HashMap<Integer, ITask>();
+			stopWatch = new StopWatch();
+			result = new RuleApplicationResult();
 		}
 
@@ -899,10 +933,7 @@
 		}
 
-		
 		private ArrayList<NumberSequence> getNumberSequences() {
 			return numberseqs;
 		}
-
-	
 
 		/**
@@ -934,5 +965,5 @@
 		}
 
-		private HashMap<Integer,ITask> getNumber2Task() {
+		private HashMap<Integer, ITask> getNumber2Task() {
 			return number2task;
 		}
@@ -940,6 +971,3 @@
 	}
 
-	
-
-
 }
