[402635] Bugfix: correctly compare URI fragments (including slashes)

Change-Id: Iea0eb2a68e52f88879b0eff9af6906a635995cd8
Signed-off-by: Dietrich Travkin <travkin@gmx.de>
diff --git a/plugins/org.eclipse.sphinx.emf.validation/src/org/eclipse/sphinx/emf/validation/markers/ValidationMarkerManager.java b/plugins/org.eclipse.sphinx.emf.validation/src/org/eclipse/sphinx/emf/validation/markers/ValidationMarkerManager.java
index e0dc814..bdf33a4 100644
--- a/plugins/org.eclipse.sphinx.emf.validation/src/org/eclipse/sphinx/emf/validation/markers/ValidationMarkerManager.java
+++ b/plugins/org.eclipse.sphinx.emf.validation/src/org/eclipse/sphinx/emf/validation/markers/ValidationMarkerManager.java
@@ -63,6 +63,8 @@
  */

 public class ValidationMarkerManager {

 

+	private static final String URI_FRAGMENT_PARTS_SEPARATOR = "/"; //$NON-NLS-1$

+

 	/**

 	 * The singleton instance

 	 */

@@ -475,37 +477,10 @@
 				if (tmp != null && tmp.length > 0) {

 					markerURI = tmp[0];

 					markerEObjType = tmp.length > 1 ? tmp[1] : null;

-					Integer hash = (Integer) marker.getAttribute(IValidationMarker.HASH_ATTRIBUTE);

 

-					switch (depth) {

-					case EObjectUtil.DEPTH_ZERO:

-						// FIXME Remove hash code comparison by ResourceSetListener that deletes associated problem

-						// markers when model file gets deleted or reloaded (see ResourceProblemHandler for details)

-						if (URI.createURI(markerURI).fragment().equals(URI.createURI(eObjURI).fragment())

-								&& (markerEObjType == null || eObjType.equals(markerEObjType))) {

-							result.add(marker);

-						}

-						break;

-					case EObjectUtil.DEPTH_ONE: // same treatment, let's modify it later if necessary

-						boolean shouldbeDeleted = true;

-						shouldbeDeleted &= markerURI.contains(eObjURI);

-						if (shouldbeDeleted) {

-							String subPart = markerURI.substring(eObjURI.length());

-							shouldbeDeleted &= subPart.indexOf('/') == subPart.lastIndexOf('/');

-						}

-

-						if (shouldbeDeleted) {

-							result.add(marker);

-						}

-						break;

-					case EObjectUtil.DEPTH_INFINITE:

-						if (markerURI.equals(eObjURI) || markerURI.contains(eObjURI + "/")) { //$NON-NLS-1$

-							result.add(marker);

-						}

-						break;

-					default:

-						// Something is rotten in my kingdom, do nothing

-						break;

+					boolean showMarker = showMarker(eObjURI, markerURI, eObjType, markerEObjType, depth);

+					if (showMarker) {

+						result.add(marker);

 					}

 				}

 			} else {

@@ -519,6 +494,39 @@
 	}

 

 	/**

+	 * Internal method, only public to allow testing

+	 */

+	public boolean showMarker(String selectedObjectUri, String markerUri, String selectedEObjectType, String markerEObjType, int depth) {

+		if (depth == EObjectUtil.DEPTH_ZERO) {

+			return markerUri.equals(selectedObjectUri) && (markerEObjType == null || selectedEObjectType.equals(markerEObjType));

+		}

+

+		String selectedObjectUriFragment = URI.createURI(selectedObjectUri).fragment();

+		String markerUriFragment = URI.createURI(markerUri).fragment();

+

+		String[] elementUriFragmentParts = selectedObjectUriFragment.split(URI_FRAGMENT_PARTS_SEPARATOR);

+		String[] markerUriFragmentParts = markerUriFragment.split(URI_FRAGMENT_PARTS_SEPARATOR);

+

+		int indexOfLastElementUriFragmentPart = elementUriFragmentParts.length - 1;

+

+		// elementURI is prefix of markerURI

+		boolean showMarker = markerUri.startsWith(selectedObjectUri)

+				// last fragment part (String after last '/') has to be equal,

+				// not just prefix of the other String

+				// e.g. fragments "abc/xyz2" and "abc/xyz2/z" are not children of fragment "abc/xyz"

+				&& elementUriFragmentParts[indexOfLastElementUriFragmentPart].equals(markerUriFragmentParts[indexOfLastElementUriFragmentPart]);

+

+		switch (depth) {

+		case EObjectUtil.DEPTH_ONE:

+			return showMarker && elementUriFragmentParts.length + 1 >= markerUriFragmentParts.length;

+		case EObjectUtil.DEPTH_INFINITE:

+			return showMarker && elementUriFragmentParts.length <= markerUriFragmentParts.length;

+		default:

+			return true;

+		}

+	}

+

+	/**

 	 * check if an array of IMarker contains a marker with the status IStatus.ERROR

 	 *

 	 * @param markers

diff --git a/tests/org.eclipse.sphinx.tests.emf.validation/src/org/eclipse/sphinx/emf/validation/markers/ValidationMarkerManagerUriComparisonTest.java b/tests/org.eclipse.sphinx.tests.emf.validation/src/org/eclipse/sphinx/emf/validation/markers/ValidationMarkerManagerUriComparisonTest.java
new file mode 100644
index 0000000..e769564
--- /dev/null
+++ b/tests/org.eclipse.sphinx.tests.emf.validation/src/org/eclipse/sphinx/emf/validation/markers/ValidationMarkerManagerUriComparisonTest.java
@@ -0,0 +1,85 @@
+package org.eclipse.sphinx.emf.validation.markers;
+
+import static org.hamcrest.CoreMatchers.is;
+import static org.junit.Assert.assertThat;
+
+import java.util.Arrays;
+import java.util.List;
+
+import org.eclipse.sphinx.emf.util.EObjectUtil;
+import org.junit.BeforeClass;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.junit.runners.Parameterized;
+
+@RunWith(Parameterized.class)
+public class ValidationMarkerManagerUriComparisonTest {
+
+	private static final String SELECTED_ELEMENT_URI = "platform:/resource/validation-1/default.arxml#/ARRoot/Adc"; //$NON-NLS-1$
+
+	private String markerUri;
+	private boolean showMarkerForDepthZero, showMarkerForDepthOne, showMarkerForDepthInfinite;
+	private static ValidationMarkerManager markerManager;
+
+	// EObjectUtil.DEPTH_ZERO, EObjectUtil.DEPTH_ONE, EObjectUtil.DEPTH_INFINITE
+
+	@Parameterized.Parameters
+	public static List<Object[]> markerUriTestData() {
+		// | Marker URI | Show marker for DEPTH_ZERO | DEPTH_ONE | DEPTH_INFINITE |
+		return Arrays.asList(new Object[][] { { "platform:/resource/validation-1/default.arxml#/ARRoot/Adc", true, true, true }, //$NON-NLS-1$
+				{ "platform:/resource/validation-1/default.arxml#/ARRoot/Adc/AdcConfigSet", false, true, true }, //$NON-NLS-1$
+				{ "platform:/resource/validation-1/default.arxml#/ARRoot/Adc/AdcConfigSet/Abc", false, false, true }, //$NON-NLS-1$
+				{ "platform:/resource/validation-1/default.arxml#/ARRoot/Adc2", false, false, false }, //$NON-NLS-1$
+				{ "platform:/resource/validation-1/default.arxml#/ARRoot/Adc2/AdcConfigSet", false, false, false }, //$NON-NLS-1$
+				{ "platform:/resource/validation-1/default.arxml#/ARRoot/Adc2/AdcConfigSet/Abc", false, false, false } }); //$NON-NLS-1$
+	}
+
+	public ValidationMarkerManagerUriComparisonTest(String markerUri, boolean showMarkerForDepthZero, boolean showMarkerForDepthOne,
+			boolean showMarkerForDepthInfinite) {
+		this.markerUri = markerUri;
+		this.showMarkerForDepthZero = showMarkerForDepthZero;
+		this.showMarkerForDepthOne = showMarkerForDepthOne;
+		this.showMarkerForDepthInfinite = showMarkerForDepthInfinite;
+	}
+
+	@BeforeClass
+	public static void setUpOnce() {
+		markerManager = ValidationMarkerManager.getInstance();
+	}
+
+	@Test
+	public void checkMarkerCorrectlyFilteredForDepthZero() {
+		int depth = EObjectUtil.DEPTH_ZERO;
+
+		boolean showMarker = markerManager.showMarker(SELECTED_ELEMENT_URI, markerUri, "EObject", null, depth); //$NON-NLS-1$
+
+		assertThat(showMarker, is(showMarkerForDepthZero));
+
+		showMarker = markerManager.showMarker(SELECTED_ELEMENT_URI, markerUri, "EObject", "EObject", depth); //$NON-NLS-1$ //$NON-NLS-2$
+
+		assertThat(showMarker, is(showMarkerForDepthZero));
+
+		showMarker = markerManager.showMarker(SELECTED_ELEMENT_URI, markerUri, "EObject", "OtherType", depth); //$NON-NLS-1$ //$NON-NLS-2$
+
+		assertThat(showMarker, is(false));
+	}
+
+	@Test
+	public void checkMarkerCorrectlyFilteredForDepthOne() {
+		int depth = EObjectUtil.DEPTH_ONE;
+
+		boolean showMarker = markerManager.showMarker(SELECTED_ELEMENT_URI, markerUri, "EObject", null, depth); //$NON-NLS-1$
+
+		assertThat(showMarker, is(showMarkerForDepthOne));
+	}
+
+	@Test
+	public void checkMarkerCorrectlyFilteredForDepthInfinite() {
+		int depth = EObjectUtil.DEPTH_INFINITE;
+
+		boolean showMarker = markerManager.showMarker(SELECTED_ELEMENT_URI, markerUri, "EObject", null, depth); //$NON-NLS-1$
+
+		assertThat(showMarker, is(showMarkerForDepthInfinite));
+	}
+
+}