Index: /trunk/de.ugoe.cs.swe.bnftools.ebnf/src/de/ugoe/cs/swe/bnftools/validation/DuplicateEntry.java
===================================================================
--- /trunk/de.ugoe.cs.swe.bnftools.ebnf/src/de/ugoe/cs/swe/bnftools/validation/DuplicateEntry.java	(revision 52)
+++ /trunk/de.ugoe.cs.swe.bnftools.ebnf/src/de/ugoe/cs/swe/bnftools/validation/DuplicateEntry.java	(revision 53)
@@ -27,5 +27,6 @@
 
 	public void addRule(Rule r) {
-		rules.add(r);
+		if (!rules.contains(r))
+			rules.add(r);
 	}
 	
Index: /trunk/de.ugoe.cs.swe.bnftools.ebnf/src/de/ugoe/cs/swe/bnftools/validation/EbnfJavaValidator.java
===================================================================
--- /trunk/de.ugoe.cs.swe.bnftools.ebnf/src/de/ugoe/cs/swe/bnftools/validation/EbnfJavaValidator.java	(revision 52)
+++ /trunk/de.ugoe.cs.swe.bnftools.ebnf/src/de/ugoe/cs/swe/bnftools/validation/EbnfJavaValidator.java	(revision 53)
@@ -2,4 +2,6 @@
 
 import java.util.ArrayList;
+import java.util.Collection;
+import java.util.Collections;
 import java.util.HashMap;
 import java.util.HashSet;
@@ -383,6 +385,6 @@
 		}
 		
-		// create warnings
-		
+		// create longest matches
+		HashMap<String, RuleDuplication> rulePairMap = new HashMap<String, RuleDuplication>();
 		Iterator<String> it = taggedEntries.iterator();
 		
@@ -390,31 +392,59 @@
 			String entry = it.next();
 			DuplicateEntry dupeEntry = dupesMap.get(entry);
+			
 			if (dupeEntry.getRules().size() < 2)
 				continue;
 			
-			String warningText = "";
-			warningText += ">>" + entry + "<< is duplicated in the following rules: ";
+			ArrayList<Integer> matchingLines = new ArrayList<Integer>(); 
 			for (int i=0; i < dupeEntry.getRules().size(); i++) {
 				Rule rule = dupeEntry.getRules().get(i);
 				CompositeNode parserNode = NodeUtil.getNodeAdapter(rule).getParserNode();
-
-				if (rule.getRulenumber() > 0) {
-					String ruleNumber = Integer.toString(rule.getRulenumber()).replaceAll("[ \t\n\r]", ""); 
-					warningText += ruleNumber;
-				}
-				warningText += " (Line ";
-				warningText += parserNode.getLine();
-				warningText += ")";
+				matchingLines.add(parserNode.getLine());
+			}
+			
+			Collections.sort(matchingLines);
+			
+			RuleDuplication rulePair = rulePairMap.get(matchingLines.toString());
+			if (rulePair == null) {
+				rulePair = new RuleDuplication();
+			} 
+			rulePair.addDupe(dupeEntry);
+			rulePairMap.put(matchingLines.toString(), rulePair);
+		}
+
+		// create warnings
+		Iterator<RuleDuplication> it2 = rulePairMap.values().iterator();
+		
+		while (it2.hasNext()) {
+			RuleDuplication rulePair = it2.next();
+			List<DuplicateEntry> dupes = rulePair.getFilteredDupes();
+			
+			for (int i=0; i < dupes.size(); i++) {
+				DuplicateEntry dupeEntry = dupes.get(i);
 				
-				if (i+1 < dupeEntry.getRules().size())
-					warningText += ", ";
-
-			}
-
-			Rule rule = dupeEntry.getRules().get(0);
-			CompositeNode parserNode = NodeUtil.getNodeAdapter(rule).getParserNode();
-			warning(warningText, parserNode.getElement(), 1);
-		}
-		
+				String warningText = "";
+				warningText += ">>" + dupeEntry.getSnippet() + "<< is duplicated in the following rules: ";
+				for (int j=0; j < dupeEntry.getRules().size(); j++) {
+					Rule rule = dupeEntry.getRules().get(j);
+					CompositeNode parserNode = NodeUtil.getNodeAdapter(rule).getParserNode();
+	
+					if (rule.getRulenumber() > 0) {
+						String ruleNumber = Integer.toString(rule.getRulenumber()).replaceAll("[ \t\n\r]", ""); 
+						warningText += ruleNumber;
+					}
+					warningText += " (Line ";
+					warningText += parserNode.getLine();
+					warningText += ")";
+					
+					if (j+1 < dupeEntry.getRules().size())
+						warningText += ", ";
+	
+				}
+	
+				Rule rule = dupeEntry.getRules().get(0);
+				CompositeNode parserNode = NodeUtil.getNodeAdapter(rule).getParserNode();
+				warning(warningText, parserNode.getElement(), 1);
+			}
+		}
 	}
 
Index: /trunk/de.ugoe.cs.swe.bnftools.ebnf/src/de/ugoe/cs/swe/bnftools/validation/RuleDuplication.java
===================================================================
--- /trunk/de.ugoe.cs.swe.bnftools.ebnf/src/de/ugoe/cs/swe/bnftools/validation/RuleDuplication.java	(revision 53)
+++ /trunk/de.ugoe.cs.swe.bnftools.ebnf/src/de/ugoe/cs/swe/bnftools/validation/RuleDuplication.java	(revision 53)
@@ -0,0 +1,52 @@
+package de.ugoe.cs.swe.bnftools.validation;
+
+import java.util.ArrayList;
+import java.util.List;
+
+public class RuleDuplication {
+	List<DuplicateEntry> dupes = new ArrayList<DuplicateEntry>();
+
+	public List<DuplicateEntry> getDupes() {
+		return dupes;
+	}
+
+	public void setDupes(List<DuplicateEntry> dupes) {
+		this.dupes = dupes;
+	}
+	
+	public void addDupe(DuplicateEntry dupe) {
+		dupes.add(dupe);
+	}
+	
+	public List<DuplicateEntry> getFilteredDupes() {
+		ArrayList<DuplicateEntry> dupesFiltered = new ArrayList<DuplicateEntry>();
+		
+		dupesFiltered.addAll(dupes);
+		
+		boolean change = true;
+		while (change) {
+			change = false;			
+			for (int i=0; i < dupesFiltered.size(); i++) {
+				for (int j=0; j < dupesFiltered.size(); j++) {
+					DuplicateEntry dupeA = dupesFiltered.get(i);
+					DuplicateEntry dupeB = dupesFiltered.get(j);
+					
+					if (dupeA.getSnippet().contains(dupeB.getSnippet()) && !dupeA.getSnippet().equals(dupeB.getSnippet())) {
+						dupesFiltered.remove(j);
+						change = true;
+					} else if (dupeB.getSnippet().contains(dupeA.getSnippet()) && !dupeB.getSnippet().equals(dupeA.getSnippet())) {
+						dupesFiltered.remove(i);
+						change = true;
+					}
+					if (change)
+						break;
+				}
+				if (change)
+					break;
+			}
+		}
+		
+		return dupesFiltered;
+	}
+	
+}
