| /* |
| * 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; |
| } |
| } |