Use ID hashes for Elastic, improved test coverage
diff --git a/org.eclipse.opencert.elastic.test/src/org/eclipse/opencert/elastic/EObjectToJsonTest.java b/org.eclipse.opencert.elastic.test/src/org/eclipse/opencert/elastic/EObjectToJsonTest.java
index 81771a9..5c6408a 100644
--- a/org.eclipse.opencert.elastic.test/src/org/eclipse/opencert/elastic/EObjectToJsonTest.java
+++ b/org.eclipse.opencert.elastic.test/src/org/eclipse/opencert/elastic/EObjectToJsonTest.java
@@ -12,6 +12,8 @@
  ******************************************************************************/

 package org.eclipse.opencert.elastic;

 

+import java.util.Iterator;

+

 import org.eclipse.emf.ecore.EObject;

 import org.junit.Assert;

 import org.junit.Test;

@@ -36,7 +38,8 @@
 	

 	@Test

 	public void testUML() {

-		EObject elem = TestData.uml().next();

+		Iterator<EObject> it = TestData.uml();

+		EObject elem = it.next();

 		JsonObject json = EObjectToJson.INSTANCE.convert(elem);

 		Assert.assertNotNull(json);

 		System.out.println(json.toString());

diff --git a/org.eclipse.opencert.elastic.test/src/org/eclipse/opencert/elastic/ElasticClientTest.java b/org.eclipse.opencert.elastic.test/src/org/eclipse/opencert/elastic/ElasticClientTest.java
index 4c77f1b..6da9035 100644
--- a/org.eclipse.opencert.elastic.test/src/org/eclipse/opencert/elastic/ElasticClientTest.java
+++ b/org.eclipse.opencert.elastic.test/src/org/eclipse/opencert/elastic/ElasticClientTest.java
@@ -36,8 +36,13 @@
 	}

 

 	@Test

+	public void testDelete() throws Exception {

+		ElasticClientImpl.on("localhost", 9200, "http").delete("amass-test").close();

+	}

+	

+	@Test

 	public void testSendMany() throws Exception {

-		List<ElasticDocument> documents = EObjectToDocument.INSTANCE.convert(TestData.uml(), "amass-test");

+		List<ElasticDocument> documents = EObjectToDocument.INSTANCE.convert(TestData.uml(50), "amass-test");

 		ElasticClientImpl.on("localhost", 9200, "http").storeAll(documents.iterator()).close();

 	}

 	

@@ -45,7 +50,7 @@
 	public void testSendAndSearch() throws Exception {

 		Component object = TestData.createComponent();

 		ElasticDocument document = EObjectToDocument.INSTANCE.convert(object, "amass-test");

-		ElasticClient client = ElasticClientImpl.on("localhost", 9200, "http")/*.delete("amass-test")*/.store(document);

+		ElasticClient client = ElasticClientImpl.on("localhost", 9200, "http").delete("amass-test").store(document);

 		Set<ElasticDocument> hits = client.search("amass-test", null, null);

 		Assert.assertEquals(1, hits.size());

 		//

diff --git a/org.eclipse.opencert.elastic.test/src/org/eclipse/opencert/elastic/ElasticFinderTest.java b/org.eclipse.opencert.elastic.test/src/org/eclipse/opencert/elastic/ElasticFinderTest.java
index 6a29336..ce3291f 100644
--- a/org.eclipse.opencert.elastic.test/src/org/eclipse/opencert/elastic/ElasticFinderTest.java
+++ b/org.eclipse.opencert.elastic.test/src/org/eclipse/opencert/elastic/ElasticFinderTest.java
@@ -13,16 +13,26 @@
 package org.eclipse.opencert.elastic;

 

 import java.util.HashMap;

+import java.util.List;

 import java.util.Map;

 import java.util.Set;

 

+import org.eclipse.opencert.elastic.search.ElasticFinder;

 import org.eclipse.opencert.elastic.search.ElasticFinderImpl;

 import org.eclipse.opencert.elastic.search.Hit;

 import org.junit.Assert;

+import org.junit.BeforeClass;

 import org.junit.Test;

 

 public class ElasticFinderTest {

 

+	@BeforeClass

+	public static void setup() throws Exception {

+		System.out.println("Indexing UML classes...");

+		List<ElasticDocument> documents = EObjectToDocument.INSTANCE.convert(TestData.umlClasses(), "amass-test");

+		ElasticClientImpl.on("localhost", 9200, "http").storeAll(documents.iterator()).close();

+	}

+	

 	@Test

 	public void testSearch() throws Exception {

 		ElasticClient client = ElasticClientImpl.on("localhost", 9200, "http");

@@ -40,53 +50,77 @@
 

 	@Test

 	public void testNoHit() throws Exception {

+		testNoHit(ElasticFinderImpl.onDummy(TestData.uml()));

+		// we use indexed UML meta model for testing

+		testNoHit(ElasticFinderImpl.onDefaultClient());

+	}

+	

+	private void testNoHit(ElasticFinder finder) throws Exception {

 		// there is no "Requirement" in UML

-		Set<Hit> hits = ElasticFinderImpl.onDummy(TestData.uml()).search("Requirement", null);

+		Set<Hit> hits = finder.search("Requirement", null);

 		Assert.assertNotNull("set expected", hits);

 		Assert.assertTrue("empty set expected", hits.isEmpty());

 	}

 

 	@Test

 	public void testHit() throws Exception {

+		// we use UML dummy meta model for testing

+		testHit(ElasticFinderImpl.onDummy(TestData.uml()));

+		// we use indexed UML meta model for testing

+		testHit(ElasticFinderImpl.onDefaultClient());

+	}

+	

+	private void testHit(ElasticFinder finder) throws Exception {

 		// we should find the "Component" class

-		Set<Hit> hits = ElasticFinderImpl.onDummy(TestData.uml()).search("Component", null);

+		Set<Hit> hits = finder.search("Component", null);

 		Assert.assertNotNull("set expected", hits);

 		Assert.assertFalse("filled set expected", hits.isEmpty());

 

 		Hit firstHit = hits.iterator().next();

 		Assert.assertTrue("score must be > 0", firstHit.score > 0);

 	}

-

+	

 	@Test

 	public void testHitWithExpression() throws Exception {

-		Set<Hit> hits = ElasticFinderImpl.onDummy(TestData.uml()).search(".*ompon.*", null);

+		testHitWithExpression(ElasticFinderImpl.onDummy(TestData.uml()));

+		testHitWithExpression(ElasticFinderImpl.onDefaultClient());

+	}

+	

+	private void testHitWithExpression(ElasticFinder finder) throws Exception {

+		Set<Hit> hits = finder.search(".*ompon.*", null);

 		Assert.assertNotNull("set expected", hits);

 		Assert.assertFalse("filled set expected", hits.isEmpty());

 	}

 

 	@Test

 	public void testHitWithNegativeFilter() throws Exception {

-		// we use UML meta model for testing

+		testHitWithNegativeFilter(ElasticFinderImpl.onDummy(TestData.uml()));

+		testHitWithNegativeFilter(ElasticFinderImpl.onDefaultClient());

+	}

 

+	private void testHitWithNegativeFilter(ElasticFinder finder) throws Exception {

 		Map<String, Object> filters = new HashMap<>();

 		filters.put("abstract", Boolean.TRUE);

-		Set<Hit> hits = ElasticFinderImpl.onDummy(TestData.uml()).search("Component", filters);

+		Set<Hit> hits = finder.search("Component", filters);

 		Assert.assertNotNull("set expected", hits);

 		Assert.assertTrue("empty set expected - Component is not abstract", hits.isEmpty());

 	}

 

 	@Test

 	public void testHitWithPositiveFilter() throws Exception {

+		testHitWithPositiveFilter(ElasticFinderImpl.onDummy(TestData.uml()));

+		testHitWithPositiveFilter(ElasticFinderImpl.onDefaultClient());

+	}

+	

+	private void testHitWithPositiveFilter(ElasticFinder finder) throws Exception {

 		Map<String, Object> filters = new HashMap<>();

 		filters.put("abstract", Boolean.FALSE);

 		filters.put("interface", Boolean.FALSE);

-		Set<Hit> hits = ElasticFinderImpl.onDummy(TestData.uml()).search("Component", filters);

+		Set<Hit> hits = finder.search("Component", filters);

 		Assert.assertNotNull("set expected", hits);

 		Assert.assertFalse("filled set expected - Component is not abstract", hits.isEmpty());

 

 		Hit firstHit = hits.iterator().next();

 		Assert.assertTrue("score must be > 1 (due to filters matched)", firstHit.score > 1);

-

-		System.out.println(hits);

 	}

 }

diff --git a/org.eclipse.opencert.elastic.test/src/org/eclipse/opencert/elastic/TestData.java b/org.eclipse.opencert.elastic.test/src/org/eclipse/opencert/elastic/TestData.java
index a132260..d6619fb 100644
--- a/org.eclipse.opencert.elastic.test/src/org/eclipse/opencert/elastic/TestData.java
+++ b/org.eclipse.opencert.elastic.test/src/org/eclipse/opencert/elastic/TestData.java
@@ -12,9 +12,12 @@
  ******************************************************************************/

 package org.eclipse.opencert.elastic;

 

+import java.util.ArrayList;

 import java.util.Iterator;

+import java.util.List;

 

 import org.eclipse.emf.common.util.URI;

+import org.eclipse.emf.ecore.EClass;

 import org.eclipse.emf.ecore.EObject;

 import org.eclipse.emf.ecore.resource.impl.ResourceImpl;

 import org.eclipse.uml2.uml.Component;

@@ -32,21 +35,53 @@
 	static Component createComponent() {

 		return createComponent(false);

 	}

-	

+

 	static Component createComponent(boolean inResource) {

 		Component comp = UMLFactory.eINSTANCE.createComponent();

 		comp.setName("Component A");

 		comp.setVisibility(VisibilityKind.PUBLIC_LITERAL);

-		

+

 		if (inResource) {

 			ResourceImpl res = new ResourceImpl(URI.createURI("custom:somewhere"));

 			res.getContents().add(comp);

 		}

-		

+

 		return comp;

 	}

-	

+

 	static Iterator<EObject> uml() {

 		return UMLPackage.eINSTANCE.eAllContents();

 	}

+

+	static Iterator<EObject> umlClasses() {

+		List<EObject> classes = new ArrayList<>();

+		Iterator<EObject> it = uml();

+		while (it.hasNext()) {

+			EObject object = (EObject) it.next();

+			if (object instanceof EClass) {

+				classes.add(object);

+			}

+		}

+		

+		System.out.println("Classes: " + classes.size());

+		return classes.iterator();

+	}

+	

+	static Iterator<EObject> uml(final int max) {

+		return new Iterator<EObject>() {

+			private Iterator<EObject> delegate = UMLPackage.eINSTANCE.eAllContents();

+			private long i = 0;

+

+			@Override

+			public boolean hasNext() {

+				return i < max && delegate.hasNext();

+			}

+

+			@Override

+			public EObject next() {

+				i++;

+				return delegate.next();

+			}

+		};

+	}

 }

diff --git a/org.eclipse.opencert.elastic/build.properties b/org.eclipse.opencert.elastic/build.properties
index 6165ef1..ef66ef1 100644
--- a/org.eclipse.opencert.elastic/build.properties
+++ b/org.eclipse.opencert.elastic/build.properties
@@ -2,15 +2,4 @@
 output.. = bin/

 bin.includes = META-INF/,\

                .,\

-               lib/,\

-               lib/elastic/elasticsearch-rest-client-5.6.1.jar,\

-               lib/elastic/elasticsearch-rest-high-level-client-5.6.1.jar,\

-               lib/elastic/elasticsearch-5.6.1.jar,\

-               lib/elastic/lucene-core-6.6.1.jar,\

-               lib/elastic/log4j-api-2.11.1.jar,\

-               lib/elastic/jackson-core-2.8.6.jar,\

-               lib/elastic/joda-time-2.9.5.jar,\

-               lib/elastic/hppc-0.7.1.jar,\

-               lib/elastic/log4j-core-2.11.1.jar,\

-               lib/elastic/lucene-queryparser-6.6.1.jar,\

-               plugin.xml

+               lib/

diff --git a/org.eclipse.opencert.elastic/src/org/eclipse/opencert/elastic/EObjectToDocument.java b/org.eclipse.opencert.elastic/src/org/eclipse/opencert/elastic/EObjectToDocument.java
index 7949f56..aee7a62 100644
--- a/org.eclipse.opencert.elastic/src/org/eclipse/opencert/elastic/EObjectToDocument.java
+++ b/org.eclipse.opencert.elastic/src/org/eclipse/opencert/elastic/EObjectToDocument.java
@@ -16,8 +16,11 @@
 import java.util.Iterator;

 import java.util.List;

 

+import org.apache.commons.codec.digest.DigestUtils;

+import org.eclipse.emf.ecore.EAnnotation;

 import org.eclipse.emf.ecore.EClass;

 import org.eclipse.emf.ecore.EObject;

+import org.eclipse.emf.ecore.impl.EStringToStringMapEntryImpl;

 import org.eclipse.emf.ecore.resource.Resource;

 

 import com.google.gson.JsonObject;

@@ -50,7 +53,7 @@
 

 		JsonObject source = EObjectToJson.INSTANCE.convert(object);

 		ElasticDocument doc = new ElasticDocument(source, index, type != null ? type.getName() : "EObject",

-				resource != null ? resource.getURIFragment(object) : "null");

+				resource != null ? DigestUtils.md5Hex(resource.getURIFragment(object)) : "null");

 		return doc;

 	}

 

diff --git a/org.eclipse.opencert.elastic/src/org/eclipse/opencert/elastic/EObjectToJson.java b/org.eclipse.opencert.elastic/src/org/eclipse/opencert/elastic/EObjectToJson.java
index 631e6e5..24775ad 100644
--- a/org.eclipse.opencert.elastic/src/org/eclipse/opencert/elastic/EObjectToJson.java
+++ b/org.eclipse.opencert.elastic/src/org/eclipse/opencert/elastic/EObjectToJson.java
@@ -14,9 +14,11 @@
 

 import org.eclipse.emf.common.util.EList;

 import org.eclipse.emf.common.util.URI;

+import org.eclipse.emf.ecore.EAnnotation;

 import org.eclipse.emf.ecore.EAttribute;

 import org.eclipse.emf.ecore.EClass;

 import org.eclipse.emf.ecore.EObject;

+import org.eclipse.emf.ecore.impl.EStringToStringMapEntryImpl;

 import org.eclipse.emf.ecore.resource.Resource;

 

 import com.google.gson.JsonObject;

@@ -84,6 +86,15 @@
 		Resource resource = object.eResource();

 		if (resource != null) {

 			String fragment = resource.getURIFragment(object);

+			if (object instanceof EAnnotation) {

+				// TODO We have problems with annotations

+				fragment = "/#";

+			}

+			else if (object instanceof EStringToStringMapEntryImpl) {

+				// TODO We have problems with these maps

+				fragment = "/#";

+			}

+			

 			URI uri = resource.getURI().appendFragment(fragment);

 			String uriString = uri.toString();

 			jsonObject.addProperty("uri", uriString);

diff --git a/org.eclipse.opencert.elastic/src/org/eclipse/opencert/elastic/ElasticClientImpl.java b/org.eclipse.opencert.elastic/src/org/eclipse/opencert/elastic/ElasticClientImpl.java
index f743efe..b363579 100644
--- a/org.eclipse.opencert.elastic/src/org/eclipse/opencert/elastic/ElasticClientImpl.java
+++ b/org.eclipse.opencert.elastic/src/org/eclipse/opencert/elastic/ElasticClientImpl.java
@@ -20,6 +20,7 @@
 import java.util.HashSet;

 import java.util.Iterator;

 import java.util.Map;

+import java.util.Map.Entry;

 import java.util.Set;

 

 import org.apache.http.HttpEntity;

@@ -34,6 +35,7 @@
 import org.elasticsearch.client.RestHighLevelClient;

 import org.elasticsearch.index.query.QueryBuilder;

 import org.elasticsearch.index.query.QueryBuilders;

+import org.elasticsearch.index.query.QueryStringQueryBuilder;

 import org.elasticsearch.search.SearchHit;

 import org.elasticsearch.search.SearchHits;

 import org.elasticsearch.search.builder.SearchSourceBuilder;

@@ -104,7 +106,10 @@
 		// find the best query builder depending on the arguments

 		QueryBuilder queryBuilder = QueryBuilders.matchAllQuery();

 		if (queryString != null) {

-			queryBuilder = QueryBuilders.queryStringQuery(queryString);

+			queryString = queryString.replaceAll(".*", "*");

+			QueryStringQueryBuilder stringQuery = QueryBuilders.queryStringQuery(queryString);

+			stringQuery.allowLeadingWildcard(true);

+			queryBuilder = stringQuery;

 		}

 		sourceBuilder.query(queryBuilder);

 		

@@ -114,8 +119,8 @@
 		

 		Set<ElasticDocument> result = new HashSet<>();

 		SearchHits hits = response.getHits();

-		for (int i=0; i< hits.totalHits; i++) {

-			SearchHit hit = hits.getAt(i);

+		// Note: total hits might be much bigger 

+		for (SearchHit hit : hits.getHits()) {

 			// convert Hit to Json

 			JsonObject json = new JsonObject();

 			

diff --git a/org.eclipse.opencert.elastic/src/org/eclipse/opencert/elastic/search/ElasticFinderImpl.java b/org.eclipse.opencert.elastic/src/org/eclipse/opencert/elastic/search/ElasticFinderImpl.java
index fe40dff..111ff6d 100644
--- a/org.eclipse.opencert.elastic/src/org/eclipse/opencert/elastic/search/ElasticFinderImpl.java
+++ b/org.eclipse.opencert.elastic/src/org/eclipse/opencert/elastic/search/ElasticFinderImpl.java
@@ -20,6 +20,7 @@
 

 import org.eclipse.opencert.elastic.ElasticClient;

 import org.eclipse.opencert.elastic.ElasticClientImpl;

+import org.eclipse.opencert.elastic.ElasticDocument;

 

 /**

  * Factory for the {@link ElasticFinder}.

@@ -71,13 +72,19 @@
 		}

 		

 		try {

-			this.client.search("_all", query, filters);

+			Set<Hit> hits = new HashSet<>();

+			Set<ElasticDocument> documents = this.client.search("_all", query, filters);

+			for (ElasticDocument document : documents) {

+				Hit hit = new Hit();

+				hit.score = 1;

+				hit.objectId = document.id;

+				hits.add(hit);

+			}

+			return hits;

 		} catch (Exception e) {

-			// TODO Auto-generated catch block

 			e.printStackTrace();

+			return Collections.emptySet();

 		}

-		

-		return Collections.emptySet();

 	}

 

 	/*

@@ -88,7 +95,6 @@
 		for (Object data : dummyData) {

 			String document = DummyData.INSTANCE.asDocument(data);

 			if ((document.contains(query) || document.matches(query)) && matchFilters(document, filters)) {

-				matchFilters(document, filters);

 				Hit hit = new Hit();

 				// we count 1 for string match + number of filters

 				hit.score = 1 + (filters != null ? filters.size() : 0);