From b33f335abf3ebdc51aa4d4627241d8a99b3b1c78 Mon Sep 17 00:00:00 2001
From: Simon Barner <barner@fortiss.org>
Date: Wed, 3 Apr 2019 11:37:54 +0200
Subject: [PATCH] getEClassForClass(): Also cache list of registered EPackages

* Obtaining EPackages from the registry is expensive.
* This speeds every (n > 1)th invocation of the method, regardless
  of the class for which the EClass is required.
* The cache that directly memorizes previously computed results is
  kept.

Issue-Ref: 3675
Issue-Url: https://af3-developer.fortiss.org/issues/3675

Signed-off-by: Simon Barner <barner@fortiss.org>
---
 .../org/fortiss/tooling/kernel/utils/.ratings |  2 +-
 .../tooling/kernel/utils/EcoreUtils.java      | 40 ++++++++++++-------
 2 files changed, 27 insertions(+), 15 deletions(-)

diff --git a/org.fortiss.tooling.kernel/src/org/fortiss/tooling/kernel/utils/.ratings b/org.fortiss.tooling.kernel/src/org/fortiss/tooling/kernel/utils/.ratings
index 5d3e20c3c..b6571fd3e 100644
--- a/org.fortiss.tooling.kernel/src/org/fortiss/tooling/kernel/utils/.ratings
+++ b/org.fortiss.tooling.kernel/src/org/fortiss/tooling/kernel/utils/.ratings
@@ -2,7 +2,7 @@ CompositionUtils.java 34c0a191bd0fb4176c94b4d61abb5c88a679d5e8 GREEN
 ConstraintsUtils.java 0f8be020f2ca4bb08931c32452163c04a28e30ce GREEN
 EMFResourceUtils.java 979d0e1f4f66a2b3e715d2da0ebef6493f547fd7 GREEN
 EcoreSerializerBase.java 0a0c2969d793d2e68094c55c8f7b0a662ef6e5d5 GREEN
-EcoreUtils.java accd567a0dcd1447d6f3e112f19fe8d53862d0cb GREEN
+EcoreUtils.java 91087233c50130c4abde858d892c6a1e7991e1bf YELLOW
 ExtensionPointUtils.java 7ce63242b49eb9a7cd4eaadd223f5ebce1dfd75b GREEN
 HierarchicalNameComparator.java 6face1b673126701a0721af48ead2f9766c17d46 GREEN
 IdentifierUtils.java fff43dc4e84cdd89c3ece4f5d9d89aec4b0749c2 GREEN
diff --git a/org.fortiss.tooling.kernel/src/org/fortiss/tooling/kernel/utils/EcoreUtils.java b/org.fortiss.tooling.kernel/src/org/fortiss/tooling/kernel/utils/EcoreUtils.java
index accd567a0..91087233c 100644
--- a/org.fortiss.tooling.kernel/src/org/fortiss/tooling/kernel/utils/EcoreUtils.java
+++ b/org.fortiss.tooling.kernel/src/org/fortiss/tooling/kernel/utils/EcoreUtils.java
@@ -489,9 +489,15 @@ public class EcoreUtils {
 		return copyRefMap;
 	}
 
-	/** Map to cache potentially expensive lookups in {@link #getEClassForClass(Class)}. */
+	/** Map to cache expensive lookups in {@link #getEClassForClass(Class)}. */
 	private static Map<Class<?>, EClass> clazz2EClassCache = new HashMap<Class<?>, EClass>();
 
+	/**
+	 * Cached list of registered {@link EPackage}s (lazy initialized in
+	 * {@link #getEClassForClass(Class)}).
+	 */
+	private static List<EPackage> ePackagesCache = null;
+
 	/**
 	 * <p>
 	 * Determines the {@link EClass} corresponding to a give {@code clazz} (typically the interface
@@ -504,23 +510,29 @@ public class EcoreUtils {
 	 * </p>
 	 */
 	public static synchronized EClass getEClassForClass(Class<?> clazz) {
-		EClass eClass = null;
+		// Return cached result if it exists
+		EClass eClass = clazz2EClassCache.get(clazz);
+		if(eClass != null) {
+			return eClass;
+		}
 
-		if(clazz2EClassCache.containsKey(clazz)) {
-			return clazz2EClassCache.get(clazz);
+		// If needed, initialize list of registered EPackages
+		if(ePackagesCache == null) {
+			ePackagesCache = new ArrayList<>();
+			Registry registry = EPackage.Registry.INSTANCE;
+			for(String key : new HashSet<String>(registry.keySet())) {
+				try {
+					ePackagesCache.add(registry.getEPackage(key));
+				} catch(Exception e) {
+					System.out.println("Error: EPackage for \"" + key +
+							"\" has not been registered (in extension point \"org.eclipse.emf.ecore.generated_package\").");
+					continue;
+				}
+			}
 		}
 
 		// Query all registered EPackages for the given clazz
-		Registry registry = EPackage.Registry.INSTANCE;
-		for(String key : new HashSet<String>(registry.keySet())) {
-			EPackage ePackage;
-			try {
-				ePackage = registry.getEPackage(key);
-			} catch(Exception e) {
-				System.out.println("Error: EPackage for \"" + key +
-						"\" has not been registered (in extension point \"org.eclipse.emf.ecore.generated_package\").");
-				continue;
-			}
+		for(EPackage ePackage : ePackagesCache) {
 			for(EClassifier eClassifier : ePackage.getEClassifiers()) {
 				if(eClassifier instanceof EClass && eClassifier.getInstanceClass() != null &&
 						clazz.isAssignableFrom(eClassifier.getInstanceClass())) {
-- 
GitLab