blob: 9eb82a82f0f08fcb04f71064a9585da4751a09a1 [file] [log] [blame]
/*
* Copyright (c) 2008-2012 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:
* Martin Taal - initial API and implementation
* Eike Stepper - maintenance
*/
package org.eclipse.emf.cdo.server.hibernate.internal.teneo;
import org.eclipse.emf.cdo.eresource.EresourcePackage;
import org.eclipse.emf.cdo.etypes.EtypesPackage;
import org.eclipse.emf.cdo.security.SecurityPackage;
import org.eclipse.emf.cdo.server.hibernate.internal.teneo.bundle.OM;
import org.eclipse.emf.cdo.server.hibernate.teneo.CDOMappingGenerator;
import org.eclipse.emf.cdo.server.internal.hibernate.CDOHibernateConstants;
import org.eclipse.emf.cdo.server.internal.hibernate.HibernateMappingProvider;
import org.eclipse.emf.cdo.server.internal.hibernate.HibernateStore;
import org.eclipse.emf.cdo.server.internal.hibernate.tuplizer.CDOBlobUserType;
import org.eclipse.emf.cdo.server.internal.hibernate.tuplizer.CDOClobUserType;
import org.eclipse.emf.cdo.server.internal.hibernate.tuplizer.CDOIDUserType;
import org.eclipse.net4j.util.om.trace.ContextTracer;
import org.eclipse.emf.ecore.EAnnotation;
import org.eclipse.emf.ecore.EClass;
import org.eclipse.emf.ecore.EClassifier;
import org.eclipse.emf.ecore.EDataType;
import org.eclipse.emf.ecore.EPackage;
import org.eclipse.emf.ecore.EStructuralFeature;
import org.eclipse.emf.ecore.EcoreFactory;
import org.eclipse.emf.ecore.xml.type.XMLTypePackage;
import org.eclipse.emf.teneo.Constants;
import org.eclipse.emf.teneo.PackageRegistryProvider;
import org.eclipse.emf.teneo.PersistenceOptions;
import java.util.HashMap;
import java.util.List;
import java.util.ListIterator;
import java.util.Map;
import java.util.Properties;
/**
* Uses the ecore string in the ePackages of the store to generate a mapping.
*
* @author Martin Taal
* @author Eike Stepper
* @since 3.0
*/
public class TeneoHibernateMappingProvider extends HibernateMappingProvider
{
private static final ContextTracer TRACER = new ContextTracer(OM.DEBUG, TeneoHibernateMappingProvider.class);
private Map<String, String> extensions = new HashMap<String, String>();
private Properties mappingProviderProperties = new Properties();
public TeneoHibernateMappingProvider()
{
}
public void putExtension(String extensionClassName, String extendingClassName)
{
extensions.put(extensionClassName, extendingClassName);
}
@Override
public HibernateStore getHibernateStore()
{
return (HibernateStore)super.getHibernateStore();
}
public String getMapping()
{
final String mapping = generateMapping();
if (TRACER.isEnabled())
{
TRACER.trace("Generated hibernate mapping:"); //$NON-NLS-1$
TRACER.trace(mapping);
}
return mapping;
}
// the passed modelObjects collection is defined as a collection of Objects
// to prevent binary dependency on emf.
public String generateMapping()
{
if (TRACER.isEnabled())
{
TRACER.trace("Generating Hibernate Mapping"); //$NON-NLS-1$
}
final Properties storeProperties = getHibernateStore().getProperties();
// merge the store properties with the mapping provider properties
// the mapping provider props take precedence
// this also prevents overwriting the original properties
final Properties properties = new Properties();
properties.putAll(storeProperties);
properties.putAll(mappingProviderProperties);
PackageRegistryProvider.getInstance()
.setThreadPackageRegistry(getHibernateStore().getRepository().getPackageRegistry());
// translate the list of EPackages to an array
boolean hasXMLTypePackage = false;
final List<EPackage> epacks = getHibernateStore().getModelEPackages();
final ListIterator<EPackage> iterator = epacks.listIterator();
while (iterator.hasNext())
{
final EPackage epack = iterator.next();
if (epack == XMLTypePackage.eINSTANCE)
{
hasXMLTypePackage = true;
}
if (SecurityPackage.eNS_URI.equals(epack.getNsURI()))
{
setEntityOnSecurityModel(epack);
}
}
if (hasXMLTypePackage)
{
addTypeAnnotationToXMLTypes();
}
addUniqueConstraintAnnotation();
final EPackage[] ePackageArray = epacks.toArray(new EPackage[epacks.size()]);
// remove the persistence xml if no epackages as this won't work without
// epackages
if (ePackageArray.length == 0 && properties.getProperty(PersistenceOptions.PERSISTENCE_XML) != null)
{
properties.remove(PersistenceOptions.PERSISTENCE_XML);
}
properties.setProperty(PersistenceOptions.FEATUREMAP_AS_COMPONENT, "true");
// add some annotations to the CDO model so that the mapping gets generated correctly
addTransientAnnotationToEClass(EtypesPackage.eINSTANCE.getModelElement());
addTransientAnnotationToEClass(EtypesPackage.eINSTANCE.getAnnotation());
addTypeAnnotationToEDataType(EtypesPackage.eINSTANCE.getBlob(), CDOBlobUserType.class.getName());
addTypeAnnotationToEDataType(EtypesPackage.eINSTANCE.getClob(), CDOClobUserType.class.getName());
addTypeAnnotationToAuditingResourcePackage();
final CDOMappingGenerator mappingGenerator = new CDOMappingGenerator();
mappingGenerator.getExtensions().putAll(extensions);
String hbm = mappingGenerator.generateMapping(ePackageArray, properties);
// to solve an issue with older versions of teneo
hbm = hbm.replaceAll("_cont", "cont"); //$NON-NLS-1$ //$NON-NLS-2$
// System.err.println(hbm);
return hbm;
}
private void setEntityOnSecurityModel(EPackage ePackage)
{
for (EClassifier eClassifier : ePackage.getEClassifiers())
{
if (eClassifier instanceof EClass)
{
final EClass eClass = (EClass)eClassifier;
if (eClass.getEAnnotation(Constants.ANNOTATION_SOURCE_TENEO_JPA) != null)
{
return;
}
final EAnnotation eAnnotation = EcoreFactory.eINSTANCE.createEAnnotation();
eAnnotation.setSource(Constants.ANNOTATION_SOURCE_TENEO_JPA);
eAnnotation.getDetails().put("value", "@Entity(name=\"CdoSecurity" + eClass.getName() + "\")");
eClass.getEAnnotations().add(eAnnotation);
}
}
}
private void addTypeAnnotationToXMLTypes()
{
for (EClassifier eClassifier : XMLTypePackage.eINSTANCE.getEClassifiers())
{
if (eClassifier instanceof EDataType)
{
final EDataType eDataType = (EDataType)eClassifier;
if (eDataType.getEAnnotation(Constants.ANNOTATION_SOURCE_TENEO_JPA) != null)
{
continue;
}
final EAnnotation eAnnotation = EcoreFactory.eINSTANCE.createEAnnotation();
eAnnotation.setSource(Constants.ANNOTATION_SOURCE_TENEO_JPA);
final String typeAnnotation = "@Type(type=\"org.eclipse.emf.cdo.server.internal.hibernate.tuplizer.XMLUserType$"
+ eDataType.getName() + "\")";
eAnnotation.getDetails().put("value", typeAnnotation);
eDataType.getEAnnotations().add(eAnnotation);
}
}
}
private void addTypeAnnotationToEDataType(EDataType eDataType, String type)
{
if (eDataType.getEAnnotation(Constants.ANNOTATION_SOURCE_TENEO_JPA) != null)
{
return;
}
{
final EAnnotation eAnnotation = EcoreFactory.eINSTANCE.createEAnnotation();
eAnnotation.setSource(Constants.ANNOTATION_SOURCE_TENEO_JPA);
final String typeAnnotation = "@Type(type=\"" + type + "\")";
eAnnotation.getDetails().put("value", typeAnnotation);
eDataType.getEAnnotations().add(eAnnotation);
}
{
final EAnnotation eAnnotation = EcoreFactory.eINSTANCE.createEAnnotation();
eAnnotation.setSource(Constants.ANNOTATION_SOURCE_TENEO_JPA_AUDITING);
final String typeAnnotation = "@Type(type=\"" + type + "\")";
eAnnotation.getDetails().put("value", typeAnnotation);
eDataType.getEAnnotations().add(eAnnotation);
}
}
private void addTypeAnnotationToAuditingResourcePackage()
{
addTypeAnnotationToAuditingResourceContents(EresourcePackage.eINSTANCE.getCDOResource_Contents());
addTypeAnnotationToAuditingResourceContents(EresourcePackage.eINSTANCE.getCDOResourceFolder_Nodes());
}
private void addTypeAnnotationToAuditingResourceContents(EStructuralFeature eFeature)
{
EAnnotation eAnnotation = eFeature.getEAnnotation(Constants.ANNOTATION_SOURCE_TENEO_JPA_AUDITING);
if (eAnnotation != null)
{
return;
}
eAnnotation = EcoreFactory.eINSTANCE.createEAnnotation();
eAnnotation.setSource(Constants.ANNOTATION_SOURCE_TENEO_JPA_AUDITING);
final String typeAnnotation = "@Type(type=\"" + CDOIDUserType.class.getName() + "\")";
eAnnotation.getDetails().put("value", typeAnnotation);
eFeature.getEAnnotations().add(eAnnotation);
}
private void addTransientAnnotationToEClass(EClass eClass)
{
if (eClass.getEAnnotation(Constants.ANNOTATION_SOURCE_TENEO_JPA) != null)
{
return;
}
final EAnnotation eAnnotation = EcoreFactory.eINSTANCE.createEAnnotation();
eAnnotation.setSource(Constants.ANNOTATION_SOURCE_TENEO_JPA);
final String transientAnnotation = "@Transient";
eAnnotation.getDetails().put("value", transientAnnotation);
eClass.getEAnnotations().add(eAnnotation);
}
// see the CDOEntityMapper, there an explicit unique-key is added to
// a column also
private void addUniqueConstraintAnnotation()
{
final EClass eClass = EresourcePackage.eINSTANCE.getCDOResourceNode();
// already been here
if (eClass.getEAnnotation("teneo.jpa") != null) //$NON-NLS-1$
{
return;
}
final EAnnotation annotation = EcoreFactory.eINSTANCE.createEAnnotation();
annotation.setSource("teneo.jpa"); //$NON-NLS-1$
final String tableAnnotation = "@Table(uniqueConstraints={@UniqueConstraint(columnNames={\"" //$NON-NLS-1$
+ CDOHibernateConstants.CONTAINER_PROPERTY_COLUMN + "\", \"" //$NON-NLS-1$
+ EresourcePackage.eINSTANCE.getCDOResourceNode_Name().getName() + "\"})})"; //$NON-NLS-1$
annotation.getDetails().put("value", tableAnnotation); //$NON-NLS-1$
eClass.getEAnnotations().add(annotation);
}
public Properties getMappingProviderProperties()
{
return mappingProviderProperties;
}
public void setMappingProviderProperties(Properties mappingProviderProperties)
{
this.mappingProviderProperties = mappingProviderProperties;
}
}