blob: 456be91d1ed6015d69fabdb38f3c917d40d3a745 [file] [log] [blame]
/**
* <copyright> Copyright (c) 2005, 2006, 2007, 2008 Springsite BV (The Netherlands) 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: Martin Taal </copyright> $Id:
* HibernateTestStore.java,v 1.16 2007/03/29 15:00:21 mtaal Exp $
*/
package org.eclipse.emf.teneo.hibernate.test.stores;
import java.io.Serializable;
import java.sql.Connection;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Date;
import java.util.List;
import java.util.Properties;
import javax.persistence.EntityManager;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.eclipse.emf.common.util.URI;
import org.eclipse.emf.ecore.EClass;
import org.eclipse.emf.ecore.EClassifier;
import org.eclipse.emf.ecore.EObject;
import org.eclipse.emf.ecore.EPackage;
import org.eclipse.emf.ecore.EStructuralFeature;
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.teneo.Constants;
import org.eclipse.emf.teneo.DataStore;
import org.eclipse.emf.teneo.PackageRegistryProvider;
import org.eclipse.emf.teneo.PersistenceOptions;
import org.eclipse.emf.teneo.annotations.pannotation.InheritanceType;
import org.eclipse.emf.teneo.ecore.EModelResolver;
import org.eclipse.emf.teneo.extension.ExtensionManager;
import org.eclipse.emf.teneo.hibernate.HbDataStore;
import org.eclipse.emf.teneo.hibernate.HbEntityDataStore;
import org.eclipse.emf.teneo.hibernate.HbHelper;
import org.eclipse.emf.teneo.hibernate.HbSessionDataStore;
import org.eclipse.emf.teneo.hibernate.SessionWrapper;
import org.eclipse.emf.teneo.hibernate.resource.HbResource;
import org.eclipse.emf.teneo.hibernate.resource.HibernateResource;
import org.eclipse.emf.teneo.hibernate.test.stores.adapters.HibernateTestDBAdapter;
import org.eclipse.emf.teneo.mapping.strategy.EntityNameStrategy;
import org.eclipse.emf.teneo.test.stores.AbstractTestStore;
import org.eclipse.emf.teneo.test.stores.HsqldbTestDatabaseAdapter;
import org.eclipse.emf.teneo.util.AssertUtil;
import org.eclipse.emf.teneo.util.EcoreDataTypes;
import org.hibernate.FlushMode;
import org.hibernate.Session;
import org.hibernate.cfg.Environment;
import junit.framework.TestCase;
/**
* The hibernate test store encapsulates the datastore actions to a hibernate store.
*
* @author <a href="mailto:mtaal@elver.org">Martin Taal</a>
* @version $Revision: 1.42 $
*/
public class HibernateTestStore extends AbstractTestStore {
/** The logger */
private static Log log = LogFactory.getLog(HibernateTestStore.class);
public static final String USE_DATASTORE_REGISTRY = "useDataStoreRegistry";
public static final String EPACKAGE_INIT_MODE = "epackageinitmode";
public static final String EPACKAGE_INIT_MODE_SPECIFIED = "specified";
public static final String SPECIFIED_EPACKAGES = "specified_epackages";
public static final String EPACKAGE_INIT_MODE_CLASS = "class";
public static final String EPACKAGE_INIT_MODE_ECORE = "ecore";
public static final String EPACKAGE_INIT_MODE_ECORE_VALUE = "ecorefile";
/** The emf resource set used during the test */
protected ResourceSet resourceSet;
/** The EMFDatastore */
private HbDataStore emfDataStore;
/** The persistence manager for this test store */
private SessionWrapper sessionWrapper;
/** The props used to create it all */
private final Properties props;
/** the used epackages */
private EPackage[] epackages;
/** The inheritance logic followed */
private final InheritanceType inheritanceType;
/** Do ejb3 */
private final boolean ejb3;
/** The extensionManager */
private final ExtensionManager extensionManager;
/**
* Constructor for emf test cases
*/
public HibernateTestStore(HibernateTestDBAdapter adapter, EPackage[] epackages, Properties props,
InheritanceType inheritanceType, boolean ejb3, ExtensionManager extensionManager) {
super(adapter);
this.props = props;
this.epackages = epackages;
this.inheritanceType = inheritanceType;
this.ejb3 = ejb3;
this.extensionManager = extensionManager;
init();
}
/** Creates/sets the persistence manager */
private void init() {
final HibernateTestDBAdapter adapter = (HibernateTestDBAdapter) getDatabaseAdapter();
props.setProperty(PersistenceOptions.INHERITANCE_MAPPING, inheritanceType.getName());
for (EPackage element : epackages) {
log.debug("Creating HibernateTeststore for " + element.getName() + " adapter "
+ adapter.getClass().getName());
cleanUpAuditingAnnotations(element);
}
setDataStore();
log.debug("HibernateTestStore initialized");
resourceSet = new ResourceSetImpl();
}
private void cleanUpAuditingAnnotations(EPackage ePackage) {
for (EClassifier eClassifier : ePackage.getEClassifiers()) {
if (eClassifier instanceof EClass) {
final EClass eClass = (EClass) eClassifier;
eClass.getEAnnotations()
.remove(eClass.getEAnnotation(Constants.ANNOTATION_SOURCE_AUDITING));
for (EStructuralFeature eFeature : eClass.getEAllStructuralFeatures()) {
eFeature.getEAnnotations().remove(
eFeature.getEAnnotation(Constants.ANNOTATION_SOURCE_AUDITING));
if (eFeature.getEAnnotation(Constants.ANNOTATION_SOURCE_TENEO_JPA) != null) {
eFeature.getEAnnotation(Constants.ANNOTATION_SOURCE_TENEO_JPA).getDetails()
.remove(Constants.ANNOTATION_AUDITING_NOT);
}
}
}
}
}
/** Creates a Hibernate property set from the databaseadapter */
private Properties getHibernateProperties(HibernateTestDBAdapter dbadapter) {
final Properties props = new Properties();
props.setProperty(Environment.DRIVER, dbadapter.getDbDriver());
props.setProperty(Environment.USER, dbadapter.getDbUser());
props.setProperty(Environment.URL, dbadapter.getDbUrl());
props.setProperty(Environment.PASS, dbadapter.getDbPwd());
props.setProperty(Environment.DIALECT, dbadapter.getDialect());
props.setProperty(Environment.BYTECODE_PROVIDER, "cglib");
props.setProperty(Environment.USE_SECOND_LEVEL_CACHE, "false");
props.setProperty(Environment.GENERATE_STATISTICS, "false");
return props;
}
/** Sets the emfDataStore */
private void setDataStore() {
// currentTimeMillis is added to make it unique
if (ejb3) {
emfDataStore = new HbEntityDataStore(); // (HbDataStore)HbHelper.INSTANCE.
// createRegisterDataStore
// (getDatabaseAdapter().getDbName());
} else {
emfDataStore = HbHelper.INSTANCE.createRegisterDataStore(getDatabaseAdapter().getDbName());
}
emfDataStore.setExtensionManager(extensionManager);
emfDataStore.setName(getDatabaseAdapter().getDbName());
// any value is fine
if (props.getProperty(USE_DATASTORE_REGISTRY) != null) {
PackageRegistryProvider.getInstance().setPackageRegistry(null);
emfDataStore.setPackageRegistry(EPackage.Registry.INSTANCE);
} else {
PackageRegistryProvider.getInstance().setPackageRegistry(EPackage.Registry.INSTANCE);
}
// set both hibernate and persistence props as we do not know the
// difference right now
props.putAll(getHibernateProperties((HibernateTestDBAdapter) getDatabaseAdapter()));
if (!props.containsKey(PersistenceOptions.JOIN_TABLE_FOR_NON_CONTAINED_ASSOCIATIONS)) {
props.setProperty(PersistenceOptions.JOIN_TABLE_FOR_NON_CONTAINED_ASSOCIATIONS, "false");
}
// do a special trick for hsqldb, because hsqldb expects all identifiers
// to be
// escaped or otherwise uppercases them, so uppercase everything
// automatically
if (getDatabaseAdapter() instanceof HsqldbTestDatabaseAdapter
&& !props.containsKey(PersistenceOptions.SQL_CASE_STRATEGY)) {
props.setProperty(PersistenceOptions.SQL_CASE_STRATEGY, "uppercase");
}
if (isEntityManagerStore()) {
props.setProperty(PersistenceOptions.ALSO_MAP_AS_CLASS, "true");
}
if (!props.containsKey(PersistenceOptions.ENABLE_AUDITING)
&& !props.containsKey(Constants.ANNOTATION_AUDITING_NOT)) {
props.setProperty(PersistenceOptions.ENABLE_AUDITING, "true");
}
emfDataStore.setDataStoreProperties(props);
if (props.getProperty(EPACKAGE_INIT_MODE) != null) {
if (props.getProperty(EPACKAGE_INIT_MODE).compareTo(EPACKAGE_INIT_MODE_SPECIFIED) == 0) {
final List<String> clss = Collections.singletonList(props.getProperty(SPECIFIED_EPACKAGES));
emfDataStore.setEPackageClasses(clss);
} else if (props.getProperty(EPACKAGE_INIT_MODE).compareTo(EPACKAGE_INIT_MODE_CLASS) == 0) {
final List<String> clss = new ArrayList<String>();
for (EPackage epackage : epackages) {
clss.add(epackage.getClass().getName());
}
emfDataStore.setEPackageClasses(clss);
} else if (props.getProperty(EPACKAGE_INIT_MODE).compareTo(EPACKAGE_INIT_MODE_ECORE) == 0) {
final List<String> ecores = new ArrayList<String>();
ecores.add(props.getProperty(EPACKAGE_INIT_MODE_ECORE_VALUE));
emfDataStore.setEPackageFiles(ecores);
}
} else {
emfDataStore.setEPackages(epackages);
}
emfDataStore.initialize();
if (sessionWrapper != null) {
refresh();
} else {
sessionWrapper = emfDataStore.createSessionWrapper();
sessionWrapper.getHibernateSession().setFlushMode(FlushMode.COMMIT);
}
}
/** Returns the mapping xml */
@Override
public String getMappingXML() {
return emfDataStore.getMappingXML();
}
/** Add an epackage to the list of epackages */
public void addEPackage(EPackage epackage) {
EPackage[] newEPacks = new EPackage[epackages.length + 1];
newEPacks[0] = epackage;
for (int i = 0; i < epackages.length; i++) {
newEPacks[i + 1] = epackages[i];
}
epackages = newEPacks;
}
/** Update the database schema */
public void updateSchema() {
// clear the configuration
if (emfDataStore instanceof HbSessionDataStore) {
((HbSessionDataStore) emfDataStore).setConfiguration(null);
} else {
((HbEntityDataStore) emfDataStore).setConfiguration(null);
}
emfDataStore.setEPackages(epackages);
emfDataStore.initialize();
refresh();
}
/** Creates a new persistence manager, actually to clear the cache */
public void refresh() {
if (sessionWrapper.isTransactionActive()) {
sessionWrapper.rollbackTransaction();
}
sessionWrapper.close();
sessionWrapper = emfDataStore.createSessionWrapper();
sessionWrapper.getHibernateSession().setFlushMode(FlushMode.COMMIT);
}
/** Returns session */
public Session getSession() {
final Object obj = sessionWrapper.getSession();
if (obj instanceof Session) {
return (Session) obj;
} else {
return (Session) ((EntityManager) obj).getDelegate();
}
}
/** Return the sessionwrapper */
public SessionWrapper getSessionWrapper() {
return sessionWrapper;
}
/** Return the entityManager */
public EntityManager getEntityManager() {
return (EntityManager) sessionWrapper.getSession();
}
/** Returns a new session */
public Session getNewSession() {
return emfDataStore.getSessionFactory().openSession();
}
/** Begin transaction */
public void beginTransaction() {
sessionWrapper.beginTransaction();
}
/** Commit transaction */
public void commitTransaction() {
sessionWrapper.commitTransaction();
refresh();
}
/** Rollback transaction */
public void rollbackTransaction() {
if (sessionWrapper.isTransactionActive()) {
sessionWrapper.rollbackTransaction();
}
refresh();
}
/** Store/Makepersistent */
public void store(Object object) {
sessionWrapper.saveOrUpdate(object);
}
/** Deletes an object */
public void deleteObject(Object obj) {
sessionWrapper.delete(obj);
}
/** Test if a delete fails */
public void checkDeleteFails(Class<?> clazz) {
checkDelete(clazz, false); // replace class is called in
// checkDelete/getObjects
}
/** Test if a delete fails */
public void checkDeleteSucceeds(Class<?> clazz) {
checkDelete(clazz, true); // replace class is called in
// CheckDelete/getObjects
}
/** Query for a class using a field and value pair */
public List<?> query(Class<?> clazz, String field, String value, int checkCount) {
// final Class interf = replaceClass(clazz);
if (sessionWrapper.isEJB3EntityManager()) {
return query("select o from " + getEntityName(clazz) + " o where o." + field + "=\'" + value
+ "\'", checkCount);
} else {
return query("from " + getEntityName(clazz) + " where " + field + "=\'" + value + "\'",
checkCount);
}
}
/** Queries for an object */
@Override
public List<?> query(Object query) {
return query(query, -1);
}
/** Queries for an object and checks the number */
public List<?> query(Object query, int checkCount) {
final String qryStr = (String) query;
final List<?> result = sessionWrapper.executeQuery(qryStr);
if (checkCount > 0) {
TestCase.assertTrue("Expected " + checkCount + " object(s) for this query but there are "
+ result.size() + " object(s) for the query " + qryStr, result.size() == checkCount);
}
return result;
}
/** Test if a delete fails */
private void checkDelete(Class<?> clazz, boolean shouldSucceed) {
beginTransaction();
final List<?> l = getObjects(clazz); // replace class is called in
// getObjects
try {
for (int i = 0; i < l.size(); i++) {
sessionWrapper.delete(l.get(i));
}
commitTransaction();
TestCase.assertTrue("The objects of class: " + clazz.getName()
+ " was deleted while this should not be possible", shouldSucceed);
} catch (Exception e) {
TestCase.assertTrue("The objects of class: " + clazz.getName()
+ " was not deleted while this should be possible", !shouldSucceed);
if (sessionWrapper.isTransactionActive()) {
rollbackTransaction();
}
refresh();
}
}
/**
* Return an object of a certain class, there should only be one in the databases
*/
@Override
@SuppressWarnings("unchecked")
public <T> T getObject(Class<T> clazz) {
List<?> l = getObjects(clazz); // replace class is called in getObjects
TestCase.assertTrue("There are " + l.size()
+ " object(s) of this class in the datastore, 1 was expected, class: " + clazz.getName(),
l.size() == 1);
return (T) l.get(0);
}
public Object getObject(String entityName, Serializable id) {
return sessionWrapper.get(entityName, id);
}
/** Returns a list of object of a certain class */
@SuppressWarnings("unchecked")
public <T> List<T> getObjects(Class<T> clazz) {
// final Class concrete = replaceClass(clazz);
if (sessionWrapper.isEJB3EntityManager()) {
return (List<T>) sessionWrapper.executeQuery("select o from " + getEntityName(clazz) + " o");
} else {
return (List<T>) sessionWrapper.executeQuery("FROM " + getEntityName(clazz));
}
}
/** Test the amount of objects of a certain class in the db */
@Override
public void checkNumber(Class<?> clazz, int count) {
final List<?> list = getObjects(clazz);
TestCase.assertTrue("Expected " + count + " object(s) but there are " + list.size()
+ " object(s) of this class in the datastore: " + clazz.getName(), list.size() == count);
}
/** Flushes all updates to the underlying datastore */
public void flush() {
sessionWrapper.flush();
}
/** Is called just before the test */
@Override
public void setUp() {
}
/**
* Is called just after the test, the dropStore parameter can be used to prevent dropping the
* database when an error
*/
@Override
public void doTearDown() {
AssertUtil.assertTrue("Transaction is still active at end of test",
!sessionWrapper.isTransactionActive());
if (sessionWrapper.isTransactionActive()) {
rollbackTransaction();
}
sessionWrapper.close();
HbHelper.INSTANCE.closeAll();
if (!donotDrop) {
dropDatabase();
}
}
/** Returns true if the transaction is still active */
public boolean transactionActive() {
return sessionWrapper.isTransactionActive();
}
/** Base method to get a resource belonging to the pmf of this test case */
@Override
public Resource getResource() {
return getResource(null);
}
/** Base method to get a resource belonging to the session of this test case */
public Resource getResource(String extraParam) {
String uriStr = "hibernate://?" + HibernateResource.DS_NAME_PARAM + "="
+ emfDataStore.getName();
if (extraParam != null) {
uriStr += "&" + extraParam;
}
final URI uri = URI.createURI(uriStr);
log.debug("Getting resource using uri: " + uri.toString());
final Resource res = resourceSet.createResource(uri);
assert (res instanceof HbResource);
return res;
}
/**
* Replaces a passed EMF Interface by its concrete class private Class replaceClass(Class
* interfaze) { if (!interfaze.isInterface()) return interfaze; if
* (!EObject.class.isAssignableFrom(interfaze)) return interfaze; return
* HibernateHelper.INSTANCE.getInstanceClass(interfaze); }
*/
/** Gets the referedto list */
public Object[] getCrossReferencers(EObject obj, boolean container) {
if (container) {
return new Object[] { obj.eContainer() };
// final EObject eobj =
// ((HbDataStore)emfDataStore).getContainer(session, obj);
// if (eobj == null)
// {
// return new EObject[0];
// }
// return new EObject[] {eobj};
} else {
return emfDataStore.getCrossReferencers(sessionWrapper, obj);
}
}
/** Gets the container list */
@Override
public boolean setContainer(EObject obj) {
return true;
}
/** Refreshes the object from the datastore */
public void refresh(Object obj) {
sessionWrapper.refresh(obj);
}
public Object merge(Object object) {
return sessionWrapper.merge(object);
}
/** Check inheritance strategy */
public boolean isInheritanceStrategy(Class<?> cls, InheritanceType strategy) {
return sessionWrapper.isInheritanceStrategy(cls, strategy);
}
/** Gets a database connection using the adapters connection info */
public Connection getConnection() {
return getDatabaseAdapter().getConnection();
}
/** Returns the query name to use for the instance */
private String getEntityName(Class<?> clazz) {
final EModelResolver emodelResolver = EModelResolver.instance();
final EClass eclass = emodelResolver.getEClass(clazz);
return getDataStore().getExtensionManager().getExtension(EntityNameStrategy.class)
.toEntityName(eclass);
}
/**
* @return the emfDataStore
*/
public HbDataStore getEmfDataStore() {
return emfDataStore;
}
/** Return the datastore */
public DataStore getDataStore() {
return getEmfDataStore();
}
/**
* @return the inheritanceType
*/
public InheritanceType getInheritanceType() {
return inheritanceType;
}
/** Is this a hibernate test store */
@Override
public boolean isHibernateTestStore() {
return true;
}
public boolean isEntityManagerStore() {
return ejb3;
}
/** Set the xmlgregoriancalendar date */
public Object getDate(Date date) {
return EcoreDataTypes.INSTANCE.getXMLGregorianCalendar(date);
}
}