summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorStefan Winkler2010-12-21 02:58:58 (EST)
committerStefan Winkler2010-12-21 02:58:58 (EST)
commit371f9244d036a04a73db4632276c91f11fc0f058 (patch)
tree460dfc4d7d9aad8491be2fb31edb26f54a13def2
parenta5c56b1f64830155431b7067f70c39048f019a65 (diff)
downloadcdo-371f9244d036a04a73db4632276c91f11fc0f058.zip
cdo-371f9244d036a04a73db4632276c91f11fc0f058.tar.gz
cdo-371f9244d036a04a73db4632276c91f11fc0f058.tar.bz2
[332912] Caching subtype-relationships in the CDOPackageRegistry
https://bugs.eclipse.org/bugs/show_bug.cgi?id=332912
-rw-r--r--plugins/org.eclipse.emf.cdo.common/src/org/eclipse/emf/cdo/common/model/CDOModelUtil.java47
-rw-r--r--plugins/org.eclipse.emf.cdo.common/src/org/eclipse/emf/cdo/common/model/CDOPackageRegistry.java10
-rw-r--r--plugins/org.eclipse.emf.cdo.common/src/org/eclipse/emf/cdo/internal/common/model/CDOPackageRegistryImpl.java18
-rw-r--r--plugins/org.eclipse.emf.cdo.tests/SubclassTest1.ecore21
-rw-r--r--plugins/org.eclipse.emf.cdo.tests/SubclassTest2.ecore8
-rw-r--r--plugins/org.eclipse.emf.cdo.tests/src/org/eclipse/emf/cdo/tests/PackageRegistryTest.java84
6 files changed, 188 insertions, 0 deletions
diff --git a/plugins/org.eclipse.emf.cdo.common/src/org/eclipse/emf/cdo/common/model/CDOModelUtil.java b/plugins/org.eclipse.emf.cdo.common/src/org/eclipse/emf/cdo/common/model/CDOModelUtil.java
index dafb50d..4858e78 100644
--- a/plugins/org.eclipse.emf.cdo.common/src/org/eclipse/emf/cdo/common/model/CDOModelUtil.java
+++ b/plugins/org.eclipse.emf.cdo.common/src/org/eclipse/emf/cdo/common/model/CDOModelUtil.java
@@ -7,9 +7,11 @@
*
* Contributors:
* Eike Stepper - initial API and implementation
+ * Stefan Winkler - Bug 332912 - Caching subtype-relationships in the CDOPackageRegistry
*/
package org.eclipse.emf.cdo.common.model;
+import org.eclipse.emf.cdo.internal.common.bundle.OM;
import org.eclipse.emf.cdo.internal.common.messages.Messages;
import org.eclipse.emf.cdo.internal.common.model.CDOClassInfoImpl;
import org.eclipse.emf.cdo.internal.common.model.CDOPackageInfoImpl;
@@ -42,7 +44,9 @@ import java.io.IOException;
import java.text.MessageFormat;
import java.util.ArrayList;
import java.util.Date;
+import java.util.HashMap;
import java.util.List;
+import java.util.Map;
/**
* @author Eike Stepper
@@ -518,4 +522,47 @@ public final class CDOModelUtil
}
}
}
+
+ /**
+ * @since 4.0
+ */
+ public static Map<EClass, List<EClass>> getSubTypes(EPackage.Registry packageRegistry)
+ {
+ Map<EClass, List<EClass>> result = new HashMap<EClass, List<EClass>>();
+ for (String nsURI : packageRegistry.keySet())
+ {
+ EPackage ePackage = packageRegistry.getEPackage(nsURI);
+ getSubTypes(ePackage, result);
+ }
+
+ return result;
+ }
+
+ private static void getSubTypes(EPackage ePackage, Map<EClass, List<EClass>> result)
+ {
+ for (EClassifier classifier : ePackage.getEClassifiers())
+ {
+ if (classifier instanceof EClass)
+ {
+ EClass eClass = (EClass)classifier;
+ for (EClass eSuperType : eClass.getEAllSuperTypes())
+ {
+ if (eSuperType.eIsProxy())
+ {
+ OM.LOG.warn("getSubTypes encountered a proxy EClass which will be ignored: " + eSuperType);
+ continue;
+ }
+
+ List<EClass> list = result.get(eSuperType);
+ if (list == null)
+ {
+ list = new ArrayList<EClass>();
+ result.put(eSuperType, list);
+ }
+
+ list.add(eClass);
+ }
+ }
+ }
+ }
}
diff --git a/plugins/org.eclipse.emf.cdo.common/src/org/eclipse/emf/cdo/common/model/CDOPackageRegistry.java b/plugins/org.eclipse.emf.cdo.common/src/org/eclipse/emf/cdo/common/model/CDOPackageRegistry.java
index 5dd513c..467423c 100644
--- a/plugins/org.eclipse.emf.cdo.common/src/org/eclipse/emf/cdo/common/model/CDOPackageRegistry.java
+++ b/plugins/org.eclipse.emf.cdo.common/src/org/eclipse/emf/cdo/common/model/CDOPackageRegistry.java
@@ -7,13 +7,18 @@
*
* Contributors:
* Eike Stepper - initial API and implementation
+ * Stefan Winkler - Bug 332912 - Caching subtype-relationships in the CDOPackageRegistry
*/
package org.eclipse.emf.cdo.common.model;
import org.eclipse.emf.common.util.Enumerator;
+import org.eclipse.emf.ecore.EClass;
import org.eclipse.emf.ecore.EEnumLiteral;
import org.eclipse.emf.ecore.EPackage;
+import java.util.List;
+import java.util.Map;
+
/**
* @author Eike Stepper
* @since 2.0
@@ -56,5 +61,10 @@ public interface CDOPackageRegistry extends EPackage.Registry
/**
* @since 4.0
*/
+ public Map<EClass, List<EClass>> getSubTypes();
+
+ /**
+ * @since 4.0
+ */
public EEnumLiteral getEnumLiteralFor(Enumerator value);
}
diff --git a/plugins/org.eclipse.emf.cdo.common/src/org/eclipse/emf/cdo/internal/common/model/CDOPackageRegistryImpl.java b/plugins/org.eclipse.emf.cdo.common/src/org/eclipse/emf/cdo/internal/common/model/CDOPackageRegistryImpl.java
index bb16ac1..8d6cdff 100644
--- a/plugins/org.eclipse.emf.cdo.common/src/org/eclipse/emf/cdo/internal/common/model/CDOPackageRegistryImpl.java
+++ b/plugins/org.eclipse.emf.cdo.common/src/org/eclipse/emf/cdo/internal/common/model/CDOPackageRegistryImpl.java
@@ -7,6 +7,7 @@
*
* Contributors:
* Eike Stepper - initial API and implementation
+ * Stefan Winkler - Bug 332912 - Caching subtype-relationships in the CDOPackageRegistry
*/
package org.eclipse.emf.cdo.internal.common.model;
@@ -35,6 +36,7 @@ import org.eclipse.net4j.util.om.trace.ContextTracer;
import org.eclipse.emf.common.notify.Adapter;
import org.eclipse.emf.common.util.EList;
import org.eclipse.emf.common.util.Enumerator;
+import org.eclipse.emf.ecore.EClass;
import org.eclipse.emf.ecore.EClassifier;
import org.eclipse.emf.ecore.EEnum;
import org.eclipse.emf.ecore.EEnumLiteral;
@@ -75,6 +77,9 @@ public class CDOPackageRegistryImpl extends EPackageRegistryImpl implements Inte
@ExcludeFromDump
private transient InternalCDOPackageUnit[] packageUnits;
+ @ExcludeFromDump
+ private transient Map<EClass, List<EClass>> subTypes;
+
private Map<Enumerator, EEnumLiteral> enumLiterals = new HashMap<Enumerator, EEnumLiteral>();
private Set<CDOPackageInfo> visitedPackages = new HashSet<CDOPackageInfo>();
@@ -534,6 +539,16 @@ public class CDOPackageRegistryImpl extends EPackageRegistryImpl implements Inte
return result;
}
+ public synchronized Map<EClass, List<EClass>> getSubTypes()
+ {
+ if (subTypes == null)
+ {
+ subTypes = CDOModelUtil.getSubTypes(this);
+ }
+
+ return subTypes;
+ }
+
@Override
public String toString()
{
@@ -607,6 +622,7 @@ public class CDOPackageRegistryImpl extends EPackageRegistryImpl implements Inte
packageInfos = null;
packageUnits = null;
+ subTypes = null;
}
protected void initPackageUnit(EPackage ePackage)
@@ -620,10 +636,12 @@ public class CDOPackageRegistryImpl extends EPackageRegistryImpl implements Inte
{
packageInfos = null;
packageUnits = null;
+ subTypes = null;
if (eagerInternalCaches)
{
getPackageInfos();
getPackageUnits();
+ getSubTypes();
}
}
diff --git a/plugins/org.eclipse.emf.cdo.tests/SubclassTest1.ecore b/plugins/org.eclipse.emf.cdo.tests/SubclassTest1.ecore
new file mode 100644
index 0000000..8c011ba
--- /dev/null
+++ b/plugins/org.eclipse.emf.cdo.tests/SubclassTest1.ecore
@@ -0,0 +1,21 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<ecore:EPackage xmi:version="2.0"
+ xmlns:xmi="http://www.omg.org/XMI" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+ xmlns:ecore="http://www.eclipse.org/emf/2002/Ecore" name="package1"
+ nsURI="http://cdo.eclipse.org/tests/PackageRegistry/SubclassTest1.ecore" nsPrefix="p1">
+ <eClassifiers xsi:type="ecore:EClass" name="RootClass"/>
+ <eClassifiers xsi:type="ecore:EClass" name="RootAbstractClass" abstract="true"/>
+ <eClassifiers xsi:type="ecore:EClass" name="RootInterface" abstract="true" interface="true"/>
+ <eClassifiers xsi:type="ecore:EClass" name="Child1" eSuperTypes="#//RootClass"/>
+ <eClassifiers xsi:type="ecore:EClass" name="Child2" eSuperTypes="#//RootAbstractClass"/>
+ <eClassifiers xsi:type="ecore:EClass" name="Child3" eSuperTypes="#//RootInterface"/>
+ <eClassifiers xsi:type="ecore:EClass" name="Child4" eSuperTypes="#//RootAbstractClass #//RootClass #//RootInterface"/>
+ <eClassifiers xsi:type="ecore:EClass" name="SubChild" eSuperTypes="#//Child4"/>
+ <eClassifiers xsi:type="ecore:EClass" name="SubChild3" eSuperTypes="#//RootClass #//SubChild"/>
+ <eSubpackages name="subpackage" nsURI="http://cdo.eclipse.org/tests/PackageRegistry/SubclassTest1.ecore#subpackage"
+ nsPrefix="sp">
+ <eClassifiers xsi:type="ecore:EClass" name="Child5" eSuperTypes="#//RootClass"/>
+ <eClassifiers xsi:type="ecore:EClass" name="Child6" eSuperTypes="#//RootAbstractClass #//RootClass #//RootInterface"/>
+ <eClassifiers xsi:type="ecore:EClass" name="SubChild2" eSuperTypes="#//Child4"/>
+ </eSubpackages>
+</ecore:EPackage>
diff --git a/plugins/org.eclipse.emf.cdo.tests/SubclassTest2.ecore b/plugins/org.eclipse.emf.cdo.tests/SubclassTest2.ecore
new file mode 100644
index 0000000..f586872
--- /dev/null
+++ b/plugins/org.eclipse.emf.cdo.tests/SubclassTest2.ecore
@@ -0,0 +1,8 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<ecore:EPackage xmi:version="2.0"
+ xmlns:xmi="http://www.omg.org/XMI" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+ xmlns:ecore="http://www.eclipse.org/emf/2002/Ecore" name="package2"
+ nsURI="http://cdo.eclipse.org/tests/PackageRegistry/SubclassTest2.ecore" nsPrefix="p2">
+ <eClassifiers xsi:type="ecore:EClass" name="Child7" eSuperTypes="SubclassTest1.ecore#//RootClass"/>
+ <eClassifiers xsi:type="ecore:EClass" name="Child8" eSuperTypes="SubclassTest1.ecore#//RootAbstractClass SubclassTest1.ecore#//RootClass SubclassTest1.ecore#//RootInterface"/>
+</ecore:EPackage>
diff --git a/plugins/org.eclipse.emf.cdo.tests/src/org/eclipse/emf/cdo/tests/PackageRegistryTest.java b/plugins/org.eclipse.emf.cdo.tests/src/org/eclipse/emf/cdo/tests/PackageRegistryTest.java
index a7550ae..50d2a7f 100644
--- a/plugins/org.eclipse.emf.cdo.tests/src/org/eclipse/emf/cdo/tests/PackageRegistryTest.java
+++ b/plugins/org.eclipse.emf.cdo.tests/src/org/eclipse/emf/cdo/tests/PackageRegistryTest.java
@@ -7,6 +7,7 @@
*
* Contributors:
* Eike Stepper - initial API and implementation
+ * Stefan Winkler - Bug 332912 - Caching subtype-relationships in the CDOPackageRegistry
*/
package org.eclipse.emf.cdo.tests;
@@ -40,11 +41,17 @@ import org.eclipse.emf.ecore.EPackage;
import org.eclipse.emf.ecore.EcoreFactory;
import org.eclipse.emf.ecore.impl.EPackageRegistryImpl;
import org.eclipse.emf.ecore.resource.Resource;
+import org.eclipse.emf.ecore.resource.ResourceSet;
+import org.eclipse.emf.ecore.resource.impl.ResourceSetImpl;
import org.eclipse.emf.ecore.util.EcoreUtil;
import org.eclipse.emf.ecore.xmi.XMIResource;
+import org.eclipse.emf.ecore.xmi.impl.XMIResourceFactoryImpl;
import org.eclipse.emf.ecore.xmi.impl.XMIResourceImpl;
import java.io.IOException;
+import java.util.Arrays;
+import java.util.List;
+import java.util.Map;
/**
* @author Eike Stepper
@@ -676,6 +683,83 @@ public class PackageRegistryTest extends AbstractCDOTest
assertEquals("Eike", company.getName());
}
+ public void testSubclassCacheInvalidation() throws IOException
+ {
+ ResourceSet rs = new ResourceSetImpl();
+ rs.getResourceFactoryRegistry().getExtensionToFactoryMap().put("ecore", new XMIResourceFactoryImpl());
+ Resource r1 = rs.createResource(URI.createURI("file:///SubclassTest1.ecore"));
+ r1.load(OM.BUNDLE.getInputStream("SubclassTest1.ecore"), null);
+ EPackage p1 = (EPackage)r1.getContents().get(0);
+ Resource r2 = rs.createResource(URI.createURI("file:///SubclassTest2.ecore"));
+ r2.load(OM.BUNDLE.getInputStream("SubclassTest2.ecore"), null);
+ EPackage p2 = (EPackage)r2.getContents().get(0);
+
+ CDOSession session = openSession();
+ CDOPackageRegistry registry = session.getPackageRegistry();
+ registry.putEPackage(p1);
+ registry.putEPackage(p2);
+
+ Map<EClass, List<EClass>> subTypes = registry.getSubTypes();
+
+ assertSubtypes((EClass)p1.getEClassifier("RootClass"), subTypes,
+ Arrays.asList("Child1", "Child4", "SubChild", "SubChild3", "Child5", "Child6", "SubChild2", "Child7", "Child8"));
+ assertSubtypes((EClass)p1.getEClassifier("RootAbstractClass"), subTypes,
+ Arrays.asList("Child2", "Child4", "SubChild", "SubChild3", "Child6", "SubChild2", "Child8"));
+ assertSubtypes((EClass)p1.getEClassifier("RootInterface"), subTypes,
+ Arrays.asList("Child3", "Child4", "SubChild", "SubChild3", "Child6", "SubChild2", "Child8"));
+ }
+
+ public void testSubclassCache() throws IOException
+ {
+ ResourceSet rs = new ResourceSetImpl();
+ rs.getResourceFactoryRegistry().getExtensionToFactoryMap().put("ecore", new XMIResourceFactoryImpl());
+ Resource r1 = rs.createResource(URI.createURI("file:///SubclassTest1.ecore"));
+ r1.load(OM.BUNDLE.getInputStream("SubclassTest1.ecore"), null);
+ EPackage p1 = (EPackage)r1.getContents().get(0);
+ Resource r2 = rs.createResource(URI.createURI("file:///SubclassTest2.ecore"));
+ r2.load(OM.BUNDLE.getInputStream("SubclassTest2.ecore"), null);
+ EPackage p2 = (EPackage)r2.getContents().get(0);
+
+ CDOSession session = openSession();
+ CDOPackageRegistry registry = session.getPackageRegistry();
+ registry.putEPackage(p1);
+ Map<EClass, List<EClass>> subTypes = registry.getSubTypes();
+
+ assertSubtypes((EClass)p1.getEClassifier("RootClass"), subTypes,
+ Arrays.asList("Child1", "Child4", "SubChild", "SubChild3", "Child5", "Child6", "SubChild2"));
+ assertSubtypes((EClass)p1.getEClassifier("RootAbstractClass"), subTypes,
+ Arrays.asList("Child2", "Child4", "SubChild", "SubChild3", "Child6", "SubChild2"));
+ assertSubtypes((EClass)p1.getEClassifier("RootInterface"), subTypes,
+ Arrays.asList("Child3", "Child4", "SubChild", "SubChild3", "Child6", "SubChild2"));
+
+ registry.putEPackage(p2);
+ subTypes = registry.getSubTypes();
+
+ assertSubtypes((EClass)p1.getEClassifier("RootClass"), subTypes,
+ Arrays.asList("Child1", "Child4", "SubChild", "SubChild3", "Child5", "Child6", "SubChild2", "Child7", "Child8"));
+ assertSubtypes((EClass)p1.getEClassifier("RootAbstractClass"), subTypes,
+ Arrays.asList("Child2", "Child4", "SubChild", "SubChild3", "Child6", "SubChild2", "Child8"));
+ assertSubtypes((EClass)p1.getEClassifier("RootInterface"), subTypes,
+ Arrays.asList("Child3", "Child4", "SubChild", "SubChild3", "Child6", "SubChild2", "Child8"));
+ }
+
+ private void assertSubtypes(EClass eClass, Map<EClass, List<EClass>> subTypes, List<String> expected)
+ {
+ List<EClass> actual = subTypes.get(eClass);
+ String[] actualArray = new String[actual.size()];
+ for (int i = 0; i < actualArray.length; i++)
+ {
+ actualArray[i] = actual.get(i).getName();
+ }
+
+ String[] expectedArray = expected.toArray(new String[expected.size()]);
+
+ Arrays.sort(actualArray);
+ Arrays.sort(expectedArray);
+
+ assertEquals(expectedArray, actualArray);
+ }
+
public static EPackage loadModel(String fileName) throws IOException
{
URI uri = URI.createURI("file://" + fileName);