diff options
Diffstat (limited to 'hibernate/org.eclipse.emf.teneo.hibernate/src/org/eclipse/emf/teneo/hibernate/auditing/AuditHandler.java')
-rw-r--r-- | hibernate/org.eclipse.emf.teneo.hibernate/src/org/eclipse/emf/teneo/hibernate/auditing/AuditHandler.java | 304 |
1 files changed, 184 insertions, 120 deletions
diff --git a/hibernate/org.eclipse.emf.teneo.hibernate/src/org/eclipse/emf/teneo/hibernate/auditing/AuditHandler.java b/hibernate/org.eclipse.emf.teneo.hibernate/src/org/eclipse/emf/teneo/hibernate/auditing/AuditHandler.java index c249cfb76..6ed21c199 100644 --- a/hibernate/org.eclipse.emf.teneo.hibernate/src/org/eclipse/emf/teneo/hibernate/auditing/AuditHandler.java +++ b/hibernate/org.eclipse.emf.teneo.hibernate/src/org/eclipse/emf/teneo/hibernate/auditing/AuditHandler.java @@ -16,6 +16,7 @@ package org.eclipse.emf.teneo.hibernate.auditing; import java.io.Serializable; +import java.lang.reflect.Array; import java.lang.reflect.Constructor; import java.util.Collection; import java.util.concurrent.ConcurrentHashMap; @@ -32,14 +33,18 @@ import org.eclipse.emf.ecore.EStructuralFeature; import org.eclipse.emf.ecore.EcoreFactory; import org.eclipse.emf.ecore.EcorePackage; import org.eclipse.emf.ecore.util.EcoreUtil; +import org.eclipse.emf.ecore.util.ExtendedMetaData; +import org.eclipse.emf.ecore.util.FeatureMap; +import org.eclipse.emf.ecore.util.FeatureMapUtil; import org.eclipse.emf.ecore.xml.type.XMLTypePackage; import org.eclipse.emf.teneo.Constants; import org.eclipse.emf.teneo.PersistenceOptions; +import org.eclipse.emf.teneo.hibernate.HbDataStore; import org.eclipse.emf.teneo.hibernate.HbStoreException; +import org.eclipse.emf.teneo.hibernate.auditing.model.teneoauditing.TeneoAuditEntry; import org.eclipse.emf.teneo.hibernate.auditing.model.teneoauditing.TeneoauditingPackage; import org.eclipse.emf.teneo.util.StoreUtil; import org.hibernate.Session; -import org.hibernate.engine.internal.ForeignKeys; import org.hibernate.engine.spi.SessionImplementor; /** @@ -70,35 +75,59 @@ public class AuditHandler { * {@link EReference} values to a String containing the id. */ @SuppressWarnings("unchecked") - public void copyContent(Session session, EObject source, EObject target, boolean copyCollections) { + public void copyContentToAuditEntry(Session session, EObject source, TeneoAuditEntry auditEntry, + boolean copyCollections) { final EClass sourceEClass = source.eClass(); - final EClass targetEClass = target.eClass(); + final EClass targetEClass = auditEntry.eClass(); for (EStructuralFeature targetEFeature : targetEClass.getEAllStructuralFeatures()) { + + if (!copyCollections && targetEFeature.isMany()) { + continue; + } + + // initialize with new arrays always to prevent hibernate from complaining if the + // same array is re-used accross entities + if (targetEFeature.getEType().getInstanceClass() != null + && targetEFeature.getEType().getInstanceClass().isArray()) { + auditEntry.eSet(targetEFeature, + Array.newInstance(targetEFeature.getEType().getInstanceClass().getComponentType(), 0)); + } + final EStructuralFeature sourceEFeature = sourceEClass.getEStructuralFeature(targetEFeature .getName()); if (sourceEFeature != null && (sourceEFeature.isMany() || source.eIsSet(sourceEFeature))) { - if (sourceEFeature instanceof EReference) { + if (targetEFeature instanceof EAttribute && sourceEFeature instanceof EReference) { if (sourceEFeature.isMany()) { - if (copyCollections) { - for (Object value : (Collection<?>) source.eGet(sourceEFeature)) { - final String idAsString = AuditHandler.getInstance().idToString(session, value); - ((Collection<Object>) target.eGet(targetEFeature)).add(idAsString); - } + for (Object value : (Collection<?>) source.eGet(sourceEFeature)) { + final String idAsString = AuditHandler.getInstance().entityToIdString(session, value); + ((Collection<Object>) auditEntry.eGet(targetEFeature)).add(idAsString); } } else { - final String idAsString = AuditHandler.getInstance().idToString(session, + final String idAsString = AuditHandler.getInstance().entityToIdString(session, source.eGet(sourceEFeature)); - target.eSet(targetEFeature, idAsString); + auditEntry.eSet(targetEFeature, idAsString); } } else { if (sourceEFeature.isMany()) { - if (copyCollections) { + if (FeatureMapUtil.isFeatureMap(sourceEFeature)) { + for (Object value : ((Collection<?>) source.eGet(sourceEFeature))) { + final FeatureMap.Entry sourceEntry = (FeatureMap.Entry) value; + final EStructuralFeature targetEntryFeature = AuditHandler.getInstance() + .getAuditingModelElement(sourceEntry.getEStructuralFeature(), + auditEntry.eClass().getName()); + final FeatureMap.Entry targetEntry = createFeatureMapEntry(session, + targetEntryFeature, sourceEntry); + ((Collection<Object>) auditEntry.eGet(targetEFeature)).add(targetEntry); + } + } else { for (Object value : (Collection<?>) source.eGet(sourceEFeature)) { - ((Collection<Object>) target.eGet(targetEFeature)).add(value); + ((Collection<Object>) auditEntry.eGet(targetEFeature)).add(convertValue( + targetEFeature, value)); } } } else { - target.eSet(targetEFeature, source.eGet(sourceEFeature)); + auditEntry.eSet(targetEFeature, + convertValue(targetEFeature, source.eGet(sourceEFeature))); } } } @@ -106,12 +135,45 @@ public class AuditHandler { } /** + * Clones an array if the value is an array, otherwise just returns the value. + */ + public Object convertValue(EStructuralFeature eFeature, Object value) { + if (value == null) { + return value; + } + + if (eFeature instanceof EReference && ((EReference) eFeature).isContainment()) { + return EcoreUtil.copy((EObject) value); + } + + // copy the array + if (value.getClass().isArray()) { + final int length = Array.getLength(value); + final Object newArray = Array.newInstance(value.getClass().getComponentType(), length); + for (int i = 0; i < length; i++) { + Array.set(newArray, i, Array.get(value, i)); + } + return newArray; + } + return value; + } + + private FeatureMap.Entry createFeatureMapEntry(Session session, EStructuralFeature eFeature, + FeatureMap.Entry sourceEntry) { + Object value = sourceEntry.getValue(); + if (sourceEntry.getEStructuralFeature() instanceof EReference) { + value = AuditHandler.getInstance().entityToIdString(session, value); + } + return FeatureMapUtil.createEntry(eFeature, value); + } + + /** * Create a string which reflects the id of the entity. */ - public String idToString(Session session, Object entity) { + public String entityToIdString(Session session, Object entity) { final String entityName = ((SessionImplementor) session).bestGuessEntityName(entity); - final Serializable id = ForeignKeys.getEntityIdentifierIfNotUnsaved(entityName, entity, - (SessionImplementor) session); + final Serializable id = ((SessionImplementor) session).getEntityPersister(entityName, entity) + .getIdentifier(entity, (SessionImplementor) session); return entityName + ID_SEPARATOR + id.getClass().getName() + ID_SEPARATOR + id; } @@ -174,20 +236,30 @@ public class AuditHandler { return (T) StoreUtil.stringToStructureFeature(id); } + public EClass getAuditingModelElement(EClass modelElement) { + return getAuditingModelElement(modelElement, null); + } + /** * Return the audit model element used to audit the passed in model element. * + * The qualifier is used to handle an efeature in a super class which is copied multiple times to + * auditing subclasses. + * * @see #setAuditingAssociation(EModelElement, EModelElement) */ @SuppressWarnings("unchecked") - public <T extends EModelElement> T getAuditingModelElement(T modelElement) { + public <T extends EModelElement> T getAuditingModelElement(T modelElement, String qualifier) { final EAnnotation eAnnotation = modelElement .getEAnnotation(Constants.ANNOTATION_SOURCE_AUDITING); if (eAnnotation == null) { return null; } + // note a qualifier is needed because a feature is created + // multiple times for an audit feature in the audit table + // so qualify using the audit eclass final String id = eAnnotation.getDetails().get( - Constants.ANNOTATION_AUDITING_MODELELEMENT_AUDITING); + Constants.ANNOTATION_AUDITING_MODELELEMENT_AUDITING + (qualifier == null ? "" : qualifier)); if (id == null) { return null; } @@ -200,24 +272,39 @@ public class AuditHandler { /** * Returns true if the model element should not be audited. */ - public <T extends EModelElement> boolean isNoAuditing(T modelElement) { + public <T extends EModelElement> boolean isNoAuditing(PersistenceOptions po, T modelElement) { + final EAnnotation teneoAnnotation = modelElement .getEAnnotation(Constants.ANNOTATION_SOURCE_TENEO_JPA); - if (teneoAnnotation == null) { - return false; - } - - for (String value : teneoAnnotation.getDetails().values()) { - if (value != null - && (value.contains("@Transient") || value.contains(Constants.ANNOTATION_AUDITING_NOT))) { + if (teneoAnnotation != null) { + // note check all keys, see EClassAnnotator + boolean noEAVPresent = false; + for (String value : teneoAnnotation.getDetails().values()) { + if (value != null + && (value.contains("@EAV") || value.contains("@Transient") || value + .contains(Constants.ANNOTATION_AUDITING_NOT))) { + return true; + } + noEAVPresent = noEAVPresent || (value != null && value.contains("@NoEAV")); + } + // eav mapped + if (po.isEAVMapping() && !noEAVPresent) { return true; } + } else if (po.isEAVMapping()) { + return true; } if (modelElement instanceof EStructuralFeature) { final EStructuralFeature eStructuralFeature = (EStructuralFeature) modelElement; - if (eStructuralFeature.isVolatile() || eStructuralFeature.isDerived()) { + // part of a featuremap, still incorporate in auditing + if (ExtendedMetaData.INSTANCE.getGroup(eStructuralFeature) != null) { + return false; + } + + if (!eStructuralFeature.isChangeable() || eStructuralFeature.isVolatile() + || eStructuralFeature.isDerived()) { return true; } @@ -236,7 +323,8 @@ public class AuditHandler { * @see #getAuditingModelElement(EModelElement) * @see #getModelElement(EModelElement) */ - public <T extends EModelElement> void setAuditingAssociation(T source, T auditing) { + public <T extends EModelElement> void setAuditingAssociation(T source, T auditing, + String qualifier) { { EAnnotation eAnnotation = auditing.getEAnnotation(Constants.ANNOTATION_SOURCE_AUDITING); if (eAnnotation == null) { @@ -259,11 +347,18 @@ public class AuditHandler { eAnnotation.setSource(Constants.ANNOTATION_SOURCE_AUDITING); source.getEAnnotations().add(eAnnotation); } + + // note a qualifier is needed because a feature is created + // multiple times for an audit feature in the audit table + // so qualify using the audit eclass + final String localQualifier = qualifier != null ? qualifier : ""; if (auditing instanceof EClass) { - eAnnotation.getDetails().put(Constants.ANNOTATION_AUDITING_MODELELEMENT_AUDITING, + eAnnotation.getDetails().put( + Constants.ANNOTATION_AUDITING_MODELELEMENT_AUDITING + localQualifier, StoreUtil.eClassToString((EClass) auditing)); } else { - eAnnotation.getDetails().put(Constants.ANNOTATION_AUDITING_MODELELEMENT_AUDITING, + eAnnotation.getDetails().put( + Constants.ANNOTATION_AUDITING_MODELELEMENT_AUDITING + localQualifier, StoreUtil.structuralFeatureToString((EStructuralFeature) auditing)); } } @@ -272,73 +367,94 @@ public class AuditHandler { /** * Entry point for creating all auditing types needed to audit the sourceEPackage. */ - public EPackage createAuditingEPackage(EPackage sourceEPackage, EPackage.Registry registry, - PersistenceOptions po) { + public EPackage createAuditingEPackage(HbDataStore dataStore, EPackage sourceEPackage, + EPackage.Registry registry, PersistenceOptions po) { final EPackage eAuditingPackage = EcoreFactory.eINSTANCE.createEPackage(); - eAuditingPackage.setName(sourceEPackage.getName() + "-auditing"); - eAuditingPackage.setNsPrefix(sourceEPackage.getNsPrefix() + "-auditing"); - eAuditingPackage.setNsURI(sourceEPackage.getNsURI() + "/auditing"); + eAuditingPackage.setName(sourceEPackage.getName() + "Auditing"); + eAuditingPackage.setNsPrefix(sourceEPackage.getNsPrefix() + "Auditing"); + eAuditingPackage.setNsURI(sourceEPackage.getNsURI() + "Auditing"); for (EClassifier eClassifier : sourceEPackage.getEClassifiers()) { if (eClassifier instanceof EClass) { - if (isNoAuditing(eClassifier)) { + + if (isNoAuditing(po, eClassifier)) { continue; } final EClass eClass = (EClass) eClassifier; final EClass auditingEClass = EcoreFactory.eINSTANCE.createEClass(); - auditingEClass.setName(eClass.getName()); - auditingEClass.getESuperTypes().add(TeneoauditingPackage.eINSTANCE.getTeneoAuditObject()); + auditingEClass.setName(po.getAuditingEntityPrefix() + eClass.getName() + + po.getAuditingEntityPostfix()); + auditingEClass.getESuperTypes().add(TeneoauditingPackage.eINSTANCE.getTeneoAuditEntry()); eAuditingPackage.getEClassifiers().add(auditingEClass); - setAuditingAssociation(eClass, auditingEClass); + setAuditingAssociation(eClass, auditingEClass, null); if (eClass.getEAnnotation(Constants.ANNOTATION_SOURCE_TENEO_JPA_AUDITING) != null) { final EAnnotation teneoAnnotation = EcoreUtil.copy(eClass .getEAnnotation(Constants.ANNOTATION_SOURCE_TENEO_JPA)); teneoAnnotation.setSource(Constants.ANNOTATION_SOURCE_TENEO_JPA); auditingEClass.getEAnnotations().add(teneoAnnotation); + } else { + // at least add an entity annotation + final EAnnotation eAnnotation = EcoreFactory.eINSTANCE.createEAnnotation(); + eAnnotation.setSource(Constants.ANNOTATION_SOURCE_TENEO_JPA); + eAnnotation.getDetails().put("value", "@Entity"); + auditingEClass.getEAnnotations().add(eAnnotation); } - // set the entity name - setEntityNameAndNamedQuery(auditingEClass, po); - for (EStructuralFeature eFeature : eClass.getEAllStructuralFeatures()) { - if (isNoAuditing(eFeature)) { + if (isNoAuditing(po, eFeature)) { continue; } - EAttribute eAttribute; - if (eFeature instanceof EReference) { - eAttribute = EcoreFactory.eINSTANCE.createEAttribute(); - eAttribute.setEType(XMLTypePackage.eINSTANCE.getString()); - } else { - eAttribute = (EAttribute) EcoreUtil.copy(eFeature); - } - // get rid of all teneo.jpa eannotations - eAttribute.getEAnnotations().remove( - eAttribute.getEAnnotation(Constants.ANNOTATION_SOURCE_TENEO_JPA)); - - for (EAttribute eSAttribute : EcorePackage.eINSTANCE.getEStructuralFeature() - .getEAllAttributes()) { - if (eSAttribute.isDerived() || eSAttribute.isVolatile()) { - continue; + EStructuralFeature auditingEFeature; + + if (eFeature instanceof EReference && StoreUtil.isMap(eFeature)) { + auditingEFeature = EcoreUtil.copy(eFeature); + } else if (eFeature instanceof EReference && dataStore.isEmbedded((EReference) eFeature)) { + auditingEFeature = EcoreUtil.copy(eFeature); + } else if (eFeature instanceof EReference) { + auditingEFeature = EcoreFactory.eINSTANCE.createEAttribute(); + auditingEFeature.setEType(XMLTypePackage.eINSTANCE.getString()); + for (EAnnotation eAnnotation : eFeature.getEAnnotations()) { + auditingEFeature.getEAnnotations().add(EcoreUtil.copy(eAnnotation)); } - if (eFeature.eIsSet(eSAttribute)) { - eAttribute.eSet(eSAttribute, eFeature.eGet(eSAttribute)); + + // copy all values + for (EAttribute eSAttribute : EcorePackage.eINSTANCE.getEStructuralFeature() + .getEAllAttributes()) { + if (eSAttribute.isDerived() || eSAttribute.isVolatile()) { + continue; + } + if (eFeature.eIsSet(eSAttribute)) { + auditingEFeature.eSet(eSAttribute, eFeature.eGet(eSAttribute)); + } } + } else { + auditingEFeature = EcoreUtil.copy(eFeature); } - // never be an id - eAttribute.setID(false); - // remove later... - eAttribute.setLowerBound(0); + // get rid of all teneo.jpa eannotations + auditingEFeature.getEAnnotations().remove( + auditingEFeature.getEAnnotation(Constants.ANNOTATION_SOURCE_TENEO_JPA)); + auditingEFeature.getEAnnotations().remove( + auditingEFeature.getEAnnotation(Constants.ANNOTATION_SOURCE_TENEO_HIBERNATE)); + // re-use the other ones if (eFeature.getEAnnotation(Constants.ANNOTATION_SOURCE_TENEO_JPA_AUDITING) != null) { final EAnnotation teneoAnnotation = EcoreUtil.copy(eFeature - .getEAnnotation(Constants.ANNOTATION_SOURCE_TENEO_JPA)); + .getEAnnotation(Constants.ANNOTATION_SOURCE_TENEO_JPA_AUDITING)); teneoAnnotation.setSource(Constants.ANNOTATION_SOURCE_TENEO_JPA); - eAttribute.getEAnnotations().add(teneoAnnotation); + auditingEFeature.getEAnnotations().add(teneoAnnotation); + } + + // never be an id + if (auditingEFeature instanceof EAttribute) { + ((EAttribute) auditingEFeature).setID(false); } + // remove later... + auditingEFeature.setLowerBound(0); - auditingEClass.getEStructuralFeatures().add(eAttribute); + auditingEClass.getEStructuralFeatures().add(auditingEFeature); + setAuditingAssociation(eFeature, auditingEFeature, auditingEClass.getName()); } } } @@ -347,56 +463,4 @@ public class AuditHandler { return eAuditingPackage; } - - /** - * Return the correct entity name using pre and postfix options. - * - * @see PersistenceOptions#getAuditingEntityPostfix() - * @see PersistenceOptions#getAuditingEntityPrefix() - */ - public String getEntityName(EClass auditingEClass, PersistenceOptions po) { - return po.getAuditingEntityPrefix() + auditingEClass.getName() + po.getAuditingEntityPostfix(); - } - - private void setEntityNameAndNamedQuery(EClass auditingEClass, PersistenceOptions po) { - final String entityName = getEntityName(auditingEClass, po); - final String entityNameJPA = "@Entity(name=\"" + entityName + "\")"; - final String namedQuery = "@NamedQuery(name=\"" + entityName + ".previousVersion\", " - + " query=\"select e from " + entityName - + " e where teneo_object_id=:objectId and teneo_end=-1\")"; - if (auditingEClass.getEAnnotation(Constants.ANNOTATION_SOURCE_TENEO_JPA) != null) { - final EAnnotation eAnnotation = auditingEClass - .getEAnnotation(Constants.ANNOTATION_SOURCE_TENEO_JPA); - boolean addEntity = true; - String foundKey = null; - String foundValue = null; - for (String key : eAnnotation.getDetails().keySet()) { - final String value = eAnnotation.getDetails().get(key); - if (value.contains("@Entity")) { - addEntity = false; - eAnnotation.getDetails().put(key, value + "\n" + namedQuery); - } - if (key.equals(Constants.ANNOTATION_KEY_VALUE) - || key.equals(Constants.ANNOTATION_KEY_APPINFO)) { - foundKey = key; - foundValue = value; - } - } - if (addEntity) { - if (foundKey != null) { - eAnnotation.getDetails().put(foundKey, - foundValue + "\n" + entityNameJPA + "\n" + namedQuery); - } else { - eAnnotation.getDetails().put(Constants.ANNOTATION_KEY_VALUE, - entityNameJPA + "\n" + namedQuery); - } - } - } else { - final EAnnotation eAnnotation = EcoreFactory.eINSTANCE.createEAnnotation(); - eAnnotation.setSource(Constants.ANNOTATION_SOURCE_TENEO_JPA); - eAnnotation.getDetails().put(Constants.ANNOTATION_KEY_VALUE, - entityNameJPA + "\n" + namedQuery); - auditingEClass.getEAnnotations().add(eAnnotation); - } - } }
\ No newline at end of file |