/* * Copyright (c) 2007-2016 Eike Stepper (Berlin, Germany) and others. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at * http://www.eclipse.org/legal/epl-v10.html * * Contributors: * Eike Stepper - initial API and implementation * Stefan Winkler - Bug 332912 - Caching subtype-relationships in the CDOPackageRegistry */ package org.eclipse.emf.cdo.tests; import org.eclipse.emf.cdo.CDOObject; import org.eclipse.emf.cdo.common.model.CDOPackageRegistry; import org.eclipse.emf.cdo.common.model.CDOPackageRegistryPopulator; import org.eclipse.emf.cdo.common.model.CDOPackageUnit; import org.eclipse.emf.cdo.eresource.CDOResource; import org.eclipse.emf.cdo.session.CDOSession; import org.eclipse.emf.cdo.tests.bundle.OM; import org.eclipse.emf.cdo.tests.config.IRepositoryConfig; import org.eclipse.emf.cdo.tests.config.impl.ConfigTest.CleanRepositoriesBefore; import org.eclipse.emf.cdo.tests.mango.MangoValue; import org.eclipse.emf.cdo.tests.model1.Company; import org.eclipse.emf.cdo.tests.model1.Model1Package; import org.eclipse.emf.cdo.tests.model1.PurchaseOrder; import org.eclipse.emf.cdo.tests.model2.SpecialPurchaseOrder; import org.eclipse.emf.cdo.tests.model3.Class1; import org.eclipse.emf.cdo.tests.model3.Model3Package; import org.eclipse.emf.cdo.tests.model3.subpackage.Class2; import org.eclipse.emf.cdo.transaction.CDOTransaction; import org.eclipse.emf.cdo.util.CDOUtil; import org.eclipse.emf.common.util.EList; import org.eclipse.emf.common.util.URI; import org.eclipse.emf.ecore.EAttribute; import org.eclipse.emf.ecore.EClass; import org.eclipse.emf.ecore.EFactory; import org.eclipse.emf.ecore.EObject; 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 */ @CleanRepositoriesBefore(reason = "To not have ModelXPackage in test already registred in CDOPackageRegistry") public class PackageRegistryTest extends AbstractCDOTest { public void testGeneratedPackage() throws Exception { { // Create resource in session 1 CDOSession session = openSession(); CDOTransaction transaction = session.openTransaction(); CDOResource res = transaction.createResource(getResourcePath("/res")); Company company = getModel1Factory().createCompany(); company.setName("Eike"); res.getContents().add(company); transaction.commit(); } // Load resource in session 2 CDOSession session = openSession(); CDOTransaction transaction = session.openTransaction(); CDOResource res = transaction.getResource(getResourcePath("/res")); Company company = (Company)res.getContents().get(0); assertEquals("Eike", company.getName()); } public void testCommitTwoPackages() throws Exception { { CDOSession session = openSession(); session.getPackageRegistry().putEPackage(getModel1Package()); session.getPackageRegistry().putEPackage(getModel2Package()); CDOTransaction transaction = session.openTransaction(); CDOResource res = transaction.createResource(getResourcePath("/res")); SpecialPurchaseOrder specialPurchaseOrder = getModel2Factory().createSpecialPurchaseOrder(); specialPurchaseOrder.setDiscountCode("12345"); res.getContents().add(specialPurchaseOrder); transaction.commit(); } CDOSession session = openSession(); CDOTransaction transaction = session.openTransaction(); CDOResource res = transaction.getResource(getResourcePath("/res")); SpecialPurchaseOrder specialPurchaseOrder = (SpecialPurchaseOrder)res.getContents().get(0); assertEquals("12345", specialPurchaseOrder.getDiscountCode()); } public void testCommitUnrelatedPackage() throws Exception { { CDOSession session = openSession(); CDOTransaction transaction = session.openTransaction(); CDOResource res = transaction.createResource(getResourcePath("/res")); PurchaseOrder purchaseOrder = getModel1Factory().createPurchaseOrder(); res.getContents().add(purchaseOrder); transaction.commit(); session.close(); } CDOSession session = openSession(); CDOTransaction transaction = session.openTransaction(); CDOResource res = transaction.getResource(getResourcePath("/res")); MangoValue value = getMangoFactory().createMangoValue(); value.setName("V0"); res.getContents().add(value); transaction.commit(); session.close(); } public void testCommitNestedPackages() throws Exception { CDOSession session = openSession(); int oldSize = session.getPackageRegistry().size(); session.getPackageRegistry().putEPackage(getModel3SubpackagePackage()); assertEquals(oldSize + 2, session.getPackageRegistry().size()); session.close(); } public void testCommitTopLevelPackages() throws Exception { CDOSession session = openSession(); int oldSize = session.getPackageRegistry().size(); session.getPackageRegistry().putEPackage(getModel3Package()); assertEquals(oldSize + 2, session.getPackageRegistry().size()); CDOTransaction transaction = session.openTransaction(); CDOResource res = transaction.createResource(getResourcePath("/res")); Class1 class1 = getModel3Factory().createClass1(); res.getContents().add(class1); transaction.commit(); EPackage model3Package = session.getPackageRegistry().getEPackage(getModel3Package().getNsURI()); assertNotNull(model3Package); session.close(); } public void testLoadNestedPackages() throws Exception { { CDOSession session = openSession(); session.getPackageRegistry().putEPackage(getModel3Package()); CDOTransaction transaction = session.openTransaction(); CDOResource res = transaction.createResource(getResourcePath("/res")); Class1 class1 = getModel3Factory().createClass1(); res.getContents().add(class1); transaction.commit(); session.close(); } CDOSession session = openSession(); EPackage model3Package = session.getPackageRegistry().getEPackage(getModel3Package().getNsURI()); assertNotNull(model3Package); EPackage subPackage = session.getPackageRegistry().getEPackage(getModel3SubpackagePackage().getNsURI()); assertNotNull(subPackage); session.close(); } public void testCommitCircularPackages() throws Exception { { CDOSession session = openSession(); session.getPackageRegistry().putEPackage(Model3Package.eINSTANCE); CDOTransaction transaction = session.openTransaction(); CDOResource res1 = transaction.createResource(getResourcePath("/res1")); CDOResource res2 = transaction.createResource(getResourcePath("/res2")); Class1 class1 = getModel3Factory().createClass1(); Class2 class2 = getModel3SubpackageFactory().createClass2(); class1.getClass2().add(class2); res1.getContents().add(class1); res2.getContents().add(class2); transaction.commit(); session.close(); } { CDOSession session = openSession(); CDOTransaction transaction = session.openTransaction(); CDOResource res1 = transaction.getResource(getResourcePath("/res1")); Class1 class1 = (Class1)res1.getContents().get(0); assertNotNull(class1); EList<Class2> class22 = class1.getClass2(); Class2 class2 = class22.get(0); assertNotNull(class2); } CDOSession session = openSession(); CDOTransaction transaction = session.openTransaction(); CDOResource res2 = transaction.getResource(getResourcePath("/res2")); Class2 class2 = (Class2)res2.getContents().get(0); assertNotNull(class2); Class1 class1 = class2.getClass1().get(0); assertNotNull(class1); } public void testPackageRegistry() throws Exception { { // Create resource in session 1 CDOSession session = openSession(IRepositoryConfig.REPOSITORY_NAME); CDOTransaction transaction = session.openTransaction(); CDOResource res = transaction.createResource(getResourcePath("/res")); Company company = getModel1Factory().createCompany(); company.setName("Eike"); res.getContents().add(company); transaction.commit(); } // Load resource in session 2 CDOSession session = openSession(); CDOTransaction transaction = session.openTransaction(); CDOResource res = transaction.getResource(getResourcePath("/res")); Company company = (Company)res.getContents().get(0); assertEquals("Eike", company.getName()); } /** * Bug 249383: Dynamic models in the global EPackage.Registry are not committed bug 249383 */ public void testGlobalDynamicPackageEager() throws Exception { EPackage p = createUniquePackage(); String nsURI = p.getNsURI(); try { EClass c = EcoreFactory.eINSTANCE.createEClass(); c.setName("DClass"); p.getEClassifiers().add(c); EPackage.Registry.INSTANCE.put(nsURI, p); CDOSession session = openSession(); session.getPackageRegistry().putEPackage(p); p = session.getPackageRegistry().getEPackage(nsURI); CDOTransaction transaction = session.openTransaction(); CDOResource res = transaction.createResource(getResourcePath("/res")); EFactory factory = p.getEFactoryInstance(); EObject object = factory.create(c); res.getContents().add(object); transaction.commit(); session.close(); } finally { EPackage.Registry.INSTANCE.remove(nsURI); } } /** * Bug 249383: Dynamic models in the global EPackage.Registry are not committed bug 249383 */ public void testGlobalDynamicPackage() throws Exception { EPackage p = createUniquePackage(); String nsURI = p.getNsURI(); try { EClass c = EcoreFactory.eINSTANCE.createEClass(); c.setName("DClass"); p.getEClassifiers().add(c); if (!isConfig(LEGACY)) { CDOUtil.prepareDynamicEPackage(p); } EPackage.Registry.INSTANCE.put(nsURI, p); CDOSession session = openSession(); CDOTransaction transaction = session.openTransaction(); CDOResource res = transaction.createResource(getResourcePath("/res")); EFactory factory = p.getEFactoryInstance(); EObject object = factory.create(c); res.getContents().add(object); transaction.commit(); session.close(); } catch (Exception ex) { EPackage.Registry.INSTANCE.remove(nsURI); } } public void testDynamicPackageLoaded() throws Exception { EPackage model1 = loadModel("model1.ecore"); CDOSession session = openSession(); session.getPackageRegistry().putEPackage(model1); EFactory modelFactory = model1.getEFactoryInstance(); // Must happen AFTER putEPackage!!! EObject object = modelFactory.create((EClass)model1.getEClassifier("Company")); CDOTransaction transaction = session.openTransaction(); CDOResource resource = transaction.createResource(getResourcePath("/res")); resource.getContents().add(object); transaction.commit(); } public void testDynamicPackageFactory() throws Exception { // -Dorg.eclipse.emf.ecore.EPackage.Registry.INSTANCE=org.eclipse.emf.ecore.impl.CDOPackageRegistryImpl { EPackage model1 = loadModel("model1.ecore"); EClass companyClass = (EClass)model1.getEClassifier("Company"); EAttribute nameAttribute = (EAttribute)companyClass.getEStructuralFeature("name"); Resource model1Resource = model1.eResource(); // Create resource in session 1 CDOSession session = openSession(); session.getPackageRegistry().putEPackage(model1); assertEquals(model1Resource, model1.eResource()); CDOTransaction transaction = session.openTransaction(); CDOResource res = transaction.createResource(getResourcePath("/res")); EFactory factory = model1.getEFactoryInstance(); EObject company = factory.create(companyClass); company.eSet(nameAttribute, "Eike"); res.getContents().add(company); transaction.commit(); session.close(); } // Load resource in session 2 CDOSession session = openSession(); CDOTransaction transaction = session.openTransaction(); CDOResource res = transaction.getResource(getResourcePath("/res")); CDOObject company = CDOUtil.getCDOObject(res.getContents().get(0)); EClass companyClass = company.eClass(); EAttribute nameAttribute = (EAttribute)companyClass.getEStructuralFeature("name"); String name = (String)company.eGet(nameAttribute); assertEquals("Eike", name); session.close(); } public void testDynamicPackageNewInstance() throws Exception { { EPackage model1 = loadModel("model1.ecore"); EClass companyClass = (EClass)model1.getEClassifier("Company"); EAttribute nameAttribute = (EAttribute)companyClass.getEStructuralFeature("name"); // Create resource in session 1 CDOSession session = openSession(); session.getPackageRegistry().putEPackage(model1); CDOTransaction transaction = session.openTransaction(); CDOResource res = transaction.createResource(getResourcePath("/res")); CDOObject company = CDOUtil.getCDOObject(EcoreUtil.create(companyClass)); company.eSet(nameAttribute, "Eike"); res.getContents().add(company); transaction.commit(); session.close(); } // Load resource in session 2 CDOSession session = openSession(); CDOTransaction transaction = session.openTransaction(); CDOResource res = transaction.getResource(getResourcePath("/res")); CDOObject company = CDOUtil.getCDOObject(res.getContents().get(0)); EClass companyClass = company.eClass(); EAttribute nameAttribute = (EAttribute)companyClass.getEStructuralFeature("name"); String name = (String)company.eGet(nameAttribute); assertEquals("Eike", name); session.close(); } public void testDuplicatePackageRegistration() throws Exception { CDOSession session1 = openSession(); CDOSession session2 = openSession(); try { { CDOTransaction transaction = session1.openTransaction(); CDOResource res = transaction.createResource(getResourcePath("/res1")); Company company = getModel1Factory().createCompany(); company.setName("Company1"); res.getContents().add(company); transaction.commit(); sleep(1000); // Give session2 a chance to react } CDOPackageRegistry packageRegistry = session2.getPackageRegistry(); Model1Package model1Package = getModel1Package(); packageRegistry.putEPackage(model1Package); CDOPackageUnit packageUnit = packageRegistry.getPackageUnit(model1Package); assertEquals(CDOPackageUnit.State.LOADED, packageUnit.getState()); { CDOTransaction transaction = session2.openTransaction(); CDOResource res = transaction.createResource(getResourcePath("/res2")); Company company = getModel1Factory().createCompany(); company.setName("Company2"); res.getContents().add(company); transaction.commit(); } } finally { session1.close(); session2.close(); } } public void testReuseCommittedPackage() throws Exception { final long timeStamp; final CDOSession session1 = openSession(); final CDOSession session2 = openSession(); try { { CDOTransaction transaction = session1.openTransaction(); CDOResource res = transaction.createResource(getResourcePath("/res1")); Company company = getModel1Factory().createCompany(); company.setName("Company1"); res.getContents().add(company); timeStamp = transaction.commit().getTimeStamp(); } new PollingTimeOuter() { @Override protected boolean successful() { return session2.getLastUpdateTime() >= timeStamp; } }.assertNoTimeOut(); { CDOTransaction transaction = session2.openTransaction(); CDOResource res = transaction.createResource(getResourcePath("/res2")); Company company = getModel1Factory().createCompany(); company.setName("Company2"); res.getContents().add(company); transaction.commit(); } } finally { session1.close(); session2.close(); } } public void testConcurrentPackageRegistration() throws Exception { CDOSession session1 = openSession(); session1.getPackageRegistry().putEPackage(getModel1Package()); CDOSession session2 = openSession(); session2.getPackageRegistry().putEPackage(getModel1Package()); try { { CDOTransaction transaction = session1.openTransaction(); CDOResource res = transaction.createResource(getResourcePath("/res1")); Company company = getModel1Factory().createCompany(); company.setName("Company1"); res.getContents().add(company); transaction.commit(); sleep(1000); // Give session2 a chance to react } CDOPackageRegistry packageRegistry = session2.getPackageRegistry(); Model1Package model1Package = getModel1Package(); CDOPackageUnit packageUnit = packageRegistry.getPackageUnit(model1Package); assertEquals(CDOPackageUnit.State.LOADED, packageUnit.getState()); { CDOTransaction transaction = session2.openTransaction(); CDOResource res = transaction.createResource(getResourcePath("/res2")); Company company = getModel1Factory().createCompany(); company.setName("Company2"); res.getContents().add(company); transaction.commit(); } } finally { session1.close(); session2.close(); } } /** * Bug 353246. * <p> * Cannot reproduce the problem with MEMStore because MEMStoreAccessor.writePackageUnits() is empty. */ public void testConcurrentPackageRegistration2() throws Exception { CDOSession session1 = openSession(); CDOTransaction transaction1 = session1.openTransaction(); CDOResource resource1 = transaction1.createResource(getResourcePath("/res1")); transaction1.commit(); CDOSession session2 = openSession(); CDOTransaction transaction2 = session2.openTransaction(); CDOResource resource2 = transaction2.createResource(getResourcePath("/res2")); transaction2.commit(); session2.options().setPassiveUpdateEnabled(false); resource1.getContents().add(getModel1Factory().createCompany()); transaction1.commit(); resource2.getContents().add(getModel1Factory().createCompany()); transaction2.commit(); } public void testPopulator() throws Exception { EPackage.Registry registry = new EPackageRegistryImpl(); EPackage p = createUniquePackage(); String nsURI = p.getNsURI(); { EClass c = EcoreFactory.eINSTANCE.createEClass(); c.setName("DClass"); p.getEClassifiers().add(c); registry.put(nsURI, p); CDOSession session = openSession(); CDOPackageRegistryPopulator.populate(registry, session.getPackageRegistry()); CDOTransaction transaction = session.openTransaction(); CDOResource res = transaction.createResource(getResourcePath("/res")); Company company = getModel1Factory().createCompany(); company.setName("Eike"); res.getContents().add(company); transaction.commit(); } // Load resource in session 2 CDOSession session = openSession(); CDOTransaction transaction = session.openTransaction(); CDOResource res = transaction.getResource(getResourcePath("/res")); Company company = (Company)res.getContents().get(0); assertEquals("Eike", company.getName()); } public void testPopulatorGlobal() throws Exception { EPackage.Registry registry = EPackage.Registry.INSTANCE; EPackage p = createUniquePackage(); String nsURI = p.getNsURI(); try { { EClass c = EcoreFactory.eINSTANCE.createEClass(); c.setName("DClass"); p.getEClassifiers().add(c); registry.put(nsURI, p); CDOSession session = openSession(); CDOPackageRegistryPopulator.populate(registry, session.getPackageRegistry()); CDOTransaction transaction = session.openTransaction(); CDOResource res = transaction.createResource(getResourcePath("/res")); Company company = getModel1Factory().createCompany(); company.setName("Eike"); res.getContents().add(company); transaction.commit(); } // Load resource in session 2 CDOSession session = openSession(); CDOTransaction transaction = session.openTransaction(); CDOResource res = transaction.getResource(getResourcePath("/res")); Company company = (Company)res.getContents().get(0); assertEquals("Eike", company.getName()); } finally { EPackage.Registry.INSTANCE.remove(nsURI); } } public void testLaziness() throws Exception { { CDOSession session = openSession(); CDOTransaction transaction = session.openTransaction(); CDOResource res = transaction.createResource(getResourcePath("/res")); Company company = getModel1Factory().createCompany(); company.setName("Eike"); res.getContents().add(company); transaction.commit(); } // Load resource in session 2 CDOSession session = openSession(); CDOTransaction transaction = session.openTransaction(); CDOResource res = transaction.getResource(getResourcePath("/res")); Company company = (Company)res.getContents().get(0); 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("SubclassTest1.ecore")); r1.load(OM.BUNDLE.getInputStream("SubclassTest1.ecore"), null); EPackage p1 = (EPackage)r1.getContents().get(0); Resource r2 = rs.createResource(URI.createURI("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("SubclassTest1.ecore")); r1.load(OM.BUNDLE.getInputStream("SubclassTest1.ecore"), null); EPackage p1 = (EPackage)r1.getContents().get(0); Resource r2 = rs.createResource(URI.createURI("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(fileName); XMIResource resource = new XMIResourceImpl(uri); resource.setEncoding("UTF-8"); resource.load(OM.BUNDLE.getInputStream(fileName), null); return (EPackage)resource.getContents().get(0); } }