HHH-7490 - Integrate Envers with Metamodel
This commit is contained in:
parent
6f342358db
commit
24ff8d6eae
|
@ -166,7 +166,7 @@ class TypeSafeActivator {
|
|||
for ( EntityBinding entityBinding : activationContext.getMetadata().getEntityBindings() ) {
|
||||
final String className = entityBinding.getEntity().getDescriptor().getName().toString();
|
||||
|
||||
if ( className == null || className.length() == 0 ) {
|
||||
if ( entityBinding.getEntity().getDescriptor() == null ) {
|
||||
continue;
|
||||
}
|
||||
|
||||
|
|
|
@ -239,7 +239,7 @@ public abstract class PersistentClass implements Serializable, Filterable, MetaA
|
|||
}
|
||||
|
||||
public void addProperty(Property p) {
|
||||
properties.add(p);
|
||||
properties.add( p );
|
||||
declaredProperties.add(p);
|
||||
p.setPersistentClass(this);
|
||||
}
|
||||
|
@ -879,7 +879,7 @@ public abstract class PersistentClass implements Serializable, Filterable, MetaA
|
|||
}
|
||||
|
||||
public void addMappedsuperclassProperty(Property p) {
|
||||
properties.add(p);
|
||||
properties.add( p );
|
||||
p.setPersistentClass(this);
|
||||
}
|
||||
|
||||
|
|
|
@ -25,6 +25,7 @@ package org.hibernate.metamodel;
|
|||
|
||||
import java.util.Collection;
|
||||
import java.util.Map;
|
||||
import java.util.UUID;
|
||||
|
||||
import javax.persistence.NamedStoredProcedureQuery;
|
||||
|
||||
|
@ -61,6 +62,12 @@ public interface Metadata {
|
|||
*/
|
||||
SessionFactory buildSessionFactory();
|
||||
|
||||
/**
|
||||
* Gets the {@link UUID} for this metamodel.
|
||||
*
|
||||
* @return the UUID.
|
||||
*/
|
||||
UUID getUUID();
|
||||
|
||||
EntityBinding getEntityBinding(String entityName);
|
||||
|
||||
|
|
|
@ -29,6 +29,7 @@ import java.util.Collections;
|
|||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.UUID;
|
||||
|
||||
import org.hibernate.AssertionFailure;
|
||||
import org.hibernate.DuplicateMappingException;
|
||||
|
@ -36,6 +37,7 @@ import org.hibernate.EntityMode;
|
|||
import org.hibernate.MappingException;
|
||||
import org.hibernate.SessionFactory;
|
||||
import org.hibernate.annotations.common.util.StringHelper;
|
||||
import org.hibernate.boot.registry.StandardServiceRegistry;
|
||||
import org.hibernate.boot.registry.classloading.spi.ClassLoaderService;
|
||||
import org.hibernate.boot.spi.CacheRegionDefinition;
|
||||
import org.hibernate.cache.spi.access.AccessType;
|
||||
|
@ -117,6 +119,8 @@ import org.jboss.jandex.DotName;
|
|||
import org.jboss.jandex.IndexView;
|
||||
import org.jboss.logging.Logger;
|
||||
|
||||
import static org.hibernate.metamodel.spi.AdditionalJaxbRootProducer.AdditionalJaxbRootProducerContext;
|
||||
|
||||
/**
|
||||
* Represents the process of building a Metadata object. The main entry point is the
|
||||
* static {@link #build}
|
||||
|
@ -126,7 +130,7 @@ import org.jboss.logging.Logger;
|
|||
public class MetadataBuildingProcess {
|
||||
private static final Logger log = Logger.getLogger( MetadataBuildingProcess.class );
|
||||
|
||||
public static MetadataImpl build(MetadataSources sources, MetadataBuildingOptions options) {
|
||||
public static MetadataImpl build(MetadataSources sources, final MetadataBuildingOptions options) {
|
||||
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
// preliminary phases
|
||||
final IndexView jandexView = handleJandex( options, sources );
|
||||
|
@ -195,8 +199,19 @@ public class MetadataBuildingProcess {
|
|||
}
|
||||
|
||||
final List<BindResult> bindResults = new ArrayList<BindResult>();
|
||||
final AdditionalJaxbRootProducerContext jaxbRootProducerContext = new AdditionalJaxbRootProducerContext() {
|
||||
@Override
|
||||
public IndexView getJandexIndex() {
|
||||
return jandexView;
|
||||
}
|
||||
|
||||
@Override
|
||||
public StandardServiceRegistry getServiceRegistry() {
|
||||
return options.getServiceRegistry();
|
||||
}
|
||||
};
|
||||
for ( AdditionalJaxbRootProducer producer : classLoaderService.loadJavaServices( AdditionalJaxbRootProducer.class ) ) {
|
||||
bindResults.addAll( producer.produceRoots( metadataCollector, jandexView ) );
|
||||
bindResults.addAll( producer.produceRoots( metadataCollector, jaxbRootProducerContext ) );
|
||||
}
|
||||
final HbmMetadataSourceProcessorImpl processor = new HbmMetadataSourceProcessorImpl( rootBindingContext, bindResults );
|
||||
final Binder binder = new Binder( rootBindingContext );
|
||||
|
@ -671,6 +686,7 @@ public class MetadataBuildingProcess {
|
|||
private final MetadataBuildingOptions options;
|
||||
private final TypeResolver typeResolver;
|
||||
|
||||
private final UUID uuid;
|
||||
private final Database database;
|
||||
private final ObjectNameNormalizer nameNormalizer;
|
||||
private final MutableIdentifierGeneratorFactory identifierGeneratorFactory;
|
||||
|
@ -702,6 +718,7 @@ public class MetadataBuildingProcess {
|
|||
new HashMap<Identifier, SecondaryTable>();
|
||||
|
||||
public InFlightMetadataCollectorImpl(MetadataBuildingOptions options, TypeResolver typeResolver) {
|
||||
this.uuid = UUID.randomUUID();
|
||||
this.options = options;
|
||||
this.typeResolver = typeResolver;
|
||||
|
||||
|
@ -766,6 +783,10 @@ public class MetadataBuildingProcess {
|
|||
);
|
||||
}
|
||||
|
||||
@Override
|
||||
public UUID getUUID() {
|
||||
return null;
|
||||
}
|
||||
|
||||
|
||||
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
@ -1157,6 +1178,7 @@ public class MetadataBuildingProcess {
|
|||
options.getServiceRegistry(),
|
||||
database,
|
||||
typeResolver,
|
||||
uuid,
|
||||
identifierGeneratorFactory,
|
||||
typeDefinitionMap,
|
||||
filterDefinitionMap,
|
||||
|
|
|
@ -27,6 +27,7 @@ import java.io.Serializable;
|
|||
import java.util.Collection;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
import java.util.UUID;
|
||||
|
||||
import org.hibernate.AssertionFailure;
|
||||
import org.hibernate.MappingException;
|
||||
|
@ -67,6 +68,8 @@ public class MetadataImpl implements MetadataImplementor, Serializable {
|
|||
private final TypeResolver typeResolver;
|
||||
private final IdentifierGeneratorFactory identifierGeneratorFactory;
|
||||
|
||||
private final UUID uuid;
|
||||
|
||||
private final Map<String, TypeDefinition> typeDefinitionMap = new HashMap<String, TypeDefinition>();
|
||||
private final Map<String, FilterDefinition> filterDefinitionMap = new HashMap<String, FilterDefinition>();
|
||||
private final Map<String, EntityBinding> entityBindingMap = new HashMap<String, EntityBinding>();
|
||||
|
@ -85,6 +88,7 @@ public class MetadataImpl implements MetadataImplementor, Serializable {
|
|||
StandardServiceRegistry serviceRegistry,
|
||||
Database database,
|
||||
TypeResolver typeResolver,
|
||||
UUID uuid,
|
||||
IdentifierGeneratorFactory identifierGeneratorFactory,
|
||||
Map<String, TypeDefinition> typeDefinitionMap,
|
||||
Map<String, FilterDefinition> filterDefinitionMap,
|
||||
|
@ -102,6 +106,7 @@ public class MetadataImpl implements MetadataImplementor, Serializable {
|
|||
this.serviceRegistry = serviceRegistry;
|
||||
this.database = database;
|
||||
this.typeResolver = typeResolver;
|
||||
this.uuid = uuid;
|
||||
this.identifierGeneratorFactory = identifierGeneratorFactory;
|
||||
|
||||
if ( typeDefinitionMap != null ) {
|
||||
|
@ -279,6 +284,11 @@ public class MetadataImpl implements MetadataImplementor, Serializable {
|
|||
return getSessionFactoryBuilder().build();
|
||||
}
|
||||
|
||||
@Override
|
||||
public UUID getUUID() {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public IdentifierGeneratorFactory getIdentifierGeneratorFactory() {
|
||||
return identifierGeneratorFactory;
|
||||
|
|
|
@ -552,7 +552,9 @@ public class Binder {
|
|||
return null;
|
||||
}
|
||||
|
||||
final DotName descriptorTypeName = javaTypeDescriptorRepository.buildName( source.getTypeName() );
|
||||
final DotName descriptorTypeName = javaTypeDescriptorRepository.buildName(
|
||||
typeHelper().determineJavaTypeName( source )
|
||||
);
|
||||
final JavaTypeDescriptor javaTypeDescriptor = javaTypeDescriptorRepository.getType( descriptorTypeName );
|
||||
|
||||
if ( EntitySource.class.isInstance( source ) ) {
|
||||
|
@ -1792,7 +1794,7 @@ public class Binder {
|
|||
if ( attribute != null ) {
|
||||
// validate its ok to use...
|
||||
if ( !Aggregate.class.isInstance( attribute.getSingularAttributeType() ) ) {
|
||||
localBindingContext().makeMappingException(
|
||||
throw localBindingContext().makeMappingException(
|
||||
"Found existing attribute on container for '" + attributeSource.getName()
|
||||
+ "', but was expecting an Aggregate"
|
||||
);
|
||||
|
@ -1805,9 +1807,12 @@ public class Binder {
|
|||
compositeTypeDescriptor = attributeSource.getTypeDescriptor();
|
||||
}
|
||||
else {
|
||||
final EntityMode entityMode =
|
||||
attributeBindingContainer.seekEntityBinding().getHierarchyDetails().getEntityMode();
|
||||
compositeTypeDescriptor = typeHelper().determineJavaType(
|
||||
attributeSource,
|
||||
attributeBindingContainer.getAttributeContainer()
|
||||
attributeBindingContainer.getAttributeContainer(),
|
||||
entityMode
|
||||
);
|
||||
}
|
||||
composite = new Aggregate( compositeTypeDescriptor, null );
|
||||
|
|
|
@ -33,6 +33,7 @@ import java.util.Map;
|
|||
import java.util.Properties;
|
||||
|
||||
import org.hibernate.AssertionFailure;
|
||||
import org.hibernate.EntityMode;
|
||||
import org.hibernate.boot.registry.classloading.spi.ClassLoaderService;
|
||||
import org.hibernate.cfg.NotYetImplementedException;
|
||||
import org.hibernate.internal.util.beans.BeanInfoHelper;
|
||||
|
@ -45,6 +46,7 @@ import org.hibernate.metamodel.source.spi.AttributeSource;
|
|||
import org.hibernate.metamodel.source.spi.BasicPluralAttributeElementSource;
|
||||
import org.hibernate.metamodel.source.spi.ComponentAttributeSource;
|
||||
import org.hibernate.metamodel.source.spi.HibernateTypeSource;
|
||||
import org.hibernate.metamodel.source.spi.IdentifiableTypeSource;
|
||||
import org.hibernate.metamodel.source.spi.ManyToManyPluralAttributeElementSource;
|
||||
import org.hibernate.metamodel.source.spi.PluralAttributeSource;
|
||||
import org.hibernate.metamodel.source.spi.SingularAttributeSource;
|
||||
|
@ -808,6 +810,35 @@ class HibernateTypeHelper {
|
|||
return null;
|
||||
}
|
||||
|
||||
public String determineJavaTypeName(final IdentifiableTypeSource identifiableTypeSource) {
|
||||
if ( identifiableTypeSource.getTypeName() == null ) {
|
||||
if ( identifiableTypeSource.getHierarchy().getEntityMode() == EntityMode.MAP ) {
|
||||
return Map.class.getName();
|
||||
|
||||
}
|
||||
else {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
else {
|
||||
return identifiableTypeSource.getTypeName();
|
||||
}
|
||||
}
|
||||
|
||||
public JavaTypeDescriptor determineJavaType(
|
||||
final ComponentAttributeSource attributeSource,
|
||||
final AttributeContainer attributeContainer,
|
||||
final EntityMode entityMode) {
|
||||
if ( attributeSource.getTypeDescriptor() != null ) {
|
||||
return attributeSource.getTypeDescriptor();
|
||||
}
|
||||
else if ( entityMode == EntityMode.MAP ) {
|
||||
return bindingContext().typeDescriptor( Map.class.getName() );
|
||||
}
|
||||
else {
|
||||
return determineJavaType( attributeSource, attributeContainer );
|
||||
}
|
||||
}
|
||||
|
||||
public JavaTypeDescriptor determineJavaType(
|
||||
final AttributeSource attributeSource,
|
||||
|
|
|
@ -689,6 +689,9 @@ public class JandexHelper {
|
|||
}
|
||||
returnValue = arr;
|
||||
}
|
||||
else if ( type.isEnum() && String.class.isInstance( returnValue ) ) {
|
||||
returnValue = Enum.valueOf( (Class<Enum>) type, (String) returnValue );
|
||||
}
|
||||
return type.cast( nullIfUndefined( returnValue, type ) );
|
||||
}
|
||||
|
||||
|
|
|
@ -202,4 +202,8 @@ class KeyManyToOneSourceImpl
|
|||
public boolean isCascadeDeleteEnabled() {
|
||||
return "cascade".equals( keyManyToOneElement.getOnDelete().value() );
|
||||
}
|
||||
|
||||
protected String getClassName() {
|
||||
return keyManyToOneElement.getClazz();
|
||||
}
|
||||
}
|
||||
|
|
|
@ -25,6 +25,8 @@ package org.hibernate.metamodel.spi;
|
|||
|
||||
import java.util.List;
|
||||
|
||||
import org.hibernate.boot.registry.StandardServiceRegistry;
|
||||
import org.hibernate.service.ServiceRegistry;
|
||||
import org.hibernate.xml.spi.BindResult;
|
||||
|
||||
import org.jboss.jandex.IndexView;
|
||||
|
@ -41,9 +43,30 @@ public interface AdditionalJaxbRootProducer {
|
|||
* Produce and return the list of additional mappings to be processed.
|
||||
*
|
||||
* @param metadataCollector The metadata (for access to binding information).
|
||||
* @param jandexIndex The Jandex annotation index
|
||||
* @param context The context.
|
||||
*
|
||||
* @return List of additional mappings
|
||||
*
|
||||
* @see AdditionalJaxbRootProducerContext
|
||||
*/
|
||||
public List<BindResult> produceRoots(InFlightMetadataCollector metadataCollector, IndexView jandexIndex);
|
||||
public List<BindResult> produceRoots(
|
||||
InFlightMetadataCollector metadataCollector,
|
||||
AdditionalJaxbRootProducerContext context);
|
||||
|
||||
public interface AdditionalJaxbRootProducerContext {
|
||||
|
||||
/**
|
||||
* Gets the Jandex annotation index.
|
||||
*
|
||||
* @return the Jandex annotation index
|
||||
*/
|
||||
public IndexView getJandexIndex();
|
||||
|
||||
/**
|
||||
* Gets the service registry.
|
||||
*
|
||||
* @return The service registry.
|
||||
*/
|
||||
public StandardServiceRegistry getServiceRegistry();
|
||||
}
|
||||
}
|
||||
|
|
|
@ -26,6 +26,7 @@ package org.hibernate.metamodel.spi.binding;
|
|||
import java.util.List;
|
||||
|
||||
import org.hibernate.FetchMode;
|
||||
import org.hibernate.metamodel.spi.relational.Value;
|
||||
|
||||
/**
|
||||
* Basic contract describing the commonality between the various types of collection element mappings.
|
||||
|
@ -52,6 +53,11 @@ public abstract class AbstractPluralAttributeElementBinding implements PluralAtt
|
|||
|
||||
protected abstract RelationalValueBindingContainer getRelationalValueContainer();
|
||||
|
||||
@Override
|
||||
public List<Value> getValues() {
|
||||
return getRelationalValueContainer().values();
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<RelationalValueBinding> getRelationalValueBindings() {
|
||||
return getRelationalValueContainer().relationalValueBindings();
|
||||
|
|
|
@ -26,6 +26,7 @@ package org.hibernate.metamodel.spi.binding;
|
|||
import java.util.List;
|
||||
|
||||
import org.hibernate.AssertionFailure;
|
||||
import org.hibernate.metamodel.spi.relational.Value;
|
||||
|
||||
/**
|
||||
*
|
||||
|
@ -44,6 +45,11 @@ public class BasicPluralAttributeIndexBinding extends AbstractPluralAttributeInd
|
|||
return relationalValueBindingContainer.relationalValueBindings();
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<Value> getValues() {
|
||||
return relationalValueBindingContainer.values();
|
||||
}
|
||||
|
||||
public void setRelationalValueBindings(List<RelationalValueBinding> relationalValueBindings) {
|
||||
if ( relationalValueBindings == null || relationalValueBindings.isEmpty() ) {
|
||||
throw new AssertionFailure( "relationalValueBindings argument must be non-null and non-empty." );
|
||||
|
|
|
@ -30,6 +30,7 @@ import java.util.Map;
|
|||
import org.hibernate.metamodel.source.spi.MetaAttributeContext;
|
||||
import org.hibernate.metamodel.spi.domain.Aggregate;
|
||||
import org.hibernate.metamodel.spi.domain.SingularAttribute;
|
||||
import org.hibernate.metamodel.spi.relational.Value;
|
||||
|
||||
/**
|
||||
* Describes plural attributes of {@link org.hibernate.metamodel.spi.binding.PluralAttributeElementBinding.Nature#AGGREGATE} elements
|
||||
|
@ -90,4 +91,9 @@ public class CompositePluralAttributeIndexBinding extends AbstractPluralAttribut
|
|||
public List<RelationalValueBinding> getRelationalValueBindings() {
|
||||
return compositeAttributeBindingContainer.getRelationalValueBindingContainer().relationalValueBindings();
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<Value> getValues() {
|
||||
return compositeAttributeBindingContainer.getRelationalValueBindingContainer().values();
|
||||
}
|
||||
}
|
||||
|
|
|
@ -630,28 +630,33 @@ public class EntityBinding extends AbstractAttributeBindingContainer implements
|
|||
public AttributeBinding[] getNonIdAttributeBindingClosure(){
|
||||
// TODO: update size to account for joins
|
||||
if ( isRoot() ) {
|
||||
return internalGetNonIdAttributeBindingClosure();
|
||||
return internalGetNonIdAttributeBindings();
|
||||
}
|
||||
else {
|
||||
return ArrayHelper.join(
|
||||
superEntityBinding.getNonIdAttributeBindingClosure(),
|
||||
internalGetNonIdAttributeBindingClosure()
|
||||
internalGetNonIdAttributeBindings()
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
private AttributeBinding[] internalGetNonIdAttributeBindingClosure() {
|
||||
List<AttributeBinding> list = new ArrayList<AttributeBinding>();
|
||||
public List<AttributeBinding> getNonIdAttributeBindings() {
|
||||
final List<AttributeBinding> list = new ArrayList<AttributeBinding>();
|
||||
for ( final AttributeBinding ab : attributeBindings() ) {
|
||||
boolean isId = getHierarchyDetails().getEntityIdentifier().isIdentifierAttributeBinding( ab );
|
||||
if ( !isId ) {
|
||||
list.add( ab );
|
||||
}
|
||||
}
|
||||
return list.toArray( new AttributeBinding[list.size()] );
|
||||
return list;
|
||||
|
||||
}
|
||||
|
||||
private AttributeBinding[] internalGetNonIdAttributeBindings() {
|
||||
final List<AttributeBinding> list = getNonIdAttributeBindings();
|
||||
return list.toArray( new AttributeBinding[list.size()] );
|
||||
}
|
||||
|
||||
public List<EntityBinding> getDirectSubEntityBindings() {
|
||||
return subEntityBindings;
|
||||
}
|
||||
|
@ -772,7 +777,7 @@ public class EntityBinding extends AbstractAttributeBindingContainer implements
|
|||
|
||||
results = ArrayHelper.join(
|
||||
results,
|
||||
subEntityBinding.internalGetNonIdAttributeBindingClosure()
|
||||
subEntityBinding.internalGetNonIdAttributeBindings()
|
||||
);
|
||||
// TODO: if EntityBinding.attributeBindings() excludes joined attributes, then they need to be added here
|
||||
}
|
||||
|
|
|
@ -26,6 +26,7 @@ package org.hibernate.metamodel.spi.binding;
|
|||
import java.util.List;
|
||||
|
||||
import org.hibernate.FetchMode;
|
||||
import org.hibernate.metamodel.spi.relational.Value;
|
||||
|
||||
|
||||
/**
|
||||
|
@ -41,6 +42,8 @@ public interface PluralAttributeElementBinding {
|
|||
*/
|
||||
PluralAttributeBinding getPluralAttributeBinding();
|
||||
|
||||
List<Value> getValues();
|
||||
|
||||
/**
|
||||
* Retrieve the relational aspect of the element binding. Essentially describes the column(s) to which the
|
||||
* binding maps the elements
|
||||
|
|
|
@ -26,6 +26,7 @@ package org.hibernate.metamodel.spi.binding;
|
|||
import java.util.List;
|
||||
|
||||
import org.hibernate.metamodel.spi.domain.Type;
|
||||
import org.hibernate.metamodel.spi.relational.Value;
|
||||
|
||||
/**
|
||||
* @author Steve Ebersole
|
||||
|
@ -43,6 +44,8 @@ public interface PluralAttributeIndexBinding {
|
|||
*/
|
||||
public List<RelationalValueBinding> getRelationalValueBindings();
|
||||
|
||||
List<Value> getValues();
|
||||
|
||||
HibernateTypeDescriptor getHibernateTypeDescriptor();
|
||||
|
||||
Type getPluralAttributeIndexType();
|
||||
|
|
|
@ -225,6 +225,15 @@ public class EntityManagerFactoryBuilderImpl implements EntityManagerFactoryBuil
|
|||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the metadata.
|
||||
* @return the metadata.
|
||||
* @deprecated This should only be needed for testing and should ultimately be removed.
|
||||
*/
|
||||
public MetadataImplementor getMetadata() {
|
||||
return metadata;
|
||||
}
|
||||
|
||||
private SettingsImpl configure(StandardServiceRegistryBuilder ssrBuilder) {
|
||||
final SettingsImpl settings = new SettingsImpl();
|
||||
|
||||
|
|
|
@ -25,11 +25,11 @@ package org.hibernate.envers;
|
|||
|
||||
import java.util.HashSet;
|
||||
import java.util.Set;
|
||||
import javax.persistence.CollectionTable;
|
||||
import javax.persistence.Column;
|
||||
import javax.persistence.ElementCollection;
|
||||
import javax.persistence.FetchType;
|
||||
import javax.persistence.JoinColumn;
|
||||
import javax.persistence.JoinTable;
|
||||
import javax.persistence.MappedSuperclass;
|
||||
|
||||
import org.hibernate.annotations.Fetch;
|
||||
|
@ -45,7 +45,7 @@ import org.hibernate.annotations.FetchMode;
|
|||
@MappedSuperclass
|
||||
public class DefaultTrackingModifiedEntitiesRevisionEntity extends DefaultRevisionEntity {
|
||||
@ElementCollection(fetch = FetchType.EAGER)
|
||||
@JoinTable(name = "REVCHANGES", joinColumns = @JoinColumn(name = "REV"))
|
||||
@CollectionTable(name = "REVCHANGES", joinColumns = @JoinColumn(name = "REV"))
|
||||
@Column(name = "ENTITYNAME")
|
||||
@Fetch(FetchMode.JOIN)
|
||||
@ModifiedEntityNames
|
||||
|
|
|
@ -0,0 +1,127 @@
|
|||
/*
|
||||
* Hibernate, Relational Persistence for Idiomatic Java
|
||||
*
|
||||
* Copyright (c) 2013, Red Hat Inc. or third-party contributors as
|
||||
* indicated by the @author tags or express copyright attribution
|
||||
* statements applied by the authors. All third-party contributions are
|
||||
* distributed under license by Red Hat Inc.
|
||||
*
|
||||
* This copyrighted material is made available to anyone wishing to use, modify,
|
||||
* copy, or redistribute it subject to the terms and conditions of the GNU
|
||||
* Lesser General Public License, as published by the Free Software Foundation.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
|
||||
* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
|
||||
* for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public License
|
||||
* along with this distribution; if not, write to:
|
||||
* Free Software Foundation, Inc.
|
||||
* 51 Franklin Street, Fifth Floor
|
||||
* Boston, MA 02110-1301 USA
|
||||
*/
|
||||
package org.hibernate.envers.configuration.internal;
|
||||
|
||||
import java.lang.reflect.Array;
|
||||
import java.lang.reflect.Method;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
import javassist.util.proxy.MethodHandler;
|
||||
import javassist.util.proxy.ProxyFactory;
|
||||
import javassist.util.proxy.ProxyObject;
|
||||
import org.jboss.jandex.AnnotationInstance;
|
||||
|
||||
import org.hibernate.HibernateException;
|
||||
import org.hibernate.boot.registry.classloading.spi.ClassLoaderService;
|
||||
import org.hibernate.metamodel.internal.source.annotations.util.JandexHelper;
|
||||
|
||||
/**
|
||||
* @author Lukasz Antoniak (lukasz dot antoniak at gmail dot com)
|
||||
*/
|
||||
public class AnnotationProxyBuilder {
|
||||
private final Map<AnnotationInstance, Object> proxyObjectMap = new HashMap<AnnotationInstance, Object>();
|
||||
private final Map<Class, ProxyFactory> proxyFactoryMap = new HashMap<Class, ProxyFactory>();
|
||||
|
||||
public <T> T getAnnotationProxy(
|
||||
final AnnotationInstance annotationInstance,
|
||||
final Class<T> annotationClass,
|
||||
final ClassLoaderService classLoaderService) {
|
||||
T annotationProxy = (T) proxyObjectMap.get( annotationInstance );
|
||||
if ( annotationProxy == null ) {
|
||||
annotationProxy = buildAnnotationProxy( annotationInstance, annotationClass, classLoaderService );
|
||||
proxyObjectMap.put( annotationInstance, annotationProxy );
|
||||
}
|
||||
return annotationProxy;
|
||||
}
|
||||
|
||||
private <T> T buildAnnotationProxy(
|
||||
final AnnotationInstance annotationInstance,
|
||||
final Class<T> annotationClass,
|
||||
final ClassLoaderService classLoaderService) {
|
||||
try {
|
||||
final Class annotation = annotationClass.getClassLoader().loadClass( annotationClass.getName() );
|
||||
final Class proxyClass = getProxyFactory( annotation ).createClass();
|
||||
final ProxyObject proxyObject = (ProxyObject) proxyClass.newInstance();
|
||||
proxyObject.setHandler( new MethodHandler() {
|
||||
@Override
|
||||
public Object invoke(Object self, Method thisMethod, Method proceed, Object[] args) throws Throwable {
|
||||
String executedMethodName = thisMethod.getName();
|
||||
if ( "toString".equals( executedMethodName ) ) {
|
||||
return proxyClass.getName() + "@" + System.identityHashCode( self );
|
||||
}
|
||||
final Class<?> returnType = thisMethod.getReturnType();
|
||||
if ( returnType.isArray() && returnType.getComponentType().isAnnotation() ) {
|
||||
final AnnotationInstance[] returnValues = JandexHelper.getValue(
|
||||
annotationInstance,
|
||||
executedMethodName,
|
||||
AnnotationInstance[].class,
|
||||
classLoaderService
|
||||
);
|
||||
return buildAnnotationProxyArray(
|
||||
returnValues,
|
||||
returnType.getComponentType(),
|
||||
classLoaderService
|
||||
);
|
||||
}
|
||||
return JandexHelper.getValue(
|
||||
annotationInstance,
|
||||
executedMethodName,
|
||||
thisMethod.getReturnType(),
|
||||
classLoaderService
|
||||
);
|
||||
}
|
||||
} );
|
||||
return (T) proxyObject;
|
||||
}
|
||||
catch ( Exception e ) {
|
||||
throw new HibernateException( e );
|
||||
}
|
||||
}
|
||||
|
||||
@SuppressWarnings( {"unchecked"})
|
||||
private <T> T[] buildAnnotationProxyArray(
|
||||
final AnnotationInstance[] annotationInstances,
|
||||
final Class<T> annotationClass,
|
||||
final ClassLoaderService classLoaderService) {
|
||||
final T[] annotationProxyArray = (T[]) Array.newInstance( annotationClass, annotationInstances.length );
|
||||
for ( int i = 0 ; i < annotationInstances.length ; i++ ) {
|
||||
annotationProxyArray[i] = buildAnnotationProxy( annotationInstances[i], annotationClass, classLoaderService );
|
||||
}
|
||||
return annotationProxyArray;
|
||||
}
|
||||
|
||||
private ProxyFactory getProxyFactory(final Class annotation) {
|
||||
ProxyFactory proxyFactory = proxyFactoryMap.get( annotation );
|
||||
if ( proxyFactory == null ) {
|
||||
proxyFactory = new ProxyFactory();
|
||||
proxyFactoryMap.put( annotation, proxyFactory );
|
||||
}
|
||||
proxyFactory.setInterfaces( new Class[] { annotation } );
|
||||
return proxyFactory;
|
||||
}
|
||||
}
|
|
@ -25,11 +25,12 @@ package org.hibernate.envers.configuration.internal;
|
|||
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
import java.util.Properties;
|
||||
|
||||
import org.hibernate.engine.config.spi.ConfigurationService;
|
||||
import org.hibernate.engine.config.spi.StandardConverters;
|
||||
import org.hibernate.envers.configuration.EnversSettings;
|
||||
import org.hibernate.envers.strategy.DefaultAuditStrategy;
|
||||
import org.hibernate.internal.util.config.ConfigurationHelper;
|
||||
import org.hibernate.service.ServiceRegistry;
|
||||
|
||||
/**
|
||||
* Configuration of versions entities - names of fields, entities and tables created to store versioning information.
|
||||
|
@ -62,36 +63,48 @@ public class AuditEntitiesConfiguration {
|
|||
|
||||
private final String embeddableSetOrdinalPropertyName;
|
||||
|
||||
public AuditEntitiesConfiguration(Properties properties, String revisionInfoEntityName) {
|
||||
public AuditEntitiesConfiguration(ServiceRegistry serviceRegistry, String revisionInfoEntityName) {
|
||||
this.revisionInfoEntityName = revisionInfoEntityName;
|
||||
|
||||
auditTablePrefix = ConfigurationHelper.getString( EnversSettings.AUDIT_TABLE_PREFIX, properties, "" );
|
||||
auditTableSuffix = ConfigurationHelper.getString( EnversSettings.AUDIT_TABLE_SUFFIX, properties, "_AUD" );
|
||||
final ConfigurationService configurationService = serviceRegistry.getService( ConfigurationService.class );
|
||||
|
||||
auditStrategyName = ConfigurationHelper.getString(
|
||||
EnversSettings.AUDIT_STRATEGY, properties, DefaultAuditStrategy.class.getName()
|
||||
auditTablePrefix = configurationService.getSetting(
|
||||
EnversSettings.AUDIT_TABLE_PREFIX, StandardConverters.STRING, ""
|
||||
);
|
||||
auditTableSuffix = configurationService.getSetting(
|
||||
EnversSettings.AUDIT_TABLE_SUFFIX, StandardConverters.STRING, "_AUD"
|
||||
);
|
||||
|
||||
auditStrategyName = configurationService.getSetting(
|
||||
EnversSettings.AUDIT_STRATEGY, StandardConverters.STRING, DefaultAuditStrategy.class.getName()
|
||||
);
|
||||
|
||||
originalIdPropName = "originalId";
|
||||
|
||||
revisionFieldName = ConfigurationHelper.getString( EnversSettings.REVISION_FIELD_NAME, properties, "REV" );
|
||||
revisionFieldName = configurationService.getSetting(
|
||||
EnversSettings.REVISION_FIELD_NAME, StandardConverters.STRING, "REV"
|
||||
);
|
||||
|
||||
revisionTypePropName = ConfigurationHelper.getString(
|
||||
EnversSettings.REVISION_TYPE_FIELD_NAME, properties, "REVTYPE"
|
||||
revisionTypePropName = configurationService.getSetting(
|
||||
EnversSettings.REVISION_TYPE_FIELD_NAME, StandardConverters.STRING, "REVTYPE"
|
||||
);
|
||||
revisionTypePropType = "byte";
|
||||
|
||||
revisionEndFieldName = ConfigurationHelper.getString(
|
||||
EnversSettings.AUDIT_STRATEGY_VALIDITY_END_REV_FIELD_NAME, properties, "REVEND"
|
||||
revisionEndFieldName = configurationService.getSetting(
|
||||
EnversSettings.AUDIT_STRATEGY_VALIDITY_END_REV_FIELD_NAME, StandardConverters.STRING, "REVEND"
|
||||
);
|
||||
|
||||
revisionEndTimestampEnabled = ConfigurationHelper.getBoolean(
|
||||
EnversSettings.AUDIT_STRATEGY_VALIDITY_STORE_REVEND_TIMESTAMP, properties, false
|
||||
revisionEndTimestampEnabled = configurationService.getSetting(
|
||||
EnversSettings.AUDIT_STRATEGY_VALIDITY_STORE_REVEND_TIMESTAMP,
|
||||
StandardConverters.BOOLEAN,
|
||||
false
|
||||
);
|
||||
|
||||
if ( revisionEndTimestampEnabled ) {
|
||||
revisionEndTimestampFieldName = ConfigurationHelper.getString(
|
||||
EnversSettings.AUDIT_STRATEGY_VALIDITY_REVEND_TIMESTAMP_FIELD_NAME, properties, "REVEND_TSTMP"
|
||||
revisionEndTimestampFieldName = configurationService.getSetting(
|
||||
EnversSettings.AUDIT_STRATEGY_VALIDITY_REVEND_TIMESTAMP_FIELD_NAME,
|
||||
StandardConverters.STRING,
|
||||
"REVEND_TSTMP"
|
||||
);
|
||||
}
|
||||
else {
|
||||
|
@ -103,8 +116,8 @@ public class AuditEntitiesConfiguration {
|
|||
revisionNumberPath = originalIdPropName + "." + revisionFieldName + ".id";
|
||||
revisionPropBasePath = originalIdPropName + "." + revisionFieldName + ".";
|
||||
|
||||
embeddableSetOrdinalPropertyName = ConfigurationHelper.getString(
|
||||
EnversSettings.EMBEDDABLE_SET_ORDINAL_FIELD_NAME, properties, "SETORDINAL"
|
||||
embeddableSetOrdinalPropertyName = configurationService.getSetting(
|
||||
EnversSettings.EMBEDDABLE_SET_ORDINAL_FIELD_NAME, StandardConverters.STRING, "SETORDINAL"
|
||||
);
|
||||
}
|
||||
|
||||
|
|
|
@ -33,12 +33,12 @@ import org.hibernate.envers.configuration.internal.metadata.reader.ClassAuditing
|
|||
import org.hibernate.envers.configuration.internal.metadata.reader.PropertyAuditingData;
|
||||
import org.hibernate.envers.internal.EnversMessageLogger;
|
||||
import org.hibernate.envers.internal.tools.MappingTools;
|
||||
import org.hibernate.mapping.PersistentClass;
|
||||
import org.hibernate.metamodel.spi.binding.EntityBinding;
|
||||
|
||||
import org.jboss.logging.Logger;
|
||||
|
||||
/**
|
||||
* A helper class holding auditing meta-data for all persistent classes.
|
||||
* A helper class holding auditing meta-data for all entity bindings.
|
||||
*
|
||||
* @author Adam Warski (adam at warski dot org)
|
||||
*/
|
||||
|
@ -49,24 +49,25 @@ public class ClassesAuditingData {
|
|||
);
|
||||
|
||||
private final Map<String, ClassAuditingData> entityNameToAuditingData = new HashMap<String, ClassAuditingData>();
|
||||
private final Map<PersistentClass, ClassAuditingData> persistentClassToAuditingData = new LinkedHashMap<PersistentClass, ClassAuditingData>();
|
||||
private final Map<EntityBinding, ClassAuditingData> entityBindingToAuditingData =
|
||||
new LinkedHashMap<EntityBinding, ClassAuditingData>();
|
||||
|
||||
/**
|
||||
* Stores information about auditing meta-data for the given class.
|
||||
*
|
||||
* @param pc Persistent class.
|
||||
* @param entityBinding The entity binding.
|
||||
* @param cad Auditing meta-data for the given class.
|
||||
*/
|
||||
public void addClassAuditingData(PersistentClass pc, ClassAuditingData cad) {
|
||||
entityNameToAuditingData.put( pc.getEntityName(), cad );
|
||||
persistentClassToAuditingData.put( pc, cad );
|
||||
public void addClassAuditingData(EntityBinding entityBinding, ClassAuditingData cad) {
|
||||
entityNameToAuditingData.put( entityBinding.getEntityName(), cad );
|
||||
entityBindingToAuditingData.put( entityBinding, cad );
|
||||
}
|
||||
|
||||
/**
|
||||
* @return A collection of all auditing meta-data for persistent classes.
|
||||
*/
|
||||
public Collection<Map.Entry<PersistentClass, ClassAuditingData>> getAllClassAuditedData() {
|
||||
return persistentClassToAuditingData.entrySet();
|
||||
public Collection<Map.Entry<EntityBinding, ClassAuditingData>> getAllEntityBindingAuditedData() {
|
||||
return entityBindingToAuditingData.entrySet();
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -85,27 +86,27 @@ public class ClassesAuditingData {
|
|||
* </ul>
|
||||
*/
|
||||
public void updateCalculatedFields() {
|
||||
for ( Map.Entry<PersistentClass, ClassAuditingData> classAuditingDataEntry : persistentClassToAuditingData.entrySet() ) {
|
||||
final PersistentClass pc = classAuditingDataEntry.getKey();
|
||||
for ( Map.Entry<EntityBinding, ClassAuditingData> classAuditingDataEntry : entityBindingToAuditingData.entrySet() ) {
|
||||
final EntityBinding entityBinding = classAuditingDataEntry.getKey();
|
||||
final ClassAuditingData classAuditingData = classAuditingDataEntry.getValue();
|
||||
for ( String propertyName : classAuditingData.getPropertyNames() ) {
|
||||
final PropertyAuditingData propertyAuditingData = classAuditingData.getPropertyAuditingData( propertyName );
|
||||
// If a property had the @AuditMappedBy annotation, setting the referenced fields to be always insertable.
|
||||
if ( propertyAuditingData.getAuditMappedBy() != null ) {
|
||||
final String referencedEntityName = MappingTools.getReferencedEntityName(
|
||||
pc.getProperty( propertyName ).getValue()
|
||||
entityBinding.locateAttributeBinding( propertyName )
|
||||
);
|
||||
|
||||
final ClassAuditingData referencedClassAuditingData = entityNameToAuditingData.get( referencedEntityName );
|
||||
|
||||
forcePropertyInsertable(
|
||||
referencedClassAuditingData, propertyAuditingData.getAuditMappedBy(),
|
||||
pc.getEntityName(), referencedEntityName
|
||||
entityBinding.getEntityName(), referencedEntityName
|
||||
);
|
||||
|
||||
forcePropertyInsertable(
|
||||
referencedClassAuditingData, propertyAuditingData.getPositionMappedBy(),
|
||||
pc.getEntityName(), referencedEntityName
|
||||
entityBinding.getEntityName(), referencedEntityName
|
||||
);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -28,23 +28,22 @@ import java.io.IOException;
|
|||
import java.io.PrintWriter;
|
||||
import java.io.Writer;
|
||||
import java.util.HashMap;
|
||||
import java.util.Iterator;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
import org.hibernate.MappingException;
|
||||
import org.hibernate.annotations.common.reflection.ReflectionManager;
|
||||
import org.hibernate.boot.registry.classloading.spi.ClassLoaderService;
|
||||
import org.hibernate.cfg.Configuration;
|
||||
import org.hibernate.envers.configuration.internal.metadata.AuditEntityNameRegister;
|
||||
import org.hibernate.envers.configuration.internal.metadata.AuditMetadataGenerator;
|
||||
import org.hibernate.envers.configuration.internal.metadata.EntityXmlMappingData;
|
||||
import org.hibernate.envers.configuration.internal.metadata.reader.AnnotationsMetadataReader;
|
||||
import org.hibernate.envers.configuration.internal.metadata.reader.ClassAuditingData;
|
||||
import org.hibernate.envers.configuration.spi.AuditConfiguration;
|
||||
import org.hibernate.envers.internal.EnversMessageLogger;
|
||||
import org.hibernate.envers.internal.entities.EntitiesConfigurations;
|
||||
import org.hibernate.envers.internal.tools.StringTools;
|
||||
import org.hibernate.envers.internal.tools.graph.GraphTopologicalSort;
|
||||
import org.hibernate.envers.strategy.AuditStrategy;
|
||||
import org.hibernate.mapping.PersistentClass;
|
||||
import org.hibernate.metamodel.spi.binding.EntityBinding;
|
||||
|
||||
import org.dom4j.Document;
|
||||
import org.dom4j.DocumentException;
|
||||
|
@ -52,80 +51,84 @@ import org.dom4j.Element;
|
|||
import org.dom4j.io.DOMWriter;
|
||||
import org.dom4j.io.OutputFormat;
|
||||
import org.dom4j.io.XMLWriter;
|
||||
import org.jboss.logging.Logger;
|
||||
|
||||
/**
|
||||
* @author Adam Warski (adam at warski dot org)
|
||||
*/
|
||||
public class EntitiesConfigurator {
|
||||
private static final EnversMessageLogger LOG = Logger.getMessageLogger(
|
||||
EnversMessageLogger.class,
|
||||
EntitiesConfigurator.class.getName()
|
||||
);
|
||||
|
||||
|
||||
public EntitiesConfigurations configure(
|
||||
Configuration cfg, ReflectionManager reflectionManager,
|
||||
GlobalConfiguration globalCfg, AuditEntitiesConfiguration verEntCfg,
|
||||
AuditStrategy auditStrategy, ClassLoaderService classLoaderService,
|
||||
Document revisionInfoXmlMapping, Element revisionInfoRelationMapping) {
|
||||
AuditConfiguration.AuditConfigurationContext context,
|
||||
AuditStrategy auditStrategy,
|
||||
Document revisionInfoXmlMapping,
|
||||
Element revisionInfoRelationMapping) {
|
||||
// Creating a name register to capture all audit entity names created.
|
||||
final AuditEntityNameRegister auditEntityNameRegister = new AuditEntityNameRegister();
|
||||
final DOMWriter writer = new DOMWriter();
|
||||
|
||||
// Sorting the persistent class topologically - superclass always before subclass
|
||||
final Iterator<PersistentClass> classes = GraphTopologicalSort.sort( new PersistentClassGraphDefiner( cfg ) )
|
||||
.iterator();
|
||||
// Sorting the entity bindings topologically - superclass always before subclass
|
||||
final List<EntityBinding> entityBindings =
|
||||
GraphTopologicalSort.sort( new EntityBindingGraphDefiner( context.getMetadata() ) );
|
||||
|
||||
final ClassesAuditingData classesAuditingData = new ClassesAuditingData();
|
||||
final Map<PersistentClass, EntityXmlMappingData> xmlMappings = new HashMap<PersistentClass, EntityXmlMappingData>();
|
||||
final Map<EntityBinding, EntityXmlMappingData> xmlMappings = new HashMap<EntityBinding, EntityXmlMappingData>();
|
||||
|
||||
// Reading metadata from annotations
|
||||
while ( classes.hasNext() ) {
|
||||
final PersistentClass pc = classes.next();
|
||||
final AnnotationsMetadataReader annotationsMetadataReader = new AnnotationsMetadataReader( context );
|
||||
for ( EntityBinding entityBinding : entityBindings ) {
|
||||
|
||||
// Collecting information from annotations on the persistent class pc
|
||||
final AnnotationsMetadataReader annotationsMetadataReader =
|
||||
new AnnotationsMetadataReader( globalCfg, reflectionManager, pc );
|
||||
final ClassAuditingData auditData = annotationsMetadataReader.getAuditData();
|
||||
final ClassAuditingData auditData = annotationsMetadataReader.getAuditData( entityBinding );
|
||||
|
||||
classesAuditingData.addClassAuditingData( pc, auditData );
|
||||
classesAuditingData.addClassAuditingData( entityBinding, auditData );
|
||||
}
|
||||
|
||||
// Now that all information is read we can update the calculated fields.
|
||||
classesAuditingData.updateCalculatedFields();
|
||||
|
||||
final AuditMetadataGenerator auditMetaGen = new AuditMetadataGenerator(
|
||||
cfg, globalCfg, verEntCfg, auditStrategy,
|
||||
classLoaderService, revisionInfoRelationMapping, auditEntityNameRegister
|
||||
context, auditStrategy, revisionInfoRelationMapping, auditEntityNameRegister
|
||||
);
|
||||
|
||||
// First pass
|
||||
for ( Map.Entry<PersistentClass, ClassAuditingData> pcDatasEntry : classesAuditingData.getAllClassAuditedData() ) {
|
||||
final PersistentClass pc = pcDatasEntry.getKey();
|
||||
for ( Map.Entry<EntityBinding, ClassAuditingData> pcDatasEntry : classesAuditingData.getAllEntityBindingAuditedData() ) {
|
||||
final EntityBinding entityBinding = pcDatasEntry.getKey();
|
||||
final ClassAuditingData auditData = pcDatasEntry.getValue();
|
||||
|
||||
final EntityXmlMappingData xmlMappingData = new EntityXmlMappingData();
|
||||
if ( auditData.isAudited() ) {
|
||||
if ( !StringTools.isEmpty( auditData.getAuditTable().value() ) ) {
|
||||
verEntCfg.addCustomAuditTableName( pc.getEntityName(), auditData.getAuditTable().value() );
|
||||
context.getAuditEntitiesConfiguration().addCustomAuditTableName( entityBinding.getEntityName(), auditData.getAuditTable().value() );
|
||||
}
|
||||
|
||||
auditMetaGen.generateFirstPass( pc, auditData, xmlMappingData, true );
|
||||
auditMetaGen.generateFirstPass( entityBinding, auditData, xmlMappingData, true );
|
||||
}
|
||||
else {
|
||||
auditMetaGen.generateFirstPass( pc, auditData, xmlMappingData, false );
|
||||
auditMetaGen.generateFirstPass( entityBinding, auditData, xmlMappingData, false );
|
||||
}
|
||||
|
||||
xmlMappings.put( pc, xmlMappingData );
|
||||
xmlMappings.put( entityBinding, xmlMappingData );
|
||||
}
|
||||
|
||||
// Second pass
|
||||
for ( Map.Entry<PersistentClass, ClassAuditingData> pcDatasEntry : classesAuditingData.getAllClassAuditedData() ) {
|
||||
for ( Map.Entry<EntityBinding, ClassAuditingData> pcDatasEntry : classesAuditingData.getAllEntityBindingAuditedData() ) {
|
||||
final EntityXmlMappingData xmlMappingData = xmlMappings.get( pcDatasEntry.getKey() );
|
||||
|
||||
if ( pcDatasEntry.getValue().isAudited() ) {
|
||||
auditMetaGen.generateSecondPass( pcDatasEntry.getKey(), pcDatasEntry.getValue(), xmlMappingData );
|
||||
try {
|
||||
cfg.addDocument( writer.write( xmlMappingData.getMainXmlMapping() ) );
|
||||
//writeDocument(xmlMappingData.getMainXmlMapping());
|
||||
logDocument( xmlMappingData.getMainXmlMapping() );
|
||||
context.addDocument( writer.write( xmlMappingData.getMainXmlMapping() ) );
|
||||
|
||||
for ( Document additionalMapping : xmlMappingData.getAdditionalXmlMappings() ) {
|
||||
cfg.addDocument( writer.write( additionalMapping ) );
|
||||
//writeDocument(additionalMapping);
|
||||
logDocument( additionalMapping );
|
||||
context.addDocument( writer.write( additionalMapping ) );
|
||||
}
|
||||
}
|
||||
catch (DocumentException e) {
|
||||
|
@ -138,8 +141,8 @@ public class EntitiesConfigurator {
|
|||
if ( auditMetaGen.getEntitiesConfigurations().size() > 0 ) {
|
||||
try {
|
||||
if ( revisionInfoXmlMapping != null ) {
|
||||
//writeDocument(revisionInfoXmlMapping);
|
||||
cfg.addDocument( writer.write( revisionInfoXmlMapping ) );
|
||||
logDocument( revisionInfoXmlMapping );
|
||||
context.addDocument( writer.write( revisionInfoXmlMapping ) );
|
||||
}
|
||||
}
|
||||
catch (DocumentException e) {
|
||||
|
@ -153,8 +156,10 @@ public class EntitiesConfigurator {
|
|||
);
|
||||
}
|
||||
|
||||
@SuppressWarnings({"UnusedDeclaration"})
|
||||
private void writeDocument(Document e) {
|
||||
private void logDocument(Document e) {
|
||||
if ( !LOG.isDebugEnabled() ) {
|
||||
return;
|
||||
}
|
||||
final ByteArrayOutputStream baos = new ByteArrayOutputStream();
|
||||
final Writer w = new PrintWriter( baos );
|
||||
|
||||
|
@ -167,8 +172,8 @@ public class EntitiesConfigurator {
|
|||
e1.printStackTrace();
|
||||
}
|
||||
|
||||
System.out.println( "-----------" );
|
||||
System.out.println( baos.toString() );
|
||||
System.out.println( "-----------" );
|
||||
LOG.debug( "-----------" );
|
||||
LOG.debug( baos.toString() );
|
||||
LOG.debug( "-----------" );
|
||||
}
|
||||
}
|
||||
|
|
|
@ -27,10 +27,10 @@ import java.util.ArrayList;
|
|||
import java.util.Iterator;
|
||||
import java.util.List;
|
||||
|
||||
import org.hibernate.cfg.Configuration;
|
||||
import org.hibernate.envers.internal.tools.Tools;
|
||||
import org.hibernate.envers.internal.tools.graph.GraphDefiner;
|
||||
import org.hibernate.mapping.PersistentClass;
|
||||
import org.hibernate.metamodel.Metadata;
|
||||
import org.hibernate.metamodel.spi.binding.EntityBinding;
|
||||
|
||||
/**
|
||||
* Defines a graph, where the vertexes are all persistent classes, and there is an edge from
|
||||
|
@ -38,45 +38,45 @@ import org.hibernate.mapping.PersistentClass;
|
|||
*
|
||||
* @author Adam Warski (adam at warski dot org)
|
||||
*/
|
||||
public class PersistentClassGraphDefiner implements GraphDefiner<PersistentClass, String> {
|
||||
private Configuration cfg;
|
||||
public class EntityBindingGraphDefiner implements GraphDefiner<EntityBinding, String> {
|
||||
private Metadata metadata;
|
||||
|
||||
public PersistentClassGraphDefiner(Configuration cfg) {
|
||||
this.cfg = cfg;
|
||||
public EntityBindingGraphDefiner(Metadata metadata) {
|
||||
this.metadata = metadata;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getRepresentation(PersistentClass pc) {
|
||||
public String getRepresentation(EntityBinding pc) {
|
||||
return pc.getEntityName();
|
||||
}
|
||||
|
||||
@Override
|
||||
public PersistentClass getValue(String entityName) {
|
||||
return cfg.getClassMapping( entityName );
|
||||
public EntityBinding getValue(String entityName) {
|
||||
return metadata.getEntityBinding( entityName );
|
||||
}
|
||||
|
||||
@SuppressWarnings({"unchecked"})
|
||||
private void addNeighbours(List<PersistentClass> neighbours, Iterator<PersistentClass> subclassIterator) {
|
||||
private void addNeighbours(List<EntityBinding> neighbours, Iterator<EntityBinding> subclassIterator) {
|
||||
while ( subclassIterator.hasNext() ) {
|
||||
final PersistentClass subclass = subclassIterator.next();
|
||||
final EntityBinding subclass = subclassIterator.next();
|
||||
neighbours.add( subclass );
|
||||
addNeighbours( neighbours, (Iterator<PersistentClass>) subclass.getSubclassIterator() );
|
||||
addNeighbours( neighbours, subclass.getDirectSubEntityBindings().iterator() );
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
@SuppressWarnings({"unchecked"})
|
||||
public List<PersistentClass> getNeighbours(PersistentClass pc) {
|
||||
final List<PersistentClass> neighbours = new ArrayList<PersistentClass>();
|
||||
public List<EntityBinding> getNeighbours(EntityBinding entityBinding) {
|
||||
final List<EntityBinding> neighbours = new ArrayList<EntityBinding>();
|
||||
|
||||
addNeighbours( neighbours, (Iterator<PersistentClass>) pc.getSubclassIterator() );
|
||||
addNeighbours( neighbours, entityBinding.getDirectSubEntityBindings().iterator() );
|
||||
|
||||
return neighbours;
|
||||
}
|
||||
|
||||
@Override
|
||||
@SuppressWarnings({"unchecked"})
|
||||
public List<PersistentClass> getValues() {
|
||||
return Tools.iteratorToList( cfg.getClassMappings() );
|
||||
public List<EntityBinding> getValues() {
|
||||
return Tools.iteratorToList( metadata.getEntityBindings().iterator() );
|
||||
}
|
||||
}
|
|
@ -23,17 +23,17 @@
|
|||
*/
|
||||
package org.hibernate.envers.configuration.internal;
|
||||
|
||||
import java.util.Properties;
|
||||
|
||||
import org.hibernate.MappingException;
|
||||
import org.hibernate.boot.registry.StandardServiceRegistry;
|
||||
import org.hibernate.boot.registry.classloading.spi.ClassLoaderService;
|
||||
import org.hibernate.boot.registry.classloading.spi.ClassLoadingException;
|
||||
import org.hibernate.cfg.Environment;
|
||||
import org.hibernate.dialect.HSQLDialect;
|
||||
import org.hibernate.engine.config.spi.ConfigurationService;
|
||||
import org.hibernate.engine.config.spi.StandardConverters;
|
||||
import org.hibernate.engine.jdbc.env.spi.JdbcEnvironment;
|
||||
import org.hibernate.envers.RevisionListener;
|
||||
import org.hibernate.envers.configuration.EnversSettings;
|
||||
import org.hibernate.envers.internal.tools.ReflectionTools;
|
||||
import org.hibernate.internal.util.config.ConfigurationHelper;
|
||||
|
||||
/**
|
||||
* @author Adam Warski (adam at warski dot org)
|
||||
|
@ -89,46 +89,64 @@ public class GlobalConfiguration {
|
|||
*/
|
||||
private final String correlatedSubqueryOperator;
|
||||
|
||||
public GlobalConfiguration(Properties properties, ClassLoaderService classLoaderService) {
|
||||
generateRevisionsForCollections = ConfigurationHelper.getBoolean(
|
||||
EnversSettings.REVISION_ON_COLLECTION_CHANGE, properties, true
|
||||
public GlobalConfiguration(StandardServiceRegistry serviceRegistry) {
|
||||
|
||||
final ConfigurationService configurationService = serviceRegistry.getService( ConfigurationService.class );
|
||||
|
||||
generateRevisionsForCollections = configurationService.getSetting(
|
||||
EnversSettings.REVISION_ON_COLLECTION_CHANGE, StandardConverters.BOOLEAN, true
|
||||
);
|
||||
|
||||
doNotAuditOptimisticLockingField = ConfigurationHelper.getBoolean(
|
||||
EnversSettings.DO_NOT_AUDIT_OPTIMISTIC_LOCKING_FIELD, properties, true
|
||||
doNotAuditOptimisticLockingField = configurationService.getSetting(
|
||||
EnversSettings.DO_NOT_AUDIT_OPTIMISTIC_LOCKING_FIELD, StandardConverters.BOOLEAN, true
|
||||
);
|
||||
|
||||
storeDataAtDelete = ConfigurationHelper.getBoolean( EnversSettings.STORE_DATA_AT_DELETE, properties, false );
|
||||
|
||||
defaultSchemaName = properties.getProperty( EnversSettings.DEFAULT_SCHEMA, null );
|
||||
defaultCatalogName = properties.getProperty( EnversSettings.DEFAULT_CATALOG, null );
|
||||
|
||||
correlatedSubqueryOperator = HSQLDialect.class.getName()
|
||||
.equals( properties.get( Environment.DIALECT ) ) ? "in" : "=";
|
||||
|
||||
trackEntitiesChangedInRevision = ConfigurationHelper.getBoolean(
|
||||
EnversSettings.TRACK_ENTITIES_CHANGED_IN_REVISION, properties, false
|
||||
storeDataAtDelete = configurationService.getSetting(
|
||||
EnversSettings.STORE_DATA_AT_DELETE, StandardConverters.BOOLEAN, false
|
||||
);
|
||||
|
||||
cascadeDeleteRevision = ConfigurationHelper.getBoolean(
|
||||
"org.hibernate.envers.cascade_delete_revision", properties, false );
|
||||
|
||||
useRevisionEntityWithNativeId = ConfigurationHelper.getBoolean(
|
||||
EnversSettings.USE_REVISION_ENTITY_WITH_NATIVE_ID, properties, true
|
||||
defaultSchemaName = configurationService.getSetting(
|
||||
EnversSettings.DEFAULT_SCHEMA, StandardConverters.STRING
|
||||
);
|
||||
defaultCatalogName = configurationService.getSetting(
|
||||
EnversSettings.DEFAULT_CATALOG, StandardConverters.STRING
|
||||
);
|
||||
|
||||
hasGlobalSettingForWithModifiedFlag = properties.get( EnversSettings.GLOBAL_WITH_MODIFIED_FLAG ) != null;
|
||||
globalWithModifiedFlag = ConfigurationHelper.getBoolean(
|
||||
EnversSettings.GLOBAL_WITH_MODIFIED_FLAG, properties, false
|
||||
);
|
||||
modifiedFlagSuffix = ConfigurationHelper.getString(
|
||||
EnversSettings.MODIFIED_FLAG_SUFFIX, properties, "_MOD"
|
||||
// TODO: is this really needed??? Should be available in dialect...
|
||||
final JdbcEnvironment jdbcEnvironment = serviceRegistry.getService( JdbcEnvironment.class );
|
||||
correlatedSubqueryOperator = HSQLDialect.class.equals( jdbcEnvironment.getDialect().getClass() ) ? "in" : "=";
|
||||
|
||||
trackEntitiesChangedInRevision = configurationService.getSetting(
|
||||
EnversSettings.TRACK_ENTITIES_CHANGED_IN_REVISION, StandardConverters.BOOLEAN, false
|
||||
);
|
||||
|
||||
final String revisionListenerClassName = properties.getProperty( EnversSettings.REVISION_LISTENER, null );
|
||||
// TODO: shouldn't there be an Envers setting for "org.hibernate.envers.cascade_delete_revision"?
|
||||
cascadeDeleteRevision = configurationService.getSetting(
|
||||
"org.hibernate.envers.cascade_delete_revision", StandardConverters.BOOLEAN, false
|
||||
);
|
||||
|
||||
useRevisionEntityWithNativeId = configurationService.getSetting(
|
||||
EnversSettings.USE_REVISION_ENTITY_WITH_NATIVE_ID, StandardConverters.BOOLEAN, true
|
||||
);
|
||||
|
||||
hasGlobalSettingForWithModifiedFlag = null != configurationService.getSetting(
|
||||
EnversSettings.GLOBAL_WITH_MODIFIED_FLAG, StandardConverters.BOOLEAN
|
||||
);
|
||||
globalWithModifiedFlag = configurationService.getSetting(
|
||||
EnversSettings.GLOBAL_WITH_MODIFIED_FLAG, StandardConverters.BOOLEAN, false
|
||||
);
|
||||
modifiedFlagSuffix = configurationService.getSetting(
|
||||
EnversSettings.MODIFIED_FLAG_SUFFIX, StandardConverters.STRING, "_MOD"
|
||||
);
|
||||
|
||||
final String revisionListenerClassName = configurationService.getSetting(
|
||||
EnversSettings.REVISION_LISTENER,
|
||||
StandardConverters.STRING
|
||||
);
|
||||
if ( revisionListenerClassName != null ) {
|
||||
try {
|
||||
revisionListenerClass = ReflectionTools.loadClass( revisionListenerClassName, classLoaderService );
|
||||
revisionListenerClass =
|
||||
serviceRegistry.getService( ClassLoaderService.class ).classForName( revisionListenerClassName );
|
||||
}
|
||||
catch (ClassLoadingException e) {
|
||||
throw new MappingException(
|
||||
|
@ -141,8 +159,8 @@ public class GlobalConfiguration {
|
|||
revisionListenerClass = null;
|
||||
}
|
||||
|
||||
allowIdentifierReuse = ConfigurationHelper.getBoolean(
|
||||
EnversSettings.ALLOW_IDENTIFIER_REUSE, properties, false
|
||||
allowIdentifierReuse = configurationService.getSetting(
|
||||
EnversSettings.ALLOW_IDENTIFIER_REUSE, StandardConverters.BOOLEAN, false
|
||||
);
|
||||
}
|
||||
|
||||
|
|
|
@ -23,28 +23,20 @@
|
|||
*/
|
||||
package org.hibernate.envers.configuration.internal;
|
||||
|
||||
import java.util.Date;
|
||||
import java.util.Iterator;
|
||||
import java.util.Set;
|
||||
import javax.persistence.Column;
|
||||
import java.sql.Date;
|
||||
import java.util.Collection;
|
||||
|
||||
import org.hibernate.MappingException;
|
||||
import org.hibernate.annotations.common.reflection.ReflectionManager;
|
||||
import org.hibernate.annotations.common.reflection.XClass;
|
||||
import org.hibernate.annotations.common.reflection.XProperty;
|
||||
import org.hibernate.cfg.Configuration;
|
||||
import org.hibernate.envers.Audited;
|
||||
import org.hibernate.boot.registry.classloading.spi.ClassLoaderService;
|
||||
import org.hibernate.envers.DefaultRevisionEntity;
|
||||
import org.hibernate.envers.DefaultTrackingModifiedEntitiesRevisionEntity;
|
||||
import org.hibernate.envers.ModifiedEntityNames;
|
||||
import org.hibernate.envers.RevisionEntity;
|
||||
import org.hibernate.envers.RevisionListener;
|
||||
import org.hibernate.envers.RevisionNumber;
|
||||
import org.hibernate.envers.RevisionTimestamp;
|
||||
import org.hibernate.envers.configuration.internal.metadata.AuditTableData;
|
||||
import org.hibernate.envers.configuration.internal.metadata.MetadataTools;
|
||||
import org.hibernate.envers.enhanced.SequenceIdRevisionEntity;
|
||||
import org.hibernate.envers.enhanced.SequenceIdTrackingModifiedEntitiesRevisionEntity;
|
||||
import org.hibernate.envers.event.spi.EnversDotNames;
|
||||
import org.hibernate.envers.internal.entities.PropertyData;
|
||||
import org.hibernate.envers.internal.revisioninfo.DefaultRevisionInfoGenerator;
|
||||
import org.hibernate.envers.internal.revisioninfo.DefaultTrackingModifiedEntitiesRevisionInfoGenerator;
|
||||
|
@ -53,14 +45,31 @@ import org.hibernate.envers.internal.revisioninfo.RevisionInfoGenerator;
|
|||
import org.hibernate.envers.internal.revisioninfo.RevisionInfoNumberReader;
|
||||
import org.hibernate.envers.internal.revisioninfo.RevisionInfoQueryCreator;
|
||||
import org.hibernate.envers.internal.tools.MutableBoolean;
|
||||
import org.hibernate.envers.internal.tools.Tools;
|
||||
import org.hibernate.internal.util.xml.XMLHelper;
|
||||
import org.hibernate.mapping.PersistentClass;
|
||||
import org.hibernate.metamodel.internal.source.annotations.util.JandexHelper;
|
||||
import org.hibernate.metamodel.internal.source.annotations.util.JPADotNames;
|
||||
import org.hibernate.metamodel.spi.InFlightMetadataCollector;
|
||||
import org.hibernate.metamodel.spi.binding.EntityBinding;
|
||||
import org.hibernate.metamodel.spi.binding.AttributeBinding;
|
||||
import org.hibernate.metamodel.spi.binding.HibernateTypeDescriptor;
|
||||
import org.hibernate.metamodel.spi.binding.SetBinding;
|
||||
import org.hibernate.type.IntegerType;
|
||||
import org.hibernate.type.LongType;
|
||||
import org.hibernate.type.Type;
|
||||
|
||||
import org.dom4j.Document;
|
||||
import org.dom4j.Element;
|
||||
|
||||
import org.jboss.jandex.AnnotationInstance;
|
||||
import org.jboss.jandex.AnnotationTarget;
|
||||
import org.jboss.jandex.ClassInfo;
|
||||
import org.jboss.jandex.FieldInfo;
|
||||
import org.jboss.jandex.IndexView;
|
||||
import org.jboss.jandex.MethodInfo;
|
||||
|
||||
import static org.hibernate.metamodel.spi.AdditionalJaxbRootProducer.AdditionalJaxbRootProducerContext;
|
||||
|
||||
/**
|
||||
* @author Adam Warski (adam at warski dot org)
|
||||
* @author Lukasz Antoniak (lukasz dot antoniak at gmail dot com)
|
||||
|
@ -109,9 +118,9 @@ public class RevisionInfoConfiguration {
|
|||
classMapping,
|
||||
revisionInfoIdData.getName(),
|
||||
revisionPropType,
|
||||
globalCfg.isUseRevisionEntityWithNativeId()
|
||||
globalCfg.isUseRevisionEntityWithNativeId(),
|
||||
"REV"
|
||||
);
|
||||
MetadataTools.addColumn( idProperty, "REV", null, null, null, null, null, null, false );
|
||||
|
||||
final Element timestampProperty = MetadataTools.addProperty(
|
||||
classMapping,
|
||||
|
@ -178,8 +187,9 @@ public class RevisionInfoConfiguration {
|
|||
private Element generateRevisionInfoRelationMapping() {
|
||||
final Document document = XMLHelper.getDocumentFactory().createDocument();
|
||||
final Element revRelMapping = document.addElement( "key-many-to-one" );
|
||||
revRelMapping.addAttribute( "type", revisionPropType );
|
||||
revRelMapping.addAttribute( "class", revisionInfoEntityName );
|
||||
// TODO: this does not belong here; does it belong somewhere else????
|
||||
//revRelMapping.addAttribute( "type", revisionPropType );
|
||||
revRelMapping.addAttribute( "entity-name", revisionInfoEntityName );
|
||||
|
||||
if ( revisionPropSqlType != null ) {
|
||||
// Putting a fake name to make Hibernate happy. It will be replaced later anyway.
|
||||
|
@ -189,97 +199,161 @@ public class RevisionInfoConfiguration {
|
|||
return revRelMapping;
|
||||
}
|
||||
|
||||
private void searchForRevisionInfoCfgInProperties(
|
||||
XClass clazz,
|
||||
ReflectionManager reflectionManager,
|
||||
MutableBoolean revisionNumberFound,
|
||||
MutableBoolean revisionTimestampFound,
|
||||
MutableBoolean modifiedEntityNamesFound,
|
||||
String accessType) {
|
||||
for ( XProperty property : clazz.getDeclaredProperties( accessType ) ) {
|
||||
final RevisionNumber revisionNumber = property.getAnnotation( RevisionNumber.class );
|
||||
final RevisionTimestamp revisionTimestamp = property.getAnnotation( RevisionTimestamp.class );
|
||||
final ModifiedEntityNames modifiedEntityNames = property.getAnnotation( ModifiedEntityNames.class );
|
||||
|
||||
if ( revisionNumber != null ) {
|
||||
private void searchForRevisionNumberCfg(
|
||||
ClassInfo revisionInfoEntityClassInfo,
|
||||
EntityBinding revisionInfoEntityBinding,
|
||||
AdditionalJaxbRootProducerContext context,
|
||||
MutableBoolean revisionNumberFound) {
|
||||
for ( AnnotationInstance annotation : context.getJandexIndex().getAnnotations( EnversDotNames.REVISION_NUMBER ) ) {
|
||||
final AnnotationTarget annotationTarget = annotation.target();
|
||||
if ( !( annotationTarget instanceof FieldInfo || annotationTarget instanceof MethodInfo ) ) {
|
||||
throw new MappingException( "@RevisionNumber is applicable only to fields or properties." );
|
||||
}
|
||||
if ( Tools.isFieldOrPropertyOfClass(
|
||||
annotationTarget,
|
||||
revisionInfoEntityClassInfo,
|
||||
context.getJandexIndex() ) ) {
|
||||
if ( revisionNumberFound.isSet() ) {
|
||||
throw new MappingException( "Only one property may be annotated with @RevisionNumber!" );
|
||||
throw new MappingException( "Only one property may be annotated with @RevisionNumber." );
|
||||
}
|
||||
|
||||
final XClass revisionNumberClass = property.getType();
|
||||
if ( reflectionManager.equals( revisionNumberClass, Integer.class ) ||
|
||||
reflectionManager.equals( revisionNumberClass, Integer.TYPE ) ) {
|
||||
revisionInfoIdData = new PropertyData( property.getName(), property.getName(), accessType, null );
|
||||
revisionNumberFound.set();
|
||||
final String revisionNumberProperty = JandexHelper.getPropertyName( annotationTarget );
|
||||
final AttributeBinding revisionNumberAttribute = revisionInfoEntityBinding.locateAttributeBinding(
|
||||
revisionNumberProperty
|
||||
);
|
||||
HibernateTypeDescriptor revisionNumberType = revisionNumberAttribute.getHibernateTypeDescriptor();
|
||||
// TODO: Check whether it is required to verify HibernateTypeDescriptor#getJavaTypeName()?
|
||||
if ( revisionNumberType.getResolvedTypeMapping() instanceof IntegerType ) {
|
||||
revisionPropType = "integer";
|
||||
}
|
||||
else if ( reflectionManager.equals( revisionNumberClass, Long.class ) ||
|
||||
reflectionManager.equals( revisionNumberClass, Long.TYPE ) ) {
|
||||
revisionInfoIdData = new PropertyData( property.getName(), property.getName(), accessType, null );
|
||||
revisionNumberFound.set();
|
||||
|
||||
// The default is integer
|
||||
else if ( revisionNumberType.getResolvedTypeMapping() instanceof LongType ) {
|
||||
// The default is integer.
|
||||
revisionPropType = "long";
|
||||
}
|
||||
else {
|
||||
throw new MappingException(
|
||||
"The field annotated with @RevisionNumber must be of type " +
|
||||
"int, Integer, long or Long"
|
||||
"Field annotated with @RevisionNumber must be of type int, Integer, long or Long."
|
||||
);
|
||||
}
|
||||
|
||||
revisionInfoIdData = new PropertyData(
|
||||
revisionNumberProperty,
|
||||
revisionNumberProperty,
|
||||
revisionNumberAttribute.getPropertyAccessorName(),
|
||||
null
|
||||
);
|
||||
revisionNumberFound.set();
|
||||
|
||||
|
||||
// Getting the @Column definition of the revision number property, to later use that info to
|
||||
// generate the same mapping for the relation from an audit table's revision number to the
|
||||
// revision entity revision number.
|
||||
final Column revisionPropColumn = property.getAnnotation( Column.class );
|
||||
if ( revisionPropColumn != null ) {
|
||||
revisionPropSqlType = revisionPropColumn.columnDefinition();
|
||||
final AnnotationInstance jpaColumnAnnotation = JandexHelper.getSingleAnnotation(
|
||||
JandexHelper.getMemberAnnotations(
|
||||
revisionInfoEntityClassInfo,
|
||||
revisionNumberProperty,
|
||||
context.getServiceRegistry()
|
||||
),
|
||||
JPADotNames.COLUMN
|
||||
);
|
||||
if ( jpaColumnAnnotation != null ) {
|
||||
final ClassLoaderService classLoaderService =
|
||||
context.getServiceRegistry().getService( ClassLoaderService.class );
|
||||
revisionPropSqlType = JandexHelper.getValue(
|
||||
jpaColumnAnnotation,
|
||||
"columnDefinition",
|
||||
String.class,
|
||||
classLoaderService
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if ( revisionTimestamp != null ) {
|
||||
private void searchForRevisionTimestampCfg(
|
||||
ClassInfo revisionInfoEntityClassInfo,
|
||||
EntityBinding revisionInfoEntityBinding,
|
||||
AdditionalJaxbRootProducerContext context,
|
||||
MutableBoolean revisionTimestampFound) {
|
||||
final IndexView jandexIndex = context.getJandexIndex();
|
||||
for ( AnnotationInstance annotation : jandexIndex.getAnnotations( EnversDotNames.REVISION_TIMESTAMP ) ) {
|
||||
AnnotationTarget annotationTarget = annotation.target();
|
||||
if ( !( annotationTarget instanceof FieldInfo || annotationTarget instanceof MethodInfo ) ) {
|
||||
throw new MappingException( "@RevisionTimestamp is applicable only to fields or properties." );
|
||||
}
|
||||
if ( Tools.isFieldOrPropertyOfClass( annotationTarget, revisionInfoEntityClassInfo, jandexIndex ) ) {
|
||||
if ( revisionTimestampFound.isSet() ) {
|
||||
throw new MappingException( "Only one property may be annotated with @RevisionTimestamp!" );
|
||||
throw new MappingException( "Only one property may be annotated with @RevisionTimestamp." );
|
||||
}
|
||||
|
||||
final XClass revisionTimestampClass = property.getType();
|
||||
if ( reflectionManager.equals( revisionTimestampClass, Long.class ) ||
|
||||
reflectionManager.equals( revisionTimestampClass, Long.TYPE ) ||
|
||||
reflectionManager.equals( revisionTimestampClass, Date.class ) ||
|
||||
reflectionManager.equals( revisionTimestampClass, java.sql.Date.class ) ) {
|
||||
final String revisionTimestampProperty = JandexHelper.getPropertyName( annotationTarget );
|
||||
final AttributeBinding revisionTimestampAttribute = revisionInfoEntityBinding.locateAttributeBinding(
|
||||
revisionTimestampProperty
|
||||
);
|
||||
HibernateTypeDescriptor revisionTimestampType = revisionTimestampAttribute.getHibernateTypeDescriptor();
|
||||
final String revisionTimestampClassName = revisionTimestampType.getJavaTypeDescriptor().getName().fullName();
|
||||
if ( Long.TYPE.getName().equals( revisionTimestampClassName ) ||
|
||||
java.util.Date.class.getName().equals( revisionTimestampClassName ) ||
|
||||
Date.class.getName().equals( revisionTimestampClassName) ) {
|
||||
revisionInfoTimestampData = new PropertyData(
|
||||
property.getName(),
|
||||
property.getName(),
|
||||
accessType,
|
||||
revisionTimestampProperty,
|
||||
revisionTimestampProperty,
|
||||
revisionTimestampAttribute.getPropertyAccessorName(),
|
||||
null
|
||||
);
|
||||
revisionTimestampFound.set();
|
||||
}
|
||||
else {
|
||||
throw new MappingException(
|
||||
"The field annotated with @RevisionTimestamp must be of type " +
|
||||
"long, Long, java.util.Date or java.sql.Date"
|
||||
"Field annotated with @RevisionTimestamp must be of type long, Long, java.util.Date or java.sql.Date."
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if ( modifiedEntityNames != null ) {
|
||||
private void searchForModifiedEntityNamesCfg(
|
||||
ClassInfo revisionInfoEntityClassInfo,
|
||||
EntityBinding revisionInfoEntityBinding,
|
||||
AdditionalJaxbRootProducerContext context,
|
||||
MutableBoolean modifiedEntityNamesFound) {
|
||||
final IndexView jandexIndex = context.getJandexIndex();
|
||||
for ( AnnotationInstance annotation : jandexIndex.getAnnotations( EnversDotNames.MODIFIED_ENTITY_NAMES ) ) {
|
||||
AnnotationTarget annotationTarget = annotation.target();
|
||||
if ( !( annotationTarget instanceof FieldInfo || annotationTarget instanceof MethodInfo ) ) {
|
||||
throw new MappingException( "@ModifiedEntityNames is applicable only to fields or properties." );
|
||||
}
|
||||
if ( Tools.isFieldOrPropertyOfClass( annotationTarget, revisionInfoEntityClassInfo, jandexIndex ) ) {
|
||||
if ( modifiedEntityNamesFound.isSet() ) {
|
||||
throw new MappingException( "Only one property may be annotated with @ModifiedEntityNames!" );
|
||||
throw new MappingException( "Only one property may be annotated with @ModifiedEntityNames." );
|
||||
}
|
||||
final XClass modifiedEntityNamesClass = property.getType();
|
||||
if ( reflectionManager.equals( modifiedEntityNamesClass, Set.class ) &&
|
||||
reflectionManager.equals( property.getElementClass(), String.class ) ) {
|
||||
modifiedEntityNamesData = new PropertyData(
|
||||
property.getName(),
|
||||
property.getName(),
|
||||
accessType,
|
||||
null
|
||||
);
|
||||
modifiedEntityNamesFound.set();
|
||||
|
||||
final String modifiedEntityNamesProperty = JandexHelper.getPropertyName( annotationTarget );
|
||||
final AttributeBinding modifiedEntityNamesAttribute = revisionInfoEntityBinding.locateAttributeBinding(
|
||||
modifiedEntityNamesProperty
|
||||
);
|
||||
|
||||
if ( modifiedEntityNamesAttribute instanceof SetBinding ) {
|
||||
final SetBinding collectionBinding = (SetBinding) modifiedEntityNamesAttribute;
|
||||
final String elementType =
|
||||
collectionBinding
|
||||
.getPluralAttributeElementBinding()
|
||||
.getHibernateTypeDescriptor()
|
||||
.getJavaTypeDescriptor().getName().fullName();
|
||||
if ( String.class.getName().equals( elementType ) ) {
|
||||
modifiedEntityNamesData = new PropertyData(
|
||||
modifiedEntityNamesProperty,
|
||||
modifiedEntityNamesProperty,
|
||||
modifiedEntityNamesAttribute.getPropertyAccessorName(),
|
||||
null
|
||||
);
|
||||
modifiedEntityNamesFound.set();
|
||||
}
|
||||
}
|
||||
else {
|
||||
|
||||
if ( !modifiedEntityNamesFound.isSet() ) {
|
||||
throw new MappingException(
|
||||
"The field annotated with @ModifiedEntityNames must be of Set<String> type."
|
||||
"Field annotated with @ModifiedEntityNames must be of Set<String> type."
|
||||
);
|
||||
}
|
||||
}
|
||||
|
@ -287,135 +361,136 @@ public class RevisionInfoConfiguration {
|
|||
}
|
||||
|
||||
private void searchForRevisionInfoCfg(
|
||||
XClass clazz, ReflectionManager reflectionManager,
|
||||
MutableBoolean revisionNumberFound, MutableBoolean revisionTimestampFound,
|
||||
ClassInfo revisionInfoEntityClassInfo,
|
||||
EntityBinding revisionInfoEntityBinding,
|
||||
AdditionalJaxbRootProducerContext context,
|
||||
MutableBoolean revisionNumberFound,
|
||||
MutableBoolean revisionTimestampFound,
|
||||
MutableBoolean modifiedEntityNamesFound) {
|
||||
final XClass superclazz = clazz.getSuperclass();
|
||||
if ( !"java.lang.Object".equals( superclazz.getName() ) ) {
|
||||
searchForRevisionNumberCfg( revisionInfoEntityClassInfo, revisionInfoEntityBinding, context, revisionNumberFound );
|
||||
searchForRevisionTimestampCfg(
|
||||
revisionInfoEntityClassInfo,
|
||||
revisionInfoEntityBinding,
|
||||
context,
|
||||
revisionTimestampFound
|
||||
);
|
||||
searchForModifiedEntityNamesCfg(
|
||||
revisionInfoEntityClassInfo,
|
||||
revisionInfoEntityBinding,
|
||||
context,
|
||||
modifiedEntityNamesFound
|
||||
);
|
||||
}
|
||||
|
||||
public RevisionInfoConfigurationResult configure(
|
||||
InFlightMetadataCollector metadataCollector,
|
||||
AdditionalJaxbRootProducerContext context) {
|
||||
|
||||
final ClassLoaderService classLoaderService = context.getServiceRegistry().getService( ClassLoaderService.class );
|
||||
|
||||
boolean revisionEntityFound = false;
|
||||
RevisionInfoGenerator revisionInfoGenerator = null;
|
||||
Class<?> revisionInfoEntityClass = null;
|
||||
|
||||
// Locate @RevisionEntity provided by user and validate its mapping.
|
||||
Collection<AnnotationInstance> revisionEntityAnnotations = context.getJandexIndex().getAnnotations(
|
||||
EnversDotNames.REVISION_ENTITY
|
||||
);
|
||||
if ( revisionEntityAnnotations.size() > 1 ) {
|
||||
throw new MappingException( "Only one entity may be annotated with @RevisionEntity." );
|
||||
}
|
||||
if ( revisionEntityAnnotations.size() == 1 ) {
|
||||
final AnnotationInstance revisionEntityAnnotation = revisionEntityAnnotations.iterator().next();
|
||||
final ClassInfo revisionInfoEntityClassInfo = (ClassInfo) revisionEntityAnnotation.target();
|
||||
|
||||
// TODO: Get rid of revisionInfoEntityClass (don't want to load the class).
|
||||
revisionInfoEntityClass = classLoaderService.classForName( revisionInfoEntityClassInfo.name().toString() );
|
||||
|
||||
// TODO: get entity name from @Entity
|
||||
revisionInfoEntityName = revisionInfoEntityClass.getName();
|
||||
|
||||
final EntityBinding revisionInfoEntityBinding = metadataCollector.getEntityBinding(
|
||||
revisionInfoEntityName
|
||||
);
|
||||
|
||||
if ( revisionInfoEntityClassInfo.annotations().containsKey( EnversDotNames.AUDITED ) ) {
|
||||
throw new MappingException( "An entity annotated with @RevisionEntity cannot be audited." );
|
||||
}
|
||||
|
||||
MutableBoolean revisionNumberFound = new MutableBoolean();
|
||||
MutableBoolean revisionTimestampFound = new MutableBoolean();
|
||||
MutableBoolean modifiedEntityNamesFound = new MutableBoolean();
|
||||
|
||||
searchForRevisionInfoCfg(
|
||||
superclazz,
|
||||
reflectionManager,
|
||||
revisionInfoEntityClassInfo,
|
||||
revisionInfoEntityBinding,
|
||||
context,
|
||||
revisionNumberFound,
|
||||
revisionTimestampFound,
|
||||
modifiedEntityNamesFound
|
||||
);
|
||||
}
|
||||
|
||||
searchForRevisionInfoCfgInProperties(
|
||||
clazz, reflectionManager, revisionNumberFound, revisionTimestampFound,
|
||||
modifiedEntityNamesFound, "field"
|
||||
);
|
||||
searchForRevisionInfoCfgInProperties(
|
||||
clazz, reflectionManager, revisionNumberFound, revisionTimestampFound,
|
||||
modifiedEntityNamesFound, "property"
|
||||
);
|
||||
}
|
||||
|
||||
public RevisionInfoConfigurationResult configure(Configuration cfg, ReflectionManager reflectionManager) {
|
||||
boolean revisionEntityFound = false;
|
||||
RevisionInfoGenerator revisionInfoGenerator = null;
|
||||
Class<?> revisionInfoClass = null;
|
||||
|
||||
final Iterator<PersistentClass> classes = cfg.getClassMappings();
|
||||
while ( classes.hasNext() ) {
|
||||
PersistentClass pc = classes.next();
|
||||
XClass clazz;
|
||||
try {
|
||||
clazz = reflectionManager.classForName( pc.getClassName(), this.getClass() );
|
||||
}
|
||||
catch (ClassNotFoundException e) {
|
||||
throw new MappingException( e );
|
||||
}
|
||||
|
||||
final RevisionEntity revisionEntity = clazz.getAnnotation( RevisionEntity.class );
|
||||
if ( revisionEntity != null ) {
|
||||
if ( revisionEntityFound ) {
|
||||
throw new MappingException( "Only one entity may be annotated with @RevisionEntity!" );
|
||||
}
|
||||
|
||||
// Checking if custom revision entity isn't audited
|
||||
if ( clazz.getAnnotation( Audited.class ) != null ) {
|
||||
throw new MappingException( "An entity annotated with @RevisionEntity cannot be audited!" );
|
||||
}
|
||||
|
||||
revisionEntityFound = true;
|
||||
|
||||
final MutableBoolean revisionNumberFound = new MutableBoolean();
|
||||
final MutableBoolean revisionTimestampFound = new MutableBoolean();
|
||||
final MutableBoolean modifiedEntityNamesFound = new MutableBoolean();
|
||||
|
||||
searchForRevisionInfoCfg(
|
||||
clazz,
|
||||
reflectionManager,
|
||||
revisionNumberFound,
|
||||
revisionTimestampFound,
|
||||
modifiedEntityNamesFound
|
||||
if ( !revisionNumberFound.isSet() ) {
|
||||
throw new MappingException(
|
||||
"An entity annotated with @RevisionEntity must have a field annotated with @RevisionNumber!"
|
||||
);
|
||||
}
|
||||
|
||||
if ( !revisionNumberFound.isSet() ) {
|
||||
throw new MappingException(
|
||||
"An entity annotated with @RevisionEntity must have a field annotated " +
|
||||
"with @RevisionNumber!"
|
||||
);
|
||||
}
|
||||
if ( !revisionTimestampFound.isSet() ) {
|
||||
throw new MappingException(
|
||||
"An entity annotated with @RevisionEntity must have a field annotated with @RevisionTimestamp!"
|
||||
);
|
||||
}
|
||||
|
||||
if ( !revisionTimestampFound.isSet() ) {
|
||||
throw new MappingException(
|
||||
"An entity annotated with @RevisionEntity must have a field annotated " +
|
||||
"with @RevisionTimestamp!"
|
||||
);
|
||||
}
|
||||
|
||||
revisionInfoEntityName = pc.getEntityName();
|
||||
revisionInfoClass = pc.getMappedClass();
|
||||
final Class<? extends RevisionListener> revisionListenerClass = getRevisionListenerClass( revisionEntity.value() );
|
||||
revisionInfoTimestampType = pc.getProperty( revisionInfoTimestampData.getName() ).getType();
|
||||
if ( globalCfg.isTrackEntitiesChangedInRevision()
|
||||
|| (globalCfg.isUseRevisionEntityWithNativeId() && DefaultTrackingModifiedEntitiesRevisionEntity.class
|
||||
.isAssignableFrom( revisionInfoClass ))
|
||||
|| (!globalCfg.isUseRevisionEntityWithNativeId() && SequenceIdTrackingModifiedEntitiesRevisionEntity.class
|
||||
.isAssignableFrom( revisionInfoClass ))
|
||||
|| modifiedEntityNamesFound.isSet() ) {
|
||||
// If tracking modified entities parameter is enabled, custom revision info entity is a subtype
|
||||
// of DefaultTrackingModifiedEntitiesRevisionEntity class, or @ModifiedEntityNames annotation is used.
|
||||
revisionInfoGenerator = new DefaultTrackingModifiedEntitiesRevisionInfoGenerator(
|
||||
revisionInfoEntityName,
|
||||
revisionInfoClass, revisionListenerClass, revisionInfoTimestampData, isTimestampAsDate(),
|
||||
modifiedEntityNamesData
|
||||
);
|
||||
globalCfg.setTrackEntitiesChangedInRevision( true );
|
||||
}
|
||||
else {
|
||||
revisionInfoGenerator = new DefaultRevisionInfoGenerator(
|
||||
revisionInfoEntityName, revisionInfoClass,
|
||||
revisionListenerClass, revisionInfoTimestampData, isTimestampAsDate()
|
||||
);
|
||||
}
|
||||
Class<? extends RevisionListener> revisionListenerClass = getRevisionListenerClass(
|
||||
classLoaderService,
|
||||
revisionEntityAnnotation
|
||||
);
|
||||
revisionInfoTimestampType =
|
||||
revisionInfoEntityBinding.locateAttributeBinding( revisionInfoTimestampData.getName() )
|
||||
.getHibernateTypeDescriptor()
|
||||
.getResolvedTypeMapping();
|
||||
if ( globalCfg.isTrackEntitiesChangedInRevision()
|
||||
|| ( globalCfg.isUseRevisionEntityWithNativeId() && DefaultTrackingModifiedEntitiesRevisionEntity.class.isAssignableFrom( revisionInfoEntityClass ) )
|
||||
|| ( !globalCfg.isUseRevisionEntityWithNativeId() && SequenceIdTrackingModifiedEntitiesRevisionEntity.class.isAssignableFrom( revisionInfoEntityClass ) )
|
||||
|| modifiedEntityNamesFound.isSet() ) {
|
||||
// If tracking modified entities parameter is enabled, custom revision info entity is a subtype
|
||||
// of DefaultTrackingModifiedEntitiesRevisionEntity class, or @ModifiedEntityNames annotation is used.
|
||||
revisionInfoGenerator = new DefaultTrackingModifiedEntitiesRevisionInfoGenerator(
|
||||
revisionInfoEntityBinding.getEntity().getName(), revisionInfoEntityClass,
|
||||
revisionListenerClass, revisionInfoTimestampData, isTimestampAsDate(), modifiedEntityNamesData
|
||||
);
|
||||
globalCfg.setTrackEntitiesChangedInRevision( true );
|
||||
}
|
||||
else {
|
||||
revisionInfoGenerator = new DefaultRevisionInfoGenerator(
|
||||
revisionInfoEntityBinding.getEntity().getName(), revisionInfoEntityClass,
|
||||
revisionListenerClass, revisionInfoTimestampData, isTimestampAsDate()
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
// In case of a custom revision info generator, the mapping will be null.
|
||||
Document revisionInfoXmlMapping = null;
|
||||
|
||||
final Class<? extends RevisionListener> revisionListenerClass = getRevisionListenerClass( RevisionListener.class );
|
||||
|
||||
if ( revisionInfoGenerator == null ) {
|
||||
final Class<? extends RevisionListener> revisionListenerClass = getRevisionListenerClass( classLoaderService, null );
|
||||
if ( globalCfg.isTrackEntitiesChangedInRevision() ) {
|
||||
revisionInfoClass = globalCfg.isUseRevisionEntityWithNativeId() ?
|
||||
DefaultTrackingModifiedEntitiesRevisionEntity.class
|
||||
:
|
||||
revisionInfoEntityClass = globalCfg.isUseRevisionEntityWithNativeId() ?
|
||||
DefaultTrackingModifiedEntitiesRevisionEntity.class :
|
||||
SequenceIdTrackingModifiedEntitiesRevisionEntity.class;
|
||||
revisionInfoEntityName = revisionInfoClass.getName();
|
||||
revisionInfoEntityName = revisionInfoEntityClass.getName();
|
||||
revisionInfoGenerator = new DefaultTrackingModifiedEntitiesRevisionInfoGenerator(
|
||||
revisionInfoEntityName, revisionInfoClass,
|
||||
revisionInfoEntityName, revisionInfoEntityClass,
|
||||
revisionListenerClass, revisionInfoTimestampData, isTimestampAsDate(), modifiedEntityNamesData
|
||||
);
|
||||
}
|
||||
else {
|
||||
revisionInfoClass = globalCfg.isUseRevisionEntityWithNativeId() ? DefaultRevisionEntity.class
|
||||
: SequenceIdRevisionEntity.class;
|
||||
revisionInfoEntityClass = globalCfg.isUseRevisionEntityWithNativeId() ?
|
||||
DefaultRevisionEntity.class :
|
||||
SequenceIdRevisionEntity.class;
|
||||
revisionInfoGenerator = new DefaultRevisionInfoGenerator(
|
||||
revisionInfoEntityName, revisionInfoClass,
|
||||
revisionInfoEntityName, revisionInfoEntityClass,
|
||||
revisionListenerClass, revisionInfoTimestampData, isTimestampAsDate()
|
||||
);
|
||||
}
|
||||
|
@ -429,13 +504,13 @@ public class RevisionInfoConfiguration {
|
|||
revisionInfoTimestampData.getName(), isTimestampAsDate()
|
||||
),
|
||||
generateRevisionInfoRelationMapping(),
|
||||
new RevisionInfoNumberReader( revisionInfoClass, revisionInfoIdData ),
|
||||
new RevisionInfoNumberReader( revisionInfoEntityClass, revisionInfoIdData ),
|
||||
globalCfg.isTrackEntitiesChangedInRevision() ? new ModifiedEntityNamesReader(
|
||||
revisionInfoClass,
|
||||
revisionInfoEntityClass,
|
||||
modifiedEntityNamesData
|
||||
)
|
||||
: null,
|
||||
revisionInfoEntityName, revisionInfoClass, revisionInfoTimestampData
|
||||
revisionInfoEntityName, revisionInfoEntityClass, revisionInfoTimestampData
|
||||
);
|
||||
}
|
||||
|
||||
|
@ -445,15 +520,21 @@ public class RevisionInfoConfiguration {
|
|||
}
|
||||
|
||||
/**
|
||||
* @param defaultListener Revision listener that shall be applied if {@code org.hibernate.envers.revision_listener}
|
||||
* parameter has not been set.
|
||||
*
|
||||
* Method takes into consideration {@code org.hibernate.envers.revision_listener} parameter and custom
|
||||
* {@link RevisionEntity} annotation.
|
||||
* @param classLoaderService Class loading service.
|
||||
* @param revisionEntityAnnotation User defined @RevisionEntity annotation, or {@code null} if none.
|
||||
* @return Revision listener.
|
||||
*/
|
||||
private Class<? extends RevisionListener> getRevisionListenerClass(Class<? extends RevisionListener> defaultListener) {
|
||||
private Class<? extends RevisionListener> getRevisionListenerClass(ClassLoaderService classLoaderService,
|
||||
AnnotationInstance revisionEntityAnnotation) {
|
||||
if ( globalCfg.getRevisionListenerClass() != null ) {
|
||||
return globalCfg.getRevisionListenerClass();
|
||||
}
|
||||
return defaultListener;
|
||||
if ( revisionEntityAnnotation != null && revisionEntityAnnotation.value() != null ) {
|
||||
// User provided revision listener implementation in @RevisionEntity mapping.
|
||||
return classLoaderService.classForName( revisionEntityAnnotation.value().asString() );
|
||||
}
|
||||
return RevisionListener.class;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -23,18 +23,17 @@
|
|||
*/
|
||||
package org.hibernate.envers.configuration.internal.metadata;
|
||||
|
||||
import java.util.Collections;
|
||||
import java.util.HashMap;
|
||||
import java.util.Iterator;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
import org.hibernate.MappingException;
|
||||
import org.hibernate.boot.registry.classloading.spi.ClassLoaderService;
|
||||
import org.hibernate.cfg.Configuration;
|
||||
import org.hibernate.envers.RelationTargetAuditMode;
|
||||
import org.hibernate.envers.configuration.internal.AuditEntitiesConfiguration;
|
||||
import org.hibernate.envers.configuration.internal.GlobalConfiguration;
|
||||
import org.hibernate.envers.configuration.internal.metadata.reader.ClassAuditingData;
|
||||
import org.hibernate.envers.configuration.internal.metadata.reader.PropertyAuditingData;
|
||||
import org.hibernate.envers.configuration.spi.AuditConfiguration;
|
||||
import org.hibernate.envers.internal.EnversMessageLogger;
|
||||
import org.hibernate.envers.internal.entities.EntityConfiguration;
|
||||
import org.hibernate.envers.internal.entities.IdMappingData;
|
||||
|
@ -46,13 +45,16 @@ import org.hibernate.envers.internal.tools.StringTools;
|
|||
import org.hibernate.envers.internal.tools.Triple;
|
||||
import org.hibernate.envers.strategy.AuditStrategy;
|
||||
import org.hibernate.envers.strategy.ValidityAuditStrategy;
|
||||
import org.hibernate.mapping.Collection;
|
||||
import org.hibernate.mapping.Join;
|
||||
import org.hibernate.mapping.OneToOne;
|
||||
import org.hibernate.mapping.PersistentClass;
|
||||
import org.hibernate.mapping.Property;
|
||||
import org.hibernate.mapping.Table;
|
||||
import org.hibernate.mapping.Value;
|
||||
import org.hibernate.metamodel.spi.binding.AttributeBinding;
|
||||
import org.hibernate.metamodel.spi.binding.CompositeAttributeBinding;
|
||||
import org.hibernate.metamodel.spi.binding.EntityBinding;
|
||||
import org.hibernate.metamodel.spi.binding.EntityDiscriminator;
|
||||
import org.hibernate.metamodel.spi.binding.ManyToOneAttributeBinding;
|
||||
import org.hibernate.metamodel.spi.binding.OneToOneAttributeBinding;
|
||||
import org.hibernate.metamodel.spi.binding.PluralAttributeBinding;
|
||||
import org.hibernate.metamodel.spi.binding.SingularAttributeBinding;
|
||||
import org.hibernate.metamodel.spi.relational.TableSpecification;
|
||||
import org.hibernate.metamodel.spi.relational.Value;
|
||||
import org.hibernate.type.CollectionType;
|
||||
import org.hibernate.type.ComponentType;
|
||||
import org.hibernate.type.ManyToOneType;
|
||||
|
@ -78,12 +80,8 @@ public final class AuditMetadataGenerator {
|
|||
EnversMessageLogger.class,
|
||||
AuditMetadataGenerator.class.getName()
|
||||
);
|
||||
|
||||
private final Configuration cfg;
|
||||
private final GlobalConfiguration globalCfg;
|
||||
private final AuditEntitiesConfiguration verEntCfg;
|
||||
private final AuditConfiguration.AuditConfigurationContext context;
|
||||
private final AuditStrategy auditStrategy;
|
||||
private final ClassLoaderService classLoaderService;
|
||||
private final Element revisionInfoRelationMapping;
|
||||
|
||||
/*
|
||||
|
@ -102,32 +100,31 @@ public final class AuditMetadataGenerator {
|
|||
|
||||
private final AuditEntityNameRegister auditEntityNameRegister;
|
||||
|
||||
// TODO: add support for secondary tables.
|
||||
// Map entity name -> (join descriptor -> element describing the "versioned" join)
|
||||
private final Map<String, Map<Join, Element>> entitiesJoins;
|
||||
//private final Map<String, Map<Join, Element>> entitiesJoins;
|
||||
|
||||
public AuditMetadataGenerator(
|
||||
Configuration cfg, GlobalConfiguration globalCfg,
|
||||
AuditEntitiesConfiguration verEntCfg,
|
||||
AuditStrategy auditStrategy, ClassLoaderService classLoaderService,
|
||||
AuditConfiguration.AuditConfigurationContext context,
|
||||
AuditStrategy auditStrategy,
|
||||
Element revisionInfoRelationMapping,
|
||||
AuditEntityNameRegister auditEntityNameRegister) {
|
||||
this.cfg = cfg;
|
||||
this.globalCfg = globalCfg;
|
||||
this.verEntCfg = verEntCfg;
|
||||
this.context = context;
|
||||
this.auditStrategy = auditStrategy;
|
||||
this.classLoaderService = classLoaderService;
|
||||
this.revisionInfoRelationMapping = revisionInfoRelationMapping;
|
||||
|
||||
this.basicMetadataGenerator = new BasicMetadataGenerator();
|
||||
this.componentMetadataGenerator = new ComponentMetadataGenerator( this );
|
||||
this.idMetadataGenerator = new IdMetadataGenerator( this );
|
||||
this.componentMetadataGenerator = new ComponentMetadataGenerator( context, this );
|
||||
this.idMetadataGenerator = new IdMetadataGenerator( context, this );
|
||||
this.toOneRelationMetadataGenerator = new ToOneRelationMetadataGenerator( this );
|
||||
|
||||
this.auditEntityNameRegister = auditEntityNameRegister;
|
||||
|
||||
entitiesConfigurations = new HashMap<String, EntityConfiguration>();
|
||||
notAuditedEntitiesConfigurations = new HashMap<String, EntityConfiguration>();
|
||||
entitiesJoins = new HashMap<String, Map<Join, Element>>();
|
||||
|
||||
// TODO: add support for secondary tables.
|
||||
//entitiesJoins = new HashMap<String, Map<SecondaryTable, Element>>();
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -138,12 +135,12 @@ public final class AuditMetadataGenerator {
|
|||
*/
|
||||
private Element cloneAndSetupRevisionInfoRelationMapping() {
|
||||
final Element revMapping = (Element) revisionInfoRelationMapping.clone();
|
||||
revMapping.addAttribute( "name", verEntCfg.getRevisionFieldName() );
|
||||
if ( globalCfg.isCascadeDeleteRevision() ) {
|
||||
revMapping.addAttribute( "name", context.getAuditEntitiesConfiguration().getRevisionFieldName() );
|
||||
if ( context.getGlobalConfiguration().isCascadeDeleteRevision() ) {
|
||||
revMapping.addAttribute( "on-delete", "cascade" );
|
||||
}
|
||||
|
||||
MetadataTools.addOrModifyColumn( revMapping, verEntCfg.getRevisionFieldName() );
|
||||
MetadataTools.addOrModifyColumn( revMapping, context.getAuditEntitiesConfiguration().getRevisionFieldName() );
|
||||
|
||||
return revMapping;
|
||||
}
|
||||
|
@ -152,13 +149,13 @@ public final class AuditMetadataGenerator {
|
|||
anyMapping.add( cloneAndSetupRevisionInfoRelationMapping() );
|
||||
}
|
||||
|
||||
void addRevisionType(Element anyMapping, Element anyMappingEnd) {
|
||||
void addRevisionType(Element anyMapping, Element anyMappingEnd, boolean key) {
|
||||
final Element revTypeProperty = MetadataTools.addProperty(
|
||||
anyMapping,
|
||||
verEntCfg.getRevisionTypePropName(),
|
||||
verEntCfg.getRevisionTypePropType(),
|
||||
context.getAuditEntitiesConfiguration().getRevisionTypePropName(),
|
||||
context.getAuditEntitiesConfiguration().getRevisionTypePropType(),
|
||||
true,
|
||||
false
|
||||
key
|
||||
);
|
||||
revTypeProperty.addAttribute( "type", "org.hibernate.envers.internal.entities.RevisionTypeType" );
|
||||
|
||||
|
@ -171,17 +168,17 @@ public final class AuditMetadataGenerator {
|
|||
if ( auditStrategy instanceof ValidityAuditStrategy ) {
|
||||
final Element endRevMapping = (Element) revisionInfoRelationMapping.clone();
|
||||
endRevMapping.setName( "many-to-one" );
|
||||
endRevMapping.addAttribute( "name", verEntCfg.getRevisionEndFieldName() );
|
||||
MetadataTools.addOrModifyColumn( endRevMapping, verEntCfg.getRevisionEndFieldName() );
|
||||
endRevMapping.addAttribute( "name", context.getAuditEntitiesConfiguration().getRevisionEndFieldName() );
|
||||
MetadataTools.addOrModifyColumn( endRevMapping, context.getAuditEntitiesConfiguration().getRevisionEndFieldName() );
|
||||
|
||||
anyMapping.add( endRevMapping );
|
||||
|
||||
if ( verEntCfg.isRevisionEndTimestampEnabled() ) {
|
||||
if ( context.getAuditEntitiesConfiguration().isRevisionEndTimestampEnabled() ) {
|
||||
// add a column for the timestamp of the end revision
|
||||
final String revisionInfoTimestampSqlType = TimestampType.INSTANCE.getName();
|
||||
final Element timestampProperty = MetadataTools.addProperty(
|
||||
anyMapping,
|
||||
verEntCfg.getRevisionEndTimestampFieldName(),
|
||||
context.getAuditEntitiesConfiguration().getRevisionEndTimestampFieldName(),
|
||||
revisionInfoTimestampSqlType,
|
||||
true,
|
||||
true,
|
||||
|
@ -189,7 +186,7 @@ public final class AuditMetadataGenerator {
|
|||
);
|
||||
MetadataTools.addColumn(
|
||||
timestampProperty,
|
||||
verEntCfg.getRevisionEndTimestampFieldName(),
|
||||
context.getAuditEntitiesConfiguration().getRevisionEndTimestampFieldName(),
|
||||
null,
|
||||
null,
|
||||
null,
|
||||
|
@ -203,20 +200,33 @@ public final class AuditMetadataGenerator {
|
|||
|
||||
private void addValueInFirstPass(
|
||||
Element parent,
|
||||
Value value,
|
||||
AttributeBinding attributeBinding,
|
||||
CompositeMapperBuilder currentMapper,
|
||||
String entityName,
|
||||
EntityXmlMappingData xmlMappingData,
|
||||
PropertyAuditingData propertyAuditingData,
|
||||
boolean insertable,
|
||||
boolean processModifiedFlag) {
|
||||
final Type type = value.getType();
|
||||
final Type type = attributeBinding.getHibernateTypeDescriptor().getResolvedTypeMapping();
|
||||
|
||||
final List<Value> values;
|
||||
final boolean isInsertable;
|
||||
if ( attributeBinding.getAttribute().isSingular() ) {
|
||||
final SingularAttributeBinding singularAttributeBinding = (SingularAttributeBinding) attributeBinding;
|
||||
values = singularAttributeBinding.getValues();
|
||||
isInsertable = singularAttributeBinding.isIncludedInInsert();
|
||||
}
|
||||
else {
|
||||
values = null;
|
||||
isInsertable = false;
|
||||
}
|
||||
|
||||
final boolean isBasic = basicMetadataGenerator.addBasic(
|
||||
parent,
|
||||
propertyAuditingData,
|
||||
value,
|
||||
attributeBinding.getHibernateTypeDescriptor(),
|
||||
values,
|
||||
isInsertable,
|
||||
currentMapper,
|
||||
insertable,
|
||||
false
|
||||
);
|
||||
|
||||
|
@ -225,8 +235,13 @@ public final class AuditMetadataGenerator {
|
|||
}
|
||||
else if ( type instanceof ComponentType ) {
|
||||
componentMetadataGenerator.addComponent(
|
||||
parent, propertyAuditingData, value, currentMapper,
|
||||
entityName, xmlMappingData, true
|
||||
parent,
|
||||
propertyAuditingData,
|
||||
(CompositeAttributeBinding) attributeBinding,
|
||||
currentMapper,
|
||||
entityName,
|
||||
xmlMappingData,
|
||||
true
|
||||
);
|
||||
}
|
||||
else {
|
||||
|
@ -247,20 +262,19 @@ public final class AuditMetadataGenerator {
|
|||
|
||||
private void addValueInSecondPass(
|
||||
Element parent,
|
||||
Value value,
|
||||
AttributeBinding attributeBinding,
|
||||
CompositeMapperBuilder currentMapper,
|
||||
String entityName,
|
||||
EntityXmlMappingData xmlMappingData,
|
||||
PropertyAuditingData propertyAuditingData,
|
||||
boolean insertable,
|
||||
boolean processModifiedFlag) {
|
||||
final Type type = value.getType();
|
||||
final Type type = attributeBinding.getHibernateTypeDescriptor().getResolvedTypeMapping();
|
||||
|
||||
if ( type instanceof ComponentType ) {
|
||||
componentMetadataGenerator.addComponent(
|
||||
parent,
|
||||
propertyAuditingData,
|
||||
value,
|
||||
(CompositeAttributeBinding) attributeBinding,
|
||||
currentMapper,
|
||||
entityName,
|
||||
xmlMappingData,
|
||||
|
@ -273,18 +287,17 @@ public final class AuditMetadataGenerator {
|
|||
toOneRelationMetadataGenerator.addToOne(
|
||||
parent,
|
||||
propertyAuditingData,
|
||||
value,
|
||||
(ManyToOneAttributeBinding) attributeBinding,
|
||||
currentMapper,
|
||||
entityName,
|
||||
insertable
|
||||
entityName
|
||||
);
|
||||
}
|
||||
else if ( type instanceof OneToOneType ) {
|
||||
final OneToOne oneToOne = (OneToOne) value;
|
||||
if ( oneToOne.getReferencedPropertyName() != null ) {
|
||||
final OneToOneAttributeBinding oneToOneAttributeBinding = (OneToOneAttributeBinding) attributeBinding;
|
||||
if ( oneToOneAttributeBinding.getReferencedAttributeBinding().getAttribute().getName() != null ) {
|
||||
toOneRelationMetadataGenerator.addOneToOneNotOwning(
|
||||
propertyAuditingData,
|
||||
value,
|
||||
oneToOneAttributeBinding,
|
||||
currentMapper,
|
||||
entityName
|
||||
);
|
||||
|
@ -293,17 +306,17 @@ public final class AuditMetadataGenerator {
|
|||
// @OneToOne relation marked with @PrimaryKeyJoinColumn
|
||||
toOneRelationMetadataGenerator.addOneToOnePrimaryKeyJoinColumn(
|
||||
propertyAuditingData,
|
||||
value,
|
||||
oneToOneAttributeBinding,
|
||||
currentMapper,
|
||||
entityName,
|
||||
insertable
|
||||
entityName
|
||||
);
|
||||
}
|
||||
}
|
||||
else if ( type instanceof CollectionType ) {
|
||||
final CollectionMetadataGenerator collectionMetadataGenerator = new CollectionMetadataGenerator(
|
||||
context,
|
||||
this,
|
||||
(Collection) value,
|
||||
(PluralAttributeBinding) attributeBinding,
|
||||
currentMapper,
|
||||
entityName,
|
||||
xmlMappingData,
|
||||
|
@ -325,50 +338,53 @@ public final class AuditMetadataGenerator {
|
|||
MetadataTools.addModifiedFlagProperty(
|
||||
parent,
|
||||
propertyAuditingData.getName(),
|
||||
globalCfg.getModifiedFlagSuffix()
|
||||
context.getGlobalConfiguration().getModifiedFlagSuffix()
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
void addValue(
|
||||
Element parent, Value value, CompositeMapperBuilder currentMapper, String entityName,
|
||||
EntityXmlMappingData xmlMappingData, PropertyAuditingData propertyAuditingData,
|
||||
boolean insertable, boolean firstPass, boolean processModifiedFlag) {
|
||||
Element parent,
|
||||
AttributeBinding attributeBinding,
|
||||
CompositeMapperBuilder currentMapper,
|
||||
String entityName,
|
||||
EntityXmlMappingData xmlMappingData,
|
||||
PropertyAuditingData propertyAuditingData,
|
||||
boolean firstPass,
|
||||
boolean processModifiedFlag) {
|
||||
if ( firstPass ) {
|
||||
addValueInFirstPass(
|
||||
parent, value, currentMapper, entityName,
|
||||
xmlMappingData, propertyAuditingData, insertable, processModifiedFlag
|
||||
parent, attributeBinding, currentMapper, entityName,
|
||||
xmlMappingData, propertyAuditingData, processModifiedFlag
|
||||
);
|
||||
}
|
||||
else {
|
||||
addValueInSecondPass(
|
||||
parent, value, currentMapper, entityName,
|
||||
xmlMappingData, propertyAuditingData, insertable, processModifiedFlag
|
||||
parent, attributeBinding, currentMapper, entityName,
|
||||
xmlMappingData, propertyAuditingData, processModifiedFlag
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
private void addProperties(
|
||||
Element parent,
|
||||
Iterator<Property> properties,
|
||||
AttributeBinding[] properties,
|
||||
CompositeMapperBuilder currentMapper,
|
||||
ClassAuditingData auditingData,
|
||||
String entityName,
|
||||
EntityXmlMappingData xmlMappingData,
|
||||
boolean firstPass) {
|
||||
while ( properties.hasNext() ) {
|
||||
final Property property = properties.next();
|
||||
final String propertyName = property.getName();
|
||||
for ( AttributeBinding property : properties ) {
|
||||
final String propertyName = property.getAttribute().getName();
|
||||
final PropertyAuditingData propertyAuditingData = auditingData.getPropertyAuditingData( propertyName );
|
||||
if ( propertyAuditingData != null ) {
|
||||
addValue(
|
||||
parent,
|
||||
property.getValue(),
|
||||
property,
|
||||
currentMapper,
|
||||
entityName,
|
||||
xmlMappingData,
|
||||
propertyAuditingData,
|
||||
property.isInsertable(),
|
||||
firstPass,
|
||||
true
|
||||
);
|
||||
|
@ -376,10 +392,10 @@ public final class AuditMetadataGenerator {
|
|||
}
|
||||
}
|
||||
|
||||
private boolean checkPropertiesAudited(Iterator<Property> properties, ClassAuditingData auditingData) {
|
||||
private boolean checkPropertiesAudited(Iterator<AttributeBinding> properties, ClassAuditingData auditingData) {
|
||||
while ( properties.hasNext() ) {
|
||||
final Property property = properties.next();
|
||||
final String propertyName = property.getName();
|
||||
final AttributeBinding property = properties.next();
|
||||
final String propertyName = property.getAttribute().getName();
|
||||
final PropertyAuditingData propertyAuditingData = auditingData.getPropertyAuditingData( propertyName );
|
||||
if ( propertyAuditingData == null ) {
|
||||
return false;
|
||||
|
@ -389,151 +405,193 @@ public final class AuditMetadataGenerator {
|
|||
return true;
|
||||
}
|
||||
|
||||
protected String getSchema(String schemaFromAnnotation, Table table) {
|
||||
protected String getSchema(String schemaFromAnnotation, TableSpecification table) {
|
||||
// Get the schema from the annotation ...
|
||||
String schema = schemaFromAnnotation;
|
||||
// ... if empty, try using the default ...
|
||||
if ( StringTools.isEmpty( schema ) ) {
|
||||
schema = globalCfg.getDefaultSchemaName();
|
||||
schema = context.getGlobalConfiguration().getDefaultSchemaName();
|
||||
|
||||
// ... if still empty, use the same as the normal table.
|
||||
if ( StringTools.isEmpty( schema ) ) {
|
||||
schema = table.getSchema();
|
||||
if ( StringTools.isEmpty( schema ) && table.getSchema().getName().getSchema() != null) {
|
||||
schema = table.getSchema().getName().getSchema().getText();
|
||||
}
|
||||
}
|
||||
|
||||
return schema;
|
||||
}
|
||||
|
||||
protected String getCatalog(String catalogFromAnnotation, Table table) {
|
||||
protected String getCatalog(String catalogFromAnnotation, TableSpecification table) {
|
||||
// Get the catalog from the annotation ...
|
||||
String catalog = catalogFromAnnotation;
|
||||
// ... if empty, try using the default ...
|
||||
if ( StringTools.isEmpty( catalog ) ) {
|
||||
catalog = globalCfg.getDefaultCatalogName();
|
||||
catalog = context.getGlobalConfiguration().getDefaultCatalogName();
|
||||
|
||||
// ... if still empty, use the same as the normal table.
|
||||
if ( StringTools.isEmpty( catalog ) ) {
|
||||
catalog = table.getCatalog();
|
||||
if ( StringTools.isEmpty( catalog ) && table.getSchema().getName().getCatalog() != null ) {
|
||||
catalog = table.getSchema().getName().getCatalog().getText();
|
||||
}
|
||||
}
|
||||
|
||||
return catalog;
|
||||
}
|
||||
|
||||
@SuppressWarnings({"unchecked"})
|
||||
private void createJoins(PersistentClass pc, Element parent, ClassAuditingData auditingData) {
|
||||
final Iterator<Join> joins = pc.getJoinIterator();
|
||||
final Map<Join, Element> joinElements = new HashMap<Join, Element>();
|
||||
entitiesJoins.put( pc.getEntityName(), joinElements );
|
||||
// TODO: add support for secondary tables
|
||||
// private void createJoins(EntityBinding entityBinding, Element parent, ClassAuditingData auditingData) {
|
||||
// final Iterator<SecondaryTable> joins = entityBinding.getSecondaryTables();
|
||||
// final Map<SecondaryTable, Element> joinElements = new HashMap<SecondaryTable, Element>();
|
||||
// entitiesJoins.put( entityBinding.getEntityName(), joinElements );
|
||||
|
||||
while ( joins.hasNext() ) {
|
||||
Join join = joins.next();
|
||||
// while ( joins.hasNext() ) {
|
||||
// SecondaryTable join = joins.next();
|
||||
|
||||
// Checking if all of the join properties are audited
|
||||
if ( !checkPropertiesAudited( join.getPropertyIterator(), auditingData ) ) {
|
||||
continue;
|
||||
}
|
||||
// if ( !checkPropertiesAudited( join.getPropertyIterator(), auditingData ) ) {
|
||||
// continue;
|
||||
// }
|
||||
|
||||
// Determining the table name. If there is no entry in the dictionary, just constructing the table name
|
||||
// as if it was an entity (by appending/prepending configured strings).
|
||||
final String originalTableName = join.getTable().getName();
|
||||
String auditTableName = auditingData.getSecondaryTableDictionary().get( originalTableName );
|
||||
if ( auditTableName == null ) {
|
||||
auditTableName = verEntCfg.getAuditEntityName( originalTableName );
|
||||
}
|
||||
// final String originalTableName = join.getSecondaryTableReference().getLogicalName().getText();
|
||||
// String auditTableName = auditingData.getSecondaryTableDictionary().get( originalTableName );
|
||||
// if ( auditTableName == null ) {
|
||||
// auditTableName = context.getAuditEntitiesConfiguration().getAuditEntityName( originalTableName );
|
||||
// }
|
||||
|
||||
final String schema = getSchema( auditingData.getAuditTable().schema(), join.getTable() );
|
||||
final String catalog = getCatalog( auditingData.getAuditTable().catalog(), join.getTable() );
|
||||
// final String schema = getSchema( auditingData.getAuditTable().schema(), join.getSecondaryTableReference() );
|
||||
// final String catalog = getCatalog( auditingData.getAuditTable().catalog(), join.getSecondaryTableReference() );
|
||||
|
||||
final Element joinElement = MetadataTools.createJoin( parent, auditTableName, schema, catalog );
|
||||
joinElements.put( join, joinElement );
|
||||
// final Element joinElement = MetadataTools.createJoin( parent, auditTableName, schema, catalog );
|
||||
// joinElements.put( join, joinElement );
|
||||
|
||||
final Element joinKey = joinElement.addElement( "key" );
|
||||
MetadataTools.addColumns( joinKey, join.getKey().getColumnIterator() );
|
||||
MetadataTools.addColumn( joinKey, verEntCfg.getRevisionFieldName(), null, null, null, null, null, null );
|
||||
}
|
||||
}
|
||||
// final Element joinKey = joinElement.addElement( "key" );
|
||||
// MetadataTools.addColumns( joinKey, join.getForeignKeyReference().getColumns() );
|
||||
// MetadataTools.addColumn( joinKey, context.getAuditEntitiesConfiguration().getRevisionFieldName(), null, null, null, null, null, null );
|
||||
// }
|
||||
// }
|
||||
|
||||
@SuppressWarnings({"unchecked"})
|
||||
private void addJoins(
|
||||
PersistentClass pc,
|
||||
CompositeMapperBuilder currentMapper,
|
||||
ClassAuditingData auditingData,
|
||||
String entityName,
|
||||
EntityXmlMappingData xmlMappingData,
|
||||
boolean firstPass) {
|
||||
final Iterator<Join> joins = pc.getJoinIterator();
|
||||
// @SuppressWarnings({"unchecked"})
|
||||
// private void createJoins(PersistentClass pc, Element parent, ClassAuditingData auditingData) {
|
||||
// final Iterator<Join> joins = pc.getJoinIterator();
|
||||
// final Map<Join, Element> joinElements = new HashMap<Join, Element>();
|
||||
// entitiesJoins.put( pc.getEntityName(), joinElements );
|
||||
//
|
||||
// while ( joins.hasNext() ) {
|
||||
// Join join = joins.next();
|
||||
|
||||
while ( joins.hasNext() ) {
|
||||
final Join join = joins.next();
|
||||
final Element joinElement = entitiesJoins.get( entityName ).get( join );
|
||||
// Checking if all of the join properties are audited
|
||||
// if ( !checkPropertiesAudited( join.getPropertyIterator(), auditingData ) ) {
|
||||
// continue;
|
||||
// }
|
||||
|
||||
if ( joinElement != null ) {
|
||||
addProperties(
|
||||
joinElement,
|
||||
join.getPropertyIterator(),
|
||||
currentMapper,
|
||||
auditingData,
|
||||
entityName,
|
||||
xmlMappingData,
|
||||
firstPass
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
// Determining the table name. If there is no entry in the dictionary, just constructing the table name
|
||||
// as if it was an entity (by appending/prepending configured strings).
|
||||
// final String originalTableName = join.getTable().getName();
|
||||
// String auditTableName = auditingData.getSecondaryTableDictionary().get( originalTableName );
|
||||
// if ( auditTableName == null ) {
|
||||
// auditTableName = verEntCfg.getAuditEntityName( originalTableName );
|
||||
// }
|
||||
|
||||
// final String schema = getSchema( auditingData.getAuditTable().schema(), join.getTable() );
|
||||
// final String catalog = getCatalog( auditingData.getAuditTable().catalog(), join.getTable() );
|
||||
|
||||
// final Element joinElement = MetadataTools.createJoin( parent, auditTableName, schema, catalog );
|
||||
// joinElements.put( join, joinElement );
|
||||
|
||||
// final Element joinKey = joinElement.addElement( "key" );
|
||||
// MetadataTools.addColumns( joinKey, join.getKey().getColumnIterator() );
|
||||
// MetadataTools.addColumn( joinKey, verEntCfg.getRevisionFieldName(), null, null, null, null, null, null );
|
||||
// }
|
||||
// }
|
||||
|
||||
// @SuppressWarnings({"unchecked"})
|
||||
// private void addJoins(
|
||||
// PersistentClass pc,
|
||||
// CompositeMapperBuilder currentMapper,
|
||||
// ClassAuditingData auditingData,
|
||||
// String entityName,
|
||||
// EntityXmlMappingData xmlMappingData,
|
||||
// boolean firstPass) {
|
||||
// final Iterator<Join> joins = pc.getJoinIterator();
|
||||
|
||||
// while ( joins.hasNext() ) {
|
||||
// final Join join = joins.next();
|
||||
// final Element joinElement = entitiesJoins.get( entityName ).get( join );
|
||||
|
||||
// if ( joinElement != null ) {
|
||||
// addProperties(
|
||||
// joinElement,
|
||||
// join.getPropertyIterator(),
|
||||
// currentMapper,
|
||||
// auditingData,
|
||||
// entityName,
|
||||
// xmlMappingData,
|
||||
// firstPass
|
||||
// );
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
|
||||
@SuppressWarnings({"unchecked"})
|
||||
private Triple<Element, ExtendedPropertyMapper, String> generateMappingData(
|
||||
PersistentClass pc, EntityXmlMappingData xmlMappingData, AuditTableData auditTableData,
|
||||
EntityBinding entityBinding, EntityXmlMappingData xmlMappingData, AuditTableData auditTableData,
|
||||
IdMappingData idMapper) {
|
||||
final Element classMapping = MetadataTools.createEntity(
|
||||
xmlMappingData.getMainXmlMapping(),
|
||||
auditTableData,
|
||||
pc.getDiscriminatorValue(),
|
||||
pc.isAbstract()
|
||||
entityBinding.getDiscriminatorMatchValue(),
|
||||
entityBinding.isAbstract()
|
||||
);
|
||||
final ExtendedPropertyMapper propertyMapper = new MultiPropertyMapper();
|
||||
|
||||
// Checking if there is a discriminator column
|
||||
if ( pc.getDiscriminator() != null ) {
|
||||
final Element discriminatorElement = classMapping.addElement( "discriminator" );
|
||||
// Database column or SQL formula allowed to distinguish entity types
|
||||
MetadataTools.addColumnsOrFormulas( discriminatorElement, pc.getDiscriminator().getColumnIterator() );
|
||||
discriminatorElement.addAttribute( "type", pc.getDiscriminator().getType().getName() );
|
||||
}
|
||||
|
||||
// Adding the id mapping
|
||||
classMapping.add( (Element) idMapper.getXmlMapping().clone() );
|
||||
|
||||
// Checking if there is a discriminator column
|
||||
if ( entityBinding.getHierarchyDetails().getEntityDiscriminator() != null ) {
|
||||
final EntityDiscriminator discriminator = entityBinding.getHierarchyDetails().getEntityDiscriminator();
|
||||
final Element discriminatorElement = classMapping.addElement( "discriminator" );
|
||||
// Database column or SQL formula allowed to distinguish entity types
|
||||
MetadataTools.addColumnsOrFormulas(
|
||||
discriminatorElement,
|
||||
Collections.singletonList( discriminator.getRelationalValue() )
|
||||
);
|
||||
discriminatorElement.addAttribute(
|
||||
"type",
|
||||
discriminator.getExplicitHibernateTypeDescriptor().getExplicitTypeName()
|
||||
);
|
||||
}
|
||||
|
||||
// Adding the "revision type" property
|
||||
addRevisionType( classMapping, classMapping );
|
||||
addRevisionType( classMapping, classMapping, false );
|
||||
|
||||
return Triple.make( classMapping, propertyMapper, null );
|
||||
}
|
||||
|
||||
private Triple<Element, ExtendedPropertyMapper, String> generateInheritanceMappingData(
|
||||
PersistentClass pc, EntityXmlMappingData xmlMappingData, AuditTableData auditTableData,
|
||||
EntityBinding entityBinding,
|
||||
EntityXmlMappingData xmlMappingData,
|
||||
AuditTableData auditTableData,
|
||||
String inheritanceMappingType) {
|
||||
final String extendsEntityName = verEntCfg.getAuditEntityName( pc.getSuperclass().getEntityName() );
|
||||
final String parentEntityName = entityBinding.getSuperEntityBinding().getEntityName();
|
||||
final String extendsEntityName = context.getAuditEntitiesConfiguration().getAuditEntityName( parentEntityName );
|
||||
final Element classMapping = MetadataTools.createSubclassEntity(
|
||||
xmlMappingData.getMainXmlMapping(),
|
||||
inheritanceMappingType,
|
||||
auditTableData,
|
||||
extendsEntityName,
|
||||
pc.getDiscriminatorValue(),
|
||||
pc.isAbstract()
|
||||
entityBinding.getDiscriminatorMatchValue(),
|
||||
entityBinding.isAbstract()
|
||||
);
|
||||
|
||||
// The id and revision type is already mapped in the parent
|
||||
|
||||
// Getting the property mapper of the parent - when mapping properties, they need to be included
|
||||
final String parentEntityName = pc.getSuperclass().getEntityName();
|
||||
|
||||
final EntityConfiguration parentConfiguration = entitiesConfigurations.get( parentEntityName );
|
||||
if ( parentConfiguration == null ) {
|
||||
throw new MappingException(
|
||||
"Entity '" + pc.getEntityName() + "' is audited, but its superclass: '" +
|
||||
"Entity '" + entityBinding.getEntityName() + "' is audited, but its superclass: '" +
|
||||
parentEntityName + "' is not."
|
||||
);
|
||||
}
|
||||
|
@ -549,16 +607,16 @@ public final class AuditMetadataGenerator {
|
|||
|
||||
@SuppressWarnings({"unchecked"})
|
||||
public void generateFirstPass(
|
||||
PersistentClass pc,
|
||||
EntityBinding entityBinding,
|
||||
ClassAuditingData auditingData,
|
||||
EntityXmlMappingData xmlMappingData,
|
||||
boolean isAudited) {
|
||||
final String schema = getSchema( auditingData.getAuditTable().schema(), pc.getTable() );
|
||||
final String catalog = getCatalog( auditingData.getAuditTable().catalog(), pc.getTable() );
|
||||
final String schema = getSchema( auditingData.getAuditTable().schema(), entityBinding.getPrimaryTable() );
|
||||
final String catalog = getCatalog( auditingData.getAuditTable().catalog(), entityBinding.getPrimaryTable() );
|
||||
|
||||
if ( !isAudited ) {
|
||||
final String entityName = pc.getEntityName();
|
||||
final IdMappingData idMapper = idMetadataGenerator.addId( pc, false );
|
||||
final String entityName = entityBinding.getEntityName();
|
||||
final IdMappingData idMapper = idMetadataGenerator.addId( entityBinding, false );
|
||||
|
||||
if ( idMapper == null ) {
|
||||
// Unsupported id mapping, e.g. key-many-to-one. If the entity is used in auditing, an exception
|
||||
|
@ -574,7 +632,7 @@ public final class AuditMetadataGenerator {
|
|||
final String parentEntityName = null;
|
||||
final EntityConfiguration entityCfg = new EntityConfiguration(
|
||||
entityName,
|
||||
pc.getClassName(),
|
||||
entityBinding.getEntity().getDescriptor().getName().fullName(),
|
||||
idMapper,
|
||||
propertyMapper,
|
||||
parentEntityName
|
||||
|
@ -583,11 +641,14 @@ public final class AuditMetadataGenerator {
|
|||
return;
|
||||
}
|
||||
|
||||
final String entityName = pc.getEntityName();
|
||||
final String entityName = entityBinding.getEntityName();
|
||||
LOG.debugf( "Generating first-pass auditing mapping for entity %s", entityName );
|
||||
|
||||
final String auditEntityName = verEntCfg.getAuditEntityName( entityName );
|
||||
final String auditTableName = verEntCfg.getAuditTableName( entityName, pc.getTable().getName() );
|
||||
final String auditEntityName = context.getAuditEntitiesConfiguration().getAuditEntityName( entityName );
|
||||
final String auditTableName = context.getAuditEntitiesConfiguration().getAuditTableName(
|
||||
entityName,
|
||||
entityBinding.getPrimaryTableName()
|
||||
);
|
||||
|
||||
// Registering the audit entity name, now that it is known
|
||||
auditEntityNameRegister.register( auditEntityName );
|
||||
|
@ -595,9 +656,9 @@ public final class AuditMetadataGenerator {
|
|||
final AuditTableData auditTableData = new AuditTableData( auditEntityName, auditTableName, schema, catalog );
|
||||
|
||||
// Generating a mapping for the id
|
||||
final IdMappingData idMapper = idMetadataGenerator.addId( pc, true );
|
||||
final IdMappingData idMapper = idMetadataGenerator.addId( entityBinding, true );
|
||||
|
||||
final InheritanceType inheritanceType = InheritanceType.get( pc );
|
||||
final InheritanceType inheritanceType = InheritanceType.get( entityBinding );
|
||||
|
||||
// These properties will be read from the mapping data
|
||||
final Element classMapping;
|
||||
|
@ -609,26 +670,26 @@ public final class AuditMetadataGenerator {
|
|||
// Reading the mapping data depending on inheritance type (if any)
|
||||
switch ( inheritanceType ) {
|
||||
case NONE:
|
||||
mappingData = generateMappingData( pc, xmlMappingData, auditTableData, idMapper );
|
||||
mappingData = generateMappingData( entityBinding, xmlMappingData, auditTableData, idMapper );
|
||||
break;
|
||||
|
||||
case SINGLE:
|
||||
mappingData = generateInheritanceMappingData( pc, xmlMappingData, auditTableData, "subclass" );
|
||||
mappingData = generateInheritanceMappingData( entityBinding, xmlMappingData, auditTableData, "subclass" );
|
||||
break;
|
||||
|
||||
case JOINED:
|
||||
mappingData = generateInheritanceMappingData( pc, xmlMappingData, auditTableData, "joined-subclass" );
|
||||
mappingData = generateInheritanceMappingData( entityBinding, xmlMappingData, auditTableData, "joined-subclass" );
|
||||
|
||||
// Adding the "key" element with all id columns...
|
||||
final Element keyMapping = mappingData.getFirst().addElement( "key" );
|
||||
MetadataTools.addColumns( keyMapping, pc.getTable().getPrimaryKey().columnIterator() );
|
||||
MetadataTools.addColumns( keyMapping, entityBinding.getPrimaryTable().getPrimaryKey().getColumns() );
|
||||
|
||||
// ... and the revision number column, read from the revision info relation mapping.
|
||||
keyMapping.add( (Element) cloneAndSetupRevisionInfoRelationMapping().element( "column" ).clone() );
|
||||
break;
|
||||
|
||||
case TABLE_PER_CLASS:
|
||||
mappingData = generateInheritanceMappingData( pc, xmlMappingData, auditTableData, "union-subclass" );
|
||||
mappingData = generateInheritanceMappingData( entityBinding, xmlMappingData, auditTableData, "union-subclass" );
|
||||
break;
|
||||
|
||||
default:
|
||||
|
@ -643,32 +704,38 @@ public final class AuditMetadataGenerator {
|
|||
|
||||
// Mapping unjoined properties
|
||||
addProperties(
|
||||
classMapping, pc.getUnjoinedPropertyIterator(), propertyMapper,
|
||||
auditingData, pc.getEntityName(), xmlMappingData,
|
||||
classMapping,
|
||||
entityBinding.getNonIdAttributeBindingClosure(), // TODO: this needs to be corrected to only get non-joined attribute bindings.
|
||||
//entityBinding.getUnjoinedPropertyIterator(),
|
||||
propertyMapper,
|
||||
auditingData,
|
||||
entityBinding.getEntityName(),
|
||||
xmlMappingData,
|
||||
true
|
||||
);
|
||||
|
||||
// TODO: add support for joins
|
||||
// Creating and mapping joins (first pass)
|
||||
createJoins( pc, classMapping, auditingData );
|
||||
addJoins( pc, propertyMapper, auditingData, pc.getEntityName(), xmlMappingData, true );
|
||||
//createJoins( entityBinding, classMapping, auditingData );
|
||||
//addJoins( entityBinding, propertyMapper, auditingData, entityBinding.getEntityName(), xmlMappingData, true );
|
||||
|
||||
// Storing the generated configuration
|
||||
final EntityConfiguration entityCfg = new EntityConfiguration(
|
||||
auditEntityName,
|
||||
pc.getClassName(),
|
||||
entityBinding.getEntity().getDescriptor().getName().fullName(),
|
||||
idMapper,
|
||||
propertyMapper,
|
||||
parentEntityName
|
||||
);
|
||||
entitiesConfigurations.put( pc.getEntityName(), entityCfg );
|
||||
entitiesConfigurations.put( entityBinding.getEntityName(), entityCfg );
|
||||
}
|
||||
|
||||
@SuppressWarnings({"unchecked"})
|
||||
public void generateSecondPass(
|
||||
PersistentClass pc,
|
||||
EntityBinding entityBinding,
|
||||
ClassAuditingData auditingData,
|
||||
EntityXmlMappingData xmlMappingData) {
|
||||
final String entityName = pc.getEntityName();
|
||||
final String entityName = entityBinding.getEntityName();
|
||||
LOG.debugf( "Generating second-pass auditing mapping for entity %s", entityName );
|
||||
|
||||
final CompositeMapperBuilder propertyMapper = entitiesConfigurations.get( entityName ).getPropertyMapper();
|
||||
|
@ -678,7 +745,8 @@ public final class AuditMetadataGenerator {
|
|||
|
||||
addProperties(
|
||||
parent,
|
||||
pc.getUnjoinedPropertyIterator(),
|
||||
entityBinding.getNonIdAttributeBindingClosure(), // TODO: this needs to be corrected to only get non-joined attribute bindings.
|
||||
//entityBinding.getUnjoinedPropertyIterator(),
|
||||
propertyMapper,
|
||||
auditingData,
|
||||
entityName,
|
||||
|
@ -686,8 +754,9 @@ public final class AuditMetadataGenerator {
|
|||
false
|
||||
);
|
||||
|
||||
// TODO: add suuport for joins
|
||||
// Mapping joins (second pass)
|
||||
addJoins( pc, propertyMapper, auditingData, entityName, xmlMappingData, false );
|
||||
//addJoins( entityBinding, propertyMapper, auditingData, entityName, xmlMappingData, false );
|
||||
}
|
||||
|
||||
public Map<String, EntityConfiguration> getEntitiesConfigurations() {
|
||||
|
@ -700,26 +769,10 @@ public final class AuditMetadataGenerator {
|
|||
return basicMetadataGenerator;
|
||||
}
|
||||
|
||||
Configuration getCfg() {
|
||||
return cfg;
|
||||
}
|
||||
|
||||
GlobalConfiguration getGlobalCfg() {
|
||||
return globalCfg;
|
||||
}
|
||||
|
||||
AuditEntitiesConfiguration getVerEntCfg() {
|
||||
return verEntCfg;
|
||||
}
|
||||
|
||||
AuditStrategy getAuditStrategy() {
|
||||
return auditStrategy;
|
||||
}
|
||||
|
||||
ClassLoaderService getClassLoaderService() {
|
||||
return classLoaderService;
|
||||
}
|
||||
|
||||
AuditEntityNameRegister getAuditEntityNameRegister() {
|
||||
return auditEntityNameRegister;
|
||||
}
|
||||
|
|
|
@ -23,16 +23,19 @@
|
|||
*/
|
||||
package org.hibernate.envers.configuration.internal.metadata;
|
||||
|
||||
import java.util.Properties;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
import org.hibernate.envers.configuration.internal.metadata.reader.PropertyAuditingData;
|
||||
import org.hibernate.envers.internal.entities.mapper.SimpleMapperBuilder;
|
||||
import org.hibernate.mapping.SimpleValue;
|
||||
import org.hibernate.mapping.Value;
|
||||
import org.hibernate.metamodel.spi.binding.AttributeBinding;
|
||||
import org.hibernate.metamodel.spi.binding.HibernateTypeDescriptor;
|
||||
import org.hibernate.metamodel.spi.binding.ManyToOneAttributeBinding;
|
||||
import org.hibernate.metamodel.spi.binding.SingularAttributeBinding;
|
||||
import org.hibernate.metamodel.spi.relational.Value;
|
||||
import org.hibernate.type.BasicType;
|
||||
import org.hibernate.type.CustomType;
|
||||
import org.hibernate.type.EnumType;
|
||||
import org.hibernate.type.SerializableToBlobType;
|
||||
import org.hibernate.type.Type;
|
||||
import org.hibernate.usertype.DynamicParameterizedType;
|
||||
|
||||
|
@ -46,18 +49,23 @@ import org.dom4j.Element;
|
|||
public final class BasicMetadataGenerator {
|
||||
@SuppressWarnings({"unchecked"})
|
||||
boolean addBasic(
|
||||
Element parent, PropertyAuditingData propertyAuditingData,
|
||||
Value value, SimpleMapperBuilder mapper, boolean insertable, boolean key) {
|
||||
final Type type = value.getType();
|
||||
|
||||
if ( type instanceof BasicType
|
||||
|| type instanceof SerializableToBlobType
|
||||
|| "org.hibernate.type.PrimitiveByteArrayBlobType".equals( type.getClass().getName() ) ) {
|
||||
Element parent,
|
||||
PropertyAuditingData propertyAuditingData,
|
||||
HibernateTypeDescriptor hibernateTypeDescriptor,
|
||||
List<Value> values,
|
||||
boolean insertable,
|
||||
SimpleMapperBuilder mapper,
|
||||
boolean key) {
|
||||
if ( hibernateTypeDescriptor.getResolvedTypeMapping() instanceof BasicType
|
||||
|| "org.hibernate.type.PrimitiveByteArrayBlobType".equals(
|
||||
hibernateTypeDescriptor.getJavaTypeDescriptor()
|
||||
.getName()
|
||||
.fullName()
|
||||
) ) {
|
||||
if ( parent != null ) {
|
||||
final boolean addNestedType = (value instanceof SimpleValue)
|
||||
&& ((SimpleValue) value).getTypeParameters() != null;
|
||||
final boolean addNestedType = !hibernateTypeDescriptor.getTypeParameters().isEmpty();
|
||||
|
||||
final String typeName = resolveType( value );
|
||||
final String typeName = resolveTypeName( hibernateTypeDescriptor );
|
||||
|
||||
final Element propMapping = MetadataTools.addProperty(
|
||||
parent,
|
||||
|
@ -66,22 +74,22 @@ public final class BasicMetadataGenerator {
|
|||
propertyAuditingData.isForceInsertable() || insertable,
|
||||
key
|
||||
);
|
||||
MetadataTools.addColumns( propMapping, value.getColumnIterator() );
|
||||
MetadataTools.addValuesAsColumns( propMapping, values );
|
||||
|
||||
if ( addNestedType ) {
|
||||
final Properties typeParameters = ((SimpleValue) value).getTypeParameters();
|
||||
final Map<String, String> typeParameters = hibernateTypeDescriptor.getTypeParameters();
|
||||
final Element typeMapping = propMapping.addElement( "type" );
|
||||
typeMapping.addAttribute( "name", typeName );
|
||||
|
||||
if ( "org.hibernate.type.EnumType".equals( typeName ) ) {
|
||||
// Proper handling of enumeration type
|
||||
mapEnumerationType( typeMapping, type, typeParameters );
|
||||
mapEnumerationType( typeMapping, hibernateTypeDescriptor.getResolvedTypeMapping(), typeParameters );
|
||||
}
|
||||
else {
|
||||
// By default copying all Hibernate properties
|
||||
for ( Object object : typeParameters.keySet() ) {
|
||||
final String keyType = (String) object;
|
||||
final String property = typeParameters.getProperty( keyType );
|
||||
final String property = typeParameters.get( keyType );
|
||||
|
||||
if ( property != null ) {
|
||||
typeMapping.addElement( "param" ).addAttribute( "name", keyType ).setText( property );
|
||||
|
@ -103,26 +111,23 @@ public final class BasicMetadataGenerator {
|
|||
return true;
|
||||
}
|
||||
|
||||
private String resolveType(Value value) {
|
||||
final Type type = value.getType();
|
||||
String typeName = null;
|
||||
if ( value instanceof SimpleValue ) {
|
||||
typeName = ( (SimpleValue) value ).getTypeName();
|
||||
}
|
||||
private String resolveTypeName(HibernateTypeDescriptor hibernateTypeDescriptor) {
|
||||
final Type type = hibernateTypeDescriptor.getResolvedTypeMapping();
|
||||
String typeName = hibernateTypeDescriptor.getExplicitTypeName();
|
||||
if ( typeName == null ) {
|
||||
typeName = type.getName();
|
||||
}
|
||||
if ( typeName == null ) {
|
||||
typeName = type.getClass().getName();
|
||||
typeName = hibernateTypeDescriptor.getJavaTypeDescriptor().getName().fullName();
|
||||
}
|
||||
return typeName;
|
||||
}
|
||||
|
||||
private void mapEnumerationType(Element parent, Type type, Properties parameters) {
|
||||
if ( parameters.getProperty( EnumType.ENUM ) != null ) {
|
||||
private void mapEnumerationType(Element parent, Type type, Map<String,String> parameters) {
|
||||
if ( parameters.get( EnumType.ENUM ) != null ) {
|
||||
parent.addElement( "param" )
|
||||
.addAttribute( "name", EnumType.ENUM )
|
||||
.setText( parameters.getProperty( EnumType.ENUM ) );
|
||||
.setText( parameters.get( EnumType.ENUM ) );
|
||||
}
|
||||
else {
|
||||
parent.addElement( "param" ).addAttribute( "name", EnumType.ENUM ).setText(
|
||||
|
@ -130,9 +135,9 @@ public final class BasicMetadataGenerator {
|
|||
.getName()
|
||||
);
|
||||
}
|
||||
if ( parameters.getProperty( EnumType.NAMED ) != null ) {
|
||||
if ( parameters.get( EnumType.NAMED ) != null ) {
|
||||
parent.addElement( "param" ).addAttribute( "name", EnumType.NAMED ).setText(
|
||||
parameters.getProperty(
|
||||
parameters.get(
|
||||
EnumType.NAMED
|
||||
)
|
||||
);
|
||||
|
@ -151,15 +156,15 @@ public final class BasicMetadataGenerator {
|
|||
boolean addManyToOne(
|
||||
Element parent,
|
||||
PropertyAuditingData propertyAuditingData,
|
||||
Value value,
|
||||
ManyToOneAttributeBinding attributeBinding,
|
||||
SimpleMapperBuilder mapper) {
|
||||
final Type type = value.getType();
|
||||
final Type type = attributeBinding.getHibernateTypeDescriptor().getResolvedTypeMapping();
|
||||
|
||||
// A null mapper occurs when adding to composite-id element
|
||||
final Element manyToOneElement = parent.addElement( mapper != null ? "many-to-one" : "key-many-to-one" );
|
||||
manyToOneElement.addAttribute( "name", propertyAuditingData.getName() );
|
||||
manyToOneElement.addAttribute( "class", type.getName() );
|
||||
MetadataTools.addColumns( manyToOneElement, value.getColumnIterator() );
|
||||
MetadataTools.addValuesAsColumns( manyToOneElement, attributeBinding.getValues() );
|
||||
|
||||
// A null mapper means that we only want to add xml mappings
|
||||
if ( mapper != null ) {
|
||||
|
|
|
@ -26,7 +26,6 @@ package org.hibernate.envers.configuration.internal.metadata;
|
|||
import java.util.ArrayList;
|
||||
import java.util.HashMap;
|
||||
import java.util.HashSet;
|
||||
import java.util.Iterator;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
|
@ -34,14 +33,15 @@ import java.util.TreeMap;
|
|||
import java.util.TreeSet;
|
||||
import javax.persistence.JoinColumn;
|
||||
|
||||
import org.hibernate.AssertionFailure;
|
||||
import org.hibernate.MappingException;
|
||||
import org.hibernate.annotations.common.reflection.ReflectionManager;
|
||||
import org.hibernate.envers.ModificationStore;
|
||||
import org.hibernate.envers.RelationTargetAuditMode;
|
||||
import org.hibernate.envers.configuration.internal.metadata.reader.AuditedPropertiesReader;
|
||||
import org.hibernate.envers.configuration.internal.metadata.reader.ComponentAuditedPropertiesReader;
|
||||
import org.hibernate.envers.configuration.internal.metadata.reader.ComponentAuditingData;
|
||||
import org.hibernate.envers.configuration.internal.metadata.reader.PropertyAuditingData;
|
||||
import org.hibernate.envers.configuration.spi.AuditConfiguration;
|
||||
import org.hibernate.envers.internal.EnversMessageLogger;
|
||||
import org.hibernate.envers.internal.entities.EntityConfiguration;
|
||||
import org.hibernate.envers.internal.entities.IdMappingData;
|
||||
|
@ -78,17 +78,24 @@ import org.hibernate.envers.internal.tools.MappingTools;
|
|||
import org.hibernate.envers.internal.tools.ReflectionTools;
|
||||
import org.hibernate.envers.internal.tools.StringTools;
|
||||
import org.hibernate.envers.internal.tools.Tools;
|
||||
import org.hibernate.mapping.Collection;
|
||||
import org.hibernate.mapping.Component;
|
||||
import org.hibernate.mapping.IndexedCollection;
|
||||
import org.hibernate.mapping.ManyToOne;
|
||||
import org.hibernate.mapping.OneToMany;
|
||||
import org.hibernate.mapping.PersistentClass;
|
||||
import org.hibernate.mapping.Property;
|
||||
import org.hibernate.mapping.Table;
|
||||
import org.hibernate.mapping.Value;
|
||||
import org.hibernate.metamodel.spi.binding.AttributeBinding;
|
||||
import org.hibernate.metamodel.spi.binding.CompositeAttributeBindingContainer;
|
||||
import org.hibernate.metamodel.spi.binding.CompositePluralAttributeElementBinding;
|
||||
import org.hibernate.metamodel.spi.binding.CompositePluralAttributeIndexBinding;
|
||||
import org.hibernate.metamodel.spi.binding.EntityBinding;
|
||||
import org.hibernate.metamodel.spi.binding.HibernateTypeDescriptor;
|
||||
import org.hibernate.metamodel.spi.binding.IndexedPluralAttributeBinding;
|
||||
import org.hibernate.metamodel.spi.binding.PluralAttributeAssociationElementBinding;
|
||||
import org.hibernate.metamodel.spi.binding.PluralAttributeBinding;
|
||||
import org.hibernate.metamodel.spi.binding.PluralAttributeElementBinding;
|
||||
import org.hibernate.metamodel.spi.binding.PluralAttributeIndexBinding;
|
||||
import org.hibernate.metamodel.spi.binding.SingularAttributeBinding;
|
||||
import org.hibernate.metamodel.spi.domain.PluralAttribute;
|
||||
import org.hibernate.metamodel.spi.relational.TableSpecification;
|
||||
import org.hibernate.metamodel.spi.relational.Value;
|
||||
import org.hibernate.type.BagType;
|
||||
import org.hibernate.type.ComponentType;
|
||||
import org.hibernate.type.EntityType;
|
||||
import org.hibernate.type.ListType;
|
||||
import org.hibernate.type.ManyToOneType;
|
||||
import org.hibernate.type.MapType;
|
||||
|
@ -113,9 +120,10 @@ public final class CollectionMetadataGenerator {
|
|||
CollectionMetadataGenerator.class.getName()
|
||||
);
|
||||
|
||||
private final AuditConfiguration.AuditConfigurationContext context;
|
||||
private final AuditMetadataGenerator mainGenerator;
|
||||
private final String propertyName;
|
||||
private final Collection propertyValue;
|
||||
private final PluralAttributeBinding pluralAttributeBinding;
|
||||
private final CompositeMapperBuilder currentMapper;
|
||||
private final String referencingEntityName;
|
||||
private final EntityXmlMappingData xmlMappingData;
|
||||
|
@ -129,7 +137,7 @@ public final class CollectionMetadataGenerator {
|
|||
|
||||
/**
|
||||
* @param mainGenerator Main generator, giving access to configuration and the basic mapper.
|
||||
* @param propertyValue Value of the collection, as mapped by Hibernate.
|
||||
* @param pluralAttributeBinding Value of the collection, as mapped by Hibernate.
|
||||
* @param currentMapper Mapper, to which the appropriate {@link PropertyMapper} will be added.
|
||||
* @param referencingEntityName Name of the entity that owns this collection.
|
||||
* @param xmlMappingData In case this collection requires a middle table, additional mapping documents will
|
||||
|
@ -139,12 +147,15 @@ public final class CollectionMetadataGenerator {
|
|||
* table and the value of the <code>@MapKey</code> annotation, if there was one.
|
||||
*/
|
||||
public CollectionMetadataGenerator(
|
||||
AuditConfiguration.AuditConfigurationContext context,
|
||||
AuditMetadataGenerator mainGenerator,
|
||||
Collection propertyValue, CompositeMapperBuilder currentMapper,
|
||||
PluralAttributeBinding pluralAttributeBinding,
|
||||
CompositeMapperBuilder currentMapper,
|
||||
String referencingEntityName, EntityXmlMappingData xmlMappingData,
|
||||
PropertyAuditingData propertyAuditingData) {
|
||||
this.context = context;
|
||||
this.mainGenerator = mainGenerator;
|
||||
this.propertyValue = propertyValue;
|
||||
this.pluralAttributeBinding = pluralAttributeBinding;
|
||||
this.currentMapper = currentMapper;
|
||||
this.referencingEntityName = referencingEntityName;
|
||||
this.xmlMappingData = xmlMappingData;
|
||||
|
@ -157,17 +168,24 @@ public final class CollectionMetadataGenerator {
|
|||
throw new MappingException( "Unable to read auditing configuration for " + referencingEntityName + "!" );
|
||||
}
|
||||
|
||||
referencedEntityName = MappingTools.getReferencedEntityName( propertyValue.getElement() );
|
||||
referencedEntityName = MappingTools.getReferencedEntityName( pluralAttributeBinding );
|
||||
}
|
||||
|
||||
void addCollection() {
|
||||
final Type type = propertyValue.getType();
|
||||
final Value value = propertyValue.getElement();
|
||||
final Type type = pluralAttributeBinding.getHibernateTypeDescriptor().getResolvedTypeMapping();
|
||||
final PluralAttributeElementBinding.Nature elementNature =
|
||||
pluralAttributeBinding.getPluralAttributeElementBinding().getNature();
|
||||
|
||||
final boolean oneToManyAttachedType = type instanceof BagType || type instanceof SetType || type instanceof MapType || type instanceof ListType;
|
||||
final boolean inverseOneToMany = (value instanceof OneToMany) && (propertyValue.isInverse());
|
||||
final boolean owningManyToOneWithJoinTableBidirectional = (value instanceof ManyToOne) && (propertyAuditingData.getRelationMappedBy() != null);
|
||||
final boolean fakeOneToManyBidirectional = (value instanceof OneToMany) && (propertyAuditingData.getAuditMappedBy() != null);
|
||||
final boolean inverseOneToMany =
|
||||
(elementNature == PluralAttributeElementBinding.Nature.ONE_TO_MANY) &&
|
||||
( pluralAttributeBinding.getPluralAttributeKeyBinding().isInverse() );
|
||||
final boolean owningManyToOneWithJoinTableBidirectional =
|
||||
(elementNature == PluralAttributeAssociationElementBinding.Nature.MANY_TO_MANY) &&
|
||||
(propertyAuditingData.getRelationMappedBy() != null);
|
||||
final boolean fakeOneToManyBidirectional =
|
||||
(elementNature == PluralAttributeElementBinding.Nature.ONE_TO_MANY)
|
||||
&& (propertyAuditingData.getAuditMappedBy() != null);
|
||||
|
||||
if ( oneToManyAttachedType && (inverseOneToMany || fakeOneToManyBidirectional || owningManyToOneWithJoinTableBidirectional) ) {
|
||||
// A one-to-many relation mapped using @ManyToOne and @OneToMany(mappedBy="...")
|
||||
|
@ -181,7 +199,7 @@ public final class CollectionMetadataGenerator {
|
|||
|
||||
private MiddleIdData createMiddleIdData(IdMappingData idMappingData, String prefix, String entityName) {
|
||||
return new MiddleIdData(
|
||||
mainGenerator.getVerEntCfg(), idMappingData, prefix, entityName,
|
||||
context.getAuditEntitiesConfiguration(), idMappingData, prefix, entityName,
|
||||
mainGenerator.getEntitiesConfigurations().containsKey( entityName )
|
||||
);
|
||||
}
|
||||
|
@ -194,7 +212,9 @@ public final class CollectionMetadataGenerator {
|
|||
propertyName
|
||||
);
|
||||
|
||||
final String mappedBy = getMappedBy( propertyValue );
|
||||
final String mappedBy = getMappedBy(
|
||||
(PluralAttributeAssociationElementBinding) pluralAttributeBinding.getPluralAttributeElementBinding()
|
||||
);
|
||||
|
||||
final IdMappingData referencedIdMapping = mainGenerator.getReferencedIdMappingData(
|
||||
referencingEntityName,
|
||||
|
@ -230,8 +250,8 @@ public final class CollectionMetadataGenerator {
|
|||
|
||||
// Generating the query generator - it should read directly from the related entity.
|
||||
final RelationQueryGenerator queryGenerator = new OneAuditEntityQueryGenerator(
|
||||
mainGenerator.getGlobalCfg(),
|
||||
mainGenerator.getVerEntCfg(),
|
||||
context.getGlobalConfiguration(),
|
||||
context.getAuditEntitiesConfiguration(),
|
||||
mainGenerator.getAuditStrategy(),
|
||||
referencingIdData,
|
||||
referencedEntityName,
|
||||
|
@ -241,7 +261,7 @@ public final class CollectionMetadataGenerator {
|
|||
|
||||
// Creating common mapper data.
|
||||
final CommonCollectionMapperData commonCollectionMapperData = new CommonCollectionMapperData(
|
||||
mainGenerator.getVerEntCfg(), referencedEntityName,
|
||||
context.getAuditEntitiesConfiguration(), referencedEntityName,
|
||||
propertyAuditingData.getPropertyData(),
|
||||
referencingIdData, queryGenerator
|
||||
);
|
||||
|
@ -327,19 +347,19 @@ public final class CollectionMetadataGenerator {
|
|||
}
|
||||
}
|
||||
|
||||
private String getMiddleTableName(Collection value, String entityName) {
|
||||
private String getMiddleTableName(PluralAttributeBinding attributeBinding, String entityName) {
|
||||
// We check how Hibernate maps the collection.
|
||||
if ( value.getElement() instanceof OneToMany && !value.isInverse() ) {
|
||||
if ( attributeBinding.getPluralAttributeElementBinding().getNature() ==
|
||||
PluralAttributeElementBinding.Nature.ONE_TO_MANY &&
|
||||
!attributeBinding.getPluralAttributeKeyBinding().isInverse() ) {
|
||||
// This must be a @JoinColumn+@OneToMany mapping. Generating the table name, as Hibernate doesn't use a
|
||||
// middle table for mapping this relation.
|
||||
return StringTools.getLastComponent( entityName ) + "_" + StringTools.getLastComponent(
|
||||
MappingTools.getReferencedEntityName(
|
||||
value.getElement()
|
||||
)
|
||||
MappingTools.getReferencedEntityName( attributeBinding )
|
||||
);
|
||||
}
|
||||
// Hibernate uses a middle table for mapping this relation, so we get it's name directly.
|
||||
return value.getCollectionTable().getName();
|
||||
return attributeBinding.getPluralAttributeKeyBinding().getCollectionTable().getLogicalName().getName();
|
||||
}
|
||||
|
||||
@SuppressWarnings({"unchecked"})
|
||||
|
@ -359,9 +379,9 @@ public final class CollectionMetadataGenerator {
|
|||
auditMiddleEntityName = propertyAuditingData.getJoinTable().name();
|
||||
}
|
||||
else {
|
||||
final String middleTableName = getMiddleTableName( propertyValue, referencingEntityName );
|
||||
auditMiddleTableName = mainGenerator.getVerEntCfg().getAuditTableName( null, middleTableName );
|
||||
auditMiddleEntityName = mainGenerator.getVerEntCfg().getAuditEntityName( middleTableName );
|
||||
final String middleTableName = getMiddleTableName( pluralAttributeBinding, referencingEntityName );
|
||||
auditMiddleTableName = context.getAuditEntitiesConfiguration().getAuditTableName( null, middleTableName );
|
||||
auditMiddleEntityName = context.getAuditEntitiesConfiguration().getAuditEntityName( middleTableName );
|
||||
}
|
||||
|
||||
LOG.debugf( "Using join table name: %s", auditMiddleTableName );
|
||||
|
@ -369,7 +389,7 @@ public final class CollectionMetadataGenerator {
|
|||
// Generating the XML mapping for the middle entity, only if the relation isn't inverse.
|
||||
// If the relation is inverse, will be later checked by comparing middleEntityXml with null.
|
||||
Element middleEntityXml;
|
||||
if ( !propertyValue.isInverse() ) {
|
||||
if ( !pluralAttributeBinding.getPluralAttributeKeyBinding().isInverse() ) {
|
||||
// Generating a unique middle entity name
|
||||
auditMiddleEntityName = mainGenerator.getAuditEntityNameRegister().createUnique( auditMiddleEntityName );
|
||||
|
||||
|
@ -379,7 +399,7 @@ public final class CollectionMetadataGenerator {
|
|||
middleEntityXml = createMiddleEntityXml(
|
||||
auditMiddleTableName,
|
||||
auditMiddleEntityName,
|
||||
propertyValue.getWhere()
|
||||
pluralAttributeBinding.getWhere()
|
||||
);
|
||||
}
|
||||
else {
|
||||
|
@ -399,11 +419,11 @@ public final class CollectionMetadataGenerator {
|
|||
String referencingPrefixRelated;
|
||||
String referencedPrefix;
|
||||
|
||||
if ( propertyValue.isInverse() ) {
|
||||
if ( pluralAttributeBinding.getPluralAttributeKeyBinding().isInverse() ) {
|
||||
// If the relation is inverse, then referencedEntityName is not null.
|
||||
mappedBy = getMappedBy(
|
||||
propertyValue.getCollectionTable(),
|
||||
mainGenerator.getCfg().getClassMapping( referencedEntityName )
|
||||
pluralAttributeBinding.getPluralAttributeKeyBinding().getCollectionTable(),
|
||||
context.getEntityBinding( referencedEntityName )
|
||||
);
|
||||
|
||||
referencingPrefixRelated = mappedBy + "_";
|
||||
|
@ -427,8 +447,8 @@ public final class CollectionMetadataGenerator {
|
|||
// references some entities (either from the element or index). At the end, this will be used to build
|
||||
// a query generator to read the raw data collection from the middle table.
|
||||
final QueryGeneratorBuilder queryGeneratorBuilder = new QueryGeneratorBuilder(
|
||||
mainGenerator.getGlobalCfg(),
|
||||
mainGenerator.getVerEntCfg(),
|
||||
context.getGlobalConfiguration(),
|
||||
context.getAuditEntitiesConfiguration(),
|
||||
mainGenerator.getAuditStrategy(),
|
||||
referencingIdData,
|
||||
auditMiddleEntityName,
|
||||
|
@ -440,7 +460,9 @@ public final class CollectionMetadataGenerator {
|
|||
// Adding related-entity (in this case: the referencing's entity id) id mapping to the xml.
|
||||
addRelatedToXmlMapping(
|
||||
middleEntityXml, referencingPrefixRelated,
|
||||
MetadataTools.getColumnNameIterator( propertyValue.getKey().getColumnIterator() ),
|
||||
MetadataTools.getColumnNameIterator(
|
||||
pluralAttributeBinding.getPluralAttributeKeyBinding().getValues().iterator()
|
||||
),
|
||||
referencingIdMapping
|
||||
);
|
||||
}
|
||||
|
@ -449,11 +471,11 @@ public final class CollectionMetadataGenerator {
|
|||
// Generating the element mapping.
|
||||
// ******
|
||||
final MiddleComponentData elementComponentData = addValueToMiddleTable(
|
||||
propertyValue.getElement(),
|
||||
middleEntityXml,
|
||||
queryGeneratorBuilder,
|
||||
referencedPrefix,
|
||||
propertyAuditingData.getJoinTable().inverseJoinColumns()
|
||||
propertyAuditingData.getJoinTable().inverseJoinColumns(),
|
||||
false
|
||||
);
|
||||
|
||||
// ******
|
||||
|
@ -469,7 +491,7 @@ public final class CollectionMetadataGenerator {
|
|||
|
||||
// Creating common data
|
||||
final CommonCollectionMapperData commonCollectionMapperData = new CommonCollectionMapperData(
|
||||
mainGenerator.getVerEntCfg(),
|
||||
context.getAuditEntitiesConfiguration(),
|
||||
auditMiddleEntityName,
|
||||
propertyAuditingData.getPropertyData(),
|
||||
referencingIdData,
|
||||
|
@ -486,17 +508,18 @@ public final class CollectionMetadataGenerator {
|
|||
}
|
||||
|
||||
private MiddleComponentData addIndex(Element middleEntityXml, QueryGeneratorBuilder queryGeneratorBuilder) {
|
||||
if ( propertyValue instanceof IndexedCollection ) {
|
||||
final IndexedCollection indexedValue = (IndexedCollection) propertyValue;
|
||||
if ( pluralAttributeBinding.getAttribute().getNature().isIndexable() ) {
|
||||
final PluralAttributeIndexBinding indexBinding =
|
||||
( (IndexedPluralAttributeBinding) pluralAttributeBinding ).getPluralAttributeIndexBinding();
|
||||
final String mapKey = propertyAuditingData.getMapKey();
|
||||
if ( mapKey == null ) {
|
||||
// This entity doesn't specify a javax.persistence.MapKey. Mapping it to the middle entity.
|
||||
return addValueToMiddleTable(
|
||||
indexedValue.getIndex(),
|
||||
middleEntityXml,
|
||||
queryGeneratorBuilder,
|
||||
"mapkey",
|
||||
null
|
||||
null,
|
||||
true
|
||||
);
|
||||
}
|
||||
else {
|
||||
|
@ -507,7 +530,7 @@ public final class CollectionMetadataGenerator {
|
|||
// The key of the map is the id of the entity.
|
||||
return new MiddleComponentData(
|
||||
new MiddleMapKeyIdComponentMapper(
|
||||
mainGenerator.getVerEntCfg(),
|
||||
context.getAuditEntitiesConfiguration(),
|
||||
referencedIdMapping.getIdMapper()
|
||||
),
|
||||
currentIndex
|
||||
|
@ -531,29 +554,46 @@ public final class CollectionMetadataGenerator {
|
|||
}
|
||||
}
|
||||
|
||||
private PluralAttributeIndexBinding getPluralAttributeIndexBinding() {
|
||||
if ( !pluralAttributeBinding.getAttribute().getNature().isIndexable() ) {
|
||||
throw new AssertionFailure( "This method is only valid for an indexed plural attribute binding." );
|
||||
}
|
||||
return ( (IndexedPluralAttributeBinding) pluralAttributeBinding ).getPluralAttributeIndexBinding();
|
||||
}
|
||||
|
||||
/**
|
||||
* @param value Value, which should be mapped to the middle-table, either as a relation to another entity,
|
||||
* or as a simple value.
|
||||
* @param xmlMapping If not <code>null</code>, xml mapping for this value is added to this element.
|
||||
* @param queryGeneratorBuilder In case <code>value</code> is a relation to another entity, information about it
|
||||
* should be added to the given.
|
||||
* @param prefix Prefix for proeprty names of related entities identifiers.
|
||||
* @param joinColumns Names of columns to use in the xml mapping, if this array isn't null and has any elements.
|
||||
* @param isIndex true, if the value is for the collection index; false, if the value is for the collection element.
|
||||
*
|
||||
* @return Data for mapping this component.
|
||||
*/
|
||||
@SuppressWarnings({"unchecked"})
|
||||
private MiddleComponentData addValueToMiddleTable(
|
||||
Value value,
|
||||
Element xmlMapping,
|
||||
QueryGeneratorBuilder queryGeneratorBuilder,
|
||||
String prefix,
|
||||
JoinColumn[] joinColumns) {
|
||||
final Type type = value.getType();
|
||||
if ( type instanceof ManyToOneType ) {
|
||||
JoinColumn[] joinColumns,
|
||||
boolean isIndex) {
|
||||
|
||||
final HibernateTypeDescriptor hibernateTypeDescriptor;
|
||||
final List<Value> values;
|
||||
if ( isIndex ) {
|
||||
hibernateTypeDescriptor = getPluralAttributeIndexBinding().getHibernateTypeDescriptor();
|
||||
values = getPluralAttributeIndexBinding().getValues();
|
||||
}
|
||||
else {
|
||||
hibernateTypeDescriptor = pluralAttributeBinding.getPluralAttributeElementBinding().getHibernateTypeDescriptor();
|
||||
values = pluralAttributeBinding.getPluralAttributeElementBinding().getValues();
|
||||
|
||||
} ;
|
||||
if ( hibernateTypeDescriptor.getResolvedTypeMapping() instanceof ManyToOneType ) {
|
||||
final String prefixRelated = prefix + "_";
|
||||
|
||||
final String referencedEntityName = MappingTools.getReferencedEntityName( value );
|
||||
final String referencedEntityName = MappingTools.getReferencedEntityName( pluralAttributeBinding );
|
||||
|
||||
final IdMappingData referencedIdMapping = mainGenerator.getReferencedIdMappingData(
|
||||
referencingEntityName,
|
||||
|
@ -569,7 +609,7 @@ public final class CollectionMetadataGenerator {
|
|||
xmlMapping, prefixRelated,
|
||||
joinColumns != null && joinColumns.length > 0
|
||||
? MetadataTools.getColumnNameIterator( joinColumns )
|
||||
: MetadataTools.getColumnNameIterator( value.getColumnIterator() ),
|
||||
: MetadataTools.getColumnNameIterator( values.iterator() ),
|
||||
referencedIdMapping
|
||||
);
|
||||
}
|
||||
|
@ -588,12 +628,20 @@ public final class CollectionMetadataGenerator {
|
|||
queryGeneratorBuilder.getCurrentIndex()
|
||||
);
|
||||
}
|
||||
else if ( type instanceof ComponentType ) {
|
||||
else if ( hibernateTypeDescriptor.getResolvedTypeMapping() instanceof ComponentType ) {
|
||||
final CompositeAttributeBindingContainer compositeAttributeBindingContainer;
|
||||
if ( isIndex ) {
|
||||
compositeAttributeBindingContainer =
|
||||
( ( CompositePluralAttributeIndexBinding ) getPluralAttributeIndexBinding() ).getCompositeAttributeBindingContainer();
|
||||
}
|
||||
else {
|
||||
compositeAttributeBindingContainer =
|
||||
( (CompositePluralAttributeElementBinding) pluralAttributeBinding.getPluralAttributeElementBinding() ).getCompositeAttributeBindingContainer();
|
||||
}
|
||||
// Collection of embeddable elements.
|
||||
final Component component = (Component) value;
|
||||
final Class componentClass = ReflectionTools.loadClass(
|
||||
component.getComponentClassName(),
|
||||
mainGenerator.getClassLoaderService()
|
||||
hibernateTypeDescriptor.getJavaTypeDescriptor().getName().fullName(),
|
||||
context.getClassLoaderService()
|
||||
);
|
||||
final MiddleEmbeddableComponentMapper componentMapper = new MiddleEmbeddableComponentMapper(
|
||||
new MultiPropertyMapper(),
|
||||
|
@ -602,12 +650,15 @@ public final class CollectionMetadataGenerator {
|
|||
|
||||
final Element parentXmlMapping = xmlMapping.getParent();
|
||||
final ComponentAuditingData auditData = new ComponentAuditingData();
|
||||
final ReflectionManager reflectionManager = mainGenerator.getCfg().getReflectionManager();
|
||||
|
||||
new ComponentAuditedPropertiesReader(
|
||||
ModificationStore.FULL,
|
||||
new AuditedPropertiesReader.ComponentPropertiesSource( reflectionManager, component ),
|
||||
auditData, mainGenerator.getGlobalCfg(), reflectionManager, ""
|
||||
context,
|
||||
auditData,
|
||||
new AuditedPropertiesReader.ComponentPropertiesSource(
|
||||
context.getClassInfo( compositeAttributeBindingContainer.getAttributeContainer() ),
|
||||
compositeAttributeBindingContainer
|
||||
),
|
||||
""
|
||||
).read();
|
||||
|
||||
// Emulating first pass.
|
||||
|
@ -615,12 +666,11 @@ public final class CollectionMetadataGenerator {
|
|||
final PropertyAuditingData nestedAuditingData = auditData.getPropertyAuditingData( auditedPropertyName );
|
||||
mainGenerator.addValue(
|
||||
parentXmlMapping,
|
||||
component.getProperty( auditedPropertyName ).getValue(),
|
||||
compositeAttributeBindingContainer.locateAttributeBinding( auditedPropertyName ),
|
||||
componentMapper,
|
||||
prefix, xmlMappingData,
|
||||
nestedAuditingData,
|
||||
true,
|
||||
true,
|
||||
true
|
||||
);
|
||||
}
|
||||
|
@ -630,12 +680,11 @@ public final class CollectionMetadataGenerator {
|
|||
final PropertyAuditingData nestedAuditingData = auditData.getPropertyAuditingData( auditedPropertyName );
|
||||
mainGenerator.addValue(
|
||||
parentXmlMapping,
|
||||
component.getProperty( auditedPropertyName ).getValue(),
|
||||
compositeAttributeBindingContainer.locateAttributeBinding( auditedPropertyName ),
|
||||
componentMapper,
|
||||
referencingEntityName,
|
||||
xmlMappingData,
|
||||
nestedAuditingData,
|
||||
true,
|
||||
false,
|
||||
true
|
||||
);
|
||||
|
@ -643,8 +692,8 @@ public final class CollectionMetadataGenerator {
|
|||
|
||||
// Add an additional column holding a number to make each entry unique within the set.
|
||||
// Embeddable properties may contain null values, so cannot be stored within composite primary key.
|
||||
if ( propertyValue.isSet() ) {
|
||||
final String setOrdinalPropertyName = mainGenerator.getVerEntCfg()
|
||||
if ( ( pluralAttributeBinding.getAttribute() ).getNature() == PluralAttribute.Nature.SET ) {
|
||||
final String setOrdinalPropertyName = context.getAuditEntitiesConfiguration()
|
||||
.getEmbeddableSetOrdinalPropertyName();
|
||||
final Element ordinalProperty = MetadataTools.addProperty(
|
||||
xmlMapping, setOrdinalPropertyName, "integer", true, true
|
||||
|
@ -669,21 +718,24 @@ public final class CollectionMetadataGenerator {
|
|||
null,
|
||||
false
|
||||
),
|
||||
value,
|
||||
hibernateTypeDescriptor,
|
||||
values,
|
||||
true, // TODO: is this correct for collection element?
|
||||
null,
|
||||
true,
|
||||
true
|
||||
);
|
||||
|
||||
if ( mapped ) {
|
||||
// Simple values are always stored in the first item of the array returned by the query generator.
|
||||
return new MiddleComponentData(
|
||||
new MiddleSimpleComponentMapper( mainGenerator.getVerEntCfg(), prefix ),
|
||||
new MiddleSimpleComponentMapper( context.getAuditEntitiesConfiguration(), prefix ),
|
||||
0
|
||||
);
|
||||
}
|
||||
else {
|
||||
mainGenerator.throwUnsupportedTypeException( type, referencingEntityName, propertyName );
|
||||
mainGenerator.throwUnsupportedTypeException(
|
||||
hibernateTypeDescriptor.getResolvedTypeMapping(), referencingEntityName, propertyName
|
||||
);
|
||||
// Impossible to get here.
|
||||
throw new AssertionError();
|
||||
}
|
||||
|
@ -694,7 +746,7 @@ public final class CollectionMetadataGenerator {
|
|||
CommonCollectionMapperData commonCollectionMapperData,
|
||||
MiddleComponentData elementComponentData,
|
||||
MiddleComponentData indexComponentData) {
|
||||
final Type type = propertyValue.getType();
|
||||
final Type type = pluralAttributeBinding.getHibernateTypeDescriptor().getResolvedTypeMapping();
|
||||
final boolean embeddableElementType = isEmbeddableElementType();
|
||||
if ( type instanceof SortedSetType ) {
|
||||
currentMapper.addComposite(
|
||||
|
@ -704,7 +756,7 @@ public final class CollectionMetadataGenerator {
|
|||
TreeSet.class,
|
||||
SortedSetProxy.class,
|
||||
elementComponentData,
|
||||
propertyValue.getComparator(),
|
||||
pluralAttributeBinding.getComparator(),
|
||||
embeddableElementType,
|
||||
embeddableElementType
|
||||
)
|
||||
|
@ -733,7 +785,7 @@ public final class CollectionMetadataGenerator {
|
|||
SortedMapProxy.class,
|
||||
elementComponentData,
|
||||
indexComponentData,
|
||||
propertyValue.getComparator(),
|
||||
pluralAttributeBinding.getComparator(),
|
||||
embeddableElementType
|
||||
)
|
||||
);
|
||||
|
@ -785,7 +837,7 @@ public final class CollectionMetadataGenerator {
|
|||
private void storeMiddleEntityRelationInformation(String mappedBy) {
|
||||
// Only if this is a relation (when there is a referenced entity).
|
||||
if ( referencedEntityName != null ) {
|
||||
if ( propertyValue.isInverse() ) {
|
||||
if ( pluralAttributeBinding.getPluralAttributeKeyBinding().isInverse() ) {
|
||||
referencingEntityConfiguration.addToManyMiddleNotOwningRelation(
|
||||
propertyName,
|
||||
mappedBy,
|
||||
|
@ -801,11 +853,11 @@ public final class CollectionMetadataGenerator {
|
|||
private Element createMiddleEntityXml(String auditMiddleTableName, String auditMiddleEntityName, String where) {
|
||||
final String schema = mainGenerator.getSchema(
|
||||
propertyAuditingData.getJoinTable().schema(),
|
||||
propertyValue.getCollectionTable()
|
||||
pluralAttributeBinding.getPluralAttributeKeyBinding().getCollectionTable()
|
||||
);
|
||||
final String catalog = mainGenerator.getCatalog(
|
||||
propertyAuditingData.getJoinTable().catalog(),
|
||||
propertyValue.getCollectionTable()
|
||||
pluralAttributeBinding.getPluralAttributeKeyBinding().getCollectionTable()
|
||||
);
|
||||
|
||||
final Element middleEntityXml = MetadataTools.createEntity(
|
||||
|
@ -819,7 +871,7 @@ public final class CollectionMetadataGenerator {
|
|||
middleEntityXml.addAttribute( "where", where );
|
||||
}
|
||||
|
||||
middleEntityXmlId.addAttribute( "name", mainGenerator.getVerEntCfg().getOriginalIdPropName() );
|
||||
middleEntityXmlId.addAttribute( "name", context.getAuditEntitiesConfiguration().getOriginalIdPropName() );
|
||||
|
||||
// Adding the revision number as a foreign key to the revision info entity to the composite id of the
|
||||
// middle table.
|
||||
|
@ -828,7 +880,8 @@ public final class CollectionMetadataGenerator {
|
|||
// Adding the revision type property to the entity xml.
|
||||
mainGenerator.addRevisionType(
|
||||
isEmbeddableElementType() ? middleEntityXmlId : middleEntityXml,
|
||||
middleEntityXml
|
||||
middleEntityXml,
|
||||
isEmbeddableElementType()
|
||||
);
|
||||
|
||||
// All other properties should also be part of the primary key of the middle entity.
|
||||
|
@ -839,20 +892,15 @@ public final class CollectionMetadataGenerator {
|
|||
* Checks if the collection element is of {@link ComponentType} type.
|
||||
*/
|
||||
private boolean isEmbeddableElementType() {
|
||||
return propertyValue.getElement().getType() instanceof ComponentType;
|
||||
return pluralAttributeBinding.getPluralAttributeElementBinding()
|
||||
.getHibernateTypeDescriptor().getResolvedTypeMapping().isComponentType();
|
||||
}
|
||||
|
||||
private String getMappedBy(Collection collectionValue) {
|
||||
PersistentClass referencedClass = null;
|
||||
if ( collectionValue.getElement() instanceof OneToMany ) {
|
||||
final OneToMany oneToManyValue = (OneToMany) collectionValue.getElement();
|
||||
referencedClass = oneToManyValue.getAssociatedClass();
|
||||
}
|
||||
else if ( collectionValue.getElement() instanceof ManyToOne ) {
|
||||
// Case for bi-directional relation with @JoinTable on the owning @ManyToOne side.
|
||||
final ManyToOne manyToOneValue = (ManyToOne) collectionValue.getElement();
|
||||
referencedClass = manyToOneValue.getMappings().getClass( manyToOneValue.getReferencedEntityName() );
|
||||
}
|
||||
private String getMappedBy(PluralAttributeAssociationElementBinding elementBinding) {
|
||||
EntityBinding referencedEntityBinding = null;
|
||||
final EntityType entityType =
|
||||
(EntityType) elementBinding.getHibernateTypeDescriptor().getResolvedTypeMapping();
|
||||
referencedEntityBinding = context.getEntityBinding( entityType.getAssociatedEntityName() );
|
||||
|
||||
// If there's an @AuditMappedBy specified, returning it directly.
|
||||
final String auditMappedBy = propertyAuditingData.getAuditMappedBy();
|
||||
|
@ -861,27 +909,30 @@ public final class CollectionMetadataGenerator {
|
|||
}
|
||||
|
||||
// searching in referenced class
|
||||
String mappedBy = this.searchMappedBy( referencedClass, collectionValue );
|
||||
String mappedBy = this.searchMappedBy( referencedEntityBinding );
|
||||
|
||||
if ( mappedBy == null ) {
|
||||
LOG.debugf(
|
||||
"Going to search the mapped by attribute for %s in superclasses of entity: %s",
|
||||
propertyName,
|
||||
referencedClass.getClassName()
|
||||
referencedEntityBinding.getEntityName()
|
||||
);
|
||||
|
||||
PersistentClass tempClass = referencedClass;
|
||||
while ( (mappedBy == null) && (tempClass.getSuperclass() != null) ) {
|
||||
LOG.debugf( "Searching in superclass: %s", tempClass.getSuperclass().getClassName() );
|
||||
mappedBy = this.searchMappedBy( tempClass.getSuperclass(), collectionValue );
|
||||
tempClass = tempClass.getSuperclass();
|
||||
EntityBinding tempEntityBinding = referencedEntityBinding;
|
||||
while ( (mappedBy == null) && (tempEntityBinding.getSuperEntityBinding() != null) ) {
|
||||
LOG.debugf(
|
||||
"Searching in superclass: %s",
|
||||
tempEntityBinding.getSuperEntityBinding().getEntity().getDescriptor().getName()
|
||||
);
|
||||
mappedBy = this.searchMappedBy( tempEntityBinding.getSuperEntityBinding() );
|
||||
tempEntityBinding = tempEntityBinding.getSuperEntityBinding();
|
||||
}
|
||||
}
|
||||
|
||||
if ( mappedBy == null ) {
|
||||
throw new MappingException(
|
||||
"Unable to read the mapped by attribute for " + propertyName + " in "
|
||||
+ referencedClass.getClassName() + "!"
|
||||
+ referencedEntityBinding.getEntity().getDescriptor().getName() + "!"
|
||||
);
|
||||
}
|
||||
|
||||
|
@ -889,22 +940,30 @@ public final class CollectionMetadataGenerator {
|
|||
}
|
||||
|
||||
@SuppressWarnings({"unchecked"})
|
||||
private String searchMappedBy(PersistentClass referencedClass, Collection collectionValue) {
|
||||
final Iterator<Property> assocClassProps = referencedClass.getPropertyIterator();
|
||||
while ( assocClassProps.hasNext() ) {
|
||||
final Property property = assocClassProps.next();
|
||||
private String searchMappedBy(EntityBinding referencedEntityBinding) {
|
||||
for ( AttributeBinding attributeBinding : referencedEntityBinding.attributeBindings() ) {
|
||||
if ( !attributeBinding.isAssociation() ) {
|
||||
continue;
|
||||
}
|
||||
final List<Value> attributeValues;
|
||||
if ( attributeBinding.getAttribute().isSingular() ) {
|
||||
attributeValues = ( (SingularAttributeBinding) attributeBinding ).getValues();
|
||||
}
|
||||
else {
|
||||
attributeValues = ( (PluralAttributeBinding) attributeBinding ).getPluralAttributeElementBinding().getValues();
|
||||
}
|
||||
|
||||
if ( Tools.iteratorsContentEqual(
|
||||
property.getValue().getColumnIterator(),
|
||||
collectionValue.getKey().getColumnIterator()
|
||||
attributeValues.iterator(),
|
||||
pluralAttributeBinding.getPluralAttributeKeyBinding().getValues().iterator()
|
||||
) ) {
|
||||
return property.getName();
|
||||
return attributeBinding.getAttribute().getName();
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
private String getMappedBy(Table collectionTable, PersistentClass referencedClass) {
|
||||
private String getMappedBy(TableSpecification collectionTable, EntityBinding referencedClass) {
|
||||
// If there's an @AuditMappedBy specified, returning it directly.
|
||||
final String auditMappedBy = propertyAuditingData.getAuditMappedBy();
|
||||
if ( auditMappedBy != null ) {
|
||||
|
@ -919,21 +978,24 @@ public final class CollectionMetadataGenerator {
|
|||
LOG.debugf(
|
||||
"Going to search the mapped by attribute for %s in superclasses of entity: %s",
|
||||
propertyName,
|
||||
referencedClass.getClassName()
|
||||
referencedClass.getEntity().getDescriptor().getName()
|
||||
);
|
||||
|
||||
PersistentClass tempClass = referencedClass;
|
||||
while ( (mappedBy == null) && (tempClass.getSuperclass() != null) ) {
|
||||
LOG.debugf( "Searching in superclass: %s", tempClass.getSuperclass().getClassName() );
|
||||
mappedBy = this.searchMappedBy( tempClass.getSuperclass(), collectionTable );
|
||||
tempClass = tempClass.getSuperclass();
|
||||
EntityBinding tempClass = referencedClass;
|
||||
while ( (mappedBy == null) && (tempClass.getSuperEntityBinding() != null) ) {
|
||||
LOG.debugf(
|
||||
"Searching in superclass: %s",
|
||||
tempClass.getSuperEntityBinding().getEntity().getDescriptor().getName()
|
||||
);
|
||||
mappedBy = this.searchMappedBy( tempClass.getSuperEntityBinding(), collectionTable );
|
||||
tempClass = tempClass.getSuperEntityBinding();
|
||||
}
|
||||
}
|
||||
|
||||
if ( mappedBy == null ) {
|
||||
throw new MappingException(
|
||||
"Unable to read the mapped by attribute for " + propertyName + " in "
|
||||
+ referencedClass.getClassName() + "!"
|
||||
+ referencedClass.getEntity().getDescriptor().getName() + "!"
|
||||
);
|
||||
}
|
||||
|
||||
|
@ -941,15 +1003,14 @@ public final class CollectionMetadataGenerator {
|
|||
}
|
||||
|
||||
@SuppressWarnings({"unchecked"})
|
||||
private String searchMappedBy(PersistentClass referencedClass, Table collectionTable) {
|
||||
final Iterator<Property> properties = referencedClass.getPropertyIterator();
|
||||
while ( properties.hasNext() ) {
|
||||
final Property property = properties.next();
|
||||
if ( property.getValue() instanceof Collection ) {
|
||||
private String searchMappedBy(EntityBinding referencedClass, TableSpecification collectionTable) {
|
||||
for ( AttributeBinding attributeBinding : referencedClass.attributeBindings() ) {
|
||||
if ( !attributeBinding.getAttribute().isSingular() ) {
|
||||
// The equality is intentional. We want to find a collection property with the same collection table.
|
||||
//noinspection ObjectEquality
|
||||
if ( ((Collection) property.getValue()).getCollectionTable() == collectionTable ) {
|
||||
return property.getName();
|
||||
if ( ((PluralAttributeBinding) attributeBinding ).getPluralAttributeKeyBinding().getCollectionTable() ==
|
||||
collectionTable ) {
|
||||
return attributeBinding.getAttribute().getName();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -23,16 +23,16 @@
|
|||
*/
|
||||
package org.hibernate.envers.configuration.internal.metadata;
|
||||
|
||||
import java.util.Iterator;
|
||||
import java.util.Map;
|
||||
|
||||
import org.hibernate.EntityMode;
|
||||
import org.hibernate.envers.configuration.internal.metadata.reader.ComponentAuditingData;
|
||||
import org.hibernate.envers.configuration.internal.metadata.reader.PropertyAuditingData;
|
||||
import org.hibernate.envers.configuration.spi.AuditConfiguration;
|
||||
import org.hibernate.envers.internal.entities.mapper.CompositeMapperBuilder;
|
||||
import org.hibernate.envers.internal.tools.ReflectionTools;
|
||||
import org.hibernate.mapping.Component;
|
||||
import org.hibernate.mapping.Property;
|
||||
import org.hibernate.mapping.Value;
|
||||
import org.hibernate.metamodel.spi.binding.AttributeBinding;
|
||||
import org.hibernate.metamodel.spi.binding.CompositeAttributeBinding;
|
||||
import org.hibernate.metamodel.spi.binding.SingularAttributeBinding;
|
||||
|
||||
import org.dom4j.Element;
|
||||
|
||||
|
@ -43,29 +43,29 @@ import org.dom4j.Element;
|
|||
* @author Lukasz Zuchowski (author at zuchos dot com)
|
||||
*/
|
||||
public final class ComponentMetadataGenerator {
|
||||
private final AuditMetadataGenerator mainGenerator;
|
||||
private final AuditConfiguration.AuditConfigurationContext context;
|
||||
|
||||
ComponentMetadataGenerator(AuditMetadataGenerator auditMetadataGenerator) {
|
||||
private final AuditMetadataGenerator mainGenerator;
|
||||
|
||||
ComponentMetadataGenerator(AuditConfiguration.AuditConfigurationContext context, AuditMetadataGenerator auditMetadataGenerator) {
|
||||
this.context = context;
|
||||
mainGenerator = auditMetadataGenerator;
|
||||
}
|
||||
|
||||
@SuppressWarnings({"unchecked"})
|
||||
public void addComponent(
|
||||
Element parent, PropertyAuditingData propertyAuditingData,
|
||||
Value value, CompositeMapperBuilder mapper, String entityName,
|
||||
CompositeAttributeBinding compositeAttributeBinding, CompositeMapperBuilder mapper, String entityName,
|
||||
EntityXmlMappingData xmlMappingData, boolean firstPass) {
|
||||
final Component propComponent = (Component) value;
|
||||
|
||||
final Class componentClass;
|
||||
if (propComponent.isDynamic()) {
|
||||
componentClass = ReflectionTools.loadClass(
|
||||
Map.class.getCanonicalName(),
|
||||
mainGenerator.getClassLoaderService());
|
||||
|
||||
final EntityMode entityMode = compositeAttributeBinding.seekEntityBinding().getHierarchyDetails().getEntityMode();
|
||||
if ( entityMode == EntityMode.MAP ) {
|
||||
componentClass = context.getClassLoaderService().classForName( Map.class.getCanonicalName() );
|
||||
} else {
|
||||
componentClass = ReflectionTools.loadClass(
|
||||
propComponent.getComponentClassName(),
|
||||
mainGenerator.getClassLoaderService()
|
||||
// TODO: get rid of classloading.
|
||||
componentClass = context.getClassLoaderService().classForName(
|
||||
compositeAttributeBinding.getHibernateTypeDescriptor().getJavaTypeDescriptor().getName().fullName()
|
||||
);
|
||||
}
|
||||
final CompositeMapperBuilder componentMapper = mapper.addComponent(
|
||||
|
@ -77,18 +77,16 @@ public final class ComponentMetadataGenerator {
|
|||
final ComponentAuditingData componentAuditingData = (ComponentAuditingData) propertyAuditingData;
|
||||
|
||||
// Adding all properties of the component
|
||||
final Iterator<Property> properties = (Iterator<Property>) propComponent.getPropertyIterator();
|
||||
while (properties.hasNext()) {
|
||||
final Property property = properties.next();
|
||||
for ( AttributeBinding attributeBinding : compositeAttributeBinding.attributeBindings() ) {
|
||||
|
||||
final PropertyAuditingData componentPropertyAuditingData =
|
||||
componentAuditingData.getPropertyAuditingData(property.getName());
|
||||
componentAuditingData.getPropertyAuditingData( attributeBinding.getAttribute().getName() );
|
||||
|
||||
// Checking if that property is audited
|
||||
if (componentPropertyAuditingData != null) {
|
||||
mainGenerator.addValue(
|
||||
parent, property.getValue(), componentMapper, entityName, xmlMappingData,
|
||||
componentPropertyAuditingData, property.isInsertable(), firstPass, false
|
||||
parent, attributeBinding, componentMapper, entityName, xmlMappingData,
|
||||
componentPropertyAuditingData, firstPass, false
|
||||
);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -23,12 +23,11 @@
|
|||
*/
|
||||
package org.hibernate.envers.configuration.internal.metadata;
|
||||
|
||||
import java.util.Iterator;
|
||||
|
||||
import org.hibernate.MappingException;
|
||||
import org.hibernate.envers.ModificationStore;
|
||||
import org.hibernate.envers.RelationTargetAuditMode;
|
||||
import org.hibernate.envers.configuration.internal.metadata.reader.PropertyAuditingData;
|
||||
import org.hibernate.envers.configuration.spi.AuditConfiguration;
|
||||
import org.hibernate.envers.internal.entities.IdMappingData;
|
||||
import org.hibernate.envers.internal.entities.PropertyData;
|
||||
import org.hibernate.envers.internal.entities.mapper.SimpleMapperBuilder;
|
||||
|
@ -36,10 +35,14 @@ import org.hibernate.envers.internal.entities.mapper.id.EmbeddedIdMapper;
|
|||
import org.hibernate.envers.internal.entities.mapper.id.MultipleIdMapper;
|
||||
import org.hibernate.envers.internal.entities.mapper.id.SimpleIdMapperBuilder;
|
||||
import org.hibernate.envers.internal.entities.mapper.id.SingleIdMapper;
|
||||
import org.hibernate.envers.internal.tools.ReflectionTools;
|
||||
import org.hibernate.mapping.Component;
|
||||
import org.hibernate.mapping.PersistentClass;
|
||||
import org.hibernate.mapping.Property;
|
||||
import org.hibernate.id.EntityIdentifierNature;
|
||||
import org.hibernate.metamodel.spi.binding.AttributeBinding;
|
||||
import org.hibernate.metamodel.spi.binding.CompositeAttributeBinding;
|
||||
import org.hibernate.metamodel.spi.binding.EntityBinding;
|
||||
import org.hibernate.metamodel.spi.binding.EntityIdentifier;
|
||||
import org.hibernate.metamodel.spi.binding.ManyToOneAttributeBinding;
|
||||
import org.hibernate.metamodel.spi.binding.SingularAttributeBinding;
|
||||
import org.hibernate.metamodel.spi.binding.SingularNonAssociationAttributeBinding;
|
||||
import org.hibernate.type.ManyToOneType;
|
||||
import org.hibernate.type.Type;
|
||||
|
||||
|
@ -52,53 +55,57 @@ import org.dom4j.tree.DefaultElement;
|
|||
* @author Adam Warski (adam at warski dot org)
|
||||
*/
|
||||
public final class IdMetadataGenerator {
|
||||
private final AuditConfiguration.AuditConfigurationContext context;
|
||||
private final AuditMetadataGenerator mainGenerator;
|
||||
|
||||
IdMetadataGenerator(AuditMetadataGenerator auditMetadataGenerator) {
|
||||
IdMetadataGenerator(AuditConfiguration.AuditConfigurationContext context, AuditMetadataGenerator auditMetadataGenerator) {
|
||||
this.context = context;
|
||||
mainGenerator = auditMetadataGenerator;
|
||||
}
|
||||
|
||||
@SuppressWarnings({"unchecked"})
|
||||
private boolean addIdProperties(
|
||||
Element parent,
|
||||
Iterator<Property> properties,
|
||||
CompositeAttributeBinding compositeAttributeBinding,
|
||||
SimpleMapperBuilder mapper,
|
||||
boolean key,
|
||||
boolean audited) {
|
||||
while ( properties.hasNext() ) {
|
||||
final Property property = properties.next();
|
||||
final Type propertyType = property.getType();
|
||||
if ( !"_identifierMapper".equals( property.getName() ) ) {
|
||||
boolean added = false;
|
||||
if ( propertyType instanceof ManyToOneType ) {
|
||||
added = mainGenerator.getBasicMetadataGenerator().addManyToOne(
|
||||
parent,
|
||||
getIdPersistentPropertyAuditingData( property ),
|
||||
property.getValue(),
|
||||
mapper
|
||||
);
|
||||
//if ( compositeAttributeBinding.getAttribute().isSynthetic() ) {
|
||||
// return true;
|
||||
//}
|
||||
for ( AttributeBinding attributeBinding : compositeAttributeBinding.attributeBindings() ) {
|
||||
final Type propertyType = attributeBinding.getHibernateTypeDescriptor().getResolvedTypeMapping();
|
||||
final boolean added;
|
||||
if ( propertyType instanceof ManyToOneType ) {
|
||||
added = mainGenerator.getBasicMetadataGenerator().addManyToOne(
|
||||
parent,
|
||||
getIdPersistentPropertyAuditingData( attributeBinding ),
|
||||
(ManyToOneAttributeBinding) attributeBinding,
|
||||
mapper
|
||||
);
|
||||
}
|
||||
else {
|
||||
final SingularAttributeBinding singularAttributeBinding = (SingularAttributeBinding) attributeBinding;
|
||||
// Last but one parameter: ids are always insertable
|
||||
added = mainGenerator.getBasicMetadataGenerator().addBasic(
|
||||
parent,
|
||||
getIdPersistentPropertyAuditingData( singularAttributeBinding ),
|
||||
singularAttributeBinding.getHibernateTypeDescriptor(),
|
||||
singularAttributeBinding.getValues(),
|
||||
singularAttributeBinding.isIncludedInInsert(),
|
||||
mapper,
|
||||
key
|
||||
);
|
||||
}
|
||||
if ( !added ) {
|
||||
// If the entity is audited, and a non-supported id component is used, throwing an exception.
|
||||
// If the entity is not audited, then we simply don't support this entity, even in
|
||||
// target relation mode not audited.
|
||||
if ( audited ) {
|
||||
throw new MappingException( "Type not supported: " + propertyType.getClass().getName() );
|
||||
}
|
||||
else {
|
||||
// Last but one parameter: ids are always insertable
|
||||
added = mainGenerator.getBasicMetadataGenerator().addBasic(
|
||||
parent,
|
||||
getIdPersistentPropertyAuditingData( property ),
|
||||
property.getValue(),
|
||||
mapper,
|
||||
true,
|
||||
key
|
||||
);
|
||||
}
|
||||
if ( !added ) {
|
||||
// If the entity is audited, and a non-supported id component is used, throwing an exception.
|
||||
// If the entity is not audited, then we simply don't support this entity, even in
|
||||
// target relation mode not audited.
|
||||
if ( audited ) {
|
||||
throw new MappingException( "Type not supported: " + propertyType.getClass().getName() );
|
||||
}
|
||||
else {
|
||||
return false;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -107,31 +114,30 @@ public final class IdMetadataGenerator {
|
|||
}
|
||||
|
||||
@SuppressWarnings({"unchecked"})
|
||||
IdMappingData addId(PersistentClass pc, boolean audited) {
|
||||
IdMappingData addId(EntityBinding entityBinding, boolean audited) {
|
||||
// Xml mapping which will be used for relations
|
||||
final Element relIdMapping = new DefaultElement( "properties" );
|
||||
// Xml mapping which will be used for the primary key of the versions table
|
||||
final Element origIdMapping = new DefaultElement( "composite-id" );
|
||||
|
||||
final Property idProp = pc.getIdentifierProperty();
|
||||
final Component idMapper = pc.getIdentifierMapper();
|
||||
//final Property idProp = pc.getIdentifierProperty();
|
||||
//final Component idMapper = pc.getIdentifierMapper();
|
||||
|
||||
// Checking if the id mapping is supported
|
||||
if ( idMapper == null && idProp == null ) {
|
||||
return null;
|
||||
}
|
||||
//if ( idMapper == null && idProp == null ) {
|
||||
// return null;
|
||||
//}
|
||||
|
||||
final EntityIdentifier entityIdentifier = entityBinding.getHierarchyDetails().getEntityIdentifier();
|
||||
SimpleIdMapperBuilder mapper;
|
||||
if ( idMapper != null ) {
|
||||
if ( entityIdentifier.getLookupClassBinding().definedIdClass() ) {
|
||||
// Multiple id
|
||||
final Class componentClass = ReflectionTools.loadClass(
|
||||
( (Component) pc.getIdentifier() ).getComponentClassName(),
|
||||
mainGenerator.getClassLoaderService()
|
||||
);
|
||||
final Class componentClass = entityIdentifier.getLookupClassBinding().getIdClassType();
|
||||
|
||||
mapper = new MultipleIdMapper( componentClass );
|
||||
if ( !addIdProperties(
|
||||
relIdMapping,
|
||||
(Iterator<Property>) idMapper.getPropertyIterator(),
|
||||
(CompositeAttributeBinding) entityIdentifier.getAttributeBinding(),
|
||||
mapper,
|
||||
false,
|
||||
audited
|
||||
|
@ -142,7 +148,7 @@ public final class IdMetadataGenerator {
|
|||
// null mapper - the mapping where already added the first time, now we only want to generate the xml
|
||||
if ( !addIdProperties(
|
||||
origIdMapping,
|
||||
(Iterator<Property>) idMapper.getPropertyIterator(),
|
||||
(CompositeAttributeBinding) entityIdentifier.getAttributeBinding(),
|
||||
null,
|
||||
true,
|
||||
audited
|
||||
|
@ -150,17 +156,16 @@ public final class IdMetadataGenerator {
|
|||
return null;
|
||||
}
|
||||
}
|
||||
else if ( idProp.isComposite() ) {
|
||||
// Embedded id
|
||||
final Component idComponent = (Component) idProp.getValue();
|
||||
final Class embeddableClass = ReflectionTools.loadClass(
|
||||
idComponent.getComponentClassName(),
|
||||
mainGenerator.getClassLoaderService()
|
||||
else if ( entityIdentifier.getNature() == EntityIdentifierNature.AGGREGATED_COMPOSITE ) {
|
||||
// Embeddable id
|
||||
// TODO: get rid of classloading.
|
||||
final Class embeddableClass = context.getClassLoaderService().classForName(
|
||||
entityIdentifier.getAttributeBinding().getHibernateTypeDescriptor().getJavaTypeDescriptor().getName().fullName()
|
||||
);
|
||||
mapper = new EmbeddedIdMapper( getIdPropertyData( idProp ), embeddableClass );
|
||||
mapper = new EmbeddedIdMapper( getIdPropertyData( entityIdentifier.getAttributeBinding() ), embeddableClass );
|
||||
if ( !addIdProperties(
|
||||
relIdMapping,
|
||||
(Iterator<Property>) idComponent.getPropertyIterator(),
|
||||
(CompositeAttributeBinding) entityIdentifier.getAttributeBinding(),
|
||||
mapper,
|
||||
false,
|
||||
audited
|
||||
|
@ -171,7 +176,7 @@ public final class IdMetadataGenerator {
|
|||
// null mapper - the mapping where already added the first time, now we only want to generate the xml
|
||||
if ( !addIdProperties(
|
||||
origIdMapping,
|
||||
(Iterator<Property>) idComponent.getPropertyIterator(),
|
||||
(CompositeAttributeBinding) entityIdentifier.getAttributeBinding(),
|
||||
null,
|
||||
true,
|
||||
audited
|
||||
|
@ -186,25 +191,27 @@ public final class IdMetadataGenerator {
|
|||
// Last but one parameter: ids are always insertable
|
||||
mainGenerator.getBasicMetadataGenerator().addBasic(
|
||||
relIdMapping,
|
||||
getIdPersistentPropertyAuditingData( idProp ),
|
||||
idProp.getValue(),
|
||||
getIdPersistentPropertyAuditingData( entityIdentifier.getAttributeBinding() ),
|
||||
entityIdentifier.getAttributeBinding().getHibernateTypeDescriptor(),
|
||||
entityIdentifier.getAttributeBinding().getValues(),
|
||||
entityIdentifier.getAttributeBinding().isIncludedInInsert(),
|
||||
mapper,
|
||||
true,
|
||||
false
|
||||
);
|
||||
|
||||
// null mapper - the mapping where already added the first time, now we only want to generate the xml
|
||||
mainGenerator.getBasicMetadataGenerator().addBasic(
|
||||
origIdMapping,
|
||||
getIdPersistentPropertyAuditingData( idProp ),
|
||||
idProp.getValue(),
|
||||
getIdPersistentPropertyAuditingData( entityIdentifier.getAttributeBinding() ),
|
||||
entityIdentifier.getAttributeBinding().getHibernateTypeDescriptor(),
|
||||
entityIdentifier.getAttributeBinding().getValues(),
|
||||
entityIdentifier.getAttributeBinding().isIncludedInInsert(),
|
||||
null,
|
||||
true,
|
||||
true
|
||||
);
|
||||
}
|
||||
|
||||
origIdMapping.addAttribute( "name", mainGenerator.getVerEntCfg().getOriginalIdPropName() );
|
||||
origIdMapping.addAttribute( "name", context.getAuditEntitiesConfiguration().getOriginalIdPropName() );
|
||||
|
||||
// Adding a relation to the revision entity (effectively: the "revision number" property)
|
||||
mainGenerator.addRevisionInfoRelation( origIdMapping );
|
||||
|
@ -212,16 +219,18 @@ public final class IdMetadataGenerator {
|
|||
return new IdMappingData( mapper, origIdMapping, relIdMapping );
|
||||
}
|
||||
|
||||
private PropertyData getIdPropertyData(Property property) {
|
||||
private PropertyData getIdPropertyData(SingularNonAssociationAttributeBinding idAttributeBinding) {
|
||||
return new PropertyData(
|
||||
property.getName(), property.getName(), property.getPropertyAccessorName(),
|
||||
idAttributeBinding.getAttribute().getName(),
|
||||
idAttributeBinding.getAttribute().getName(),
|
||||
idAttributeBinding.getPropertyAccessorName(),
|
||||
ModificationStore.FULL
|
||||
);
|
||||
}
|
||||
|
||||
private PropertyAuditingData getIdPersistentPropertyAuditingData(Property property) {
|
||||
private PropertyAuditingData getIdPersistentPropertyAuditingData(AttributeBinding property) {
|
||||
return new PropertyAuditingData(
|
||||
property.getName(), property.getPropertyAccessorName(),
|
||||
property.getAttribute().getName(), property.getPropertyAccessorName(),
|
||||
ModificationStore.FULL, RelationTargetAuditMode.AUDITED, null, null, false
|
||||
);
|
||||
}
|
||||
|
|
|
@ -24,11 +24,7 @@
|
|||
package org.hibernate.envers.configuration.internal.metadata;
|
||||
|
||||
import org.hibernate.MappingException;
|
||||
import org.hibernate.mapping.JoinedSubclass;
|
||||
import org.hibernate.mapping.PersistentClass;
|
||||
import org.hibernate.mapping.SingleTableSubclass;
|
||||
import org.hibernate.mapping.Subclass;
|
||||
import org.hibernate.mapping.UnionSubclass;
|
||||
import org.hibernate.metamodel.spi.binding.EntityBinding;
|
||||
|
||||
/**
|
||||
* @author Adam Warski (adam at warski dot org)
|
||||
|
@ -40,30 +36,30 @@ public enum InheritanceType {
|
|||
TABLE_PER_CLASS;
|
||||
|
||||
/**
|
||||
* @param pc The class for which to get the inheritance type.
|
||||
* @param entityBinding The class for which to get the inheritance type.
|
||||
*
|
||||
* @return The inheritance type of this class. NONE, if this class does not inherit from
|
||||
* another persistent class.
|
||||
*/
|
||||
public static InheritanceType get(PersistentClass pc) {
|
||||
final PersistentClass superclass = pc.getSuperclass();
|
||||
if ( superclass == null ) {
|
||||
public static InheritanceType get(EntityBinding entityBinding) {
|
||||
final EntityBinding superEntityBinding = entityBinding.getSuperEntityBinding();
|
||||
if ( superEntityBinding == null ) {
|
||||
return InheritanceType.NONE;
|
||||
}
|
||||
|
||||
// We assume that every subclass is of the same type.
|
||||
final Subclass subclass = (Subclass) superclass.getSubclassIterator().next();
|
||||
final EntityBinding subEntityBinding = superEntityBinding.getDirectSubEntityBindings().get( 0 );
|
||||
|
||||
if ( subclass instanceof SingleTableSubclass ) {
|
||||
if ( subEntityBinding.getHierarchyDetails().getInheritanceType() == org.hibernate.metamodel.spi.binding.InheritanceType.SINGLE_TABLE ) {
|
||||
return InheritanceType.SINGLE;
|
||||
}
|
||||
else if ( subclass instanceof JoinedSubclass ) {
|
||||
else if ( subEntityBinding.getHierarchyDetails().getInheritanceType() == org.hibernate.metamodel.spi.binding.InheritanceType.JOINED ) {
|
||||
return InheritanceType.JOINED;
|
||||
}
|
||||
else if ( subclass instanceof UnionSubclass ) {
|
||||
else if ( subEntityBinding.getHierarchyDetails().getInheritanceType() == org.hibernate.metamodel.spi.binding.InheritanceType.TABLE_PER_CLASS ) {
|
||||
return InheritanceType.TABLE_PER_CLASS;
|
||||
}
|
||||
|
||||
throw new MappingException( "Unknown subclass class: " + subclass.getClass() );
|
||||
throw new MappingException( "Unknown subclass class: " + subEntityBinding.getClass() );
|
||||
}
|
||||
}
|
||||
|
|
|
@ -24,12 +24,14 @@
|
|||
package org.hibernate.envers.configuration.internal.metadata;
|
||||
|
||||
import java.util.Iterator;
|
||||
import java.util.List;
|
||||
import javax.persistence.JoinColumn;
|
||||
|
||||
import org.hibernate.AssertionFailure;
|
||||
import org.hibernate.envers.internal.tools.StringTools;
|
||||
import org.hibernate.mapping.Column;
|
||||
import org.hibernate.mapping.Formula;
|
||||
import org.hibernate.mapping.Selectable;
|
||||
import org.hibernate.metamodel.spi.relational.Column;
|
||||
import org.hibernate.metamodel.spi.relational.DerivedValue;
|
||||
import org.hibernate.metamodel.spi.relational.Value;
|
||||
|
||||
import org.dom4j.Attribute;
|
||||
import org.dom4j.Document;
|
||||
|
@ -46,9 +48,11 @@ public final class MetadataTools {
|
|||
|
||||
public static Element addNativelyGeneratedId(
|
||||
Element parent, String name, String type,
|
||||
boolean useRevisionEntityWithNativeId) {
|
||||
boolean useRevisionEntityWithNativeId,
|
||||
String idColumnName) {
|
||||
final Element idMapping = parent.addElement( "id" );
|
||||
idMapping.addAttribute( "name", name ).addAttribute( "type", type );
|
||||
MetadataTools.addColumn( idMapping, idColumnName, null, null, null, null, null, null, false );
|
||||
|
||||
final Element generatorMapping = idMapping.addElement( "generator" );
|
||||
if ( useRevisionEntityWithNativeId ) {
|
||||
|
@ -87,9 +91,11 @@ public final class MetadataTools {
|
|||
}
|
||||
|
||||
propMapping.addAttribute( "name", name );
|
||||
propMapping.addAttribute( "insert", Boolean.toString( insertable ) );
|
||||
propMapping.addAttribute( "update", Boolean.toString( updateable ) );
|
||||
|
||||
if ( !key ) {
|
||||
propMapping.addAttribute( "insert", Boolean.toString( insertable ) );
|
||||
propMapping.addAttribute( "update", Boolean.toString( updateable ) );
|
||||
}
|
||||
if ( type != null ) {
|
||||
propMapping.addAttribute( "type", type );
|
||||
}
|
||||
|
@ -151,7 +157,7 @@ public final class MetadataTools {
|
|||
public static Element addColumn(
|
||||
Element parent,
|
||||
String name,
|
||||
Integer length,
|
||||
Long length,
|
||||
Integer scale,
|
||||
Integer precision,
|
||||
String sqlType,
|
||||
|
@ -163,7 +169,7 @@ public final class MetadataTools {
|
|||
public static Element addColumn(
|
||||
Element parent,
|
||||
String name,
|
||||
Integer length,
|
||||
Long length,
|
||||
Integer scale,
|
||||
Integer precision,
|
||||
String sqlType,
|
||||
|
@ -215,16 +221,18 @@ public final class MetadataTools {
|
|||
classMapping.addAttribute( "discriminator-value", discriminatorValue );
|
||||
}
|
||||
|
||||
if ( !StringTools.isEmpty( auditTableData.getAuditTableName() ) ) {
|
||||
classMapping.addAttribute( "table", auditTableData.getAuditTableName() );
|
||||
}
|
||||
if ( !"subclass".equals( type ) ) {
|
||||
if ( !StringTools.isEmpty( auditTableData.getAuditTableName() ) ) {
|
||||
classMapping.addAttribute( "table", auditTableData.getAuditTableName() );
|
||||
}
|
||||
|
||||
if ( !StringTools.isEmpty( auditTableData.getSchema() ) ) {
|
||||
classMapping.addAttribute( "schema", auditTableData.getSchema() );
|
||||
}
|
||||
if ( !StringTools.isEmpty( auditTableData.getSchema() ) ) {
|
||||
classMapping.addAttribute( "schema", auditTableData.getSchema() );
|
||||
}
|
||||
|
||||
if ( !StringTools.isEmpty( auditTableData.getCatalog() ) ) {
|
||||
classMapping.addAttribute( "catalog", auditTableData.getCatalog() );
|
||||
if ( !StringTools.isEmpty( auditTableData.getCatalog() ) ) {
|
||||
classMapping.addAttribute( "catalog", auditTableData.getCatalog() );
|
||||
}
|
||||
}
|
||||
|
||||
if ( isAbstract != null ) {
|
||||
|
@ -282,13 +290,18 @@ public final class MetadataTools {
|
|||
return joinMapping;
|
||||
}
|
||||
|
||||
public static void addColumns(Element anyMapping, Iterator selectables) {
|
||||
while ( selectables.hasNext() ) {
|
||||
final Selectable selectable = (Selectable) selectables.next();
|
||||
if ( selectable.isFormula() ) {
|
||||
public static void addColumns(Element anyMapping, List<Column> columns) {
|
||||
for ( Column column : columns ) {
|
||||
addColumn( anyMapping, column );
|
||||
}
|
||||
}
|
||||
|
||||
public static void addValuesAsColumns(Element anyMapping, List<Value> values) {
|
||||
for ( Value value : values ) {
|
||||
if ( Value.ValueType.DERIVED_VALUE.equals( value.getValueType() ) ) {
|
||||
throw new FormulaNotSupportedException();
|
||||
}
|
||||
addColumn( anyMapping, (Column) selectable );
|
||||
addColumn( anyMapping, (Column) value );
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -303,14 +316,14 @@ public final class MetadataTools {
|
|||
public static void addColumn(Element anyMapping, Column column) {
|
||||
addColumn(
|
||||
anyMapping,
|
||||
column.getName(),
|
||||
column.getLength(),
|
||||
column.getScale(),
|
||||
column.getPrecision(),
|
||||
column.getColumnName().getText(),
|
||||
column.getSize().getLength(),
|
||||
column.getSize().getScale(),
|
||||
column.getSize().getPrecision(),
|
||||
column.getSqlType(),
|
||||
column.getCustomRead(),
|
||||
column.getCustomWrite(),
|
||||
column.isQuoted()
|
||||
column.getReadFragment(),
|
||||
column.getWriteFragment(),
|
||||
column.getColumnName().isQuoted()
|
||||
);
|
||||
}
|
||||
|
||||
|
@ -350,9 +363,11 @@ public final class MetadataTools {
|
|||
|
||||
if ( changeToKey ) {
|
||||
property.setName( "key-" + property.getName() );
|
||||
// "insert" and "update" attributes are not allowed on key-many-to-one or key-property elements.
|
||||
property.remove( property.attribute( "insert" ) );
|
||||
property.remove( property.attribute( "update" ) );
|
||||
}
|
||||
|
||||
if ( "property".equals( property.getName() ) ) {
|
||||
else if ( "property".equals( property.getName() ) ) {
|
||||
final Attribute insert = property.attribute( "insert" );
|
||||
insert.setText( Boolean.toString( insertable ) );
|
||||
}
|
||||
|
@ -366,25 +381,28 @@ public final class MetadataTools {
|
|||
* @param element Parent element.
|
||||
* @param formula Formula descriptor.
|
||||
*/
|
||||
public static void addFormula(Element element, Formula formula) {
|
||||
element.addElement( "formula" ).setText( formula.getText() );
|
||||
public static void addFormula(Element element, DerivedValue formula) {
|
||||
element.addElement( "formula" ).setText( formula.getExpression() );
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds all <code>column</code> or <code>formula</code> elements.
|
||||
*
|
||||
* @param element Parent element.
|
||||
* @param columnIterator Iterator pointing at {@link org.hibernate.mapping.Column} and/or
|
||||
* {@link org.hibernate.mapping.Formula} objects.
|
||||
* @param values List of {@link Column} and/or {@link DerivedValue} objects.
|
||||
*/
|
||||
public static void addColumnsOrFormulas(Element element, Iterator columnIterator) {
|
||||
while ( columnIterator.hasNext() ) {
|
||||
final Object o = columnIterator.next();
|
||||
if ( o instanceof Column ) {
|
||||
addColumn( element, (Column) o );
|
||||
public static void addColumnsOrFormulas(Element element, List<Value> values) {
|
||||
for ( Value value : values ) {
|
||||
if ( value.getValueType() == Value.ValueType.COLUMN ) {
|
||||
addColumn( element, (Column) value );
|
||||
}
|
||||
else if ( o instanceof Formula ) {
|
||||
addFormula( element, (Formula) o );
|
||||
else if ( value.getValueType() == Value.ValueType.DERIVED_VALUE ) {
|
||||
addFormula( element, (DerivedValue) value );
|
||||
}
|
||||
else {
|
||||
throw new AssertionFailure(
|
||||
String.format( "unknown type of value: %s", value.getValueType() )
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -395,18 +413,18 @@ public final class MetadataTools {
|
|||
public static abstract class ColumnNameIterator implements Iterator<String> {
|
||||
}
|
||||
|
||||
public static ColumnNameIterator getColumnNameIterator(final Iterator<Selectable> selectableIterator) {
|
||||
public static ColumnNameIterator getColumnNameIterator(final Iterator<Value> selectableIterator) {
|
||||
return new ColumnNameIterator() {
|
||||
public boolean hasNext() {
|
||||
return selectableIterator.hasNext();
|
||||
}
|
||||
|
||||
public String next() {
|
||||
final Selectable next = selectableIterator.next();
|
||||
if ( next.isFormula() ) {
|
||||
final Value next = selectableIterator.next();
|
||||
if ( next.getValueType() == Value.ValueType.DERIVED_VALUE ) {
|
||||
throw new FormulaNotSupportedException();
|
||||
}
|
||||
return ((Column) next).getName();
|
||||
return ((Column) next).getColumnName().getText();
|
||||
}
|
||||
|
||||
public void remove() {
|
||||
|
|
|
@ -37,6 +37,9 @@ import org.hibernate.envers.internal.tools.MappingTools;
|
|||
import org.hibernate.mapping.OneToOne;
|
||||
import org.hibernate.mapping.ToOne;
|
||||
import org.hibernate.mapping.Value;
|
||||
import org.hibernate.metamodel.internal.source.annotations.attribute.SingularAssociationAttribute;
|
||||
import org.hibernate.metamodel.spi.binding.OneToOneAttributeBinding;
|
||||
import org.hibernate.metamodel.spi.binding.SingularAssociationAttributeBinding;
|
||||
|
||||
import org.dom4j.Element;
|
||||
|
||||
|
@ -57,11 +60,10 @@ public final class ToOneRelationMetadataGenerator {
|
|||
void addToOne(
|
||||
Element parent,
|
||||
PropertyAuditingData propertyAuditingData,
|
||||
Value value,
|
||||
SingularAssociationAttributeBinding attributeBinding,
|
||||
CompositeMapperBuilder mapper,
|
||||
String entityName,
|
||||
boolean insertable) {
|
||||
final String referencedEntityName = ((ToOne) value).getReferencedEntityName();
|
||||
String entityName) {
|
||||
final String referencedEntityName = attributeBinding.getReferencedEntityName();
|
||||
|
||||
final IdMappingData idMapping = mainGenerator.getReferencedIdMappingData(
|
||||
entityName,
|
||||
|
@ -76,9 +78,10 @@ public final class ToOneRelationMetadataGenerator {
|
|||
final IdMapper relMapper = idMapping.getIdMapper().prefixMappedProperties( lastPropertyPrefix );
|
||||
|
||||
// Storing information about this relation
|
||||
boolean insertable = attributeBinding.isIncludedInInsert();
|
||||
mainGenerator.getEntitiesConfigurations().get( entityName ).addToOneRelation(
|
||||
propertyAuditingData.getName(), referencedEntityName, relMapper,
|
||||
insertable, MappingTools.ignoreNotFound( value )
|
||||
insertable, MappingTools.ignoreNotFound( attributeBinding )
|
||||
);
|
||||
|
||||
// If the property isn't insertable, checking if this is not a "fake" bidirectional many-to-one relationship,
|
||||
|
@ -104,7 +107,7 @@ public final class ToOneRelationMetadataGenerator {
|
|||
MetadataTools.prefixNamesInPropertyElement(
|
||||
properties,
|
||||
lastPropertyPrefix,
|
||||
MetadataTools.getColumnNameIterator( value.getColumnIterator() ),
|
||||
MetadataTools.getColumnNameIterator( attributeBinding.getValues().iterator() ),
|
||||
false,
|
||||
insertable
|
||||
);
|
||||
|
@ -127,11 +130,11 @@ public final class ToOneRelationMetadataGenerator {
|
|||
@SuppressWarnings({"unchecked"})
|
||||
void addOneToOneNotOwning(
|
||||
PropertyAuditingData propertyAuditingData,
|
||||
Value value,
|
||||
OneToOneAttributeBinding attributeBinding,
|
||||
CompositeMapperBuilder mapper,
|
||||
String entityName) {
|
||||
final OneToOne propertyValue = (OneToOne) value;
|
||||
final String owningReferencePropertyName = propertyValue.getReferencedPropertyName();
|
||||
final String owningReferencePropertyName =
|
||||
attributeBinding.getReferencedAttributeBinding().getAttribute().getName();
|
||||
|
||||
final EntityConfiguration configuration = mainGenerator.getEntitiesConfigurations().get( entityName );
|
||||
if ( configuration == null ) {
|
||||
|
@ -145,7 +148,7 @@ public final class ToOneRelationMetadataGenerator {
|
|||
}
|
||||
|
||||
final String lastPropertyPrefix = MappingTools.createToOneRelationPrefix( owningReferencePropertyName );
|
||||
final String referencedEntityName = propertyValue.getReferencedEntityName();
|
||||
final String referencedEntityName = attributeBinding.getReferencedEntityName();
|
||||
|
||||
// Generating the id mapper for the relation
|
||||
final IdMapper ownedIdMapper = ownedIdMapping.getIdMapper().prefixMappedProperties( lastPropertyPrefix );
|
||||
|
@ -153,7 +156,7 @@ public final class ToOneRelationMetadataGenerator {
|
|||
// Storing information about this relation
|
||||
mainGenerator.getEntitiesConfigurations().get( entityName ).addToOneNotOwningRelation(
|
||||
propertyAuditingData.getName(), owningReferencePropertyName, referencedEntityName,
|
||||
ownedIdMapper, MappingTools.ignoreNotFound( value )
|
||||
ownedIdMapper, MappingTools.ignoreNotFound( attributeBinding )
|
||||
);
|
||||
|
||||
// Adding mapper for the id
|
||||
|
@ -167,11 +170,10 @@ public final class ToOneRelationMetadataGenerator {
|
|||
@SuppressWarnings({"unchecked"})
|
||||
void addOneToOnePrimaryKeyJoinColumn(
|
||||
PropertyAuditingData propertyAuditingData,
|
||||
Value value,
|
||||
OneToOneAttributeBinding attributeBinding,
|
||||
CompositeMapperBuilder mapper,
|
||||
String entityName,
|
||||
boolean insertable) {
|
||||
final String referencedEntityName = ((ToOne) value).getReferencedEntityName();
|
||||
String entityName) {
|
||||
final String referencedEntityName = attributeBinding.getReferencedEntityName();
|
||||
|
||||
final IdMappingData idMapping = mainGenerator.getReferencedIdMappingData(
|
||||
entityName,
|
||||
|
@ -187,8 +189,8 @@ public final class ToOneRelationMetadataGenerator {
|
|||
|
||||
// Storing information about this relation
|
||||
mainGenerator.getEntitiesConfigurations().get( entityName ).addToOneRelation(
|
||||
propertyAuditingData.getName(), referencedEntityName, relMapper, insertable,
|
||||
MappingTools.ignoreNotFound( value )
|
||||
propertyAuditingData.getName(), referencedEntityName, relMapper, attributeBinding.isIncludedInInsert(),
|
||||
MappingTools.ignoreNotFound( attributeBinding )
|
||||
);
|
||||
|
||||
// Adding mapper for the id
|
||||
|
|
|
@ -24,19 +24,18 @@
|
|||
package org.hibernate.envers.configuration.internal.metadata.reader;
|
||||
|
||||
import java.lang.annotation.Annotation;
|
||||
import java.util.Iterator;
|
||||
|
||||
import org.hibernate.MappingException;
|
||||
import org.hibernate.annotations.common.reflection.ReflectionManager;
|
||||
import org.hibernate.annotations.common.reflection.XClass;
|
||||
import org.jboss.jandex.AnnotationInstance;
|
||||
import org.jboss.jandex.ClassInfo;
|
||||
|
||||
import org.hibernate.envers.AuditTable;
|
||||
import org.hibernate.envers.Audited;
|
||||
import org.hibernate.envers.ModificationStore;
|
||||
import org.hibernate.envers.SecondaryAuditTable;
|
||||
import org.hibernate.envers.SecondaryAuditTables;
|
||||
import org.hibernate.envers.configuration.internal.GlobalConfiguration;
|
||||
import org.hibernate.mapping.PersistentClass;
|
||||
import org.hibernate.mapping.Property;
|
||||
import org.hibernate.envers.configuration.spi.AuditConfiguration;
|
||||
import org.hibernate.envers.event.spi.EnversDotNames;
|
||||
import org.hibernate.metamodel.source.internal.annotations.util.JandexHelper;
|
||||
import org.hibernate.metamodel.spi.binding.AttributeBinding;
|
||||
import org.hibernate.metamodel.spi.binding.AttributeBindingContainer;
|
||||
import org.hibernate.metamodel.spi.binding.EntityBinding;
|
||||
|
||||
/**
|
||||
* A helper class to read versioning meta-data from annotations on a persistent class.
|
||||
|
@ -45,101 +44,8 @@ import org.hibernate.mapping.Property;
|
|||
* @author Sebastian Komander
|
||||
*/
|
||||
public final class AnnotationsMetadataReader {
|
||||
private final GlobalConfiguration globalCfg;
|
||||
private final ReflectionManager reflectionManager;
|
||||
private final PersistentClass pc;
|
||||
|
||||
/**
|
||||
* This object is filled with information read from annotations and returned by the <code>getVersioningData</code>
|
||||
* method.
|
||||
*/
|
||||
private final ClassAuditingData auditData;
|
||||
|
||||
public AnnotationsMetadataReader(
|
||||
GlobalConfiguration globalCfg, ReflectionManager reflectionManager,
|
||||
PersistentClass pc) {
|
||||
this.globalCfg = globalCfg;
|
||||
this.reflectionManager = reflectionManager;
|
||||
this.pc = pc;
|
||||
|
||||
auditData = new ClassAuditingData();
|
||||
}
|
||||
|
||||
private ModificationStore getDefaultAudited(XClass clazz) {
|
||||
final Audited defaultAudited = clazz.getAnnotation( Audited.class );
|
||||
|
||||
if ( defaultAudited != null ) {
|
||||
return defaultAudited.modStore();
|
||||
}
|
||||
else {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
private void addAuditTable(XClass clazz) {
|
||||
final AuditTable auditTable = clazz.getAnnotation( AuditTable.class );
|
||||
if ( auditTable != null ) {
|
||||
auditData.setAuditTable( auditTable );
|
||||
}
|
||||
else {
|
||||
auditData.setAuditTable( getDefaultAuditTable() );
|
||||
}
|
||||
}
|
||||
|
||||
private void addAuditSecondaryTables(XClass clazz) {
|
||||
// Getting information on secondary tables
|
||||
final SecondaryAuditTable secondaryVersionsTable1 = clazz.getAnnotation( SecondaryAuditTable.class );
|
||||
if ( secondaryVersionsTable1 != null ) {
|
||||
auditData.getSecondaryTableDictionary().put(
|
||||
secondaryVersionsTable1.secondaryTableName(),
|
||||
secondaryVersionsTable1.secondaryAuditTableName()
|
||||
);
|
||||
}
|
||||
|
||||
final SecondaryAuditTables secondaryAuditTables = clazz.getAnnotation( SecondaryAuditTables.class );
|
||||
if ( secondaryAuditTables != null ) {
|
||||
for ( SecondaryAuditTable secondaryAuditTable2 : secondaryAuditTables.value() ) {
|
||||
auditData.getSecondaryTableDictionary().put(
|
||||
secondaryAuditTable2.secondaryTableName(),
|
||||
secondaryAuditTable2.secondaryAuditTableName()
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public ClassAuditingData getAuditData() {
|
||||
if ( pc.getClassName() == null ) {
|
||||
return auditData;
|
||||
}
|
||||
|
||||
try {
|
||||
final XClass xclass = reflectionManager.classForName( pc.getClassName(), this.getClass() );
|
||||
|
||||
final ModificationStore defaultStore = getDefaultAudited( xclass );
|
||||
if ( defaultStore != null ) {
|
||||
auditData.setDefaultAudited( true );
|
||||
}
|
||||
|
||||
new AuditedPropertiesReader(
|
||||
defaultStore,
|
||||
new PersistentClassPropertiesSource( xclass ),
|
||||
auditData,
|
||||
globalCfg,
|
||||
reflectionManager,
|
||||
""
|
||||
).read();
|
||||
|
||||
addAuditTable( xclass );
|
||||
addAuditSecondaryTables( xclass );
|
||||
}
|
||||
catch (ClassNotFoundException e) {
|
||||
throw new MappingException( e );
|
||||
}
|
||||
|
||||
return auditData;
|
||||
}
|
||||
|
||||
private AuditTable defaultAuditTable = new AuditTable() {
|
||||
private static final AuditTable DEFAULT_AUDIT_TABLE = new AuditTable() {
|
||||
public String value() {
|
||||
return "";
|
||||
}
|
||||
|
@ -157,28 +63,136 @@ public final class AnnotationsMetadataReader {
|
|||
}
|
||||
};
|
||||
|
||||
private final AuditConfiguration.AuditConfigurationContext context;
|
||||
|
||||
public AnnotationsMetadataReader(AuditConfiguration.AuditConfigurationContext context) {
|
||||
this.context = context;
|
||||
}
|
||||
|
||||
private ModificationStore getDefaultAudited(ClassInfo classInfo) {
|
||||
final AnnotationInstance audited = JandexHelper.getSingleAnnotation(
|
||||
classInfo.annotations(),
|
||||
EnversDotNames.AUDITED,
|
||||
classInfo
|
||||
);
|
||||
if ( audited != null ) {
|
||||
return JandexHelper.getValue( audited, "modStore", ModificationStore.class, context.getClassLoaderService() );
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
private void addAuditTable(ClassInfo classInfo, ClassAuditingData auditData) {
|
||||
final AnnotationInstance auditTable = JandexHelper.getSingleAnnotation( classInfo, EnversDotNames.AUDIT_TABLE );
|
||||
if ( auditTable != null ) {
|
||||
auditData.setAuditTable(
|
||||
context.getAnnotationProxy(
|
||||
auditTable,
|
||||
AuditTable.class
|
||||
)
|
||||
);
|
||||
}
|
||||
else {
|
||||
auditData.setAuditTable( getDefaultAuditTable() );
|
||||
}
|
||||
}
|
||||
|
||||
private void addAuditSecondaryTables(ClassInfo classInfo, ClassAuditingData auditData) {
|
||||
// Getting information on secondary tables
|
||||
final AnnotationInstance secondaryAuditTable1 = JandexHelper.getSingleAnnotation(
|
||||
classInfo, EnversDotNames.SECONDARY_AUDIT_TABLE
|
||||
);
|
||||
if ( secondaryAuditTable1 != null ) {
|
||||
auditData.getSecondaryTableDictionary().put(
|
||||
JandexHelper.getValue(
|
||||
secondaryAuditTable1, "secondaryTableName", String.class, context.getClassLoaderService()
|
||||
),
|
||||
JandexHelper.getValue(
|
||||
secondaryAuditTable1, "secondaryAuditTableName", String.class, context.getClassLoaderService()
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
final AnnotationInstance secondaryAuditTables = JandexHelper.getSingleAnnotation( classInfo, EnversDotNames.SECONDARY_AUDIT_TABLES );
|
||||
if ( secondaryAuditTables != null ) {
|
||||
final AnnotationInstance[] secondaryAuditTableValues =
|
||||
JandexHelper.getValue( secondaryAuditTables, "value", AnnotationInstance[].class, context.getClassLoaderService() );
|
||||
for ( AnnotationInstance secondaryAuditTable : secondaryAuditTableValues ) {
|
||||
auditData.getSecondaryTableDictionary().put(
|
||||
JandexHelper.getValue(
|
||||
secondaryAuditTable, "secondaryTableName", String.class, context.getClassLoaderService()
|
||||
),
|
||||
JandexHelper.getValue(
|
||||
secondaryAuditTable, "secondaryAuditTableName", String.class, context.getClassLoaderService()
|
||||
)
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public ClassAuditingData getAuditData(EntityBinding entityBinding) {
|
||||
/**
|
||||
* This object is filled with information read from annotations and returned by the <code>getVersioningData</code>
|
||||
* method.
|
||||
*/
|
||||
final ClassAuditingData auditData = new ClassAuditingData();
|
||||
|
||||
if ( entityBinding.getEntity().getDescriptor() == null ) {
|
||||
// TODO: What is the case here? Test by throwing exception.
|
||||
return auditData;
|
||||
}
|
||||
|
||||
final PersistentClassPropertiesSource persistentClassPropertiesSource = new PersistentClassPropertiesSource(
|
||||
entityBinding,
|
||||
context.getClassInfo(
|
||||
entityBinding.getEntity().getDescriptor().getName().toString()
|
||||
)
|
||||
);
|
||||
|
||||
ModificationStore defaultStore = getDefaultAudited( persistentClassPropertiesSource.getClassInfo() );
|
||||
auditData.setDefaultAudited( defaultStore != null );
|
||||
|
||||
new AuditedPropertiesReader(
|
||||
context,
|
||||
auditData,
|
||||
persistentClassPropertiesSource,
|
||||
""
|
||||
).read();
|
||||
|
||||
addAuditTable( persistentClassPropertiesSource.getClassInfo(), auditData );
|
||||
addAuditSecondaryTables( persistentClassPropertiesSource.getClassInfo(), auditData );
|
||||
|
||||
return auditData;
|
||||
}
|
||||
|
||||
private AuditTable getDefaultAuditTable() {
|
||||
return defaultAuditTable;
|
||||
return DEFAULT_AUDIT_TABLE;
|
||||
}
|
||||
|
||||
private class PersistentClassPropertiesSource implements PersistentPropertiesSource {
|
||||
private final XClass xclass;
|
||||
private final EntityBinding entityBinding;
|
||||
private final ClassInfo classInfo;
|
||||
|
||||
private PersistentClassPropertiesSource(XClass xclass) {
|
||||
this.xclass = xclass;
|
||||
private PersistentClassPropertiesSource(EntityBinding entityBinding, ClassInfo classInfo) {
|
||||
this.entityBinding = entityBinding;
|
||||
this.classInfo = classInfo;
|
||||
}
|
||||
|
||||
@SuppressWarnings({"unchecked"})
|
||||
public Iterator<Property> getPropertyIterator() {
|
||||
return pc.getPropertyIterator();
|
||||
public Iterable<AttributeBinding> getNonIdAttributeBindings() {
|
||||
return entityBinding.getNonIdAttributeBindings();
|
||||
}
|
||||
|
||||
public Property getProperty(String propertyName) {
|
||||
return pc.getProperty( propertyName );
|
||||
public AttributeBinding getAttributeBinding(String attributeName) {
|
||||
return entityBinding.locateAttributeBinding( attributeName );
|
||||
}
|
||||
|
||||
public XClass getXClass() {
|
||||
return xclass;
|
||||
@Override
|
||||
public AttributeBindingContainer getAttributeBindingContainer() {
|
||||
return entityBinding;
|
||||
}
|
||||
|
||||
public ClassInfo getClassInfo() {
|
||||
return classInfo;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
File diff suppressed because it is too large
Load Diff
|
@ -25,6 +25,8 @@ package org.hibernate.envers.configuration.internal.metadata.reader;
|
|||
|
||||
import java.util.Map;
|
||||
|
||||
import org.jboss.jandex.AnnotationInstance;
|
||||
|
||||
import org.hibernate.envers.AuditTable;
|
||||
|
||||
import static org.hibernate.envers.internal.tools.Tools.newHashMap;
|
||||
|
|
|
@ -23,11 +23,17 @@
|
|||
*/
|
||||
package org.hibernate.envers.configuration.internal.metadata.reader;
|
||||
|
||||
import org.hibernate.annotations.common.reflection.ReflectionManager;
|
||||
import org.hibernate.annotations.common.reflection.XProperty;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
import org.jboss.jandex.AnnotationInstance;
|
||||
import org.jboss.jandex.DotName;
|
||||
|
||||
import org.hibernate.envers.Audited;
|
||||
import org.hibernate.envers.ModificationStore;
|
||||
import org.hibernate.envers.configuration.internal.GlobalConfiguration;
|
||||
import org.hibernate.envers.configuration.spi.AuditConfiguration;
|
||||
import org.hibernate.envers.event.spi.EnversDotNames;
|
||||
import org.hibernate.metamodel.spi.domain.Attribute;
|
||||
|
||||
/**
|
||||
* Reads the audited properties for components.
|
||||
|
@ -38,25 +44,29 @@ import org.hibernate.envers.configuration.internal.GlobalConfiguration;
|
|||
public class ComponentAuditedPropertiesReader extends AuditedPropertiesReader {
|
||||
|
||||
public ComponentAuditedPropertiesReader(
|
||||
ModificationStore defaultStore,
|
||||
PersistentPropertiesSource persistentPropertiesSource,
|
||||
AuditConfiguration.AuditConfigurationContext context,
|
||||
AuditedPropertiesHolder auditedPropertiesHolder,
|
||||
GlobalConfiguration globalCfg, ReflectionManager reflectionManager,
|
||||
PersistentPropertiesSource persistentPropertiesSource,
|
||||
String propertyNamePrefix) {
|
||||
super(
|
||||
defaultStore, persistentPropertiesSource, auditedPropertiesHolder,
|
||||
globalCfg, reflectionManager, propertyNamePrefix
|
||||
context, auditedPropertiesHolder, persistentPropertiesSource, propertyNamePrefix
|
||||
);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected boolean checkAudited(
|
||||
XProperty property,
|
||||
Attribute attribute,
|
||||
PropertyAuditingData propertyData,
|
||||
Audited allClassAudited) {
|
||||
// Checking if this property is explicitly audited or if all properties are.
|
||||
final Audited aud = property.getAnnotation( Audited.class );
|
||||
if ( aud != null ) {
|
||||
final Map<DotName, List<AnnotationInstance>> attributeAnnotations =
|
||||
getContext().locateAttributeAnnotations( attribute );
|
||||
// Checking if this property is explicitly audited or if all properties are.
|
||||
if ( attributeAnnotations.containsKey( EnversDotNames.AUDITED ) ) {
|
||||
final Audited aud = getContext().getAnnotationProxy(
|
||||
attributeAnnotations.get( EnversDotNames.AUDITED ).get( 0 ),
|
||||
Audited.class
|
||||
);
|
||||
propertyData.setStore( aud.modStore() );
|
||||
propertyData.setRelationTargetAuditMode( aud.targetAuditMode() );
|
||||
propertyData.setUsingModifiedFlag( checkUsingModifiedFlag( aud ) );
|
||||
|
|
|
@ -1,102 +0,0 @@
|
|||
package org.hibernate.envers.configuration.internal.metadata.reader;
|
||||
|
||||
import java.lang.annotation.Annotation;
|
||||
import java.util.Collection;
|
||||
|
||||
import org.hibernate.annotations.common.reflection.XClass;
|
||||
import org.hibernate.annotations.common.reflection.XProperty;
|
||||
|
||||
/**
|
||||
* This class prenteds to be property but in fact it represents entry in the map (for dynamic component)
|
||||
*
|
||||
* @author Lukasz Zuchowski (author at zuchos dot com)
|
||||
*/
|
||||
public class DynamicProperty implements XProperty {
|
||||
|
||||
private AuditedPropertiesReader.DynamicComponentSource source;
|
||||
private String propertyName;
|
||||
|
||||
public DynamicProperty(AuditedPropertiesReader.DynamicComponentSource source, String propertyName) {
|
||||
this.source = source;
|
||||
this.propertyName = propertyName;
|
||||
}
|
||||
|
||||
@Override
|
||||
public XClass getDeclaringClass() {
|
||||
return source.getXClass();
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getName() {
|
||||
return propertyName;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isCollection() {
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isArray() {
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Class<? extends Collection> getCollectionClass() {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public XClass getType() {
|
||||
return source.getXClass();
|
||||
}
|
||||
|
||||
@Override
|
||||
public XClass getElementClass() {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public XClass getClassOrElementClass() {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public XClass getMapKey() {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getModifiers() {
|
||||
return 0;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setAccessible(boolean accessible) {
|
||||
}
|
||||
|
||||
@Override
|
||||
public Object invoke(Object target, Object... parameters) {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isTypeResolved() {
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public <T extends Annotation> T getAnnotation(Class<T> annotationType) {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public <T extends Annotation> boolean isAnnotationPresent(Class<T> annotationType) {
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Annotation[] getAnnotations() {
|
||||
return new Annotation[0];
|
||||
}
|
||||
}
|
|
@ -24,9 +24,15 @@
|
|||
package org.hibernate.envers.configuration.internal.metadata.reader;
|
||||
|
||||
import java.util.Iterator;
|
||||
import java.util.List;
|
||||
|
||||
import org.jboss.jandex.ClassInfo;
|
||||
|
||||
import org.hibernate.annotations.common.reflection.XClass;
|
||||
import org.hibernate.mapping.Property;
|
||||
import org.hibernate.metamodel.spi.binding.AttributeBinding;
|
||||
import org.hibernate.metamodel.spi.binding.AttributeBindingContainer;
|
||||
import org.hibernate.metamodel.spi.domain.AttributeContainer;
|
||||
|
||||
/**
|
||||
* A source of data on persistent properties of a class or component.
|
||||
|
@ -34,9 +40,11 @@ import org.hibernate.mapping.Property;
|
|||
* @author Adam Warski (adam at warski dot org)
|
||||
*/
|
||||
public interface PersistentPropertiesSource {
|
||||
Iterator<Property> getPropertyIterator();
|
||||
Iterable<AttributeBinding> getNonIdAttributeBindings();
|
||||
|
||||
Property getProperty(String propertyName);
|
||||
AttributeBinding getAttributeBinding(String attributeName);
|
||||
|
||||
XClass getXClass();
|
||||
AttributeBindingContainer getAttributeBindingContainer();
|
||||
|
||||
ClassInfo getClassInfo();
|
||||
}
|
||||
|
|
|
@ -24,18 +24,21 @@
|
|||
package org.hibernate.envers.configuration.spi;
|
||||
|
||||
import java.util.HashSet;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Properties;
|
||||
import java.util.UUID;
|
||||
import java.util.WeakHashMap;
|
||||
|
||||
import org.jboss.jandex.AnnotationInstance;
|
||||
import org.jboss.jandex.ClassInfo;
|
||||
import org.jboss.jandex.DotName;
|
||||
import org.jboss.jandex.IndexView;
|
||||
|
||||
import org.hibernate.MappingException;
|
||||
import org.hibernate.annotations.common.reflection.ReflectionManager;
|
||||
import org.hibernate.boot.registry.classloading.spi.ClassLoaderService;
|
||||
import org.hibernate.cfg.Configuration;
|
||||
import org.hibernate.envers.configuration.internal.AuditEntitiesConfiguration;
|
||||
import org.hibernate.envers.configuration.internal.EntitiesConfigurator;
|
||||
import org.hibernate.envers.configuration.internal.GlobalConfiguration;
|
||||
import org.hibernate.envers.configuration.internal.RevisionInfoConfiguration;
|
||||
import org.hibernate.envers.configuration.internal.RevisionInfoConfigurationResult;
|
||||
import org.hibernate.envers.internal.entities.EntitiesConfigurations;
|
||||
import org.hibernate.envers.internal.entities.PropertyData;
|
||||
|
@ -46,8 +49,13 @@ import org.hibernate.envers.internal.synchronization.AuditProcessManager;
|
|||
import org.hibernate.envers.internal.tools.ReflectionTools;
|
||||
import org.hibernate.envers.strategy.AuditStrategy;
|
||||
import org.hibernate.envers.strategy.ValidityAuditStrategy;
|
||||
import org.hibernate.internal.util.ClassLoaderHelper;
|
||||
import org.hibernate.internal.util.ReflectHelper;
|
||||
import org.hibernate.metamodel.Metadata;
|
||||
import org.hibernate.metamodel.spi.binding.AttributeBinding;
|
||||
import org.hibernate.metamodel.spi.binding.AttributeBindingContainer;
|
||||
import org.hibernate.metamodel.spi.binding.EntityBinding;
|
||||
import org.hibernate.metamodel.spi.domain.Attribute;
|
||||
import org.hibernate.metamodel.spi.domain.AttributeContainer;
|
||||
import org.hibernate.property.Getter;
|
||||
|
||||
/**
|
||||
|
@ -101,45 +109,37 @@ public class AuditConfiguration {
|
|||
return classLoaderService;
|
||||
}
|
||||
|
||||
public AuditConfiguration(Configuration cfg) {
|
||||
this( cfg, null );
|
||||
}
|
||||
//public AuditConfiguration(Configuration cfg) {
|
||||
// this( cfg, null );
|
||||
//}
|
||||
|
||||
public AuditConfiguration(Configuration cfg, ClassLoaderService classLoaderService) {
|
||||
// TODO: Temporarily allow Envers to continuing using
|
||||
// hibernate-commons-annotations' for reflection and class loading.
|
||||
final ClassLoader tccl = Thread.currentThread().getContextClassLoader();
|
||||
Thread.currentThread().setContextClassLoader( ClassLoaderHelper.getContextClassLoader() );
|
||||
public AuditConfiguration(AuditConfigurationContext context) {
|
||||
this.globalCfg = context.getGlobalConfiguration();
|
||||
this.auditEntCfg = context.getAuditEntitiesConfiguration();
|
||||
|
||||
final Properties properties = cfg.getProperties();
|
||||
this.auditProcessManager = new AuditProcessManager( context.getRevisionInfoConfigurationResult().getRevisionInfoGenerator() );
|
||||
this.revisionInfoQueryCreator = context.getRevisionInfoConfigurationResult().getRevisionInfoQueryCreator();
|
||||
this.revisionInfoNumberReader = context.getRevisionInfoConfigurationResult().getRevisionInfoNumberReader();
|
||||
this.modifiedEntityNamesReader = context.getRevisionInfoConfigurationResult().getModifiedEntityNamesReader();
|
||||
|
||||
final ReflectionManager reflectionManager = cfg.getReflectionManager();
|
||||
this.globalCfg = new GlobalConfiguration( properties, classLoaderService );
|
||||
final RevisionInfoConfiguration revInfoCfg = new RevisionInfoConfiguration( globalCfg );
|
||||
final RevisionInfoConfigurationResult revInfoCfgResult = revInfoCfg.configure( cfg, reflectionManager );
|
||||
this.auditEntCfg = new AuditEntitiesConfiguration( properties, revInfoCfgResult.getRevisionInfoEntityName() );
|
||||
this.auditProcessManager = new AuditProcessManager( revInfoCfgResult.getRevisionInfoGenerator() );
|
||||
this.revisionInfoQueryCreator = revInfoCfgResult.getRevisionInfoQueryCreator();
|
||||
this.revisionInfoNumberReader = revInfoCfgResult.getRevisionInfoNumberReader();
|
||||
this.modifiedEntityNamesReader = revInfoCfgResult.getModifiedEntityNamesReader();
|
||||
this.classLoaderService = classLoaderService;
|
||||
this.auditStrategy = initializeAuditStrategy(
|
||||
revInfoCfgResult.getRevisionInfoClass(),
|
||||
revInfoCfgResult.getRevisionInfoTimestampData()
|
||||
context.getRevisionInfoConfigurationResult().getRevisionInfoClass(),
|
||||
context.getRevisionInfoConfigurationResult().getRevisionInfoTimestampData()
|
||||
);
|
||||
this.entCfg = new EntitiesConfigurator().configure(
|
||||
cfg, reflectionManager, globalCfg, auditEntCfg, auditStrategy, classLoaderService,
|
||||
revInfoCfgResult.getRevisionInfoXmlMapping(), revInfoCfgResult.getRevisionInfoRelationMapping()
|
||||
context,
|
||||
auditStrategy,
|
||||
context.getRevisionInfoConfigurationResult().getRevisionInfoXmlMapping(),
|
||||
context.getRevisionInfoConfigurationResult().getRevisionInfoRelationMapping()
|
||||
);
|
||||
|
||||
Thread.currentThread().setContextClassLoader( tccl );
|
||||
}
|
||||
|
||||
private AuditStrategy initializeAuditStrategy(Class<?> revisionInfoClass, PropertyData revisionInfoTimestampData) {
|
||||
AuditStrategy strategy;
|
||||
|
||||
try {
|
||||
Class<?> auditStrategyClass = null;
|
||||
Class<?> auditStrategyClass;
|
||||
try {
|
||||
auditStrategyClass = this.getClass().getClassLoader().loadClass( auditEntCfg.getAuditStrategyName() );
|
||||
}
|
||||
|
@ -167,20 +167,19 @@ public class AuditConfiguration {
|
|||
return strategy;
|
||||
}
|
||||
|
||||
private static final Map<Configuration, AuditConfiguration> CFGS = new WeakHashMap<Configuration, AuditConfiguration>();
|
||||
private static final Map<UUID, AuditConfiguration> CFGS = new WeakHashMap<UUID, AuditConfiguration>();
|
||||
|
||||
public synchronized static AuditConfiguration getFor(Configuration cfg) {
|
||||
return getFor( cfg, null );
|
||||
}
|
||||
//public synchronized static AuditConfiguration register(MetadataImplementor metadata) {
|
||||
// return register( metadata, null );
|
||||
//}
|
||||
|
||||
public synchronized static AuditConfiguration getFor(Configuration cfg, ClassLoaderService classLoaderService) {
|
||||
AuditConfiguration verCfg = CFGS.get( cfg );
|
||||
public synchronized static AuditConfiguration register(
|
||||
AuditConfigurationContext context, Metadata metadata) {
|
||||
AuditConfiguration verCfg = CFGS.get( metadata.getUUID() );
|
||||
|
||||
if ( verCfg == null ) {
|
||||
verCfg = new AuditConfiguration( cfg, classLoaderService );
|
||||
CFGS.put( cfg, verCfg );
|
||||
|
||||
cfg.buildMappings();
|
||||
verCfg = new AuditConfiguration( context );
|
||||
CFGS.put( metadata.getUUID(), verCfg );
|
||||
}
|
||||
|
||||
return verCfg;
|
||||
|
@ -188,7 +187,7 @@ public class AuditConfiguration {
|
|||
|
||||
public void destroy() {
|
||||
synchronized (AuditConfiguration.class) {
|
||||
for ( Map.Entry<Configuration, AuditConfiguration> c : new HashSet<Map.Entry<Configuration, AuditConfiguration>>(
|
||||
for ( Map.Entry<UUID, AuditConfiguration> c : new HashSet<Map.Entry<UUID, AuditConfiguration>>(
|
||||
CFGS.entrySet() ) ) {
|
||||
if ( c.getValue() == this ) { // this is nasty cleanup fix, whole static CFGS should be reworked
|
||||
CFGS.remove( c.getKey() );
|
||||
|
@ -197,4 +196,41 @@ public class AuditConfiguration {
|
|||
}
|
||||
classLoaderService = null;
|
||||
}
|
||||
|
||||
public interface AuditConfigurationContext {
|
||||
//InFlightMetadataCollector metadataCollector,
|
||||
//AdditionalJaxbRootProducer.AdditionalJaxbRootProducerContext context,
|
||||
//GlobalConfiguration globalCfg,
|
||||
//AuditEntitiesConfiguration verEntCfg,
|
||||
//AuditStrategy auditStrategy,
|
||||
|
||||
Metadata getMetadata();
|
||||
|
||||
EntityBinding getEntityBinding(String entityName);
|
||||
|
||||
EntityBinding getEntityBinding(ClassInfo classInfo);
|
||||
|
||||
IndexView getJandexIndex();
|
||||
|
||||
ClassInfo getClassInfo(String className);
|
||||
|
||||
ClassInfo getClassInfo(DotName classDotName);
|
||||
|
||||
ClassInfo getClassInfo(AttributeContainer attributeContainer);
|
||||
|
||||
ClassLoaderService getClassLoaderService();
|
||||
|
||||
<T> T getAnnotationProxy(AnnotationInstance annotationInstance, Class<T> annotationClass);
|
||||
|
||||
Map<DotName, List<AnnotationInstance>> locateAttributeAnnotations(Attribute attribute);
|
||||
// return coreConfiguration.locateAttributeAnnotations;
|
||||
|
||||
GlobalConfiguration getGlobalConfiguration();
|
||||
|
||||
AuditEntitiesConfiguration getAuditEntitiesConfiguration();
|
||||
|
||||
public RevisionInfoConfigurationResult getRevisionInfoConfigurationResult();
|
||||
|
||||
void addDocument(org.w3c.dom.Document document);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -25,11 +25,11 @@ package org.hibernate.envers.enhanced;
|
|||
|
||||
import java.util.HashSet;
|
||||
import java.util.Set;
|
||||
import javax.persistence.CollectionTable;
|
||||
import javax.persistence.Column;
|
||||
import javax.persistence.ElementCollection;
|
||||
import javax.persistence.FetchType;
|
||||
import javax.persistence.JoinColumn;
|
||||
import javax.persistence.JoinTable;
|
||||
import javax.persistence.MappedSuperclass;
|
||||
|
||||
import org.hibernate.annotations.Fetch;
|
||||
|
@ -46,7 +46,7 @@ import org.hibernate.envers.ModifiedEntityNames;
|
|||
@MappedSuperclass
|
||||
public class SequenceIdTrackingModifiedEntitiesRevisionEntity extends SequenceIdRevisionEntity {
|
||||
@ElementCollection(fetch = FetchType.EAGER)
|
||||
@JoinTable(name = "REVCHANGES", joinColumns = @JoinColumn(name = "REV"))
|
||||
@CollectionTable(name = "REVCHANGES", joinColumns = @JoinColumn(name = "REV"))
|
||||
@Column(name = "ENTITYNAME")
|
||||
@Fetch(FetchMode.JOIN)
|
||||
@ModifiedEntityNames
|
||||
|
|
|
@ -0,0 +1,36 @@
|
|||
package org.hibernate.envers.event.spi;
|
||||
|
||||
import org.jboss.jandex.DotName;
|
||||
|
||||
import org.hibernate.envers.AuditJoinTable;
|
||||
import org.hibernate.envers.AuditMappedBy;
|
||||
import org.hibernate.envers.AuditOverride;
|
||||
import org.hibernate.envers.AuditOverrides;
|
||||
import org.hibernate.envers.AuditTable;
|
||||
import org.hibernate.envers.Audited;
|
||||
import org.hibernate.envers.ModifiedEntityNames;
|
||||
import org.hibernate.envers.NotAudited;
|
||||
import org.hibernate.envers.RevisionEntity;
|
||||
import org.hibernate.envers.RevisionNumber;
|
||||
import org.hibernate.envers.RevisionTimestamp;
|
||||
import org.hibernate.envers.SecondaryAuditTable;
|
||||
import org.hibernate.envers.SecondaryAuditTables;
|
||||
|
||||
/**
|
||||
* @author Lukasz Antoniak (lukasz dot antoniak at gmail dot com)
|
||||
*/
|
||||
public interface EnversDotNames {
|
||||
DotName AUDITED = DotName.createSimple( Audited.class.getName() );
|
||||
DotName AUDIT_JOIN_TABLE = DotName.createSimple( AuditJoinTable.class.getName() );
|
||||
DotName AUDIT_MAPPED_BY = DotName.createSimple( AuditMappedBy.class.getName() );
|
||||
DotName AUDIT_OVERRIDE = DotName.createSimple( AuditOverride.class.getName() );
|
||||
DotName AUDIT_OVERRIDES = DotName.createSimple( AuditOverrides.class.getName() );
|
||||
DotName AUDIT_TABLE = DotName.createSimple( AuditTable.class.getName() );
|
||||
DotName MODIFIED_ENTITY_NAMES = DotName.createSimple( ModifiedEntityNames.class.getName() );
|
||||
DotName NOT_AUDITED = DotName.createSimple( NotAudited.class.getName() );
|
||||
DotName REVISION_ENTITY = DotName.createSimple( RevisionEntity.class.getName() );
|
||||
DotName REVISION_NUMBER = DotName.createSimple( RevisionNumber.class.getName() );
|
||||
DotName REVISION_TIMESTAMP = DotName.createSimple( RevisionTimestamp.class.getName() );
|
||||
DotName SECONDARY_AUDIT_TABLE = DotName.createSimple( SecondaryAuditTable.class.getName() );
|
||||
DotName SECONDARY_AUDIT_TABLES = DotName.createSimple( SecondaryAuditTables.class.getName() );
|
||||
}
|
|
@ -23,8 +23,10 @@
|
|||
*/
|
||||
package org.hibernate.envers.event.spi;
|
||||
|
||||
import org.hibernate.boot.registry.classloading.spi.ClassLoaderService;
|
||||
import org.hibernate.AssertionFailure;
|
||||
import org.hibernate.cfg.Configuration;
|
||||
import org.hibernate.engine.config.spi.ConfigurationService;
|
||||
import org.hibernate.engine.config.spi.StandardConverters;
|
||||
import org.hibernate.engine.spi.SessionFactoryImplementor;
|
||||
import org.hibernate.envers.configuration.spi.AuditConfiguration;
|
||||
import org.hibernate.event.service.spi.EventListenerRegistry;
|
||||
|
@ -73,11 +75,72 @@ public class EnversIntegrator implements Integrator {
|
|||
final EventListenerRegistry listenerRegistry = serviceRegistry.getService( EventListenerRegistry.class );
|
||||
listenerRegistry.addDuplicationStrategy( EnversListenerDuplicationStrategy.INSTANCE );
|
||||
|
||||
enversConfiguration = AuditConfiguration.getFor(
|
||||
configuration,
|
||||
serviceRegistry.getService(
|
||||
ClassLoaderService.class
|
||||
)
|
||||
if ( enversConfiguration.getEntCfg().hasAuditedEntities() ) {
|
||||
listenerRegistry.appendListeners(
|
||||
EventType.POST_DELETE, new EnversPostDeleteEventListenerImpl(
|
||||
enversConfiguration
|
||||
)
|
||||
);
|
||||
listenerRegistry.appendListeners(
|
||||
EventType.POST_INSERT, new EnversPostInsertEventListenerImpl(
|
||||
enversConfiguration
|
||||
)
|
||||
);
|
||||
listenerRegistry.appendListeners(
|
||||
EventType.POST_UPDATE, new EnversPostUpdateEventListenerImpl(
|
||||
enversConfiguration
|
||||
)
|
||||
);
|
||||
listenerRegistry.appendListeners(
|
||||
EventType.POST_COLLECTION_RECREATE,
|
||||
new EnversPostCollectionRecreateEventListenerImpl( enversConfiguration )
|
||||
);
|
||||
listenerRegistry.appendListeners(
|
||||
EventType.PRE_COLLECTION_REMOVE,
|
||||
new EnversPreCollectionRemoveEventListenerImpl( enversConfiguration )
|
||||
);
|
||||
listenerRegistry.appendListeners(
|
||||
EventType.PRE_COLLECTION_UPDATE,
|
||||
new EnversPreCollectionUpdateEventListenerImpl( enversConfiguration )
|
||||
);
|
||||
throw new AssertionFailure( "No longer implemented." );
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void disintegrate(SessionFactoryImplementor sessionFactory, SessionFactoryServiceRegistry serviceRegistry) {
|
||||
if ( enversConfiguration != null ) {
|
||||
enversConfiguration.destroy();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*
|
||||
* @see org.hibernate.integrator.spi.Integrator#integrate(org.hibernate.metamodel.spi.MetadataImplementor, org.hibernate.engine.spi.SessionFactoryImplementor, org.hibernate.service.spi.SessionFactoryServiceRegistry)
|
||||
*/
|
||||
@Override
|
||||
public void integrate(
|
||||
MetadataImplementor metadata,
|
||||
SessionFactoryImplementor sessionFactory,
|
||||
SessionFactoryServiceRegistry serviceRegistry) {
|
||||
final ConfigurationService configurationService = serviceRegistry.getService( ConfigurationService.class );
|
||||
final boolean autoRegister = configurationService.getSetting(
|
||||
AUTO_REGISTER,
|
||||
StandardConverters.BOOLEAN,
|
||||
true
|
||||
);
|
||||
if ( !autoRegister ) {
|
||||
LOG.debug( "Skipping Envers listener auto registration" );
|
||||
return;
|
||||
}
|
||||
|
||||
final EventListenerRegistry listenerRegistry = serviceRegistry.getService( EventListenerRegistry.class );
|
||||
listenerRegistry.addDuplicationStrategy( EnversListenerDuplicationStrategy.INSTANCE );
|
||||
|
||||
enversConfiguration = AuditConfiguration.register(
|
||||
null,
|
||||
metadata
|
||||
);
|
||||
|
||||
if ( enversConfiguration.getEntCfg().hasAuditedEntities() ) {
|
||||
|
@ -110,24 +173,4 @@ public class EnversIntegrator implements Integrator {
|
|||
);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void disintegrate(SessionFactoryImplementor sessionFactory, SessionFactoryServiceRegistry serviceRegistry) {
|
||||
if ( enversConfiguration != null ) {
|
||||
enversConfiguration.destroy();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*
|
||||
* @see org.hibernate.integrator.spi.Integrator#integrate(org.hibernate.metamodel.source.MetadataImplementor, org.hibernate.engine.spi.SessionFactoryImplementor, org.hibernate.service.spi.SessionFactoryServiceRegistry)
|
||||
*/
|
||||
@Override
|
||||
public void integrate(
|
||||
MetadataImplementor metadata,
|
||||
SessionFactoryImplementor sessionFactory,
|
||||
SessionFactoryServiceRegistry serviceRegistry) {
|
||||
// TODO: implement
|
||||
}
|
||||
}
|
||||
|
|
|
@ -0,0 +1,200 @@
|
|||
package org.hibernate.envers.event.spi;
|
||||
|
||||
import java.io.ByteArrayInputStream;
|
||||
import java.io.ByteArrayOutputStream;
|
||||
import java.io.InputStream;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
import javax.xml.transform.Result;
|
||||
import javax.xml.transform.Source;
|
||||
import javax.xml.transform.TransformerConfigurationException;
|
||||
import javax.xml.transform.TransformerException;
|
||||
import javax.xml.transform.TransformerFactory;
|
||||
import javax.xml.transform.dom.DOMSource;
|
||||
import javax.xml.transform.stream.StreamResult;
|
||||
|
||||
import org.jboss.jandex.AnnotationInstance;
|
||||
import org.jboss.jandex.ClassInfo;
|
||||
import org.jboss.jandex.DotName;
|
||||
import org.jboss.jandex.IndexView;
|
||||
import org.jboss.logging.Logger;
|
||||
|
||||
import org.hibernate.MappingException;
|
||||
import org.hibernate.boot.registry.classloading.spi.ClassLoaderService;
|
||||
import org.hibernate.envers.configuration.internal.AnnotationProxyBuilder;
|
||||
import org.hibernate.envers.configuration.internal.AuditEntitiesConfiguration;
|
||||
import org.hibernate.envers.configuration.internal.GlobalConfiguration;
|
||||
import org.hibernate.envers.configuration.internal.RevisionInfoConfiguration;
|
||||
import org.hibernate.envers.configuration.internal.RevisionInfoConfigurationResult;
|
||||
import org.hibernate.envers.configuration.spi.AuditConfiguration;
|
||||
import org.hibernate.internal.CoreMessageLogger;
|
||||
import org.hibernate.metamodel.Metadata;
|
||||
import org.hibernate.metamodel.internal.source.annotations.util.JandexHelper;
|
||||
import org.hibernate.metamodel.spi.AdditionalJaxbRootProducer;
|
||||
import org.hibernate.metamodel.spi.InFlightMetadataCollector;
|
||||
import org.hibernate.metamodel.spi.binding.EntityBinding;
|
||||
import org.hibernate.metamodel.spi.domain.Attribute;
|
||||
import org.hibernate.metamodel.spi.domain.AttributeContainer;
|
||||
import org.hibernate.xml.internal.jaxb.MappingXmlBinder;
|
||||
import org.hibernate.xml.spi.BindResult;
|
||||
import org.hibernate.xml.spi.Origin;
|
||||
import org.hibernate.xml.spi.SourceType;
|
||||
|
||||
/**
|
||||
* @author Lukasz Antoniak (lukasz dot antoniak at gmail dot com)
|
||||
*/
|
||||
public class EnversJaxbRootProducer implements AdditionalJaxbRootProducer {
|
||||
private static final CoreMessageLogger LOG = Logger.getMessageLogger(
|
||||
CoreMessageLogger.class,
|
||||
EnversJaxbRootProducer.class.getName()
|
||||
);
|
||||
|
||||
@Override
|
||||
public List<BindResult> produceRoots(
|
||||
final InFlightMetadataCollector metadataCollector,
|
||||
final AdditionalJaxbRootProducerContext additionalJaxbRootProducerContext) {
|
||||
|
||||
final AuditConfigurationContextImpl context = new AuditConfigurationContextImpl(
|
||||
metadataCollector,
|
||||
additionalJaxbRootProducerContext
|
||||
);
|
||||
|
||||
final AuditConfiguration configuration = AuditConfiguration.register( context, metadataCollector);
|
||||
return Collections.unmodifiableList( context.getBindResults() );
|
||||
}
|
||||
|
||||
|
||||
private class AuditConfigurationContextImpl implements AuditConfiguration.AuditConfigurationContext {
|
||||
|
||||
private final InFlightMetadataCollector metadataCollector;
|
||||
private final AdditionalJaxbRootProducerContext additionalJaxbRootProducerContext;
|
||||
private final AnnotationProxyBuilder annotationProxyBuilder = new AnnotationProxyBuilder();
|
||||
private final MappingXmlBinder jaxbProcessor;
|
||||
private final List<BindResult> bindResults = new ArrayList<BindResult>();
|
||||
private final Origin origin = new Origin( SourceType.DOM, Origin.UNKNOWN_FILE_PATH );
|
||||
private final GlobalConfiguration globalCfg;
|
||||
private final AuditEntitiesConfiguration auditEntCfg;
|
||||
private final RevisionInfoConfigurationResult revInfoCfgResult;
|
||||
|
||||
AuditConfigurationContextImpl(
|
||||
final InFlightMetadataCollector metadataCollector,
|
||||
final AdditionalJaxbRootProducerContext additionalJaxbRootProducerContext) {
|
||||
this.metadataCollector = metadataCollector;
|
||||
this.additionalJaxbRootProducerContext = additionalJaxbRootProducerContext;
|
||||
this.globalCfg = new GlobalConfiguration( additionalJaxbRootProducerContext.getServiceRegistry() );
|
||||
final RevisionInfoConfiguration revInfoCfg = new RevisionInfoConfiguration( globalCfg );
|
||||
this.revInfoCfgResult = revInfoCfg.configure( metadataCollector, additionalJaxbRootProducerContext );
|
||||
this.auditEntCfg = new AuditEntitiesConfiguration( additionalJaxbRootProducerContext.getServiceRegistry(), revInfoCfgResult.getRevisionInfoEntityName() );
|
||||
jaxbProcessor = new MappingXmlBinder(
|
||||
additionalJaxbRootProducerContext.getServiceRegistry()
|
||||
);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Metadata getMetadata() {
|
||||
return metadataCollector;
|
||||
}
|
||||
|
||||
@Override
|
||||
public EntityBinding getEntityBinding(String entityName) {
|
||||
return metadataCollector.getEntityBinding( entityName );
|
||||
}
|
||||
|
||||
@Override
|
||||
public EntityBinding getEntityBinding(final ClassInfo clazz) {
|
||||
// TODO: Is there a better way?
|
||||
// final AnnotationInstance jpaEntityAnnotation = JandexHelper.getSingleAnnotation( clazz, JPADotNames.ENTITY );
|
||||
// String entityName = JandexHelper.getValue( jpaEntityAnnotation, "name", String.class );
|
||||
// if ( entityName == null ) {
|
||||
// entityName = clazz.name().toString();
|
||||
// }
|
||||
return getEntityBinding( clazz.name().toString() );
|
||||
}
|
||||
|
||||
@Override
|
||||
public IndexView getJandexIndex() {
|
||||
return additionalJaxbRootProducerContext.getJandexIndex();
|
||||
}
|
||||
|
||||
@Override
|
||||
public ClassInfo getClassInfo(AttributeContainer attributeContainer) {
|
||||
return getClassInfo(
|
||||
attributeContainer.getDescriptor().getName().fullName()
|
||||
);
|
||||
}
|
||||
|
||||
@Override
|
||||
public ClassInfo getClassInfo(String className) {
|
||||
return getClassInfo( DotName.createSimple( className ) );
|
||||
}
|
||||
|
||||
@Override
|
||||
public ClassInfo getClassInfo(DotName classDotName) {
|
||||
return getJandexIndex().getClassByName( classDotName );
|
||||
}
|
||||
|
||||
@Override
|
||||
public ClassLoaderService getClassLoaderService() {
|
||||
return additionalJaxbRootProducerContext.getServiceRegistry().getService( ClassLoaderService.class );
|
||||
}
|
||||
|
||||
@Override
|
||||
public <T> T getAnnotationProxy(AnnotationInstance annotationInstance, Class<T> annotationClass) {
|
||||
return annotationProxyBuilder.getAnnotationProxy(
|
||||
annotationInstance, annotationClass, getClassLoaderService()
|
||||
);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Map<DotName, List<AnnotationInstance>> locateAttributeAnnotations(final Attribute attribute) {
|
||||
final ClassInfo classInfo = getClassInfo( attribute.getAttributeContainer() );
|
||||
return JandexHelper.getMemberAnnotations(
|
||||
classInfo,
|
||||
attribute.getName(),
|
||||
additionalJaxbRootProducerContext.getServiceRegistry()
|
||||
);
|
||||
}
|
||||
|
||||
@Override
|
||||
public GlobalConfiguration getGlobalConfiguration() {
|
||||
return globalCfg;
|
||||
}
|
||||
|
||||
@Override
|
||||
public AuditEntitiesConfiguration getAuditEntitiesConfiguration() {
|
||||
return auditEntCfg;
|
||||
}
|
||||
|
||||
@Override
|
||||
public RevisionInfoConfigurationResult getRevisionInfoConfigurationResult() {
|
||||
return revInfoCfgResult;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void addDocument(org.w3c.dom.Document document) {
|
||||
|
||||
ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
|
||||
Source xmlSource = new DOMSource( document );
|
||||
Result outputTarget = new StreamResult( outputStream );
|
||||
try {
|
||||
TransformerFactory.newInstance().newTransformer().transform(xmlSource, outputTarget);
|
||||
}
|
||||
catch ( TransformerConfigurationException ex ){
|
||||
throw new MappingException( ex );
|
||||
}
|
||||
catch ( TransformerException ex ) {
|
||||
throw new MappingException( ex );
|
||||
}
|
||||
InputStream is = new ByteArrayInputStream(outputStream.toByteArray());
|
||||
bindResults.add( jaxbProcessor.bind( is, origin ) );
|
||||
|
||||
}
|
||||
|
||||
private List<BindResult> getBindResults() {
|
||||
return bindResults;
|
||||
}
|
||||
}
|
||||
}
|
|
@ -23,11 +23,14 @@
|
|||
*/
|
||||
package org.hibernate.envers.internal.tools;
|
||||
|
||||
import org.hibernate.mapping.Collection;
|
||||
import org.hibernate.mapping.ManyToOne;
|
||||
import org.hibernate.mapping.OneToMany;
|
||||
import org.hibernate.mapping.ToOne;
|
||||
import org.hibernate.mapping.Value;
|
||||
import org.hibernate.metamodel.spi.binding.AttributeBinding;
|
||||
import org.hibernate.metamodel.spi.binding.ManyToOneAttributeBinding;
|
||||
import org.hibernate.metamodel.spi.binding.PluralAttributeAssociationElementBinding;
|
||||
import org.hibernate.metamodel.spi.binding.PluralAttributeBinding;
|
||||
import org.hibernate.metamodel.spi.binding.PluralAttributeElementBinding;
|
||||
import org.hibernate.metamodel.spi.binding.SingularAssociationAttributeBinding;
|
||||
import org.hibernate.metamodel.spi.binding.SingularAttributeBinding;
|
||||
import org.hibernate.type.EntityType;
|
||||
|
||||
/**
|
||||
* @author Adam Warski (adam at warski dot org)
|
||||
|
@ -51,30 +54,43 @@ public abstract class MappingTools {
|
|||
return referencePropertyName + "_";
|
||||
}
|
||||
|
||||
public static String getReferencedEntityName(Value value) {
|
||||
if ( value instanceof ToOne ) {
|
||||
return ((ToOne) value).getReferencedEntityName();
|
||||
public static String getReferencedEntityName(AttributeBinding attributeBinding) {
|
||||
if ( attributeBinding.getAttribute().isSingular() ) {
|
||||
final SingularAttributeBinding singularAttributeBinding = (SingularAssociationAttributeBinding) attributeBinding;
|
||||
if ( singularAttributeBinding.isAssociation() ) {
|
||||
return SingularAssociationAttributeBinding.class.cast( singularAttributeBinding ).getReferencedEntityName();
|
||||
}
|
||||
}
|
||||
else if ( value instanceof OneToMany ) {
|
||||
return ((OneToMany) value).getReferencedEntityName();
|
||||
else {
|
||||
final PluralAttributeBinding pluralAttributeBinding = (PluralAttributeBinding) attributeBinding;
|
||||
if ( pluralAttributeBinding.getPluralAttributeElementBinding().getNature().isAssociation() ) {
|
||||
final PluralAttributeAssociationElementBinding associationPluralAttributeElementBinding =
|
||||
(PluralAttributeAssociationElementBinding) pluralAttributeBinding.getPluralAttributeElementBinding();
|
||||
final EntityType entityType =
|
||||
(EntityType) associationPluralAttributeElementBinding
|
||||
.getHibernateTypeDescriptor()
|
||||
.getResolvedTypeMapping();
|
||||
return entityType.getAssociatedEntityName();
|
||||
}
|
||||
}
|
||||
else if ( value instanceof Collection ) {
|
||||
return getReferencedEntityName( ((Collection) value).getElement() );
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param value Persistent property.
|
||||
* @param attributeBinding Persistent property.
|
||||
* @return {@code false} if lack of associated entity shall raise an exception, {@code true} otherwise.
|
||||
*/
|
||||
public static boolean ignoreNotFound(Value value) {
|
||||
if ( value instanceof ManyToOne ) {
|
||||
return ( (ManyToOne) value ).isIgnoreNotFound();
|
||||
public static boolean ignoreNotFound(AttributeBinding attributeBinding) {
|
||||
if ( ManyToOneAttributeBinding.class.isInstance( attributeBinding )) {
|
||||
return ! ( (ManyToOneAttributeBinding) attributeBinding ).isNotFoundAnException();
|
||||
}
|
||||
else if ( value instanceof OneToMany ) {
|
||||
return ( (OneToMany) value ).isIgnoreNotFound();
|
||||
else if ( attributeBinding instanceof PluralAttributeBinding ) {
|
||||
final PluralAttributeBinding pluralAttributeBinding = (PluralAttributeBinding) attributeBinding;
|
||||
final PluralAttributeElementBinding elementBinding = pluralAttributeBinding.getPluralAttributeElementBinding();
|
||||
if ( elementBinding.getNature() == PluralAttributeElementBinding.Nature.ONE_TO_MANY ) {
|
||||
// TODO: FIX THIS!!!
|
||||
//return !( (OneToManyPluralAttributeElementBinding) elementBinding ).isNotFoundAnException();
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
|
|
@ -126,7 +126,7 @@ public abstract class ReflectionTools {
|
|||
*
|
||||
* @param name Fully qualified class name.
|
||||
* @param classLoaderService Class loading service. Passing {@code null} reference
|
||||
* in case of {@link AuditConfiguration#getFor(Configuration)} usage.
|
||||
* in case of {@link AuditConfiguration#register(Configuration)} usage.
|
||||
*
|
||||
* @return The cass reference.
|
||||
*
|
||||
|
|
|
@ -32,6 +32,13 @@ import java.util.List;
|
|||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
|
||||
import org.jboss.jandex.AnnotationTarget;
|
||||
import org.jboss.jandex.ClassInfo;
|
||||
import org.jboss.jandex.FieldInfo;
|
||||
import org.jboss.jandex.IndexView;
|
||||
import org.jboss.jandex.MethodInfo;
|
||||
|
||||
import org.hibernate.AssertionFailure;
|
||||
import org.hibernate.envers.tools.Pair;
|
||||
|
||||
/**
|
||||
|
@ -100,4 +107,21 @@ public abstract class Tools {
|
|||
|
||||
return ret;
|
||||
}
|
||||
|
||||
public static boolean isFieldOrPropertyOfClass(AnnotationTarget target, ClassInfo clazz, IndexView jandexIndex) {
|
||||
final ClassInfo enclosingClass;
|
||||
if ( target instanceof FieldInfo ) {
|
||||
final FieldInfo field = (FieldInfo) target;
|
||||
enclosingClass = field.declaringClass();
|
||||
}
|
||||
else if ( target instanceof MethodInfo ) {
|
||||
final MethodInfo method = (MethodInfo) target;
|
||||
enclosingClass = method.declaringClass();
|
||||
}
|
||||
else {
|
||||
throw new AssertionFailure( "Unexpected annotation target " + target.toString() );
|
||||
}
|
||||
return enclosingClass.equals( clazz ) || jandexIndex.getAllKnownSubclasses( clazz.name() ).contains( enclosingClass );
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -24,11 +24,27 @@
|
|||
package org.hibernate.envers.tools.hbm2ddl;
|
||||
|
||||
import java.sql.Connection;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Properties;
|
||||
|
||||
import org.jboss.jandex.AnnotationInstance;
|
||||
import org.jboss.jandex.ClassInfo;
|
||||
import org.jboss.jandex.DotName;
|
||||
import org.jboss.jandex.IndexView;
|
||||
import org.w3c.dom.Document;
|
||||
|
||||
import org.hibernate.HibernateException;
|
||||
import org.hibernate.boot.registry.classloading.spi.ClassLoaderService;
|
||||
import org.hibernate.cfg.Configuration;
|
||||
import org.hibernate.envers.configuration.internal.AuditEntitiesConfiguration;
|
||||
import org.hibernate.envers.configuration.internal.GlobalConfiguration;
|
||||
import org.hibernate.envers.configuration.internal.RevisionInfoConfigurationResult;
|
||||
import org.hibernate.envers.configuration.spi.AuditConfiguration;
|
||||
import org.hibernate.metamodel.Metadata;
|
||||
import org.hibernate.metamodel.spi.MetadataImplementor;
|
||||
import org.hibernate.metamodel.spi.binding.AttributeBinding;
|
||||
import org.hibernate.metamodel.spi.binding.EntityBinding;
|
||||
import org.hibernate.service.ServiceRegistry;
|
||||
import org.hibernate.tool.hbm2ddl.SchemaExport;
|
||||
|
||||
|
@ -38,33 +54,11 @@ import org.hibernate.tool.hbm2ddl.SchemaExport;
|
|||
public class EnversSchemaGenerator {
|
||||
private final SchemaExport export;
|
||||
|
||||
public EnversSchemaGenerator(ServiceRegistry serviceRegistry, Configuration configuration) {
|
||||
configuration = configureAuditing( configuration );
|
||||
export = new SchemaExport( serviceRegistry, configuration );
|
||||
}
|
||||
|
||||
public EnversSchemaGenerator(Configuration configuration) {
|
||||
configuration = configureAuditing( configuration );
|
||||
export = new SchemaExport( configuration );
|
||||
}
|
||||
|
||||
public EnversSchemaGenerator(Configuration configuration, Properties properties) throws HibernateException {
|
||||
configuration = configureAuditing( configuration );
|
||||
export = new SchemaExport( configuration, properties );
|
||||
}
|
||||
|
||||
public EnversSchemaGenerator(Configuration configuration, Connection connection) throws HibernateException {
|
||||
configuration = configureAuditing( configuration );
|
||||
export = new SchemaExport( configuration, connection );
|
||||
public EnversSchemaGenerator(MetadataImplementor metadata) {
|
||||
export = new SchemaExport( metadata );
|
||||
}
|
||||
|
||||
public SchemaExport export() {
|
||||
return export;
|
||||
}
|
||||
|
||||
private Configuration configureAuditing(Configuration configuration) {
|
||||
configuration.buildMappings();
|
||||
AuditConfiguration.getFor( configuration );
|
||||
return configuration;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -0,0 +1 @@
|
|||
org.hibernate.envers.event.spi.EnversJaxbRootProducer
|
|
@ -52,6 +52,7 @@ import org.hibernate.jpa.test.PersistenceUnitDescriptorAdapter;
|
|||
|
||||
import org.junit.After;
|
||||
|
||||
import org.hibernate.metamodel.spi.MetadataImplementor;
|
||||
import org.hibernate.testing.AfterClassOnce;
|
||||
import org.hibernate.testing.BeforeClassOnce;
|
||||
import org.hibernate.testing.jta.TestingJtaPlatformImpl;
|
||||
|
@ -85,8 +86,8 @@ public abstract class BaseEnversJPAFunctionalTestCase extends AbstractEnversTest
|
|||
return serviceRegistry;
|
||||
}
|
||||
|
||||
protected Configuration getCfg() {
|
||||
return entityManagerFactoryBuilder.getHibernateConfiguration();
|
||||
protected MetadataImplementor getMetadata() {
|
||||
return entityManagerFactoryBuilder.getMetadata();
|
||||
}
|
||||
|
||||
@BeforeClassOnce
|
||||
|
|
|
@ -2,6 +2,7 @@ package org.hibernate.envers.test.entities.collection;
|
|||
|
||||
import javax.persistence.Column;
|
||||
import javax.persistence.Entity;
|
||||
import javax.persistence.ForeignKey;
|
||||
import javax.persistence.GeneratedValue;
|
||||
import javax.persistence.GenerationType;
|
||||
import javax.persistence.Id;
|
||||
|
@ -9,7 +10,6 @@ import javax.persistence.JoinColumn;
|
|||
import javax.persistence.ManyToOne;
|
||||
import javax.persistence.Version;
|
||||
|
||||
import org.hibernate.annotations.ForeignKey;
|
||||
import org.hibernate.envers.Audited;
|
||||
import org.hibernate.envers.NotAudited;
|
||||
|
||||
|
@ -29,8 +29,7 @@ public class MultipleCollectionRefEntity1 {
|
|||
private String text;
|
||||
|
||||
@ManyToOne
|
||||
@JoinColumn(name = "MCE_ID", nullable = false, insertable = false, updatable = false)
|
||||
@ForeignKey(name = "FK_RE1_MCE")
|
||||
@JoinColumn(name = "MCE_ID", nullable = false, insertable = false, updatable = false, foreignKey = @ForeignKey(name = "FK_RE1_MCE") )
|
||||
@NotAudited
|
||||
private MultipleCollectionEntity multipleCollectionEntity;
|
||||
|
||||
|
|
|
@ -2,6 +2,7 @@ package org.hibernate.envers.test.entities.collection;
|
|||
|
||||
import javax.persistence.Column;
|
||||
import javax.persistence.Entity;
|
||||
import javax.persistence.ForeignKey;
|
||||
import javax.persistence.GeneratedValue;
|
||||
import javax.persistence.GenerationType;
|
||||
import javax.persistence.Id;
|
||||
|
@ -9,7 +10,6 @@ import javax.persistence.JoinColumn;
|
|||
import javax.persistence.ManyToOne;
|
||||
import javax.persistence.Version;
|
||||
|
||||
import org.hibernate.annotations.ForeignKey;
|
||||
import org.hibernate.envers.Audited;
|
||||
import org.hibernate.envers.NotAudited;
|
||||
|
||||
|
@ -29,8 +29,7 @@ public class MultipleCollectionRefEntity2 {
|
|||
private String text;
|
||||
|
||||
@ManyToOne
|
||||
@JoinColumn(name = "MCE_ID", nullable = false, insertable = false, updatable = false)
|
||||
@ForeignKey(name = "FK_RE2_MCE")
|
||||
@JoinColumn(name = "MCE_ID", nullable = false, insertable = false, updatable = false, foreignKey = @ForeignKey(name = "FK_RE2_MCE") )
|
||||
@NotAudited
|
||||
private MultipleCollectionEntity multipleCollectionEntity;
|
||||
|
||||
|
|
|
@ -27,10 +27,10 @@ import javax.persistence.ElementCollection;
|
|||
import javax.persistence.Entity;
|
||||
import javax.persistence.GeneratedValue;
|
||||
import javax.persistence.Id;
|
||||
import javax.persistence.OrderColumn;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
import org.hibernate.annotations.IndexColumn;
|
||||
import org.hibernate.envers.Audited;
|
||||
|
||||
/**
|
||||
|
@ -44,7 +44,7 @@ public class StringListEntity {
|
|||
|
||||
@Audited
|
||||
@ElementCollection
|
||||
@IndexColumn(name = "list_index")
|
||||
@OrderColumn(name = "list_index")
|
||||
private List<String> strings;
|
||||
|
||||
public StringListEntity() {
|
||||
|
|
|
@ -1,10 +1,12 @@
|
|||
package org.hibernate.envers.test.entities.components;
|
||||
|
||||
import javax.persistence.Embeddable;
|
||||
import javax.persistence.Embedded;
|
||||
|
||||
/**
|
||||
* @author Erik-Berndt Scheper
|
||||
*/
|
||||
@Embeddable
|
||||
public class DefaultValueComponent1 {
|
||||
|
||||
private String str1;
|
||||
|
|
|
@ -1,9 +1,12 @@
|
|||
package org.hibernate.envers.test.entities.components;
|
||||
|
||||
|
||||
import javax.persistence.Embeddable;
|
||||
|
||||
/**
|
||||
* @author Erik-Berndt Scheper
|
||||
*/
|
||||
@Embeddable
|
||||
public class DefaultValueComponent2 {
|
||||
|
||||
private String str1 = "defaultValue";
|
||||
|
|
|
@ -33,8 +33,7 @@ import java.util.SortedSet;
|
|||
import java.util.TreeMap;
|
||||
import java.util.TreeSet;
|
||||
|
||||
import org.hibernate.annotations.Sort;
|
||||
import org.hibernate.annotations.SortType;
|
||||
import org.hibernate.annotations.SortComparator;
|
||||
import org.hibernate.envers.Audited;
|
||||
import org.hibernate.envers.test.entities.StrTestEntity;
|
||||
import org.hibernate.envers.test.entities.StrTestEntityComparator;
|
||||
|
@ -54,12 +53,12 @@ public class SortedSetEntity {
|
|||
|
||||
@Audited
|
||||
@ManyToMany
|
||||
@Sort(type = SortType.COMPARATOR, comparator = StrTestEntityComparator.class)
|
||||
@SortComparator(value = StrTestEntityComparator.class)
|
||||
private SortedSet<StrTestEntity> sortedSet = new TreeSet<StrTestEntity>( StrTestEntityComparator.INSTANCE );
|
||||
@Audited
|
||||
@ElementCollection
|
||||
@MapKeyJoinColumn
|
||||
@Sort(type = SortType.COMPARATOR, comparator = StrTestEntityComparator.class)
|
||||
@SortComparator(value = StrTestEntityComparator.class)
|
||||
private SortedMap<StrTestEntity, String> sortedMap = new TreeMap<StrTestEntity, String>( StrTestEntityComparator.INSTANCE );
|
||||
|
||||
public SortedSetEntity() {
|
||||
|
|
|
@ -5,12 +5,12 @@ import javax.persistence.GeneratedValue;
|
|||
import javax.persistence.Id;
|
||||
import javax.persistence.JoinColumn;
|
||||
import javax.persistence.OneToMany;
|
||||
import javax.persistence.OrderColumn;
|
||||
import javax.persistence.Table;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
|
||||
import org.hibernate.annotations.IndexColumn;
|
||||
import org.hibernate.envers.AuditMappedBy;
|
||||
import org.hibernate.envers.Audited;
|
||||
|
||||
|
@ -32,7 +32,7 @@ public class IndexedListJoinColumnBidirectionalRefIngEntity {
|
|||
|
||||
@OneToMany
|
||||
@JoinColumn(name = "indexed_join_column")
|
||||
@IndexColumn(name = "indexed_index")
|
||||
@OrderColumn(name = "indexed_index")
|
||||
@AuditMappedBy(mappedBy = "owner", positionMappedBy = "position")
|
||||
private List<IndexedListJoinColumnBidirectionalRefEdEntity> references;
|
||||
|
||||
|
|
|
@ -7,12 +7,12 @@ import javax.persistence.Inheritance;
|
|||
import javax.persistence.InheritanceType;
|
||||
import javax.persistence.JoinColumn;
|
||||
import javax.persistence.OneToMany;
|
||||
import javax.persistence.OrderColumn;
|
||||
import javax.persistence.Table;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
|
||||
import org.hibernate.annotations.IndexColumn;
|
||||
import org.hibernate.envers.AuditMappedBy;
|
||||
import org.hibernate.envers.Audited;
|
||||
|
||||
|
@ -35,7 +35,7 @@ public abstract class ParentIndexedListJoinColumnBidirectionalRefIngEntity {
|
|||
|
||||
@OneToMany
|
||||
@JoinColumn(name = "indexed_join_column")
|
||||
@IndexColumn(name = "indexed_index")
|
||||
@OrderColumn(name = "indexed_index")
|
||||
@AuditMappedBy(mappedBy = "owner", positionMappedBy = "position")
|
||||
private List<ParentOwnedIndexedListJoinColumnBidirectionalRefEdEntity> references;
|
||||
|
||||
|
|
|
@ -1,12 +1,12 @@
|
|||
package org.hibernate.envers.test.entities.reventity.trackmodifiedentities;
|
||||
|
||||
import javax.persistence.CollectionTable;
|
||||
import javax.persistence.Column;
|
||||
import javax.persistence.ElementCollection;
|
||||
import javax.persistence.Entity;
|
||||
import javax.persistence.GeneratedValue;
|
||||
import javax.persistence.Id;
|
||||
import javax.persistence.JoinColumn;
|
||||
import javax.persistence.JoinTable;
|
||||
import javax.persistence.Table;
|
||||
import java.util.Set;
|
||||
|
||||
|
@ -44,7 +44,7 @@ public class AnnotatedTrackingRevisionEntity {
|
|||
private long customTimestamp;
|
||||
|
||||
@ElementCollection
|
||||
@JoinTable(name = "REVCHANGES", joinColumns = @JoinColumn(name = "REV"))
|
||||
@CollectionTable(name = "REVCHANGES", joinColumns = @JoinColumn(name = "REV"))
|
||||
@Column(name = "ENTITYNAME")
|
||||
@ModifiedEntityNames
|
||||
private Set<String> entityNames;
|
||||
|
|
|
@ -23,12 +23,13 @@
|
|||
*/
|
||||
package org.hibernate.envers.test.integration.accesstype;
|
||||
|
||||
import javax.persistence.Access;
|
||||
import javax.persistence.AccessType;
|
||||
import javax.persistence.Entity;
|
||||
import javax.persistence.GeneratedValue;
|
||||
import javax.persistence.Id;
|
||||
import javax.persistence.Transient;
|
||||
|
||||
import org.hibernate.annotations.AccessType;
|
||||
import org.hibernate.envers.Audited;
|
||||
|
||||
/**
|
||||
|
@ -40,7 +41,7 @@ public class MixedAccessTypeEntity {
|
|||
@GeneratedValue
|
||||
private Integer id;
|
||||
|
||||
@AccessType("property")
|
||||
@Access(value = AccessType.PROPERTY)
|
||||
private String data;
|
||||
|
||||
@Transient
|
||||
|
|
|
@ -5,12 +5,12 @@ import java.util.Arrays;
|
|||
|
||||
import org.hibernate.envers.test.BaseEnversJPAFunctionalTestCase;
|
||||
import org.hibernate.envers.test.Priority;
|
||||
import org.hibernate.mapping.Column;
|
||||
import org.hibernate.mapping.Table;
|
||||
|
||||
import org.junit.Assert;
|
||||
import org.junit.Test;
|
||||
|
||||
import org.hibernate.metamodel.spi.relational.Column;
|
||||
import org.hibernate.metamodel.spi.relational.TableSpecification;
|
||||
import org.hibernate.testing.TestForIssue;
|
||||
|
||||
/**
|
||||
|
@ -18,8 +18,8 @@ import org.hibernate.testing.TestForIssue;
|
|||
*/
|
||||
@TestForIssue(jiraKey = "HHH-7003")
|
||||
public class ColumnScalePrecisionTest extends BaseEnversJPAFunctionalTestCase {
|
||||
private Table auditTable = null;
|
||||
private Table originalTable = null;
|
||||
private TableSpecification auditTable = null;
|
||||
private TableSpecification originalTable = null;
|
||||
private Long id = null;
|
||||
|
||||
@Override
|
||||
|
@ -39,21 +39,29 @@ public class ColumnScalePrecisionTest extends BaseEnversJPAFunctionalTestCase {
|
|||
em.getTransaction().commit();
|
||||
|
||||
id = entity.getId();
|
||||
auditTable = getCfg().getClassMapping( "org.hibernate.envers.test.integration.basic.ScalePrecisionEntity_AUD" )
|
||||
.getTable();
|
||||
originalTable = getCfg().getClassMapping( "org.hibernate.envers.test.integration.basic.ScalePrecisionEntity" )
|
||||
.getTable();
|
||||
auditTable = getMetadata().getEntityBinding(
|
||||
"org.hibernate.envers.test.integration.basic.ScalePrecisionEntity_AUD"
|
||||
)
|
||||
.getPrimaryTable();
|
||||
originalTable = getMetadata().getEntityBinding(
|
||||
"org.hibernate.envers.test.integration.basic.ScalePrecisionEntity"
|
||||
)
|
||||
.getPrimaryTable();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testColumnScalePrecision() {
|
||||
Column testColumn = new Column( "wholeNumber" );
|
||||
Column scalePrecisionAuditColumn = auditTable.getColumn( testColumn );
|
||||
Column scalePrecisionColumn = originalTable.getColumn( testColumn );
|
||||
String columnName = "wholeNumber";
|
||||
Column scalePrecisionAuditColumn = auditTable.locateColumn( columnName );
|
||||
Column scalePrecisionColumn = originalTable.locateColumn( columnName );
|
||||
|
||||
Assert.assertNotNull( scalePrecisionAuditColumn );
|
||||
Assert.assertEquals( scalePrecisionColumn.getPrecision(), scalePrecisionAuditColumn.getPrecision() );
|
||||
Assert.assertEquals( scalePrecisionColumn.getScale(), scalePrecisionAuditColumn.getScale() );
|
||||
Assert.assertNotNull( scalePrecisionAuditColumn.getSize() );
|
||||
Assert.assertEquals(
|
||||
scalePrecisionColumn.getSize().getPrecision(),
|
||||
scalePrecisionAuditColumn.getSize().getPrecision()
|
||||
);
|
||||
Assert.assertEquals( scalePrecisionColumn.getSize().getScale(), scalePrecisionAuditColumn.getSize().getScale() );
|
||||
}
|
||||
|
||||
@Test
|
||||
|
|
|
@ -28,7 +28,7 @@ import java.util.Iterator;
|
|||
import java.util.List;
|
||||
|
||||
import org.hibernate.envers.test.BaseEnversJPAFunctionalTestCase;
|
||||
import org.hibernate.mapping.PersistentClass;
|
||||
import org.hibernate.metamodel.spi.binding.EntityBinding;
|
||||
|
||||
import org.junit.Assert;
|
||||
import org.junit.Test;
|
||||
|
@ -44,9 +44,12 @@ public class NoneAudited extends BaseEnversJPAFunctionalTestCase {
|
|||
|
||||
@Test
|
||||
public void testRevisionInfoTableNotCreated() {
|
||||
@SuppressWarnings({"unchecked"}) List<PersistentClass> pcs = iteratorToList( getCfg().getClassMappings() );
|
||||
@SuppressWarnings({"unchecked"}) List<EntityBinding> pcs = iteratorToList(
|
||||
getMetadata().getEntityBindings()
|
||||
.iterator()
|
||||
);
|
||||
Assert.assertEquals( 1, pcs.size() );
|
||||
Assert.assertTrue( pcs.get( 0 ).getClassName().contains( "BasicTestEntity3" ) );
|
||||
Assert.assertTrue( pcs.get( 0 ).getEntityName().contains( "BasicTestEntity3" ) );
|
||||
}
|
||||
|
||||
private <T> List<T> iteratorToList(Iterator<T> it) {
|
||||
|
|
|
@ -53,7 +53,7 @@ public class EmbeddableList1 extends BaseEnversJPAFunctionalTestCase {
|
|||
|
||||
@Override
|
||||
protected Class<?>[] getAnnotatedClasses() {
|
||||
return new Class<?>[] {EmbeddableListEntity1.class};
|
||||
return new Class<?>[] {EmbeddableListEntity1.class, Component3.class, Component4.class};
|
||||
}
|
||||
|
||||
@Test
|
||||
|
|
|
@ -62,7 +62,7 @@ public class EmbeddableList2 extends BaseEnversJPAFunctionalTestCase {
|
|||
|
||||
@Override
|
||||
protected Class<?>[] getAnnotatedClasses() {
|
||||
return new Class<?>[] {EmbeddableListEntity2.class, StrTestNoProxyEntity.class};
|
||||
return new Class<?>[] {EmbeddableListEntity2.class, StrTestNoProxyEntity.class, ManyToOneEagerComponent.class};
|
||||
}
|
||||
|
||||
@Test
|
||||
|
|
|
@ -54,7 +54,7 @@ public class EmbeddableMap extends BaseEnversJPAFunctionalTestCase {
|
|||
|
||||
@Override
|
||||
protected Class<?>[] getAnnotatedClasses() {
|
||||
return new Class<?>[] {EmbeddableMapEntity.class};
|
||||
return new Class<?>[] {EmbeddableMapEntity.class, Component3.class, Component4.class};
|
||||
}
|
||||
|
||||
@Test
|
||||
|
|
|
@ -55,7 +55,7 @@ public class EmbeddableSet extends BaseEnversJPAFunctionalTestCase {
|
|||
|
||||
@Override
|
||||
protected Class<?>[] getAnnotatedClasses() {
|
||||
return new Class<?>[] {EmbeddableSetEntity.class};
|
||||
return new Class<?>[] {EmbeddableSetEntity.class, Component3.class, Component4.class};
|
||||
}
|
||||
|
||||
@Test
|
||||
|
|
|
@ -32,12 +32,14 @@ import org.hibernate.envers.test.entities.components.Component1;
|
|||
import org.hibernate.envers.test.entities.components.Component2;
|
||||
import org.hibernate.envers.test.entities.components.ComponentTestEntity;
|
||||
import org.hibernate.envers.test.tools.TestTools;
|
||||
import org.hibernate.testing.FailureExpectedWithNewMetamodel;
|
||||
|
||||
import org.junit.Test;
|
||||
|
||||
/**
|
||||
* @author Adam Warski (adam at warski dot org)
|
||||
*/
|
||||
@FailureExpectedWithNewMetamodel( message = " Plural attribute index that is an attribute of the referenced entity is not supported yet." )
|
||||
public class ComponentMapKey extends BaseEnversJPAFunctionalTestCase {
|
||||
private Integer cmke_id;
|
||||
|
||||
|
@ -46,7 +48,7 @@ public class ComponentMapKey extends BaseEnversJPAFunctionalTestCase {
|
|||
|
||||
@Override
|
||||
protected Class<?>[] getAnnotatedClasses() {
|
||||
return new Class[] {ComponentMapKeyEntity.class, ComponentTestEntity.class};
|
||||
return new Class[] {ComponentMapKeyEntity.class, ComponentTestEntity.class, Component1.class, Component2.class};
|
||||
}
|
||||
|
||||
@Test
|
||||
|
|
|
@ -30,12 +30,14 @@ import org.hibernate.envers.test.BaseEnversJPAFunctionalTestCase;
|
|||
import org.hibernate.envers.test.Priority;
|
||||
import org.hibernate.envers.test.entities.StrTestEntity;
|
||||
import org.hibernate.envers.test.tools.TestTools;
|
||||
import org.hibernate.testing.FailureExpectedWithNewMetamodel;
|
||||
|
||||
import org.junit.Test;
|
||||
|
||||
/**
|
||||
* @author Adam Warski (adam at warski dot org)
|
||||
*/
|
||||
@FailureExpectedWithNewMetamodel( message = " Plural attribute index that is an attribute of the referenced entity is not supported yet." )
|
||||
public class IdMapKey extends BaseEnversJPAFunctionalTestCase {
|
||||
private Integer imke_id;
|
||||
|
||||
|
|
|
@ -45,7 +45,7 @@ public class Components extends BaseEnversJPAFunctionalTestCase {
|
|||
|
||||
@Override
|
||||
protected Class<?>[] getAnnotatedClasses() {
|
||||
return new Class[] {ComponentTestEntity.class};
|
||||
return new Class[] {ComponentTestEntity.class, Component1.class, Component2.class};
|
||||
}
|
||||
|
||||
@Test
|
||||
|
|
|
@ -57,7 +57,7 @@ public class DefaultValueComponents extends BaseEnversJPAFunctionalTestCase {
|
|||
|
||||
@Override
|
||||
protected Class<?>[] getAnnotatedClasses() {
|
||||
return new Class[] {DefaultValueComponentTestEntity.class};
|
||||
return new Class[] {DefaultValueComponentTestEntity.class, DefaultValueComponent1.class, DefaultValueComponent2.class};
|
||||
}
|
||||
|
||||
@Test
|
||||
|
|
|
@ -5,21 +5,22 @@ import org.hibernate.envers.test.BaseEnversFunctionalTestCase;
|
|||
import org.hibernate.envers.test.Priority;
|
||||
import org.hibernate.envers.test.entities.components.UniquePropsEntity;
|
||||
import org.hibernate.envers.test.entities.components.UniquePropsNotAuditedEntity;
|
||||
import org.hibernate.mapping.Column;
|
||||
import org.hibernate.mapping.PersistentClass;
|
||||
|
||||
import org.junit.Assert;
|
||||
import org.junit.Test;
|
||||
|
||||
import org.hibernate.metamodel.spi.binding.EntityBinding;
|
||||
import org.hibernate.testing.FailureExpectedWithNewMetamodel;
|
||||
import org.hibernate.testing.TestForIssue;
|
||||
|
||||
/**
|
||||
* @author Lukasz Antoniak (lukasz dot antoniak at gmail dot com)
|
||||
*/
|
||||
@TestForIssue(jiraKey = "HHH-6636")
|
||||
@FailureExpectedWithNewMetamodel( message = "hbm.xml source not supported because it is not indexed." )
|
||||
public class PropertiesGroupTest extends BaseEnversFunctionalTestCase {
|
||||
private PersistentClass uniquePropsAudit = null;
|
||||
private PersistentClass uniquePropsNotAuditedAudit = null;
|
||||
private EntityBinding uniquePropsAudit = null;
|
||||
private EntityBinding uniquePropsNotAuditedAudit = null;
|
||||
private UniquePropsEntity entityRev1 = null;
|
||||
private UniquePropsNotAuditedEntity entityNotAuditedRev2 = null;
|
||||
|
||||
|
@ -34,10 +35,10 @@ public class PropertiesGroupTest extends BaseEnversFunctionalTestCase {
|
|||
@Test
|
||||
@Priority(10)
|
||||
public void initData() {
|
||||
uniquePropsAudit = configuration().getClassMapping(
|
||||
uniquePropsAudit = metadata().getEntityBinding(
|
||||
"org.hibernate.envers.test.entities.components.UniquePropsEntity_AUD"
|
||||
);
|
||||
uniquePropsNotAuditedAudit = configuration().getClassMapping(
|
||||
uniquePropsNotAuditedAudit = metadata().getEntityBinding(
|
||||
"org.hibernate.envers.test.entities.components.UniquePropsNotAuditedEntity_AUD"
|
||||
);
|
||||
|
||||
|
@ -65,11 +66,11 @@ public class PropertiesGroupTest extends BaseEnversFunctionalTestCase {
|
|||
|
||||
@Test
|
||||
public void testAuditTableColumns() {
|
||||
Assert.assertNotNull( uniquePropsAudit.getTable().getColumn( new Column( "DATA1" ) ) );
|
||||
Assert.assertNotNull( uniquePropsAudit.getTable().getColumn( new Column( "DATA2" ) ) );
|
||||
Assert.assertNotNull( uniquePropsAudit.getPrimaryTable().locateColumn( "DATA1" ) );
|
||||
Assert.assertNotNull( uniquePropsAudit.getPrimaryTable().locateColumn( "DATA2" ) );
|
||||
|
||||
Assert.assertNotNull( uniquePropsNotAuditedAudit.getTable().getColumn( new Column( "DATA1" ) ) );
|
||||
Assert.assertNull( uniquePropsNotAuditedAudit.getTable().getColumn( new Column( "DATA2" ) ) );
|
||||
Assert.assertNotNull( uniquePropsNotAuditedAudit.getPrimaryTable().locateColumn( "DATA1" ) );
|
||||
Assert.assertNull( uniquePropsNotAuditedAudit.getPrimaryTable().locateColumn( "DATA2" ) );
|
||||
}
|
||||
|
||||
@Test
|
||||
|
|
|
@ -18,6 +18,7 @@ import org.hibernate.envers.query.AuditEntity;
|
|||
import org.hibernate.envers.test.BaseEnversFunctionalTestCase;
|
||||
import org.hibernate.envers.test.Priority;
|
||||
import org.hibernate.service.ServiceRegistry;
|
||||
import org.hibernate.testing.FailureExpectedWithNewMetamodel;
|
||||
import org.hibernate.testing.ServiceRegistryBuilder;
|
||||
import org.hibernate.testing.TestForIssue;
|
||||
|
||||
|
@ -26,6 +27,7 @@ import org.hibernate.testing.TestForIssue;
|
|||
* @author Lukasz Zuchowski (author at zuchos dot com)
|
||||
*/
|
||||
@TestForIssue(jiraKey = "HHH-8049")
|
||||
@FailureExpectedWithNewMetamodel( message = "hbm.xml source not supported because it is not indexed." )
|
||||
public class AuditedDynamicComponentTest extends BaseEnversFunctionalTestCase {
|
||||
|
||||
@Override
|
||||
|
|
|
@ -17,6 +17,7 @@ import org.hibernate.envers.exception.AuditException;
|
|||
import org.hibernate.envers.query.AuditEntity;
|
||||
import org.hibernate.envers.test.BaseEnversFunctionalTestCase;
|
||||
import org.hibernate.envers.test.Priority;
|
||||
import org.hibernate.testing.FailureExpectedWithNewMetamodel;
|
||||
import org.hibernate.testing.TestForIssue;
|
||||
|
||||
/**
|
||||
|
@ -24,6 +25,7 @@ import org.hibernate.testing.TestForIssue;
|
|||
* More advanced tests for dynamic component.
|
||||
*/
|
||||
@TestForIssue(jiraKey = "HHH-8049")
|
||||
@FailureExpectedWithNewMetamodel( message = "hbm.xml source not supported because it is not indexed." )
|
||||
public class AuditedDynamicComponentsAdvancedCasesTest extends BaseEnversFunctionalTestCase {
|
||||
|
||||
public static final String PROP_BOOLEAN = "propBoolean";
|
||||
|
|
|
@ -8,12 +8,14 @@ import org.junit.Test;
|
|||
import org.hibernate.Session;
|
||||
import org.hibernate.envers.test.BaseEnversFunctionalTestCase;
|
||||
import org.hibernate.envers.test.Priority;
|
||||
import org.hibernate.testing.FailureExpectedWithNewMetamodel;
|
||||
import org.hibernate.testing.TestForIssue;
|
||||
|
||||
/**
|
||||
* @author Lukasz Antoniak (lukasz dot antoniak at gmail dot com)
|
||||
*/
|
||||
@TestForIssue(jiraKey = "HHH-8049")
|
||||
@FailureExpectedWithNewMetamodel( message = "hbm.xml source not supported because it is not indexed." )
|
||||
public class NotAuditedDynamicComponentTest extends BaseEnversFunctionalTestCase {
|
||||
@Override
|
||||
protected String[] getMappings() {
|
||||
|
|
|
@ -12,7 +12,9 @@ import org.hibernate.envers.exception.AuditException;
|
|||
import org.hibernate.envers.query.AuditEntity;
|
||||
import org.hibernate.envers.test.BaseEnversFunctionalTestCase;
|
||||
import org.hibernate.envers.test.Priority;
|
||||
import org.hibernate.testing.FailureExpectedWithNewMetamodel;
|
||||
|
||||
@FailureExpectedWithNewMetamodel( message = "hbm.xml source not supported because it is not indexed." )
|
||||
public class SanityCheckTest extends BaseEnversFunctionalTestCase {
|
||||
|
||||
@Override
|
||||
|
|
|
@ -44,7 +44,7 @@ public class ManyToOneInComponent extends BaseEnversJPAFunctionalTestCase {
|
|||
|
||||
@Override
|
||||
protected Class<?>[] getAnnotatedClasses() {
|
||||
return new Class[] {ManyToOneComponentTestEntity.class, StrTestEntity.class};
|
||||
return new Class[] {ManyToOneComponentTestEntity.class, StrTestEntity.class, ManyToOneComponent.class};
|
||||
|
||||
}
|
||||
|
||||
|
|
|
@ -42,7 +42,11 @@ public class NotAuditedManyToOneInComponent extends BaseEnversJPAFunctionalTestC
|
|||
|
||||
@Override
|
||||
protected Class<?>[] getAnnotatedClasses() {
|
||||
return new Class[] {NotAuditedManyToOneComponentTestEntity.class, UnversionedStrTestEntity.class};
|
||||
return new Class[] {
|
||||
NotAuditedManyToOneComponentTestEntity.class,
|
||||
UnversionedStrTestEntity.class,
|
||||
NotAuditedManyToOneComponent.class
|
||||
};
|
||||
}
|
||||
|
||||
@Test
|
||||
|
|
|
@ -44,7 +44,7 @@ public class OneToManyInComponent extends BaseEnversJPAFunctionalTestCase {
|
|||
|
||||
@Override
|
||||
protected Class<?>[] getAnnotatedClasses() {
|
||||
return new Class[] {OneToManyComponentTestEntity.class, StrTestEntity.class};
|
||||
return new Class[] {OneToManyComponentTestEntity.class, StrTestEntity.class, OneToManyComponent.class};
|
||||
}
|
||||
|
||||
@Test
|
||||
|
|
|
@ -14,6 +14,7 @@ import org.hibernate.envers.test.entities.customtype.UnspecifiedEnumTypeEntity;
|
|||
import org.junit.Assert;
|
||||
import org.junit.Test;
|
||||
|
||||
import org.hibernate.testing.FailureExpectedWithNewMetamodel;
|
||||
import org.hibernate.testing.RequiresDialect;
|
||||
import org.hibernate.testing.TestForIssue;
|
||||
|
||||
|
@ -22,6 +23,7 @@ import org.hibernate.testing.TestForIssue;
|
|||
*/
|
||||
@TestForIssue(jiraKey = "HHH-7780")
|
||||
@RequiresDialect(value = H2Dialect.class)
|
||||
@FailureExpectedWithNewMetamodel( message = "hbm.xml source not supported because it is not indexed." )
|
||||
public class UnspecifiedEnumTypeTest extends BaseEnversFunctionalTestCase {
|
||||
private Long id = null;
|
||||
|
||||
|
|
|
@ -8,12 +8,14 @@ import java.util.List;
|
|||
import org.hibernate.MappingException;
|
||||
import org.hibernate.envers.test.AbstractOneSessionTest;
|
||||
import org.hibernate.envers.test.Priority;
|
||||
import org.hibernate.testing.FailureExpectedWithNewMetamodel;
|
||||
|
||||
import org.junit.Test;
|
||||
|
||||
/**
|
||||
* @author Hernán Chanfreau
|
||||
*/
|
||||
@FailureExpectedWithNewMetamodel( message = "hbm.xml source not supported because it is not indexed." )
|
||||
public class ReadEntityWhitEntityNameTest extends AbstractOneSessionTest {
|
||||
|
||||
private long id_pers1;
|
||||
|
@ -36,6 +38,7 @@ public class ReadEntityWhitEntityNameTest extends AbstractOneSessionTest {
|
|||
|
||||
@Test
|
||||
@Priority(10)
|
||||
//@FailureExpectedWithNewMetamodel( message = "hbm.xml source not supported because it is not indexed." )
|
||||
public void initData() {
|
||||
|
||||
initializeSession();
|
||||
|
@ -79,6 +82,7 @@ public class ReadEntityWhitEntityNameTest extends AbstractOneSessionTest {
|
|||
|
||||
|
||||
@Test
|
||||
@FailureExpectedWithNewMetamodel( message = "hbm.xml source not supported because it is not indexed." )
|
||||
public void testRetrieveRevisionsWithEntityName() {
|
||||
List<Number> pers1Revs = getAuditReader().getRevisions( Person.class, "Personaje", id_pers1 );
|
||||
List<Number> pers2Revs = getAuditReader().getRevisions( Person.class, "Personaje", id_pers2 );
|
||||
|
@ -90,6 +94,7 @@ public class ReadEntityWhitEntityNameTest extends AbstractOneSessionTest {
|
|||
}
|
||||
|
||||
@Test
|
||||
@FailureExpectedWithNewMetamodel( message = "hbm.xml source not supported because it is not indexed." )
|
||||
public void testRetrieveAuditedEntityWithEntityName() {
|
||||
person1_1 = getAuditReader().find( Person.class, "Personaje", id_pers1, 1 );
|
||||
person1_2 = getAuditReader().find( Person.class, "Personaje", id_pers1, 2 );
|
||||
|
@ -102,6 +107,7 @@ public class ReadEntityWhitEntityNameTest extends AbstractOneSessionTest {
|
|||
}
|
||||
|
||||
@Test
|
||||
@FailureExpectedWithNewMetamodel( message = "hbm.xml source not supported because it is not indexed." )
|
||||
public void testObtainEntityNameAuditedEntityWithEntityName() {
|
||||
person1_1 = getAuditReader().find( Person.class, "Personaje", id_pers1, 1 );
|
||||
person1_2 = getAuditReader().find( Person.class, "Personaje", id_pers1, 2 );
|
||||
|
@ -121,6 +127,7 @@ public class ReadEntityWhitEntityNameTest extends AbstractOneSessionTest {
|
|||
}
|
||||
|
||||
@Test
|
||||
@FailureExpectedWithNewMetamodel( message = "hbm.xml source not supported because it is not indexed." )
|
||||
public void testRetrieveAuditedEntityWithEntityNameWithNewSession() {
|
||||
|
||||
// force a new session and AR
|
||||
|
|
|
@ -9,12 +9,14 @@ import java.util.List;
|
|||
import org.hibernate.MappingException;
|
||||
import org.hibernate.envers.test.AbstractOneSessionTest;
|
||||
import org.hibernate.envers.test.Priority;
|
||||
import org.hibernate.testing.FailureExpectedWithNewMetamodel;
|
||||
|
||||
import org.junit.Test;
|
||||
|
||||
/**
|
||||
* @author Hernán Chanfreau
|
||||
*/
|
||||
@FailureExpectedWithNewMetamodel( message = "hbm.xml source not supported because it is not indexed." )
|
||||
public class ReadEntityWithAuditedManyToManyTest extends AbstractOneSessionTest {
|
||||
|
||||
private long id_car1;
|
||||
|
|
|
@ -9,12 +9,14 @@ import java.util.List;
|
|||
import org.hibernate.MappingException;
|
||||
import org.hibernate.envers.test.AbstractOneSessionTest;
|
||||
import org.hibernate.envers.test.Priority;
|
||||
import org.hibernate.testing.FailureExpectedWithNewMetamodel;
|
||||
|
||||
import org.junit.Test;
|
||||
|
||||
/**
|
||||
* @author Hernán Chanfreau
|
||||
*/
|
||||
@FailureExpectedWithNewMetamodel( message = "hbm.xml source not supported because it is not indexed." )
|
||||
public class ReadEntityWithAuditedCollectionTest extends AbstractOneSessionTest {
|
||||
|
||||
private long id_car1;
|
||||
|
|
|
@ -7,12 +7,14 @@ import java.net.URL;
|
|||
import org.hibernate.MappingException;
|
||||
import org.hibernate.envers.test.AbstractOneSessionTest;
|
||||
import org.hibernate.envers.test.Priority;
|
||||
import org.hibernate.testing.FailureExpectedWithNewMetamodel;
|
||||
|
||||
import org.junit.Test;
|
||||
|
||||
/**
|
||||
* @author Hernán Chanfreau
|
||||
*/
|
||||
@FailureExpectedWithNewMetamodel( message = "hbm.xml source not supported because it is not indexed." )
|
||||
public class ReadEntityAssociatedAuditedTest extends AbstractOneSessionTest {
|
||||
|
||||
private long id_car1;
|
||||
|
|
|
@ -11,11 +11,13 @@ import org.hibernate.envers.test.Priority;
|
|||
import org.junit.Assert;
|
||||
import org.junit.Test;
|
||||
|
||||
import org.hibernate.testing.FailureExpectedWithNewMetamodel;
|
||||
import org.hibernate.testing.TestForIssue;
|
||||
|
||||
/**
|
||||
* @author Lukasz Antoniak (lukasz dot antoniak at gmail dot com)
|
||||
*/
|
||||
@FailureExpectedWithNewMetamodel( message = "hbm.xml source not supported because it is not indexed." )
|
||||
public class SingleDomainObjectToMultipleTablesTest extends AbstractOneSessionTest {
|
||||
private long carId = 0;
|
||||
private long ownerId = 0;
|
||||
|
|
|
@ -7,12 +7,14 @@ import java.net.URL;
|
|||
import org.hibernate.MappingException;
|
||||
import org.hibernate.envers.test.AbstractOneSessionTest;
|
||||
import org.hibernate.envers.test.Priority;
|
||||
import org.hibernate.testing.FailureExpectedWithNewMetamodel;
|
||||
|
||||
import org.junit.Test;
|
||||
|
||||
/**
|
||||
* @author Hernán Chanfreau
|
||||
*/
|
||||
@FailureExpectedWithNewMetamodel( message = "hbm.xml source not supported because it is not indexed." )
|
||||
public class ReadEntityAssociatedNotAuditedTest extends AbstractOneSessionTest {
|
||||
|
||||
private long id_car1;
|
||||
|
|
|
@ -42,7 +42,7 @@ public class CompositeDateId extends BaseEnversJPAFunctionalTestCase {
|
|||
|
||||
@Override
|
||||
protected Class<?>[] getAnnotatedClasses() {
|
||||
return new Class[] {CompositeDateIdTestEntity.class};
|
||||
return new Class[] {CompositeDateIdTestEntity.class, DateEmbId.class};
|
||||
}
|
||||
|
||||
@Test
|
||||
|
|
|
@ -51,7 +51,13 @@ public class CompositeIds extends BaseEnversJPAFunctionalTestCase {
|
|||
|
||||
@Override
|
||||
protected Class<?>[] getAnnotatedClasses() {
|
||||
return new Class[] {EmbIdTestEntity.class, MulIdTestEntity.class, EmbIdWithCustomTypeTestEntity.class};
|
||||
return new Class[] {
|
||||
EmbIdTestEntity.class,
|
||||
MulIdTestEntity.class,
|
||||
EmbIdWithCustomTypeTestEntity.class,
|
||||
EmbId.class,
|
||||
EmbIdWithCustomType.class
|
||||
};
|
||||
}
|
||||
|
||||
@Test
|
||||
|
|
|
@ -22,7 +22,12 @@ public class ManyToOneIdNotAudited extends BaseEnversJPAFunctionalTestCase {
|
|||
|
||||
@Override
|
||||
protected Class<?>[] getAnnotatedClasses() {
|
||||
return new Class[] {ManyToOneIdNotAuditedTestEntity.class, UnversionedStrTestEntity.class, StrTestEntity.class};
|
||||
return new Class[] {
|
||||
ManyToOneIdNotAuditedTestEntity.class,
|
||||
UnversionedStrTestEntity.class,
|
||||
StrTestEntity.class,
|
||||
ManyToOneNotAuditedEmbId.class
|
||||
};
|
||||
}
|
||||
|
||||
@Test
|
||||
|
|
|
@ -9,12 +9,14 @@ import org.hibernate.envers.test.Priority;
|
|||
import org.junit.Assert;
|
||||
import org.junit.Test;
|
||||
|
||||
import org.hibernate.testing.FailureExpectedWithNewMetamodel;
|
||||
import org.hibernate.testing.TestForIssue;
|
||||
|
||||
/**
|
||||
* @author Lukasz Antoniak (lukasz dot antoniak at gmail dot com)
|
||||
*/
|
||||
@TestForIssue(jiraKey = "HHH-7690")
|
||||
@FailureExpectedWithNewMetamodel( message = "Associations with non-envers entities not supported yet." )
|
||||
public class RelationInsideEmbeddableTest extends BaseEnversJPAFunctionalTestCase {
|
||||
private Integer orderId = null;
|
||||
private ItemId itemId = null;
|
||||
|
|
|
@ -30,7 +30,7 @@ import java.util.Arrays;
|
|||
import org.hibernate.envers.test.BaseEnversJPAFunctionalTestCase;
|
||||
import org.hibernate.envers.test.Priority;
|
||||
import org.hibernate.envers.test.integration.inheritance.joined.ParentEntity;
|
||||
import org.hibernate.mapping.Column;
|
||||
import org.hibernate.metamodel.spi.relational.Column;
|
||||
|
||||
import org.junit.Assert;
|
||||
import org.junit.Test;
|
||||
|
@ -101,11 +101,15 @@ public class ChildPrimaryKeyJoinAuditing extends BaseEnversJPAFunctionalTestCase
|
|||
public void testChildIdColumnName() {
|
||||
Assert.assertEquals(
|
||||
"other_id",
|
||||
((Column) getCfg()
|
||||
.getClassMapping(
|
||||
( (Column) getMetadata()
|
||||
.getEntityBinding(
|
||||
"org.hibernate.envers.test.integration.inheritance.joined.primarykeyjoin.ChildPrimaryKeyJoinEntity_AUD"
|
||||
)
|
||||
.getKey().getColumnIterator().next()).getName()
|
||||
.getHierarchyDetails()
|
||||
.getEntityIdentifier()
|
||||
.getAttributeBinding()
|
||||
.getValues()
|
||||
.get( 0 ) ).getColumnName().getText()
|
||||
);
|
||||
}
|
||||
}
|
|
@ -30,7 +30,8 @@ public class MixedInheritanceStrategiesEntityTest extends BaseEnversJPAFunctiona
|
|||
AbstractActivity.class,
|
||||
AbstractCheckActivity.class,
|
||||
CheckInActivity.class,
|
||||
NormalActivity.class
|
||||
NormalActivity.class,
|
||||
ActivityId.class
|
||||
};
|
||||
}
|
||||
|
||||
|
|
|
@ -2,13 +2,14 @@ package org.hibernate.envers.test.integration.inheritance.single.discriminatorfo
|
|||
|
||||
import javax.persistence.EntityManager;
|
||||
import java.util.Arrays;
|
||||
import java.util.Iterator;
|
||||
import java.util.List;
|
||||
|
||||
import org.hibernate.envers.test.BaseEnversJPAFunctionalTestCase;
|
||||
import org.hibernate.envers.test.Priority;
|
||||
import org.hibernate.mapping.Formula;
|
||||
import org.hibernate.mapping.PersistentClass;
|
||||
import org.hibernate.metamodel.spi.binding.EntityBinding;
|
||||
import org.hibernate.metamodel.spi.binding.EntityDiscriminator;
|
||||
import org.hibernate.metamodel.spi.relational.DerivedValue;
|
||||
import org.hibernate.metamodel.spi.relational.Value;
|
||||
|
||||
import org.junit.Assert;
|
||||
import org.junit.Test;
|
||||
|
@ -17,7 +18,7 @@ import org.junit.Test;
|
|||
* @author Lukasz Antoniak (lukasz dot antoniak at gmail dot com)
|
||||
*/
|
||||
public class DiscriminatorFormulaTest extends BaseEnversJPAFunctionalTestCase {
|
||||
private PersistentClass parentAudit = null;
|
||||
private EntityBinding parentAudit = null;
|
||||
private ChildEntity childVer1 = null;
|
||||
private ChildEntity childVer2 = null;
|
||||
private ParentEntity parentVer1 = null;
|
||||
|
@ -31,7 +32,7 @@ public class DiscriminatorFormulaTest extends BaseEnversJPAFunctionalTestCase {
|
|||
@Test
|
||||
@Priority(10)
|
||||
public void initData() {
|
||||
parentAudit = getCfg().getClassMapping(
|
||||
parentAudit = getMetadata().getEntityBinding(
|
||||
"org.hibernate.envers.test.integration.inheritance.single.discriminatorformula.ParentEntity_AUD"
|
||||
);
|
||||
|
||||
|
@ -87,16 +88,10 @@ public class DiscriminatorFormulaTest extends BaseEnversJPAFunctionalTestCase {
|
|||
|
||||
@Test
|
||||
public void testDiscriminatorFormulaInAuditTable() {
|
||||
assert parentAudit.getDiscriminator().hasFormula();
|
||||
Iterator iterator = parentAudit.getDiscriminator().getColumnIterator();
|
||||
while ( iterator.hasNext() ) {
|
||||
Object o = iterator.next();
|
||||
if ( o instanceof Formula ) {
|
||||
Formula formula = (Formula) o;
|
||||
Assert.assertEquals( ParentEntity.DISCRIMINATOR_QUERY, formula.getText() );
|
||||
return;
|
||||
}
|
||||
}
|
||||
final EntityDiscriminator entityDiscriminator = parentAudit.getHierarchyDetails().getEntityDiscriminator();
|
||||
assert entityDiscriminator.getRelationalValue().getValueType() == Value.ValueType.DERIVED_VALUE;
|
||||
DerivedValue derivedValue = (DerivedValue) entityDiscriminator.getRelationalValue();
|
||||
Assert.assertEquals( ParentEntity.DISCRIMINATOR_QUERY, derivedValue.getExpression() );
|
||||
assert false;
|
||||
}
|
||||
|
||||
|
|
|
@ -1,15 +1,16 @@
|
|||
package org.hibernate.envers.test.integration.inheritance.tableperclass.abstractparent;
|
||||
|
||||
import javax.persistence.EntityManager;
|
||||
import java.util.Iterator;
|
||||
|
||||
import org.hibernate.envers.test.BaseEnversJPAFunctionalTestCase;
|
||||
import org.hibernate.envers.test.Priority;
|
||||
import org.hibernate.mapping.Table;
|
||||
|
||||
import org.junit.Assert;
|
||||
import org.junit.Test;
|
||||
|
||||
import org.hibernate.metamodel.spi.relational.Schema;
|
||||
import org.hibernate.metamodel.spi.relational.Table;
|
||||
import org.hibernate.metamodel.spi.relational.TableSpecification;
|
||||
import org.hibernate.testing.TestForIssue;
|
||||
|
||||
/**
|
||||
|
@ -38,12 +39,12 @@ public class AuditedAbstractParentTest extends BaseEnversJPAFunctionalTestCase {
|
|||
|
||||
@Test
|
||||
public void testAbstractTableExistence() {
|
||||
Iterator<Table> tableIterator = getCfg().getTableMappings();
|
||||
while ( tableIterator.hasNext() ) {
|
||||
Table table = tableIterator.next();
|
||||
if ( "AbstractEntity_AUD".equals( table.getName() ) ) {
|
||||
Assert.assertFalse( table.isPhysicalTable() );
|
||||
return;
|
||||
for ( Schema schema : getMetadata().getDatabase().getSchemas() ) {
|
||||
for ( TableSpecification table : schema.getTables() ) {
|
||||
if ( "AbstractEntity_AUD".equals( table.getLogicalName().getText() ) ) {
|
||||
Assert.assertFalse( Table.class.isInstance( table ) );
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
Assert.fail();
|
||||
|
|
|
@ -39,7 +39,7 @@ public class InterfacesComponents extends BaseEnversJPAFunctionalTestCase {
|
|||
|
||||
@Override
|
||||
protected Class<?>[] getAnnotatedClasses() {
|
||||
return new Class[] {ComponentTestEntity.class};
|
||||
return new Class[] {ComponentTestEntity.class, Component1.class};
|
||||
}
|
||||
|
||||
@Test
|
||||
|
|
|
@ -1,10 +1,12 @@
|
|||
package org.hibernate.envers.test.integration.interfaces.hbm.allAudited.joined;
|
||||
|
||||
import org.hibernate.envers.test.integration.interfaces.hbm.allAudited.AbstractAllAuditedTest;
|
||||
import org.hibernate.testing.FailureExpectedWithNewMetamodel;
|
||||
|
||||
/**
|
||||
* @author Hern<EFBFBD>n Chanfreau
|
||||
*/
|
||||
@FailureExpectedWithNewMetamodel( message = "hbm.xml source not supported because it is not indexed." )
|
||||
public class JoinedAllAuditedTest extends AbstractAllAuditedTest {
|
||||
@Override
|
||||
protected String[] getMappings() {
|
||||
|
|
|
@ -1,10 +1,12 @@
|
|||
package org.hibernate.envers.test.integration.interfaces.hbm.allAudited.subclass;
|
||||
|
||||
import org.hibernate.envers.test.integration.interfaces.hbm.allAudited.AbstractAllAuditedTest;
|
||||
import org.hibernate.testing.FailureExpectedWithNewMetamodel;
|
||||
|
||||
/**
|
||||
* @author Hern<EFBFBD>n Chanfreau
|
||||
*/
|
||||
@FailureExpectedWithNewMetamodel( message = "hbm.xml source not supported because it is not indexed." )
|
||||
public class SubclassAllAuditedTest extends AbstractAllAuditedTest {
|
||||
@Override
|
||||
protected String[] getMappings() {
|
||||
|
|
|
@ -1,10 +1,12 @@
|
|||
package org.hibernate.envers.test.integration.interfaces.hbm.allAudited.union;
|
||||
|
||||
import org.hibernate.envers.test.integration.interfaces.hbm.allAudited.AbstractAllAuditedTest;
|
||||
import org.hibernate.testing.FailureExpectedWithNewMetamodel;
|
||||
|
||||
/**
|
||||
* @author Hern<EFBFBD>n Chanfreau
|
||||
*/
|
||||
@FailureExpectedWithNewMetamodel( message = "hbm.xml source not supported because it is not indexed." )
|
||||
public class UnionAllAuditedTest extends AbstractAllAuditedTest {
|
||||
@Override
|
||||
protected String[] getMappings() {
|
||||
|
|
|
@ -1,10 +1,12 @@
|
|||
package org.hibernate.envers.test.integration.interfaces.hbm.propertiesAudited.joined;
|
||||
|
||||
import org.hibernate.envers.test.integration.interfaces.hbm.propertiesAudited.AbstractPropertiesAuditedTest;
|
||||
import org.hibernate.testing.FailureExpectedWithNewMetamodel;
|
||||
|
||||
/**
|
||||
* @author Hern<EFBFBD>n Chanfreau
|
||||
*/
|
||||
@FailureExpectedWithNewMetamodel( message = "hbm.xml source not supported because it is not indexed." )
|
||||
public class JoinedPropertiesAuditedTest extends AbstractPropertiesAuditedTest {
|
||||
|
||||
@Override
|
||||
|
|
|
@ -1,10 +1,12 @@
|
|||
package org.hibernate.envers.test.integration.interfaces.hbm.propertiesAudited.subclass;
|
||||
|
||||
import org.hibernate.envers.test.integration.interfaces.hbm.propertiesAudited.AbstractPropertiesAuditedTest;
|
||||
import org.hibernate.testing.FailureExpectedWithNewMetamodel;
|
||||
|
||||
/**
|
||||
* @author Hern<EFBFBD>n Chanfreau
|
||||
*/
|
||||
@FailureExpectedWithNewMetamodel( message = "hbm.xml source not supported because it is not indexed." )
|
||||
public class SubclassPropertiesAuditedTest extends AbstractPropertiesAuditedTest {
|
||||
@Override
|
||||
protected String[] getMappings() {
|
||||
|
|
|
@ -1,10 +1,12 @@
|
|||
package org.hibernate.envers.test.integration.interfaces.hbm.propertiesAudited.union;
|
||||
|
||||
import org.hibernate.envers.test.integration.interfaces.hbm.propertiesAudited.AbstractPropertiesAuditedTest;
|
||||
import org.hibernate.testing.FailureExpectedWithNewMetamodel;
|
||||
|
||||
/**
|
||||
* @author Hern<EFBFBD>n Chanfreau
|
||||
*/
|
||||
@FailureExpectedWithNewMetamodel( message = "hbm.xml source not supported because it is not indexed." )
|
||||
public class UnionPropertiesAuditedTest extends AbstractPropertiesAuditedTest {
|
||||
|
||||
@Override
|
||||
|
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue