[hibernate-commits] Hibernate SVN: r15406 - in core/trunk: envers and 105 other directories.
hibernate-commits at lists.jboss.org
hibernate-commits at lists.jboss.org
Mon Oct 27 14:56:32 EDT 2008
Author: steve.ebersole at jboss.com
Date: 2008-10-27 14:56:31 -0400 (Mon, 27 Oct 2008)
New Revision: 15406
Added:
core/trunk/envers/
core/trunk/envers/pom.xml
core/trunk/envers/src/
core/trunk/envers/src/demo/
core/trunk/envers/src/demo/java/
core/trunk/envers/src/demo/java/org/
core/trunk/envers/src/demo/java/org/jboss/
core/trunk/envers/src/demo/java/org/jboss/envers/
core/trunk/envers/src/demo/java/org/jboss/envers/demo/
core/trunk/envers/src/demo/java/org/jboss/envers/demo/Address.java
core/trunk/envers/src/demo/java/org/jboss/envers/demo/Person.java
core/trunk/envers/src/demo/java/org/jboss/envers/demo/TestConsole.java
core/trunk/envers/src/demo/resources/
core/trunk/envers/src/demo/resources/META-INF/
core/trunk/envers/src/demo/resources/META-INF/persistence.xml
core/trunk/envers/src/main/
core/trunk/envers/src/main/java/
core/trunk/envers/src/main/java/org/
core/trunk/envers/src/main/java/org/hibernate/
core/trunk/envers/src/main/java/org/hibernate/tool/
core/trunk/envers/src/main/java/org/hibernate/tool/ant/
core/trunk/envers/src/main/java/org/hibernate/tool/ant/EnversHibernateToolTask.java
core/trunk/envers/src/main/java/org/jboss/
core/trunk/envers/src/main/java/org/jboss/envers/
core/trunk/envers/src/main/java/org/jboss/envers/DefaultRevisionEntity.java
core/trunk/envers/src/main/java/org/jboss/envers/ModificationStore.java
core/trunk/envers/src/main/java/org/jboss/envers/RevisionEntity.java
core/trunk/envers/src/main/java/org/jboss/envers/RevisionListener.java
core/trunk/envers/src/main/java/org/jboss/envers/RevisionNumber.java
core/trunk/envers/src/main/java/org/jboss/envers/RevisionTimestamp.java
core/trunk/envers/src/main/java/org/jboss/envers/RevisionType.java
core/trunk/envers/src/main/java/org/jboss/envers/SecondaryVersionsTable.java
core/trunk/envers/src/main/java/org/jboss/envers/SecondaryVersionsTables.java
core/trunk/envers/src/main/java/org/jboss/envers/Unversioned.java
core/trunk/envers/src/main/java/org/jboss/envers/Versioned.java
core/trunk/envers/src/main/java/org/jboss/envers/VersionsJoinTable.java
core/trunk/envers/src/main/java/org/jboss/envers/VersionsReader.java
core/trunk/envers/src/main/java/org/jboss/envers/VersionsReaderFactory.java
core/trunk/envers/src/main/java/org/jboss/envers/VersionsTable.java
core/trunk/envers/src/main/java/org/jboss/envers/ant/
core/trunk/envers/src/main/java/org/jboss/envers/ant/AnnotationConfigurationTaskWithEnvers.java
core/trunk/envers/src/main/java/org/jboss/envers/ant/ConfigurationTaskWithEnvers.java
core/trunk/envers/src/main/java/org/jboss/envers/ant/JPAConfigurationTaskWithEnvers.java
core/trunk/envers/src/main/java/org/jboss/envers/configuration/
core/trunk/envers/src/main/java/org/jboss/envers/configuration/EntitiesConfigurator.java
core/trunk/envers/src/main/java/org/jboss/envers/configuration/GlobalConfiguration.java
core/trunk/envers/src/main/java/org/jboss/envers/configuration/PersistentClassGraphDefiner.java
core/trunk/envers/src/main/java/org/jboss/envers/configuration/RevisionInfoConfiguration.java
core/trunk/envers/src/main/java/org/jboss/envers/configuration/VersionsConfiguration.java
core/trunk/envers/src/main/java/org/jboss/envers/configuration/VersionsEntitiesConfiguration.java
core/trunk/envers/src/main/java/org/jboss/envers/configuration/metadata/
core/trunk/envers/src/main/java/org/jboss/envers/configuration/metadata/AnnotationsMetadataReader.java
core/trunk/envers/src/main/java/org/jboss/envers/configuration/metadata/BasicMetadataGenerator.java
core/trunk/envers/src/main/java/org/jboss/envers/configuration/metadata/CollectionMetadataGenerator.java
core/trunk/envers/src/main/java/org/jboss/envers/configuration/metadata/EntityXmlMappingData.java
core/trunk/envers/src/main/java/org/jboss/envers/configuration/metadata/IdMetadataGenerator.java
core/trunk/envers/src/main/java/org/jboss/envers/configuration/metadata/InheritanceType.java
core/trunk/envers/src/main/java/org/jboss/envers/configuration/metadata/MetadataTools.java
core/trunk/envers/src/main/java/org/jboss/envers/configuration/metadata/PersistentClassVersioningData.java
core/trunk/envers/src/main/java/org/jboss/envers/configuration/metadata/PropertyStoreInfo.java
core/trunk/envers/src/main/java/org/jboss/envers/configuration/metadata/QueryGeneratorBuilder.java
core/trunk/envers/src/main/java/org/jboss/envers/configuration/metadata/ToOneRelationMetadataGenerator.java
core/trunk/envers/src/main/java/org/jboss/envers/configuration/metadata/VersionsMetadataGenerator.java
core/trunk/envers/src/main/java/org/jboss/envers/entities/
core/trunk/envers/src/main/java/org/jboss/envers/entities/EntitiesConfigurations.java
core/trunk/envers/src/main/java/org/jboss/envers/entities/EntityConfiguration.java
core/trunk/envers/src/main/java/org/jboss/envers/entities/EntityInstantiator.java
core/trunk/envers/src/main/java/org/jboss/envers/entities/IdMappingData.java
core/trunk/envers/src/main/java/org/jboss/envers/entities/RelationDescription.java
core/trunk/envers/src/main/java/org/jboss/envers/entities/RelationType.java
core/trunk/envers/src/main/java/org/jboss/envers/entities/RevisionTypeType.java
core/trunk/envers/src/main/java/org/jboss/envers/entities/mapper/
core/trunk/envers/src/main/java/org/jboss/envers/entities/mapper/CompositeMapperBuilder.java
core/trunk/envers/src/main/java/org/jboss/envers/entities/mapper/ExtendedPropertyMapper.java
core/trunk/envers/src/main/java/org/jboss/envers/entities/mapper/MapPropertyMapper.java
core/trunk/envers/src/main/java/org/jboss/envers/entities/mapper/MultiPropertyMapper.java
core/trunk/envers/src/main/java/org/jboss/envers/entities/mapper/PersistentCollectionChangeData.java
core/trunk/envers/src/main/java/org/jboss/envers/entities/mapper/PropertyMapper.java
core/trunk/envers/src/main/java/org/jboss/envers/entities/mapper/SimpleMapperBuilder.java
core/trunk/envers/src/main/java/org/jboss/envers/entities/mapper/SinglePropertyMapper.java
core/trunk/envers/src/main/java/org/jboss/envers/entities/mapper/SubclassPropertyMapper.java
core/trunk/envers/src/main/java/org/jboss/envers/entities/mapper/id/
core/trunk/envers/src/main/java/org/jboss/envers/entities/mapper/id/AbstractCompositeIdMapper.java
core/trunk/envers/src/main/java/org/jboss/envers/entities/mapper/id/AbstractIdMapper.java
core/trunk/envers/src/main/java/org/jboss/envers/entities/mapper/id/EmbeddedIdMapper.java
core/trunk/envers/src/main/java/org/jboss/envers/entities/mapper/id/IdMapper.java
core/trunk/envers/src/main/java/org/jboss/envers/entities/mapper/id/MultipleIdMapper.java
core/trunk/envers/src/main/java/org/jboss/envers/entities/mapper/id/QueryParameterData.java
core/trunk/envers/src/main/java/org/jboss/envers/entities/mapper/id/SimpleIdMapperBuilder.java
core/trunk/envers/src/main/java/org/jboss/envers/entities/mapper/id/SingleIdMapper.java
core/trunk/envers/src/main/java/org/jboss/envers/entities/mapper/relation/
core/trunk/envers/src/main/java/org/jboss/envers/entities/mapper/relation/AbstractCollectionMapper.java
core/trunk/envers/src/main/java/org/jboss/envers/entities/mapper/relation/BasicCollectionMapper.java
core/trunk/envers/src/main/java/org/jboss/envers/entities/mapper/relation/CommonCollectionMapperData.java
core/trunk/envers/src/main/java/org/jboss/envers/entities/mapper/relation/ListCollectionMapper.java
core/trunk/envers/src/main/java/org/jboss/envers/entities/mapper/relation/MapCollectionMapper.java
core/trunk/envers/src/main/java/org/jboss/envers/entities/mapper/relation/MiddleComponentData.java
core/trunk/envers/src/main/java/org/jboss/envers/entities/mapper/relation/MiddleIdData.java
core/trunk/envers/src/main/java/org/jboss/envers/entities/mapper/relation/OneToOneNotOwningMapper.java
core/trunk/envers/src/main/java/org/jboss/envers/entities/mapper/relation/ToOneIdMapper.java
core/trunk/envers/src/main/java/org/jboss/envers/entities/mapper/relation/component/
core/trunk/envers/src/main/java/org/jboss/envers/entities/mapper/relation/component/MiddleComponentMapper.java
core/trunk/envers/src/main/java/org/jboss/envers/entities/mapper/relation/component/MiddleDummyComponentMapper.java
core/trunk/envers/src/main/java/org/jboss/envers/entities/mapper/relation/component/MiddleMapKeyIdComponentMapper.java
core/trunk/envers/src/main/java/org/jboss/envers/entities/mapper/relation/component/MiddleMapKeyPropertyComponentMapper.java
core/trunk/envers/src/main/java/org/jboss/envers/entities/mapper/relation/component/MiddleRelatedComponentMapper.java
core/trunk/envers/src/main/java/org/jboss/envers/entities/mapper/relation/component/MiddleSimpleComponentMapper.java
core/trunk/envers/src/main/java/org/jboss/envers/entities/mapper/relation/lazy/
core/trunk/envers/src/main/java/org/jboss/envers/entities/mapper/relation/lazy/AbstractDelegateSessionImplementor.java
core/trunk/envers/src/main/java/org/jboss/envers/entities/mapper/relation/lazy/ToOneDelegateSessionImplementor.java
core/trunk/envers/src/main/java/org/jboss/envers/entities/mapper/relation/lazy/initializor/
core/trunk/envers/src/main/java/org/jboss/envers/entities/mapper/relation/lazy/initializor/AbstractCollectionInitializor.java
core/trunk/envers/src/main/java/org/jboss/envers/entities/mapper/relation/lazy/initializor/ArrayCollectionInitializor.java
core/trunk/envers/src/main/java/org/jboss/envers/entities/mapper/relation/lazy/initializor/BasicCollectionInitializor.java
core/trunk/envers/src/main/java/org/jboss/envers/entities/mapper/relation/lazy/initializor/Initializor.java
core/trunk/envers/src/main/java/org/jboss/envers/entities/mapper/relation/lazy/initializor/ListCollectionInitializor.java
core/trunk/envers/src/main/java/org/jboss/envers/entities/mapper/relation/lazy/initializor/MapCollectionInitializor.java
core/trunk/envers/src/main/java/org/jboss/envers/entities/mapper/relation/lazy/proxy/
core/trunk/envers/src/main/java/org/jboss/envers/entities/mapper/relation/lazy/proxy/CollectionProxy.java
core/trunk/envers/src/main/java/org/jboss/envers/entities/mapper/relation/lazy/proxy/ListProxy.java
core/trunk/envers/src/main/java/org/jboss/envers/entities/mapper/relation/lazy/proxy/MapProxy.java
core/trunk/envers/src/main/java/org/jboss/envers/entities/mapper/relation/lazy/proxy/SetProxy.java
core/trunk/envers/src/main/java/org/jboss/envers/entities/mapper/relation/lazy/proxy/SortedMapProxy.java
core/trunk/envers/src/main/java/org/jboss/envers/entities/mapper/relation/lazy/proxy/SortedSetProxy.java
core/trunk/envers/src/main/java/org/jboss/envers/entities/mapper/relation/query/
core/trunk/envers/src/main/java/org/jboss/envers/entities/mapper/relation/query/OneEntityQueryGenerator.java
core/trunk/envers/src/main/java/org/jboss/envers/entities/mapper/relation/query/OneVersionsEntityQueryGenerator.java
core/trunk/envers/src/main/java/org/jboss/envers/entities/mapper/relation/query/QueryGeneratorTools.java
core/trunk/envers/src/main/java/org/jboss/envers/entities/mapper/relation/query/RelationQueryGenerator.java
core/trunk/envers/src/main/java/org/jboss/envers/entities/mapper/relation/query/ThreeEntityQueryGenerator.java
core/trunk/envers/src/main/java/org/jboss/envers/entities/mapper/relation/query/TwoEntityQueryGenerator.java
core/trunk/envers/src/main/java/org/jboss/envers/entity/
core/trunk/envers/src/main/java/org/jboss/envers/entity/VersionsInheritanceEntityPersister.java
core/trunk/envers/src/main/java/org/jboss/envers/event/
core/trunk/envers/src/main/java/org/jboss/envers/event/VersionsEventListener.java
core/trunk/envers/src/main/java/org/jboss/envers/exception/
core/trunk/envers/src/main/java/org/jboss/envers/exception/NotVersionedException.java
core/trunk/envers/src/main/java/org/jboss/envers/exception/RevisionDoesNotExistException.java
core/trunk/envers/src/main/java/org/jboss/envers/exception/VersionsException.java
core/trunk/envers/src/main/java/org/jboss/envers/query/
core/trunk/envers/src/main/java/org/jboss/envers/query/RevisionProperty.java
core/trunk/envers/src/main/java/org/jboss/envers/query/RevisionTypeProperty.java
core/trunk/envers/src/main/java/org/jboss/envers/query/VersionsQuery.java
core/trunk/envers/src/main/java/org/jboss/envers/query/VersionsQueryCreator.java
core/trunk/envers/src/main/java/org/jboss/envers/query/VersionsRestrictions.java
core/trunk/envers/src/main/java/org/jboss/envers/query/criteria/
core/trunk/envers/src/main/java/org/jboss/envers/query/criteria/AggregatedFieldVersionsExpression.java
core/trunk/envers/src/main/java/org/jboss/envers/query/criteria/BetweenVersionsExpression.java
core/trunk/envers/src/main/java/org/jboss/envers/query/criteria/CriteriaTools.java
core/trunk/envers/src/main/java/org/jboss/envers/query/criteria/ExtendableCriterion.java
core/trunk/envers/src/main/java/org/jboss/envers/query/criteria/IdentifierEqVersionsExpression.java
core/trunk/envers/src/main/java/org/jboss/envers/query/criteria/InVersionsExpression.java
core/trunk/envers/src/main/java/org/jboss/envers/query/criteria/LogicalVersionsExpression.java
core/trunk/envers/src/main/java/org/jboss/envers/query/criteria/NotNullVersionsExpression.java
core/trunk/envers/src/main/java/org/jboss/envers/query/criteria/NotVersionsExpression.java
core/trunk/envers/src/main/java/org/jboss/envers/query/criteria/NullVersionsExpression.java
core/trunk/envers/src/main/java/org/jboss/envers/query/criteria/PropertyVersionsExpression.java
core/trunk/envers/src/main/java/org/jboss/envers/query/criteria/RelatedVersionsExpression.java
core/trunk/envers/src/main/java/org/jboss/envers/query/criteria/RevisionVersionsExpression.java
core/trunk/envers/src/main/java/org/jboss/envers/query/criteria/SimpleVersionsExpression.java
core/trunk/envers/src/main/java/org/jboss/envers/query/criteria/VersionsConjunction.java
core/trunk/envers/src/main/java/org/jboss/envers/query/criteria/VersionsCriterion.java
core/trunk/envers/src/main/java/org/jboss/envers/query/criteria/VersionsDisjunction.java
core/trunk/envers/src/main/java/org/jboss/envers/query/impl/
core/trunk/envers/src/main/java/org/jboss/envers/query/impl/AbstractVersionsQuery.java
core/trunk/envers/src/main/java/org/jboss/envers/query/impl/EntitiesAtRevisionQuery.java
core/trunk/envers/src/main/java/org/jboss/envers/query/impl/RevisionsOfEntityQuery.java
core/trunk/envers/src/main/java/org/jboss/envers/query/order/
core/trunk/envers/src/main/java/org/jboss/envers/query/order/RevisionVersionsOrder.java
core/trunk/envers/src/main/java/org/jboss/envers/query/order/VersionsOrder.java
core/trunk/envers/src/main/java/org/jboss/envers/query/projection/
core/trunk/envers/src/main/java/org/jboss/envers/query/projection/RevisionVersionsProjection.java
core/trunk/envers/src/main/java/org/jboss/envers/query/projection/VersionsProjection.java
core/trunk/envers/src/main/java/org/jboss/envers/reader/
core/trunk/envers/src/main/java/org/jboss/envers/reader/FirstLevelCache.java
core/trunk/envers/src/main/java/org/jboss/envers/reader/VersionsReaderImpl.java
core/trunk/envers/src/main/java/org/jboss/envers/reader/VersionsReaderImplementor.java
core/trunk/envers/src/main/java/org/jboss/envers/revisioninfo/
core/trunk/envers/src/main/java/org/jboss/envers/revisioninfo/DefaultRevisionInfoGenerator.java
core/trunk/envers/src/main/java/org/jboss/envers/revisioninfo/RevisionInfoGenerator.java
core/trunk/envers/src/main/java/org/jboss/envers/revisioninfo/RevisionInfoNumberReader.java
core/trunk/envers/src/main/java/org/jboss/envers/revisioninfo/RevisionInfoQueryCreator.java
core/trunk/envers/src/main/java/org/jboss/envers/synchronization/
core/trunk/envers/src/main/java/org/jboss/envers/synchronization/VersionsSync.java
core/trunk/envers/src/main/java/org/jboss/envers/synchronization/VersionsSyncManager.java
core/trunk/envers/src/main/java/org/jboss/envers/synchronization/work/
core/trunk/envers/src/main/java/org/jboss/envers/synchronization/work/AbstractVersionsWorkUnit.java
core/trunk/envers/src/main/java/org/jboss/envers/synchronization/work/AddWorkUnit.java
core/trunk/envers/src/main/java/org/jboss/envers/synchronization/work/CollectionChangeWorkUnit.java
core/trunk/envers/src/main/java/org/jboss/envers/synchronization/work/DelWorkUnit.java
core/trunk/envers/src/main/java/org/jboss/envers/synchronization/work/KeepCheckDispatcher.java
core/trunk/envers/src/main/java/org/jboss/envers/synchronization/work/KeepCheckResult.java
core/trunk/envers/src/main/java/org/jboss/envers/synchronization/work/KeepCheckVisitor.java
core/trunk/envers/src/main/java/org/jboss/envers/synchronization/work/ModWorkUnit.java
core/trunk/envers/src/main/java/org/jboss/envers/synchronization/work/PersistentCollectionChangeWorkUnit.java
core/trunk/envers/src/main/java/org/jboss/envers/synchronization/work/VersionsWorkUnit.java
core/trunk/envers/src/main/java/org/jboss/envers/tools/
core/trunk/envers/src/main/java/org/jboss/envers/tools/ArgumentsTools.java
core/trunk/envers/src/main/java/org/jboss/envers/tools/ArraysTools.java
core/trunk/envers/src/main/java/org/jboss/envers/tools/ConcurrentReferenceHashMap.java
core/trunk/envers/src/main/java/org/jboss/envers/tools/HibernateVersion.java
core/trunk/envers/src/main/java/org/jboss/envers/tools/MutableBoolean.java
core/trunk/envers/src/main/java/org/jboss/envers/tools/MutableInteger.java
core/trunk/envers/src/main/java/org/jboss/envers/tools/Pair.java
core/trunk/envers/src/main/java/org/jboss/envers/tools/StringTools.java
core/trunk/envers/src/main/java/org/jboss/envers/tools/Tools.java
core/trunk/envers/src/main/java/org/jboss/envers/tools/Triple.java
core/trunk/envers/src/main/java/org/jboss/envers/tools/graph/
core/trunk/envers/src/main/java/org/jboss/envers/tools/graph/GraphDefiner.java
core/trunk/envers/src/main/java/org/jboss/envers/tools/graph/GraphTopologicalSort.java
core/trunk/envers/src/main/java/org/jboss/envers/tools/graph/TopologicalSort.java
core/trunk/envers/src/main/java/org/jboss/envers/tools/graph/Vertex.java
core/trunk/envers/src/main/java/org/jboss/envers/tools/log/
core/trunk/envers/src/main/java/org/jboss/envers/tools/log/YLog.java
core/trunk/envers/src/main/java/org/jboss/envers/tools/log/YLogManager.java
core/trunk/envers/src/main/java/org/jboss/envers/tools/query/
core/trunk/envers/src/main/java/org/jboss/envers/tools/query/Parameters.java
core/trunk/envers/src/main/java/org/jboss/envers/tools/query/QueryBuilder.java
core/trunk/envers/src/main/java/org/jboss/envers/tools/reflection/
core/trunk/envers/src/main/java/org/jboss/envers/tools/reflection/ReflectionTools.java
core/trunk/envers/src/main/java/org/jboss/envers/tools/reflection/YClass.java
core/trunk/envers/src/main/java/org/jboss/envers/tools/reflection/YMethodsAndClasses.java
core/trunk/envers/src/main/java/org/jboss/envers/tools/reflection/YProperty.java
core/trunk/envers/src/main/java/org/jboss/envers/tools/reflection/YReflectionManager.java
core/trunk/envers/src/main/resources/
core/trunk/envers/src/main/resources/META-INF/
core/trunk/envers/src/main/resources/META-INF/COPYING.txt
core/trunk/envers/src/main/resources/META-INF/copyright.txt
core/trunk/envers/src/test/
core/trunk/envers/src/test/java/
core/trunk/envers/src/test/java/org/
core/trunk/envers/src/test/java/org/jboss/
core/trunk/envers/src/test/java/org/jboss/envers/
core/trunk/envers/src/test/java/org/jboss/envers/test/
core/trunk/envers/src/test/java/org/jboss/envers/test/AbstractEntityTest.java
core/trunk/envers/src/test/java/org/jboss/envers/test/entities/
core/trunk/envers/src/test/java/org/jboss/envers/test/entities/IntTestEntity.java
core/trunk/envers/src/test/java/org/jboss/envers/test/entities/StrIntTestEntity.java
core/trunk/envers/src/test/java/org/jboss/envers/test/entities/StrTestEntity.java
core/trunk/envers/src/test/java/org/jboss/envers/test/entities/UnversionedEntity.java
core/trunk/envers/src/test/java/org/jboss/envers/test/entities/UnversionedStrTestEntity.java
core/trunk/envers/src/test/java/org/jboss/envers/test/entities/collection/
core/trunk/envers/src/test/java/org/jboss/envers/test/entities/collection/EnumSetEntity.java
core/trunk/envers/src/test/java/org/jboss/envers/test/entities/collection/StringListEntity.java
core/trunk/envers/src/test/java/org/jboss/envers/test/entities/collection/StringMapEntity.java
core/trunk/envers/src/test/java/org/jboss/envers/test/entities/collection/StringSetEntity.java
core/trunk/envers/src/test/java/org/jboss/envers/test/entities/components/
core/trunk/envers/src/test/java/org/jboss/envers/test/entities/components/Component1.java
core/trunk/envers/src/test/java/org/jboss/envers/test/entities/components/Component2.java
core/trunk/envers/src/test/java/org/jboss/envers/test/entities/components/ComponentTestEntity.java
core/trunk/envers/src/test/java/org/jboss/envers/test/entities/customtype/
core/trunk/envers/src/test/java/org/jboss/envers/test/entities/customtype/Component.java
core/trunk/envers/src/test/java/org/jboss/envers/test/entities/customtype/CompositeCustomTypeEntity.java
core/trunk/envers/src/test/java/org/jboss/envers/test/entities/customtype/CompositeTestUserType.java
core/trunk/envers/src/test/java/org/jboss/envers/test/entities/customtype/ParametrizedCustomTypeEntity.java
core/trunk/envers/src/test/java/org/jboss/envers/test/entities/customtype/ParametrizedTestUserType.java
core/trunk/envers/src/test/java/org/jboss/envers/test/entities/ids/
core/trunk/envers/src/test/java/org/jboss/envers/test/entities/ids/EmbId.java
core/trunk/envers/src/test/java/org/jboss/envers/test/entities/ids/EmbIdTestEntity.java
core/trunk/envers/src/test/java/org/jboss/envers/test/entities/ids/MulId.java
core/trunk/envers/src/test/java/org/jboss/envers/test/entities/ids/MulIdTestEntity.java
core/trunk/envers/src/test/java/org/jboss/envers/test/entities/manytomany/
core/trunk/envers/src/test/java/org/jboss/envers/test/entities/manytomany/ListOwnedEntity.java
core/trunk/envers/src/test/java/org/jboss/envers/test/entities/manytomany/ListOwningEntity.java
core/trunk/envers/src/test/java/org/jboss/envers/test/entities/manytomany/MapOwnedEntity.java
core/trunk/envers/src/test/java/org/jboss/envers/test/entities/manytomany/MapOwningEntity.java
core/trunk/envers/src/test/java/org/jboss/envers/test/entities/manytomany/SetOwnedEntity.java
core/trunk/envers/src/test/java/org/jboss/envers/test/entities/manytomany/SetOwningEntity.java
core/trunk/envers/src/test/java/org/jboss/envers/test/entities/manytomany/unidirectional/
core/trunk/envers/src/test/java/org/jboss/envers/test/entities/manytomany/unidirectional/ListUniEntity.java
core/trunk/envers/src/test/java/org/jboss/envers/test/entities/manytomany/unidirectional/MapUniEntity.java
core/trunk/envers/src/test/java/org/jboss/envers/test/entities/manytomany/unidirectional/SetUniEntity.java
core/trunk/envers/src/test/java/org/jboss/envers/test/entities/onetomany/
core/trunk/envers/src/test/java/org/jboss/envers/test/entities/onetomany/CollectionRefEdEntity.java
core/trunk/envers/src/test/java/org/jboss/envers/test/entities/onetomany/CollectionRefIngEntity.java
core/trunk/envers/src/test/java/org/jboss/envers/test/entities/onetomany/ListRefEdEntity.java
core/trunk/envers/src/test/java/org/jboss/envers/test/entities/onetomany/ListRefIngEntity.java
core/trunk/envers/src/test/java/org/jboss/envers/test/entities/onetomany/SetRefEdEntity.java
core/trunk/envers/src/test/java/org/jboss/envers/test/entities/onetomany/SetRefIngEntity.java
core/trunk/envers/src/test/java/org/jboss/envers/test/entities/onetomany/detached/
core/trunk/envers/src/test/java/org/jboss/envers/test/entities/onetomany/detached/DoubleSetRefCollEntity.java
core/trunk/envers/src/test/java/org/jboss/envers/test/entities/onetomany/detached/ListRefCollEntity.java
core/trunk/envers/src/test/java/org/jboss/envers/test/entities/onetomany/detached/SetJoinColumnRefCollEntity.java
core/trunk/envers/src/test/java/org/jboss/envers/test/entities/onetomany/detached/SetRefCollEntity.java
core/trunk/envers/src/test/java/org/jboss/envers/test/entities/onetomany/detached/ids/
core/trunk/envers/src/test/java/org/jboss/envers/test/entities/onetomany/detached/ids/SetRefCollEntityEmbId.java
core/trunk/envers/src/test/java/org/jboss/envers/test/entities/onetomany/detached/ids/SetRefCollEntityMulId.java
core/trunk/envers/src/test/java/org/jboss/envers/test/entities/onetomany/ids/
core/trunk/envers/src/test/java/org/jboss/envers/test/entities/onetomany/ids/SetRefEdEmbIdEntity.java
core/trunk/envers/src/test/java/org/jboss/envers/test/entities/onetomany/ids/SetRefEdMulIdEntity.java
core/trunk/envers/src/test/java/org/jboss/envers/test/entities/onetomany/ids/SetRefIngEmbIdEntity.java
core/trunk/envers/src/test/java/org/jboss/envers/test/entities/onetomany/ids/SetRefIngMulIdEntity.java
core/trunk/envers/src/test/java/org/jboss/envers/test/entities/reventity/
core/trunk/envers/src/test/java/org/jboss/envers/test/entities/reventity/CustomPropertyAccessRevEntity.java
core/trunk/envers/src/test/java/org/jboss/envers/test/entities/reventity/CustomRevEntity.java
core/trunk/envers/src/test/java/org/jboss/envers/test/integration/
core/trunk/envers/src/test/java/org/jboss/envers/test/integration/basic/
core/trunk/envers/src/test/java/org/jboss/envers/test/integration/basic/BasicTestEntity1.java
core/trunk/envers/src/test/java/org/jboss/envers/test/integration/basic/BasicTestEntity2.java
core/trunk/envers/src/test/java/org/jboss/envers/test/integration/basic/BasicTestEntity3.java
core/trunk/envers/src/test/java/org/jboss/envers/test/integration/basic/BasicTestEntity4.java
core/trunk/envers/src/test/java/org/jboss/envers/test/integration/basic/Delete.java
core/trunk/envers/src/test/java/org/jboss/envers/test/integration/basic/GlobalVersioned.java
core/trunk/envers/src/test/java/org/jboss/envers/test/integration/basic/ManyOperationsInTransaction.java
core/trunk/envers/src/test/java/org/jboss/envers/test/integration/basic/NotVersioned.java
core/trunk/envers/src/test/java/org/jboss/envers/test/integration/basic/NullProperties.java
core/trunk/envers/src/test/java/org/jboss/envers/test/integration/basic/Simple.java
core/trunk/envers/src/test/java/org/jboss/envers/test/integration/basic/SingleOperationInTransaction.java
core/trunk/envers/src/test/java/org/jboss/envers/test/integration/basic/UnversionedPropertiesChange.java
core/trunk/envers/src/test/java/org/jboss/envers/test/integration/basic/UnversionedProperty.java
core/trunk/envers/src/test/java/org/jboss/envers/test/integration/cache/
core/trunk/envers/src/test/java/org/jboss/envers/test/integration/cache/OneToManyCache.java
core/trunk/envers/src/test/java/org/jboss/envers/test/integration/cache/OneToOneCache.java
core/trunk/envers/src/test/java/org/jboss/envers/test/integration/cache/QueryCache.java
core/trunk/envers/src/test/java/org/jboss/envers/test/integration/collection/
core/trunk/envers/src/test/java/org/jboss/envers/test/integration/collection/EnumSet.java
core/trunk/envers/src/test/java/org/jboss/envers/test/integration/collection/StringList.java
core/trunk/envers/src/test/java/org/jboss/envers/test/integration/collection/StringMap.java
core/trunk/envers/src/test/java/org/jboss/envers/test/integration/collection/StringSet.java
core/trunk/envers/src/test/java/org/jboss/envers/test/integration/collection/mapkey/
core/trunk/envers/src/test/java/org/jboss/envers/test/integration/collection/mapkey/ComponentMapKey.java
core/trunk/envers/src/test/java/org/jboss/envers/test/integration/collection/mapkey/ComponentMapKeyEntity.java
core/trunk/envers/src/test/java/org/jboss/envers/test/integration/collection/mapkey/IdMapKey.java
core/trunk/envers/src/test/java/org/jboss/envers/test/integration/collection/mapkey/IdMapKeyEntity.java
core/trunk/envers/src/test/java/org/jboss/envers/test/integration/components/
core/trunk/envers/src/test/java/org/jboss/envers/test/integration/components/Components.java
core/trunk/envers/src/test/java/org/jboss/envers/test/integration/customtype/
core/trunk/envers/src/test/java/org/jboss/envers/test/integration/customtype/CompositeCustom.java
core/trunk/envers/src/test/java/org/jboss/envers/test/integration/customtype/ParametrizedCustom.java
core/trunk/envers/src/test/java/org/jboss/envers/test/integration/data/
core/trunk/envers/src/test/java/org/jboss/envers/test/integration/data/DateTestEntity.java
core/trunk/envers/src/test/java/org/jboss/envers/test/integration/data/Dates.java
core/trunk/envers/src/test/java/org/jboss/envers/test/integration/data/EnumTestEntity.java
core/trunk/envers/src/test/java/org/jboss/envers/test/integration/data/Enums.java
core/trunk/envers/src/test/java/org/jboss/envers/test/integration/data/LobTestEntity.java
core/trunk/envers/src/test/java/org/jboss/envers/test/integration/data/Lobs.java
core/trunk/envers/src/test/java/org/jboss/envers/test/integration/data/SerObject.java
core/trunk/envers/src/test/java/org/jboss/envers/test/integration/data/SerializableTestEntity.java
core/trunk/envers/src/test/java/org/jboss/envers/test/integration/data/Serializables.java
core/trunk/envers/src/test/java/org/jboss/envers/test/integration/flush/
core/trunk/envers/src/test/java/org/jboss/envers/test/integration/flush/AbstractFlushTest.java
core/trunk/envers/src/test/java/org/jboss/envers/test/integration/flush/DoubleFlushAddDel.java
core/trunk/envers/src/test/java/org/jboss/envers/test/integration/flush/DoubleFlushAddMod.java
core/trunk/envers/src/test/java/org/jboss/envers/test/integration/flush/DoubleFlushModDel.java
core/trunk/envers/src/test/java/org/jboss/envers/test/integration/flush/DoubleFlushModMod.java
core/trunk/envers/src/test/java/org/jboss/envers/test/integration/flush/ManualFlush.java
core/trunk/envers/src/test/java/org/jboss/envers/test/integration/ids/
core/trunk/envers/src/test/java/org/jboss/envers/test/integration/ids/CompositeIds.java
core/trunk/envers/src/test/java/org/jboss/envers/test/integration/inheritance/
core/trunk/envers/src/test/java/org/jboss/envers/test/integration/inheritance/single/
core/trunk/envers/src/test/java/org/jboss/envers/test/integration/inheritance/single/ChildEntity.java
core/trunk/envers/src/test/java/org/jboss/envers/test/integration/inheritance/single/ChildVersioning.java
core/trunk/envers/src/test/java/org/jboss/envers/test/integration/inheritance/single/ParentEntity.java
core/trunk/envers/src/test/java/org/jboss/envers/test/integration/inheritance/single/ParentVersioning.java
core/trunk/envers/src/test/java/org/jboss/envers/test/integration/inheritance/single/childrelation/
core/trunk/envers/src/test/java/org/jboss/envers/test/integration/inheritance/single/childrelation/ChildIngEntity.java
core/trunk/envers/src/test/java/org/jboss/envers/test/integration/inheritance/single/childrelation/ChildReferencing.java
core/trunk/envers/src/test/java/org/jboss/envers/test/integration/inheritance/single/childrelation/ParentNotIngEntity.java
core/trunk/envers/src/test/java/org/jboss/envers/test/integration/inheritance/single/childrelation/ReferencedEntity.java
core/trunk/envers/src/test/java/org/jboss/envers/test/integration/inheritance/single/relation/
core/trunk/envers/src/test/java/org/jboss/envers/test/integration/inheritance/single/relation/ChildIngEntity.java
core/trunk/envers/src/test/java/org/jboss/envers/test/integration/inheritance/single/relation/ParentIngEntity.java
core/trunk/envers/src/test/java/org/jboss/envers/test/integration/inheritance/single/relation/PolymorphicCollection.java
core/trunk/envers/src/test/java/org/jboss/envers/test/integration/inheritance/single/relation/ReferencedEntity.java
core/trunk/envers/src/test/java/org/jboss/envers/test/integration/manytomany/
core/trunk/envers/src/test/java/org/jboss/envers/test/integration/manytomany/BasicList.java
core/trunk/envers/src/test/java/org/jboss/envers/test/integration/manytomany/BasicMap.java
core/trunk/envers/src/test/java/org/jboss/envers/test/integration/manytomany/BasicSet.java
core/trunk/envers/src/test/java/org/jboss/envers/test/integration/manytomany/ternary/
core/trunk/envers/src/test/java/org/jboss/envers/test/integration/manytomany/ternary/TernaryMap.java
core/trunk/envers/src/test/java/org/jboss/envers/test/integration/manytomany/ternary/TernaryMapEntity.java
core/trunk/envers/src/test/java/org/jboss/envers/test/integration/manytomany/unidirectional/
core/trunk/envers/src/test/java/org/jboss/envers/test/integration/manytomany/unidirectional/BasicUniList.java
core/trunk/envers/src/test/java/org/jboss/envers/test/integration/manytomany/unidirectional/BasicUniMap.java
core/trunk/envers/src/test/java/org/jboss/envers/test/integration/manytomany/unidirectional/BasicUniSet.java
core/trunk/envers/src/test/java/org/jboss/envers/test/integration/naming/
core/trunk/envers/src/test/java/org/jboss/envers/test/integration/naming/BasicNaming.java
core/trunk/envers/src/test/java/org/jboss/envers/test/integration/naming/DetachedNamingTestEntity.java
core/trunk/envers/src/test/java/org/jboss/envers/test/integration/naming/JoinNaming.java
core/trunk/envers/src/test/java/org/jboss/envers/test/integration/naming/JoinNamingRefEdEntity.java
core/trunk/envers/src/test/java/org/jboss/envers/test/integration/naming/JoinNamingRefIngEntity.java
core/trunk/envers/src/test/java/org/jboss/envers/test/integration/naming/NamingTestEntity1.java
core/trunk/envers/src/test/java/org/jboss/envers/test/integration/naming/OneToManyUnidirectionalNaming.java
core/trunk/envers/src/test/java/org/jboss/envers/test/integration/naming/VersionsJoinTableNaming.java
core/trunk/envers/src/test/java/org/jboss/envers/test/integration/naming/VersionsJoinTableTestEntity.java
core/trunk/envers/src/test/java/org/jboss/envers/test/integration/naming/ids/
core/trunk/envers/src/test/java/org/jboss/envers/test/integration/naming/ids/EmbIdNaming.java
core/trunk/envers/src/test/java/org/jboss/envers/test/integration/naming/ids/JoinEmbIdNaming.java
core/trunk/envers/src/test/java/org/jboss/envers/test/integration/naming/ids/JoinEmbIdNamingRefEdEntity.java
core/trunk/envers/src/test/java/org/jboss/envers/test/integration/naming/ids/JoinEmbIdNamingRefIngEntity.java
core/trunk/envers/src/test/java/org/jboss/envers/test/integration/naming/ids/JoinMulIdNaming.java
core/trunk/envers/src/test/java/org/jboss/envers/test/integration/naming/ids/JoinMulIdNamingRefEdEntity.java
core/trunk/envers/src/test/java/org/jboss/envers/test/integration/naming/ids/JoinMulIdNamingRefIngEntity.java
core/trunk/envers/src/test/java/org/jboss/envers/test/integration/naming/ids/MulIdNaming.java
core/trunk/envers/src/test/java/org/jboss/envers/test/integration/notinsertable/
core/trunk/envers/src/test/java/org/jboss/envers/test/integration/notinsertable/NotInsertable.java
core/trunk/envers/src/test/java/org/jboss/envers/test/integration/notinsertable/NotInsertableTestEntity.java
core/trunk/envers/src/test/java/org/jboss/envers/test/integration/onetomany/
core/trunk/envers/src/test/java/org/jboss/envers/test/integration/onetomany/BasicCollection.java
core/trunk/envers/src/test/java/org/jboss/envers/test/integration/onetomany/BasicList.java
core/trunk/envers/src/test/java/org/jboss/envers/test/integration/onetomany/BasicSet.java
core/trunk/envers/src/test/java/org/jboss/envers/test/integration/onetomany/BasicSetWithEmbId.java
core/trunk/envers/src/test/java/org/jboss/envers/test/integration/onetomany/BasicSetWithMulId.java
core/trunk/envers/src/test/java/org/jboss/envers/test/integration/onetomany/BasicSetWithNullsDelete.java
core/trunk/envers/src/test/java/org/jboss/envers/test/integration/onetomany/BidirectionalMapKey.java
core/trunk/envers/src/test/java/org/jboss/envers/test/integration/onetomany/RefEdMapKeyEntity.java
core/trunk/envers/src/test/java/org/jboss/envers/test/integration/onetomany/RefIngMapKeyEntity.java
core/trunk/envers/src/test/java/org/jboss/envers/test/integration/onetomany/detached/
core/trunk/envers/src/test/java/org/jboss/envers/test/integration/onetomany/detached/BasicDetachedList.java
core/trunk/envers/src/test/java/org/jboss/envers/test/integration/onetomany/detached/BasicDetachedSet.java
core/trunk/envers/src/test/java/org/jboss/envers/test/integration/onetomany/detached/BasicDetachedSetWithEmbId.java
core/trunk/envers/src/test/java/org/jboss/envers/test/integration/onetomany/detached/BasicDetachedSetWithMulId.java
core/trunk/envers/src/test/java/org/jboss/envers/test/integration/onetomany/detached/BasicJoinColumnSet.java
core/trunk/envers/src/test/java/org/jboss/envers/test/integration/onetomany/detached/DataChangesDetachedSet.java
core/trunk/envers/src/test/java/org/jboss/envers/test/integration/onetomany/detached/DoubleDetachedSet.java
core/trunk/envers/src/test/java/org/jboss/envers/test/integration/onetoone/
core/trunk/envers/src/test/java/org/jboss/envers/test/integration/onetoone/bidirectional/
core/trunk/envers/src/test/java/org/jboss/envers/test/integration/onetoone/bidirectional/BiRefEdEntity.java
core/trunk/envers/src/test/java/org/jboss/envers/test/integration/onetoone/bidirectional/BiRefIngEntity.java
core/trunk/envers/src/test/java/org/jboss/envers/test/integration/onetoone/bidirectional/Bidirectional.java
core/trunk/envers/src/test/java/org/jboss/envers/test/integration/onetoone/bidirectional/Bidirectional2.java
core/trunk/envers/src/test/java/org/jboss/envers/test/integration/onetoone/bidirectional/BidirectionalNoNulls.java
core/trunk/envers/src/test/java/org/jboss/envers/test/integration/onetoone/bidirectional/ids/
core/trunk/envers/src/test/java/org/jboss/envers/test/integration/onetoone/bidirectional/ids/BiEmbIdRefEdEntity.java
core/trunk/envers/src/test/java/org/jboss/envers/test/integration/onetoone/bidirectional/ids/BiEmbIdRefIngEntity.java
core/trunk/envers/src/test/java/org/jboss/envers/test/integration/onetoone/bidirectional/ids/BiMulIdRefEdEntity.java
core/trunk/envers/src/test/java/org/jboss/envers/test/integration/onetoone/bidirectional/ids/BiMulIdRefIngEntity.java
core/trunk/envers/src/test/java/org/jboss/envers/test/integration/onetoone/bidirectional/ids/EmbIdBidirectional.java
core/trunk/envers/src/test/java/org/jboss/envers/test/integration/onetoone/bidirectional/ids/MulIdBidirectional.java
core/trunk/envers/src/test/java/org/jboss/envers/test/integration/onetoone/unidirectional/
core/trunk/envers/src/test/java/org/jboss/envers/test/integration/onetoone/unidirectional/UniRefEdEntity.java
core/trunk/envers/src/test/java/org/jboss/envers/test/integration/onetoone/unidirectional/UniRefIngEntity.java
core/trunk/envers/src/test/java/org/jboss/envers/test/integration/onetoone/unidirectional/Unidirectional.java
core/trunk/envers/src/test/java/org/jboss/envers/test/integration/onetoone/unidirectional/UnidirectionalWithNulls.java
core/trunk/envers/src/test/java/org/jboss/envers/test/integration/properties/
core/trunk/envers/src/test/java/org/jboss/envers/test/integration/properties/PropertiesTestEntity.java
core/trunk/envers/src/test/java/org/jboss/envers/test/integration/properties/UnversionedOptimisticLockingField.java
core/trunk/envers/src/test/java/org/jboss/envers/test/integration/properties/UnversionedOptimisticLockingFieldEntity.java
core/trunk/envers/src/test/java/org/jboss/envers/test/integration/properties/VersionsProperties.java
core/trunk/envers/src/test/java/org/jboss/envers/test/integration/query/
core/trunk/envers/src/test/java/org/jboss/envers/test/integration/query/AggregateQuery.java
core/trunk/envers/src/test/java/org/jboss/envers/test/integration/query/CustomRevEntityQuery.java
core/trunk/envers/src/test/java/org/jboss/envers/test/integration/query/DeletedEntities.java
core/trunk/envers/src/test/java/org/jboss/envers/test/integration/query/MaximalizePropertyQuery.java
core/trunk/envers/src/test/java/org/jboss/envers/test/integration/query/OrderByLimitQuery.java
core/trunk/envers/src/test/java/org/jboss/envers/test/integration/query/RevisionConstraintQuery.java
core/trunk/envers/src/test/java/org/jboss/envers/test/integration/query/SimpleQuery.java
core/trunk/envers/src/test/java/org/jboss/envers/test/integration/query/ids/
core/trunk/envers/src/test/java/org/jboss/envers/test/integration/query/ids/EmbIdOneToManyQuery.java
core/trunk/envers/src/test/java/org/jboss/envers/test/integration/query/ids/MulIdOneToManyQuery.java
core/trunk/envers/src/test/java/org/jboss/envers/test/integration/reventity/
core/trunk/envers/src/test/java/org/jboss/envers/test/integration/reventity/Custom.java
core/trunk/envers/src/test/java/org/jboss/envers/test/integration/reventity/CustomBoxed.java
core/trunk/envers/src/test/java/org/jboss/envers/test/integration/reventity/CustomBoxedRevEntity.java
core/trunk/envers/src/test/java/org/jboss/envers/test/integration/reventity/CustomPropertyAccess.java
core/trunk/envers/src/test/java/org/jboss/envers/test/integration/reventity/Inherited.java
core/trunk/envers/src/test/java/org/jboss/envers/test/integration/reventity/InheritedRevEntity.java
core/trunk/envers/src/test/java/org/jboss/envers/test/integration/reventity/Listener.java
core/trunk/envers/src/test/java/org/jboss/envers/test/integration/reventity/ListenerRevEntity.java
core/trunk/envers/src/test/java/org/jboss/envers/test/integration/reventity/LongRevNumber.java
core/trunk/envers/src/test/java/org/jboss/envers/test/integration/reventity/LongRevNumberRevEntity.java
core/trunk/envers/src/test/java/org/jboss/envers/test/integration/reventity/TestRevisionListener.java
core/trunk/envers/src/test/java/org/jboss/envers/test/integration/revfordate/
core/trunk/envers/src/test/java/org/jboss/envers/test/integration/revfordate/RevisionForDate.java
core/trunk/envers/src/test/java/org/jboss/envers/test/integration/sameids/
core/trunk/envers/src/test/java/org/jboss/envers/test/integration/sameids/SameIdTestEntity1.java
core/trunk/envers/src/test/java/org/jboss/envers/test/integration/sameids/SameIdTestEntity2.java
core/trunk/envers/src/test/java/org/jboss/envers/test/integration/sameids/SameIds.java
core/trunk/envers/src/test/java/org/jboss/envers/test/integration/secondary/
core/trunk/envers/src/test/java/org/jboss/envers/test/integration/secondary/BasicSecondary.java
core/trunk/envers/src/test/java/org/jboss/envers/test/integration/secondary/NamingSecondary.java
core/trunk/envers/src/test/java/org/jboss/envers/test/integration/secondary/SecondaryNamingTestEntity.java
core/trunk/envers/src/test/java/org/jboss/envers/test/integration/secondary/SecondaryTestEntity.java
core/trunk/envers/src/test/java/org/jboss/envers/test/integration/secondary/ids/
core/trunk/envers/src/test/java/org/jboss/envers/test/integration/secondary/ids/EmbIdSecondary.java
core/trunk/envers/src/test/java/org/jboss/envers/test/integration/secondary/ids/MulIdSecondary.java
core/trunk/envers/src/test/java/org/jboss/envers/test/integration/secondary/ids/SecondaryEmbIdTestEntity.java
core/trunk/envers/src/test/java/org/jboss/envers/test/integration/secondary/ids/SecondaryMulIdTestEntity.java
core/trunk/envers/src/test/java/org/jboss/envers/test/integration/superclass/
core/trunk/envers/src/test/java/org/jboss/envers/test/integration/superclass/MappedSubclassing.java
core/trunk/envers/src/test/java/org/jboss/envers/test/integration/superclass/SubclassEntity.java
core/trunk/envers/src/test/java/org/jboss/envers/test/integration/superclass/SuperclassOfEntity.java
core/trunk/envers/src/test/java/org/jboss/envers/test/performance/
core/trunk/envers/src/test/java/org/jboss/envers/test/performance/AbstractPerformanceTest.java
core/trunk/envers/src/test/java/org/jboss/envers/test/performance/InsertsPerformance.java
core/trunk/envers/src/test/java/org/jboss/envers/test/performance/UpdatesPerformance.java
core/trunk/envers/src/test/java/org/jboss/envers/test/tools/
core/trunk/envers/src/test/java/org/jboss/envers/test/tools/TestTools.java
core/trunk/envers/src/test/java/org/jboss/envers/test/various/
core/trunk/envers/src/test/java/org/jboss/envers/test/various/Address.java
core/trunk/envers/src/test/java/org/jboss/envers/test/various/HsqlTest.java
core/trunk/envers/src/test/java/org/jboss/envers/test/various/Person.java
core/trunk/envers/src/test/resources/
core/trunk/envers/src/test/resources/hibernate.test.cfg.xml
core/trunk/envers/src/test/resources/testng.xml
Modified:
core/trunk/pom.xml
Log:
HHH-3351 : import envers as core module
Property changes on: core/trunk/envers
___________________________________________________________________
Name: svn:ignore
+ target
local
*.ipr
*.iws
*.iml
.classpath
.project
.nbattrs
*.log
*.properties
.clover
Added: core/trunk/envers/pom.xml
===================================================================
--- core/trunk/envers/pom.xml (rev 0)
+++ core/trunk/envers/pom.xml 2008-10-27 18:56:31 UTC (rev 15406)
@@ -0,0 +1,235 @@
+<project xmlns="http://maven.apache.org/POM/4.0.0"
+ xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+ xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
+
+ <modelVersion>4.0.0</modelVersion>
+
+ <parent>
+ <groupId>org.hibernate</groupId>
+ <artifactId>hibernate-parent</artifactId>
+ <version>3.4.0-SNAPSHOT</version>
+ <relativePath>../parent/pom.xml</relativePath>
+ </parent>
+
+ <groupId>org.hibernate</groupId>
+ <artifactId>hibernate-envers</artifactId>
+ <packaging>jar</packaging>
+
+ <name>Hibernate Envers</name>
+ <description>Support for entity historizing</description>
+
+ <build>
+ <plugins>
+ <plugin>
+ <groupId>org.apache.maven.plugins</groupId>
+ <artifactId>maven-compiler-plugin</artifactId>
+ <configuration>
+ <source>1.5</source>
+ <target>1.5</target>
+ </configuration>
+ </plugin>
+
+ <plugin>
+ <groupId>org.apache.maven.plugins</groupId>
+ <artifactId>maven-surefire-plugin</artifactId>
+ <configuration>
+ <systemProperties>
+ </systemProperties>
+ <suiteXmlFiles>
+ <suiteXmlFile>resources/test/testng.xml</suiteXmlFile>
+ </suiteXmlFiles>
+ </configuration>
+ </plugin>
+
+ <!-- javadocs : we want these run in the 'package' lifecycle phase-->
+ <plugin>
+ <groupId>org.apache.maven.plugins</groupId>
+ <artifactId>maven-javadoc-plugin</artifactId>
+ <executions>
+ <execution>
+ <phase>package</phase>
+ <goals>
+ <goal>javadoc</goal>
+ </goals>
+ <configuration>
+ <aggregate>${jbossenvers.reports.aggregate}</aggregate>
+ <links>
+ <link>http://java.sun.com/j2se/1.5.0/docs/api/</link>
+ <link>http://java.sun.com/javaee/5/docs/api/</link>
+ </links>
+ </configuration>
+ </execution>
+ </executions>
+ </plugin>
+ </plugins>
+ </build>
+
+ <dependencies>
+ <dependency>
+ <groupId>org.hibernate</groupId>
+ <artifactId>hibernate-core</artifactId>
+ </dependency>
+ <dependency>
+ <groupId>javax.persistence</groupId>
+ <artifactId>persistence-api</artifactId>
+ </dependency>
+ <dependency>
+ <groupId>org.hibernate</groupId>
+ <artifactId>hibernate-annotations</artifactId>
+ <exclusions>
+ <!-- todo : only needed until we migrate annotations/em back to core -->
+ <exclusion>
+ <groupId>org.hibernate</groupId>
+ <artifactId>hibernate</artifactId>
+ </exclusion>
+ <exclusion>
+ <groupId>net.sf.ehcache</groupId>
+ <artifactId>ehcache</artifactId>
+ </exclusion>
+ <exclusion>
+ <groupId>cglib</groupId>
+ <artifactId>cglib</artifactId>
+ </exclusion>
+ <exclusion>
+ <groupId>asm</groupId>
+ <artifactId>asm</artifactId>
+ </exclusion>
+ <exclusion>
+ <groupId>asm</groupId>
+ <artifactId>asm-attrs</artifactId>
+ </exclusion>
+ </exclusions>
+ </dependency>
+ <dependency>
+ <groupId>org.hibernate</groupId>
+ <artifactId>hibernate-commons-annotations</artifactId>
+ <exclusions>
+ <!-- todo : only needed until we migrate annotations/em back to core -->
+ <exclusion>
+ <groupId>org.hibernate</groupId>
+ <artifactId>hibernate</artifactId>
+ </exclusion>
+ <exclusion>
+ <groupId>net.sf.ehcache</groupId>
+ <artifactId>ehcache</artifactId>
+ </exclusion>
+ <exclusion>
+ <groupId>cglib</groupId>
+ <artifactId>cglib</artifactId>
+ </exclusion>
+ <exclusion>
+ <groupId>asm</groupId>
+ <artifactId>asm</artifactId>
+ </exclusion>
+ <exclusion>
+ <groupId>asm</groupId>
+ <artifactId>asm-attrs</artifactId>
+ </exclusion>
+ </exclusions>
+ </dependency>
+ <dependency>
+ <groupId>org.hibernate</groupId>
+ <artifactId>hibernate-entitymanager</artifactId>
+ <exclusions>
+ <!-- todo : only needed until we migrate annotations/em back to core -->
+ <exclusion>
+ <groupId>org.hibernate</groupId>
+ <artifactId>hibernate</artifactId>
+ </exclusion>
+ <exclusion>
+ <groupId>net.sf.ehcache</groupId>
+ <artifactId>ehcache</artifactId>
+ </exclusion>
+ <exclusion>
+ <groupId>cglib</groupId>
+ <artifactId>cglib</artifactId>
+ </exclusion>
+ <exclusion>
+ <groupId>asm</groupId>
+ <artifactId>asm</artifactId>
+ </exclusion>
+ <exclusion>
+ <groupId>asm</groupId>
+ <artifactId>asm-attrs</artifactId>
+ </exclusion>
+ </exclusions>
+ </dependency>
+ <dependency>
+ <groupId>org.hibernate</groupId>
+ <artifactId>hibernate-tools</artifactId>
+ </dependency>
+ <dependency>
+ <groupId>ant</groupId>
+ <artifactId>ant</artifactId>
+ <scope>provided</scope>
+ </dependency>
+
+ <dependency>
+ <groupId>org.testng</groupId>
+ <artifactId>testng</artifactId>
+ <version>5.8</version>
+ <scope>test</scope>
+ <classifier>jdk15</classifier>
+ </dependency>
+ <dependency>
+ <groupId>hsqldb</groupId>
+ <artifactId>hsqldb</artifactId>
+ <version>1.8.0.7</version>
+ <scope>test</scope>
+ </dependency>
+ <dependency>
+ <groupId>mysql</groupId>
+ <artifactId>mysql-connector-java</artifactId>
+ <version>5.1.6</version>
+ </dependency>
+ </dependencies>
+
+ <dependencyManagement>
+ <dependencies>
+ <dependency>
+ <groupId>org.hibernate</groupId>
+ <artifactId>hibernate-core</artifactId>
+ <version>${version}</version>
+ </dependency>
+ <dependency>
+ <groupId>javax.persistence</groupId>
+ <artifactId>persistence-api</artifactId>
+ <version>1.0</version>
+ </dependency>
+ <!-- todo : change to work like hibernate-core after we import annotations and em back into core -->
+ <dependency>
+ <groupId>org.hibernate</groupId>
+ <artifactId>hibernate-annotations</artifactId>
+ <version>3.3.0.ga</version>
+ </dependency>
+ <!-- todo : change to work like hibernate-core after we import annotations and em back into core -->
+ <dependency>
+ <groupId>org.hibernate</groupId>
+ <artifactId>hibernate-commons-annotations</artifactId>
+ <version>3.3.0.ga</version>
+ </dependency>
+ <!-- todo : change to work like hibernate-core after we import annotations and em back into core -->
+ <dependency>
+ <groupId>org.hibernate</groupId>
+ <artifactId>hibernate-entitymanager</artifactId>
+ <version>3.3.1.ga</version>
+ </dependency>
+ <dependency>
+ <groupId>org.hibernate</groupId>
+ <artifactId>hibernate-tools</artifactId>
+ <version>3.2.0.ga</version>
+ </dependency>
+ <dependency>
+ <groupId>ant</groupId>
+ <artifactId>ant</artifactId>
+ <version>1.6.5</version>
+ </dependency>
+ </dependencies>
+ </dependencyManagement>
+
+ <properties>
+ <!-- for now, at least, lets aggregate them -->
+ <jbossenvers.reports.aggregate>true</jbossenvers.reports.aggregate>
+ </properties>
+
+</project>
Added: core/trunk/envers/src/demo/java/org/jboss/envers/demo/Address.java
===================================================================
--- core/trunk/envers/src/demo/java/org/jboss/envers/demo/Address.java (rev 0)
+++ core/trunk/envers/src/demo/java/org/jboss/envers/demo/Address.java 2008-10-27 18:56:31 UTC (rev 15406)
@@ -0,0 +1,113 @@
+/*
+ * Envers. http://www.jboss.org/envers
+ *
+ * Copyright 2008 Red Hat Middleware, LLC. All rights reserved.
+ *
+ * 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, v. 2.1.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT A 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, v.2.1 along with this distribution; if not, write to the Free
+ * Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+ * 02110-1301, USA.
+ *
+ * Red Hat Author(s): Adam Warski
+ */
+package org.jboss.envers.demo;
+
+import org.jboss.envers.Versioned;
+
+import javax.persistence.*;
+import java.util.Set;
+
+/**
+ * @author Adam Warski (adam at warski dot org)
+ */
+ at Entity
+public class Address {
+ @Id
+ @GeneratedValue
+ private int id;
+
+ @Versioned
+ private String streetName;
+
+ @Versioned
+ private Integer houseNumber;
+
+ @Versioned
+ private Integer flatNumber;
+
+ @Versioned
+ @OneToMany(mappedBy = "address")
+ private Set<Person> persons;
+
+ public int getId() {
+ return id;
+ }
+
+ public void setId(int id) {
+ this.id = id;
+ }
+
+ public String getStreetName() {
+ return streetName;
+ }
+
+ public void setStreetName(String streetName) {
+ this.streetName = streetName;
+ }
+
+ public Integer getHouseNumber() {
+ return houseNumber;
+ }
+
+ public void setHouseNumber(Integer houseNumber) {
+ this.houseNumber = houseNumber;
+ }
+
+ public Integer getFlatNumber() {
+ return flatNumber;
+ }
+
+ public void setFlatNumber(Integer flatNumber) {
+ this.flatNumber = flatNumber;
+ }
+
+ public Set<Person> getPersons() {
+ return persons;
+ }
+
+ public void setPersons(Set<Person> persons) {
+ this.persons = persons;
+ }
+
+ public boolean equals(Object o) {
+ if (this == o) return true;
+ if (!(o instanceof Address)) return false;
+
+ Address address = (Address) o;
+
+ if (id != address.id) return false;
+ if (flatNumber != null ? !flatNumber.equals(address.flatNumber) : address.flatNumber != null) return false;
+ if (houseNumber != null ? !houseNumber.equals(address.houseNumber) : address.houseNumber != null) return false;
+ if (streetName != null ? !streetName.equals(address.streetName) : address.streetName != null) return false;
+
+ return true;
+ }
+
+ public int hashCode() {
+ int result;
+ result = id;
+ result = 31 * result + (streetName != null ? streetName.hashCode() : 0);
+ result = 31 * result + (houseNumber != null ? houseNumber.hashCode() : 0);
+ result = 31 * result + (flatNumber != null ? flatNumber.hashCode() : 0);
+ return result;
+ }
+}
Added: core/trunk/envers/src/demo/java/org/jboss/envers/demo/Person.java
===================================================================
--- core/trunk/envers/src/demo/java/org/jboss/envers/demo/Person.java (rev 0)
+++ core/trunk/envers/src/demo/java/org/jboss/envers/demo/Person.java 2008-10-27 18:56:31 UTC (rev 15406)
@@ -0,0 +1,99 @@
+/*
+ * Envers. http://www.jboss.org/envers
+ *
+ * Copyright 2008 Red Hat Middleware, LLC. All rights reserved.
+ *
+ * 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, v. 2.1.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT A 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, v.2.1 along with this distribution; if not, write to the Free
+ * Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+ * 02110-1301, USA.
+ *
+ * Red Hat Author(s): Adam Warski
+ */
+package org.jboss.envers.demo;
+
+import org.jboss.envers.Versioned;
+
+import javax.persistence.*;
+
+/**
+ * @author Adam Warski (adam at warski dot org)
+ */
+ at Entity
+public class Person {
+ @Id
+ @GeneratedValue
+ private int id;
+
+ @Versioned
+ private String name;
+
+ @Versioned
+ private String surname;
+
+ @Versioned
+ @ManyToOne
+ private Address address;
+
+ public int getId() {
+ return id;
+ }
+
+ public void setId(int id) {
+ this.id = id;
+ }
+
+ public String getName() {
+ return name;
+ }
+
+ public void setName(String name) {
+ this.name = name;
+ }
+
+ public String getSurname() {
+ return surname;
+ }
+
+ public void setSurname(String surname) {
+ this.surname = surname;
+ }
+
+ public Address getAddress() {
+ return address;
+ }
+
+ public void setAddress(Address address) {
+ this.address = address;
+ }
+
+ public boolean equals(Object o) {
+ if (this == o) return true;
+ if (!(o instanceof Person)) return false;
+
+ Person person = (Person) o;
+
+ if (id != person.id) return false;
+ if (name != null ? !name.equals(person.name) : person.name != null) return false;
+ if (surname != null ? !surname.equals(person.surname) : person.surname != null) return false;
+
+ return true;
+ }
+
+ public int hashCode() {
+ int result;
+ result = id;
+ result = 31 * result + (name != null ? name.hashCode() : 0);
+ result = 31 * result + (surname != null ? surname.hashCode() : 0);
+ return result;
+ }
+}
Added: core/trunk/envers/src/demo/java/org/jboss/envers/demo/TestConsole.java
===================================================================
--- core/trunk/envers/src/demo/java/org/jboss/envers/demo/TestConsole.java (rev 0)
+++ core/trunk/envers/src/demo/java/org/jboss/envers/demo/TestConsole.java 2008-10-27 18:56:31 UTC (rev 15406)
@@ -0,0 +1,467 @@
+/*
+ * Envers. http://www.jboss.org/envers
+ *
+ * Copyright 2008 Red Hat Middleware, LLC. All rights reserved.
+ *
+ * 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, v. 2.1.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT A 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, v.2.1 along with this distribution; if not, write to the Free
+ * Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+ * 02110-1301, USA.
+ *
+ * Red Hat Author(s): Adam Warski
+ */
+package org.jboss.envers.demo;
+
+import org.jboss.envers.VersionsReader;
+import org.jboss.envers.VersionsReaderFactory;
+import org.jboss.envers.DefaultRevisionEntity;
+import org.jboss.envers.query.VersionsRestrictions;
+
+import javax.persistence.EntityManager;
+import javax.persistence.EntityManagerFactory;
+import javax.persistence.Persistence;
+import java.util.*;
+import java.io.PrintStream;
+import java.io.File;
+
+/**
+ * @author Adam Warski (adam at warski dot org)
+ */
+public class TestConsole {
+ private EntityManager entityManager;
+
+ public TestConsole(EntityManager entityManager) {
+ this.entityManager = entityManager;
+ }
+
+ private String convertString(String s, String def) {
+ if ("NULL".equals(s)) { return null; }
+ if ("".equals(s)) { return def; }
+ return s;
+ }
+
+ private int convertStringToInteger(String s, int def) {
+ if ("".equals(s)) { return def; }
+ try {
+ return Integer.parseInt(s);
+ } catch (NumberFormatException e) {
+ System.err.println("Invalid number, returning 0.");
+ return 0;
+ }
+ }
+
+ private void printPerson(StringBuilder sb, Person p) {
+ sb.append("id = ").append(p.getId()).append(", name = ").append(p.getName())
+ .append(", surname = ").append(p.getSurname());
+
+ Address a = p.getAddress();
+ if (a != null) {
+ sb.append(", address = <").append(a.getId()).append("> ").append(a.getStreetName()).append(" ")
+ .append(a.getHouseNumber()).append("/").append(a.getFlatNumber());
+ }
+ }
+
+ @SuppressWarnings({"unchecked"})
+ private void printPersons(StringBuilder sb) {
+ List<Person> persons = entityManager.createQuery(
+ "select p from Person p order by p.id").getResultList();
+
+ sb.append("Persons:\n");
+ for (Person p : persons) {
+ printPerson(sb, p);
+ sb.append("\n");
+ }
+ }
+
+ private void printPersonHistory(StringBuilder sb, int personId) {
+ VersionsReader reader = VersionsReaderFactory.get(entityManager);
+
+ List personHistory = reader.createQuery()
+ .forRevisionsOfEntity(Person.class, false, true)
+ .add(VersionsRestrictions.idEq(personId))
+ .getResultList();
+
+ if (personHistory.size() == 0) {
+ sb.append("A person with id ").append(personId).append(" does not exist.\n");
+ } else {
+ for (Object historyObj : personHistory) {
+ Object[] history = (Object[]) historyObj;
+ DefaultRevisionEntity revision = (DefaultRevisionEntity) history[1];
+ sb.append("revision = ").append(revision.getId()).append(", ");
+ printPerson(sb, (Person) history[0]);
+ sb.append(" (").append(revision.getRevisionDate()).append(")\n");
+ }
+ }
+ }
+
+ private void printPersonAtRevision(StringBuilder sb, int personId, int revision) {
+ VersionsReader reader = VersionsReaderFactory.get(entityManager);
+
+ Person p = reader.find(Person.class, personId, revision);
+ if (p == null) {
+ sb.append("This person does not exist at that revision.");
+ } else {
+ printPerson(sb, p);
+ }
+ }
+
+ private void readAndSetAddress(Scanner scanner, Person p) {
+ Address old = p.getAddress();
+
+ String input = scanner.nextLine();
+ if ("NULL".equals(input)) {
+ p.setAddress(null);
+ if (old != null) {
+ old.getPersons().remove(p);
+ }
+ } else if ("".equals(input)) {
+ } else {
+ try {
+ Integer id = Integer.valueOf(input);
+
+ Address a = entityManager.find(Address.class, id);
+
+ if (a == null) {
+ System.err.println("Unknown address id, setting to NULL.");
+ p.setAddress(null);
+ if (old != null) {
+ old.getPersons().remove(p);
+ }
+ } else {
+ p.setAddress(a);
+
+ a.getPersons().add(p);
+
+ if (old != null) {
+ old.getPersons().remove(p);
+ }
+ }
+ } catch (NumberFormatException e) {
+ System.err.println("Invalid address id, setting to NULL.");
+ p.setAddress(null);
+ if (old != null) {
+ old.getPersons().remove(p);
+ }
+ }
+ }
+ }
+
+ private Person readNewPerson(PrintStream out, Scanner scanner) {
+ Person p = new Person();
+
+ out.print("Person name (NULL for null): ");
+ p.setName(convertString(scanner.nextLine(), ""));
+
+ out.print("Person surname (NULL for null): ");
+ p.setSurname(convertString(scanner.nextLine(), ""));
+
+ out.print("Person address id (NULL for null): ");
+ readAndSetAddress(scanner, p);
+
+ return p;
+ }
+
+ private void readModifyPerson(PrintStream out, Scanner scanner, int personId) {
+ Person current = entityManager.find(Person.class, personId);
+
+ if (current == null) {
+ out.println("Person with id " + personId + " does not exist.");
+ return;
+ }
+
+ out.print("Person name (NULL for null, enter for no change, current - " + current.getName() + "): ");
+ current.setName(convertString(scanner.nextLine(), current.getName()));
+
+ out.print("Person surname (NULL for null, enter for no change, current - " + current.getSurname() + "): ");
+ current.setSurname(convertString(scanner.nextLine(), current.getSurname()));
+
+ out.print("Person address id (NULL for null, enter for no change, current - " +
+ (current.getAddress() == null ? "NULL" : current.getAddress().getId()) + "): ");
+ readAndSetAddress(scanner, current);
+ }
+
+ private void printAddress(StringBuilder sb, Address a) {
+ sb.append("id = ").append(a.getId()).append(", streetName = ").append(a.getStreetName())
+ .append(", houseNumber = ").append(a.getHouseNumber())
+ .append(", flatNumber = ").append(a.getFlatNumber())
+ .append(", persons = (");
+
+ Iterator<Person> iter = a.getPersons().iterator();
+ while (iter.hasNext()) {
+ Person p = iter.next();
+ sb.append("<").append(p.getId()).append("> ").append(p.getName()).append(" ").append(p.getSurname());
+ if (iter.hasNext()) {
+ sb.append(", ");
+ }
+ }
+
+ sb.append(")");
+ }
+
+ @SuppressWarnings({"unchecked"})
+ private void printAddresses(StringBuilder sb) {
+ List<Address> addresses = entityManager.createQuery(
+ "select a from Address a order by a.id").getResultList();
+
+ sb.append("Addresses:\n");
+ for (Address a : addresses) {
+ printAddress(sb, a);
+ sb.append("\n");
+ }
+ }
+
+ private void printAddressHistory(StringBuilder sb, int addressId) {
+ VersionsReader reader = VersionsReaderFactory.get(entityManager);
+
+ List addressHistory = reader.createQuery()
+ .forRevisionsOfEntity(Address.class, false, true)
+ .add(VersionsRestrictions.idEq(addressId))
+ .getResultList();
+
+ if (addressHistory.size() == 0) {
+ sb.append("A address with id ").append(addressId).append(" does not exist.\n");
+ } else {
+ for (Object historyObj : addressHistory) {
+ Object[] history = (Object[]) historyObj;
+ DefaultRevisionEntity revision = (DefaultRevisionEntity) history[1];
+ sb.append("revision = ").append(revision.getId()).append(", ");
+ printAddress(sb, (Address) history[0]);
+ sb.append(" (").append(revision.getRevisionDate()).append(")\n");
+ }
+ }
+ }
+
+ private void printAddressAtRevision(StringBuilder sb, int addressId, int revision) {
+ VersionsReader reader = VersionsReaderFactory.get(entityManager);
+
+ Address a = reader.find(Address.class, addressId, revision);
+ if (a == null) {
+ sb.append("This address does not exist at that revision.");
+ } else {
+ printAddress(sb, a);
+ }
+ }
+
+ private Address readNewAddress(PrintStream out, Scanner scanner) {
+ Address a = new Address();
+
+ out.print("Street name (NULL for null): ");
+ a.setStreetName(convertString(scanner.nextLine(), ""));
+
+ out.print("House number: ");
+ a.setHouseNumber(convertStringToInteger(scanner.nextLine(), 0));
+
+ out.print("Flat number: ");
+ a.setFlatNumber(convertStringToInteger(scanner.nextLine(), 0));
+
+ a.setPersons(new HashSet<Person>());
+
+ return a;
+ }
+
+ private void readModifyAddress(PrintStream out, Scanner scanner, int addressId) {
+ Address current = entityManager.find(Address.class, addressId);
+
+ if (current == null) {
+ out.println("Address with id " + addressId + " does not exist.");
+ return;
+ }
+
+ out.print("Street name (NULL for null, enter for no change, current - " + current.getStreetName() + "): ");
+ current.setStreetName(convertString(scanner.nextLine(), current.getStreetName()));
+
+ out.print("House number (enter for no change, current - " + current.getHouseNumber() + "): ");
+ current.setHouseNumber(convertStringToInteger(scanner.nextLine(), current.getHouseNumber()));
+
+ out.print("Flat number (enter for no change, current - " + current.getFlatNumber() + "): ");
+ current.setFlatNumber(convertStringToInteger(scanner.nextLine(), current.getFlatNumber()));
+ }
+
+ private void start() {
+ Scanner scanner = new Scanner(System.in);
+ PrintStream out = System.out;
+
+ while (true) {
+ out.println("-----------------------------------------------");
+ out.println("1 - list persons 5 - list addresses");
+ out.println("2 - list person history 6 - list addresses history");
+ out.println("3 - new person 7 - new address");
+ out.println("4 - modify person 8 - modify address");
+ out.println("9 - get person at revision 10 - get address at revision");
+ out.println(" 0 - end");
+
+ try {
+ int choice = scanner.nextInt();
+
+ scanner.nextLine();
+
+ entityManager.getTransaction().begin();
+
+ StringBuilder sb;
+ int personId;
+ int addressId;
+ int revision;
+ switch (choice) {
+ case 1:
+ sb = new StringBuilder();
+ printPersons(sb);
+ out.println(sb.toString());
+ break;
+ case 2:
+ out.print("Person id: ");
+ personId = scanner.nextInt(); scanner.nextLine();
+ sb = new StringBuilder();
+ printPersonHistory(sb, personId);
+ out.println(sb.toString());
+ break;
+ case 3:
+ Person p = readNewPerson(out, scanner);
+ entityManager.persist(p);
+ break;
+ case 4:
+ out.print("Person id: ");
+ personId = scanner.nextInt(); scanner.nextLine();
+ readModifyPerson(out, scanner, personId);
+ break;
+ case 5:
+ sb = new StringBuilder();
+ printAddresses(sb);
+ out.println(sb.toString());
+ break;
+ case 6:
+ out.print("Address id: ");
+ addressId = scanner.nextInt(); scanner.nextLine();
+ sb = new StringBuilder();
+ printAddressHistory(sb, addressId);
+ out.println(sb.toString());
+ break;
+ case 7:
+ Address a = readNewAddress(out, scanner);
+ entityManager.persist(a);
+ break;
+ case 8:
+ out.print("Address id: ");
+ addressId = scanner.nextInt(); scanner.nextLine();
+ readModifyAddress(out, scanner, addressId);
+ break;
+ case 9:
+ out.print("Person id: ");
+ personId = scanner.nextInt(); scanner.nextLine();
+ out.print("Revision number: ");
+ revision = scanner.nextInt(); scanner.nextLine();
+ if (revision <= 0) {
+ System.out.println("Revision must be greater then 0!");
+ continue;
+ }
+ sb = new StringBuilder();
+ printPersonAtRevision(sb, personId, revision);
+ out.println(sb.toString());
+ break;
+ case 10:
+ out.print("Address id: ");
+ addressId = scanner.nextInt(); scanner.nextLine();
+ out.print("Revision number: ");
+ revision = scanner.nextInt(); scanner.nextLine();
+ if (revision <= 0) {
+ System.out.println("Revision must be greater then 0!");
+ continue;
+ }
+ sb = new StringBuilder();
+ printAddressAtRevision(sb, addressId, revision);
+ out.println(sb.toString());
+ break;
+
+ case 0:
+ return;
+ }
+ } catch (InputMismatchException e) {
+ // continuing
+ } finally {
+ entityManager.getTransaction().commit();
+ }
+ }
+ }
+
+ private boolean hasData() {
+ return (((Long) entityManager.createQuery("select count(a) from Address a").getSingleResult()) +
+ ((Long) entityManager.createQuery("select count(p) from Person p").getSingleResult())) > 0;
+ }
+
+ private void populateTestData() {
+ entityManager.getTransaction().begin();
+
+ if (!hasData()) {
+ Person p1 = new Person();
+ Person p2 = new Person();
+ Person p3 = new Person();
+
+ Address a1 = new Address();
+ Address a2 = new Address();
+
+ p1.setName("James");
+ p1.setSurname("Bond");
+ p1.setAddress(a1);
+
+ p2.setName("John");
+ p2.setSurname("McClane");
+ p2.setAddress(a2);
+
+ p3.setName("Holly");
+ p3.setSurname("Gennaro");
+ p3.setAddress(a2);
+
+ a1.setStreetName("MI6");
+ a1.setHouseNumber(18);
+ a1.setFlatNumber(25);
+ a1.setPersons(new HashSet<Person>());
+ a1.getPersons().add(p1);
+
+ a2.setStreetName("Nakatomi Plaza");
+ a2.setHouseNumber(10);
+ a2.setFlatNumber(34);
+ a2.setPersons(new HashSet<Person>());
+ a2.getPersons().add(p2);
+ a2.getPersons().add(p3);
+
+ entityManager.persist(a1);
+ entityManager.persist(a2);
+
+ entityManager.persist(p1);
+ entityManager.persist(p2);
+ entityManager.persist(p3);
+
+ System.out.println("The DB was populated with example data.");
+ }
+
+ entityManager.getTransaction().commit();
+ }
+
+ public static void main(String[] args) {
+ String userDbFile = System.getProperty("java.io.tmpdir") + File.separator + "_versions_demo.db";
+
+ Map<String, String> configurationOverrides = new HashMap<String, String>();
+ EntityManagerFactory emf = Persistence.createEntityManagerFactory("ConsolePU", configurationOverrides);
+ EntityManager entityManager = emf.createEntityManager();
+
+ TestConsole console = new TestConsole(entityManager);
+
+ System.out.println("");
+ System.out.println("Welcome to EntityVersions demo!");
+ System.out.println("HSQLDB database file location: " + userDbFile);
+
+ console.populateTestData();
+ console.start();
+
+ entityManager.close();
+ emf.close();
+ }
+}
Added: core/trunk/envers/src/demo/resources/META-INF/persistence.xml
===================================================================
--- core/trunk/envers/src/demo/resources/META-INF/persistence.xml (rev 0)
+++ core/trunk/envers/src/demo/resources/META-INF/persistence.xml 2008-10-27 18:56:31 UTC (rev 15406)
@@ -0,0 +1,30 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<persistence xmlns="http://java.sun.com/xml/ns/persistence" version="1.0">
+ <persistence-unit name="ConsolePU">
+ <provider>org.hibernate.ejb.HibernatePersistence</provider>
+ <class>org.jboss.envers.demo.Address</class>
+ <class>org.jboss.envers.demo.Person</class>
+ <exclude-unlisted-classes />
+ <properties>
+ <property name="hibernate.dialect" value="org.hibernate.dialect.HSQLDialect"/>
+ <property name="hibernate.connection.url" value="jdbc:hsqldb:file:${java.io.tmpdir}/_versions_demo.db"/>
+ <property name="hibernate.connection.driver_class" value="org.hsqldb.jdbcDriver"/>
+ <property name="hibernate.connection.username" value="sa"/>
+ <property name="hibernate.connection.password" value=""/>
+
+ <!--<property name="hibernate.dialect" value="org.hibernate.dialect.MySQLDialect"/>
+ <property name="hibernate.connection.url" value="jdbc:mysql:///hibernate_tests?useUnicode=true&characterEncoding=UTF-8"/>
+ <property name="hibernate.connection.driver_class" value="com.mysql.jdbc.Driver"/>
+ <property name="hibernate.connection.username" value="root"/>
+ <property name="hibernate.connection.password" value=""/>-->
+
+ <property name="hibernate.hbm2ddl.auto" value="update"/>
+ <!--<property name="hibernate.show_sql" value="true"/>
+ <property name="hibernate.format_sql" value="true"/>-->
+
+ <property name="hibernate.ejb.event.post-insert" value="org.jboss.envers.event.VersionsEventListener" />
+ <property name="hibernate.ejb.event.post-update" value="org.jboss.envers.event.VersionsEventListener" />
+ <property name="hibernate.ejb.event.post-delete" value="org.jboss.envers.event.VersionsEventListener" />
+ </properties>
+ </persistence-unit>
+</persistence>
\ No newline at end of file
Added: core/trunk/envers/src/main/java/org/hibernate/tool/ant/EnversHibernateToolTask.java
===================================================================
--- core/trunk/envers/src/main/java/org/hibernate/tool/ant/EnversHibernateToolTask.java (rev 0)
+++ core/trunk/envers/src/main/java/org/hibernate/tool/ant/EnversHibernateToolTask.java 2008-10-27 18:56:31 UTC (rev 15406)
@@ -0,0 +1,59 @@
+/*
+ * Envers. http://www.jboss.org/envers
+ *
+ * Copyright 2008 Red Hat Middleware, LLC. All rights reserved.
+ *
+ * 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, v. 2.1.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT A 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, v.2.1 along with this distribution; if not, write to the Free
+ * Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+ * 02110-1301, USA.
+ *
+ * Red Hat Author(s): Adam Warski
+ */
+package org.hibernate.tool.ant;
+
+import org.jboss.envers.ant.JPAConfigurationTaskWithEnvers;
+import org.jboss.envers.ant.ConfigurationTaskWithEnvers;
+import org.jboss.envers.ant.AnnotationConfigurationTaskWithEnvers;
+import org.apache.tools.ant.BuildException;
+
+/**
+ * @author Adam Warski (adam at warski dot org)
+ */
+public class EnversHibernateToolTask extends HibernateToolTask {
+ private void checkConfiguration() {
+ if (configurationTask!=null) {
+ throw new BuildException("Only a single configuration is allowed.");
+ }
+ }
+
+ public JPAConfigurationTask createJpaConfiguration() {
+ checkConfiguration();
+ JPAConfigurationTask task = new JPAConfigurationTaskWithEnvers();
+ configurationTask = task;
+ return task;
+ }
+
+ public ConfigurationTask createConfiguration() {
+ checkConfiguration();
+ ConfigurationTaskWithEnvers task = new ConfigurationTaskWithEnvers();
+ configurationTask = task;
+ return task;
+ }
+
+ public AnnotationConfigurationTask createAnnotationConfiguration() {
+ checkConfiguration();
+ AnnotationConfigurationTaskWithEnvers task = new AnnotationConfigurationTaskWithEnvers();
+ configurationTask = task;
+ return task;
+ }
+}
Added: core/trunk/envers/src/main/java/org/jboss/envers/DefaultRevisionEntity.java
===================================================================
--- core/trunk/envers/src/main/java/org/jboss/envers/DefaultRevisionEntity.java (rev 0)
+++ core/trunk/envers/src/main/java/org/jboss/envers/DefaultRevisionEntity.java 2008-10-27 18:56:31 UTC (rev 15406)
@@ -0,0 +1,87 @@
+/*
+ * Envers. http://www.jboss.org/envers
+ *
+ * Copyright 2008 Red Hat Middleware, LLC. All rights reserved.
+ *
+ * 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, v. 2.1.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT A 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, v.2.1 along with this distribution; if not, write to the Free
+ * Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+ * 02110-1301, USA.
+ *
+ * Red Hat Author(s): Adam Warski
+ */
+package org.jboss.envers;
+
+import javax.persistence.MappedSuperclass;
+import javax.persistence.Id;
+import javax.persistence.GeneratedValue;
+import javax.persistence.Transient;
+import java.util.Date;
+import java.text.DateFormat;
+
+/**
+ * @author Adam Warski (adam at warski dot org)
+ */
+ at MappedSuperclass
+public class DefaultRevisionEntity {
+ @Id
+ @GeneratedValue
+ @RevisionNumber
+ private int id;
+
+ @RevisionTimestamp
+ private long timestamp;
+
+ public int getId() {
+ return id;
+ }
+
+ public void setId(int id) {
+ this.id = id;
+ }
+
+ @Transient
+ public Date getRevisionDate() {
+ return new Date(timestamp);
+ }
+
+ public long getTimestamp() {
+ return timestamp;
+ }
+
+ public void setTimestamp(long timestamp) {
+ this.timestamp = timestamp;
+ }
+
+ public boolean equals(Object o) {
+ if (this == o) return true;
+ if (!(o instanceof DefaultRevisionEntity)) return false;
+
+ DefaultRevisionEntity that = (DefaultRevisionEntity) o;
+
+ if (id != that.id) return false;
+ if (timestamp != that.timestamp) return false;
+
+ return true;
+ }
+
+ public int hashCode() {
+ int result;
+ result = id;
+ result = 31 * result + (int) (timestamp ^ (timestamp >>> 32));
+ return result;
+ }
+
+ public String toString() {
+ return "DefaultRevisionEntity(id = " + id + ", revisionDate = " + DateFormat.getDateTimeInstance().format(getRevisionDate()) + ")";
+ }
+}
Added: core/trunk/envers/src/main/java/org/jboss/envers/ModificationStore.java
===================================================================
--- core/trunk/envers/src/main/java/org/jboss/envers/ModificationStore.java (rev 0)
+++ core/trunk/envers/src/main/java/org/jboss/envers/ModificationStore.java 2008-10-27 18:56:31 UTC (rev 15406)
@@ -0,0 +1,29 @@
+/*
+ * Envers. http://www.jboss.org/envers
+ *
+ * Copyright 2008 Red Hat Middleware, LLC. All rights reserved.
+ *
+ * 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, v. 2.1.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT A 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, v.2.1 along with this distribution; if not, write to the Free
+ * Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+ * 02110-1301, USA.
+ *
+ * Red Hat Author(s): Adam Warski
+ */
+package org.jboss.envers;
+
+/**
+ * @author Adam Warski (adam at warski dot org)
+ */
+public enum ModificationStore {
+ FULL
+}
Added: core/trunk/envers/src/main/java/org/jboss/envers/RevisionEntity.java
===================================================================
--- core/trunk/envers/src/main/java/org/jboss/envers/RevisionEntity.java (rev 0)
+++ core/trunk/envers/src/main/java/org/jboss/envers/RevisionEntity.java 2008-10-27 18:56:31 UTC (rev 15406)
@@ -0,0 +1,41 @@
+/*
+ * Envers. http://www.jboss.org/envers
+ *
+ * Copyright 2008 Red Hat Middleware, LLC. All rights reserved.
+ *
+ * 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, v. 2.1.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT A 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, v.2.1 along with this distribution; if not, write to the Free
+ * Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+ * 02110-1301, USA.
+ *
+ * Red Hat Author(s): Adam Warski
+ */
+package org.jboss.envers;
+
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+import java.lang.annotation.Target;
+import java.lang.annotation.ElementType;
+
+/**
+ * Marks an entity to be created whenever a new revision is generated. The revisions entity must have
+ * an integer-valued unique property (preferrably the primary id) annotated with {@link RevisionNumber}
+ * and a long-valued property annotated with {@link RevisionTimestamp}. The {@link DefaultRevisionEntity}
+ * already has those two fields, so you may extend it, but you may also write your own revision entity
+ * from scratch.
+ * @author Adam Warski (adam at warski dot org)
+ */
+ at Retention(RetentionPolicy.RUNTIME)
+ at Target(ElementType.TYPE)
+public @interface RevisionEntity {
+ Class<? extends RevisionListener> value() default RevisionListener.class;
+}
Added: core/trunk/envers/src/main/java/org/jboss/envers/RevisionListener.java
===================================================================
--- core/trunk/envers/src/main/java/org/jboss/envers/RevisionListener.java (rev 0)
+++ core/trunk/envers/src/main/java/org/jboss/envers/RevisionListener.java 2008-10-27 18:56:31 UTC (rev 15406)
@@ -0,0 +1,36 @@
+/*
+ * Envers. http://www.jboss.org/envers
+ *
+ * Copyright 2008 Red Hat Middleware, LLC. All rights reserved.
+ *
+ * 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, v. 2.1.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT A 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, v.2.1 along with this distribution; if not, write to the Free
+ * Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+ * 02110-1301, USA.
+ *
+ * Red Hat Author(s): Adam Warski
+ */
+package org.jboss.envers;
+
+/**
+ * An implementation of this class, having a no-arg constructor, should be passed as an argument to the
+ * {@link RevisionEntity} annotation.
+ * @author Adam Warski (adam at warski dot org)
+ */
+public interface RevisionListener {
+ /**
+ * Called when a new revision is created.
+ * @param revisionEntity An instance of the entity annotated with {@link RevisionEntity}, which will be persisted
+ * after this method returns. All properties on this entity that are to be persisted should be set by this method.
+ */
+ void newRevision(Object revisionEntity);
+}
Added: core/trunk/envers/src/main/java/org/jboss/envers/RevisionNumber.java
===================================================================
--- core/trunk/envers/src/main/java/org/jboss/envers/RevisionNumber.java (rev 0)
+++ core/trunk/envers/src/main/java/org/jboss/envers/RevisionNumber.java 2008-10-27 18:56:31 UTC (rev 15406)
@@ -0,0 +1,40 @@
+/*
+ * Envers. http://www.jboss.org/envers
+ *
+ * Copyright 2008 Red Hat Middleware, LLC. All rights reserved.
+ *
+ * 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, v. 2.1.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT A 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, v.2.1 along with this distribution; if not, write to the Free
+ * Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+ * 02110-1301, USA.
+ *
+ * Red Hat Author(s): Adam Warski
+ */
+package org.jboss.envers;
+
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+import java.lang.annotation.Target;
+import java.lang.annotation.ElementType;
+
+/**
+ * Marks a property which will hold the number of the revision in a revision entity, see
+ * {@link RevisionListener}. Values of this property should form a strictly-increasing sequence
+ * of numbers. The value of this property won't be set by Envers. In most cases, this should be
+ * an auto-generated database-assigned primary id.
+ * @author Adam Warski (adam at warski dot org)
+ * @author Sanne Grinovero
+ */
+ at Retention(RetentionPolicy.RUNTIME)
+ at Target({ElementType.METHOD, ElementType.FIELD})
+public @interface RevisionNumber {
+}
Added: core/trunk/envers/src/main/java/org/jboss/envers/RevisionTimestamp.java
===================================================================
--- core/trunk/envers/src/main/java/org/jboss/envers/RevisionTimestamp.java (rev 0)
+++ core/trunk/envers/src/main/java/org/jboss/envers/RevisionTimestamp.java 2008-10-27 18:56:31 UTC (rev 15406)
@@ -0,0 +1,38 @@
+/*
+ * Envers. http://www.jboss.org/envers
+ *
+ * Copyright 2008 Red Hat Middleware, LLC. All rights reserved.
+ *
+ * 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, v. 2.1.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT A 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, v.2.1 along with this distribution; if not, write to the Free
+ * Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+ * 02110-1301, USA.
+ *
+ * Red Hat Author(s): Adam Warski
+ */
+package org.jboss.envers;
+
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+import java.lang.annotation.Target;
+import java.lang.annotation.ElementType;
+
+/**
+ * Marks a property which will hold the timestamp of the revision in a revision entity, see
+ * {@link RevisionListener}. The value of this property will be automatically set by Envers.
+ * @author Adam Warski (adam at warski dot org)
+ * @author Sanne Grinovero
+ */
+ at Retention(RetentionPolicy.RUNTIME)
+ at Target({ElementType.METHOD, ElementType.FIELD})
+public @interface RevisionTimestamp {
+}
Added: core/trunk/envers/src/main/java/org/jboss/envers/RevisionType.java
===================================================================
--- core/trunk/envers/src/main/java/org/jboss/envers/RevisionType.java (rev 0)
+++ core/trunk/envers/src/main/java/org/jboss/envers/RevisionType.java 2008-10-27 18:56:31 UTC (rev 15406)
@@ -0,0 +1,65 @@
+/*
+ * Envers. http://www.jboss.org/envers
+ *
+ * Copyright 2008 Red Hat Middleware, LLC. All rights reserved.
+ *
+ * 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, v. 2.1.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT A 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, v.2.1 along with this distribution; if not, write to the Free
+ * Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+ * 02110-1301, USA.
+ *
+ * Red Hat Author(s): Adam Warski
+ */
+package org.jboss.envers;
+
+/**
+ * Type of the revision.
+ * @author Adam Warski (adam at warski dot org)
+ */
+public enum RevisionType {
+ /**
+ * Indicates that the entity was added (persisted) at that revision.
+ */
+ ADD((byte) 0),
+ /**
+ * Indicates that the entity was modified (one or more of its fields) at that revision.
+ */
+ MOD((byte) 1),
+ /**
+ * Indicates that the entity was deleted (removed) at that revision.
+ */
+ DEL((byte) 2);
+
+ private Byte representation;
+
+ RevisionType(byte representation) {
+ this.representation = representation;
+ }
+
+ public Byte getRepresentation() {
+ return representation;
+ }
+
+ public static RevisionType fromRepresentation(Object representation) {
+ if (representation == null || !(representation instanceof Byte)) {
+ return null;
+ }
+
+ switch ((Byte) representation) {
+ case 0: return ADD;
+ case 1: return MOD;
+ case 2: return DEL;
+ }
+
+ throw new IllegalArgumentException("Unknown representation: " + representation);
+ }
+}
Added: core/trunk/envers/src/main/java/org/jboss/envers/SecondaryVersionsTable.java
===================================================================
--- core/trunk/envers/src/main/java/org/jboss/envers/SecondaryVersionsTable.java (rev 0)
+++ core/trunk/envers/src/main/java/org/jboss/envers/SecondaryVersionsTable.java 2008-10-27 18:56:31 UTC (rev 15406)
@@ -0,0 +1,38 @@
+/*
+ * Envers. http://www.jboss.org/envers
+ *
+ * Copyright 2008 Red Hat Middleware, LLC. All rights reserved.
+ *
+ * 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, v. 2.1.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT A 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, v.2.1 along with this distribution; if not, write to the Free
+ * Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+ * 02110-1301, USA.
+ *
+ * Red Hat Author(s): Adam Warski
+ */
+package org.jboss.envers;
+
+import java.lang.annotation.ElementType;
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+import java.lang.annotation.Target;
+
+/**
+ * @author Adam Warski (adam at warski dot org)
+ */
+ at Target(ElementType.TYPE)
+ at Retention(RetentionPolicy.RUNTIME)
+public @interface SecondaryVersionsTable {
+ String secondaryTableName();
+
+ String secondaryVersionsTableName();
+}
Added: core/trunk/envers/src/main/java/org/jboss/envers/SecondaryVersionsTables.java
===================================================================
--- core/trunk/envers/src/main/java/org/jboss/envers/SecondaryVersionsTables.java (rev 0)
+++ core/trunk/envers/src/main/java/org/jboss/envers/SecondaryVersionsTables.java 2008-10-27 18:56:31 UTC (rev 15406)
@@ -0,0 +1,36 @@
+/*
+ * Envers. http://www.jboss.org/envers
+ *
+ * Copyright 2008 Red Hat Middleware, LLC. All rights reserved.
+ *
+ * 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, v. 2.1.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT A 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, v.2.1 along with this distribution; if not, write to the Free
+ * Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+ * 02110-1301, USA.
+ *
+ * Red Hat Author(s): Adam Warski
+ */
+package org.jboss.envers;
+
+import java.lang.annotation.Target;
+import java.lang.annotation.ElementType;
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+
+/**
+ * @author Adam Warski (adam at warski dot org)
+ */
+ at Target(ElementType.TYPE)
+ at Retention(RetentionPolicy.RUNTIME)
+public @interface SecondaryVersionsTables {
+ SecondaryVersionsTable[] value();
+}
Added: core/trunk/envers/src/main/java/org/jboss/envers/Unversioned.java
===================================================================
--- core/trunk/envers/src/main/java/org/jboss/envers/Unversioned.java (rev 0)
+++ core/trunk/envers/src/main/java/org/jboss/envers/Unversioned.java 2008-10-27 18:56:31 UTC (rev 15406)
@@ -0,0 +1,37 @@
+/*
+ * Envers. http://www.jboss.org/envers
+ *
+ * Copyright 2008 Red Hat Middleware, LLC. All rights reserved.
+ *
+ * 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, v. 2.1.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT A 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, v.2.1 along with this distribution; if not, write to the Free
+ * Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+ * 02110-1301, USA.
+ *
+ * Red Hat Author(s): Adam Warski
+ */
+package org.jboss.envers;
+
+import java.lang.annotation.Target;
+import java.lang.annotation.ElementType;
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+
+/**
+ * When applied to a field, indicates that this field should not be versioned.
+ * @author Sebastian Komander
+ */
+ at Retention(RetentionPolicy.RUNTIME)
+ at Target({ElementType.METHOD, ElementType.FIELD})
+public @interface Unversioned {
+
+}
Added: core/trunk/envers/src/main/java/org/jboss/envers/Versioned.java
===================================================================
--- core/trunk/envers/src/main/java/org/jboss/envers/Versioned.java (rev 0)
+++ core/trunk/envers/src/main/java/org/jboss/envers/Versioned.java 2008-10-27 18:56:31 UTC (rev 15406)
@@ -0,0 +1,38 @@
+/*
+ * Envers. http://www.jboss.org/envers
+ *
+ * Copyright 2008 Red Hat Middleware, LLC. All rights reserved.
+ *
+ * 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, v. 2.1.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT A 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, v.2.1 along with this distribution; if not, write to the Free
+ * Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+ * 02110-1301, USA.
+ *
+ * Red Hat Author(s): Adam Warski
+ */
+package org.jboss.envers;
+
+import java.lang.annotation.Target;
+import java.lang.annotation.ElementType;
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+
+/**
+ * When applied to a class, indicates that all of its properties should be versioned.
+ * When applied to a field, indicates that this field should be versioned.
+ * @author Adam Warski (adam at warski dot org)
+ */
+ at Retention(RetentionPolicy.RUNTIME)
+ at Target({ElementType.TYPE, ElementType.METHOD, ElementType.FIELD})
+public @interface Versioned {
+ ModificationStore modStore() default ModificationStore.FULL;
+}
Added: core/trunk/envers/src/main/java/org/jboss/envers/VersionsJoinTable.java
===================================================================
--- core/trunk/envers/src/main/java/org/jboss/envers/VersionsJoinTable.java (rev 0)
+++ core/trunk/envers/src/main/java/org/jboss/envers/VersionsJoinTable.java 2008-10-27 18:56:31 UTC (rev 15406)
@@ -0,0 +1,57 @@
+/*
+ * Envers. http://www.jboss.org/envers
+ *
+ * Copyright 2008 Red Hat Middleware, LLC. All rights reserved.
+ *
+ * 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, v. 2.1.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT A 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, v.2.1 along with this distribution; if not, write to the Free
+ * Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+ * 02110-1301, USA.
+ *
+ * Red Hat Author(s): Adam Warski
+ */
+package org.jboss.envers;
+
+import javax.persistence.JoinColumn;
+import java.lang.annotation.ElementType;
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+import java.lang.annotation.Target;
+
+/**
+ * @author Adam Warski (adam at warski dot org)
+ */
+ at Retention(RetentionPolicy.RUNTIME)
+ at Target({ElementType.FIELD, ElementType.METHOD})
+public @interface VersionsJoinTable {
+ /**
+ * @return Name of the join table. Defaults to a concatenation of the names of the primary table of the entity
+ * owning the association and of the primary table of the entity referenced by the association.
+ */
+ String name() default "";
+
+ /**
+ * @return The schema of the join table. Defaults to the schema of the entity owning the association.
+ */
+ String schema() default "";
+
+ /**
+ * @return The catalog of the join table. Defaults to the catalog of the entity owning the association.
+ */
+ String catalog() default "";
+
+ /**
+ * @return The foreign key columns of the join table which reference the primary table of the entity that does not
+ * own the association (i.e. the inverse side of the association).
+ */
+ JoinColumn[] inverseJoinColumns() default {};
+}
\ No newline at end of file
Added: core/trunk/envers/src/main/java/org/jboss/envers/VersionsReader.java
===================================================================
--- core/trunk/envers/src/main/java/org/jboss/envers/VersionsReader.java (rev 0)
+++ core/trunk/envers/src/main/java/org/jboss/envers/VersionsReader.java 2008-10-27 18:56:31 UTC (rev 15406)
@@ -0,0 +1,108 @@
+/*
+ * Envers. http://www.jboss.org/envers
+ *
+ * Copyright 2008 Red Hat Middleware, LLC. All rights reserved.
+ *
+ * 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, v. 2.1.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT A 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, v.2.1 along with this distribution; if not, write to the Free
+ * Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+ * 02110-1301, USA.
+ *
+ * Red Hat Author(s): Adam Warski
+ */
+package org.jboss.envers;
+
+import org.jboss.envers.exception.NotVersionedException;
+import org.jboss.envers.exception.RevisionDoesNotExistException;
+import org.jboss.envers.query.VersionsQueryCreator;
+
+import java.util.List;
+import java.util.Date;
+
+/**
+ * @author Adam Warski (adam at warski dot org)
+ */
+public interface VersionsReader {
+ /**
+ * Find an entity by primary key at the given revision.
+ * @param cls Class of the entity.
+ * @param primaryKey Primary key of the entity.
+ * @param revision Revision in which to get the entity.
+ * @return The found entity instance at the given revision (its properties may be partially filled
+ * if not all properties are versioned) or null, if an entity with that id didn't exist at that
+ * revision.
+ * @throws IllegalArgumentException If cls or primaryKey is null or revision is less or equal to 0.
+ * @throws NotVersionedException When entities of the given class are not versioned.
+ * @throws IllegalStateException If the associated entity manager is closed.
+ */
+ <T> T find(Class<T> cls, Object primaryKey, Number revision) throws
+ IllegalArgumentException, NotVersionedException, IllegalStateException;
+
+ /**
+ * Get a list of revision numbers, at which an entity was modified.
+ * @param cls Class of the entity.
+ * @param primaryKey Primary key of the entity.
+ * @return A list of revision numbers, at which the entity was modified, sorted in ascending order (so older
+ * revisions come first).
+ * @throws NotVersionedException When entities of the given class are not versioned.
+ * @throws IllegalArgumentException If cls or primaryKey is null.
+ * @throws IllegalStateException If the associated entity manager is closed.
+ */
+ List<Number> getRevisions(Class<?> cls, Object primaryKey)
+ throws IllegalArgumentException, NotVersionedException, IllegalStateException;
+
+ /**
+ * Get the date, at which a revision was created.
+ * @param revision Number of the revision for which to get the date.
+ * @return Date of commiting the given revision.
+ * @throws IllegalArgumentException If revision is less or equal to 0.
+ * @throws RevisionDoesNotExistException If the revision does not exist.
+ * @throws IllegalStateException If the associated entity manager is closed.
+ */
+ Date getRevisionDate(Number revision) throws IllegalArgumentException, RevisionDoesNotExistException,
+ IllegalStateException;
+
+ /**
+ * Gets the revision number, that corresponds to the given date. More precisely, returns
+ * the number of the highest revision, which was created on or before the given date. So:
+ * <code>getRevisionDate(getRevisionNumberForDate(date)) <= date</code> and
+ * <code>getRevisionDate(getRevisionNumberForDate(date)+1) > date</code>.
+ * @param date Date for which to get the revision.
+ * @return Revision number corresponding to the given date.
+ * @throws IllegalStateException If the associated entity manager is closed.
+ * @throws RevisionDoesNotExistException If the given date is before the first revision.
+ * @throws IllegalArgumentException If <code>date</code> is <code>null</code>.
+ */
+ Number getRevisionNumberForDate(Date date) throws IllegalStateException, RevisionDoesNotExistException,
+ IllegalArgumentException;
+
+ /**
+ * A helper method; should be used only if a custom revision entity is used. See also {@link RevisionEntity}.
+ * @param revisionEntityClass Class of the revision entity. Should be annotated with {@link RevisionEntity}.
+ * @param revision Number of the revision for which to get the data.
+ * @return Entity containing data for the given revision.
+ * @throws IllegalArgumentException If revision is less or equal to 0 or if the class of the revision entity
+ * is invalid.
+ * @throws RevisionDoesNotExistException If the revision does not exist.
+ * @throws IllegalStateException If the associated entity manager is closed.
+ */
+ <T> T findRevision(Class<T> revisionEntityClass, Number revision) throws IllegalArgumentException,
+ RevisionDoesNotExistException, IllegalStateException;
+
+ /**
+ *
+ * @return A query creator, associated with this VersionsReader instance, with which queries can be
+ * created and later executed. Shouldn't be used after the associated Session or EntityManager
+ * is closed.
+ */
+ VersionsQueryCreator createQuery();
+}
Added: core/trunk/envers/src/main/java/org/jboss/envers/VersionsReaderFactory.java
===================================================================
--- core/trunk/envers/src/main/java/org/jboss/envers/VersionsReaderFactory.java (rev 0)
+++ core/trunk/envers/src/main/java/org/jboss/envers/VersionsReaderFactory.java 2008-10-27 18:56:31 UTC (rev 15406)
@@ -0,0 +1,90 @@
+/*
+ * Envers. http://www.jboss.org/envers
+ *
+ * Copyright 2008 Red Hat Middleware, LLC. All rights reserved.
+ *
+ * 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, v. 2.1.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT A 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, v.2.1 along with this distribution; if not, write to the Free
+ * Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+ * 02110-1301, USA.
+ *
+ * Red Hat Author(s): Adam Warski
+ */
+package org.jboss.envers;
+
+import org.hibernate.Session;
+import org.hibernate.event.EventListeners;
+import org.hibernate.event.PostInsertEventListener;
+import org.hibernate.engine.SessionImplementor;
+import org.jboss.envers.exception.VersionsException;
+import org.jboss.envers.event.VersionsEventListener;
+import static org.jboss.envers.tools.ArraysTools.arrayIncludesInstanceOf;
+import org.jboss.envers.reader.VersionsReaderImpl;
+
+import javax.persistence.EntityManager;
+
+/**
+ * @author Adam Warski (adam at warski dot org)
+ */
+public class VersionsReaderFactory {
+ private VersionsReaderFactory() { }
+
+ /**
+ * Create a versions reader associated with an open session.
+ * <b>WARNING:</b> Using Envers with Hibernate (not with Hibernate Entity Manager/JPA) is experimental,
+ * if possible, use {@link org.jboss.envers.VersionsReaderFactory#get(javax.persistence.EntityManager)}.
+ * @param session An open session.
+ * @return A versions reader associated with the given sesison. It shouldn't be used
+ * after the session is closed.
+ * @throws VersionsException When the given required listeners aren't installed.
+ */
+ public static VersionsReader get(Session session) throws VersionsException {
+ SessionImplementor sessionImpl = (SessionImplementor) session;
+
+ EventListeners listeners = sessionImpl.getListeners();
+
+ for (PostInsertEventListener listener : listeners.getPostInsertEventListeners()) {
+ if (listener instanceof VersionsEventListener) {
+ if (arrayIncludesInstanceOf(listeners.getPostUpdateEventListeners(), VersionsEventListener.class) &&
+ arrayIncludesInstanceOf(listeners.getPostDeleteEventListeners(), VersionsEventListener.class)) {
+ return new VersionsReaderImpl(((VersionsEventListener) listener).getVerCfg(), session,
+ sessionImpl);
+ }
+ }
+ }
+
+ throw new VersionsException("You need install the org.jboss.envers.event.VersionsEventListener " +
+ "class as post insert, update and delete event listener.");
+ }
+
+ /**
+ * Create a versions reader associated with an open entity manager.
+ * @param entityManager An open entity manager.
+ * @return A versions reader associated with the given entity manager. It shouldn't be used
+ * after the entity manager is closed.
+ * @throws VersionsException When the given entity manager is not based on Hibernate, or if the required
+ * listeners aren't installed.
+ */
+ public static VersionsReader get(EntityManager entityManager) throws VersionsException {
+ if (entityManager.getDelegate() instanceof Session) {
+ return get((Session) entityManager.getDelegate());
+ }
+
+ if (entityManager.getDelegate() instanceof EntityManager) {
+ if (entityManager.getDelegate() instanceof Session) {
+ return get((Session) entityManager.getDelegate());
+ }
+ }
+
+ throw new VersionsException("Hibernate EntityManager not present!");
+ }
+}
Added: core/trunk/envers/src/main/java/org/jboss/envers/VersionsTable.java
===================================================================
--- core/trunk/envers/src/main/java/org/jboss/envers/VersionsTable.java (rev 0)
+++ core/trunk/envers/src/main/java/org/jboss/envers/VersionsTable.java 2008-10-27 18:56:31 UTC (rev 15406)
@@ -0,0 +1,46 @@
+/*
+ * Envers. http://www.jboss.org/envers
+ *
+ * Copyright 2008 Red Hat Middleware, LLC. All rights reserved.
+ *
+ * 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, v. 2.1.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT A 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, v.2.1 along with this distribution; if not, write to the Free
+ * Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+ * 02110-1301, USA.
+ *
+ * Red Hat Author(s): Adam Warski
+ */
+package org.jboss.envers;
+
+import java.lang.annotation.Target;
+import java.lang.annotation.ElementType;
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+
+/**
+ * @author Adam Warski (adam at warski dot org)
+ */
+ at Retention(RetentionPolicy.RUNTIME)
+ at Target(ElementType.TYPE)
+public @interface VersionsTable {
+ String value();
+
+ /**
+ * @return The schema of the table. Defaults to the schema of the annotated entity.
+ */
+ String schema() default "";
+
+ /**
+ * @return The catalog of the table. Defaults to the catalog of the annotated entity.
+ */
+ String catalog() default "";
+}
Added: core/trunk/envers/src/main/java/org/jboss/envers/ant/AnnotationConfigurationTaskWithEnvers.java
===================================================================
--- core/trunk/envers/src/main/java/org/jboss/envers/ant/AnnotationConfigurationTaskWithEnvers.java (rev 0)
+++ core/trunk/envers/src/main/java/org/jboss/envers/ant/AnnotationConfigurationTaskWithEnvers.java 2008-10-27 18:56:31 UTC (rev 15406)
@@ -0,0 +1,37 @@
+/*
+ * Envers. http://www.jboss.org/envers
+ *
+ * Copyright 2008 Red Hat Middleware, LLC. All rights reserved.
+ *
+ * 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, v. 2.1.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT A 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, v.2.1 along with this distribution; if not, write to the Free
+ * Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+ * 02110-1301, USA.
+ *
+ * Red Hat Author(s): Adam Warski
+ */
+package org.jboss.envers.ant;
+
+import org.hibernate.tool.ant.AnnotationConfigurationTask;
+import org.hibernate.cfg.Configuration;
+import org.jboss.envers.configuration.VersionsConfiguration;
+
+/**
+ * @author Adam Warski (adam at warski dot org)
+ */
+public class AnnotationConfigurationTaskWithEnvers extends AnnotationConfigurationTask {
+ protected void doConfiguration(Configuration configuration) {
+ VersionsConfiguration.getFor(configuration);
+
+ super.doConfiguration(configuration);
+ }
+}
Added: core/trunk/envers/src/main/java/org/jboss/envers/ant/ConfigurationTaskWithEnvers.java
===================================================================
--- core/trunk/envers/src/main/java/org/jboss/envers/ant/ConfigurationTaskWithEnvers.java (rev 0)
+++ core/trunk/envers/src/main/java/org/jboss/envers/ant/ConfigurationTaskWithEnvers.java 2008-10-27 18:56:31 UTC (rev 15406)
@@ -0,0 +1,37 @@
+/*
+ * Envers. http://www.jboss.org/envers
+ *
+ * Copyright 2008 Red Hat Middleware, LLC. All rights reserved.
+ *
+ * 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, v. 2.1.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT A 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, v.2.1 along with this distribution; if not, write to the Free
+ * Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+ * 02110-1301, USA.
+ *
+ * Red Hat Author(s): Adam Warski
+ */
+package org.jboss.envers.ant;
+
+import org.hibernate.tool.ant.ConfigurationTask;
+import org.hibernate.cfg.Configuration;
+import org.jboss.envers.configuration.VersionsConfiguration;
+
+/**
+ * @author Adam Warski (adam at warski dot org)
+ */
+public class ConfigurationTaskWithEnvers extends ConfigurationTask {
+ protected void doConfiguration(Configuration configuration) {
+ VersionsConfiguration.getFor(configuration);
+
+ super.doConfiguration(configuration);
+ }
+}
Added: core/trunk/envers/src/main/java/org/jboss/envers/ant/JPAConfigurationTaskWithEnvers.java
===================================================================
--- core/trunk/envers/src/main/java/org/jboss/envers/ant/JPAConfigurationTaskWithEnvers.java (rev 0)
+++ core/trunk/envers/src/main/java/org/jboss/envers/ant/JPAConfigurationTaskWithEnvers.java 2008-10-27 18:56:31 UTC (rev 15406)
@@ -0,0 +1,37 @@
+/*
+ * Envers. http://www.jboss.org/envers
+ *
+ * Copyright 2008 Red Hat Middleware, LLC. All rights reserved.
+ *
+ * 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, v. 2.1.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT A 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, v.2.1 along with this distribution; if not, write to the Free
+ * Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+ * 02110-1301, USA.
+ *
+ * Red Hat Author(s): Adam Warski
+ */
+package org.jboss.envers.ant;
+
+import org.hibernate.tool.ant.JPAConfigurationTask;
+import org.hibernate.cfg.Configuration;
+import org.jboss.envers.configuration.VersionsConfiguration;
+
+/**
+ * @author Adam Warski (adam at warski dot org)
+ */
+public class JPAConfigurationTaskWithEnvers extends JPAConfigurationTask {
+ protected void doConfiguration(Configuration configuration) {
+ VersionsConfiguration.getFor(configuration);
+
+ super.doConfiguration(configuration);
+ }
+}
Added: core/trunk/envers/src/main/java/org/jboss/envers/configuration/EntitiesConfigurator.java
===================================================================
--- core/trunk/envers/src/main/java/org/jboss/envers/configuration/EntitiesConfigurator.java (rev 0)
+++ core/trunk/envers/src/main/java/org/jboss/envers/configuration/EntitiesConfigurator.java 2008-10-27 18:56:31 UTC (rev 15406)
@@ -0,0 +1,143 @@
+/*
+ * Envers. http://www.jboss.org/envers
+ *
+ * Copyright 2008 Red Hat Middleware, LLC. All rights reserved.
+ *
+ * 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, v. 2.1.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT A 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, v.2.1 along with this distribution; if not, write to the Free
+ * Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+ * 02110-1301, USA.
+ *
+ * Red Hat Author(s): Adam Warski
+ */
+package org.jboss.envers.configuration;
+
+import org.jboss.envers.entities.EntitiesConfigurations;
+import org.jboss.envers.configuration.metadata.VersionsMetadataGenerator;
+import org.jboss.envers.configuration.metadata.PersistentClassVersioningData;
+import org.jboss.envers.configuration.metadata.AnnotationsMetadataReader;
+import org.jboss.envers.configuration.metadata.EntityXmlMappingData;
+import org.jboss.envers.tools.graph.GraphTopologicalSort;
+import org.jboss.envers.tools.reflection.YReflectionManager;
+import org.jboss.envers.tools.StringTools;
+import org.dom4j.io.DOMWriter;
+import org.dom4j.io.XMLWriter;
+import org.dom4j.io.OutputFormat;
+import org.dom4j.Document;
+import org.dom4j.DocumentException;
+import org.dom4j.Element;
+import org.hibernate.mapping.PersistentClass;
+import org.hibernate.MappingException;
+import org.hibernate.cfg.Configuration;
+
+import java.util.Iterator;
+import java.util.Map;
+import java.util.HashMap;
+import java.io.ByteArrayOutputStream;
+import java.io.Writer;
+import java.io.PrintWriter;
+import java.io.IOException;
+
+/**
+ * @author Adam Warski (adam at warski dot org)
+ */
+public class EntitiesConfigurator {
+ public EntitiesConfigurations configure(Configuration cfg, YReflectionManager reflectionManager,
+ GlobalConfiguration globalCfg, VersionsEntitiesConfiguration verEntCfg,
+ Document revisionInfoXmlMapping, Element revisionInfoRelationMapping) {
+ VersionsMetadataGenerator versionsMetaGen = new VersionsMetadataGenerator(cfg, globalCfg, verEntCfg,
+ revisionInfoRelationMapping);
+ DOMWriter writer = new DOMWriter();
+
+ // Sorting the persistent class topologically - superclass always before subclass
+ Iterator<PersistentClass> classes = GraphTopologicalSort.sort(new PersistentClassGraphDefiner(cfg)).iterator();
+
+ Map<PersistentClass, PersistentClassVersioningData> pcDatas =
+ new HashMap<PersistentClass, PersistentClassVersioningData>();
+ Map<PersistentClass, EntityXmlMappingData> xmlMappings = new HashMap<PersistentClass, EntityXmlMappingData>();
+
+ // First pass
+ while (classes.hasNext()) {
+ PersistentClass pc = classes.next();
+ // Collecting information from annotations on the persistent class pc
+ AnnotationsMetadataReader annotationsMetadataReader =
+ new AnnotationsMetadataReader(globalCfg, reflectionManager, pc);
+ PersistentClassVersioningData versioningData = annotationsMetadataReader.getVersioningData();
+
+ if (versioningData.isVersioned()) {
+ pcDatas.put(pc, versioningData);
+
+ if (!StringTools.isEmpty(versioningData.versionsTable.value())) {
+ verEntCfg.addCustomVersionsTableName(pc.getEntityName(), versioningData.versionsTable.value());
+ }
+
+ EntityXmlMappingData xmlMappingData = new EntityXmlMappingData();
+ versionsMetaGen.generateFirstPass(pc, versioningData, xmlMappingData);
+ xmlMappings.put(pc, xmlMappingData);
+ }
+ }
+
+ // Second pass
+ for (Map.Entry<PersistentClass, PersistentClassVersioningData> pcDatasEntry : pcDatas.entrySet()) {
+ EntityXmlMappingData xmlMappingData = xmlMappings.get(pcDatasEntry.getKey());
+
+ versionsMetaGen.generateSecondPass(pcDatasEntry.getKey(), pcDatasEntry.getValue(), xmlMappingData);
+
+ try {
+ cfg.addDocument(writer.write(xmlMappingData.getMainXmlMapping()));
+ // TODO
+ //writeDocument(xmlMappingData.getMainXmlMapping());
+
+ for (Document additionalMapping : xmlMappingData.getAdditionalXmlMappings()) {
+ cfg.addDocument(writer.write(additionalMapping));
+ // TODO
+ //writeDocument(additionalMapping);
+ }
+ } catch (DocumentException e) {
+ throw new MappingException(e);
+ }
+ }
+
+ // Only if there are any versioned classes
+ if (pcDatas.size() > 0) {
+ try {
+ if (revisionInfoXmlMapping != null) {
+ // TODO
+ //writeDocument(revisionInfoXmlMapping);
+ cfg.addDocument(writer.write(revisionInfoXmlMapping));
+ }
+ } catch (DocumentException e) {
+ throw new MappingException(e);
+ }
+ }
+
+ return new EntitiesConfigurations(versionsMetaGen.getEntitiesConfigurations());
+ }
+
+ // todo
+ private void writeDocument(Document e) {
+ ByteArrayOutputStream baos = new ByteArrayOutputStream();
+ Writer w = new PrintWriter(baos);
+
+ try {
+ XMLWriter xw = new XMLWriter(w, new OutputFormat(" ", true));
+ xw.write(e);
+ w.flush();
+ } catch (IOException e1) {
+ e1.printStackTrace();
+ }
+
+ System.out.println("-----------");
+ System.out.println(baos.toString());
+ System.out.println("-----------");
+ }
+}
Added: core/trunk/envers/src/main/java/org/jboss/envers/configuration/GlobalConfiguration.java
===================================================================
--- core/trunk/envers/src/main/java/org/jboss/envers/configuration/GlobalConfiguration.java (rev 0)
+++ core/trunk/envers/src/main/java/org/jboss/envers/configuration/GlobalConfiguration.java 2008-10-27 18:56:31 UTC (rev 15406)
@@ -0,0 +1,82 @@
+/*
+ * JBoss, Home of Professional Open Source
+ *
+ * Copyright 2008, Red Hat Middleware LLC, and others contributors as indicated
+ * by the @authors tag. All rights reserved.
+ *
+ * See the copyright.txt in the distribution for a full listing of individual
+ * contributors. 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, v. 2.1.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT A 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, v.2.1 along with this distribution; if not, write to the Free
+ * Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+ * 02110-1301, USA.
+ *
+ * Red Hat Author(s): Adam Warski
+ */
+package org.jboss.envers.configuration;
+
+import java.util.Properties;
+
+/**
+ * @author Adam Warski (adam at warski dot org)
+ * @author Nicolas Doroskevich
+ */
+public class GlobalConfiguration {
+ // Should a revision be generated when a not-owned relation field changes
+ private final boolean generateRevisionsForCollections;
+
+ // Should a warning, instead of an error and an exception, be logged, when an unsupported type is versioned
+ private final boolean warnOnUnsupportedTypes;
+
+ // Should the optimistic locking property of an entity be considered unversioned
+ private final boolean unversionedOptimisticLockingField;
+
+ /*
+ Which operator to use in correlated subqueries (when we want a property to be equal to the result of
+ a correlated subquery, for example: e.p <operator> (select max(e2.p) where e2.p2 = e.p2 ...).
+ Normally, this should be "=". However, HSQLDB has an issue related to that, so as a workaround,
+ "in" is used. See {@link org.jboss.envers.test.various.HsqlTest}.
+ */
+ private final String correlatedSubqueryOperator;
+
+ public GlobalConfiguration(Properties properties) {
+ String generateRevisionsForCollectionsStr = properties.getProperty("org.jboss.envers.revisionOnCollectionChange",
+ "true");
+ generateRevisionsForCollections = Boolean.parseBoolean(generateRevisionsForCollectionsStr);
+
+ String warnOnUnsupportedTypesStr = properties.getProperty("org.jboss.envers.warnOnUnsupportedTypes",
+ "false");
+ warnOnUnsupportedTypes = Boolean.parseBoolean(warnOnUnsupportedTypesStr);
+
+ String ignoreOptimisticLockingPropertyStr = properties.getProperty("org.jboss.envers.unversionedOptimisticLockingField",
+ "false");
+ unversionedOptimisticLockingField = Boolean.parseBoolean(ignoreOptimisticLockingPropertyStr);
+
+ correlatedSubqueryOperator = "org.hibernate.dialect.HSQLDialect".equals(
+ properties.getProperty("hibernate.dialect")) ? "in" : "=";
+ }
+
+ public boolean isGenerateRevisionsForCollections() {
+ return generateRevisionsForCollections;
+ }
+
+ public boolean isWarnOnUnsupportedTypes() {
+ return warnOnUnsupportedTypes;
+ }
+
+ public boolean isUnversionedOptimisticLockingField() {
+ return unversionedOptimisticLockingField;
+ }
+
+ public String getCorrelatedSubqueryOperator() {
+ return correlatedSubqueryOperator;
+ }
+}
Added: core/trunk/envers/src/main/java/org/jboss/envers/configuration/PersistentClassGraphDefiner.java
===================================================================
--- core/trunk/envers/src/main/java/org/jboss/envers/configuration/PersistentClassGraphDefiner.java (rev 0)
+++ core/trunk/envers/src/main/java/org/jboss/envers/configuration/PersistentClassGraphDefiner.java 2008-10-27 18:56:31 UTC (rev 15406)
@@ -0,0 +1,75 @@
+/*
+ * Envers. http://www.jboss.org/envers
+ *
+ * Copyright 2008 Red Hat Middleware, LLC. All rights reserved.
+ *
+ * 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, v. 2.1.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT A 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, v.2.1 along with this distribution; if not, write to the Free
+ * Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+ * 02110-1301, USA.
+ *
+ * Red Hat Author(s): Adam Warski
+ */
+package org.jboss.envers.configuration;
+
+import org.hibernate.mapping.PersistentClass;
+import org.hibernate.cfg.Configuration;
+import org.jboss.envers.tools.graph.GraphDefiner;
+import org.jboss.envers.tools.Tools;
+
+import java.util.List;
+import java.util.Iterator;
+import java.util.ArrayList;
+
+/**
+ * Defines a graph, where the vertexes are all persistent classes, and there is an edge from
+ * p.c. A to p.c. B iff A is a superclass of B.
+ * @author Adam Warski (adam at warski dot org)
+ */
+public class PersistentClassGraphDefiner implements GraphDefiner<PersistentClass, String> {
+ private Configuration cfg;
+
+ public PersistentClassGraphDefiner(Configuration cfg) {
+ this.cfg = cfg;
+ }
+
+ public String getRepresentation(PersistentClass pc) {
+ return pc.getEntityName();
+ }
+
+ public PersistentClass getValue(String entityName) {
+ return cfg.getClassMapping(entityName);
+ }
+
+ @SuppressWarnings({"unchecked"})
+ private void addNeighbours(List<PersistentClass> neighbours, Iterator<PersistentClass> subclassIterator) {
+ while (subclassIterator.hasNext()) {
+ PersistentClass subclass = subclassIterator.next();
+ neighbours.add(subclass);
+ addNeighbours(neighbours, (Iterator<PersistentClass>) subclass.getSubclassIterator());
+ }
+ }
+
+ @SuppressWarnings({"unchecked"})
+ public List<PersistentClass> getNeighbours(PersistentClass pc) {
+ List<PersistentClass> neighbours = new ArrayList<PersistentClass>();
+
+ addNeighbours(neighbours, (Iterator<PersistentClass>) pc.getSubclassIterator());
+
+ return neighbours;
+ }
+
+ @SuppressWarnings({"unchecked"})
+ public List<PersistentClass> getValues() {
+ return Tools.iteratorToList((Iterator<PersistentClass>) cfg.getClassMappings());
+ }
+}
Added: core/trunk/envers/src/main/java/org/jboss/envers/configuration/RevisionInfoConfiguration.java
===================================================================
--- core/trunk/envers/src/main/java/org/jboss/envers/configuration/RevisionInfoConfiguration.java (rev 0)
+++ core/trunk/envers/src/main/java/org/jboss/envers/configuration/RevisionInfoConfiguration.java 2008-10-27 18:56:31 UTC (rev 15406)
@@ -0,0 +1,265 @@
+/*
+ * JBoss, Home of Professional Open Source
+ *
+ * Copyright 2008, Red Hat Middleware LLC, and others contributors as indicated
+ * by the @authors tag. All rights reserved.
+ *
+ * See the copyright.txt in the distribution for a full listing of individual
+ * contributors. 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, v. 2.1.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT A 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, v.2.1 along with this distribution; if not, write to the Free
+ * Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+ * 02110-1301, USA.
+ *
+ * Red Hat Author(s): Adam Warski
+ */
+package org.jboss.envers.configuration;
+
+import org.jboss.envers.tools.reflection.YClass;
+import org.jboss.envers.tools.reflection.YReflectionManager;
+import org.jboss.envers.tools.reflection.YProperty;
+import org.jboss.envers.tools.MutableBoolean;
+import org.jboss.envers.*;
+import org.jboss.envers.configuration.metadata.MetadataTools;
+import org.jboss.envers.revisioninfo.*;
+import org.hibernate.MappingException;
+import org.hibernate.mapping.PersistentClass;
+import org.hibernate.cfg.Configuration;
+import org.dom4j.Document;
+import org.dom4j.DocumentHelper;
+import org.dom4j.Element;
+
+import java.util.Iterator;
+
+/**
+ * @author Adam Warski (adam at warski dot org)
+ */
+public class RevisionInfoConfiguration {
+ private String revisionInfoEntityName;
+ private String revisionInfoIdName;
+ private String revisionInfoTimestampName;
+ private String revisionInfoTimestampType;
+
+ private String revisionPropType;
+
+ public RevisionInfoConfiguration() {
+ revisionInfoEntityName = "org.jboss.envers.DefaultRevisionEntity";
+ revisionInfoIdName = "id";
+ revisionInfoTimestampName = "timestamp";
+ revisionInfoTimestampType = "long";
+
+ revisionPropType = "integer";
+ }
+
+ private Document generateDefaultRevisionInfoXmlMapping() {
+ Document document = DocumentHelper.createDocument();
+
+ Element class_mapping = MetadataTools.createEntity(document, null, null, null, null, null);
+
+ class_mapping.addAttribute("name", revisionInfoEntityName);
+ class_mapping.addAttribute("table", "_revisions_info");
+
+ Element idProperty = MetadataTools.addNativelyGeneratedId(class_mapping, revisionInfoIdName,
+ revisionPropType);
+ MetadataTools.addColumn(idProperty, "revision_id", null);
+
+ Element timestampProperty = MetadataTools.addProperty(class_mapping, revisionInfoTimestampName,
+ revisionInfoTimestampType, true, false);
+ MetadataTools.addColumn(timestampProperty, "revision_timestamp", null);
+
+ return document;
+ }
+
+ private Element generateRevisionInfoRelationMapping() {
+ Document document = DocumentHelper.createDocument();
+ Element rev_rel_mapping =document.addElement("key-many-to-one");
+ rev_rel_mapping.addAttribute("type", revisionPropType);
+ rev_rel_mapping.addAttribute("class", revisionInfoEntityName);
+
+ return rev_rel_mapping;
+ }
+
+ private void searchForRevisionInfoCfgInProperties(YClass clazz, YReflectionManager reflectionManager,
+ MutableBoolean revisionNumberFound, MutableBoolean revisionTimestampFound,
+ String accessType) {
+ for (YProperty property : clazz.getDeclaredProperties(accessType)) {
+ RevisionNumber revisionNumber = property.getAnnotation(RevisionNumber.class);
+ RevisionTimestamp revisionTimestamp = property.getAnnotation(RevisionTimestamp.class);
+
+ if (revisionNumber != null) {
+ if (revisionNumberFound.isSet()) {
+ throw new MappingException("Only one property may be annotated with @RevisionNumber!");
+ }
+
+ YClass revisionNumberClass = property.getType();
+ if (reflectionManager.equals(revisionNumberClass, Integer.class) ||
+ reflectionManager.equals(revisionNumberClass, Integer.TYPE)) {
+ revisionInfoIdName = property.getName();
+ revisionNumberFound.set();
+ } else if (reflectionManager.equals(revisionNumberClass, Long.class) ||
+ reflectionManager.equals(revisionNumberClass, Long.TYPE)) {
+ revisionInfoIdName = property.getName();
+ revisionNumberFound.set();
+
+ // The default is integer
+ revisionPropType = "long";
+ } else {
+ throw new MappingException("The field annotated with @RevisionNumber must be of type " +
+ "int, Integer, long or Long");
+ }
+ }
+
+ if (revisionTimestamp != null) {
+ if (revisionTimestampFound.isSet()) {
+ throw new MappingException("Only one property may be annotated with @RevisionTimestamp!");
+ }
+
+ YClass revisionTimestampClass = property.getType();
+ if (reflectionManager.equals(revisionTimestampClass, Long.class) ||
+ reflectionManager.equals(revisionTimestampClass, Long.TYPE)) {
+ revisionInfoTimestampName = property.getName();
+ revisionTimestampFound.set();
+ } else {
+ throw new MappingException("The field annotated with @RevisionTimestamp must be of type " +
+ "long or Long");
+ }
+ }
+ }
+ }
+
+ private void searchForRevisionInfoCfg(YClass clazz, YReflectionManager reflectionManager,
+ MutableBoolean revisionNumberFound, MutableBoolean revisionTimestampFound) {
+ YClass superclazz = clazz.getSuperclass();
+ if (!"java.lang.Object".equals(superclazz.getName())) {
+ searchForRevisionInfoCfg(superclazz, reflectionManager, revisionNumberFound, revisionTimestampFound);
+ }
+
+ searchForRevisionInfoCfgInProperties(clazz, reflectionManager, revisionNumberFound, revisionTimestampFound,
+ "field");
+ searchForRevisionInfoCfgInProperties(clazz, reflectionManager, revisionNumberFound, revisionTimestampFound,
+ "property");
+ }
+
+ @SuppressWarnings({"unchecked"})
+ public RevisionInfoConfigurationResult configure(Configuration cfg, YReflectionManager reflectionManager) {
+ Iterator<PersistentClass> classes = (Iterator<PersistentClass>) cfg.getClassMappings();
+ boolean revisionEntityFound = false;
+ RevisionInfoGenerator revisionInfoGenerator = null;
+
+ Class<?> revisionInfoClass = null;
+
+ while (classes.hasNext()) {
+ PersistentClass pc = classes.next();
+ YClass clazz;
+ try {
+ clazz = reflectionManager.classForName(pc.getClassName(), this.getClass());
+ } catch (ClassNotFoundException e) {
+ throw new MappingException(e);
+ }
+
+ 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 versioned
+ if (clazz.getAnnotation(Versioned.class) != null) {
+ throw new MappingException("An entity annotated with @RevisionEntity cannot be versioned!");
+ }
+
+ revisionEntityFound = true;
+
+ MutableBoolean revisionNumberFound = new MutableBoolean();
+ MutableBoolean revisionTimestampFound = new MutableBoolean();
+
+ searchForRevisionInfoCfg(clazz, reflectionManager, revisionNumberFound, revisionTimestampFound);
+
+ 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!");
+ }
+
+ revisionInfoEntityName = pc.getEntityName();
+
+ revisionInfoClass = pc.getMappedClass();
+ revisionInfoGenerator = new DefaultRevisionInfoGenerator(revisionInfoEntityName, revisionInfoClass,
+ revisionEntity.value(), revisionInfoTimestampName);
+ }
+ }
+
+ // In case of a custom revision info generator, the mapping will be null.
+ Document revisionInfoXmlMapping = null;
+
+ if (revisionInfoGenerator == null) {
+ revisionInfoClass = DefaultRevisionEntity.class;
+ revisionInfoGenerator = new DefaultRevisionInfoGenerator(revisionInfoEntityName, revisionInfoClass,
+ RevisionListener.class, revisionInfoTimestampName);
+ revisionInfoXmlMapping = generateDefaultRevisionInfoXmlMapping();
+ }
+
+ return new RevisionInfoConfigurationResult(
+ revisionInfoGenerator, revisionInfoXmlMapping,
+ new RevisionInfoQueryCreator(revisionInfoEntityName, revisionInfoIdName, revisionInfoTimestampName),
+ generateRevisionInfoRelationMapping(),
+ new RevisionInfoNumberReader(revisionInfoClass, revisionInfoIdName), revisionInfoEntityName);
+ }
+}
+
+class RevisionInfoConfigurationResult {
+ private final RevisionInfoGenerator revisionInfoGenerator;
+ private final Document revisionInfoXmlMapping;
+ private final RevisionInfoQueryCreator revisionInfoQueryCreator;
+ private final Element revisionInfoRelationMapping;
+ private final RevisionInfoNumberReader revisionInfoNumberReader;
+ private final String revisionInfoEntityName;
+
+ RevisionInfoConfigurationResult(RevisionInfoGenerator revisionInfoGenerator,
+ Document revisionInfoXmlMapping, RevisionInfoQueryCreator revisionInfoQueryCreator,
+ Element revisionInfoRelationMapping,
+ RevisionInfoNumberReader revisionInfoNumberReader, String revisionInfoEntityName) {
+ this.revisionInfoGenerator = revisionInfoGenerator;
+ this.revisionInfoXmlMapping = revisionInfoXmlMapping;
+ this.revisionInfoQueryCreator = revisionInfoQueryCreator;
+ this.revisionInfoRelationMapping = revisionInfoRelationMapping;
+ this.revisionInfoNumberReader = revisionInfoNumberReader;
+ this.revisionInfoEntityName = revisionInfoEntityName;
+ }
+
+ public RevisionInfoGenerator getRevisionInfoGenerator() {
+ return revisionInfoGenerator;
+ }
+
+ public Document getRevisionInfoXmlMapping() {
+ return revisionInfoXmlMapping;
+ }
+
+ public RevisionInfoQueryCreator getRevisionInfoQueryCreator() {
+ return revisionInfoQueryCreator;
+ }
+
+ public Element getRevisionInfoRelationMapping() {
+ return revisionInfoRelationMapping;
+ }
+
+ public RevisionInfoNumberReader getRevisionInfoNumberReader() {
+ return revisionInfoNumberReader;
+ }
+
+ public String getRevisionInfoEntityName() {
+ return revisionInfoEntityName;
+ }
+}
\ No newline at end of file
Added: core/trunk/envers/src/main/java/org/jboss/envers/configuration/VersionsConfiguration.java
===================================================================
--- core/trunk/envers/src/main/java/org/jboss/envers/configuration/VersionsConfiguration.java (rev 0)
+++ core/trunk/envers/src/main/java/org/jboss/envers/configuration/VersionsConfiguration.java 2008-10-27 18:56:31 UTC (rev 15406)
@@ -0,0 +1,101 @@
+/*
+ * Envers. http://www.jboss.org/envers
+ *
+ * Copyright 2008 Red Hat Middleware, LLC. All rights reserved.
+ *
+ * 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, v. 2.1.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT A 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, v.2.1 along with this distribution; if not, write to the Free
+ * Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+ * 02110-1301, USA.
+ *
+ * Red Hat Author(s): Adam Warski
+ */
+package org.jboss.envers.configuration;
+
+import org.hibernate.cfg.Configuration;
+import org.jboss.envers.entities.EntitiesConfigurations;
+import org.jboss.envers.synchronization.VersionsSyncManager;
+import org.jboss.envers.tools.reflection.YReflectionManager;
+import org.jboss.envers.revisioninfo.RevisionInfoQueryCreator;
+import org.jboss.envers.revisioninfo.RevisionInfoNumberReader;
+
+import java.util.*;
+
+/**
+ * @author Adam Warski (adam at warski dot org)
+ */
+public class VersionsConfiguration {
+ private final GlobalConfiguration globalCfg;
+ private final VersionsEntitiesConfiguration verEntCfg;
+ private final VersionsSyncManager versionsSyncManager;
+ private final EntitiesConfigurations entCfg;
+ private final RevisionInfoQueryCreator revisionInfoQueryCreator;
+ private final RevisionInfoNumberReader revisionInfoNumberReader;
+
+ public VersionsEntitiesConfiguration getVerEntCfg() {
+ return verEntCfg;
+ }
+
+ public VersionsSyncManager getSyncManager() {
+ return versionsSyncManager;
+ }
+
+ public GlobalConfiguration getGlobalCfg() {
+ return globalCfg;
+ }
+
+ public EntitiesConfigurations getEntCfg() {
+ return entCfg;
+ }
+
+ public RevisionInfoQueryCreator getRevisionInfoQueryCreator() {
+ return revisionInfoQueryCreator;
+ }
+
+ public RevisionInfoNumberReader getRevisionInfoNumberReader() {
+ return revisionInfoNumberReader;
+ }
+
+ @SuppressWarnings({"unchecked"})
+ public VersionsConfiguration(Configuration cfg) {
+ Properties properties = cfg.getProperties();
+
+ YReflectionManager reflectionManager = YReflectionManager.get(cfg);
+ RevisionInfoConfiguration revInfoCfg = new RevisionInfoConfiguration();
+ RevisionInfoConfigurationResult revInfoCfgResult = revInfoCfg.configure(cfg, reflectionManager);
+ verEntCfg = new VersionsEntitiesConfiguration(properties, revInfoCfgResult.getRevisionInfoEntityName());
+ globalCfg = new GlobalConfiguration(properties);
+ versionsSyncManager = new VersionsSyncManager(revInfoCfgResult.getRevisionInfoGenerator());
+ revisionInfoQueryCreator = revInfoCfgResult.getRevisionInfoQueryCreator();
+ revisionInfoNumberReader = revInfoCfgResult.getRevisionInfoNumberReader();
+ entCfg = new EntitiesConfigurator().configure(cfg, reflectionManager, globalCfg, verEntCfg,
+ revInfoCfgResult.getRevisionInfoXmlMapping(), revInfoCfgResult.getRevisionInfoRelationMapping());
+ }
+
+ //
+
+ private static Map<Configuration, VersionsConfiguration> cfgs
+ = new WeakHashMap<Configuration, VersionsConfiguration>();
+
+ public synchronized static VersionsConfiguration getFor(Configuration cfg) {
+ VersionsConfiguration verCfg = cfgs.get(cfg);
+
+ if (verCfg == null) {
+ verCfg = new VersionsConfiguration(cfg);
+ cfgs.put(cfg, verCfg);
+
+ cfg.buildMappings();
+ }
+
+ return verCfg;
+ }
+}
Added: core/trunk/envers/src/main/java/org/jboss/envers/configuration/VersionsEntitiesConfiguration.java
===================================================================
--- core/trunk/envers/src/main/java/org/jboss/envers/configuration/VersionsEntitiesConfiguration.java (rev 0)
+++ core/trunk/envers/src/main/java/org/jboss/envers/configuration/VersionsEntitiesConfiguration.java 2008-10-27 18:56:31 UTC (rev 15406)
@@ -0,0 +1,108 @@
+/*
+ * Envers. http://www.jboss.org/envers
+ *
+ * Copyright 2008 Red Hat Middleware, LLC. All rights reserved.
+ *
+ * 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, v. 2.1.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT A 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, v.2.1 along with this distribution; if not, write to the Free
+ * Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+ * 02110-1301, USA.
+ *
+ * Red Hat Author(s): Adam Warski
+ */
+package org.jboss.envers.configuration;
+
+import java.util.*;
+
+/**
+ * Configuration of versions entities - names of fields, entities and tables created to store versioning information.
+ * @author Adam Warski (adam at warski dot org)
+ */
+public class VersionsEntitiesConfiguration {
+ private final String versionsTablePrefix;
+ private final String versionsTableSuffix;
+
+ private final String originalIdPropName;
+
+ private final String revisionPropName;
+ private final String revisionPropPath;
+
+ private final String revisionTypePropName;
+ private final String revisionTypePropType;
+
+ private final String revisionInfoEntityName;
+
+ private final Map<String, String> customVersionsTablesNames;
+
+ public VersionsEntitiesConfiguration(Properties properties, String revisionInfoEntityName) {
+ this.revisionInfoEntityName = revisionInfoEntityName;
+
+ versionsTablePrefix = properties.getProperty("org.jboss.envers.versionsTablePrefix", "");
+ versionsTableSuffix = properties.getProperty("org.jboss.envers.versionsTableSuffix", "_versions");
+
+ originalIdPropName = "originalId";
+
+ revisionPropName = properties.getProperty("org.jboss.envers.revisionFieldName", "_revision");
+
+ revisionTypePropName = properties.getProperty("org.jboss.envers.revisionTypeFieldName", "_revision_type");
+ revisionTypePropType = "byte";
+
+ customVersionsTablesNames = new HashMap<String, String>();
+
+ revisionPropPath = originalIdPropName + "." + revisionPropName + ".id";
+ }
+
+ public String getOriginalIdPropName() {
+ return originalIdPropName;
+ }
+
+ public String getRevisionPropName() {
+ return revisionPropName;
+ }
+
+ public String getRevisionPropPath() {
+ return revisionPropPath;
+ }
+
+ public String getRevisionTypePropName() {
+ return revisionTypePropName;
+ }
+
+ public String getRevisionTypePropType() {
+ return revisionTypePropType;
+ }
+
+ public String getRevisionInfoEntityName() {
+ return revisionInfoEntityName;
+ }
+
+ //
+
+ public void addCustomVersionsTableName(String entityName, String tableName) {
+ customVersionsTablesNames.put(entityName, tableName);
+ }
+
+ //
+
+ public String getVersionsEntityName(String entityName) {
+ return versionsTablePrefix + entityName + versionsTableSuffix;
+ }
+
+ public String getVersionsTableName(String entityName, String tableName) {
+ String customHistoryTableName = customVersionsTablesNames.get(entityName);
+ if (customHistoryTableName == null) {
+ return versionsTablePrefix + tableName + versionsTableSuffix;
+ }
+
+ return customHistoryTableName;
+ }
+}
Added: core/trunk/envers/src/main/java/org/jboss/envers/configuration/metadata/AnnotationsMetadataReader.java
===================================================================
--- core/trunk/envers/src/main/java/org/jboss/envers/configuration/metadata/AnnotationsMetadataReader.java (rev 0)
+++ core/trunk/envers/src/main/java/org/jboss/envers/configuration/metadata/AnnotationsMetadataReader.java 2008-10-27 18:56:31 UTC (rev 15406)
@@ -0,0 +1,181 @@
+/*
+ * Envers. http://www.jboss.org/envers
+ *
+ * Copyright 2008 Red Hat Middleware, LLC. All rights reserved.
+ *
+ * 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, v. 2.1.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT A 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, v.2.1 along with this distribution; if not, write to the Free
+ * Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+ * 02110-1301, USA.
+ *
+ * Red Hat Author(s): Adam Warski
+ */
+package org.jboss.envers.configuration.metadata;
+
+import javax.persistence.Version;
+import javax.persistence.MapKey;
+
+import org.jboss.envers.configuration.GlobalConfiguration;
+import org.jboss.envers.tools.reflection.YClass;
+import org.jboss.envers.tools.reflection.YProperty;
+import org.jboss.envers.tools.reflection.YReflectionManager;
+import org.jboss.envers.*;
+import org.hibernate.mapping.PersistentClass;
+import org.hibernate.MappingException;
+
+import java.lang.annotation.Annotation;
+
+/**
+ * A helper class to read versioning meta-data from annotations on a persistent class.
+ * @author Adam Warski (adam at warski dot org)
+ * @author Sebastian Komander
+ */
+public final class AnnotationsMetadataReader {
+ private final GlobalConfiguration globalCfg;
+ private final YReflectionManager reflectionManager;
+ private final PersistentClass pc;
+
+ /**
+ * This object is filled with information read from annotations and returned by the <code>getVersioningData</code>
+ * method.
+ */
+ private final PersistentClassVersioningData versioningData;
+
+ public AnnotationsMetadataReader(GlobalConfiguration globalCfg, YReflectionManager reflectionManager,
+ PersistentClass pc) {
+ this.globalCfg = globalCfg;
+ this.reflectionManager = reflectionManager;
+ this.pc = pc;
+
+ versioningData = new PersistentClassVersioningData();
+ }
+
+ private void addPropertyVersioned(YProperty property) {
+ Versioned ver = property.getAnnotation(Versioned.class);
+ if (ver != null) {
+ versioningData.propertyStoreInfo.propertyStores.put(property.getName(), ver.modStore());
+ }
+ }
+
+ private void addPropertyMapKey(YProperty property) {
+ MapKey mapKey = property.getAnnotation(MapKey.class);
+ if (mapKey != null) {
+ versioningData.mapKeys.put(property.getName(), mapKey.name());
+ }
+ }
+
+ private void addPropertyUnversioned(YProperty property) {
+ // check if a property is declared as unversioned to exclude it
+ // useful if a class is versioned but some properties should be excluded
+ Unversioned unVer = property.getAnnotation(Unversioned.class);
+ if (unVer != null) {
+ versioningData.unversionedProperties.add(property.getName());
+ } else {
+ // if the optimistic locking field has to be unversioned and the current property
+ // is the optimistic locking field, add it to the unversioned properties list
+ if (globalCfg.isUnversionedOptimisticLockingField()) {
+ Version jpaVer = property.getAnnotation(Version.class);
+ if (jpaVer != null) {
+ versioningData.unversionedProperties.add(property.getName());
+ }
+ }
+ }
+ }
+
+ private void addPropertyJoinTables(YProperty property) {
+ VersionsJoinTable joinTable = property.getAnnotation(VersionsJoinTable.class);
+ if (joinTable != null) {
+ versioningData.versionsJoinTables.put(property.getName(), joinTable);
+ }
+ }
+
+ private void addFromProperties(Iterable<YProperty> properties) {
+ for (YProperty property : properties) {
+ addPropertyVersioned(property);
+ addPropertyUnversioned(property);
+ addPropertyJoinTables(property);
+ addPropertyMapKey(property);
+ }
+ }
+
+ private void addPropertiesFromClass(YClass clazz) {
+ YClass superclazz = clazz.getSuperclass();
+ if (!"java.lang.Object".equals(superclazz.getName())) {
+ addPropertiesFromClass(superclazz);
+ }
+
+ addFromProperties(clazz.getDeclaredProperties("field"));
+ addFromProperties(clazz.getDeclaredProperties("property"));
+ }
+
+ private void addDefaultVersioned(YClass clazz) {
+ Versioned defaultVersioned = clazz.getAnnotation(Versioned.class);
+
+ if (defaultVersioned != null) {
+ versioningData.propertyStoreInfo.defaultStore = defaultVersioned.modStore();
+ }
+ }
+
+ private void addVersionsTable(YClass clazz) {
+ VersionsTable versionsTable = clazz.getAnnotation(VersionsTable.class);
+ if (versionsTable != null) {
+ versioningData.versionsTable = versionsTable;
+ } else {
+ versioningData.versionsTable = getDefaultVersionsTable();
+ }
+ }
+
+ private void addVersionsSecondaryTables(YClass clazz) {
+ // Getting information on secondary tables
+ SecondaryVersionsTable secondaryVersionsTable1 = clazz.getAnnotation(SecondaryVersionsTable.class);
+ if (secondaryVersionsTable1 != null) {
+ versioningData.secondaryTableDictionary.put(secondaryVersionsTable1.secondaryTableName(),
+ secondaryVersionsTable1.secondaryVersionsTableName());
+ }
+
+ SecondaryVersionsTables secondaryVersionsTables = clazz.getAnnotation(SecondaryVersionsTables.class);
+ if (secondaryVersionsTables != null) {
+ for (SecondaryVersionsTable secondaryVersionsTable2 : secondaryVersionsTables.value()) {
+ versioningData.secondaryTableDictionary.put(secondaryVersionsTable2.secondaryTableName(),
+ secondaryVersionsTable2.secondaryVersionsTableName());
+ }
+ }
+ }
+
+ public PersistentClassVersioningData getVersioningData() {
+ if (pc.getClassName() == null) {
+ return versioningData;
+ }
+
+ try {
+ YClass clazz = reflectionManager.classForName(pc.getClassName(), this.getClass());
+
+ addDefaultVersioned(clazz);
+ addPropertiesFromClass(clazz);
+ addVersionsTable(clazz);
+ addVersionsSecondaryTables(clazz);
+ } catch (ClassNotFoundException e) {
+ throw new MappingException(e);
+ }
+
+ return versioningData;
+ }
+
+ private VersionsTable getDefaultVersionsTable() {
+ return new VersionsTable() {
+ public String value() { return ""; }
+ public String schema() { return ""; }
+ public String catalog() { return ""; }
+ public Class<? extends Annotation> annotationType() { return this.getClass(); }
+ };
+ }
+}
Added: core/trunk/envers/src/main/java/org/jboss/envers/configuration/metadata/BasicMetadataGenerator.java
===================================================================
--- core/trunk/envers/src/main/java/org/jboss/envers/configuration/metadata/BasicMetadataGenerator.java (rev 0)
+++ core/trunk/envers/src/main/java/org/jboss/envers/configuration/metadata/BasicMetadataGenerator.java 2008-10-27 18:56:31 UTC (rev 15406)
@@ -0,0 +1,164 @@
+/*
+ * JBoss, Home of Professional Open Source
+ *
+ * Copyright 2008, Red Hat Middleware LLC, and others contributors as indicated
+ * by the @authors tag. All rights reserved.
+ *
+ * See the copyright.txt in the distribution for a full listing of individual
+ * contributors. 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, v. 2.1.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT A 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, v.2.1 along with this distribution; if not, write to the Free
+ * Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+ * 02110-1301, USA.
+ *
+ * Red Hat Author(s): Adam Warski
+ */
+package org.jboss.envers.configuration.metadata;
+
+import org.dom4j.Element;
+import org.hibernate.mapping.*;
+import org.hibernate.type.*;
+import org.hibernate.util.StringHelper;
+import org.jboss.envers.entities.mapper.SimpleMapperBuilder;
+import org.jboss.envers.entities.mapper.CompositeMapperBuilder;
+import org.jboss.envers.ModificationStore;
+
+import java.util.Iterator;
+import java.util.Properties;
+
+/**
+ * Generates metadata for basic properties: immutable types (including enums) and components
+ * @author Adam Warski (adam at warski dot org)
+ */
+public final class BasicMetadataGenerator {
+ boolean addBasic(Element parent, String name, Value value, CompositeMapperBuilder mapper,
+ ModificationStore store, String entityName, boolean insertable, boolean key) {
+ Type type = value.getType();
+
+ if (type instanceof ComponentType) {
+ addComponent(parent, name, value, mapper, entityName, key);
+ return true;
+ } else {
+ return addBasicNoComponent(parent, name, value, mapper, store, insertable, key);
+ }
+ }
+
+ boolean addBasicNoComponent(Element parent, String name, Value value, SimpleMapperBuilder mapper,
+ ModificationStore store, boolean insertable, boolean key) {
+ Type type = value.getType();
+
+ if (type instanceof ImmutableType || type instanceof MutableType) {
+ addSimpleValue(parent, name, value, mapper, store, insertable, key);
+ } else if (type instanceof CustomType || type instanceof CompositeCustomType) {
+ addCustomValue(parent, name, value, mapper, store, insertable, key);
+ } else if ("org.hibernate.type.PrimitiveByteArrayBlobType".equals(type.getClass().getName())) {
+ addSimpleValue(parent, name, value, mapper, store, insertable, key);
+ } else {
+ return false;
+ }
+
+ return true;
+ }
+
+ @SuppressWarnings({"unchecked"})
+ private void addSimpleValue(Element parent, String name, Value value, SimpleMapperBuilder mapper,
+ ModificationStore store, boolean insertable, boolean key) {
+ if (parent != null) {
+ Element prop_mapping = MetadataTools.addProperty(parent, name,
+ value.getType().getName(), insertable, key);
+ MetadataTools.addColumns(prop_mapping, (Iterator<Column>) value.getColumnIterator());
+ }
+
+ // A null mapper means that we only want to add xml mappings
+ if (mapper != null) {
+ mapper.add(name, store);
+ }
+ }
+
+ @SuppressWarnings({"unchecked"})
+ private void addCustomValue(Element parent, String name, Value value, SimpleMapperBuilder mapper,
+ ModificationStore store, boolean insertable, boolean key) {
+ if (parent != null) {
+ Element prop_mapping = MetadataTools.addProperty(parent, name,
+ null, insertable, key);
+
+ //CustomType propertyType = (CustomType) value.getType();
+
+ Element type_mapping = prop_mapping.addElement("type");
+ type_mapping.addAttribute("name", value.getType().getName());
+
+ if (value instanceof SimpleValue) {
+ Properties typeParameters = ((SimpleValue) value).getTypeParameters();
+ if (typeParameters != null) {
+ for (java.util.Map.Entry paramKeyValue : typeParameters.entrySet()) {
+ Element type_param = type_mapping.addElement("param");
+ type_param.addAttribute("name", (String) paramKeyValue.getKey());
+ type_param.setText((String) paramKeyValue.getValue());
+ }
+ }
+ }
+
+ MetadataTools.addColumns(prop_mapping, (Iterator<Column>) value.getColumnIterator());
+ }
+
+ if (mapper != null) {
+ mapper.add(name, store);
+ }
+ }
+
+ private void addComponentClassName(Element any_mapping, Component comp) {
+ if (StringHelper.isNotEmpty(comp.getComponentClassName())) {
+ any_mapping.addAttribute("class", comp.getComponentClassName());
+ }
+ }
+
+ @SuppressWarnings({"unchecked"})
+ private void addComponent(Element parent, String name, Value value, CompositeMapperBuilder mapper,
+ String entityName, boolean key) {
+ Element component_mapping = null;
+ Component prop_component = (Component) value;
+
+ if (parent != null) {
+ /*
+ TODO: investigate relations inside components
+ if (!firstPass) {
+ // The required element already exists.
+ Iterator<Element> iter = parent.elementIterator("component");
+ while (iter.hasNext()) {
+ Element child = iter.next();
+ if (child.attribute("name").getText().equals(name)) {
+ component_mapping = child;
+ break;
+ }
+ }
+
+ if (component_mapping == null) {
+ throw new VersionsException("Element for component not found during second pass!");
+ }
+ } else {
+ */
+
+ component_mapping = parent.addElement("component");
+ component_mapping.addAttribute("name", name);
+
+ addComponentClassName(component_mapping, prop_component);
+ }
+
+ CompositeMapperBuilder componentMapper = mapper.addComposite(name);
+
+ Iterator<Property> properties = (Iterator<Property>) prop_component.getPropertyIterator();
+ while (properties.hasNext()) {
+ Property property = properties.next();
+ addBasic(component_mapping, property.getName(), property.getValue(), componentMapper,
+ ModificationStore.FULL, entityName, property.isInsertable(), key);
+ }
+ }
+}
Added: core/trunk/envers/src/main/java/org/jboss/envers/configuration/metadata/CollectionMetadataGenerator.java
===================================================================
--- core/trunk/envers/src/main/java/org/jboss/envers/configuration/metadata/CollectionMetadataGenerator.java (rev 0)
+++ core/trunk/envers/src/main/java/org/jboss/envers/configuration/metadata/CollectionMetadataGenerator.java 2008-10-27 18:56:31 UTC (rev 15406)
@@ -0,0 +1,490 @@
+/*
+ * JBoss, Home of Professional Open Source
+ *
+ * Copyright 2008, Red Hat Middleware LLC, and others contributors as indicated
+ * by the @authors tag. All rights reserved.
+ *
+ * See the copyright.txt in the distribution for a full listing of individual
+ * contributors. 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, v. 2.1.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT A 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, v.2.1 along with this distribution; if not, write to the Free
+ * Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+ * 02110-1301, USA.
+ *
+ * Red Hat Author(s): Adam Warski
+ */
+package org.jboss.envers.configuration.metadata;
+
+import org.hibernate.mapping.*;
+import org.hibernate.mapping.Collection;
+import org.hibernate.MappingException;
+import org.hibernate.type.*;
+import org.jboss.envers.entities.mapper.CompositeMapperBuilder;
+import org.jboss.envers.entities.mapper.relation.*;
+import org.jboss.envers.entities.mapper.relation.lazy.proxy.*;
+import org.jboss.envers.entities.mapper.relation.query.RelationQueryGenerator;
+import org.jboss.envers.entities.mapper.relation.query.OneVersionsEntityQueryGenerator;
+import org.jboss.envers.entities.mapper.relation.component.*;
+import org.jboss.envers.entities.EntityConfiguration;
+import org.jboss.envers.entities.IdMappingData;
+import org.jboss.envers.tools.Tools;
+import org.jboss.envers.tools.StringTools;
+import org.jboss.envers.ModificationStore;
+import org.jboss.envers.VersionsJoinTable;
+import org.dom4j.Element;
+
+import javax.persistence.JoinColumn;
+import java.util.*;
+import java.util.Set;
+import java.util.List;
+import java.util.Map;
+import java.lang.annotation.Annotation;
+
+/**
+ * Generates metadata for a collection-valued property.
+ * @author Adam Warski (adam at warski dot org)
+ */
+public final class CollectionMetadataGenerator {
+ private final VersionsMetadataGenerator mainGenerator;
+ private final String propertyName;
+ private final Collection propertyValue;
+ private final CompositeMapperBuilder currentMapper;
+ private final String referencingEntityName;
+ private final EntityXmlMappingData xmlMappingData;
+ private final VersionsJoinTable joinTable;
+ private final String mapKey;
+
+ private final EntityConfiguration referencingEntityConfiguration;
+ /**
+ * Null if this collection isn't a relation to another entity.
+ */
+ private final String referencedEntityName;
+
+ /**
+ * @param mainGenerator Main generator, giving access to configuration and the basic mapper.
+ * @param propertyName Name of the property that references the collection in the referencing entity.
+ * @param propertyValue Value of the collection, as mapped by Hibernate.
+ * @param currentMapper Mapper, to which the appropriate {@link org.jboss.envers.entities.mapper.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
+ * be created using this object.
+ * @param joinTable User data for the middle (join) table. <code>null</code> if the user didn't specify it.
+ * @param mapKey The value of the name() property of the MapKey annotation on this property. Null, if this
+ * property isn't annotated with this annotation.
+ */
+ public CollectionMetadataGenerator(VersionsMetadataGenerator mainGenerator, String propertyName,
+ Collection propertyValue, CompositeMapperBuilder currentMapper,
+ String referencingEntityName, EntityXmlMappingData xmlMappingData,
+ VersionsJoinTable joinTable, String mapKey) {
+ this.mainGenerator = mainGenerator;
+ this.propertyName = propertyName;
+ this.propertyValue = propertyValue;
+ this.currentMapper = currentMapper;
+ this.referencingEntityName = referencingEntityName;
+ this.xmlMappingData = xmlMappingData;
+ this.joinTable = joinTable == null ? getDefaultVersionsJoinTable() : joinTable;
+ this.mapKey = mapKey;
+
+ referencingEntityConfiguration = mainGenerator.getEntitiesConfigurations().get(referencingEntityName);
+ if (referencingEntityConfiguration == null) {
+ throw new MappingException("Unable to read versioning configuration for " + referencingEntityName + "!");
+ }
+
+ referencedEntityName = getReferencedEntityName(propertyValue.getElement());
+ }
+
+ private String getReferencedEntityName(Value value) {
+ if (value instanceof ToOne) {
+ return ((ToOne) value).getReferencedEntityName();
+ } else if (value instanceof OneToMany) {
+ return ((OneToMany) value).getReferencedEntityName();
+ } else {
+ return null;
+ }
+ }
+
+ void addCollection() {
+ Type type = propertyValue.getType();
+
+ if ((type instanceof BagType || type instanceof SetType || type instanceof MapType) &&
+ (propertyValue.getElement() instanceof OneToMany) && (propertyValue.isInverse())) {
+ // A one-to-many relation mapped using @ManyToOne and @OneToMany(mappedBy="...")
+ addOneToManyAttached();
+ } else {
+ // All other kinds of relations require a middle (join) table.
+ addWithMiddleTable();
+ }
+ }
+
+ @SuppressWarnings({"unchecked"})
+ private void addOneToManyAttached() {
+ String mappedBy = getMappedBy(propertyValue);
+
+ EntityConfiguration referencedEntityConfiguration = mainGenerator.getEntitiesConfigurations()
+ .get(referencedEntityName);
+
+ IdMappingData referencedIdMapping = referencedEntityConfiguration.getIdMappingData();
+ IdMappingData referencingIdMapping = referencingEntityConfiguration.getIdMappingData();
+
+ // Generating the id mappers data for the referencing side of the relation.
+ MiddleIdData referencingIdData = new MiddleIdData(mainGenerator.getVerEntCfg(), referencingIdMapping,
+ mappedBy + "_", referencingEntityName);
+
+ // And for the referenced side. The prefixed mapper won't be used (as this collection isn't persisted
+ // in a join table, so the prefix value is arbitrary).
+ MiddleIdData referencedIdData = new MiddleIdData(mainGenerator.getVerEntCfg(), referencedIdMapping,
+ null, referencedEntityName);
+
+ // Generating the element mapping.
+ MiddleComponentData elementComponentData = new MiddleComponentData(
+ new MiddleRelatedComponentMapper(referencedIdData), 0);
+
+ // Generating the index mapping, if an index exists. It can only exists in case a javax.persistence.MapKey
+ // annotation is present on the entity. So the middleEntityXml will be not be used. The queryGeneratorBuilder
+ // will only be checked for nullnes.
+ MiddleComponentData indexComponentData = addIndex(null, null);
+
+ // Generating the query generator - it should read directly from the related entity.
+ RelationQueryGenerator queryGenerator = new OneVersionsEntityQueryGenerator(mainGenerator.getGlobalCfg(),
+ mainGenerator.getVerEntCfg(), referencingIdData, referencedEntityName,
+ referencedIdMapping.getIdMapper());
+
+ // Creating common mapper data.
+ CommonCollectionMapperData commonCollectionMapperData = new CommonCollectionMapperData(
+ mainGenerator.getVerEntCfg(), referencedEntityName, propertyName,
+ referencingIdData, queryGenerator);
+
+ // Checking the type of the collection and adding an appropriate mapper.
+ addMapper(commonCollectionMapperData, elementComponentData, indexComponentData);
+
+ // Storing information about this relation.
+ referencingEntityConfiguration.addToManyNotOwningRelation(propertyName, mappedBy,
+ referencedEntityName, referencingIdData.getPrefixedMapper());
+ }
+
+ /**
+ * Adds mapping of the id of a related entity to the given xml mapping, prefixing the id with the given prefix.
+ * @param xmlMapping Mapping, to which to add the xml.
+ * @param prefix Prefix for the names of properties which will be prepended to properties that form the id.
+ * @param columnNameIterator Iterator over the column names that will be used for properties that form the id.
+ * @param relatedIdMapping Id mapping data of the related entity.
+ */
+ @SuppressWarnings({"unchecked"})
+ private void addRelatedToXmlMapping(Element xmlMapping, String prefix,
+ MetadataTools.ColumnNameIterator columnNameIterator,
+ IdMappingData relatedIdMapping) {
+ Element properties = (Element) relatedIdMapping.getXmlRelationMapping().clone();
+ MetadataTools.prefixNamesInPropertyElement(properties, prefix, columnNameIterator, true);
+ for (Element idProperty : (java.util.List<Element>) properties.elements()) {
+ xmlMapping.add((Element) idProperty.clone());
+ }
+ }
+
+ private String getMiddleTableName(Collection value, String entityName) {
+ // We check how Hibernate maps the collection.
+ if (value.getElement() instanceof OneToMany && !value.isInverse()) {
+ // This must be a @JoinColumn+ at OneToMany mapping. Generating the table name, as Hibernate doesn't use a
+ // middle table for mapping this relation.
+ return StringTools.getLastComponent(entityName) + "_" + StringTools.getLastComponent(getReferencedEntityName(value.getElement()));
+ } else {
+ // Hibernate uses a middle table for mapping this relation, so we get it's name directly.
+ return value.getCollectionTable().getName();
+ }
+ }
+
+ @SuppressWarnings({"unchecked"})
+ private void addWithMiddleTable() {
+ // Generating the name of the middle table
+ String versionsMiddleTableName;
+ String versionsMiddleEntityName;
+ if (!StringTools.isEmpty(joinTable.name())) {
+ versionsMiddleTableName = joinTable.name();
+ versionsMiddleEntityName = joinTable.name();
+ } else {
+ String middleTableName = getMiddleTableName(propertyValue, referencingEntityName);
+ versionsMiddleTableName = mainGenerator.getVerEntCfg().getVersionsTableName(null, middleTableName);
+ versionsMiddleEntityName = mainGenerator.getVerEntCfg().getVersionsEntityName(middleTableName);
+ }
+
+ // 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()) {
+ middleEntityXml = createMiddleEntityXml(versionsMiddleTableName, versionsMiddleEntityName);
+ } else {
+ middleEntityXml = null;
+ }
+
+ // ******
+ // Generating the mapping for the referencing entity (it must be an entity).
+ // ******
+ // Getting the id-mapping data of the referencing entity (the entity that "owns" this collection).
+ IdMappingData referencingIdMapping = referencingEntityConfiguration.getIdMappingData();
+
+ // Only valid for an inverse relation; null otherwise.
+ String mappedBy;
+
+ // The referencing prefix is always for a related entity. So it has always the "_" at the end added.
+ String referencingPrefixRelated;
+ String referencedPrefix;
+
+ if (propertyValue.isInverse()) {
+ // If the relation is inverse, then referencedEntityName is not null.
+ mappedBy = getMappedBy(propertyValue.getCollectionTable(), mainGenerator.getCfg().getClassMapping(referencedEntityName));
+
+ referencingPrefixRelated = mappedBy + "_";
+ referencedPrefix = StringTools.getLastComponent(referencedEntityName);
+ } else {
+ mappedBy = null;
+
+ referencingPrefixRelated = StringTools.getLastComponent(referencingEntityName) + "_";
+ referencedPrefix = referencedEntityName == null ? "element" : propertyName;
+ }
+
+ // Storing the id data of the referencing entity: original mapper, prefixed mapper and entity name.
+ MiddleIdData referencingIdData = new MiddleIdData(mainGenerator.getVerEntCfg(), referencingIdMapping,
+ referencingPrefixRelated, referencingEntityName);
+
+ // Creating a query generator builder, to which additional id data will be added, in case this collection
+ // 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.
+ QueryGeneratorBuilder queryGeneratorBuilder = new QueryGeneratorBuilder(mainGenerator.getGlobalCfg(),
+ mainGenerator.getVerEntCfg(), referencingIdData, versionsMiddleEntityName);
+
+ // Adding the XML mapping for the referencing entity, if the relation isn't inverse.
+ if (middleEntityXml != null) {
+ // Adding related-entity (in this case: the referencing's entity id) id mapping to the xml.
+ addRelatedToXmlMapping(middleEntityXml, referencingPrefixRelated,
+ MetadataTools.getColumnNameIterator(propertyValue.getKey().getColumnIterator()),
+ referencingIdMapping);
+ }
+
+ // ******
+ // Generating the element mapping.
+ // ******
+ MiddleComponentData elementComponentData = addValueToMiddleTable(propertyValue.getElement(), middleEntityXml,
+ queryGeneratorBuilder, referencedPrefix, joinTable.inverseJoinColumns());
+
+ // ******
+ // Generating the index mapping, if an index exists.
+ // ******
+ MiddleComponentData indexComponentData = addIndex(middleEntityXml, queryGeneratorBuilder);
+
+ // ******
+ // Generating the property mapper.
+ // ******
+ // Building the query generator.
+ RelationQueryGenerator queryGenerator = queryGeneratorBuilder.build(elementComponentData, indexComponentData);
+
+ // Creating common data
+ CommonCollectionMapperData commonCollectionMapperData = new CommonCollectionMapperData(
+ mainGenerator.getVerEntCfg(), versionsMiddleEntityName, propertyName, referencingIdData, queryGenerator);
+
+ // Checking the type of the collection and adding an appropriate mapper.
+ addMapper(commonCollectionMapperData, elementComponentData, indexComponentData);
+
+ // ******
+ // Storing information about this relation.
+ // ******
+ storeMiddleEntityRelationInformation(mappedBy);
+ }
+
+ private MiddleComponentData addIndex(Element middleEntityXml, QueryGeneratorBuilder queryGeneratorBuilder) {
+ if (propertyValue instanceof IndexedCollection) {
+ IndexedCollection indexedValue = (IndexedCollection) propertyValue;
+ 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);
+ } else {
+ IdMappingData referencedIdMapping = mainGenerator.getEntitiesConfigurations()
+ .get(referencedEntityName).getIdMappingData();
+ int currentIndex = queryGeneratorBuilder == null ? 0 : queryGeneratorBuilder.getCurrentIndex();
+ if ("".equals(mapKey)) {
+ // The key of the map is the id of the entity.
+ return new MiddleComponentData(new MiddleMapKeyIdComponentMapper(mainGenerator.getVerEntCfg(),
+ referencedIdMapping.getIdMapper()), currentIndex);
+ } else {
+ // The key of the map is a property of the entity.
+ return new MiddleComponentData(new MiddleMapKeyPropertyComponentMapper(mapKey), currentIndex);
+ }
+ }
+ } else {
+ // No index - creating a dummy mapper.
+ return new MiddleComponentData(new MiddleDummyComponentMapper(), 0);
+ }
+ }
+
+ /**
+ *
+ * @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.
+ * @return Data for mapping this component.
+ */
+ @SuppressWarnings({"unchecked"})
+ private MiddleComponentData addValueToMiddleTable(Value value, Element xmlMapping,
+ QueryGeneratorBuilder queryGeneratorBuilder,
+ String prefix, JoinColumn[] joinColumns) {
+ Type type = value.getType();
+ if (type instanceof ManyToOneType) {
+ String prefixRelated = prefix + "_";
+
+ String referencedEntityName = getReferencedEntityName(value);
+ IdMappingData referencedIdMapping = mainGenerator.getEntitiesConfigurations()
+ .get(referencedEntityName).getIdMappingData();
+
+ // Adding related-entity (in this case: the referenced entities id) id mapping to the xml only if the
+ // relation isn't inverse (so when <code>xmlMapping</code> is not null).
+ if (xmlMapping != null) {
+ addRelatedToXmlMapping(xmlMapping, prefixRelated,
+ joinColumns != null && joinColumns.length > 0
+ ? MetadataTools.getColumnNameIterator(joinColumns)
+ : MetadataTools.getColumnNameIterator(value.getColumnIterator()),
+ referencedIdMapping);
+ }
+
+ // Storing the id data of the referenced entity: original mapper, prefixed mapper and entity name.
+ MiddleIdData referencedIdData = new MiddleIdData(mainGenerator.getVerEntCfg(), referencedIdMapping,
+ prefixRelated, referencedEntityName);
+ // And adding it to the generator builder.
+ queryGeneratorBuilder.addRelation(referencedIdData);
+
+ return new MiddleComponentData(new MiddleRelatedComponentMapper(referencedIdData),
+ queryGeneratorBuilder.getCurrentIndex());
+ } else {
+ // Last but one parameter: collection components are always insertable
+ boolean mapped = mainGenerator.getBasicMetadataGenerator().addBasicNoComponent(xmlMapping, prefix, value, null,
+ ModificationStore.FULL, 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), 0);
+ } else {
+ mainGenerator.throwUnsupportedTypeException(type, referencingEntityName, propertyName);
+ // Impossible to get here.
+ throw new AssertionError();
+ }
+ }
+ }
+
+ private void addMapper(CommonCollectionMapperData commonCollectionMapperData, MiddleComponentData elementComponentData,
+ MiddleComponentData indexComponentData) {
+ Type type = propertyValue.getType();
+ if (type instanceof SortedSetType) {
+ currentMapper.addComposite(propertyName, new BasicCollectionMapper<Set>(commonCollectionMapperData,
+ TreeSet.class, SortedSetProxy.class, elementComponentData));
+ } else if (type instanceof SetType) {
+ currentMapper.addComposite(propertyName, new BasicCollectionMapper<Set>(commonCollectionMapperData,
+ HashSet.class, SetProxy.class, elementComponentData));
+ } else if (type instanceof SortedMapType) {
+ // Indexed collection, so <code>indexComponentData</code> is not null.
+ currentMapper.addComposite(propertyName, new MapCollectionMapper<Map>(commonCollectionMapperData,
+ TreeMap.class, SortedMapProxy.class, elementComponentData, indexComponentData));
+ } else if (type instanceof MapType) {
+ // Indexed collection, so <code>indexComponentData</code> is not null.
+ currentMapper.addComposite(propertyName, new MapCollectionMapper<Map>(commonCollectionMapperData,
+ HashMap.class, MapProxy.class, elementComponentData, indexComponentData));
+ } else if (type instanceof BagType) {
+ currentMapper.addComposite(propertyName, new BasicCollectionMapper<List>(commonCollectionMapperData,
+ ArrayList.class, ListProxy.class, elementComponentData));
+ } else if (type instanceof ListType) {
+ // Indexed collection, so <code>indexComponentData</code> is not null.
+ currentMapper.addComposite(propertyName, new ListCollectionMapper(commonCollectionMapperData,
+ elementComponentData, indexComponentData));
+ } else {
+ mainGenerator.throwUnsupportedTypeException(type, referencingEntityName, propertyName);
+ }
+ }
+
+ private void storeMiddleEntityRelationInformation(String mappedBy) {
+ // Only if this is a relation (when there is a referenced entity).
+ if (referencedEntityName != null) {
+ if (propertyValue.isInverse()) {
+ referencingEntityConfiguration.addToManyMiddleNotOwningRelation(propertyName, mappedBy, referencedEntityName);
+ } else {
+ referencingEntityConfiguration.addToManyMiddleRelation(propertyName, referencedEntityName);
+ }
+ }
+ }
+
+ private Element createMiddleEntityXml(String versionsMiddleTableName, String versionsMiddleEntityName) {
+ String schema = StringTools.isEmpty(joinTable.schema()) ? propertyValue.getCollectionTable().getSchema() : joinTable.schema();
+ String catalog = StringTools.isEmpty(joinTable.catalog()) ? propertyValue.getCollectionTable().getCatalog() : joinTable.catalog();
+
+ Element middleEntityXml = MetadataTools.createEntity(xmlMappingData.newAdditionalMapping(),
+ versionsMiddleEntityName, versionsMiddleTableName, schema, catalog, null);
+ Element middleEntityXmlId = middleEntityXml.addElement("composite-id");
+
+ middleEntityXmlId.addAttribute("name", mainGenerator.getVerEntCfg().getOriginalIdPropName());
+
+ // Adding the revision number as a foreign key to the revision info entity to the composite id of the
+ // middle table.
+ mainGenerator.addRevisionInfoRelation(middleEntityXmlId);
+
+ // Adding the revision type property to the entity xml.
+ mainGenerator.addRevisionType(middleEntityXml);
+
+ // All other properties should also be part of the primary key of the middle entity.
+ return middleEntityXmlId;
+ }
+
+ private VersionsJoinTable getDefaultVersionsJoinTable() {
+ return new VersionsJoinTable() {
+ public String name() { return ""; }
+ public String schema() { return ""; }
+ public String catalog() { return ""; }
+ public JoinColumn[] inverseJoinColumns() { return new JoinColumn[0]; }
+ public Class<? extends Annotation> annotationType() { return this.getClass(); }
+ };
+ }
+
+ @SuppressWarnings({"unchecked"})
+ private String getMappedBy(Collection collectionValue) {
+ Iterator<Property> assocClassProps =
+ ((OneToMany) collectionValue.getElement()).getAssociatedClass().getPropertyIterator();
+
+ while (assocClassProps.hasNext()) {
+ Property property = assocClassProps.next();
+
+ if (Tools.iteratorsContentEqual(property.getValue().getColumnIterator(),
+ collectionValue.getKey().getColumnIterator())) {
+ return property.getName();
+ }
+ }
+
+ throw new MappingException("Unable to read the mapped by attribute for " + propertyName + " in "
+ + referencingEntityName + "!");
+ }
+
+ @SuppressWarnings({"unchecked"})
+ private String getMappedBy(Table collectionTable, PersistentClass referencedClass) {
+ Iterator<Property> properties = referencedClass.getPropertyIterator();
+ while (properties.hasNext()) {
+ Property property = properties.next();
+ if (property.getValue() instanceof Collection) {
+ // 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();
+ }
+ }
+ }
+
+ throw new MappingException("Unable to read the mapped by attribute for " + propertyName + " in "
+ + referencingEntityName + "!");
+ }
+}
Added: core/trunk/envers/src/main/java/org/jboss/envers/configuration/metadata/EntityXmlMappingData.java
===================================================================
--- core/trunk/envers/src/main/java/org/jboss/envers/configuration/metadata/EntityXmlMappingData.java (rev 0)
+++ core/trunk/envers/src/main/java/org/jboss/envers/configuration/metadata/EntityXmlMappingData.java 2008-10-27 18:56:31 UTC (rev 15406)
@@ -0,0 +1,58 @@
+/*
+ * JBoss, Home of Professional Open Source
+ *
+ * Copyright 2008, Red Hat Middleware LLC, and others contributors as indicated
+ * by the @authors tag. All rights reserved.
+ *
+ * See the copyright.txt in the distribution for a full listing of individual
+ * contributors. 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, v. 2.1.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT A 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, v.2.1 along with this distribution; if not, write to the Free
+ * Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+ * 02110-1301, USA.
+ *
+ * Red Hat Author(s): Adam Warski
+ */
+package org.jboss.envers.configuration.metadata;
+
+import org.dom4j.Document;
+import org.dom4j.DocumentHelper;
+
+import java.util.List;
+import java.util.ArrayList;
+
+/**
+ * @author Adam Warski (adam at warski dot org)
+ */
+public class EntityXmlMappingData {
+ private Document mainXmlMapping;
+ private List<Document> additionalXmlMappings;
+
+ public EntityXmlMappingData() {
+ mainXmlMapping = DocumentHelper.createDocument();
+ additionalXmlMappings = new ArrayList<Document>();
+ }
+
+ public Document getMainXmlMapping() {
+ return mainXmlMapping;
+ }
+
+ public List<Document> getAdditionalXmlMappings() {
+ return additionalXmlMappings;
+ }
+
+ public Document newAdditionalMapping() {
+ Document additionalMapping = DocumentHelper.createDocument();
+ additionalXmlMappings.add(additionalMapping);
+
+ return additionalMapping;
+ }
+}
Added: core/trunk/envers/src/main/java/org/jboss/envers/configuration/metadata/IdMetadataGenerator.java
===================================================================
--- core/trunk/envers/src/main/java/org/jboss/envers/configuration/metadata/IdMetadataGenerator.java (rev 0)
+++ core/trunk/envers/src/main/java/org/jboss/envers/configuration/metadata/IdMetadataGenerator.java 2008-10-27 18:56:31 UTC (rev 15406)
@@ -0,0 +1,122 @@
+/*
+ * JBoss, Home of Professional Open Source
+ *
+ * Copyright 2008, Red Hat Middleware LLC, and others contributors as indicated
+ * by the @authors tag. All rights reserved.
+ *
+ * See the copyright.txt in the distribution for a full listing of individual
+ * contributors. 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, v. 2.1.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT A 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, v.2.1 along with this distribution; if not, write to the Free
+ * Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+ * 02110-1301, USA.
+ *
+ * Red Hat Author(s): Adam Warski
+ */
+package org.jboss.envers.configuration.metadata;
+
+import org.dom4j.Element;
+import org.dom4j.tree.DefaultElement;
+import org.hibernate.mapping.Property;
+import org.hibernate.mapping.PersistentClass;
+import org.hibernate.mapping.Component;
+import org.hibernate.type.Type;
+import org.hibernate.type.ImmutableType;
+import org.hibernate.MappingException;
+import org.jboss.envers.entities.mapper.SimpleMapperBuilder;
+import org.jboss.envers.entities.mapper.id.SimpleIdMapperBuilder;
+import org.jboss.envers.entities.mapper.id.MultipleIdMapper;
+import org.jboss.envers.entities.mapper.id.EmbeddedIdMapper;
+import org.jboss.envers.entities.mapper.id.SingleIdMapper;
+import org.jboss.envers.entities.IdMappingData;
+import org.jboss.envers.ModificationStore;
+
+import java.util.Iterator;
+
+/**
+ * Generates metadata for primary identifiers (ids) of versions entities.
+ * @author Adam Warski (adam at warski dot org)
+ */
+public final class IdMetadataGenerator {
+ private final VersionsMetadataGenerator mainGenerator;
+
+ IdMetadataGenerator(VersionsMetadataGenerator versionsMetadataGenerator) {
+ mainGenerator = versionsMetadataGenerator;
+ }
+
+ @SuppressWarnings({"unchecked"})
+ private void addIdProperties(Element parent, Iterator<Property> properties, SimpleMapperBuilder mapper, boolean key) {
+ while (properties.hasNext()) {
+ Property property = properties.next();
+ Type propertyType = property.getType();
+ if (!"_identifierMapper".equals(property.getName())) {
+ if (propertyType instanceof ImmutableType) {
+ // Last but one parameter: ids are always insertable
+ mainGenerator.getBasicMetadataGenerator().addBasicNoComponent(parent, property.getName(),
+ property.getValue(), mapper, ModificationStore.FULL, true, key);
+ } else {
+ throw new MappingException("Type not supported: " + propertyType.getClass().getName());
+ }
+ }
+ }
+ }
+
+ @SuppressWarnings({"unchecked"})
+ IdMappingData addId(PersistentClass pc) {
+ // Xml mapping which will be used for relations
+ Element rel_id_mapping = new DefaultElement("properties");
+ // Xml mapping which will be used for the primary key of the versions table
+ Element orig_id_mapping = new DefaultElement("composite-id");
+
+ Property id_prop = pc.getIdentifierProperty();
+ Component id_mapper = pc.getIdentifierMapper();
+
+ SimpleIdMapperBuilder mapper;
+ if (id_mapper != null) {
+ // Multiple id
+
+ mapper = new MultipleIdMapper(((Component) pc.getIdentifier()).getComponentClassName());
+ addIdProperties(rel_id_mapping, (Iterator<Property>) id_mapper.getPropertyIterator(), mapper, false);
+
+ // null mapper - the mapping where already added the first time, now we only want to generate the xml
+ addIdProperties(orig_id_mapping, (Iterator<Property>) id_mapper.getPropertyIterator(), null, true);
+ } else if (id_prop.isComposite()) {
+ // Embedded id
+
+ Component id_component = (Component) id_prop.getValue();
+
+ mapper = new EmbeddedIdMapper(id_prop.getName(), id_component.getComponentClassName());
+ addIdProperties(rel_id_mapping, (Iterator<Property>) id_component.getPropertyIterator(), mapper, false);
+
+ // null mapper - the mapping where already added the first time, now we only want to generate the xml
+ addIdProperties(orig_id_mapping, (Iterator<Property>) id_component.getPropertyIterator(), null, true);
+ } else {
+ // Single id
+
+ mapper = new SingleIdMapper();
+
+ // Last but one parameter: ids are always insertable
+ mainGenerator.getBasicMetadataGenerator().addBasicNoComponent(rel_id_mapping, id_prop.getName(),
+ id_prop.getValue(), mapper, ModificationStore.FULL, true, false);
+
+ // null mapper - the mapping where already added the first time, now we only want to generate the xml
+ mainGenerator.getBasicMetadataGenerator().addBasicNoComponent(orig_id_mapping, id_prop.getName(),
+ id_prop.getValue(), null, ModificationStore.FULL, true, true);
+ }
+
+ orig_id_mapping.addAttribute("name", mainGenerator.getVerEntCfg().getOriginalIdPropName());
+
+ // Adding a relation to the revision entity (effectively: the "revision number" property)
+ mainGenerator.addRevisionInfoRelation(orig_id_mapping);
+
+ return new IdMappingData(mapper, orig_id_mapping, rel_id_mapping);
+ }
+}
Added: core/trunk/envers/src/main/java/org/jboss/envers/configuration/metadata/InheritanceType.java
===================================================================
--- core/trunk/envers/src/main/java/org/jboss/envers/configuration/metadata/InheritanceType.java (rev 0)
+++ core/trunk/envers/src/main/java/org/jboss/envers/configuration/metadata/InheritanceType.java 2008-10-27 18:56:31 UTC (rev 15406)
@@ -0,0 +1,60 @@
+/*
+ * Envers. http://www.jboss.org/envers
+ *
+ * Copyright 2008 Red Hat Middleware, LLC. All rights reserved.
+ *
+ * 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, v. 2.1.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT A 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, v.2.1 along with this distribution; if not, write to the Free
+ * Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+ * 02110-1301, USA.
+ *
+ * Red Hat Author(s): Adam Warski
+ */
+package org.jboss.envers.configuration.metadata;
+
+import org.hibernate.mapping.*;
+import org.hibernate.MappingException;
+
+/**
+ * @author Adam Warski (adam at warski dot org)
+ */
+public enum InheritanceType {
+ NONE,
+ JOINED,
+ SINGLE,
+ TABLE_PER_CLASS;
+
+ /**
+ * @param pc 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 persisten class.
+ */
+ public static InheritanceType get(PersistentClass pc) {
+ PersistentClass superclass = pc.getSuperclass();
+ if (superclass == null) {
+ return InheritanceType.NONE;
+ }
+
+ // We assume that every subclass is of the same type.
+ Subclass subclass = (Subclass) superclass.getSubclassIterator().next();
+
+ if (subclass instanceof SingleTableSubclass) {
+ return InheritanceType.SINGLE;
+ } else if (subclass instanceof JoinedSubclass) {
+ return InheritanceType.JOINED;
+ } else if (subclass instanceof UnionSubclass) {
+ return InheritanceType.TABLE_PER_CLASS;
+ }
+
+ throw new MappingException("Unknown subclass class: " + subclass.getClass());
+ }
+}
Added: core/trunk/envers/src/main/java/org/jboss/envers/configuration/metadata/MetadataTools.java
===================================================================
--- core/trunk/envers/src/main/java/org/jboss/envers/configuration/metadata/MetadataTools.java (rev 0)
+++ core/trunk/envers/src/main/java/org/jboss/envers/configuration/metadata/MetadataTools.java 2008-10-27 18:56:31 UTC (rev 15406)
@@ -0,0 +1,207 @@
+/*
+ * Envers. http://www.jboss.org/envers
+ *
+ * Copyright 2008 Red Hat Middleware, LLC. All rights reserved.
+ *
+ * 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, v. 2.1.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT A 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, v.2.1 along with this distribution; if not, write to the Free
+ * Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+ * 02110-1301, USA.
+ *
+ * Red Hat Author(s): Adam Warski
+ */
+package org.jboss.envers.configuration.metadata;
+
+import org.dom4j.Element;
+import org.dom4j.Document;
+import org.dom4j.Attribute;
+import org.jboss.envers.tools.StringTools;
+import org.hibernate.mapping.Column;
+
+import javax.persistence.JoinColumn;
+import java.util.Iterator;
+
+/**
+ * @author Adam Warski (adam at warski dot org)
+ */
+public class MetadataTools {
+ public static Element addNativelyGeneratedId(Element parent, String name, String type) {
+ Element id_mapping = parent.addElement("id");
+ id_mapping.addAttribute("name", name).addAttribute("type", type);
+
+ Element generator_mapping = id_mapping.addElement("generator");
+ generator_mapping.addAttribute("class", "native");
+ /*generator_mapping.addAttribute("class", "sequence");
+ generator_mapping.addElement("param").addAttribute("name", "sequence").setText("custom");*/
+
+ return id_mapping;
+ }
+
+ public static Element addProperty(Element parent, String name, String type, boolean insertable, boolean key) {
+ Element prop_mapping;
+ if (key) {
+ prop_mapping = parent.addElement("key-property");
+ } else {
+ prop_mapping = parent.addElement("property");
+ }
+
+ prop_mapping.addAttribute("name", name);
+ prop_mapping.addAttribute("insert", Boolean.toString(insertable));
+
+ if (type != null) {
+ prop_mapping.addAttribute("type", type);
+ }
+
+ return prop_mapping;
+ }
+
+ public static Element addColumn(Element parent, String name, Integer length) {
+ Element column_mapping = parent.addElement("column");
+
+ column_mapping.addAttribute("name", name);
+ if (length != null) {
+ column_mapping.addAttribute("length", length.toString());
+ }
+
+ return column_mapping;
+ }
+
+ private static Element createEntityCommon(Document document, String type, String entityName,
+ String tableName, String schema, String catalog,
+ String discriminatorValue) {
+ Element hibernate_mapping = document.addElement("hibernate-mapping");
+ hibernate_mapping.addAttribute("auto-import", "false");
+
+ Element class_mapping = hibernate_mapping.addElement(type);
+
+ if (entityName != null) {
+ class_mapping.addAttribute("entity-name", entityName);
+ }
+
+ if (discriminatorValue != null) {
+ class_mapping.addAttribute("discriminator-value", discriminatorValue);
+ }
+
+ if (!StringTools.isEmpty(tableName)) {
+ class_mapping.addAttribute("table", tableName);
+ }
+
+ if (!StringTools.isEmpty(schema)) {
+ class_mapping.addAttribute("schema", schema);
+ }
+
+ if (!StringTools.isEmpty(catalog)) {
+ class_mapping.addAttribute("catalog", catalog);
+ }
+
+ return class_mapping;
+ }
+
+ public static Element createEntity(Document document, String entityName, String tableName,
+ String schema, String catalog, String discriminatorValue) {
+ return createEntityCommon(document, "class", entityName, tableName, schema, catalog, discriminatorValue);
+ }
+
+ public static Element createSubclassEntity(Document document, String entityName, String tableName,
+ String schema, String catalog, String extendsEntityName,
+ String discriminatorValue) {
+ Element class_mapping = createEntityCommon(document, "subclass", entityName, tableName, schema, catalog,
+ discriminatorValue);
+
+ class_mapping.addAttribute("extends", extendsEntityName);
+
+ return class_mapping;
+ }
+
+ public static Element createJoin(Element parent, String tableName,
+ String schema, String catalog) {
+ Element join_mapping = parent.addElement("join");
+
+ join_mapping.addAttribute("table", tableName);
+
+ if (!StringTools.isEmpty(schema)) {
+ join_mapping.addAttribute("schema", schema);
+ }
+
+ if (!StringTools.isEmpty(catalog)) {
+ join_mapping.addAttribute("catalog", catalog);
+ }
+
+ return join_mapping;
+ }
+
+ public static void addColumns(Element any_mapping, Iterator<Column> columns) {
+ while (columns.hasNext()) {
+ Column column = columns.next();
+ addColumn(any_mapping, column.getName(), column.getLength());
+ }
+ }
+
+ @SuppressWarnings({"unchecked"})
+ private static void changeNamesInColumnElement(Element element, ColumnNameIterator columnNameIterator) {
+ Iterator<Element> properties = element.elementIterator();
+ while (properties.hasNext()) {
+ Element property = properties.next();
+
+ if ("column".equals(property.getName())) {
+ Attribute nameAttr = property.attribute("name");
+ if (nameAttr != null) {
+ nameAttr.setText(columnNameIterator.next());
+ }
+ }
+ }
+ }
+
+ @SuppressWarnings({"unchecked"})
+ public static void prefixNamesInPropertyElement(Element element, String prefix, ColumnNameIterator columnNameIterator,
+ boolean changeToKey) {
+ Iterator<Element> properties = element.elementIterator();
+ while (properties.hasNext()) {
+ Element property = properties.next();
+
+ if ("property".equals(property.getName())) {
+ Attribute nameAttr = property.attribute("name");
+ if (nameAttr != null) {
+ nameAttr.setText(prefix + nameAttr.getText());
+ }
+
+ changeNamesInColumnElement(property, columnNameIterator);
+
+ if (changeToKey) {
+ property.setName("key-property");
+ }
+ }
+ }
+ }
+
+ /**
+ * An iterator over column names.
+ */
+ public static abstract class ColumnNameIterator implements Iterator<String> { }
+
+ public static ColumnNameIterator getColumnNameIterator(final Iterator<Column> columnIterator) {
+ return new ColumnNameIterator() {
+ public boolean hasNext() { return columnIterator.hasNext(); }
+ public String next() { return columnIterator.next().getName(); }
+ public void remove() { columnIterator.remove(); }
+ };
+ }
+
+ public static ColumnNameIterator getColumnNameIterator(final JoinColumn[] joinColumns) {
+ return new ColumnNameIterator() {
+ int counter = 0;
+ public boolean hasNext() { return counter < joinColumns.length; }
+ public String next() { return joinColumns[counter++].name(); }
+ public void remove() { throw new UnsupportedOperationException(); }
+ };
+ }
+}
Added: core/trunk/envers/src/main/java/org/jboss/envers/configuration/metadata/PersistentClassVersioningData.java
===================================================================
--- core/trunk/envers/src/main/java/org/jboss/envers/configuration/metadata/PersistentClassVersioningData.java (rev 0)
+++ core/trunk/envers/src/main/java/org/jboss/envers/configuration/metadata/PersistentClassVersioningData.java 2008-10-27 18:56:31 UTC (rev 15406)
@@ -0,0 +1,65 @@
+/*
+ * Envers. http://www.jboss.org/envers
+ *
+ * Copyright 2008 Red Hat Middleware, LLC. All rights reserved.
+ *
+ * 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, v. 2.1.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT A 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, v.2.1 along with this distribution; if not, write to the Free
+ * Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+ * 02110-1301, USA.
+ *
+ * Red Hat Author(s): Adam Warski
+ */
+package org.jboss.envers.configuration.metadata;
+
+import org.jboss.envers.ModificationStore;
+import org.jboss.envers.VersionsJoinTable;
+import org.jboss.envers.VersionsTable;
+
+import java.util.HashMap;
+import java.util.Map;
+import java.util.List;
+import java.util.ArrayList;
+
+/**
+ * @author Adam Warski (adam at warski dot org)
+ * @author Sebastian Komander
+*/
+public class PersistentClassVersioningData {
+ public PersistentClassVersioningData() {
+ propertyStoreInfo = new PropertyStoreInfo(new HashMap<String, ModificationStore>());
+ secondaryTableDictionary = new HashMap<String, String>();
+ unversionedProperties = new ArrayList<String>();
+ versionsJoinTables = new HashMap<String, VersionsJoinTable>();
+ mapKeys = new HashMap<String, String>();
+ }
+
+ public PropertyStoreInfo propertyStoreInfo;
+ public VersionsTable versionsTable;
+ public Map<String, String> secondaryTableDictionary;
+ public List<String> unversionedProperties;
+ /**
+ * A map from property names to custom join tables definitions.
+ */
+ public Map<String, VersionsJoinTable> versionsJoinTables;
+ /**
+ * A map from property names to the value of the related property names in a map key annotation. An empty string,
+ * if the property name is not specified in the mapkey annotation.
+ */
+ public Map<String, String> mapKeys;
+
+ public boolean isVersioned() {
+ if (propertyStoreInfo.propertyStores.size() > 0) { return true; }
+ if (propertyStoreInfo.defaultStore != null) { return true; }
+ return false;
+ }
+}
Added: core/trunk/envers/src/main/java/org/jboss/envers/configuration/metadata/PropertyStoreInfo.java
===================================================================
--- core/trunk/envers/src/main/java/org/jboss/envers/configuration/metadata/PropertyStoreInfo.java (rev 0)
+++ core/trunk/envers/src/main/java/org/jboss/envers/configuration/metadata/PropertyStoreInfo.java 2008-10-27 18:56:31 UTC (rev 15406)
@@ -0,0 +1,46 @@
+/*
+ * Envers. http://www.jboss.org/envers
+ *
+ * Copyright 2008 Red Hat Middleware, LLC. All rights reserved.
+ *
+ * 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, v. 2.1.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT A 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, v.2.1 along with this distribution; if not, write to the Free
+ * Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+ * 02110-1301, USA.
+ *
+ * Red Hat Author(s): Adam Warski
+ */
+package org.jboss.envers.configuration.metadata;
+
+import org.jboss.envers.ModificationStore;
+
+import java.util.Map;
+
+/**
+ * @author Adam Warski (adam at warski dot org)
+*/
+public class PropertyStoreInfo {
+ // Not null if the whole class is versioned
+ public ModificationStore defaultStore;
+
+ // Maps property names to their stores defined in per-field versioned annotations
+ public Map<String, ModificationStore> propertyStores;
+
+ public PropertyStoreInfo(Map<String, ModificationStore> propertyStores) {
+ this.propertyStores = propertyStores;
+ }
+
+ public PropertyStoreInfo(ModificationStore defaultStore, Map<String, ModificationStore> propertyStores) {
+ this.defaultStore = defaultStore;
+ this.propertyStores = propertyStores;
+ }
+}
Added: core/trunk/envers/src/main/java/org/jboss/envers/configuration/metadata/QueryGeneratorBuilder.java
===================================================================
--- core/trunk/envers/src/main/java/org/jboss/envers/configuration/metadata/QueryGeneratorBuilder.java (rev 0)
+++ core/trunk/envers/src/main/java/org/jboss/envers/configuration/metadata/QueryGeneratorBuilder.java 2008-10-27 18:56:31 UTC (rev 15406)
@@ -0,0 +1,86 @@
+/*
+ * JBoss, Home of Professional Open Source
+ *
+ * Copyright 2008, Red Hat Middleware LLC, and others contributors as indicated
+ * by the @authors tag. All rights reserved.
+ *
+ * See the copyright.txt in the distribution for a full listing of individual
+ * contributors. 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, v. 2.1.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT A 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, v.2.1 along with this distribution; if not, write to the Free
+ * Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+ * 02110-1301, USA.
+ *
+ * Red Hat Author(s): Adam Warski
+ */
+package org.jboss.envers.configuration.metadata;
+
+import org.jboss.envers.entities.mapper.relation.MiddleIdData;
+import org.jboss.envers.entities.mapper.relation.MiddleComponentData;
+import org.jboss.envers.entities.mapper.relation.query.RelationQueryGenerator;
+import org.jboss.envers.entities.mapper.relation.query.OneEntityQueryGenerator;
+import org.jboss.envers.entities.mapper.relation.query.ThreeEntityQueryGenerator;
+import org.jboss.envers.entities.mapper.relation.query.TwoEntityQueryGenerator;
+import org.jboss.envers.configuration.VersionsEntitiesConfiguration;
+import org.jboss.envers.configuration.GlobalConfiguration;
+
+import java.util.List;
+import java.util.ArrayList;
+
+/**
+ * Builds query generators, for reading collection middle tables, along with any related entities.
+ * The related entities information can be added gradually, and when complete, the query generator can be built.
+ * @author Adam Warski (adam at warski dot org)
+ */
+public final class QueryGeneratorBuilder {
+ private final GlobalConfiguration globalCfg;
+ private final VersionsEntitiesConfiguration verEntCfg;
+ private final MiddleIdData referencingIdData;
+ private final String versionsMiddleEntityName;
+ private final List<MiddleIdData> idDatas;
+
+ QueryGeneratorBuilder(GlobalConfiguration globalCfg, VersionsEntitiesConfiguration verEntCfg,
+ MiddleIdData referencingIdData, String versionsMiddleEntityName) {
+ this.globalCfg = globalCfg;
+ this.verEntCfg = verEntCfg;
+ this.referencingIdData = referencingIdData;
+ this.versionsMiddleEntityName = versionsMiddleEntityName;
+
+ idDatas = new ArrayList<MiddleIdData>();
+ }
+
+ void addRelation(MiddleIdData idData) {
+ idDatas.add(idData);
+ }
+
+ RelationQueryGenerator build(MiddleComponentData... componentDatas) {
+ if (idDatas.size() == 0) {
+ return new OneEntityQueryGenerator(verEntCfg, versionsMiddleEntityName, referencingIdData,
+ componentDatas);
+ } else if (idDatas.size() == 1) {
+ return new TwoEntityQueryGenerator(globalCfg, verEntCfg, versionsMiddleEntityName, referencingIdData,
+ idDatas.get(0), componentDatas);
+ } else if (idDatas.size() == 2) {
+ return new ThreeEntityQueryGenerator(globalCfg, verEntCfg, versionsMiddleEntityName, referencingIdData,
+ idDatas.get(0), idDatas.get(1), componentDatas);
+ } else {
+ throw new IllegalStateException("Illegal number of related entities.");
+ }
+ }
+
+ /**
+ * @return Current index of data in the array, which will be the element of a list, returned when executing a query
+ * generated by the built query generator.
+ */
+ int getCurrentIndex() {
+ return idDatas.size();
+ }
+}
Added: core/trunk/envers/src/main/java/org/jboss/envers/configuration/metadata/ToOneRelationMetadataGenerator.java
===================================================================
--- core/trunk/envers/src/main/java/org/jboss/envers/configuration/metadata/ToOneRelationMetadataGenerator.java (rev 0)
+++ core/trunk/envers/src/main/java/org/jboss/envers/configuration/metadata/ToOneRelationMetadataGenerator.java 2008-10-27 18:56:31 UTC (rev 15406)
@@ -0,0 +1,111 @@
+/*
+ * JBoss, Home of Professional Open Source
+ *
+ * Copyright 2008, Red Hat Middleware LLC, and others contributors as indicated
+ * by the @authors tag. All rights reserved.
+ *
+ * See the copyright.txt in the distribution for a full listing of individual
+ * contributors. 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, v. 2.1.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT A 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, v.2.1 along with this distribution; if not, write to the Free
+ * Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+ * 02110-1301, USA.
+ *
+ * Red Hat Author(s): Adam Warski
+ */
+package org.jboss.envers.configuration.metadata;
+
+import org.dom4j.Element;
+import org.hibernate.mapping.Value;
+import org.hibernate.mapping.ToOne;
+import org.hibernate.mapping.OneToOne;
+import org.hibernate.MappingException;
+import org.jboss.envers.entities.mapper.CompositeMapperBuilder;
+import org.jboss.envers.entities.mapper.relation.ToOneIdMapper;
+import org.jboss.envers.entities.mapper.relation.OneToOneNotOwningMapper;
+import org.jboss.envers.entities.mapper.id.IdMapper;
+import org.jboss.envers.entities.EntityConfiguration;
+import org.jboss.envers.entities.IdMappingData;
+
+/**
+ * Generates metadata for to-one relations (reference-valued properties).
+ * @author Adam Warski (adam at warski dot org)
+ */
+public final class ToOneRelationMetadataGenerator {
+ private final VersionsMetadataGenerator mainGenerator;
+
+ ToOneRelationMetadataGenerator(VersionsMetadataGenerator versionsMetadataGenerator) {
+ mainGenerator = versionsMetadataGenerator;
+ }
+
+ @SuppressWarnings({"unchecked"})
+ void addToOne(Element parent, String name, Value value, CompositeMapperBuilder mapper, String entityName) {
+ String referencedEntityName = ((ToOne) value).getReferencedEntityName();
+
+ EntityConfiguration configuration = mainGenerator.getEntitiesConfigurations().get(referencedEntityName);
+ if (configuration == null) {
+ throw new MappingException("A versioned relation to a non-versioned entity " + referencedEntityName + "!");
+ }
+
+ IdMappingData idMapping = configuration.getIdMappingData();
+
+ String lastPropertyPrefix = name + "_";
+
+ // Generating the id mapper for the relation
+ IdMapper relMapper = idMapping.getIdMapper().prefixMappedProperties(lastPropertyPrefix);
+
+ // Storing information about this relation
+ mainGenerator.getEntitiesConfigurations().get(entityName).addToOneRelation(name, referencedEntityName, relMapper);
+
+ // Adding an element to the mapping corresponding to the references entity id's
+ Element properties = (Element) idMapping.getXmlRelationMapping().clone();
+ properties.addAttribute("name", name);
+
+ MetadataTools.prefixNamesInPropertyElement(properties, lastPropertyPrefix,
+ MetadataTools.getColumnNameIterator(value.getColumnIterator()), false);
+ parent.add(properties);
+
+ // Adding mapper for the id
+ mapper.addComposite(name, new ToOneIdMapper(relMapper, name, referencedEntityName));
+ }
+
+ @SuppressWarnings({"unchecked"})
+ void addOneToOneNotOwning(String name, Value value, CompositeMapperBuilder mapper, String entityName) {
+ OneToOne propertyValue = (OneToOne) value;
+
+ String owningReferencePropertyName = propertyValue.getReferencedPropertyName(); // mappedBy
+
+ EntityConfiguration configuration = mainGenerator.getEntitiesConfigurations().get(entityName);
+ if (configuration == null) {
+ throw new MappingException("A versioned relation to a non-versioned entity " + entityName + "!");
+ }
+
+ IdMappingData ownedIdMapping = configuration.getIdMappingData();
+
+ if (ownedIdMapping == null) {
+ throw new MappingException("A versioned relation to a non-versioned entity " + entityName + "!");
+ }
+
+ String lastPropertyPrefix = owningReferencePropertyName + "_";
+ String referencedEntityName = propertyValue.getReferencedEntityName();
+
+ // Generating the id mapper for the relation
+ IdMapper ownedIdMapper = ownedIdMapping.getIdMapper().prefixMappedProperties(lastPropertyPrefix);
+
+ // Storing information about this relation
+ mainGenerator.getEntitiesConfigurations().get(entityName).addToOneNotOwningRelation(name, owningReferencePropertyName,
+ referencedEntityName, ownedIdMapper);
+
+ // Adding mapper for the id
+ mapper.addComposite(name, new OneToOneNotOwningMapper(owningReferencePropertyName,
+ referencedEntityName, name));
+ }
+}
Added: core/trunk/envers/src/main/java/org/jboss/envers/configuration/metadata/VersionsMetadataGenerator.java
===================================================================
--- core/trunk/envers/src/main/java/org/jboss/envers/configuration/metadata/VersionsMetadataGenerator.java (rev 0)
+++ core/trunk/envers/src/main/java/org/jboss/envers/configuration/metadata/VersionsMetadataGenerator.java 2008-10-27 18:56:31 UTC (rev 15406)
@@ -0,0 +1,372 @@
+/*
+ * Envers. http://www.jboss.org/envers
+ *
+ * Copyright 2008 Red Hat Middleware, LLC. All rights reserved.
+ *
+ * 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, v. 2.1.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT A 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, v.2.1 along with this distribution; if not, write to the Free
+ * Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+ * 02110-1301, USA.
+ *
+ * Red Hat Author(s): Adam Warski
+ */
+package org.jboss.envers.configuration.metadata;
+
+import org.hibernate.type.*;
+import org.hibernate.MappingException;
+import org.hibernate.cfg.Configuration;
+import org.hibernate.mapping.*;
+import org.hibernate.mapping.Collection;
+import org.dom4j.Element;
+import org.jboss.envers.entities.EntityConfiguration;
+import org.jboss.envers.entities.IdMappingData;
+import org.jboss.envers.configuration.GlobalConfiguration;
+import org.jboss.envers.configuration.VersionsEntitiesConfiguration;
+import org.jboss.envers.entities.mapper.*;
+import org.jboss.envers.tools.StringTools;
+import org.jboss.envers.ModificationStore;
+import org.jboss.envers.VersionsJoinTable;
+import org.jboss.envers.entity.VersionsInheritanceEntityPersister;
+import org.jboss.envers.tools.log.YLog;
+import org.jboss.envers.tools.log.YLogManager;
+
+import java.util.*;
+import java.util.List;
+import java.util.Map;
+
+/**
+ * @author Adam Warski (adam at warski dot org)
+ * @author Sebastian Komander
+ */
+public final class VersionsMetadataGenerator {
+ private final Configuration cfg;
+ private final GlobalConfiguration globalCfg;
+ private final VersionsEntitiesConfiguration verEntCfg;
+ private final Element revisionInfoRelationMapping;
+
+ private final BasicMetadataGenerator basicMetadataGenerator;
+ private final IdMetadataGenerator idMetadataGenerator;
+ private final ToOneRelationMetadataGenerator toOneRelationMetadataGenerator;
+
+ private final Map<String, EntityConfiguration> entitiesConfigurations;
+
+ // Map entity name -> (join descriptor -> element describing the "versioned" join)
+ private final Map<String, Map<Join, Element>> entitiesJoins;
+
+ private YLog log = YLogManager.getLogManager().getLog(VersionsMetadataGenerator.class);
+
+ public VersionsMetadataGenerator(Configuration cfg, GlobalConfiguration globalCfg,
+ VersionsEntitiesConfiguration verEntCfg,
+ Element revisionInfoRelationMapping) {
+ this.cfg = cfg;
+ this.globalCfg = globalCfg;
+ this.verEntCfg = verEntCfg;
+ this.revisionInfoRelationMapping = revisionInfoRelationMapping;
+
+ this.basicMetadataGenerator = new BasicMetadataGenerator();
+ this.idMetadataGenerator = new IdMetadataGenerator(this);
+ this.toOneRelationMetadataGenerator = new ToOneRelationMetadataGenerator(this);
+
+ entitiesConfigurations = new HashMap<String, EntityConfiguration>();
+ entitiesJoins = new HashMap<String, Map<Join, Element>>();
+ }
+
+ void addRevisionInfoRelation(Element any_mapping) {
+ Element rev_mapping = (Element) revisionInfoRelationMapping.clone();
+ rev_mapping.addAttribute("name", verEntCfg.getRevisionPropName());
+ MetadataTools.addColumn(rev_mapping, verEntCfg.getRevisionPropName(), null);
+
+ any_mapping.add(rev_mapping);
+ }
+
+ void addRevisionType(Element any_mapping) {
+ Element revTypeProperty = MetadataTools.addProperty(any_mapping, verEntCfg.getRevisionTypePropName(),
+ verEntCfg.getRevisionTypePropType(), true, false);
+ revTypeProperty.addAttribute("type", "org.jboss.envers.entities.RevisionTypeType");
+ }
+
+ private ModificationStore getStoreForProperty(Property property, PropertyStoreInfo propertyStoreInfo,
+ List<String> unversionedProperties) {
+ /*
+ * Checks if a property is versioned, which is when:
+ * - the property isn't unversioned
+ * - the whole entity is versioned, then the default store is not null
+ * - there is a store defined for this entity, which is when this property is annotated
+ */
+
+ if (unversionedProperties.contains(property.getName())) {
+ return null;
+ }
+
+ ModificationStore store = propertyStoreInfo.propertyStores.get(property.getName());
+
+ if (store == null) {
+ return propertyStoreInfo.defaultStore;
+ }
+
+ return store;
+ }
+
+ @SuppressWarnings({"unchecked"})
+ void addValue(Element parent, String name, Value value, CompositeMapperBuilder currentMapper,
+ ModificationStore store, String entityName, EntityXmlMappingData xmlMappingData,
+ VersionsJoinTable joinTable, String mapKey, boolean insertable, boolean firstPass) {
+ Type type = value.getType();
+
+ // only first pass
+ if (firstPass) {
+ if (basicMetadataGenerator.addBasic(parent, name, value, currentMapper, store, entityName, insertable,
+ false)) {
+ // The property was mapped by the basic generator.
+ return;
+ }
+ }
+
+ if (type instanceof ManyToOneType) {
+ // only second pass
+ if (!firstPass) {
+ toOneRelationMetadataGenerator.addToOne(parent, name, value, currentMapper, entityName);
+ }
+ } else if (type instanceof OneToOneType) {
+ // only second pass
+ if (!firstPass) {
+ toOneRelationMetadataGenerator.addOneToOneNotOwning(name, value, currentMapper, entityName);
+ }
+ } else if (type instanceof CollectionType) {
+ // only second pass
+ if (!firstPass) {
+ CollectionMetadataGenerator collectionMetadataGenerator = new CollectionMetadataGenerator(this,
+ name, (Collection) value, currentMapper, entityName, xmlMappingData, joinTable, mapKey);
+ collectionMetadataGenerator.addCollection();
+ }
+ } else {
+ if (firstPass) {
+ // If we got here in the first pass, it means the basic mapper didn't map it, and none of the
+ // above branches either.
+ throwUnsupportedTypeException(type, entityName, name);
+ }
+ }
+ }
+
+ @SuppressWarnings({"unchecked"})
+ private void addProperties(Element parent, Iterator<Property> properties, CompositeMapperBuilder currentMapper,
+ PersistentClassVersioningData versioningData, String entityName, EntityXmlMappingData xmlMappingData,
+ boolean firstPass) {
+ while (properties.hasNext()) {
+ Property property = properties.next();
+ if (!"_identifierMapper".equals(property.getName())) {
+ ModificationStore store = getStoreForProperty(property, versioningData.propertyStoreInfo,
+ versioningData.unversionedProperties);
+
+ if (store != null) {
+ addValue(parent, property.getName(), property.getValue(), currentMapper, store, entityName,
+ xmlMappingData, versioningData.versionsJoinTables.get(property.getName()),
+ versioningData.mapKeys.get(property.getName()), property.isInsertable(), firstPass);
+ }
+ }
+ }
+ }
+
+ @SuppressWarnings({"unchecked"})
+ private void createJoins(PersistentClass pc, Element parent, PersistentClassVersioningData versioningData) {
+ Iterator<Join> joins = pc.getJoinIterator();
+
+ Map<Join, Element> joinElements = new HashMap<Join, Element>();
+ entitiesJoins.put(pc.getEntityName(), joinElements);
+
+ while (joins.hasNext()) {
+ Join join = joins.next();
+
+ // 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).
+ String originalTableName = join.getTable().getName();
+ String versionedTableName = versioningData.secondaryTableDictionary.get(originalTableName);
+ if (versionedTableName == null) {
+ versionedTableName = verEntCfg.getVersionsEntityName(originalTableName);
+ }
+
+ String schema = versioningData.versionsTable.schema();
+ if (StringTools.isEmpty(schema)) {
+ schema = join.getTable().getSchema();
+ }
+
+ String catalog = versioningData.versionsTable.catalog();
+ if (StringTools.isEmpty(catalog)) {
+ catalog = join.getTable().getCatalog();
+ }
+
+ Element joinElement = MetadataTools.createJoin(parent, versionedTableName, schema, catalog);
+ joinElements.put(join, joinElement);
+
+ Element joinKey = joinElement.addElement("key");
+ MetadataTools.addColumns(joinKey, join.getKey().getColumnIterator());
+ MetadataTools.addColumn(joinKey, verEntCfg.getRevisionPropName(), null);
+ }
+ }
+
+ @SuppressWarnings({"unchecked"})
+ private void addJoins(PersistentClass pc, CompositeMapperBuilder currentMapper, PersistentClassVersioningData versioningData,
+ String entityName, EntityXmlMappingData xmlMappingData,boolean firstPass) {
+ Iterator<Join> joins = pc.getJoinIterator();
+
+ while (joins.hasNext()) {
+ Join join = joins.next();
+ Element joinElement = entitiesJoins.get(entityName).get(join);
+
+ addProperties(joinElement, join.getPropertyIterator(), currentMapper, versioningData, entityName,
+ xmlMappingData, firstPass);
+ }
+ }
+
+ private void addPersisterHack(Element class_mapping) {
+ class_mapping.addAttribute("persister", VersionsInheritanceEntityPersister.class.getName() );
+ }
+
+ @SuppressWarnings({"unchecked"})
+ public void generateFirstPass(PersistentClass pc, PersistentClassVersioningData versioningData,
+ EntityXmlMappingData xmlMappingData) {
+ String schema = versioningData.versionsTable.schema();
+ if (StringTools.isEmpty(schema)) {
+ schema = pc.getTable().getSchema();
+ }
+
+ String catalog = versioningData.versionsTable.catalog();
+ if (StringTools.isEmpty(catalog)) {
+ catalog = pc.getTable().getCatalog();
+ }
+
+ String entityName = pc.getEntityName();
+ String versionsEntityName = verEntCfg.getVersionsEntityName(entityName);
+ String versionsTableName = verEntCfg.getVersionsTableName(entityName, pc.getTable().getName());
+
+ // Generating a mapping for the id
+ IdMappingData idMapper = idMetadataGenerator.addId(pc);
+
+ Element class_mapping;
+ ExtendedPropertyMapper propertyMapper;
+
+ InheritanceType inheritanceType = InheritanceType.get(pc);
+ String parentEntityName = null;
+
+ switch (inheritanceType) {
+ case NONE:
+ class_mapping = MetadataTools.createEntity(xmlMappingData.getMainXmlMapping(), versionsEntityName, versionsTableName,
+ schema, catalog, pc.getDiscriminatorValue());
+ propertyMapper = new MultiPropertyMapper();
+
+ // Checking if there is a discriminator column
+ if (pc.getDiscriminator() != null) {
+ Element discriminator_element = class_mapping.addElement("discriminator");
+ MetadataTools.addColumns(discriminator_element, pc.getDiscriminator().getColumnIterator());
+ discriminator_element.addAttribute("type", pc.getDiscriminator().getType().getName());
+
+ // If so, there is some inheritance scheme -> using the persister hack.
+ addPersisterHack(class_mapping);
+ }
+
+ // Adding the id mapping
+ class_mapping.add((Element) idMapper.getXmlMapping().clone());
+
+ // Adding the "revision type" property
+ addRevisionType(class_mapping);
+
+ break;
+ case SINGLE:
+ String extendsEntityName = verEntCfg.getVersionsEntityName(pc.getSuperclass().getEntityName());
+ class_mapping = MetadataTools.createSubclassEntity(xmlMappingData.getMainXmlMapping(), versionsEntityName,
+ versionsTableName, schema, catalog, extendsEntityName, pc.getDiscriminatorValue());
+
+ addPersisterHack(class_mapping);
+
+ // 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
+ parentEntityName = pc.getSuperclass().getEntityName();
+ ExtendedPropertyMapper parentPropertyMapper = entitiesConfigurations.get(parentEntityName).getPropertyMapper();
+ propertyMapper = new SubclassPropertyMapper(new MultiPropertyMapper(), parentPropertyMapper);
+
+ break;
+ case JOINED:
+ throw new MappingException("Joined inheritance strategy not supported for versioning!");
+ case TABLE_PER_CLASS:
+ throw new MappingException("Table-per-class inheritance strategy not supported for versioning!");
+ default:
+ throw new AssertionError("Impossible enum value.");
+ }
+
+ // Mapping unjoined properties
+ addProperties(class_mapping, (Iterator<Property>) pc.getUnjoinedPropertyIterator(), propertyMapper,
+ versioningData, pc.getEntityName(), xmlMappingData,
+ true);
+
+ // Creating and mapping joins (first pass)
+ createJoins(pc, class_mapping, versioningData);
+ addJoins(pc, propertyMapper, versioningData, pc.getEntityName(), xmlMappingData, true);
+
+ // Storing the generated configuration
+ EntityConfiguration entityCfg = new EntityConfiguration(versionsEntityName, idMapper,
+ propertyMapper, parentEntityName);
+ entitiesConfigurations.put(pc.getEntityName(), entityCfg);
+ }
+
+ @SuppressWarnings({"unchecked"})
+ public void generateSecondPass(PersistentClass pc, PersistentClassVersioningData versioningData,
+ EntityXmlMappingData xmlMappingData) {
+ String entityName = pc.getEntityName();
+
+ CompositeMapperBuilder propertyMapper = entitiesConfigurations.get(entityName).getPropertyMapper();
+
+ // Mapping unjoined properties
+ Element parent = xmlMappingData.getMainXmlMapping().getRootElement().element("class");
+ if (parent == null) {
+ parent = xmlMappingData.getMainXmlMapping().getRootElement().element("subclass");
+ }
+
+ addProperties(parent, (Iterator<Property>) pc.getUnjoinedPropertyIterator(),
+ propertyMapper, versioningData, entityName, xmlMappingData, false);
+
+ // Mapping joins (second pass)
+ addJoins(pc, propertyMapper, versioningData, entityName, xmlMappingData, false);
+ }
+
+ public Map<String, EntityConfiguration> getEntitiesConfigurations() {
+ return entitiesConfigurations;
+ }
+
+ // Getters for generators and configuration
+
+ BasicMetadataGenerator getBasicMetadataGenerator() {
+ return basicMetadataGenerator;
+ }
+
+ Configuration getCfg() {
+ return cfg;
+ }
+
+ GlobalConfiguration getGlobalCfg() {
+ return globalCfg;
+ }
+
+ VersionsEntitiesConfiguration getVerEntCfg() {
+ return verEntCfg;
+ }
+
+ void throwUnsupportedTypeException(Type type, String entityName, String propertyName) {
+ String message = "Type not supported for versioning: " + type.getClass().getName() +
+ ", on entity " + entityName + ", property '" + propertyName + "'.";
+ if (globalCfg.isWarnOnUnsupportedTypes()) {
+ log.warn(message);
+ } else {
+ throw new MappingException(message);
+ }
+ }
+}
Added: core/trunk/envers/src/main/java/org/jboss/envers/entities/EntitiesConfigurations.java
===================================================================
--- core/trunk/envers/src/main/java/org/jboss/envers/entities/EntitiesConfigurations.java (rev 0)
+++ core/trunk/envers/src/main/java/org/jboss/envers/entities/EntitiesConfigurations.java 2008-10-27 18:56:31 UTC (rev 15406)
@@ -0,0 +1,99 @@
+/*
+ * Envers. http://www.jboss.org/envers
+ *
+ * Copyright 2008 Red Hat Middleware, LLC. All rights reserved.
+ *
+ * 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, v. 2.1.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT A 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, v.2.1 along with this distribution; if not, write to the Free
+ * Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+ * 02110-1301, USA.
+ *
+ * Red Hat Author(s): Adam Warski
+ */
+package org.jboss.envers.entities;
+
+import java.util.Map;
+import java.util.HashMap;
+
+/**
+ * Configuration of the user entities: property mapping of the entities, relations, inheritance.
+ * @author Adam Warski (adam at warski dot org)
+ */
+public class EntitiesConfigurations {
+ private Map<String, EntityConfiguration> entitiesConfigurations;
+
+ // Map versions entity name -> entity name
+ private Map<String, String> entityNamesForVersionsEntityNames = new HashMap<String, String>();
+
+ public EntitiesConfigurations(Map<String, EntityConfiguration> entitiesConfigurations) {
+ this.entitiesConfigurations = entitiesConfigurations;
+
+ generateBidirectionRelationInfo();
+ generateVersionsEntityToEntityNames();
+ }
+
+ private void generateVersionsEntityToEntityNames() {
+ entityNamesForVersionsEntityNames = new HashMap<String, String>();
+
+ for (String entityName : entitiesConfigurations.keySet()) {
+ entityNamesForVersionsEntityNames.put(entitiesConfigurations.get(entityName).getVersionsEntityName(),
+ entityName);
+ }
+ }
+
+ private void generateBidirectionRelationInfo() {
+ // Checking each relation if it is bidirectional. If so, storing that information.
+ for (String entityName : entitiesConfigurations.keySet()) {
+ EntityConfiguration entCfg = entitiesConfigurations.get(entityName);
+ // Iterating over all relations from that entity
+ for (RelationDescription relDesc : entCfg.getRelationsIterator()) {
+ // If this is an "owned" relation, checking the related entity, if it has a relation that has
+ // a mapped-by attribute to the currently checked. If so, this is a bidirectional relation.
+ if (relDesc.getRelationType() == RelationType.TO_ONE ||
+ relDesc.getRelationType() == RelationType.TO_MANY_MIDDLE) {
+ for (RelationDescription other : entitiesConfigurations.get(relDesc.getToEntityName()).getRelationsIterator()) {
+ if (relDesc.getFromPropertyName().equals(other.getMappedByPropertyName()) &&
+ (entityName.equals(other.getToEntityName()))) {
+ relDesc.setBidirectional(true);
+ other.setBidirectional(true);
+ }
+ }
+ }
+ }
+ }
+ }
+
+ public EntityConfiguration get(String entityName) {
+ return entitiesConfigurations.get(entityName);
+ }
+
+ public String getEntityNameForVersionsEntityName(String versionsEntityName) {
+ return entityNamesForVersionsEntityNames.get(versionsEntityName);
+ }
+
+ public boolean isVersioned(String entityName) {
+ return get(entityName) != null;
+ }
+
+ public RelationDescription getRelationDescription(String entityName, String propertyName) {
+ EntityConfiguration entCfg = entitiesConfigurations.get(entityName);
+ RelationDescription relDesc = entCfg.getRelationDescription(propertyName);
+ if (relDesc != null) {
+ return relDesc;
+ } else if (entCfg.getParentEntityName() != null) {
+ // The field may be declared in a superclass ...
+ return getRelationDescription(entCfg.getParentEntityName(), propertyName);
+ } else {
+ return null;
+ }
+ }
+}
Added: core/trunk/envers/src/main/java/org/jboss/envers/entities/EntityConfiguration.java
===================================================================
--- core/trunk/envers/src/main/java/org/jboss/envers/entities/EntityConfiguration.java (rev 0)
+++ core/trunk/envers/src/main/java/org/jboss/envers/entities/EntityConfiguration.java 2008-10-27 18:56:31 UTC (rev 15406)
@@ -0,0 +1,111 @@
+/*
+ * Envers. http://www.jboss.org/envers
+ *
+ * Copyright 2008 Red Hat Middleware, LLC. All rights reserved.
+ *
+ * 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, v. 2.1.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT A 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, v.2.1 along with this distribution; if not, write to the Free
+ * Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+ * 02110-1301, USA.
+ *
+ * Red Hat Author(s): Adam Warski
+ */
+package org.jboss.envers.entities;
+
+import org.jboss.envers.entities.mapper.ExtendedPropertyMapper;
+import org.jboss.envers.entities.mapper.id.IdMapper;
+
+import java.util.Map;
+import java.util.HashMap;
+
+/**
+ * @author Adam Warski (adam at warski dot org)
+ */
+public class EntityConfiguration {
+ private String versionsEntityName;
+ private IdMappingData idMappingData;
+ private ExtendedPropertyMapper propertyMapper;
+ // Maps from property name
+ private Map<String, RelationDescription> relations;
+ private String parentEntityName;
+
+ public EntityConfiguration(String versionsEntityName, IdMappingData idMappingData,
+ ExtendedPropertyMapper propertyMapper, String parentEntityName) {
+ this.versionsEntityName = versionsEntityName;
+ this.idMappingData = idMappingData;
+ this.propertyMapper = propertyMapper;
+ this.parentEntityName = parentEntityName;
+
+ this.relations = new HashMap<String, RelationDescription>();
+ }
+
+ public void addToOneRelation(String fromPropertyName, String toEntityName, IdMapper idMapper) {
+ relations.put(fromPropertyName, new RelationDescription(fromPropertyName, RelationType.TO_ONE,
+ toEntityName, null, idMapper));
+ }
+
+ public void addToOneNotOwningRelation(String fromPropertyName, String mappedByPropertyName, String toEntityName,
+ IdMapper idMapper) {
+ relations.put(fromPropertyName, new RelationDescription(fromPropertyName, RelationType.TO_ONE_NOT_OWNING,
+ toEntityName, mappedByPropertyName, idMapper));
+ }
+
+ public void addToManyNotOwningRelation(String fromPropertyName, String mappedByPropertyName, String toEntityName,
+ IdMapper idMapper) {
+ relations.put(fromPropertyName, new RelationDescription(fromPropertyName, RelationType.TO_MANY_NOT_OWNING,
+ toEntityName, mappedByPropertyName, idMapper));
+ }
+
+ public void addToManyMiddleRelation(String fromPropertyName, String toEntityName) {
+ relations.put(fromPropertyName, new RelationDescription(fromPropertyName, RelationType.TO_MANY_MIDDLE,
+ toEntityName, null, null));
+ }
+
+ public void addToManyMiddleNotOwningRelation(String fromPropertyName, String mappedByPropertyName, String toEntityName) {
+ relations.put(fromPropertyName, new RelationDescription(fromPropertyName, RelationType.TO_MANY_MIDDLE_NOT_OWNING,
+ toEntityName, mappedByPropertyName, null));
+ }
+
+ public boolean isRelation(String propertyName) {
+ return relations.get(propertyName) != null;
+ }
+
+ public RelationDescription getRelationDescription(String propertyName) {
+ return relations.get(propertyName);
+ }
+
+ public IdMappingData getIdMappingData() {
+ return idMappingData;
+ }
+
+ public IdMapper getIdMapper() {
+ return idMappingData.getIdMapper();
+ }
+
+ public ExtendedPropertyMapper getPropertyMapper() {
+ return propertyMapper;
+ }
+
+ // For use by EntitiesConfigurations
+
+ String getParentEntityName() {
+ return parentEntityName;
+ }
+
+ String getVersionsEntityName() {
+ return versionsEntityName;
+ }
+
+ Iterable<RelationDescription> getRelationsIterator() {
+ return relations.values();
+ }
+}
Added: core/trunk/envers/src/main/java/org/jboss/envers/entities/EntityInstantiator.java
===================================================================
--- core/trunk/envers/src/main/java/org/jboss/envers/entities/EntityInstantiator.java (rev 0)
+++ core/trunk/envers/src/main/java/org/jboss/envers/entities/EntityInstantiator.java 2008-10-27 18:56:31 UTC (rev 15406)
@@ -0,0 +1,103 @@
+/*
+ * Envers. http://www.jboss.org/envers
+ *
+ * Copyright 2008 Red Hat Middleware, LLC. All rights reserved.
+ *
+ * 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, v. 2.1.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT A 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, v.2.1 along with this distribution; if not, write to the Free
+ * Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+ * 02110-1301, USA.
+ *
+ * Red Hat Author(s): Adam Warski
+ */
+package org.jboss.envers.entities;
+
+import org.jboss.envers.exception.VersionsException;
+import org.jboss.envers.configuration.VersionsConfiguration;
+import org.jboss.envers.entities.mapper.id.IdMapper;
+import org.jboss.envers.reader.VersionsReaderImplementor;
+import org.jboss.envers.tools.reflection.ReflectionTools;
+
+import java.util.Map;
+import java.util.List;
+import java.util.Collection;
+
+/**
+ * @author Adam Warski (adam at warski dot org)
+ */
+public class EntityInstantiator {
+ private final VersionsConfiguration verCfg;
+ private final VersionsReaderImplementor versionsReader;
+
+ public EntityInstantiator(VersionsConfiguration verCfg, VersionsReaderImplementor versionsReader) {
+ this.verCfg = verCfg;
+ this.versionsReader = versionsReader;
+ }
+
+ /**
+ * Creates an entity instance based on an entry from the versions table.
+ * @param entityName Name of the entity, which instances should be read
+ * @param versionsEntity An entry in the versions table, from which data should be mapped.
+ * @param revision Revision at which this entity was read.
+ * @return An entity instance, with versioned properties set as in the versionsEntity map, and proxies
+ * created for collections.
+ */
+ public Object createInstanceFromVersionsEntity(String entityName, Map versionsEntity, Number revision) {
+ if (versionsEntity == null) {
+ return null;
+ }
+
+ // The $type$ property holds the name of the (versions) entity
+ String type = verCfg.getEntCfg().getEntityNameForVersionsEntityName((String) versionsEntity.get("$type$"));
+
+ if (type != null) {
+ entityName = type;
+ }
+
+ // First mapping the primary key
+ IdMapper idMapper = verCfg.getEntCfg().get(entityName).getIdMapper();
+ Map originalId = (Map) versionsEntity.get(verCfg.getVerEntCfg().getOriginalIdPropName());
+
+ Object primaryKey = idMapper.mapToIdFromMap(originalId);
+
+ // Checking if the entity is in cache
+ if (versionsReader.getFirstLevelCache().contains(entityName, revision, primaryKey)) {
+ return versionsReader.getFirstLevelCache().get(entityName, revision, primaryKey);
+ }
+
+ // If it is not in the cache, creating a new entity instance
+ Object ret;
+ try {
+ Class<?> cls = ReflectionTools.loadClass(entityName);
+ ret = cls.newInstance();
+ } catch (Exception e) {
+ throw new VersionsException(e);
+ }
+
+ // Putting the newly created entity instance into the first level cache, in case a one-to-one bidirectional
+ // relation is present (which is eagerly loaded).
+ versionsReader.getFirstLevelCache().put(entityName, revision, primaryKey, ret);
+
+ verCfg.getEntCfg().get(entityName).getPropertyMapper().mapToEntityFromMap(verCfg, ret, versionsEntity, primaryKey,
+ versionsReader, revision);
+ idMapper.mapToEntityFromMap(ret, originalId);
+
+ return ret;
+ }
+
+ @SuppressWarnings({"unchecked"})
+ public void addInstancesFromVersionsEntities(String entityName, Collection addTo, List<Map> versionsEntities, Number revision) {
+ for (Map versionsEntity : versionsEntities) {
+ addTo.add(createInstanceFromVersionsEntity(entityName, versionsEntity, revision));
+ }
+ }
+}
Added: core/trunk/envers/src/main/java/org/jboss/envers/entities/IdMappingData.java
===================================================================
--- core/trunk/envers/src/main/java/org/jboss/envers/entities/IdMappingData.java (rev 0)
+++ core/trunk/envers/src/main/java/org/jboss/envers/entities/IdMappingData.java 2008-10-27 18:56:31 UTC (rev 15406)
@@ -0,0 +1,54 @@
+/*
+ * Envers. http://www.jboss.org/envers
+ *
+ * Copyright 2008 Red Hat Middleware, LLC. All rights reserved.
+ *
+ * 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, v. 2.1.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT A 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, v.2.1 along with this distribution; if not, write to the Free
+ * Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+ * 02110-1301, USA.
+ *
+ * Red Hat Author(s): Adam Warski
+ */
+package org.jboss.envers.entities;
+
+import org.jboss.envers.entities.mapper.id.IdMapper;
+import org.dom4j.Element;
+
+/**
+ * @author Adam Warski (adam at warski dot org)
+ */
+public class IdMappingData {
+ private final IdMapper idMapper;
+ // Mapping which will be used to generate the entity
+ private final Element xmlMapping;
+ // Mapping which will be used to generate references to the entity in related entities
+ private final Element xmlRelationMapping;
+
+ public IdMappingData(IdMapper idMapper, Element xmlMapping, Element xmlRelationMapping) {
+ this.idMapper = idMapper;
+ this.xmlMapping = xmlMapping;
+ this.xmlRelationMapping = xmlRelationMapping;
+ }
+
+ public IdMapper getIdMapper() {
+ return idMapper;
+ }
+
+ public Element getXmlMapping() {
+ return xmlMapping;
+ }
+
+ public Element getXmlRelationMapping() {
+ return xmlRelationMapping;
+ }
+}
Added: core/trunk/envers/src/main/java/org/jboss/envers/entities/RelationDescription.java
===================================================================
--- core/trunk/envers/src/main/java/org/jboss/envers/entities/RelationDescription.java (rev 0)
+++ core/trunk/envers/src/main/java/org/jboss/envers/entities/RelationDescription.java 2008-10-27 18:56:31 UTC (rev 15406)
@@ -0,0 +1,75 @@
+/*
+ * Envers. http://www.jboss.org/envers
+ *
+ * Copyright 2008 Red Hat Middleware, LLC. All rights reserved.
+ *
+ * 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, v. 2.1.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT A 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, v.2.1 along with this distribution; if not, write to the Free
+ * Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+ * 02110-1301, USA.
+ *
+ * Red Hat Author(s): Adam Warski
+ */
+package org.jboss.envers.entities;
+
+import org.jboss.envers.entities.mapper.id.IdMapper;
+
+/**
+ * @author Adam Warski (adam at warski dot org)
+*/
+public class RelationDescription {
+ private final String fromPropertyName;
+ private final RelationType relationType;
+ private final String toEntityName;
+ private final String mappedByPropertyName;
+ private final IdMapper idMapper;
+ private boolean bidirectional;
+
+ public RelationDescription(String fromPropertyName, RelationType relationType, String toEntityName,
+ String mappedByPropertyName, IdMapper idMapper) {
+ this.fromPropertyName = fromPropertyName;
+ this.relationType = relationType;
+ this.toEntityName = toEntityName;
+ this.mappedByPropertyName = mappedByPropertyName;
+ this.idMapper = idMapper;
+
+ this.bidirectional = false;
+ }
+
+ public String getFromPropertyName() {
+ return fromPropertyName;
+ }
+
+ public RelationType getRelationType() {
+ return relationType;
+ }
+
+ public String getToEntityName() {
+ return toEntityName;
+ }
+
+ public String getMappedByPropertyName() {
+ return mappedByPropertyName;
+ }
+
+ public IdMapper getIdMapper() {
+ return idMapper;
+ }
+
+ public boolean isBidirectional() {
+ return bidirectional;
+ }
+
+ void setBidirectional(boolean bidirectional) {
+ this.bidirectional = bidirectional;
+ }
+}
Added: core/trunk/envers/src/main/java/org/jboss/envers/entities/RelationType.java
===================================================================
--- core/trunk/envers/src/main/java/org/jboss/envers/entities/RelationType.java (rev 0)
+++ core/trunk/envers/src/main/java/org/jboss/envers/entities/RelationType.java 2008-10-27 18:56:31 UTC (rev 15406)
@@ -0,0 +1,54 @@
+/*
+ * JBoss, Home of Professional Open Source
+ *
+ * Copyright 2008, Red Hat Middleware LLC, and others contributors as indicated
+ * by the @authors tag. All rights reserved.
+ *
+ * See the copyright.txt in the distribution for a full listing of individual
+ * contributors. 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, v. 2.1.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT A 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, v.2.1 along with this distribution; if not, write to the Free
+ * Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+ * 02110-1301, USA.
+ *
+ * Red Hat Author(s): Adam Warski
+ */
+package org.jboss.envers.entities;
+
+/**
+ * Type of a relation between two entities.
+ * @author Adam Warski (adam at warski dot org)
+*/
+public enum RelationType {
+ /**
+ * A single-reference-valued relation. The entity owns the relation.
+ */
+ TO_ONE,
+ /**
+ * A single-reference-valued relation. The entity doesn't own the relation. It is directly mapped in the related
+ * entity.
+ */
+ TO_ONE_NOT_OWNING,
+ /**
+ * A collection-of-references-valued relation. The entity doesn't own the relation. It is directly mapped in the
+ * related entity.
+ */
+ TO_MANY_NOT_OWNING,
+ /**
+ * A collection-of-references-valued relation. The entity owns the relation. It is mapped using a middle table.
+ */
+ TO_MANY_MIDDLE,
+ /**
+ * A collection-of-references-valued relation. The entity doesn't own the relation. It is mapped using a middle
+ * table.
+ */
+ TO_MANY_MIDDLE_NOT_OWNING
+}
Added: core/trunk/envers/src/main/java/org/jboss/envers/entities/RevisionTypeType.java
===================================================================
--- core/trunk/envers/src/main/java/org/jboss/envers/entities/RevisionTypeType.java (rev 0)
+++ core/trunk/envers/src/main/java/org/jboss/envers/entities/RevisionTypeType.java 2008-10-27 18:56:31 UTC (rev 15406)
@@ -0,0 +1,108 @@
+/*
+ * JBoss, Home of Professional Open Source
+ *
+ * Copyright 2008, Red Hat Middleware LLC, and others contributors as indicated
+ * by the @authors tag. All rights reserved.
+ *
+ * See the copyright.txt in the distribution for a full listing of individual
+ * contributors. 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, v. 2.1.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT A 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, v.2.1 along with this distribution; if not, write to the Free
+ * Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+ * 02110-1301, USA.
+ *
+ * Red Hat Author(s): Adam Warski
+ */
+package org.jboss.envers.entities;
+
+import org.hibernate.usertype.UserType;
+import org.hibernate.HibernateException;
+import org.jboss.envers.RevisionType;
+
+import java.sql.ResultSet;
+import java.sql.Types;
+import java.sql.SQLException;
+import java.sql.PreparedStatement;
+import java.io.Serializable;
+
+/**
+ * A hibernate type for the {@link RevisionType} enum.
+ * @author Adam Warski (adam at warski dot org)
+ */
+public class RevisionTypeType implements UserType {
+ private static final int[] SQL_TYPES = { Types.TINYINT };
+
+ public int[] sqlTypes() {
+ return SQL_TYPES;
+ }
+
+ public Class returnedClass() {
+ return RevisionType.class;
+ }
+
+ public RevisionType nullSafeGet(ResultSet resultSet, String[] names, Object owner) throws HibernateException, SQLException {
+ byte representation = (byte) resultSet.getInt(names[0]);
+ RevisionType result = null;
+
+ if (!resultSet.wasNull()) {
+ result = RevisionType.fromRepresentation(representation);
+ }
+
+ return result;
+ }
+
+ public void nullSafeSet(PreparedStatement preparedStatement, Object value, int index) throws HibernateException, SQLException {
+ if (null == value) {
+ preparedStatement.setNull(index, Types.TINYINT);
+ } else {
+ preparedStatement.setInt(index, ((RevisionType) value).getRepresentation());
+ }
+ }
+
+ public Object deepCopy(Object value) throws HibernateException{
+ return value;
+ }
+
+ public boolean isMutable() {
+ return false;
+ }
+
+ public Object assemble(Serializable cached, Object owner) throws HibernateException {
+ return cached;
+ }
+
+ public Serializable disassemble(Object value) throws HibernateException {
+ return (Serializable)value;
+ }
+
+ public Object replace(Object original, Object target, Object owner) throws HibernateException {
+ return original;
+ }
+
+ public int hashCode(Object x) throws HibernateException {
+ return x.hashCode();
+ }
+
+ public boolean equals(Object x, Object y) throws HibernateException {
+ //noinspection ObjectEquality
+ if (x == y) {
+ return true;
+ }
+
+ if (null == x || null == y) {
+ return false;
+ }
+
+ return x.equals(y);
+ }
+}
+
+
Added: core/trunk/envers/src/main/java/org/jboss/envers/entities/mapper/CompositeMapperBuilder.java
===================================================================
--- core/trunk/envers/src/main/java/org/jboss/envers/entities/mapper/CompositeMapperBuilder.java (rev 0)
+++ core/trunk/envers/src/main/java/org/jboss/envers/entities/mapper/CompositeMapperBuilder.java 2008-10-27 18:56:31 UTC (rev 15406)
@@ -0,0 +1,30 @@
+/*
+ * Envers. http://www.jboss.org/envers
+ *
+ * Copyright 2008 Red Hat Middleware, LLC. All rights reserved.
+ *
+ * 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, v. 2.1.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT A 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, v.2.1 along with this distribution; if not, write to the Free
+ * Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+ * 02110-1301, USA.
+ *
+ * Red Hat Author(s): Adam Warski
+ */
+package org.jboss.envers.entities.mapper;
+
+/**
+ * @author Adam Warski (adam at warski dot org)
+ */
+public interface CompositeMapperBuilder extends SimpleMapperBuilder {
+ public CompositeMapperBuilder addComposite(String propertyName);
+ public void addComposite(String propertyName, PropertyMapper propertyMapper);
+}
Added: core/trunk/envers/src/main/java/org/jboss/envers/entities/mapper/ExtendedPropertyMapper.java
===================================================================
--- core/trunk/envers/src/main/java/org/jboss/envers/entities/mapper/ExtendedPropertyMapper.java (rev 0)
+++ core/trunk/envers/src/main/java/org/jboss/envers/entities/mapper/ExtendedPropertyMapper.java 2008-10-27 18:56:31 UTC (rev 15406)
@@ -0,0 +1,31 @@
+/*
+ * Envers. http://www.jboss.org/envers
+ *
+ * Copyright 2008 Red Hat Middleware, LLC. All rights reserved.
+ *
+ * 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, v. 2.1.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT A 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, v.2.1 along with this distribution; if not, write to the Free
+ * Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+ * 02110-1301, USA.
+ *
+ * Red Hat Author(s): Adam Warski
+ */
+package org.jboss.envers.entities.mapper;
+
+import java.util.Map;
+
+/**
+ * @author Adam Warski (adam at warski dot org)
+ */
+public interface ExtendedPropertyMapper extends PropertyMapper, CompositeMapperBuilder {
+ public boolean map(Map<String, Object> data, String[] propertyNames, Object[] newState, Object[] oldState);
+}
Added: core/trunk/envers/src/main/java/org/jboss/envers/entities/mapper/MapPropertyMapper.java
===================================================================
--- core/trunk/envers/src/main/java/org/jboss/envers/entities/mapper/MapPropertyMapper.java (rev 0)
+++ core/trunk/envers/src/main/java/org/jboss/envers/entities/mapper/MapPropertyMapper.java 2008-10-27 18:56:31 UTC (rev 15406)
@@ -0,0 +1,94 @@
+/*
+ * Envers. http://www.jboss.org/envers
+ *
+ * Copyright 2008 Red Hat Middleware, LLC. All rights reserved.
+ *
+ * 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, v. 2.1.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT A 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, v.2.1 along with this distribution; if not, write to the Free
+ * Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+ * 02110-1301, USA.
+ *
+ * Red Hat Author(s): Adam Warski
+ */
+package org.jboss.envers.entities.mapper;
+
+import org.jboss.envers.ModificationStore;
+import org.jboss.envers.configuration.VersionsConfiguration;
+import org.jboss.envers.tools.reflection.ReflectionTools;
+import org.jboss.envers.reader.VersionsReaderImplementor;
+import org.jboss.envers.exception.VersionsException;
+import org.hibernate.property.Getter;
+import org.hibernate.property.Setter;
+import org.hibernate.util.ReflectHelper;
+import org.hibernate.collection.PersistentCollection;
+
+import java.util.Map;
+import java.util.HashMap;
+import java.util.List;
+import java.io.Serializable;
+
+/**
+ * @author Adam Warski (adam at warski dot org)
+ */
+public class MapPropertyMapper implements PropertyMapper, CompositeMapperBuilder {
+ private String propertyName;
+ private ExtendedPropertyMapper delegate;
+
+ public MapPropertyMapper(String propertyName) {
+ this.propertyName = propertyName;
+ this.delegate = new MultiPropertyMapper();
+ }
+
+ public void add(String propertyName, ModificationStore modStore) {
+ delegate.add(propertyName, modStore);
+ }
+
+ public CompositeMapperBuilder addComposite(String propertyName) {
+ return delegate.addComposite(propertyName);
+ }
+
+ public void addComposite(String propertyName, PropertyMapper propertyMapper) {
+ delegate.addComposite(propertyName, propertyMapper);
+ }
+
+ public boolean mapToMapFromEntity(Map<String, Object> data, Object newObj, Object oldObj) {
+ Map<String, Object> newData = new HashMap<String, Object>();
+ data.put(propertyName, newData);
+
+ return delegate.mapToMapFromEntity(newData, newObj, oldObj);
+ }
+
+ public void mapToEntityFromMap(VersionsConfiguration verCfg, Object obj, Map data, Object primaryKey, VersionsReaderImplementor versionsReader, Number revision) {
+ if (data == null || obj == null) {
+ return;
+ }
+
+ Getter getter = ReflectionTools.getGetter(obj.getClass(), propertyName);
+ Setter setter = ReflectionTools.getSetter(obj.getClass(), propertyName);
+
+ try {
+ Object subObj = ReflectHelper.getDefaultConstructor(getter.getReturnType()).newInstance();
+ setter.set(obj, subObj, null);
+ delegate.mapToEntityFromMap(verCfg, subObj, (Map) data.get(propertyName), primaryKey, versionsReader, revision);
+ } catch (Exception e) {
+ throw new VersionsException(e);
+ }
+ }
+
+ public List<PersistentCollectionChangeData> mapCollectionChanges(String referencingPropertyName,
+ PersistentCollection newColl,
+ Serializable oldColl,
+ Serializable id) {
+ return delegate.mapCollectionChanges(referencingPropertyName, newColl, oldColl, id);
+ }
+
+}
Added: core/trunk/envers/src/main/java/org/jboss/envers/entities/mapper/MultiPropertyMapper.java
===================================================================
--- core/trunk/envers/src/main/java/org/jboss/envers/entities/mapper/MultiPropertyMapper.java (rev 0)
+++ core/trunk/envers/src/main/java/org/jboss/envers/entities/mapper/MultiPropertyMapper.java 2008-10-27 18:56:31 UTC (rev 15406)
@@ -0,0 +1,122 @@
+/*
+ * Envers. http://www.jboss.org/envers
+ *
+ * Copyright 2008 Red Hat Middleware, LLC. All rights reserved.
+ *
+ * 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, v. 2.1.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT A 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, v.2.1 along with this distribution; if not, write to the Free
+ * Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+ * 02110-1301, USA.
+ *
+ * Red Hat Author(s): Adam Warski
+ */
+package org.jboss.envers.entities.mapper;
+
+import org.hibernate.property.Getter;
+import org.hibernate.MappingException;
+import org.hibernate.collection.PersistentCollection;
+import org.jboss.envers.ModificationStore;
+import org.jboss.envers.configuration.VersionsConfiguration;
+import org.jboss.envers.tools.reflection.ReflectionTools;
+import org.jboss.envers.reader.VersionsReaderImplementor;
+
+import java.util.Map;
+import java.util.HashMap;
+import java.util.List;
+import java.io.Serializable;
+
+/**
+ * @author Adam Warski (adam at warski dot org)
+ */
+public class MultiPropertyMapper implements ExtendedPropertyMapper {
+ protected Map<String, PropertyMapper> properties;
+
+ public MultiPropertyMapper() {
+ properties = new HashMap<String, PropertyMapper>();
+ }
+
+ public void add(String propertyName, ModificationStore modStore) {
+ SinglePropertyMapper single = new SinglePropertyMapper();
+ single.add(propertyName, modStore);
+ properties.put(propertyName, single);
+ }
+
+ public CompositeMapperBuilder addComposite(String propertyName) {
+ if (properties.get(propertyName) != null) {
+ throw new MappingException("Mapping for " + propertyName + " already added!");
+ }
+
+ MapPropertyMapper mapperBuilder = new MapPropertyMapper(propertyName);
+ properties.put(propertyName, mapperBuilder);
+
+ return mapperBuilder;
+ }
+
+ public void addComposite(String propertyName, PropertyMapper propertyMapper) {
+ properties.put(propertyName, propertyMapper);
+ }
+
+ private Object getAtIndexOrNull(Object[] array, int index) { return array == null ? null : array[index]; }
+
+ public boolean map(Map<String, Object> data, String[] propertyNames, Object[] newState, Object[] oldState) {
+ boolean ret = false;
+ for (int i=0; i<propertyNames.length; i++) {
+ String propertyName = propertyNames[i];
+
+ if (properties.containsKey(propertyName)) {
+ ret |= properties.get(propertyName).mapToMapFromEntity(data,
+ getAtIndexOrNull(newState, i),
+ getAtIndexOrNull(oldState, i));
+ }
+ }
+
+ return ret;
+ }
+
+ public boolean mapToMapFromEntity(Map<String, Object> data, Object newObj, Object oldObj) {
+ boolean ret = false;
+ for (String propertyName : properties.keySet()) {
+ Getter getter;
+ if (newObj != null) {
+ getter = ReflectionTools.getGetter(newObj.getClass(), propertyName);
+ } else if (oldObj != null) {
+ getter = ReflectionTools.getGetter(oldObj.getClass(), propertyName);
+ } else {
+ return false;
+ }
+
+ ret |= properties.get(propertyName).mapToMapFromEntity(data,
+ newObj == null ? null : getter.get(newObj),
+ oldObj == null ? null : getter.get(oldObj));
+ }
+
+ return ret;
+ }
+
+ public void mapToEntityFromMap(VersionsConfiguration verCfg, Object obj, Map data, Object primaryKey, VersionsReaderImplementor versionsReader, Number revision) {
+ for (String propertyName : properties.keySet()) {
+ properties.get(propertyName).mapToEntityFromMap(verCfg, obj, data, primaryKey, versionsReader, revision);
+ }
+ }
+
+ public List<PersistentCollectionChangeData> mapCollectionChanges(String referencingPropertyName,
+ PersistentCollection newColl,
+ Serializable oldColl,
+ Serializable id) {
+ PropertyMapper mapper = properties.get(referencingPropertyName);
+ if (mapper != null) {
+ return mapper.mapCollectionChanges(referencingPropertyName, newColl, oldColl, id);
+ } else {
+ return null;
+ }
+ }
+}
Added: core/trunk/envers/src/main/java/org/jboss/envers/entities/mapper/PersistentCollectionChangeData.java
===================================================================
--- core/trunk/envers/src/main/java/org/jboss/envers/entities/mapper/PersistentCollectionChangeData.java (rev 0)
+++ core/trunk/envers/src/main/java/org/jboss/envers/entities/mapper/PersistentCollectionChangeData.java 2008-10-27 18:56:31 UTC (rev 15406)
@@ -0,0 +1,63 @@
+/*
+ * JBoss, Home of Professional Open Source
+ *
+ * Copyright 2008, Red Hat Middleware LLC, and others contributors as indicated
+ * by the @authors tag. All rights reserved.
+ *
+ * See the copyright.txt in the distribution for a full listing of individual
+ * contributors. 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, v. 2.1.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT A 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, v.2.1 along with this distribution; if not, write to the Free
+ * Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+ * 02110-1301, USA.
+ *
+ * Red Hat Author(s): Adam Warski
+ */
+package org.jboss.envers.entities.mapper;
+
+import java.util.Map;
+
+/**
+ * Data describing the change of a single object in a persisten collection (when the object was added, removed or
+ * modified in the collection).
+ * @author Adam Warski (adam at warski dot org)
+ */
+public class PersistentCollectionChangeData {
+ private final String entityName;
+ private final Map<String, Object> data;
+ private final Object changedElement;
+
+ public PersistentCollectionChangeData(String entityName, Map<String, Object> data, Object changedElement) {
+ this.entityName = entityName;
+ this.data = data;
+ this.changedElement = changedElement;
+ }
+
+ /**
+ *
+ * @return Name of the (middle) entity that holds the collection data.
+ */
+ public String getEntityName() {
+ return entityName;
+ }
+
+ public Map<String, Object> getData() {
+ return data;
+ }
+
+ /**
+ * For use by bi-directional associations.
+ * @return The affected element, which was changed (added, removed, modified) in the collection.
+ */
+ public Object getChangedElement() {
+ return changedElement;
+ }
+}
Added: core/trunk/envers/src/main/java/org/jboss/envers/entities/mapper/PropertyMapper.java
===================================================================
--- core/trunk/envers/src/main/java/org/jboss/envers/entities/mapper/PropertyMapper.java (rev 0)
+++ core/trunk/envers/src/main/java/org/jboss/envers/entities/mapper/PropertyMapper.java 2008-10-27 18:56:31 UTC (rev 15406)
@@ -0,0 +1,68 @@
+/*
+ * Envers. http://www.jboss.org/envers
+ *
+ * Copyright 2008 Red Hat Middleware, LLC. All rights reserved.
+ *
+ * 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, v. 2.1.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT A 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, v.2.1 along with this distribution; if not, write to the Free
+ * Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+ * 02110-1301, USA.
+ *
+ * Red Hat Author(s): Adam Warski
+ */
+package org.jboss.envers.entities.mapper;
+
+import org.jboss.envers.reader.VersionsReaderImplementor;
+import org.jboss.envers.configuration.VersionsConfiguration;
+import org.hibernate.collection.PersistentCollection;
+
+import java.util.Map;
+import java.util.List;
+import java.io.Serializable;
+
+/**
+ * @author Adam Warski (adam at warski dot org)
+ */
+public interface PropertyMapper {
+ /**
+ * Maps properties to the given map, basing on differences between properties of new and old objects.
+ * @param data Data to map to.
+ * @param newObj New state of the entity.
+ * @param oldObj Old state of the entity.
+ * @return True if there are any differences between the states represented by newObj and oldObj.
+ */
+ boolean mapToMapFromEntity(Map<String, Object> data, Object newObj, Object oldObj);
+
+ /**
+ * Maps properties from the given map to the given object.
+ * @param verCfg Versions configuration.
+ * @param obj Object to map to.
+ * @param data Data to map from.
+ * @param primaryKey Primary key of the object to which we map (for relations)
+ * @param versionsReader VersionsReader for reading relations
+ * @param revision Revision at which the object is read, for reading relations
+ */
+ void mapToEntityFromMap(VersionsConfiguration verCfg, Object obj, Map data, Object primaryKey,
+ VersionsReaderImplementor versionsReader, Number revision);
+
+ /**
+ * Maps collection changes
+ * @param referencingPropertyName Name of the field, which holds the collection in the entity.
+ * @param newColl New collection, after updates.
+ * @param oldColl Old collection, before updates.
+ * @param id Id of the object owning the collection.
+ * @return List of changes that need to be performed on the persistent store.
+ */
+ List<PersistentCollectionChangeData> mapCollectionChanges(String referencingPropertyName,
+ PersistentCollection newColl,
+ Serializable oldColl, Serializable id);
+}
Added: core/trunk/envers/src/main/java/org/jboss/envers/entities/mapper/SimpleMapperBuilder.java
===================================================================
--- core/trunk/envers/src/main/java/org/jboss/envers/entities/mapper/SimpleMapperBuilder.java (rev 0)
+++ core/trunk/envers/src/main/java/org/jboss/envers/entities/mapper/SimpleMapperBuilder.java 2008-10-27 18:56:31 UTC (rev 15406)
@@ -0,0 +1,31 @@
+/*
+ * Envers. http://www.jboss.org/envers
+ *
+ * Copyright 2008 Red Hat Middleware, LLC. All rights reserved.
+ *
+ * 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, v. 2.1.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT A 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, v.2.1 along with this distribution; if not, write to the Free
+ * Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+ * 02110-1301, USA.
+ *
+ * Red Hat Author(s): Adam Warski
+ */
+package org.jboss.envers.entities.mapper;
+
+import org.jboss.envers.ModificationStore;
+
+/**
+ * @author Adam Warski (adam at warski dot org)
+ */
+public interface SimpleMapperBuilder {
+ public void add(String propertyName, ModificationStore modStore);
+}
\ No newline at end of file
Added: core/trunk/envers/src/main/java/org/jboss/envers/entities/mapper/SinglePropertyMapper.java
===================================================================
--- core/trunk/envers/src/main/java/org/jboss/envers/entities/mapper/SinglePropertyMapper.java (rev 0)
+++ core/trunk/envers/src/main/java/org/jboss/envers/entities/mapper/SinglePropertyMapper.java 2008-10-27 18:56:31 UTC (rev 15406)
@@ -0,0 +1,76 @@
+/*
+ * Envers. http://www.jboss.org/envers
+ *
+ * Copyright 2008 Red Hat Middleware, LLC. All rights reserved.
+ *
+ * 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, v. 2.1.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT A 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, v.2.1 along with this distribution; if not, write to the Free
+ * Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+ * 02110-1301, USA.
+ *
+ * Red Hat Author(s): Adam Warski
+ */
+package org.jboss.envers.entities.mapper;
+
+import org.jboss.envers.ModificationStore;
+import org.jboss.envers.configuration.VersionsConfiguration;
+import org.jboss.envers.tools.reflection.ReflectionTools;
+import org.jboss.envers.reader.VersionsReaderImplementor;
+import org.jboss.envers.tools.Tools;
+import org.jboss.envers.exception.VersionsException;
+import org.hibernate.property.Setter;
+import org.hibernate.collection.PersistentCollection;
+
+import java.util.Map;
+import java.util.List;
+import java.io.Serializable;
+
+/**
+ * TODO: diff
+ * @author Adam Warski (adam at warski dot org)
+ */
+public class SinglePropertyMapper implements PropertyMapper, SimpleMapperBuilder {
+ private String propertyName;
+
+ public SinglePropertyMapper() { }
+
+ public void add(String propertyName, ModificationStore modStore) {
+ if (this.propertyName != null) {
+ throw new VersionsException("Only one property can be added!");
+ }
+
+ this.propertyName = propertyName;
+ }
+
+ public boolean mapToMapFromEntity(Map<String, Object> data, Object newObj, Object oldObj) {
+ data.put(propertyName, newObj);
+
+ return !Tools.objectsEqual(newObj, oldObj);
+ }
+
+ public void mapToEntityFromMap(VersionsConfiguration verCfg, Object obj, Map data, Object primaryKey, VersionsReaderImplementor versionsReader, Number revision) {
+ if (data == null || obj == null) {
+ return;
+ }
+
+ Setter setter = ReflectionTools.getSetter(obj.getClass(), propertyName);
+ setter.set(obj, data.get(propertyName), null);
+ }
+
+ public List<PersistentCollectionChangeData> mapCollectionChanges(String referencingPropertyName,
+ PersistentCollection newColl,
+ Serializable oldColl,
+ Serializable id) {
+ return null;
+ }
+
+}
Added: core/trunk/envers/src/main/java/org/jboss/envers/entities/mapper/SubclassPropertyMapper.java
===================================================================
--- core/trunk/envers/src/main/java/org/jboss/envers/entities/mapper/SubclassPropertyMapper.java (rev 0)
+++ core/trunk/envers/src/main/java/org/jboss/envers/entities/mapper/SubclassPropertyMapper.java 2008-10-27 18:56:31 UTC (rev 15406)
@@ -0,0 +1,91 @@
+/*
+ * Envers. http://www.jboss.org/envers
+ *
+ * Copyright 2008 Red Hat Middleware, LLC. All rights reserved.
+ *
+ * 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, v. 2.1.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT A 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, v.2.1 along with this distribution; if not, write to the Free
+ * Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+ * 02110-1301, USA.
+ *
+ * Red Hat Author(s): Adam Warski
+ */
+package org.jboss.envers.entities.mapper;
+
+import org.jboss.envers.reader.VersionsReaderImplementor;
+import org.jboss.envers.ModificationStore;
+import org.jboss.envers.configuration.VersionsConfiguration;
+import org.hibernate.collection.PersistentCollection;
+
+import java.util.Map;
+import java.util.List;
+import java.io.Serializable;
+
+/**
+ * A mapper which maps from a parent mapper and a "main" one, but adds only to the "main". The "main" mapper
+ * should be the mapper of the subclass.
+ * @author Adam Warski (adam at warski dot org)
+ */
+public class SubclassPropertyMapper implements ExtendedPropertyMapper {
+ private ExtendedPropertyMapper main;
+ private ExtendedPropertyMapper parentMapper;
+
+ public SubclassPropertyMapper(ExtendedPropertyMapper main, ExtendedPropertyMapper parentMapper) {
+ this.main = main;
+ this.parentMapper = parentMapper;
+ }
+
+ public boolean map(Map<String, Object> data, String[] propertyNames, Object[] newState, Object[] oldState) {
+ boolean parentDiffs = parentMapper.map(data, propertyNames, newState, oldState);
+ boolean mainDiffs = main.map(data, propertyNames, newState, oldState);
+
+ return parentDiffs || mainDiffs;
+ }
+
+ public boolean mapToMapFromEntity(Map<String, Object> data, Object newObj, Object oldObj) {
+ boolean parentDiffs = parentMapper.mapToMapFromEntity(data, newObj, oldObj);
+ boolean mainDiffs = main.mapToMapFromEntity(data, newObj, oldObj);
+
+ return parentDiffs || mainDiffs;
+ }
+
+ public void mapToEntityFromMap(VersionsConfiguration verCfg, Object obj, Map data, Object primaryKey, VersionsReaderImplementor versionsReader, Number revision) {
+ parentMapper.mapToEntityFromMap(verCfg, obj, data, primaryKey, versionsReader, revision);
+ main.mapToEntityFromMap(verCfg, obj, data, primaryKey, versionsReader, revision);
+ }
+
+ public List<PersistentCollectionChangeData> mapCollectionChanges(String referencingPropertyName,
+ PersistentCollection newColl,
+ Serializable oldColl,
+ Serializable id) {
+ List<PersistentCollectionChangeData> collectionChanges = parentMapper.mapCollectionChanges(
+ referencingPropertyName, newColl, oldColl, id);
+
+ if (collectionChanges == null) {
+ return main.mapCollectionChanges(referencingPropertyName, newColl, oldColl, id);
+ } else {
+ return collectionChanges;
+ }
+ }
+
+ public CompositeMapperBuilder addComposite(String propertyName) {
+ return main.addComposite(propertyName);
+ }
+
+ public void addComposite(String propertyName, PropertyMapper propertyMapper) {
+ main.addComposite(propertyName, propertyMapper);
+ }
+
+ public void add(String propertyName, ModificationStore modStore) {
+ main.add(propertyName, modStore);
+ }
+}
Added: core/trunk/envers/src/main/java/org/jboss/envers/entities/mapper/id/AbstractCompositeIdMapper.java
===================================================================
--- core/trunk/envers/src/main/java/org/jboss/envers/entities/mapper/id/AbstractCompositeIdMapper.java (rev 0)
+++ core/trunk/envers/src/main/java/org/jboss/envers/entities/mapper/id/AbstractCompositeIdMapper.java 2008-10-27 18:56:31 UTC (rev 15406)
@@ -0,0 +1,61 @@
+/*
+ * Envers. http://www.jboss.org/envers
+ *
+ * Copyright 2008 Red Hat Middleware, LLC. All rights reserved.
+ *
+ * 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, v. 2.1.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT A 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, v.2.1 along with this distribution; if not, write to the Free
+ * Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+ * 02110-1301, USA.
+ *
+ * Red Hat Author(s): Adam Warski
+ */
+package org.jboss.envers.entities.mapper.id;
+
+import org.jboss.envers.ModificationStore;
+import org.jboss.envers.exception.VersionsException;
+
+import java.util.Map;
+import java.util.LinkedHashMap;
+
+/**
+ * @author Adam Warski (adam at warski dot org)
+ */
+public abstract class AbstractCompositeIdMapper extends AbstractIdMapper implements SimpleIdMapperBuilder {
+ protected Map<String, SingleIdMapper> ids;
+ protected String compositeIdClass;
+
+ protected AbstractCompositeIdMapper(String compositeIdClass) {
+ ids = new LinkedHashMap<String, SingleIdMapper>();
+
+ this.compositeIdClass = compositeIdClass;
+ }
+
+ public void add(String propertyName, ModificationStore modStore) {
+ ids.put(propertyName, new SingleIdMapper(propertyName));
+ }
+
+ public Object mapToIdFromMap(Map data) {
+ Object ret;
+ try {
+ ret = Thread.currentThread().getContextClassLoader().loadClass(compositeIdClass).newInstance();
+ } catch (Exception e) {
+ throw new VersionsException(e);
+ }
+
+ for (SingleIdMapper mapper : ids.values()) {
+ mapper.mapToEntityFromMap(ret, data);
+ }
+
+ return ret;
+ }
+}
Added: core/trunk/envers/src/main/java/org/jboss/envers/entities/mapper/id/AbstractIdMapper.java
===================================================================
--- core/trunk/envers/src/main/java/org/jboss/envers/entities/mapper/id/AbstractIdMapper.java (rev 0)
+++ core/trunk/envers/src/main/java/org/jboss/envers/entities/mapper/id/AbstractIdMapper.java 2008-10-27 18:56:31 UTC (rev 15406)
@@ -0,0 +1,86 @@
+/*
+ * Envers. http://www.jboss.org/envers
+ *
+ * Copyright 2008 Red Hat Middleware, LLC. All rights reserved.
+ *
+ * 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, v. 2.1.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT A 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, v.2.1 along with this distribution; if not, write to the Free
+ * Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+ * 02110-1301, USA.
+ *
+ * Red Hat Author(s): Adam Warski
+ */
+package org.jboss.envers.entities.mapper.id;
+
+import org.jboss.envers.tools.query.Parameters;
+
+import java.util.Iterator;
+import java.util.List;
+
+/**
+ * @author Adam Warski (adam at warski dot org)
+ */
+public abstract class AbstractIdMapper implements IdMapper {
+ private Parameters getParametersToUse(Parameters parameters, List<QueryParameterData> paramDatas) {
+ if (paramDatas.size() > 1) {
+ return parameters.addSubParameters("and");
+ } else {
+ return parameters;
+ }
+ }
+
+ public void addIdsEqualToQuery(Parameters parameters, String prefix1, String prefix2) {
+ List<QueryParameterData> paramDatas = mapToQueryParametersFromId(null);
+
+ Parameters parametersToUse = getParametersToUse(parameters, paramDatas);
+
+ for (QueryParameterData paramData : paramDatas) {
+ parametersToUse.addWhere(paramData.getProperty(prefix1), false, "=", paramData.getProperty(prefix2), false);
+ }
+ }
+
+ public void addIdsEqualToQuery(Parameters parameters, String prefix1, IdMapper mapper2, String prefix2) {
+ List<QueryParameterData> paramDatas1 = mapToQueryParametersFromId(null);
+ List<QueryParameterData> paramDatas2 = mapper2.mapToQueryParametersFromId(null);
+
+ Parameters parametersToUse = getParametersToUse(parameters, paramDatas1);
+
+ Iterator<QueryParameterData> paramDataIter1 = paramDatas1.iterator();
+ Iterator<QueryParameterData> paramDataIter2 = paramDatas2.iterator();
+ while (paramDataIter1.hasNext()) {
+ QueryParameterData paramData1 = paramDataIter1.next();
+ QueryParameterData paramData2 = paramDataIter2.next();
+
+ parametersToUse.addWhere(paramData1.getProperty(prefix1), false, "=", paramData2.getProperty(prefix2), false);
+ }
+ }
+
+ public void addIdEqualsToQuery(Parameters parameters, Object id, String prefix, boolean equals) {
+ List<QueryParameterData> paramDatas = mapToQueryParametersFromId(id);
+
+ Parameters parametersToUse = getParametersToUse(parameters, paramDatas);
+
+ for (QueryParameterData paramData : paramDatas) {
+ parametersToUse.addWhereWithParam(paramData.getProperty(prefix), equals ? "=" : "<>", paramData.getValue());
+ }
+ }
+
+ public void addNamedIdEqualsToQuery(Parameters parameters, String prefix, boolean equals) {
+ List<QueryParameterData> paramDatas = mapToQueryParametersFromId(null);
+
+ Parameters parametersToUse = getParametersToUse(parameters, paramDatas);
+
+ for (QueryParameterData paramData : paramDatas) {
+ parametersToUse.addWhereWithNamedParam(paramData.getProperty(prefix), equals ? "=" : "<>", paramData.getQueryParameterName());
+ }
+ }
+}
Added: core/trunk/envers/src/main/java/org/jboss/envers/entities/mapper/id/EmbeddedIdMapper.java
===================================================================
--- core/trunk/envers/src/main/java/org/jboss/envers/entities/mapper/id/EmbeddedIdMapper.java (rev 0)
+++ core/trunk/envers/src/main/java/org/jboss/envers/entities/mapper/id/EmbeddedIdMapper.java 2008-10-27 18:56:31 UTC (rev 15406)
@@ -0,0 +1,110 @@
+/*
+ * Envers. http://www.jboss.org/envers
+ *
+ * Copyright 2008 Red Hat Middleware, LLC. All rights reserved.
+ *
+ * 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, v. 2.1.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT A 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, v.2.1 along with this distribution; if not, write to the Free
+ * Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+ * 02110-1301, USA.
+ *
+ * Red Hat Author(s): Adam Warski
+ */
+package org.jboss.envers.entities.mapper.id;
+
+import org.hibernate.property.Getter;
+import org.hibernate.property.Setter;
+import org.hibernate.util.ReflectHelper;
+import org.jboss.envers.exception.VersionsException;
+import org.jboss.envers.tools.reflection.ReflectionTools;
+
+import java.util.*;
+
+/**
+ * @author Adam Warski (adam at warski dot org)
+ */
+public class EmbeddedIdMapper extends AbstractCompositeIdMapper implements SimpleIdMapperBuilder {
+ private String idPropertyName;
+
+ public EmbeddedIdMapper(String idPropertyName, String compositeIdClass) {
+ super(compositeIdClass);
+
+ this.idPropertyName = idPropertyName;
+ }
+
+ public void mapToMapFromId(Map<String, Object> data, Object obj) {
+ for (IdMapper idMapper : ids.values()) {
+ idMapper.mapToMapFromEntity(data, obj);
+ }
+ }
+
+ public void mapToMapFromEntity(Map<String, Object> data, Object obj) {
+ if (obj == null) {
+ return;
+ }
+
+ Getter getter = ReflectionTools.getGetter(obj.getClass(), idPropertyName);
+ mapToMapFromId(data, getter.get(obj));
+ }
+
+ public void mapToEntityFromMap(Object obj, Map data) {
+ if (data == null || obj == null) {
+ return;
+ }
+
+ Getter getter = ReflectionTools.getGetter(obj.getClass(), idPropertyName);
+ Setter setter = ReflectionTools.getSetter(obj.getClass(), idPropertyName);
+
+ try {
+ Object subObj = ReflectHelper.getDefaultConstructor(getter.getReturnType()).newInstance();
+ setter.set(obj, subObj, null);
+
+ for (IdMapper idMapper : ids.values()) {
+ idMapper.mapToEntityFromMap(subObj, data);
+ }
+ } catch (Exception e) {
+ throw new VersionsException(e);
+ }
+ }
+
+ public IdMapper prefixMappedProperties(String prefix) {
+ EmbeddedIdMapper ret = new EmbeddedIdMapper(idPropertyName, compositeIdClass);
+
+ for (String propertyName : ids.keySet()) {
+ ret.ids.put(propertyName, new SingleIdMapper(propertyName, prefix + propertyName));
+ }
+
+ return ret;
+ }
+
+ public Object mapToIdFromEntity(Object data) {
+ if (data == null) {
+ return null;
+ }
+
+ Getter getter = ReflectionTools.getGetter(data.getClass(), idPropertyName);
+ return getter.get(data);
+ }
+
+ public List<QueryParameterData> mapToQueryParametersFromId(Object obj) {
+ Map<String, Object> data = new LinkedHashMap<String, Object>();
+ mapToMapFromId(data, obj);
+
+ List<QueryParameterData> ret = new ArrayList<QueryParameterData>();
+
+ for (Map.Entry<String, Object> propertyData : data.entrySet()) {
+ ret.add(new QueryParameterData(propertyData.getKey(), propertyData.getValue()));
+ }
+
+ return ret;
+ }
+}
Added: core/trunk/envers/src/main/java/org/jboss/envers/entities/mapper/id/IdMapper.java
===================================================================
--- core/trunk/envers/src/main/java/org/jboss/envers/entities/mapper/id/IdMapper.java (rev 0)
+++ core/trunk/envers/src/main/java/org/jboss/envers/entities/mapper/id/IdMapper.java 2008-10-27 18:56:31 UTC (rev 15406)
@@ -0,0 +1,97 @@
+/*
+ * Envers. http://www.jboss.org/envers
+ *
+ * Copyright 2008 Red Hat Middleware, LLC. All rights reserved.
+ *
+ * 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, v. 2.1.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT A 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, v.2.1 along with this distribution; if not, write to the Free
+ * Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+ * 02110-1301, USA.
+ *
+ * Red Hat Author(s): Adam Warski
+ */
+package org.jboss.envers.entities.mapper.id;
+
+import org.jboss.envers.tools.query.Parameters;
+
+import java.util.Map;
+import java.util.List;
+
+/**
+ * @author Adam Warski (adam at warski dot org)
+ */
+public interface IdMapper {
+ void mapToMapFromId(Map<String, Object> data, Object obj);
+
+ void mapToMapFromEntity(Map<String, Object> data, Object obj);
+
+ void mapToEntityFromMap(Object obj, Map data);
+
+ Object mapToIdFromEntity(Object data);
+
+ Object mapToIdFromMap(Map data);
+
+ /**
+ * Creates a mapper with all mapped properties prefixed. A mapped property is a property which
+ * is directly mapped to values (not composite).
+ * @param prefix Prefix to add to mapped properties
+ * @return A copy of the current property mapper, with mapped properties prefixed.
+ */
+ IdMapper prefixMappedProperties(String prefix);
+
+ /**
+ * @param obj Id from which to map.
+ * @return A set parameter data, needed to build a query basing on the given id.
+ */
+ List<QueryParameterData> mapToQueryParametersFromId(Object obj);
+
+ /**
+ * Adds query statements, which contains restrictions, which express the property that the id of the entity
+ * with alias prefix1, is equal to the id of the entity with alias prefix2 (the entity is the same).
+ * @param parameters Parameters, to which to add the statements.
+ * @param prefix1 First alias of the entity + prefix to add to the properties.
+ * @param prefix2 Second alias of the entity + prefix to add to the properties.
+ */
+ void addIdsEqualToQuery(Parameters parameters, String prefix1, String prefix2);
+
+ /**
+ * Adds query statements, which contains restrictions, which express the property that the id of the entity
+ * with alias prefix1, is equal to the id of the entity with alias prefix2 mapped by the second mapper
+ * (the second mapper must be for the same entity, but it can have, for example, prefixed properties).
+ * @param parameters Parameters, to which to add the statements.
+ * @param prefix1 First alias of the entity + prefix to add to the properties.
+ * @param mapper2 Second mapper for the same entity, which will be used to get properties for the right side
+ * of the equation.
+ * @param prefix2 Second alias of the entity + prefix to add to the properties.
+ */
+ void addIdsEqualToQuery(Parameters parameters, String prefix1, IdMapper mapper2, String prefix2);
+
+ /**
+ * Adds query statements, which contains restrictions, which express the property that the id of the entity
+ * with alias prefix, is equal to the given object.
+ * @param parameters Parameters, to which to add the statements.
+ * @param id Value of id.
+ * @param prefix Prefix to add to the properties (may be null).
+ * @param equals Should this query express the "=" relation or the "<>" relation.
+ */
+ void addIdEqualsToQuery(Parameters parameters, Object id, String prefix, boolean equals);
+
+ /**
+ * Adds query statements, which contains named parameters, which express the property that the id of the entity
+ * with alias prefix, is equal to the given object. It is the responsibility of the using method to read
+ * parameter values from the id and specify them on the final query object.
+ * @param parameters Parameters, to which to add the statements.
+ * @param prefix Prefix to add to the properties (may be null).
+ * @param equals Should this query express the "=" relation or the "<>" relation.
+ */
+ void addNamedIdEqualsToQuery(Parameters parameters, String prefix, boolean equals);
+}
Added: core/trunk/envers/src/main/java/org/jboss/envers/entities/mapper/id/MultipleIdMapper.java
===================================================================
--- core/trunk/envers/src/main/java/org/jboss/envers/entities/mapper/id/MultipleIdMapper.java (rev 0)
+++ core/trunk/envers/src/main/java/org/jboss/envers/entities/mapper/id/MultipleIdMapper.java 2008-10-27 18:56:31 UTC (rev 15406)
@@ -0,0 +1,93 @@
+/*
+ * Envers. http://www.jboss.org/envers
+ *
+ * Copyright 2008 Red Hat Middleware, LLC. All rights reserved.
+ *
+ * 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, v. 2.1.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT A 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, v.2.1 along with this distribution; if not, write to the Free
+ * Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+ * 02110-1301, USA.
+ *
+ * Red Hat Author(s): Adam Warski
+ */
+package org.jboss.envers.entities.mapper.id;
+
+import org.jboss.envers.exception.VersionsException;
+
+import java.util.*;
+
+/**
+ * @author Adam Warski (adam at warski dot org)
+ */
+public class MultipleIdMapper extends AbstractCompositeIdMapper implements SimpleIdMapperBuilder {
+ public MultipleIdMapper(String compositeIdClass) {
+ super(compositeIdClass);
+ }
+
+ public void mapToMapFromId(Map<String, Object> data, Object obj) {
+ for (IdMapper idMapper : ids.values()) {
+ idMapper.mapToMapFromEntity(data, obj);
+ }
+ }
+
+ public void mapToMapFromEntity(Map<String, Object> data, Object obj) {
+ mapToMapFromId(data, obj);
+ }
+
+ public void mapToEntityFromMap(Object obj, Map data) {
+ for (IdMapper idMapper : ids.values()) {
+ idMapper.mapToEntityFromMap(obj, data);
+ }
+ }
+
+ public IdMapper prefixMappedProperties(String prefix) {
+ MultipleIdMapper ret = new MultipleIdMapper(compositeIdClass);
+
+ for (String propertyName : ids.keySet()) {
+ ret.ids.put(propertyName, new SingleIdMapper(propertyName, prefix + propertyName));
+ }
+
+ return ret;
+ }
+
+ public Object mapToIdFromEntity(Object data) {
+ if (data == null) {
+ return null;
+ }
+
+ Object ret;
+ try {
+ ret = Thread.currentThread().getContextClassLoader().loadClass(compositeIdClass).newInstance();
+ } catch (Exception e) {
+ throw new VersionsException(e);
+ }
+
+ for (SingleIdMapper mapper : ids.values()) {
+ mapper.mapToEntityFromEntity(ret, data);
+ }
+
+ return ret;
+ }
+
+ public List<QueryParameterData> mapToQueryParametersFromId(Object obj) {
+ Map<String, Object> data = new LinkedHashMap<String, Object>();
+ mapToMapFromId(data, obj);
+
+ List<QueryParameterData> ret = new ArrayList<QueryParameterData>();
+
+ for (Map.Entry<String, Object> propertyData : data.entrySet()) {
+ ret.add(new QueryParameterData(propertyData.getKey(), propertyData.getValue()));
+ }
+
+ return ret;
+ }
+}
Added: core/trunk/envers/src/main/java/org/jboss/envers/entities/mapper/id/QueryParameterData.java
===================================================================
--- core/trunk/envers/src/main/java/org/jboss/envers/entities/mapper/id/QueryParameterData.java (rev 0)
+++ core/trunk/envers/src/main/java/org/jboss/envers/entities/mapper/id/QueryParameterData.java 2008-10-27 18:56:31 UTC (rev 15406)
@@ -0,0 +1,73 @@
+/*
+ * Envers. http://www.jboss.org/envers
+ *
+ * Copyright 2008 Red Hat Middleware, LLC. All rights reserved.
+ *
+ * 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, v. 2.1.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT A 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, v.2.1 along with this distribution; if not, write to the Free
+ * Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+ * 02110-1301, USA.
+ *
+ * Red Hat Author(s): Adam Warski
+ */
+package org.jboss.envers.entities.mapper.id;
+
+import org.hibernate.Query;
+
+/**
+ * @author Adam Warski (adam at warski dot org)
+ */
+public class QueryParameterData {
+ private String flatEntityPropertyName;
+ private Object value;
+
+ public QueryParameterData(String flatEntityPropertyName, Object value) {
+ this.flatEntityPropertyName = flatEntityPropertyName;
+ this.value = value;
+ }
+
+ public String getProperty(String prefix) {
+ if (prefix != null) {
+ return prefix + "." + flatEntityPropertyName;
+ } else {
+ return flatEntityPropertyName;
+ }
+ }
+
+ public Object getValue() {
+ return value;
+ }
+
+ public void setParameterValue(Query query) {
+ query.setParameter(flatEntityPropertyName, value);
+ }
+
+ public String getQueryParameterName() {
+ return flatEntityPropertyName;
+ }
+
+ public boolean equals(Object o) {
+ if (this == o) return true;
+ if (!(o instanceof QueryParameterData)) return false;
+
+ QueryParameterData that = (QueryParameterData) o;
+
+ if (flatEntityPropertyName != null ? !flatEntityPropertyName.equals(that.flatEntityPropertyName) : that.flatEntityPropertyName != null)
+ return false;
+
+ return true;
+ }
+
+ public int hashCode() {
+ return (flatEntityPropertyName != null ? flatEntityPropertyName.hashCode() : 0);
+ }
+}
Added: core/trunk/envers/src/main/java/org/jboss/envers/entities/mapper/id/SimpleIdMapperBuilder.java
===================================================================
--- core/trunk/envers/src/main/java/org/jboss/envers/entities/mapper/id/SimpleIdMapperBuilder.java (rev 0)
+++ core/trunk/envers/src/main/java/org/jboss/envers/entities/mapper/id/SimpleIdMapperBuilder.java 2008-10-27 18:56:31 UTC (rev 15406)
@@ -0,0 +1,30 @@
+/*
+ * Envers. http://www.jboss.org/envers
+ *
+ * Copyright 2008 Red Hat Middleware, LLC. All rights reserved.
+ *
+ * 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, v. 2.1.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT A 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, v.2.1 along with this distribution; if not, write to the Free
+ * Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+ * 02110-1301, USA.
+ *
+ * Red Hat Author(s): Adam Warski
+ */
+package org.jboss.envers.entities.mapper.id;
+
+import org.jboss.envers.entities.mapper.SimpleMapperBuilder;
+
+/**
+ * @author Adam Warski (adam at warski dot org)
+ */
+public interface SimpleIdMapperBuilder extends IdMapper, SimpleMapperBuilder {
+}
Added: core/trunk/envers/src/main/java/org/jboss/envers/entities/mapper/id/SingleIdMapper.java
===================================================================
--- core/trunk/envers/src/main/java/org/jboss/envers/entities/mapper/id/SingleIdMapper.java (rev 0)
+++ core/trunk/envers/src/main/java/org/jboss/envers/entities/mapper/id/SingleIdMapper.java 2008-10-27 18:56:31 UTC (rev 15406)
@@ -0,0 +1,123 @@
+/*
+ * Envers. http://www.jboss.org/envers
+ *
+ * Copyright 2008 Red Hat Middleware, LLC. All rights reserved.
+ *
+ * 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, v. 2.1.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT A 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, v.2.1 along with this distribution; if not, write to the Free
+ * Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+ * 02110-1301, USA.
+ *
+ * Red Hat Author(s): Adam Warski
+ */
+package org.jboss.envers.entities.mapper.id;
+
+import org.jboss.envers.ModificationStore;
+import org.jboss.envers.tools.reflection.ReflectionTools;
+import org.jboss.envers.exception.VersionsException;
+import org.hibernate.property.Setter;
+import org.hibernate.property.Getter;
+
+import java.util.*;
+
+/**
+ * @author Adam Warski (adam at warski dot org)
+ */
+public class SingleIdMapper extends AbstractIdMapper implements SimpleIdMapperBuilder {
+ private String beanPropertyName;
+ private String propertyName;
+
+ public SingleIdMapper() {
+ }
+
+ public SingleIdMapper(String beanPropertyName, String propertyName) {
+ this.beanPropertyName = beanPropertyName;
+ this.propertyName = propertyName;
+ }
+
+ public SingleIdMapper(String propertyName) {
+ this.beanPropertyName = propertyName;
+ this.propertyName = propertyName;
+ }
+
+ public void add(String propertyName, ModificationStore modStore) {
+ if (this.propertyName != null) {
+ throw new VersionsException("Only one property can be added!");
+ }
+
+ this.propertyName = propertyName;
+ this.beanPropertyName = propertyName;
+ }
+
+ public void mapToEntityFromMap(Object obj, Map data) {
+ if (data == null || obj == null) {
+ return;
+ }
+
+ Setter setter = ReflectionTools.getSetter(obj.getClass(), beanPropertyName);
+ setter.set(obj, data.get(propertyName), null);
+ }
+
+ public Object mapToIdFromMap(Map data) {
+ if (data == null) {
+ return null;
+ }
+
+ return data.get(propertyName);
+ }
+
+ public Object mapToIdFromEntity(Object data) {
+ if (data == null) {
+ return null;
+ }
+
+ Getter getter = ReflectionTools.getGetter(data.getClass(), beanPropertyName);
+ return getter.get(data);
+ }
+
+ public void mapToMapFromId(Map<String, Object> data, Object obj) {
+ if (data != null) {
+ data.put(propertyName, obj);
+ }
+ }
+
+ public void mapToMapFromEntity(Map<String, Object> data, Object obj) {
+ if (obj == null) {
+ data.put(propertyName, null);
+ } else {
+ Getter getter = ReflectionTools.getGetter(obj.getClass(), beanPropertyName);
+ data.put(propertyName, getter.get(obj));
+ }
+ }
+
+ public void mapToEntityFromEntity(Object objTo, Object objFrom) {
+ if (objTo == null || objFrom == null) {
+ return;
+ }
+
+ Getter getter = ReflectionTools.getGetter(objFrom.getClass(), beanPropertyName);
+ Setter setter = ReflectionTools.getSetter(objTo.getClass(), beanPropertyName);
+ setter.set(objTo, getter.get(objFrom), null);
+ }
+
+ public IdMapper prefixMappedProperties(String prefix) {
+ return new SingleIdMapper(propertyName, prefix + propertyName);
+ }
+
+ public List<QueryParameterData> mapToQueryParametersFromId(Object obj) {
+ List<QueryParameterData> ret = new ArrayList<QueryParameterData>();
+
+ ret.add(new QueryParameterData(propertyName, obj));
+
+ return ret;
+ }
+}
Added: core/trunk/envers/src/main/java/org/jboss/envers/entities/mapper/relation/AbstractCollectionMapper.java
===================================================================
--- core/trunk/envers/src/main/java/org/jboss/envers/entities/mapper/relation/AbstractCollectionMapper.java (rev 0)
+++ core/trunk/envers/src/main/java/org/jboss/envers/entities/mapper/relation/AbstractCollectionMapper.java 2008-10-27 18:56:31 UTC (rev 15406)
@@ -0,0 +1,145 @@
+/*
+ * JBoss, Home of Professional Open Source
+ *
+ * Copyright 2008, Red Hat Middleware LLC, and others contributors as indicated
+ * by the @authors tag. All rights reserved.
+ *
+ * See the copyright.txt in the distribution for a full listing of individual
+ * contributors. 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, v. 2.1.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT A 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, v.2.1 along with this distribution; if not, write to the Free
+ * Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+ * 02110-1301, USA.
+ *
+ * Red Hat Author(s): Adam Warski
+ */
+package org.jboss.envers.entities.mapper.relation;
+
+import org.jboss.envers.entities.mapper.PersistentCollectionChangeData;
+import org.jboss.envers.entities.mapper.PropertyMapper;
+import org.jboss.envers.entities.mapper.relation.lazy.initializor.Initializor;
+import org.jboss.envers.RevisionType;
+import org.jboss.envers.exception.VersionsException;
+import org.jboss.envers.tools.reflection.ReflectionTools;
+import org.jboss.envers.reader.VersionsReaderImplementor;
+import org.jboss.envers.configuration.VersionsConfiguration;
+import org.hibernate.collection.PersistentCollection;
+import org.hibernate.property.Setter;
+
+import java.util.*;
+import java.io.Serializable;
+import java.lang.reflect.InvocationTargetException;
+import java.lang.reflect.Constructor;
+
+/**
+ * @author Adam Warski (adam at warski dot org)
+ */
+public abstract class AbstractCollectionMapper<T> implements PropertyMapper {
+ protected final CommonCollectionMapperData commonCollectionMapperData;
+ protected final Class<? extends T> collectionClass;
+
+ private final Constructor<? extends T> proxyConstructor;
+
+ protected AbstractCollectionMapper(CommonCollectionMapperData commonCollectionMapperData,
+ Class<? extends T> collectionClass, Class<? extends T> proxyClass) {
+ this.commonCollectionMapperData = commonCollectionMapperData;
+ this.collectionClass = collectionClass;
+
+ try {
+ proxyConstructor = proxyClass.getConstructor(Initializor.class);
+ } catch (NoSuchMethodException e) {
+ throw new VersionsException(e);
+ }
+ }
+
+ protected abstract Collection getNewCollectionContent(PersistentCollection newCollection);
+ protected abstract Collection getOldCollectionContent(Serializable oldCollection);
+ protected abstract Object getElement(Object changedObject);
+
+ /**
+ * Maps the changed collection element to the given map.
+ * @param data Where to map the data.
+ * @param changed The changed collection element to map.
+ */
+ protected abstract void mapToMapFromObject(Map<String, Object> data, Object changed);
+
+ private void addCollectionChanges(List<PersistentCollectionChangeData> collectionChanges, Set<Object> changed,
+ RevisionType revisionType, Serializable id) {
+ for (Object changedObj : changed) {
+ Map<String, Object> entityData = new HashMap<String, Object>();
+ Map<String, Object> originalId = new HashMap<String, Object>();
+ entityData.put(commonCollectionMapperData.getVerEntCfg().getOriginalIdPropName(), originalId);
+
+ collectionChanges.add(new PersistentCollectionChangeData(
+ commonCollectionMapperData.getVersionsMiddleEntityName(), entityData, getElement(changedObj)));
+ // Mapping the collection owner's id.
+ commonCollectionMapperData.getReferencingIdData().getPrefixedMapper().mapToMapFromId(originalId, id);
+
+ // Mapping collection element and index (if present).
+ mapToMapFromObject(originalId, changedObj);
+
+ entityData.put(commonCollectionMapperData.getVerEntCfg().getRevisionTypePropName(), revisionType);
+ }
+ }
+
+ @SuppressWarnings({"unchecked"})
+ public List<PersistentCollectionChangeData> mapCollectionChanges(String referencingPropertyName,
+ PersistentCollection newColl,
+ Serializable oldColl, Serializable id) {
+ if (!commonCollectionMapperData.getCollectionReferencingPropertyName().equals(referencingPropertyName)) {
+ return null;
+ }
+
+ List<PersistentCollectionChangeData> collectionChanges = new ArrayList<PersistentCollectionChangeData>();
+
+ // Comparing new and old collection content.
+ Collection newCollection = getNewCollectionContent(newColl);
+ Collection oldCollection = getOldCollectionContent(oldColl);
+
+ Set<Object> added = new HashSet<Object>();
+ if (newColl != null) { added.addAll(newCollection); }
+ if (oldColl != null) { added.removeAll(oldCollection); }
+
+ addCollectionChanges(collectionChanges, added, RevisionType.ADD, id);
+
+ Set<Object> deleted = new HashSet<Object>();
+ if (oldColl != null) { deleted.addAll(oldCollection); }
+ if (newColl != null) { deleted.removeAll(newCollection); }
+
+ addCollectionChanges(collectionChanges, deleted, RevisionType.DEL, id);
+
+ return collectionChanges;
+ }
+
+ public boolean mapToMapFromEntity(Map<String, Object> data, Object newObj, Object oldObj) {
+ // Changes are mapped in the "mapCollectionChanges" method.
+ return false;
+ }
+
+ protected abstract Initializor<T> getInitializor(VersionsConfiguration verCfg,
+ VersionsReaderImplementor versionsReader, Object primaryKey,
+ Number revision);
+
+ public void mapToEntityFromMap(VersionsConfiguration verCfg, Object obj, Map data, Object primaryKey,
+ VersionsReaderImplementor versionsReader, Number revision) {
+ Setter setter = ReflectionTools.getSetter(obj.getClass(),
+ commonCollectionMapperData.getCollectionReferencingPropertyName());
+ try {
+ setter.set(obj, proxyConstructor.newInstance(getInitializor(verCfg, versionsReader, primaryKey, revision)), null);
+ } catch (InstantiationException e) {
+ throw new VersionsException(e);
+ } catch (IllegalAccessException e) {
+ throw new VersionsException(e);
+ } catch (InvocationTargetException e) {
+ throw new VersionsException(e);
+ }
+ }
+}
Added: core/trunk/envers/src/main/java/org/jboss/envers/entities/mapper/relation/BasicCollectionMapper.java
===================================================================
--- core/trunk/envers/src/main/java/org/jboss/envers/entities/mapper/relation/BasicCollectionMapper.java (rev 0)
+++ core/trunk/envers/src/main/java/org/jboss/envers/entities/mapper/relation/BasicCollectionMapper.java 2008-10-27 18:56:31 UTC (rev 15406)
@@ -0,0 +1,77 @@
+/*
+ * JBoss, Home of Professional Open Source
+ *
+ * Copyright 2008, Red Hat Middleware LLC, and others contributors as indicated
+ * by the @authors tag. All rights reserved.
+ *
+ * See the copyright.txt in the distribution for a full listing of individual
+ * contributors. 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, v. 2.1.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT A 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, v.2.1 along with this distribution; if not, write to the Free
+ * Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+ * 02110-1301, USA.
+ *
+ * Red Hat Author(s): Adam Warski
+ */
+package org.jboss.envers.entities.mapper.relation;
+
+import org.jboss.envers.entities.mapper.PropertyMapper;
+import org.jboss.envers.entities.mapper.relation.lazy.initializor.Initializor;
+import org.jboss.envers.entities.mapper.relation.lazy.initializor.BasicCollectionInitializor;
+import org.jboss.envers.configuration.VersionsConfiguration;
+import org.jboss.envers.reader.VersionsReaderImplementor;
+import org.hibernate.collection.PersistentCollection;
+
+import java.util.Map;
+import java.util.Collection;
+import java.io.Serializable;
+
+/**
+ * @author Adam Warski (adam at warski dot org)
+ */
+public final class BasicCollectionMapper<T extends Collection> extends AbstractCollectionMapper<T> implements PropertyMapper {
+ private final MiddleComponentData elementComponentData;
+
+ public BasicCollectionMapper(CommonCollectionMapperData commonCollectionMapperData,
+ Class<? extends T> collectionClass, Class<? extends T> proxyClass,
+ MiddleComponentData elementComponentData) {
+ super(commonCollectionMapperData, collectionClass, proxyClass);
+ this.elementComponentData = elementComponentData;
+ }
+
+ protected Initializor<T> getInitializor(VersionsConfiguration verCfg, VersionsReaderImplementor versionsReader,
+ Object primaryKey, Number revision) {
+ return new BasicCollectionInitializor<T>(verCfg, versionsReader, commonCollectionMapperData.getQueryGenerator(),
+ primaryKey, revision, collectionClass, elementComponentData);
+ }
+
+ protected Collection getNewCollectionContent(PersistentCollection newCollection) {
+ return (Collection) newCollection;
+ }
+
+ protected Collection getOldCollectionContent(Serializable oldCollection) {
+ if (oldCollection == null) {
+ return null;
+ } else if (oldCollection instanceof Map) {
+ return ((Map) oldCollection).keySet();
+ } else {
+ return (Collection) oldCollection;
+ }
+ }
+
+ protected void mapToMapFromObject(Map<String, Object> data, Object changed) {
+ elementComponentData.getComponentMapper().mapToMapFromObject(data, changed);
+ }
+
+ protected Object getElement(Object changedObject) {
+ return changedObject;
+ }
+}
Added: core/trunk/envers/src/main/java/org/jboss/envers/entities/mapper/relation/CommonCollectionMapperData.java
===================================================================
--- core/trunk/envers/src/main/java/org/jboss/envers/entities/mapper/relation/CommonCollectionMapperData.java (rev 0)
+++ core/trunk/envers/src/main/java/org/jboss/envers/entities/mapper/relation/CommonCollectionMapperData.java 2008-10-27 18:56:31 UTC (rev 15406)
@@ -0,0 +1,69 @@
+/*
+ * JBoss, Home of Professional Open Source
+ *
+ * Copyright 2008, Red Hat Middleware LLC, and others contributors as indicated
+ * by the @authors tag. All rights reserved.
+ *
+ * See the copyright.txt in the distribution for a full listing of individual
+ * contributors. 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, v. 2.1.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT A 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, v.2.1 along with this distribution; if not, write to the Free
+ * Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+ * 02110-1301, USA.
+ *
+ * Red Hat Author(s): Adam Warski
+ */
+package org.jboss.envers.entities.mapper.relation;
+
+import org.jboss.envers.configuration.VersionsEntitiesConfiguration;
+import org.jboss.envers.entities.mapper.relation.query.RelationQueryGenerator;
+
+/**
+ * Data that is used by all collection mappers, regardless of the type.
+ * @author Adam Warski (adam at warski dot org)
+ */
+public final class CommonCollectionMapperData {
+ private final VersionsEntitiesConfiguration verEntCfg;
+ private final String versionsMiddleEntityName;
+ private final String collectionReferencingPropertyName;
+ private final MiddleIdData referencingIdData;
+ private final RelationQueryGenerator queryGenerator;
+
+ public CommonCollectionMapperData(VersionsEntitiesConfiguration verEntCfg, String versionsMiddleEntityName,
+ String collectionReferencingPropertyName, MiddleIdData referencingIdData,
+ RelationQueryGenerator queryGenerator) {
+ this.verEntCfg = verEntCfg;
+ this.versionsMiddleEntityName = versionsMiddleEntityName;
+ this.collectionReferencingPropertyName = collectionReferencingPropertyName;
+ this.referencingIdData = referencingIdData;
+ this.queryGenerator = queryGenerator;
+ }
+
+ public VersionsEntitiesConfiguration getVerEntCfg() {
+ return verEntCfg;
+ }
+
+ public String getVersionsMiddleEntityName() {
+ return versionsMiddleEntityName;
+ }
+
+ public String getCollectionReferencingPropertyName() {
+ return collectionReferencingPropertyName;
+ }
+
+ public MiddleIdData getReferencingIdData() {
+ return referencingIdData;
+ }
+
+ public RelationQueryGenerator getQueryGenerator() {
+ return queryGenerator;
+ }
+}
Added: core/trunk/envers/src/main/java/org/jboss/envers/entities/mapper/relation/ListCollectionMapper.java
===================================================================
--- core/trunk/envers/src/main/java/org/jboss/envers/entities/mapper/relation/ListCollectionMapper.java (rev 0)
+++ core/trunk/envers/src/main/java/org/jboss/envers/entities/mapper/relation/ListCollectionMapper.java 2008-10-27 18:56:31 UTC (rev 15406)
@@ -0,0 +1,90 @@
+/*
+ * JBoss, Home of Professional Open Source
+ *
+ * Copyright 2008, Red Hat Middleware LLC, and others contributors as indicated
+ * by the @authors tag. All rights reserved.
+ *
+ * See the copyright.txt in the distribution for a full listing of individual
+ * contributors. 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, v. 2.1.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT A 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, v.2.1 along with this distribution; if not, write to the Free
+ * Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+ * 02110-1301, USA.
+ *
+ * Red Hat Author(s): Adam Warski
+ */
+package org.jboss.envers.entities.mapper.relation;
+
+import org.jboss.envers.entities.mapper.PropertyMapper;
+import org.jboss.envers.entities.mapper.relation.lazy.initializor.Initializor;
+import org.jboss.envers.entities.mapper.relation.lazy.initializor.ListCollectionInitializor;
+import org.jboss.envers.entities.mapper.relation.lazy.proxy.ListProxy;
+import org.jboss.envers.configuration.VersionsConfiguration;
+import org.jboss.envers.reader.VersionsReaderImplementor;
+import org.jboss.envers.tools.Tools;
+import org.jboss.envers.tools.Pair;
+import org.hibernate.collection.PersistentCollection;
+
+import java.util.Collection;
+import java.util.List;
+import java.util.Map;
+import java.io.Serializable;
+
+/**
+ * @author Adam Warski (adam at warski dot org)
+ */
+public final class ListCollectionMapper extends AbstractCollectionMapper<List> implements PropertyMapper {
+ private final MiddleComponentData elementComponentData;
+ private final MiddleComponentData indexComponentData;
+
+ public ListCollectionMapper(CommonCollectionMapperData commonCollectionMapperData,
+ MiddleComponentData elementComponentData, MiddleComponentData indexComponentData) {
+ super(commonCollectionMapperData, List.class, ListProxy.class);
+ this.elementComponentData = elementComponentData;
+ this.indexComponentData = indexComponentData;
+ }
+
+ protected Initializor<List> getInitializor(VersionsConfiguration verCfg, VersionsReaderImplementor versionsReader,
+ Object primaryKey, Number revision) {
+ return new ListCollectionInitializor(verCfg, versionsReader, commonCollectionMapperData.getQueryGenerator(),
+ primaryKey, revision, elementComponentData, indexComponentData);
+ }
+
+ @SuppressWarnings({"unchecked"})
+ protected Collection getNewCollectionContent(PersistentCollection newCollection) {
+ if (newCollection == null) {
+ return null;
+ } else {
+ return Tools.listToIndexElementPairList((List<Object>) newCollection);
+ }
+ }
+
+ @SuppressWarnings({"unchecked"})
+ protected Collection getOldCollectionContent(Serializable oldCollection) {
+ if (oldCollection == null) {
+ return null;
+ } else {
+ return Tools.listToIndexElementPairList((List<Object>) oldCollection);
+ }
+ }
+
+ @SuppressWarnings({"unchecked"})
+ protected void mapToMapFromObject(Map<String, Object> data, Object changed) {
+ Pair<Integer, Object> indexValuePair = (Pair<Integer, Object>) changed;
+ elementComponentData.getComponentMapper().mapToMapFromObject(data, indexValuePair.getSecond());
+ indexComponentData.getComponentMapper().mapToMapFromObject(data, indexValuePair.getFirst());
+ }
+
+ @SuppressWarnings({"unchecked"})
+ protected Object getElement(Object changedObject) {
+ return ((Pair<Integer, Object>) changedObject).getFirst();
+ }
+}
\ No newline at end of file
Added: core/trunk/envers/src/main/java/org/jboss/envers/entities/mapper/relation/MapCollectionMapper.java
===================================================================
--- core/trunk/envers/src/main/java/org/jboss/envers/entities/mapper/relation/MapCollectionMapper.java (rev 0)
+++ core/trunk/envers/src/main/java/org/jboss/envers/entities/mapper/relation/MapCollectionMapper.java 2008-10-27 18:56:31 UTC (rev 15406)
@@ -0,0 +1,82 @@
+/*
+ * JBoss, Home of Professional Open Source
+ *
+ * Copyright 2008, Red Hat Middleware LLC, and others contributors as indicated
+ * by the @authors tag. All rights reserved.
+ *
+ * See the copyright.txt in the distribution for a full listing of individual
+ * contributors. 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, v. 2.1.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT A 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, v.2.1 along with this distribution; if not, write to the Free
+ * Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+ * 02110-1301, USA.
+ *
+ * Red Hat Author(s): Adam Warski
+ */
+package org.jboss.envers.entities.mapper.relation;
+
+import org.jboss.envers.entities.mapper.PropertyMapper;
+import org.jboss.envers.entities.mapper.relation.lazy.initializor.Initializor;
+import org.jboss.envers.entities.mapper.relation.lazy.initializor.MapCollectionInitializor;
+import org.jboss.envers.configuration.VersionsConfiguration;
+import org.jboss.envers.reader.VersionsReaderImplementor;
+import org.hibernate.collection.PersistentCollection;
+
+import java.util.Map;
+import java.util.Collection;
+import java.io.Serializable;
+
+/**
+ * @author Adam Warski (adam at warski dot org)
+ */
+public final class MapCollectionMapper<T extends Map> extends AbstractCollectionMapper<T> implements PropertyMapper {
+ private final MiddleComponentData elementComponentData;
+ private final MiddleComponentData indexComponentData;
+
+ public MapCollectionMapper(CommonCollectionMapperData commonCollectionMapperData,
+ Class<? extends T> collectionClass, Class<? extends T> proxyClass,
+ MiddleComponentData elementComponentData, MiddleComponentData indexComponentData) {
+ super(commonCollectionMapperData, collectionClass, proxyClass);
+ this.elementComponentData = elementComponentData;
+ this.indexComponentData = indexComponentData;
+ }
+
+ protected Initializor<T> getInitializor(VersionsConfiguration verCfg, VersionsReaderImplementor versionsReader,
+ Object primaryKey, Number revision) {
+ return new MapCollectionInitializor<T>(verCfg, versionsReader, commonCollectionMapperData.getQueryGenerator(),
+ primaryKey, revision, collectionClass, elementComponentData, indexComponentData);
+ }
+
+ protected Collection getNewCollectionContent(PersistentCollection newCollection) {
+ if (newCollection == null) {
+ return null;
+ } else {
+ return ((Map) newCollection).entrySet();
+ }
+ }
+
+ protected Collection getOldCollectionContent(Serializable oldCollection) {
+ if (oldCollection == null) {
+ return null;
+ } else {
+ return ((Map) oldCollection).entrySet();
+ }
+ }
+
+ protected void mapToMapFromObject(Map<String, Object> data, Object changed) {
+ elementComponentData.getComponentMapper().mapToMapFromObject(data, ((Map.Entry) changed).getValue());
+ indexComponentData.getComponentMapper().mapToMapFromObject(data, ((Map.Entry) changed).getKey());
+ }
+
+ protected Object getElement(Object changedObject) {
+ return ((Map.Entry) changedObject).getValue();
+ }
+}
\ No newline at end of file
Added: core/trunk/envers/src/main/java/org/jboss/envers/entities/mapper/relation/MiddleComponentData.java
===================================================================
--- core/trunk/envers/src/main/java/org/jboss/envers/entities/mapper/relation/MiddleComponentData.java (rev 0)
+++ core/trunk/envers/src/main/java/org/jboss/envers/entities/mapper/relation/MiddleComponentData.java 2008-10-27 18:56:31 UTC (rev 15406)
@@ -0,0 +1,51 @@
+/*
+ * JBoss, Home of Professional Open Source
+ *
+ * Copyright 2008, Red Hat Middleware LLC, and others contributors as indicated
+ * by the @authors tag. All rights reserved.
+ *
+ * See the copyright.txt in the distribution for a full listing of individual
+ * contributors. 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, v. 2.1.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT A 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, v.2.1 along with this distribution; if not, write to the Free
+ * Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+ * 02110-1301, USA.
+ *
+ * Red Hat Author(s): Adam Warski
+ */
+package org.jboss.envers.entities.mapper.relation;
+
+import org.jboss.envers.entities.mapper.relation.component.MiddleComponentMapper;
+
+/**
+ * A data holder for a middle relation component (which is either the collection element or index):
+ * - component mapper used to map the component to and from versions entities
+ * - an index, which specifies in which element of the array returned by the query for reading the collection the data
+ * of the component is
+ * @author Adam Warski (adam at warski dot org)
+ */
+public final class MiddleComponentData {
+ private final MiddleComponentMapper componentMapper;
+ private final int componentIndex;
+
+ public MiddleComponentData(MiddleComponentMapper componentMapper, int componentIndex) {
+ this.componentMapper = componentMapper;
+ this.componentIndex = componentIndex;
+ }
+
+ public MiddleComponentMapper getComponentMapper() {
+ return componentMapper;
+ }
+
+ public int getComponentIndex() {
+ return componentIndex;
+ }
+}
Added: core/trunk/envers/src/main/java/org/jboss/envers/entities/mapper/relation/MiddleIdData.java
===================================================================
--- core/trunk/envers/src/main/java/org/jboss/envers/entities/mapper/relation/MiddleIdData.java (rev 0)
+++ core/trunk/envers/src/main/java/org/jboss/envers/entities/mapper/relation/MiddleIdData.java 2008-10-27 18:56:31 UTC (rev 15406)
@@ -0,0 +1,76 @@
+/*
+ * JBoss, Home of Professional Open Source
+ *
+ * Copyright 2008, Red Hat Middleware LLC, and others contributors as indicated
+ * by the @authors tag. All rights reserved.
+ *
+ * See the copyright.txt in the distribution for a full listing of individual
+ * contributors. 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, v. 2.1.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT A 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, v.2.1 along with this distribution; if not, write to the Free
+ * Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+ * 02110-1301, USA.
+ *
+ * Red Hat Author(s): Adam Warski
+ */
+package org.jboss.envers.entities.mapper.relation;
+
+import org.jboss.envers.entities.mapper.id.IdMapper;
+import org.jboss.envers.entities.IdMappingData;
+import org.jboss.envers.configuration.VersionsEntitiesConfiguration;
+
+/**
+ * A class holding information about ids, which form a virtual "relation" from a middle-table. Middle-tables are used
+ * when mapping collections.
+ * @author Adam Warski (adam at warski dot org)
+ */
+public final class MiddleIdData {
+ /**
+ * Original id mapper of the related entity.
+ */
+ private final IdMapper originalMapper;
+ /**
+ * Prefixed id mapper (with the names for the id fields that are used in the middle table) of the related entity.
+ */
+ private final IdMapper prefixedMapper;
+ /**
+ * Name of the related entity.
+ */
+ private final String entityName;
+ /**
+ * Versions name of the related entity.
+ */
+ private final String versionsEntityName;
+
+ public MiddleIdData(VersionsEntitiesConfiguration verEntCfg, IdMappingData mappingData, String prefix,
+ String entityName) {
+ this.originalMapper = mappingData.getIdMapper();
+ this.prefixedMapper = mappingData.getIdMapper().prefixMappedProperties(prefix);
+ this.entityName = entityName;
+ this.versionsEntityName = verEntCfg.getVersionsEntityName(entityName);
+ }
+
+ public IdMapper getOriginalMapper() {
+ return originalMapper;
+ }
+
+ public IdMapper getPrefixedMapper() {
+ return prefixedMapper;
+ }
+
+ public String getEntityName() {
+ return entityName;
+ }
+
+ public String getVersionsEntityName() {
+ return versionsEntityName;
+ }
+}
Added: core/trunk/envers/src/main/java/org/jboss/envers/entities/mapper/relation/OneToOneNotOwningMapper.java
===================================================================
--- core/trunk/envers/src/main/java/org/jboss/envers/entities/mapper/relation/OneToOneNotOwningMapper.java (rev 0)
+++ core/trunk/envers/src/main/java/org/jboss/envers/entities/mapper/relation/OneToOneNotOwningMapper.java 2008-10-27 18:56:31 UTC (rev 15406)
@@ -0,0 +1,87 @@
+/*
+ * Envers. http://www.jboss.org/envers
+ *
+ * Copyright 2008 Red Hat Middleware, LLC. All rights reserved.
+ *
+ * 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, v. 2.1.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT A 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, v.2.1 along with this distribution; if not, write to the Free
+ * Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+ * 02110-1301, USA.
+ *
+ * Red Hat Author(s): Adam Warski
+ */
+package org.jboss.envers.entities.mapper.relation;
+
+import org.jboss.envers.entities.mapper.PropertyMapper;
+import org.jboss.envers.entities.mapper.PersistentCollectionChangeData;
+import org.jboss.envers.reader.VersionsReaderImplementor;
+import org.jboss.envers.tools.reflection.ReflectionTools;
+import org.jboss.envers.query.VersionsRestrictions;
+import org.jboss.envers.exception.VersionsException;
+import org.jboss.envers.configuration.VersionsConfiguration;
+import org.hibernate.property.Setter;
+import org.hibernate.NonUniqueResultException;
+import org.hibernate.collection.PersistentCollection;
+
+import javax.persistence.NoResultException;
+import java.util.Map;
+import java.util.List;
+import java.io.Serializable;
+
+/**
+ * @author Adam Warski (adam at warski dot org)
+ */
+public class OneToOneNotOwningMapper implements PropertyMapper {
+ private String owningReferencePropertyName;
+ private String owningEntityName;
+ private String propertyName;
+
+ public OneToOneNotOwningMapper(String owningReferencePropertyName, String owningEntityName, String propertyName) {
+ this.owningReferencePropertyName = owningReferencePropertyName;
+ this.owningEntityName = owningEntityName;
+ this.propertyName = propertyName;
+ }
+
+ public boolean mapToMapFromEntity(Map<String, Object> data, Object newObj, Object oldObj) {
+ return false;
+ }
+
+ public void mapToEntityFromMap(VersionsConfiguration verCfg, Object obj, Map data, Object primaryKey, VersionsReaderImplementor versionsReader, Number revision) {
+ if (obj == null) {
+ return;
+ }
+
+ Class<?> entityClass = ReflectionTools.loadClass(owningEntityName);
+
+ Object value;
+
+ try {
+ value = versionsReader.createQuery().forEntitiesAtRevision(entityClass, revision)
+ .add(VersionsRestrictions.relatedIdEq(owningReferencePropertyName, primaryKey)).getSingleResult();
+ } catch (NoResultException e) {
+ value = null;
+ } catch (NonUniqueResultException e) {
+ throw new VersionsException("Many versions results for one-to-one relationship: (" + owningEntityName +
+ ", " + owningReferencePropertyName + ")");
+ }
+
+ Setter setter = ReflectionTools.getSetter(obj.getClass(), propertyName);
+ setter.set(obj, value, null);
+ }
+
+ public List<PersistentCollectionChangeData> mapCollectionChanges(String referencingPropertyName,
+ PersistentCollection newColl,
+ Serializable oldColl,
+ Serializable id) {
+ return null;
+ }
+}
Added: core/trunk/envers/src/main/java/org/jboss/envers/entities/mapper/relation/ToOneIdMapper.java
===================================================================
--- core/trunk/envers/src/main/java/org/jboss/envers/entities/mapper/relation/ToOneIdMapper.java (rev 0)
+++ core/trunk/envers/src/main/java/org/jboss/envers/entities/mapper/relation/ToOneIdMapper.java 2008-10-27 18:56:31 UTC (rev 15406)
@@ -0,0 +1,94 @@
+/*
+ * Envers. http://www.jboss.org/envers
+ *
+ * Copyright 2008 Red Hat Middleware, LLC. All rights reserved.
+ *
+ * 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, v. 2.1.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT A 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, v.2.1 along with this distribution; if not, write to the Free
+ * Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+ * 02110-1301, USA.
+ *
+ * Red Hat Author(s): Adam Warski
+ */
+package org.jboss.envers.entities.mapper.relation;
+
+import org.jboss.envers.entities.mapper.PropertyMapper;
+import org.jboss.envers.entities.mapper.PersistentCollectionChangeData;
+import org.jboss.envers.entities.mapper.id.IdMapper;
+import org.jboss.envers.tools.Tools;
+import org.jboss.envers.tools.reflection.ReflectionTools;
+import org.jboss.envers.reader.VersionsReaderImplementor;
+import org.jboss.envers.entities.mapper.relation.lazy.ToOneDelegateSessionImplementor;
+import org.jboss.envers.configuration.VersionsConfiguration;
+import org.hibernate.property.Setter;
+import org.hibernate.collection.PersistentCollection;
+
+import java.util.Map;
+import java.util.HashMap;
+import java.util.List;
+import java.io.Serializable;
+
+/**
+ * @author Adam Warski (adam at warski dot org)
+ */
+public class ToOneIdMapper implements PropertyMapper {
+ private final IdMapper delegate;
+ private final String propertyName;
+ private final String referencedEntityName;
+
+ public ToOneIdMapper(IdMapper delegate, String propertyName, String referencedEntityName) {
+ this.delegate = delegate;
+ this.propertyName = propertyName;
+ this.referencedEntityName = referencedEntityName;
+ }
+
+ public boolean mapToMapFromEntity(Map<String, Object> data, Object newObj, Object oldObj) {
+ HashMap<String, Object> newData = new HashMap<String, Object>();
+ data.put(propertyName, newData);
+
+ delegate.mapToMapFromEntity(newData, newObj);
+
+ return !Tools.objectsEqual(newObj, oldObj);
+ }
+
+ public void mapToEntityFromMap(VersionsConfiguration verCfg, Object obj, Map data, Object primaryKey,
+ VersionsReaderImplementor versionsReader, Number revision) {
+ if (obj == null) {
+ return;
+ }
+
+ Object entityId = delegate.mapToIdFromMap((Map) data.get(propertyName));
+ Object value;
+ if (entityId == null) {
+ value = null;
+ } else {
+ if (versionsReader.getFirstLevelCache().contains(referencedEntityName, revision, entityId)) {
+ value = versionsReader.getFirstLevelCache().get(referencedEntityName, revision, entityId);
+ } else {
+ Class<?> entityClass = ReflectionTools.loadClass(referencedEntityName);
+
+ value = versionsReader.getSessionImplementor().getFactory().getEntityPersister(referencedEntityName).
+ createProxy(null, new ToOneDelegateSessionImplementor(versionsReader, entityClass, entityId, revision));
+ }
+ }
+
+ Setter setter = ReflectionTools.getSetter(obj.getClass(), propertyName);
+ setter.set(obj, value, null);
+ }
+
+ public List<PersistentCollectionChangeData> mapCollectionChanges(String referencingPropertyName,
+ PersistentCollection newColl,
+ Serializable oldColl,
+ Serializable id) {
+ return null;
+ }
+}
Added: core/trunk/envers/src/main/java/org/jboss/envers/entities/mapper/relation/component/MiddleComponentMapper.java
===================================================================
--- core/trunk/envers/src/main/java/org/jboss/envers/entities/mapper/relation/component/MiddleComponentMapper.java (rev 0)
+++ core/trunk/envers/src/main/java/org/jboss/envers/entities/mapper/relation/component/MiddleComponentMapper.java 2008-10-27 18:56:31 UTC (rev 15406)
@@ -0,0 +1,63 @@
+/*
+ * JBoss, Home of Professional Open Source
+ *
+ * Copyright 2008, Red Hat Middleware LLC, and others contributors as indicated
+ * by the @authors tag. All rights reserved.
+ *
+ * See the copyright.txt in the distribution for a full listing of individual
+ * contributors. 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, v. 2.1.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT A 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, v.2.1 along with this distribution; if not, write to the Free
+ * Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+ * 02110-1301, USA.
+ *
+ * Red Hat Author(s): Adam Warski
+ */
+package org.jboss.envers.entities.mapper.relation.component;
+
+import org.jboss.envers.entities.EntityInstantiator;
+import org.jboss.envers.tools.query.Parameters;
+
+import java.util.Map;
+
+/**
+ * @author Adam Warski (adam at warski dot org)
+ */
+public interface MiddleComponentMapper {
+ /**
+ * Maps from full object data, contained in the given map (or object representation of the map, if
+ * available), to an object.
+ * @param entityInstantiator An entity instatiator bound with an open versions reader.
+ * @param data Full object data.
+ * @param dataObject An optional object representation of the data.
+ * @param revision Revision at which the data is read.
+ * @return An object with data corresponding to the one found in the given map.
+ */
+ Object mapToObjectFromFullMap(EntityInstantiator entityInstantiator, Map<String, Object> data,
+ Object dataObject, Number revision);
+
+ /**
+ * Maps from an object to the object's map representation (for an entity - only its id).
+ * @param data Map to which data should be added.
+ * @param obj Object to map from.
+ */
+ void mapToMapFromObject(Map<String, Object> data, Object obj);
+
+ /**
+ * Adds query statements, which contains restrictions, which express the property that part of the middle
+ * entity with alias prefix1, is equal to part of the middle entity with alias prefix2 (the entity is the same).
+ * The part is the component's representation in the middle entity.
+ * @param parameters Parameters, to which to add the statements.
+ * @param prefix1 First alias of the entity + prefix to add to the properties.
+ * @param prefix2 Second alias of the entity + prefix to add to the properties.
+ */
+ void addMiddleEqualToQuery(Parameters parameters, String prefix1, String prefix2);
+}
Added: core/trunk/envers/src/main/java/org/jboss/envers/entities/mapper/relation/component/MiddleDummyComponentMapper.java
===================================================================
--- core/trunk/envers/src/main/java/org/jboss/envers/entities/mapper/relation/component/MiddleDummyComponentMapper.java (rev 0)
+++ core/trunk/envers/src/main/java/org/jboss/envers/entities/mapper/relation/component/MiddleDummyComponentMapper.java 2008-10-27 18:56:31 UTC (rev 15406)
@@ -0,0 +1,45 @@
+/*
+ * JBoss, Home of Professional Open Source
+ *
+ * Copyright 2008, Red Hat Middleware LLC, and others contributors as indicated
+ * by the @authors tag. All rights reserved.
+ *
+ * See the copyright.txt in the distribution for a full listing of individual
+ * contributors. 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, v. 2.1.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT A 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, v.2.1 along with this distribution; if not, write to the Free
+ * Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+ * 02110-1301, USA.
+ *
+ * Red Hat Author(s): Adam Warski
+ */
+package org.jboss.envers.entities.mapper.relation.component;
+
+import org.jboss.envers.entities.EntityInstantiator;
+import org.jboss.envers.tools.query.Parameters;
+
+import java.util.Map;
+
+/**
+ * @author Adam Warski (adam at warski dot org)
+ */
+public final class MiddleDummyComponentMapper implements MiddleComponentMapper {
+ public Object mapToObjectFromFullMap(EntityInstantiator entityInstantiator, Map<String, Object> data,
+ Object dataObject, Number revision) {
+ return null;
+ }
+
+ public void mapToMapFromObject(Map<String, Object> data, Object obj) {
+ }
+
+ public void addMiddleEqualToQuery(Parameters parameters, String prefix1, String prefix2) {
+ }
+}
\ No newline at end of file
Added: core/trunk/envers/src/main/java/org/jboss/envers/entities/mapper/relation/component/MiddleMapKeyIdComponentMapper.java
===================================================================
--- core/trunk/envers/src/main/java/org/jboss/envers/entities/mapper/relation/component/MiddleMapKeyIdComponentMapper.java (rev 0)
+++ core/trunk/envers/src/main/java/org/jboss/envers/entities/mapper/relation/component/MiddleMapKeyIdComponentMapper.java 2008-10-27 18:56:31 UTC (rev 15406)
@@ -0,0 +1,60 @@
+/*
+ * JBoss, Home of Professional Open Source
+ *
+ * Copyright 2008, Red Hat Middleware LLC, and others contributors as indicated
+ * by the @authors tag. All rights reserved.
+ *
+ * See the copyright.txt in the distribution for a full listing of individual
+ * contributors. 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, v. 2.1.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT A 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, v.2.1 along with this distribution; if not, write to the Free
+ * Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+ * 02110-1301, USA.
+ *
+ * Red Hat Author(s): Adam Warski
+ */
+package org.jboss.envers.entities.mapper.relation.component;
+
+import org.jboss.envers.entities.EntityInstantiator;
+import org.jboss.envers.entities.mapper.id.IdMapper;
+import org.jboss.envers.tools.query.Parameters;
+import org.jboss.envers.configuration.VersionsEntitiesConfiguration;
+
+import java.util.Map;
+
+/**
+ * A component mapper for the @MapKey mapping: the value of the map's key is the id of the entity. This
+ * doesn't have an effect on the data stored in the versions tables, so <code>mapToMapFromObject</code> is
+ * empty.
+ * @author Adam Warski (adam at warski dot org)
+ */
+public final class MiddleMapKeyIdComponentMapper implements MiddleComponentMapper {
+ private final VersionsEntitiesConfiguration verEntCfg;
+ private final IdMapper relatedIdMapper;
+
+ public MiddleMapKeyIdComponentMapper(VersionsEntitiesConfiguration verEntCfg, IdMapper relatedIdMapper) {
+ this.verEntCfg = verEntCfg;
+ this.relatedIdMapper = relatedIdMapper;
+ }
+
+ public Object mapToObjectFromFullMap(EntityInstantiator entityInstantiator, Map<String, Object> data,
+ Object dataObject, Number revision) {
+ return relatedIdMapper.mapToIdFromMap((Map) data.get(verEntCfg.getOriginalIdPropName()));
+ }
+
+ public void mapToMapFromObject(Map<String, Object> data, Object obj) {
+ // Doing nothing.
+ }
+
+ public void addMiddleEqualToQuery(Parameters parameters, String prefix1, String prefix2) {
+ // Doing nothing.
+ }
+}
\ No newline at end of file
Added: core/trunk/envers/src/main/java/org/jboss/envers/entities/mapper/relation/component/MiddleMapKeyPropertyComponentMapper.java
===================================================================
--- core/trunk/envers/src/main/java/org/jboss/envers/entities/mapper/relation/component/MiddleMapKeyPropertyComponentMapper.java (rev 0)
+++ core/trunk/envers/src/main/java/org/jboss/envers/entities/mapper/relation/component/MiddleMapKeyPropertyComponentMapper.java 2008-10-27 18:56:31 UTC (rev 15406)
@@ -0,0 +1,58 @@
+/*
+ * JBoss, Home of Professional Open Source
+ *
+ * Copyright 2008, Red Hat Middleware LLC, and others contributors as indicated
+ * by the @authors tag. All rights reserved.
+ *
+ * See the copyright.txt in the distribution for a full listing of individual
+ * contributors. 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, v. 2.1.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT A 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, v.2.1 along with this distribution; if not, write to the Free
+ * Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+ * 02110-1301, USA.
+ *
+ * Red Hat Author(s): Adam Warski
+ */
+package org.jboss.envers.entities.mapper.relation.component;
+
+import org.jboss.envers.entities.EntityInstantiator;
+import org.jboss.envers.tools.query.Parameters;
+import org.jboss.envers.tools.reflection.ReflectionTools;
+
+import java.util.Map;
+
+/**
+ * A component mapper for the @MapKey mapping with the name parameter specified: the value of the map's key
+ * is a property of the entity. This doesn't have an effect on the data stored in the versions tables,
+ * so <code>mapToMapFromObject</code> is empty.
+ * @author Adam Warski (adam at warski dot org)
+ */
+public final class MiddleMapKeyPropertyComponentMapper implements MiddleComponentMapper {
+ private final String propertyName;
+
+ public MiddleMapKeyPropertyComponentMapper(String propertyName) {
+ this.propertyName = propertyName;
+ }
+
+ public Object mapToObjectFromFullMap(EntityInstantiator entityInstantiator, Map<String, Object> data,
+ Object dataObject, Number revision) {
+ // dataObject is not null, as this mapper can only be used in an index.
+ return ReflectionTools.getGetter(dataObject.getClass(), propertyName).get(dataObject);
+ }
+
+ public void mapToMapFromObject(Map<String, Object> data, Object obj) {
+ // Doing nothing.
+ }
+
+ public void addMiddleEqualToQuery(Parameters parameters, String prefix1, String prefix2) {
+ // Doing nothing.
+ }
+}
\ No newline at end of file
Added: core/trunk/envers/src/main/java/org/jboss/envers/entities/mapper/relation/component/MiddleRelatedComponentMapper.java
===================================================================
--- core/trunk/envers/src/main/java/org/jboss/envers/entities/mapper/relation/component/MiddleRelatedComponentMapper.java (rev 0)
+++ core/trunk/envers/src/main/java/org/jboss/envers/entities/mapper/relation/component/MiddleRelatedComponentMapper.java 2008-10-27 18:56:31 UTC (rev 15406)
@@ -0,0 +1,54 @@
+/*
+ * JBoss, Home of Professional Open Source
+ *
+ * Copyright 2008, Red Hat Middleware LLC, and others contributors as indicated
+ * by the @authors tag. All rights reserved.
+ *
+ * See the copyright.txt in the distribution for a full listing of individual
+ * contributors. 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, v. 2.1.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT A 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, v.2.1 along with this distribution; if not, write to the Free
+ * Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+ * 02110-1301, USA.
+ *
+ * Red Hat Author(s): Adam Warski
+ */
+package org.jboss.envers.entities.mapper.relation.component;
+
+import org.jboss.envers.entities.EntityInstantiator;
+import org.jboss.envers.entities.mapper.relation.MiddleIdData;
+import org.jboss.envers.tools.query.Parameters;
+
+import java.util.Map;
+
+/**
+ * @author Adam Warski (adam at warski dot org)
+ */
+public final class MiddleRelatedComponentMapper implements MiddleComponentMapper {
+ private final MiddleIdData relatedIdData;
+
+ public MiddleRelatedComponentMapper(MiddleIdData relatedIdData) {
+ this.relatedIdData = relatedIdData;
+ }
+
+ public Object mapToObjectFromFullMap(EntityInstantiator entityInstantiator, Map<String, Object> data,
+ Object dataObject, Number revision) {
+ return entityInstantiator.createInstanceFromVersionsEntity(relatedIdData.getEntityName(), data, revision);
+ }
+
+ public void mapToMapFromObject(Map<String, Object> data, Object obj) {
+ relatedIdData.getPrefixedMapper().mapToMapFromEntity(data, obj);
+ }
+
+ public void addMiddleEqualToQuery(Parameters parameters, String prefix1, String prefix2) {
+ relatedIdData.getPrefixedMapper().addIdsEqualToQuery(parameters, prefix1, prefix2);
+ }
+}
Added: core/trunk/envers/src/main/java/org/jboss/envers/entities/mapper/relation/component/MiddleSimpleComponentMapper.java
===================================================================
--- core/trunk/envers/src/main/java/org/jboss/envers/entities/mapper/relation/component/MiddleSimpleComponentMapper.java (rev 0)
+++ core/trunk/envers/src/main/java/org/jboss/envers/entities/mapper/relation/component/MiddleSimpleComponentMapper.java 2008-10-27 18:56:31 UTC (rev 15406)
@@ -0,0 +1,57 @@
+/*
+ * JBoss, Home of Professional Open Source
+ *
+ * Copyright 2008, Red Hat Middleware LLC, and others contributors as indicated
+ * by the @authors tag. All rights reserved.
+ *
+ * See the copyright.txt in the distribution for a full listing of individual
+ * contributors. 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, v. 2.1.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT A 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, v.2.1 along with this distribution; if not, write to the Free
+ * Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+ * 02110-1301, USA.
+ *
+ * Red Hat Author(s): Adam Warski
+ */
+package org.jboss.envers.entities.mapper.relation.component;
+
+import org.jboss.envers.entities.EntityInstantiator;
+import org.jboss.envers.configuration.VersionsEntitiesConfiguration;
+import org.jboss.envers.tools.query.Parameters;
+
+import java.util.Map;
+
+/**
+ * @author Adam Warski (adam at warski dot org)
+ */
+public final class MiddleSimpleComponentMapper implements MiddleComponentMapper {
+ private final String propertyName;
+ private final VersionsEntitiesConfiguration verEntCfg;
+
+ public MiddleSimpleComponentMapper(VersionsEntitiesConfiguration verEntCfg, String propertyName) {
+ this.propertyName = propertyName;
+ this.verEntCfg = verEntCfg;
+ }
+
+ @SuppressWarnings({"unchecked"})
+ public Object mapToObjectFromFullMap(EntityInstantiator entityInstantiator, Map<String, Object> data,
+ Object dataObject, Number revision) {
+ return ((Map<String, Object>) data.get(verEntCfg.getOriginalIdPropName())).get(propertyName);
+ }
+
+ public void mapToMapFromObject(Map<String, Object> data, Object obj) {
+ data.put(propertyName, obj);
+ }
+
+ public void addMiddleEqualToQuery(Parameters parameters, String prefix1, String prefix2) {
+ parameters.addWhere(prefix1 + "." + propertyName, false, "=", prefix2 + "." + propertyName, false);
+ }
+}
Added: core/trunk/envers/src/main/java/org/jboss/envers/entities/mapper/relation/lazy/AbstractDelegateSessionImplementor.java
===================================================================
--- core/trunk/envers/src/main/java/org/jboss/envers/entities/mapper/relation/lazy/AbstractDelegateSessionImplementor.java (rev 0)
+++ core/trunk/envers/src/main/java/org/jboss/envers/entities/mapper/relation/lazy/AbstractDelegateSessionImplementor.java 2008-10-27 18:56:31 UTC (rev 15406)
@@ -0,0 +1,271 @@
+/*
+ * Envers. http://www.jboss.org/envers
+ *
+ * Copyright 2008 Red Hat Middleware, LLC. All rights reserved.
+ *
+ * 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, v. 2.1.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT A 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, v.2.1 along with this distribution; if not, write to the Free
+ * Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+ * 02110-1301, USA.
+ *
+ * Red Hat Author(s): Adam Warski
+ */
+package org.jboss.envers.entities.mapper.relation.lazy;
+
+import org.hibernate.engine.*;
+import org.hibernate.engine.query.sql.NativeSQLQuerySpecification;
+import org.hibernate.*;
+import org.hibernate.event.EventListeners;
+import org.hibernate.type.Type;
+import org.hibernate.loader.custom.CustomQuery;
+import org.hibernate.persister.entity.EntityPersister;
+import org.hibernate.impl.CriteriaImpl;
+import org.hibernate.jdbc.Batcher;
+import org.hibernate.jdbc.JDBCContext;
+import org.hibernate.collection.PersistentCollection;
+
+import java.io.Serializable;
+import java.util.List;
+import java.util.Iterator;
+import java.util.Map;
+import java.sql.Connection;
+
+/**
+ * @author Adam Warski (adam at warski dot org)
+ */
+public abstract class AbstractDelegateSessionImplementor implements SessionImplementor {
+ private SessionImplementor delegate;
+
+ public AbstractDelegateSessionImplementor(SessionImplementor delegate) {
+ this.delegate = delegate;
+ }
+
+ public abstract Object doImmediateLoad(String entityName);
+
+ public Object immediateLoad(String entityName, Serializable id) throws HibernateException {
+ return doImmediateLoad(entityName);
+ }
+
+ // Delegate methods
+
+ public LoadQueryInfluencers getLoadQueryInfluencers() {
+ return delegate.getLoadQueryInfluencers();
+ }
+
+ public Interceptor getInterceptor() {
+ return delegate.getInterceptor();
+ }
+
+ public void setAutoClear(boolean enabled) {
+ delegate.setAutoClear(enabled);
+ }
+
+ public boolean isTransactionInProgress() {
+ return delegate.isTransactionInProgress();
+ }
+
+ public void initializeCollection(PersistentCollection collection, boolean writing) throws HibernateException {
+ delegate.initializeCollection(collection, writing);
+ }
+
+ public Object internalLoad(String entityName, Serializable id, boolean eager, boolean nullable) throws HibernateException {
+ return delegate.internalLoad(entityName, id, eager, nullable);
+ }
+
+ public long getTimestamp() {
+ return delegate.getTimestamp();
+ }
+
+ public SessionFactoryImplementor getFactory() {
+ return delegate.getFactory();
+ }
+
+ public Batcher getBatcher() {
+ return delegate.getBatcher();
+ }
+
+ public List list(String query, QueryParameters queryParameters) throws HibernateException {
+ return delegate.list(query, queryParameters);
+ }
+
+ public Iterator iterate(String query, QueryParameters queryParameters) throws HibernateException {
+ return delegate.iterate(query, queryParameters);
+ }
+
+ public ScrollableResults scroll(String query, QueryParameters queryParameters) throws HibernateException {
+ return delegate.scroll(query, queryParameters);
+ }
+
+ public ScrollableResults scroll(CriteriaImpl criteria, ScrollMode scrollMode) {
+ return delegate.scroll(criteria, scrollMode);
+ }
+
+ public List list(CriteriaImpl criteria) {
+ return delegate.list(criteria);
+ }
+
+ public List listFilter(Object collection, String filter, QueryParameters queryParameters) throws HibernateException {
+ return delegate.listFilter(collection, filter, queryParameters);
+ }
+
+ public Iterator iterateFilter(Object collection, String filter, QueryParameters queryParameters) throws HibernateException {
+ return delegate.iterateFilter(collection, filter, queryParameters);
+ }
+
+ public EntityPersister getEntityPersister(String entityName, Object object) throws HibernateException {
+ return delegate.getEntityPersister(entityName, object);
+ }
+
+ public Object getEntityUsingInterceptor(EntityKey key) throws HibernateException {
+ return delegate.getEntityUsingInterceptor(key);
+ }
+
+ public void afterTransactionCompletion(boolean successful, Transaction tx) {
+ delegate.afterTransactionCompletion(successful, tx);
+ }
+
+ public void beforeTransactionCompletion(Transaction tx) {
+ delegate.beforeTransactionCompletion(tx);
+ }
+
+ public Serializable getContextEntityIdentifier(Object object) {
+ return delegate.getContextEntityIdentifier(object);
+ }
+
+ public String bestGuessEntityName(Object object) {
+ return delegate.bestGuessEntityName(object);
+ }
+
+ public String guessEntityName(Object entity) throws HibernateException {
+ return delegate.guessEntityName(entity);
+ }
+
+ public Object instantiate(String entityName, Serializable id) throws HibernateException {
+ return delegate.instantiate(entityName, id);
+ }
+
+ public List listCustomQuery(CustomQuery customQuery, QueryParameters queryParameters) throws HibernateException {
+ return delegate.listCustomQuery(customQuery, queryParameters);
+ }
+
+ public ScrollableResults scrollCustomQuery(CustomQuery customQuery, QueryParameters queryParameters) throws HibernateException {
+ return delegate.scrollCustomQuery(customQuery, queryParameters);
+ }
+
+ public List list(NativeSQLQuerySpecification spec, QueryParameters queryParameters) throws HibernateException {
+ return delegate.list(spec, queryParameters);
+ }
+
+ public ScrollableResults scroll(NativeSQLQuerySpecification spec, QueryParameters queryParameters) throws HibernateException {
+ return delegate.scroll(spec, queryParameters);
+ }
+
+ public Object getFilterParameterValue(String filterParameterName) {
+ return delegate.getFilterParameterValue(filterParameterName);
+ }
+
+ public Type getFilterParameterType(String filterParameterName) {
+ return delegate.getFilterParameterType(filterParameterName);
+ }
+
+ public Map getEnabledFilters() {
+ return delegate.getEnabledFilters();
+ }
+
+ public int getDontFlushFromFind() {
+ return delegate.getDontFlushFromFind();
+ }
+
+ public EventListeners getListeners() {
+ return delegate.getListeners();
+ }
+
+ public PersistenceContext getPersistenceContext() {
+ return delegate.getPersistenceContext();
+ }
+
+ public int executeUpdate(String query, QueryParameters queryParameters) throws HibernateException {
+ return delegate.executeUpdate(query, queryParameters);
+ }
+
+ public int executeNativeUpdate(NativeSQLQuerySpecification specification, QueryParameters queryParameters) throws HibernateException {
+ return delegate.executeNativeUpdate(specification, queryParameters);
+ }
+
+ public EntityMode getEntityMode() {
+ return delegate.getEntityMode();
+ }
+
+ public CacheMode getCacheMode() {
+ return delegate.getCacheMode();
+ }
+
+ public void setCacheMode(CacheMode cm) {
+ delegate.setCacheMode(cm);
+ }
+
+ public boolean isOpen() {
+ return delegate.isOpen();
+ }
+
+ public boolean isConnected() {
+ return delegate.isConnected();
+ }
+
+ public FlushMode getFlushMode() {
+ return delegate.getFlushMode();
+ }
+
+ public void setFlushMode(FlushMode fm) {
+ delegate.setFlushMode(fm);
+ }
+
+ public Connection connection() {
+ return delegate.connection();
+ }
+
+ public void flush() {
+ delegate.flush();
+ }
+
+ public Query getNamedQuery(String name) {
+ return delegate.getNamedQuery(name);
+ }
+
+ public Query getNamedSQLQuery(String name) {
+ return delegate.getNamedSQLQuery(name);
+ }
+
+ public boolean isEventSource() {
+ return delegate.isEventSource();
+ }
+
+ public void afterScrollOperation() {
+ delegate.afterScrollOperation();
+ }
+
+ public void setFetchProfile(String name) {
+ delegate.setFetchProfile(name);
+ }
+
+ public String getFetchProfile() {
+ return delegate.getFetchProfile();
+ }
+
+ public JDBCContext getJDBCContext() {
+ return delegate.getJDBCContext();
+ }
+
+ public boolean isClosed() {
+ return delegate.isClosed();
+ }
+}
Added: core/trunk/envers/src/main/java/org/jboss/envers/entities/mapper/relation/lazy/ToOneDelegateSessionImplementor.java
===================================================================
--- core/trunk/envers/src/main/java/org/jboss/envers/entities/mapper/relation/lazy/ToOneDelegateSessionImplementor.java (rev 0)
+++ core/trunk/envers/src/main/java/org/jboss/envers/entities/mapper/relation/lazy/ToOneDelegateSessionImplementor.java 2008-10-27 18:56:31 UTC (rev 15406)
@@ -0,0 +1,48 @@
+/*
+ * Envers. http://www.jboss.org/envers
+ *
+ * Copyright 2008 Red Hat Middleware, LLC. All rights reserved.
+ *
+ * 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, v. 2.1.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT A 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, v.2.1 along with this distribution; if not, write to the Free
+ * Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+ * 02110-1301, USA.
+ *
+ * Red Hat Author(s): Adam Warski
+ */
+package org.jboss.envers.entities.mapper.relation.lazy;
+
+import org.hibernate.HibernateException;
+import org.jboss.envers.reader.VersionsReaderImplementor;
+
+/**
+ * @author Adam Warski (adam at warski dot org)
+ */
+public class ToOneDelegateSessionImplementor extends AbstractDelegateSessionImplementor {
+ private final VersionsReaderImplementor versionsReader;
+ private final Class<?> entityClass;
+ private final Object entityId;
+ private final Number revision;
+
+ public ToOneDelegateSessionImplementor(VersionsReaderImplementor versionsReader,
+ Class<?> entityClass, Object entityId, Number revision) {
+ super(versionsReader.getSessionImplementor());
+ this.versionsReader = versionsReader;
+ this.entityClass = entityClass;
+ this.entityId = entityId;
+ this.revision = revision;
+ }
+
+ public Object doImmediateLoad(String entityName) throws HibernateException {
+ return versionsReader.find(entityClass, entityId, revision);
+ }
+}
Added: core/trunk/envers/src/main/java/org/jboss/envers/entities/mapper/relation/lazy/initializor/AbstractCollectionInitializor.java
===================================================================
--- core/trunk/envers/src/main/java/org/jboss/envers/entities/mapper/relation/lazy/initializor/AbstractCollectionInitializor.java (rev 0)
+++ core/trunk/envers/src/main/java/org/jboss/envers/entities/mapper/relation/lazy/initializor/AbstractCollectionInitializor.java 2008-10-27 18:56:31 UTC (rev 15406)
@@ -0,0 +1,72 @@
+/*
+ * JBoss, Home of Professional Open Source
+ *
+ * Copyright 2008, Red Hat Middleware LLC, and others contributors as indicated
+ * by the @authors tag. All rights reserved.
+ *
+ * See the copyright.txt in the distribution for a full listing of individual
+ * contributors. 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, v. 2.1.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT A 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, v.2.1 along with this distribution; if not, write to the Free
+ * Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+ * 02110-1301, USA.
+ *
+ * Red Hat Author(s): Adam Warski
+ */
+package org.jboss.envers.entities.mapper.relation.lazy.initializor;
+
+import org.jboss.envers.entities.mapper.relation.query.RelationQueryGenerator;
+import org.jboss.envers.entities.EntityInstantiator;
+import org.jboss.envers.reader.VersionsReaderImplementor;
+import org.jboss.envers.configuration.VersionsConfiguration;
+
+import java.util.List;
+
+/**
+ * Initializes a persistent collection.
+ * @author Adam Warski (adam at warski dot org)
+ */
+public abstract class AbstractCollectionInitializor<T> implements Initializor<T> {
+ private final VersionsReaderImplementor versionsReader;
+ private final RelationQueryGenerator queryGenerator;
+ private final Object primaryKey;
+
+ protected final Number revision;
+ protected final EntityInstantiator entityInstantiator;
+
+ public AbstractCollectionInitializor(VersionsConfiguration verCfg,
+ VersionsReaderImplementor versionsReader,
+ RelationQueryGenerator queryGenerator,
+ Object primaryKey, Number revision) {
+ this.versionsReader = versionsReader;
+ this.queryGenerator = queryGenerator;
+ this.primaryKey = primaryKey;
+ this.revision = revision;
+
+ entityInstantiator = new EntityInstantiator(verCfg, versionsReader);
+ }
+
+ protected abstract T initializeCollection(int size);
+
+ protected abstract void addToCollection(T collection, Object collectionRow);
+
+ public T initialize() {
+ List<?> collectionContent = queryGenerator.getQuery(versionsReader, primaryKey, revision).list();
+
+ T collection = initializeCollection(collectionContent.size());
+
+ for (Object collectionRow : collectionContent) {
+ addToCollection(collection, collectionRow);
+ }
+
+ return collection;
+ }
+}
Added: core/trunk/envers/src/main/java/org/jboss/envers/entities/mapper/relation/lazy/initializor/ArrayCollectionInitializor.java
===================================================================
--- core/trunk/envers/src/main/java/org/jboss/envers/entities/mapper/relation/lazy/initializor/ArrayCollectionInitializor.java (rev 0)
+++ core/trunk/envers/src/main/java/org/jboss/envers/entities/mapper/relation/lazy/initializor/ArrayCollectionInitializor.java 2008-10-27 18:56:31 UTC (rev 15406)
@@ -0,0 +1,70 @@
+/*
+ * JBoss, Home of Professional Open Source
+ *
+ * Copyright 2008, Red Hat Middleware LLC, and others contributors as indicated
+ * by the @authors tag. All rights reserved.
+ *
+ * See the copyright.txt in the distribution for a full listing of individual
+ * contributors. 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, v. 2.1.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT A 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, v.2.1 along with this distribution; if not, write to the Free
+ * Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+ * 02110-1301, USA.
+ *
+ * Red Hat Author(s): Adam Warski
+ */
+package org.jboss.envers.entities.mapper.relation.lazy.initializor;
+
+import org.jboss.envers.entities.mapper.relation.query.RelationQueryGenerator;
+import org.jboss.envers.entities.mapper.relation.MiddleComponentData;
+import org.jboss.envers.reader.VersionsReaderImplementor;
+import org.jboss.envers.configuration.VersionsConfiguration;
+
+import java.util.*;
+
+/**
+ * Initializes a map.
+ * @author Adam Warski (adam at warski dot org)
+ */
+public class ArrayCollectionInitializor extends AbstractCollectionInitializor<Object[]> {
+ private final MiddleComponentData elementComponentData;
+ private final MiddleComponentData indexComponentData;
+
+ public ArrayCollectionInitializor(VersionsConfiguration verCfg,
+ VersionsReaderImplementor versionsReader,
+ RelationQueryGenerator queryGenerator,
+ Object primaryKey, Number revision,
+ MiddleComponentData elementComponentData,
+ MiddleComponentData indexComponentData) {
+ super(verCfg, versionsReader, queryGenerator, primaryKey, revision);
+
+ this.elementComponentData = elementComponentData;
+ this.indexComponentData = indexComponentData;
+ }
+
+ protected Object[] initializeCollection(int size) {
+ return new Object[size];
+ }
+
+ @SuppressWarnings({"unchecked"})
+ protected void addToCollection(Object[] collection, Object collectionRow) {
+ Object elementData = ((List) collectionRow).get(elementComponentData.getComponentIndex());
+ Object element = elementComponentData.getComponentMapper().mapToObjectFromFullMap(entityInstantiator,
+ (Map<String, Object>) elementData, null, revision);
+
+ Object indexData = ((List) collectionRow).get(indexComponentData.getComponentIndex());
+ Object indexObj = indexComponentData.getComponentMapper().mapToObjectFromFullMap(entityInstantiator,
+ (Map<String, Object>) indexData, element, revision);
+ int index = ((Number) indexObj).intValue();
+
+ collection[index] = element;
+ }
+}
\ No newline at end of file
Added: core/trunk/envers/src/main/java/org/jboss/envers/entities/mapper/relation/lazy/initializor/BasicCollectionInitializor.java
===================================================================
--- core/trunk/envers/src/main/java/org/jboss/envers/entities/mapper/relation/lazy/initializor/BasicCollectionInitializor.java (rev 0)
+++ core/trunk/envers/src/main/java/org/jboss/envers/entities/mapper/relation/lazy/initializor/BasicCollectionInitializor.java 2008-10-27 18:56:31 UTC (rev 15406)
@@ -0,0 +1,71 @@
+/*
+ * JBoss, Home of Professional Open Source
+ *
+ * Copyright 2008, Red Hat Middleware LLC, and others contributors as indicated
+ * by the @authors tag. All rights reserved.
+ *
+ * See the copyright.txt in the distribution for a full listing of individual
+ * contributors. 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, v. 2.1.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT A 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, v.2.1 along with this distribution; if not, write to the Free
+ * Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+ * 02110-1301, USA.
+ *
+ * Red Hat Author(s): Adam Warski
+ */
+package org.jboss.envers.entities.mapper.relation.lazy.initializor;
+
+import org.jboss.envers.entities.mapper.relation.query.RelationQueryGenerator;
+import org.jboss.envers.entities.mapper.relation.MiddleComponentData;
+import org.jboss.envers.reader.VersionsReaderImplementor;
+import org.jboss.envers.exception.VersionsException;
+import org.jboss.envers.configuration.VersionsConfiguration;
+
+import java.util.*;
+
+/**
+ * Initializes a non-indexed java collection (set or list, eventually sorted).
+ * @author Adam Warski (adam at warski dot org)
+ */
+public class BasicCollectionInitializor<T extends Collection> extends AbstractCollectionInitializor<T> {
+ private final Class<? extends T> collectionClass;
+ private final MiddleComponentData elementComponentData;
+
+ public BasicCollectionInitializor(VersionsConfiguration verCfg,
+ VersionsReaderImplementor versionsReader,
+ RelationQueryGenerator queryGenerator,
+ Object primaryKey, Number revision,
+ Class<? extends T> collectionClass,
+ MiddleComponentData elementComponentData) {
+ super(verCfg, versionsReader, queryGenerator, primaryKey, revision);
+
+ this.collectionClass = collectionClass;
+ this.elementComponentData = elementComponentData;
+ }
+
+ protected T initializeCollection(int size) {
+ try {
+ return collectionClass.newInstance();
+ } catch (InstantiationException e) {
+ throw new VersionsException(e);
+ } catch (IllegalAccessException e) {
+ throw new VersionsException(e);
+ }
+ }
+
+ @SuppressWarnings({"unchecked"})
+ protected void addToCollection(T collection, Object collectionRow) {
+ Object elementData = ((List) collectionRow).get(elementComponentData.getComponentIndex());
+ Object element = elementComponentData.getComponentMapper().mapToObjectFromFullMap(entityInstantiator,
+ (Map<String, Object>) elementData, null, revision);
+ collection.add(element);
+ }
+}
Added: core/trunk/envers/src/main/java/org/jboss/envers/entities/mapper/relation/lazy/initializor/Initializor.java
===================================================================
--- core/trunk/envers/src/main/java/org/jboss/envers/entities/mapper/relation/lazy/initializor/Initializor.java (rev 0)
+++ core/trunk/envers/src/main/java/org/jboss/envers/entities/mapper/relation/lazy/initializor/Initializor.java 2008-10-27 18:56:31 UTC (rev 15406)
@@ -0,0 +1,29 @@
+/*
+ * Envers. http://www.jboss.org/envers
+ *
+ * Copyright 2008 Red Hat Middleware, LLC. All rights reserved.
+ *
+ * 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, v. 2.1.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT A 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, v.2.1 along with this distribution; if not, write to the Free
+ * Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+ * 02110-1301, USA.
+ *
+ * Red Hat Author(s): Adam Warski
+ */
+package org.jboss.envers.entities.mapper.relation.lazy.initializor;
+
+/**
+ * @author Adam Warski (adam at warski dot org)
+ */
+public interface Initializor<T> {
+ T initialize();
+}
Added: core/trunk/envers/src/main/java/org/jboss/envers/entities/mapper/relation/lazy/initializor/ListCollectionInitializor.java
===================================================================
--- core/trunk/envers/src/main/java/org/jboss/envers/entities/mapper/relation/lazy/initializor/ListCollectionInitializor.java (rev 0)
+++ core/trunk/envers/src/main/java/org/jboss/envers/entities/mapper/relation/lazy/initializor/ListCollectionInitializor.java 2008-10-27 18:56:31 UTC (rev 15406)
@@ -0,0 +1,75 @@
+/*
+ * JBoss, Home of Professional Open Source
+ *
+ * Copyright 2008, Red Hat Middleware LLC, and others contributors as indicated
+ * by the @authors tag. All rights reserved.
+ *
+ * See the copyright.txt in the distribution for a full listing of individual
+ * contributors. 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, v. 2.1.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT A 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, v.2.1 along with this distribution; if not, write to the Free
+ * Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+ * 02110-1301, USA.
+ *
+ * Red Hat Author(s): Adam Warski
+ */
+package org.jboss.envers.entities.mapper.relation.lazy.initializor;
+
+import org.jboss.envers.entities.mapper.relation.query.RelationQueryGenerator;
+import org.jboss.envers.entities.mapper.relation.MiddleComponentData;
+import org.jboss.envers.reader.VersionsReaderImplementor;
+import org.jboss.envers.configuration.VersionsConfiguration;
+
+import java.util.*;
+
+/**
+ * Initializes a map.
+ * @author Adam Warski (adam at warski dot org)
+ */
+public class ListCollectionInitializor extends AbstractCollectionInitializor<List> {
+ private final MiddleComponentData elementComponentData;
+ private final MiddleComponentData indexComponentData;
+
+ public ListCollectionInitializor(VersionsConfiguration verCfg,
+ VersionsReaderImplementor versionsReader,
+ RelationQueryGenerator queryGenerator,
+ Object primaryKey, Number revision,
+ MiddleComponentData elementComponentData,
+ MiddleComponentData indexComponentData) {
+ super(verCfg, versionsReader, queryGenerator, primaryKey, revision);
+
+ this.elementComponentData = elementComponentData;
+ this.indexComponentData = indexComponentData;
+ }
+
+ @SuppressWarnings({"unchecked"})
+ protected List initializeCollection(int size) {
+ // Creating a list of the given capacity with all elements null initially. This ensures that we can then
+ // fill the elements safely using the <code>List.set</code> method.
+ List list = new ArrayList(size);
+ for (int i=0; i<size; i++) { list.add(null); }
+ return list;
+ }
+
+ @SuppressWarnings({"unchecked"})
+ protected void addToCollection(List collection, Object collectionRow) {
+ Object elementData = ((List) collectionRow).get(elementComponentData.getComponentIndex());
+ Object element = elementComponentData.getComponentMapper().mapToObjectFromFullMap(entityInstantiator,
+ (Map<String, Object>) elementData, null, revision);
+
+ Object indexData = ((List) collectionRow).get(indexComponentData.getComponentIndex());
+ Object indexObj = indexComponentData.getComponentMapper().mapToObjectFromFullMap(entityInstantiator,
+ (Map<String, Object>) indexData, element, revision);
+ int index = ((Number) indexObj).intValue();
+
+ collection.set(index, element);
+ }
+}
\ No newline at end of file
Added: core/trunk/envers/src/main/java/org/jboss/envers/entities/mapper/relation/lazy/initializor/MapCollectionInitializor.java
===================================================================
--- core/trunk/envers/src/main/java/org/jboss/envers/entities/mapper/relation/lazy/initializor/MapCollectionInitializor.java (rev 0)
+++ core/trunk/envers/src/main/java/org/jboss/envers/entities/mapper/relation/lazy/initializor/MapCollectionInitializor.java 2008-10-27 18:56:31 UTC (rev 15406)
@@ -0,0 +1,79 @@
+/*
+ * JBoss, Home of Professional Open Source
+ *
+ * Copyright 2008, Red Hat Middleware LLC, and others contributors as indicated
+ * by the @authors tag. All rights reserved.
+ *
+ * See the copyright.txt in the distribution for a full listing of individual
+ * contributors. 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, v. 2.1.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT A 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, v.2.1 along with this distribution; if not, write to the Free
+ * Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+ * 02110-1301, USA.
+ *
+ * Red Hat Author(s): Adam Warski
+ */
+package org.jboss.envers.entities.mapper.relation.lazy.initializor;
+
+import org.jboss.envers.entities.mapper.relation.query.RelationQueryGenerator;
+import org.jboss.envers.entities.mapper.relation.MiddleComponentData;
+import org.jboss.envers.reader.VersionsReaderImplementor;
+import org.jboss.envers.exception.VersionsException;
+import org.jboss.envers.configuration.VersionsConfiguration;
+
+import java.util.*;
+
+/**
+ * Initializes a map.
+ * @author Adam Warski (adam at warski dot org)
+ */
+public class MapCollectionInitializor<T extends Map> extends AbstractCollectionInitializor<T> {
+ private final Class<? extends T> collectionClass;
+ private final MiddleComponentData elementComponentData;
+ private final MiddleComponentData indexComponentData;
+
+ public MapCollectionInitializor(VersionsConfiguration verCfg,
+ VersionsReaderImplementor versionsReader,
+ RelationQueryGenerator queryGenerator,
+ Object primaryKey, Number revision,
+ Class<? extends T> collectionClass,
+ MiddleComponentData elementComponentData,
+ MiddleComponentData indexComponentData) {
+ super(verCfg, versionsReader, queryGenerator, primaryKey, revision);
+
+ this.collectionClass = collectionClass;
+ this.elementComponentData = elementComponentData;
+ this.indexComponentData = indexComponentData;
+ }
+
+ protected T initializeCollection(int size) {
+ try {
+ return collectionClass.newInstance();
+ } catch (InstantiationException e) {
+ throw new VersionsException(e);
+ } catch (IllegalAccessException e) {
+ throw new VersionsException(e);
+ }
+ }
+
+ @SuppressWarnings({"unchecked"})
+ protected void addToCollection(T collection, Object collectionRow) {
+ Object elementData = ((List) collectionRow).get(elementComponentData.getComponentIndex());
+ Object element = elementComponentData.getComponentMapper().mapToObjectFromFullMap(entityInstantiator,
+ (Map<String, Object>) elementData, null, revision);
+
+ Object indexData = ((List) collectionRow).get(indexComponentData.getComponentIndex());
+ Object index = indexComponentData.getComponentMapper().mapToObjectFromFullMap(entityInstantiator,
+ (Map<String, Object>) indexData, element, revision);
+
+ collection.put(index, element);
+ }
+}
\ No newline at end of file
Added: core/trunk/envers/src/main/java/org/jboss/envers/entities/mapper/relation/lazy/proxy/CollectionProxy.java
===================================================================
--- core/trunk/envers/src/main/java/org/jboss/envers/entities/mapper/relation/lazy/proxy/CollectionProxy.java (rev 0)
+++ core/trunk/envers/src/main/java/org/jboss/envers/entities/mapper/relation/lazy/proxy/CollectionProxy.java 2008-10-27 18:56:31 UTC (rev 15406)
@@ -0,0 +1,129 @@
+/*
+ * Envers. http://www.jboss.org/envers
+ *
+ * Copyright 2008 Red Hat Middleware, LLC. All rights reserved.
+ *
+ * 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, v. 2.1.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT A 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, v.2.1 along with this distribution; if not, write to the Free
+ * Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+ * 02110-1301, USA.
+ *
+ * Red Hat Author(s): Adam Warski
+ */
+package org.jboss.envers.entities.mapper.relation.lazy.proxy;
+
+import org.jboss.envers.entities.mapper.relation.lazy.initializor.Initializor;
+
+import java.util.Collection;
+import java.util.Iterator;
+
+/**
+ * @author Adam Warski (adam at warski dot org)
+ */
+public abstract class CollectionProxy<U, T extends Collection<U>> implements Collection<U> {
+ private org.jboss.envers.entities.mapper.relation.lazy.initializor.Initializor<T> initializor;
+ protected T delegate;
+
+ public CollectionProxy(Initializor<T> initializor) {
+ this.initializor = initializor;
+ }
+
+ protected void checkInit() {
+ if (delegate == null) {
+ delegate = initializor.initialize();
+ }
+ }
+
+ public int size() {
+ checkInit();
+ return delegate.size();
+ }
+
+ public boolean isEmpty() {
+ checkInit();
+ return delegate.isEmpty();
+ }
+
+ public boolean contains(Object o) {
+ checkInit();
+ return delegate.contains(o);
+ }
+
+ public Iterator<U> iterator() {
+ checkInit();
+ return delegate.iterator();
+ }
+
+ public Object[] toArray() {
+ checkInit();
+ return delegate.toArray();
+ }
+
+ public <V> V[] toArray(V[] a) {
+ checkInit();
+ return delegate.toArray(a);
+ }
+
+ public boolean add(U o) {
+ checkInit();
+ return delegate.add(o);
+ }
+
+ public boolean remove(Object o) {
+ checkInit();
+ return delegate.remove(o);
+ }
+
+ public boolean containsAll(Collection<?> c) {
+ checkInit();
+ return delegate.containsAll(c);
+ }
+
+ public boolean addAll(Collection<? extends U> c) {
+ checkInit();
+ return delegate.addAll(c);
+ }
+
+ public boolean removeAll(Collection<?> c) {
+ checkInit();
+ return delegate.removeAll(c);
+ }
+
+ public boolean retainAll(Collection<?> c) {
+ checkInit();
+ return delegate.retainAll(c);
+ }
+
+ public void clear() {
+ checkInit();
+ delegate.clear();
+ }
+
+ @Override
+ public String toString() {
+ checkInit();
+ return delegate.toString();
+ }
+
+ @SuppressWarnings({"EqualsWhichDoesntCheckParameterClass"})
+ @Override
+ public boolean equals(Object obj) {
+ checkInit();
+ return delegate.equals(obj);
+ }
+
+ @Override
+ public int hashCode() {
+ checkInit();
+ return delegate.hashCode();
+ }
+}
Added: core/trunk/envers/src/main/java/org/jboss/envers/entities/mapper/relation/lazy/proxy/ListProxy.java
===================================================================
--- core/trunk/envers/src/main/java/org/jboss/envers/entities/mapper/relation/lazy/proxy/ListProxy.java (rev 0)
+++ core/trunk/envers/src/main/java/org/jboss/envers/entities/mapper/relation/lazy/proxy/ListProxy.java 2008-10-27 18:56:31 UTC (rev 15406)
@@ -0,0 +1,85 @@
+/*
+ * Envers. http://www.jboss.org/envers
+ *
+ * Copyright 2008 Red Hat Middleware, LLC. All rights reserved.
+ *
+ * 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, v. 2.1.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT A 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, v.2.1 along with this distribution; if not, write to the Free
+ * Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+ * 02110-1301, USA.
+ *
+ * Red Hat Author(s): Adam Warski
+ */
+package org.jboss.envers.entities.mapper.relation.lazy.proxy;
+
+import java.util.List;
+import java.util.Collection;
+import java.util.ListIterator;
+
+/**
+ * @author Adam Warski (adam at warski dot org)
+ */
+public class ListProxy<U> extends CollectionProxy<U, List<U>> implements List<U> {
+ public ListProxy(org.jboss.envers.entities.mapper.relation.lazy.initializor.Initializor<List<U>> initializor) {
+ super(initializor);
+ }
+
+ public boolean addAll(int index, Collection<? extends U> c) {
+ checkInit();
+ return delegate.addAll(index, c);
+ }
+
+ public U get(int index) {
+ checkInit();
+ return delegate.get(index);
+ }
+
+ public U set(int index, U element) {
+ checkInit();
+ return delegate.set(index, element);
+ }
+
+ public void add(int index, U element) {
+ checkInit();
+ delegate.add(index, element);
+ }
+
+ public U remove(int index) {
+ checkInit();
+ return delegate.remove(index);
+ }
+
+ public int indexOf(Object o) {
+ checkInit();
+ return delegate.indexOf(o);
+ }
+
+ public int lastIndexOf(Object o) {
+ checkInit();
+ return delegate.lastIndexOf(o);
+ }
+
+ public ListIterator<U> listIterator() {
+ checkInit();
+ return delegate.listIterator();
+ }
+
+ public ListIterator<U> listIterator(int index) {
+ checkInit();
+ return delegate.listIterator(index);
+ }
+
+ public List<U> subList(int fromIndex, int toIndex) {
+ checkInit();
+ return delegate.subList(fromIndex, toIndex);
+ }
+}
Added: core/trunk/envers/src/main/java/org/jboss/envers/entities/mapper/relation/lazy/proxy/MapProxy.java
===================================================================
--- core/trunk/envers/src/main/java/org/jboss/envers/entities/mapper/relation/lazy/proxy/MapProxy.java (rev 0)
+++ core/trunk/envers/src/main/java/org/jboss/envers/entities/mapper/relation/lazy/proxy/MapProxy.java 2008-10-27 18:56:31 UTC (rev 15406)
@@ -0,0 +1,127 @@
+/*
+ * JBoss, Home of Professional Open Source
+ *
+ * Copyright 2008, Red Hat Middleware LLC, and others contributors as indicated
+ * by the @authors tag. All rights reserved.
+ *
+ * See the copyright.txt in the distribution for a full listing of individual
+ * contributors. 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, v. 2.1.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT A 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, v.2.1 along with this distribution; if not, write to the Free
+ * Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+ * 02110-1301, USA.
+ *
+ * Red Hat Author(s): Adam Warski
+ */
+package org.jboss.envers.entities.mapper.relation.lazy.proxy;
+
+import org.jboss.envers.entities.mapper.relation.lazy.initializor.Initializor;
+
+import java.util.Map;
+import java.util.Set;
+import java.util.Collection;
+
+/**
+ * @author Adam Warski (adam at warski dot org)
+ */
+public class MapProxy<K, V> implements Map<K, V> {
+ private Initializor<Map<K, V>> initializor;
+ protected Map<K, V> delegate;
+
+ public MapProxy(org.jboss.envers.entities.mapper.relation.lazy.initializor.Initializor<Map<K, V>> initializor) {
+ this.initializor = initializor;
+ }
+
+ private void checkInit() {
+ if (delegate == null) {
+ delegate = initializor.initialize();
+ }
+ }
+
+ public int size() {
+ checkInit();
+ return delegate.size();
+ }
+
+ public boolean isEmpty() {
+ checkInit();
+ return delegate.isEmpty();
+ }
+
+ public boolean containsKey(Object o) {
+ checkInit();
+ return delegate.containsKey(o);
+ }
+
+ public boolean containsValue(Object o) {
+ checkInit();
+ return delegate.containsValue(o);
+ }
+
+ public V get(Object o) {
+ checkInit();
+ return delegate.get(o);
+ }
+
+ public V put(K k, V v) {
+ checkInit();
+ return delegate.put(k, v);
+ }
+
+ public V remove(Object o) {
+ checkInit();
+ return delegate.remove(o);
+ }
+
+ public void putAll(Map<? extends K, ? extends V> map) {
+ checkInit();
+ delegate.putAll(map);
+ }
+
+ public void clear() {
+ checkInit();
+ delegate.clear();
+ }
+
+ public Set<K> keySet() {
+ checkInit();
+ return delegate.keySet();
+ }
+
+ public Collection<V> values() {
+ checkInit();
+ return delegate.values();
+ }
+
+ public Set<Entry<K, V>> entrySet() {
+ checkInit();
+ return delegate.entrySet();
+ }
+
+ @Override
+ public String toString() {
+ checkInit();
+ return delegate.toString();
+ }
+
+ @SuppressWarnings({"EqualsWhichDoesntCheckParameterClass"})
+ @Override
+ public boolean equals(Object obj) {
+ checkInit();
+ return delegate.equals(obj);
+ }
+
+ @Override
+ public int hashCode() {
+ checkInit();
+ return delegate.hashCode();
+ }
+}
Added: core/trunk/envers/src/main/java/org/jboss/envers/entities/mapper/relation/lazy/proxy/SetProxy.java
===================================================================
--- core/trunk/envers/src/main/java/org/jboss/envers/entities/mapper/relation/lazy/proxy/SetProxy.java (rev 0)
+++ core/trunk/envers/src/main/java/org/jboss/envers/entities/mapper/relation/lazy/proxy/SetProxy.java 2008-10-27 18:56:31 UTC (rev 15406)
@@ -0,0 +1,33 @@
+/*
+ * Envers. http://www.jboss.org/envers
+ *
+ * Copyright 2008 Red Hat Middleware, LLC. All rights reserved.
+ *
+ * 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, v. 2.1.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT A 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, v.2.1 along with this distribution; if not, write to the Free
+ * Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+ * 02110-1301, USA.
+ *
+ * Red Hat Author(s): Adam Warski
+ */
+package org.jboss.envers.entities.mapper.relation.lazy.proxy;
+
+import java.util.Set;
+
+/**
+ * @author Adam Warski (adam at warski dot org)
+ */
+public class SetProxy<U> extends CollectionProxy<U, Set<U>> implements Set<U> {
+ public SetProxy(org.jboss.envers.entities.mapper.relation.lazy.initializor.Initializor<Set<U>> initializor) {
+ super(initializor);
+ }
+}
Added: core/trunk/envers/src/main/java/org/jboss/envers/entities/mapper/relation/lazy/proxy/SortedMapProxy.java
===================================================================
--- core/trunk/envers/src/main/java/org/jboss/envers/entities/mapper/relation/lazy/proxy/SortedMapProxy.java (rev 0)
+++ core/trunk/envers/src/main/java/org/jboss/envers/entities/mapper/relation/lazy/proxy/SortedMapProxy.java 2008-10-27 18:56:31 UTC (rev 15406)
@@ -0,0 +1,147 @@
+/*
+ * JBoss, Home of Professional Open Source
+ *
+ * Copyright 2008, Red Hat Middleware LLC, and others contributors as indicated
+ * by the @authors tag. All rights reserved.
+ *
+ * See the copyright.txt in the distribution for a full listing of individual
+ * contributors. 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, v. 2.1.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT A 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, v.2.1 along with this distribution; if not, write to the Free
+ * Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+ * 02110-1301, USA.
+ *
+ * Red Hat Author(s): Adam Warski
+ */
+package org.jboss.envers.entities.mapper.relation.lazy.proxy;
+
+import org.jboss.envers.entities.mapper.relation.lazy.initializor.Initializor;
+
+import java.util.*;
+
+/**
+ * @author Adam Warski (adam at warski dot org)
+ */
+public class SortedMapProxy<K, V> implements SortedMap<K, V> {
+ private Initializor<SortedMap<K, V>> initializor;
+ protected SortedMap<K, V> delegate;
+
+ public SortedMapProxy(org.jboss.envers.entities.mapper.relation.lazy.initializor.Initializor<SortedMap<K, V>> initializor) {
+ this.initializor = initializor;
+ }
+
+ private void checkInit() {
+ if (delegate == null) {
+ delegate = initializor.initialize();
+ }
+ }
+
+ public int size() {
+ checkInit();
+ return delegate.size();
+ }
+
+ public boolean isEmpty() {
+ checkInit();
+ return delegate.isEmpty();
+ }
+
+ public boolean containsKey(Object o) {
+ checkInit();
+ return delegate.containsKey(o);
+ }
+
+ public boolean containsValue(Object o) {
+ checkInit();
+ return delegate.containsValue(o);
+ }
+
+ public V get(Object o) {
+ checkInit();
+ return delegate.get(o);
+ }
+
+ public V put(K k, V v) {
+ checkInit();
+ return delegate.put(k, v);
+ }
+
+ public V remove(Object o) {
+ checkInit();
+ return delegate.remove(o);
+ }
+
+ public void putAll(Map<? extends K, ? extends V> map) {
+ checkInit();
+ delegate.putAll(map);
+ }
+
+ public void clear() {
+ checkInit();
+ delegate.clear();
+ }
+
+ public Set<K> keySet() {
+ checkInit();
+ return delegate.keySet();
+ }
+
+ public Collection<V> values() {
+ checkInit();
+ return delegate.values();
+ }
+
+ public Set<Entry<K, V>> entrySet() {
+ checkInit();
+ return delegate.entrySet();
+ }
+
+ public Comparator<? super K> comparator() {
+ checkInit();
+ return delegate.comparator();
+ }
+
+ public SortedMap<K, V> subMap(K k, K k1) {
+ checkInit();
+ return delegate.subMap(k, k1);
+ }
+
+ public SortedMap<K, V> headMap(K k) {
+ checkInit();
+ return delegate.headMap(k);
+ }
+
+ public SortedMap<K, V> tailMap(K k) {
+ checkInit();
+ return delegate.tailMap(k);
+ }
+
+ public K firstKey() {
+ checkInit();
+ return delegate.firstKey();
+ }
+
+ public K lastKey() {
+ checkInit();
+ return delegate.lastKey();
+ }
+
+ @SuppressWarnings({"EqualsWhichDoesntCheckParameterClass"})
+ public boolean equals(Object o) {
+ checkInit();
+ return delegate.equals(o);
+ }
+
+ public int hashCode() {
+ checkInit();
+ return delegate.hashCode();
+ }
+}
\ No newline at end of file
Added: core/trunk/envers/src/main/java/org/jboss/envers/entities/mapper/relation/lazy/proxy/SortedSetProxy.java
===================================================================
--- core/trunk/envers/src/main/java/org/jboss/envers/entities/mapper/relation/lazy/proxy/SortedSetProxy.java (rev 0)
+++ core/trunk/envers/src/main/java/org/jboss/envers/entities/mapper/relation/lazy/proxy/SortedSetProxy.java 2008-10-27 18:56:31 UTC (rev 15406)
@@ -0,0 +1,66 @@
+/*
+ * JBoss, Home of Professional Open Source
+ *
+ * Copyright 2008, Red Hat Middleware LLC, and others contributors as indicated
+ * by the @authors tag. All rights reserved.
+ *
+ * See the copyright.txt in the distribution for a full listing of individual
+ * contributors. 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, v. 2.1.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT A 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, v.2.1 along with this distribution; if not, write to the Free
+ * Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+ * 02110-1301, USA.
+ *
+ * Red Hat Author(s): Adam Warski
+ */
+package org.jboss.envers.entities.mapper.relation.lazy.proxy;
+
+import java.util.SortedSet;
+import java.util.Comparator;
+
+/**
+ * @author Adam Warski (adam at warski dot org)
+ */
+public class SortedSetProxy<U> extends CollectionProxy<U, SortedSet<U>> implements SortedSet<U> {
+ public SortedSetProxy(org.jboss.envers.entities.mapper.relation.lazy.initializor.Initializor<SortedSet<U>> initializor) {
+ super(initializor);
+ }
+
+ public Comparator<? super U> comparator() {
+ checkInit();
+ return delegate.comparator();
+ }
+
+ public SortedSet<U> subSet(U u, U u1) {
+ checkInit();
+ return delegate.subSet(u, u1);
+ }
+
+ public SortedSet<U> headSet(U u) {
+ checkInit();
+ return delegate.headSet(u);
+ }
+
+ public SortedSet<U> tailSet(U u) {
+ checkInit();
+ return delegate.tailSet(u);
+ }
+
+ public U first() {
+ checkInit();
+ return delegate.first();
+ }
+
+ public U last() {
+ checkInit();
+ return delegate.last();
+ }
+}
\ No newline at end of file
Added: core/trunk/envers/src/main/java/org/jboss/envers/entities/mapper/relation/query/OneEntityQueryGenerator.java
===================================================================
--- core/trunk/envers/src/main/java/org/jboss/envers/entities/mapper/relation/query/OneEntityQueryGenerator.java (rev 0)
+++ core/trunk/envers/src/main/java/org/jboss/envers/entities/mapper/relation/query/OneEntityQueryGenerator.java 2008-10-27 18:56:31 UTC (rev 15406)
@@ -0,0 +1,107 @@
+/*
+ * JBoss, Home of Professional Open Source
+ *
+ * Copyright 2008, Red Hat Middleware LLC, and others contributors as indicated
+ * by the @authors tag. All rights reserved.
+ *
+ * See the copyright.txt in the distribution for a full listing of individual
+ * contributors. 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, v. 2.1.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT A 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, v.2.1 along with this distribution; if not, write to the Free
+ * Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+ * 02110-1301, USA.
+ *
+ * Red Hat Author(s): Adam Warski
+ */
+package org.jboss.envers.entities.mapper.relation.query;
+
+import org.jboss.envers.entities.mapper.relation.MiddleIdData;
+import org.jboss.envers.entities.mapper.relation.MiddleComponentData;
+import org.jboss.envers.entities.mapper.id.QueryParameterData;
+import org.jboss.envers.configuration.VersionsEntitiesConfiguration;
+import org.jboss.envers.reader.VersionsReaderImplementor;
+import org.jboss.envers.RevisionType;
+import org.jboss.envers.tools.query.QueryBuilder;
+import org.jboss.envers.tools.query.Parameters;
+import org.hibernate.Query;
+
+import java.util.Collections;
+
+/**
+ * Selects data from a relation middle-table only.
+ * @author Adam Warski (adam at warski dot org)
+ */
+public final class OneEntityQueryGenerator implements RelationQueryGenerator {
+ private final String queryString;
+ private final MiddleIdData referencingIdData;
+
+ public OneEntityQueryGenerator(VersionsEntitiesConfiguration verEntCfg,
+ String versionsMiddleEntityName,
+ MiddleIdData referencingIdData,
+ MiddleComponentData... componentDatas) {
+ this.referencingIdData = referencingIdData;
+
+ /*
+ * The query that we need to create:
+ * SELECT new list(ee) FROM middleEntity ee WHERE
+ * (only entities referenced by the association; id_ref_ing = id of the referencing entity)
+ * ee.originalId.id_ref_ing = :id_ref_ing AND
+ * (the association at revision :revision)
+ * ee.revision = (SELECT max(ee2.revision) FROM middleEntity ee2
+ * WHERE ee2.revision <= :revision AND ee2.originalId.* = ee.originalId.*) AND
+ * (only non-deleted entities and associations)
+ * ee.revision_type != DEL
+ */
+ String revisionPropertyPath = verEntCfg.getRevisionPropPath();
+ String originalIdPropertyName = verEntCfg.getOriginalIdPropName();
+
+ // SELECT new list(ee) FROM middleEntity ee
+ QueryBuilder qb = new QueryBuilder(versionsMiddleEntityName, "ee");
+ qb.addProjection("new list", "ee", false, false);
+ // WHERE
+ Parameters rootParameters = qb.getRootParameters();
+ // ee.originalId.id_ref_ing = :id_ref_ing
+ referencingIdData.getPrefixedMapper().addNamedIdEqualsToQuery(rootParameters, originalIdPropertyName, true);
+ // SELECT max(ee2.revision) FROM middleEntity ee2
+ QueryBuilder maxRevQb = qb.newSubQueryBuilder(versionsMiddleEntityName, "ee2");
+ maxRevQb.addProjection("max", revisionPropertyPath, false);
+ // WHERE
+ Parameters maxRevQbParameters = maxRevQb.getRootParameters();
+ // ee2.revision <= :revision
+ maxRevQbParameters.addWhereWithNamedParam(revisionPropertyPath, "<=", "revision");
+ // ee2.originalId.* = ee.originalId.*
+ String eeOriginalIdPropertyPath = "ee." + originalIdPropertyName;
+ String ee2OriginalIdPropertyPath = "ee2." + originalIdPropertyName;
+ referencingIdData.getPrefixedMapper().addIdsEqualToQuery(maxRevQbParameters, eeOriginalIdPropertyPath, ee2OriginalIdPropertyPath);
+ for (MiddleComponentData componentData : componentDatas) {
+ componentData.getComponentMapper().addMiddleEqualToQuery(maxRevQbParameters, eeOriginalIdPropertyPath, ee2OriginalIdPropertyPath);
+ }
+ // ee.revision = (SELECT max(...) ...)
+ rootParameters.addWhere(revisionPropertyPath, "=", maxRevQb);
+ // ee.revision_type != DEL
+ rootParameters.addWhereWithNamedParam(verEntCfg.getRevisionTypePropName(), "!=", "delrevisiontype");
+
+ StringBuilder sb = new StringBuilder();
+ qb.build(sb, Collections.<String, Object>emptyMap());
+ queryString = sb.toString();
+ }
+
+ public Query getQuery(VersionsReaderImplementor versionsReader, Object primaryKey, Number revision) {
+ Query query = versionsReader.getSession().createQuery(queryString);
+ query.setParameter("revision", revision);
+ query.setParameter("delrevisiontype", RevisionType.DEL);
+ for (QueryParameterData paramData: referencingIdData.getPrefixedMapper().mapToQueryParametersFromId(primaryKey)) {
+ paramData.setParameterValue(query);
+ }
+
+ return query;
+ }
+}
Added: core/trunk/envers/src/main/java/org/jboss/envers/entities/mapper/relation/query/OneVersionsEntityQueryGenerator.java
===================================================================
--- core/trunk/envers/src/main/java/org/jboss/envers/entities/mapper/relation/query/OneVersionsEntityQueryGenerator.java (rev 0)
+++ core/trunk/envers/src/main/java/org/jboss/envers/entities/mapper/relation/query/OneVersionsEntityQueryGenerator.java 2008-10-27 18:56:31 UTC (rev 15406)
@@ -0,0 +1,109 @@
+/*
+ * JBoss, Home of Professional Open Source
+ *
+ * Copyright 2008, Red Hat Middleware LLC, and others contributors as indicated
+ * by the @authors tag. All rights reserved.
+ *
+ * See the copyright.txt in the distribution for a full listing of individual
+ * contributors. 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, v. 2.1.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT A 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, v.2.1 along with this distribution; if not, write to the Free
+ * Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+ * 02110-1301, USA.
+ *
+ * Red Hat Author(s): Adam Warski
+ */
+package org.jboss.envers.entities.mapper.relation.query;
+
+import org.jboss.envers.entities.mapper.id.QueryParameterData;
+import org.jboss.envers.entities.mapper.id.IdMapper;
+import org.jboss.envers.entities.mapper.relation.MiddleIdData;
+import org.jboss.envers.configuration.VersionsEntitiesConfiguration;
+import org.jboss.envers.configuration.GlobalConfiguration;
+import org.jboss.envers.reader.VersionsReaderImplementor;
+import org.jboss.envers.RevisionType;
+import org.jboss.envers.tools.query.QueryBuilder;
+import org.jboss.envers.tools.query.Parameters;
+import org.hibernate.Query;
+
+import java.util.Collections;
+
+/**
+ * Selects data from a versions entity.
+ * @author Adam Warski (adam at warski dot org)
+ */
+public final class OneVersionsEntityQueryGenerator implements RelationQueryGenerator {
+ private final String queryString;
+ private final MiddleIdData referencingIdData;
+
+ public OneVersionsEntityQueryGenerator(GlobalConfiguration globalCfg, VersionsEntitiesConfiguration verEntCfg,
+ MiddleIdData referencingIdData, String referencedEntityName,
+ IdMapper referencedIdMapper) {
+ this.referencingIdData = referencingIdData;
+
+ /*
+ * The query that we need to create:
+ * SELECT new list(e) FROM versionsReferencedEntity e
+ * WHERE
+ * (only entities referenced by the association; id_ref_ing = id of the referencing entity)
+ * e.id_ref_ing = :id_ref_ing AND
+ * (selecting e entities at revision :revision)
+ * e.revision = (SELECT max(e2.revision) FROM versionsReferencedEntity e2
+ * WHERE e2.revision <= :revision AND e2.id = e.id) AND
+ * (only non-deleted entities)
+ * e.revision_type != DEL
+ */
+ String revisionPropertyPath = verEntCfg.getRevisionPropPath();
+ String originalIdPropertyName = verEntCfg.getOriginalIdPropName();
+
+ String versionsReferencedEntityName = verEntCfg.getVersionsEntityName(referencedEntityName);
+
+ // SELECT new list(e) FROM versionsEntity e
+ QueryBuilder qb = new QueryBuilder(versionsReferencedEntityName, "e");
+ qb.addProjection("new list", "e", false, false);
+ // WHERE
+ Parameters rootParameters = qb.getRootParameters();
+ // e.id_ref_ed = :id_ref_ed
+ referencingIdData.getPrefixedMapper().addNamedIdEqualsToQuery(rootParameters, null, true);
+
+ // SELECT max(e.revision) FROM versionsReferencedEntity e2
+ QueryBuilder maxERevQb = qb.newSubQueryBuilder(versionsReferencedEntityName, "e2");
+ maxERevQb.addProjection("max", revisionPropertyPath, false);
+ // WHERE
+ Parameters maxERevQbParameters = maxERevQb.getRootParameters();
+ // e2.revision <= :revision
+ maxERevQbParameters.addWhereWithNamedParam(revisionPropertyPath, "<=", "revision");
+ // e2.id = e.id
+ referencedIdMapper.addIdsEqualToQuery(maxERevQbParameters,
+ "e." + originalIdPropertyName, "e2." + originalIdPropertyName);
+
+ // e.revision = (SELECT max(...) ...)
+ rootParameters.addWhere(revisionPropertyPath, false, globalCfg.getCorrelatedSubqueryOperator(), maxERevQb);
+
+ // e.revision_type != DEL
+ rootParameters.addWhereWithNamedParam(verEntCfg.getRevisionTypePropName(), false, "!=", "delrevisiontype");
+
+ StringBuilder sb = new StringBuilder();
+ qb.build(sb, Collections.<String, Object>emptyMap());
+ queryString = sb.toString();
+ }
+
+ public Query getQuery(VersionsReaderImplementor versionsReader, Object primaryKey, Number revision) {
+ Query query = versionsReader.getSession().createQuery(queryString);
+ query.setParameter("revision", revision);
+ query.setParameter("delrevisiontype", RevisionType.DEL);
+ for (QueryParameterData paramData: referencingIdData.getPrefixedMapper().mapToQueryParametersFromId(primaryKey)) {
+ paramData.setParameterValue(query);
+ }
+
+ return query;
+ }
+}
\ No newline at end of file
Added: core/trunk/envers/src/main/java/org/jboss/envers/entities/mapper/relation/query/QueryGeneratorTools.java
===================================================================
--- core/trunk/envers/src/main/java/org/jboss/envers/entities/mapper/relation/query/QueryGeneratorTools.java (rev 0)
+++ core/trunk/envers/src/main/java/org/jboss/envers/entities/mapper/relation/query/QueryGeneratorTools.java 2008-10-27 18:56:31 UTC (rev 15406)
@@ -0,0 +1,75 @@
+/*
+ * JBoss, Home of Professional Open Source
+ *
+ * Copyright 2008, Red Hat Middleware LLC, and others contributors as indicated
+ * by the @authors tag. All rights reserved.
+ *
+ * See the copyright.txt in the distribution for a full listing of individual
+ * contributors. 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, v. 2.1.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT A 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, v.2.1 along with this distribution; if not, write to the Free
+ * Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+ * 02110-1301, USA.
+ *
+ * Red Hat Author(s): Adam Warski
+ */
+package org.jboss.envers.entities.mapper.relation.query;
+
+import org.jboss.envers.tools.query.QueryBuilder;
+import org.jboss.envers.tools.query.Parameters;
+import org.jboss.envers.entities.mapper.relation.MiddleIdData;
+import org.jboss.envers.entities.mapper.relation.MiddleComponentData;
+import org.jboss.envers.configuration.GlobalConfiguration;
+
+/**
+ * @author Adam Warski (adam at warski dot org)
+ */
+public class QueryGeneratorTools {
+ public static void addEntityAtRevision(GlobalConfiguration globalCfg, QueryBuilder qb, Parameters rootParameters,
+ MiddleIdData idData, String revisionPropertyPath, String originalIdPropertyName,
+ String alias1, String alias2) {
+ // SELECT max(e.revision) FROM versionsReferencedEntity e2
+ QueryBuilder maxERevQb = qb.newSubQueryBuilder(idData.getVersionsEntityName(), alias2);
+ maxERevQb.addProjection("max", revisionPropertyPath, false);
+ // WHERE
+ Parameters maxERevQbParameters = maxERevQb.getRootParameters();
+ // e2.revision <= :revision
+ maxERevQbParameters.addWhereWithNamedParam(revisionPropertyPath, "<=", "revision");
+ // e2.id_ref_ed = e.id_ref_ed
+ idData.getOriginalMapper().addIdsEqualToQuery(maxERevQbParameters,
+ alias1 + "." + originalIdPropertyName, alias2 +"." + originalIdPropertyName);
+
+ // e.revision = (SELECT max(...) ...)
+ rootParameters.addWhere("e." + revisionPropertyPath, false, globalCfg.getCorrelatedSubqueryOperator(), maxERevQb);
+ }
+
+ public static void addAssociationAtRevision(QueryBuilder qb, Parameters rootParameters,
+ MiddleIdData referencingIdData, String versionsMiddleEntityName,
+ String eeOriginalIdPropertyPath, String revisionPropertyPath,
+ String originalIdPropertyName, MiddleComponentData... componentDatas) {
+ // SELECT max(ee2.revision) FROM middleEntity ee2
+ QueryBuilder maxEeRevQb = qb.newSubQueryBuilder(versionsMiddleEntityName, "ee2");
+ maxEeRevQb.addProjection("max", revisionPropertyPath, false);
+ // WHERE
+ Parameters maxEeRevQbParameters = maxEeRevQb.getRootParameters();
+ // ee2.revision <= :revision
+ maxEeRevQbParameters.addWhereWithNamedParam(revisionPropertyPath, "<=", "revision");
+ // ee2.originalId.* = ee.originalId.*
+ String ee2OriginalIdPropertyPath = "ee2." + originalIdPropertyName;
+ referencingIdData.getPrefixedMapper().addIdsEqualToQuery(maxEeRevQbParameters, eeOriginalIdPropertyPath, ee2OriginalIdPropertyPath);
+ for (MiddleComponentData componentData : componentDatas) {
+ componentData.getComponentMapper().addMiddleEqualToQuery(maxEeRevQbParameters, eeOriginalIdPropertyPath, ee2OriginalIdPropertyPath);
+ }
+
+ // ee.revision = (SELECT max(...) ...)
+ rootParameters.addWhere(revisionPropertyPath, "=", maxEeRevQb);
+ }
+}
Added: core/trunk/envers/src/main/java/org/jboss/envers/entities/mapper/relation/query/RelationQueryGenerator.java
===================================================================
--- core/trunk/envers/src/main/java/org/jboss/envers/entities/mapper/relation/query/RelationQueryGenerator.java (rev 0)
+++ core/trunk/envers/src/main/java/org/jboss/envers/entities/mapper/relation/query/RelationQueryGenerator.java 2008-10-27 18:56:31 UTC (rev 15406)
@@ -0,0 +1,37 @@
+/*
+ * JBoss, Home of Professional Open Source
+ *
+ * Copyright 2008, Red Hat Middleware LLC, and others contributors as indicated
+ * by the @authors tag. All rights reserved.
+ *
+ * See the copyright.txt in the distribution for a full listing of individual
+ * contributors. 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, v. 2.1.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT A 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, v.2.1 along with this distribution; if not, write to the Free
+ * Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+ * 02110-1301, USA.
+ *
+ * Red Hat Author(s): Adam Warski
+ */
+package org.jboss.envers.entities.mapper.relation.query;
+
+import org.hibernate.Query;
+import org.jboss.envers.reader.VersionsReaderImplementor;
+
+/**
+ * Implementations of this interface provide a method to generate queries on a relation table (a table used
+ * for mapping relations). The query can select, apart from selecting the content of the relation table, also data of
+ * other "related" entities.
+ * @author Adam Warski (adam at warski dot org)
+ */
+public interface RelationQueryGenerator {
+ Query getQuery(VersionsReaderImplementor versionsReader, Object primaryKey, Number revision);
+}
Added: core/trunk/envers/src/main/java/org/jboss/envers/entities/mapper/relation/query/ThreeEntityQueryGenerator.java
===================================================================
--- core/trunk/envers/src/main/java/org/jboss/envers/entities/mapper/relation/query/ThreeEntityQueryGenerator.java (rev 0)
+++ core/trunk/envers/src/main/java/org/jboss/envers/entities/mapper/relation/query/ThreeEntityQueryGenerator.java 2008-10-27 18:56:31 UTC (rev 15406)
@@ -0,0 +1,135 @@
+/*
+ * JBoss, Home of Professional Open Source
+ *
+ * Copyright 2008, Red Hat Middleware LLC, and others contributors as indicated
+ * by the @authors tag. All rights reserved.
+ *
+ * See the copyright.txt in the distribution for a full listing of individual
+ * contributors. 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, v. 2.1.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT A 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, v.2.1 along with this distribution; if not, write to the Free
+ * Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+ * 02110-1301, USA.
+ *
+ * Red Hat Author(s): Adam Warski
+ */
+package org.jboss.envers.entities.mapper.relation.query;
+
+import org.jboss.envers.entities.mapper.id.QueryParameterData;
+import org.jboss.envers.entities.mapper.relation.MiddleIdData;
+import org.jboss.envers.entities.mapper.relation.MiddleComponentData;
+import org.jboss.envers.configuration.VersionsEntitiesConfiguration;
+import org.jboss.envers.configuration.GlobalConfiguration;
+import org.jboss.envers.reader.VersionsReaderImplementor;
+import org.jboss.envers.RevisionType;
+import org.jboss.envers.tools.query.QueryBuilder;
+import org.jboss.envers.tools.query.Parameters;
+import org.hibernate.Query;
+
+import java.util.Collections;
+
+/**
+ * Selects data from a relation middle-table and a two related versions entity.
+ * @author Adam Warski (adam at warski dot org)
+ */
+public final class ThreeEntityQueryGenerator implements RelationQueryGenerator {
+ private final String queryString;
+ private final MiddleIdData referencingIdData;
+
+ public ThreeEntityQueryGenerator(GlobalConfiguration globalCfg,
+ VersionsEntitiesConfiguration verEntCfg,
+ String versionsMiddleEntityName,
+ MiddleIdData referencingIdData,
+ MiddleIdData referencedIdData,
+ MiddleIdData indexIdData,
+ MiddleComponentData... componentDatas) {
+ this.referencingIdData = referencingIdData;
+
+ /*
+ * The query that we need to create:
+ * SELECT new list(ee, e, f) FROM versionsReferencedEntity e, versionsIndexEntity f, middleEntity ee
+ * WHERE
+ * (entities referenced by the middle table; id_ref_ed = id of the referenced entity)
+ * ee.id_ref_ed = e.id_ref_ed AND
+ * (entities referenced by the middle table; id_ref_ind = id of the index entity)
+ * ee.id_ref_ind = f.id_ref_ind AND
+ * (only entities referenced by the association; id_ref_ing = id of the referencing entity)
+ * ee.id_ref_ing = :id_ref_ing AND
+ * (selecting e entities at revision :revision)
+ * e.revision = (SELECT max(e2.revision) FROM versionsReferencedEntity e2
+ * WHERE e2.revision <= :revision AND e2.id_ref_ed = e.id_ref_ed) AND
+ * (selecting f entities at revision :revision)
+ * f.revision = (SELECT max(f2.revision) FROM versionsIndexEntity f2
+ * WHERE f2.revision <= :revision AND f2.id_ref_ed = f.id_ref_ed) AND
+ * (the association at revision :revision)
+ * ee.revision = (SELECT max(ee2.revision) FROM middleEntity ee2
+ * WHERE ee2.revision <= :revision AND ee2.originalId.* = ee.originalId.*) AND
+ * (only non-deleted entities and associations)
+ * ee.revision_type != DEL AND
+ * e.revision_type != DEL AND
+ * f.revision_type != DEL
+ */
+ String revisionPropertyPath = verEntCfg.getRevisionPropPath();
+ String originalIdPropertyName = verEntCfg.getOriginalIdPropName();
+
+ String eeOriginalIdPropertyPath = "ee." + originalIdPropertyName;
+
+ // SELECT new list(ee) FROM middleEntity ee
+ QueryBuilder qb = new QueryBuilder(versionsMiddleEntityName, "ee");
+ qb.addFrom(referencedIdData.getVersionsEntityName(), "e");
+ qb.addFrom(indexIdData.getVersionsEntityName(), "f");
+ qb.addProjection("new list", "ee, e, f", false, false);
+ // WHERE
+ Parameters rootParameters = qb.getRootParameters();
+ // ee.id_ref_ed = e.id_ref_ed
+ referencedIdData.getPrefixedMapper().addIdsEqualToQuery(rootParameters, eeOriginalIdPropertyPath,
+ referencedIdData.getOriginalMapper(), "e." + originalIdPropertyName);
+ // ee.id_ref_ind = f.id_ref_ind
+ indexIdData.getPrefixedMapper().addIdsEqualToQuery(rootParameters, eeOriginalIdPropertyPath,
+ indexIdData.getOriginalMapper(), "f." + originalIdPropertyName);
+ // ee.originalId.id_ref_ing = :id_ref_ing
+ referencingIdData.getPrefixedMapper().addNamedIdEqualsToQuery(rootParameters, originalIdPropertyName, true);
+
+ // e.revision = (SELECT max(...) ...)
+ QueryGeneratorTools.addEntityAtRevision(globalCfg, qb, rootParameters, referencedIdData, revisionPropertyPath,
+ originalIdPropertyName, "e", "e2");
+
+ // f.revision = (SELECT max(...) ...)
+ QueryGeneratorTools.addEntityAtRevision(globalCfg, qb, rootParameters, indexIdData, revisionPropertyPath,
+ originalIdPropertyName, "f", "f2");
+
+ // ee.revision = (SELECT max(...) ...)
+ QueryGeneratorTools.addAssociationAtRevision(qb, rootParameters, referencingIdData, versionsMiddleEntityName,
+ eeOriginalIdPropertyPath, revisionPropertyPath, originalIdPropertyName, componentDatas);
+
+ // ee.revision_type != DEL
+ rootParameters.addWhereWithNamedParam(verEntCfg.getRevisionTypePropName(), "!=", "delrevisiontype");
+ // e.revision_type != DEL
+ rootParameters.addWhereWithNamedParam("e." + verEntCfg.getRevisionTypePropName(), false, "!=", "delrevisiontype");
+ // f.revision_type != DEL
+ rootParameters.addWhereWithNamedParam("f." + verEntCfg.getRevisionTypePropName(), false, "!=", "delrevisiontype");
+
+ StringBuilder sb = new StringBuilder();
+ qb.build(sb, Collections.<String, Object>emptyMap());
+ queryString = sb.toString();
+ }
+
+ public Query getQuery(VersionsReaderImplementor versionsReader, Object primaryKey, Number revision) {
+ Query query = versionsReader.getSession().createQuery(queryString);
+ query.setParameter("revision", revision);
+ query.setParameter("delrevisiontype", RevisionType.DEL);
+ for (QueryParameterData paramData: referencingIdData.getPrefixedMapper().mapToQueryParametersFromId(primaryKey)) {
+ paramData.setParameterValue(query);
+ }
+
+ return query;
+ }
+}
Added: core/trunk/envers/src/main/java/org/jboss/envers/entities/mapper/relation/query/TwoEntityQueryGenerator.java
===================================================================
--- core/trunk/envers/src/main/java/org/jboss/envers/entities/mapper/relation/query/TwoEntityQueryGenerator.java (rev 0)
+++ core/trunk/envers/src/main/java/org/jboss/envers/entities/mapper/relation/query/TwoEntityQueryGenerator.java 2008-10-27 18:56:31 UTC (rev 15406)
@@ -0,0 +1,118 @@
+/*
+ * JBoss, Home of Professional Open Source
+ *
+ * Copyright 2008, Red Hat Middleware LLC, and others contributors as indicated
+ * by the @authors tag. All rights reserved.
+ *
+ * See the copyright.txt in the distribution for a full listing of individual
+ * contributors. 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, v. 2.1.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT A 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, v.2.1 along with this distribution; if not, write to the Free
+ * Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+ * 02110-1301, USA.
+ *
+ * Red Hat Author(s): Adam Warski
+ */
+package org.jboss.envers.entities.mapper.relation.query;
+
+import org.jboss.envers.entities.mapper.id.QueryParameterData;
+import org.jboss.envers.entities.mapper.relation.MiddleIdData;
+import org.jboss.envers.entities.mapper.relation.MiddleComponentData;
+import org.jboss.envers.configuration.VersionsEntitiesConfiguration;
+import org.jboss.envers.configuration.GlobalConfiguration;
+import org.jboss.envers.reader.VersionsReaderImplementor;
+import org.jboss.envers.RevisionType;
+import org.jboss.envers.tools.query.QueryBuilder;
+import org.jboss.envers.tools.query.Parameters;
+import org.hibernate.Query;
+
+import java.util.Collections;
+
+/**
+ * Selects data from a relation middle-table and a related versions entity.
+ * @author Adam Warski (adam at warski dot org)
+ */
+public final class TwoEntityQueryGenerator implements RelationQueryGenerator {
+ private final String queryString;
+ private final MiddleIdData referencingIdData;
+
+ public TwoEntityQueryGenerator(GlobalConfiguration globalCfg,
+ VersionsEntitiesConfiguration verEntCfg,
+ String versionsMiddleEntityName,
+ MiddleIdData referencingIdData,
+ MiddleIdData referencedIdData,
+ MiddleComponentData... componentDatas) {
+ this.referencingIdData = referencingIdData;
+
+ /*
+ * The query that we need to create:
+ * SELECT new list(ee, e) FROM versionsReferencedEntity e, middleEntity ee
+ * WHERE
+ * (entities referenced by the middle table; id_ref_ed = id of the referenced entity)
+ * ee.id_ref_ed = e.id_ref_ed AND
+ * (only entities referenced by the association; id_ref_ing = id of the referencing entity)
+ * ee.id_ref_ing = :id_ref_ing AND
+ * (selecting e entities at revision :revision)
+ * e.revision = (SELECT max(e2.revision) FROM versionsReferencedEntity e2
+ * WHERE e2.revision <= :revision AND e2.id_ref_ed = e.id_ref_ed) AND
+ * (the association at revision :revision)
+ * ee.revision = (SELECT max(ee2.revision) FROM middleEntity ee2
+ * WHERE ee2.revision <= :revision AND ee2.originalId.* = ee.originalId.*) AND
+ * (only non-deleted entities and associations)
+ * ee.revision_type != DEL AND
+ * e.revision_type != DEL
+ */
+ String revisionPropertyPath = verEntCfg.getRevisionPropPath();
+ String originalIdPropertyName = verEntCfg.getOriginalIdPropName();
+
+ String eeOriginalIdPropertyPath = "ee." + originalIdPropertyName;
+
+ // SELECT new list(ee) FROM middleEntity ee
+ QueryBuilder qb = new QueryBuilder(versionsMiddleEntityName, "ee");
+ qb.addFrom(referencedIdData.getVersionsEntityName(), "e");
+ qb.addProjection("new list", "ee, e", false, false);
+ // WHERE
+ Parameters rootParameters = qb.getRootParameters();
+ // ee.id_ref_ed = e.id_ref_ed
+ referencedIdData.getPrefixedMapper().addIdsEqualToQuery(rootParameters, eeOriginalIdPropertyPath,
+ referencedIdData.getOriginalMapper(), "e." + originalIdPropertyName);
+ // ee.originalId.id_ref_ing = :id_ref_ing
+ referencingIdData.getPrefixedMapper().addNamedIdEqualsToQuery(rootParameters, originalIdPropertyName, true);
+
+ // e.revision = (SELECT max(...) ...)
+ QueryGeneratorTools.addEntityAtRevision(globalCfg, qb, rootParameters, referencedIdData, revisionPropertyPath,
+ originalIdPropertyName, "e", "e2");
+
+ // ee.revision = (SELECT max(...) ...)
+ QueryGeneratorTools.addAssociationAtRevision(qb, rootParameters, referencingIdData, versionsMiddleEntityName,
+ eeOriginalIdPropertyPath, revisionPropertyPath, originalIdPropertyName, componentDatas);
+
+ // ee.revision_type != DEL
+ rootParameters.addWhereWithNamedParam(verEntCfg.getRevisionTypePropName(), "!=", "delrevisiontype");
+ // e.revision_type != DEL
+ rootParameters.addWhereWithNamedParam("e." + verEntCfg.getRevisionTypePropName(), false, "!=", "delrevisiontype");
+
+ StringBuilder sb = new StringBuilder();
+ qb.build(sb, Collections.<String, Object>emptyMap());
+ queryString = sb.toString();
+ }
+
+ public Query getQuery(VersionsReaderImplementor versionsReader, Object primaryKey, Number revision) {
+ Query query = versionsReader.getSession().createQuery(queryString);
+ query.setParameter("revision", revision);
+ query.setParameter("delrevisiontype", RevisionType.DEL);
+ for (QueryParameterData paramData: referencingIdData.getPrefixedMapper().mapToQueryParametersFromId(primaryKey)) {
+ paramData.setParameterValue(query);
+ }
+
+ return query;
+ }
+}
Added: core/trunk/envers/src/main/java/org/jboss/envers/entity/VersionsInheritanceEntityPersister.java
===================================================================
--- core/trunk/envers/src/main/java/org/jboss/envers/entity/VersionsInheritanceEntityPersister.java (rev 0)
+++ core/trunk/envers/src/main/java/org/jboss/envers/entity/VersionsInheritanceEntityPersister.java 2008-10-27 18:56:31 UTC (rev 15406)
@@ -0,0 +1,45 @@
+/*
+ * Envers. http://www.jboss.org/envers
+ *
+ * Copyright 2008 Red Hat Middleware, LLC. All rights reserved.
+ *
+ * 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, v. 2.1.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT A 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, v.2.1 along with this distribution; if not, write to the Free
+ * Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+ * 02110-1301, USA.
+ *
+ * Red Hat Author(s): Adam Warski
+ */
+package org.jboss.envers.entity;
+
+import org.hibernate.persister.entity.SingleTableEntityPersister;
+import org.hibernate.persister.entity.EntityPersister;
+import org.hibernate.mapping.PersistentClass;
+import org.hibernate.cache.access.EntityRegionAccessStrategy;
+import org.hibernate.engine.SessionFactoryImplementor;
+import org.hibernate.engine.Mapping;
+import org.hibernate.HibernateException;
+import org.hibernate.EntityMode;
+
+/**
+ * @author Adam Warski (adam at warski dot org)
+ */
+public class VersionsInheritanceEntityPersister extends SingleTableEntityPersister {
+ public VersionsInheritanceEntityPersister(PersistentClass persistentClass, EntityRegionAccessStrategy entityRegionAccessStrategy, SessionFactoryImplementor factory, Mapping mapping) throws HibernateException {
+ super(persistentClass, entityRegionAccessStrategy, factory, mapping);
+ }
+
+ // A hack for http://opensource.atlassian.com/projects/hibernate/browse/HHH-3351
+ public EntityPersister getSubclassEntityPersister(Object instance, SessionFactoryImplementor factory, EntityMode entityMode) {
+ return this;
+ }
+}
\ No newline at end of file
Added: core/trunk/envers/src/main/java/org/jboss/envers/event/VersionsEventListener.java
===================================================================
--- core/trunk/envers/src/main/java/org/jboss/envers/event/VersionsEventListener.java (rev 0)
+++ core/trunk/envers/src/main/java/org/jboss/envers/event/VersionsEventListener.java 2008-10-27 18:56:31 UTC (rev 15406)
@@ -0,0 +1,198 @@
+/*
+ * Envers. http://www.jboss.org/envers
+ *
+ * Copyright 2008 Red Hat Middleware, LLC. All rights reserved.
+ *
+ * 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, v. 2.1.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT A 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, v.2.1 along with this distribution; if not, write to the Free
+ * Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+ * 02110-1301, USA.
+ *
+ * Red Hat Author(s): Adam Warski
+ */
+package org.jboss.envers.event;
+
+import org.hibernate.event.*;
+import org.hibernate.cfg.Configuration;
+import org.hibernate.persister.entity.EntityPersister;
+import org.hibernate.engine.CollectionEntry;
+import org.hibernate.collection.PersistentCollection;
+import org.jboss.envers.configuration.VersionsConfiguration;
+import org.jboss.envers.entities.RelationDescription;
+import org.jboss.envers.entities.RelationType;
+import org.jboss.envers.synchronization.VersionsSync;
+import org.jboss.envers.synchronization.work.*;
+import org.jboss.envers.tools.Tools;
+import org.jboss.envers.entities.mapper.id.IdMapper;
+import org.jboss.envers.entities.mapper.PersistentCollectionChangeData;
+
+import java.io.Serializable;
+
+/**
+ * @author Adam Warski (adam at warski dot org)
+ */
+public class VersionsEventListener implements PostInsertEventListener, PostUpdateEventListener,
+ PostDeleteEventListener, PreCollectionUpdateEventListener, PreCollectionRemoveEventListener,
+ PostCollectionRecreateEventListener, Initializable {
+ private VersionsConfiguration verCfg;
+
+ private void generateBidirectionalCollectionChangeWorkUnits(VersionsSync verSync, EntityPersister entityPersister,
+ String entityName, Object[] newState, Object[] oldState) {
+ // Checking if this is enabled in configuration ...
+ if (!verCfg.getGlobalCfg().isGenerateRevisionsForCollections()) {
+ return;
+ }
+
+ // Checks every property of the entity, if it is an "owned" to-one relation to another entity.
+ // If the value of that property changed, and the relation is bi-directional, a new revision
+ // for the related entity is generated.
+ String[] propertyNames = entityPersister.getPropertyNames();
+
+ for (int i=0; i<propertyNames.length; i++) {
+ String propertyName = propertyNames[i];
+ RelationDescription relDesc = verCfg.getEntCfg().getRelationDescription(entityName, propertyName);
+ if (relDesc != null && relDesc.isBidirectional() && relDesc.getRelationType() == RelationType.TO_ONE) {
+ // Checking for changes
+ Object oldValue = oldState == null ? null : oldState[i];
+ Object newValue = newState == null ? null : newState[i];
+
+ if (!Tools.objectsEqual(oldValue, newValue)) {
+ IdMapper idMapper = verCfg.getEntCfg().get(relDesc.getToEntityName()).getIdMapper();
+
+ // We have to generate changes both in the old collection (size decreses) and new collection
+ // (size increases).
+ if (newValue != null) {
+ Serializable id = (Serializable) idMapper.mapToIdFromEntity(newValue);
+ verSync.addWorkUnit(new CollectionChangeWorkUnit(relDesc.getToEntityName(), verCfg, id, newValue));
+ }
+
+ if (oldValue != null) {
+ Serializable id = (Serializable) idMapper.mapToIdFromEntity(oldValue);
+ verSync.addWorkUnit(new CollectionChangeWorkUnit(relDesc.getToEntityName(), verCfg, id, oldValue));
+ }
+ }
+ }
+ }
+ }
+
+ public void onPostInsert(PostInsertEvent event) {
+ String entityName = event.getPersister().getEntityName();
+
+ if (verCfg.getEntCfg().isVersioned(entityName)) {
+ VersionsSync verSync = verCfg.getSyncManager().get(event.getSession());
+
+ verSync.addWorkUnit(new AddWorkUnit(event.getPersister().getEntityName(), verCfg, event.getId(),
+ event.getPersister(), event.getState()));
+
+ generateBidirectionalCollectionChangeWorkUnits(verSync, event.getPersister(), entityName, event.getState(), null);
+ }
+ }
+
+ public void onPostUpdate(PostUpdateEvent event) {
+ String entityName = event.getPersister().getEntityName();
+
+ if (verCfg.getEntCfg().isVersioned(entityName)) {
+ VersionsSync verSync = verCfg.getSyncManager().get(event.getSession());
+
+ verSync.addWorkUnit(new ModWorkUnit(event.getPersister().getEntityName(), verCfg, event.getId(),
+ event.getPersister(), event.getState(), event.getOldState()));
+
+ generateBidirectionalCollectionChangeWorkUnits(verSync, event.getPersister(), entityName, event.getState(), event.getOldState());
+ }
+ }
+
+ public void onPostDelete(PostDeleteEvent event) {
+ String entityName = event.getPersister().getEntityName();
+
+ if (verCfg.getEntCfg().isVersioned(entityName)) {
+ VersionsSync verSync = verCfg.getSyncManager().get(event.getSession());
+
+ verSync.addWorkUnit(new DelWorkUnit(event.getPersister().getEntityName(), verCfg, event.getId()));
+
+ generateBidirectionalCollectionChangeWorkUnits(verSync, event.getPersister(), entityName, null, event.getDeletedState());
+ }
+ }
+
+ private void generateBidirectionalCollectionChangeWorkUnits(VersionsSync verSync, AbstractCollectionEvent event,
+ PersistentCollectionChangeWorkUnit workUnit) {
+ // Checking if this is enabled in configuration ...
+ if (!verCfg.getGlobalCfg().isGenerateRevisionsForCollections()) {
+ return;
+ }
+
+ // Checking if this is not a bidirectional relation - then, a revision needs also be generated for
+ // the other side of the relation.
+ RelationDescription relDesc = verCfg.getEntCfg().getRelationDescription(event.getAffectedOwnerEntityName(),
+ workUnit.getReferencingPropertyName());
+
+ // relDesc can be null if this is a collection of simple values (not a relation).
+ if (relDesc != null && relDesc.isBidirectional()) {
+ String relatedEntityName = relDesc.getToEntityName();
+ IdMapper relatedIdMapper = verCfg.getEntCfg().get(relatedEntityName).getIdMapper();
+
+ for (PersistentCollectionChangeData changeData : workUnit.getCollectionChanges()) {
+ Object relatedObj = changeData.getChangedElement();
+ Serializable relatedId = (Serializable) relatedIdMapper.mapToIdFromEntity(relatedObj);
+
+ verSync.addWorkUnit(new CollectionChangeWorkUnit(relatedEntityName, verCfg, relatedId, relatedObj));
+ }
+ }
+ }
+
+ private void onCollectionAction(AbstractCollectionEvent event, PersistentCollection newColl, Serializable oldColl,
+ CollectionEntry collectionEntry) {
+ String entityName = event.getAffectedOwnerEntityName();
+
+ if (verCfg.getEntCfg().isVersioned(entityName)) {
+ VersionsSync verSync = verCfg.getSyncManager().get(event.getSession());
+
+ PersistentCollectionChangeWorkUnit workUnit = new PersistentCollectionChangeWorkUnit(entityName, verCfg,
+ newColl, collectionEntry.getRole(), oldColl, event.getAffectedOwnerIdOrNull());
+ verSync.addWorkUnit(workUnit);
+
+ if (workUnit.containsWork()) {
+ // There are some changes: a revision needs also be generated for the collection owner
+ verSync.addWorkUnit(new CollectionChangeWorkUnit(event.getAffectedOwnerEntityName(), verCfg,
+ event.getAffectedOwnerIdOrNull(), event.getAffectedOwnerOrNull()));
+
+ generateBidirectionalCollectionChangeWorkUnits(verSync, event, workUnit);
+ }
+ }
+ }
+
+ private CollectionEntry getCollectionEntry(AbstractCollectionEvent event) {
+ return event.getSession().getPersistenceContext().getCollectionEntry(event.getCollection());
+ }
+
+ public void onPreUpdateCollection(PreCollectionUpdateEvent event) {
+ CollectionEntry collectionEntry = getCollectionEntry(event);
+ onCollectionAction(event, event.getCollection(), collectionEntry.getSnapshot(), collectionEntry);
+ }
+
+ public void onPreRemoveCollection(PreCollectionRemoveEvent event) {
+ CollectionEntry collectionEntry = getCollectionEntry(event);
+ onCollectionAction(event, null, collectionEntry.getSnapshot(), collectionEntry);
+ }
+
+ public void onPostRecreateCollection(PostCollectionRecreateEvent event) {
+ onCollectionAction(event, event.getCollection(), null, getCollectionEntry(event));
+ }
+
+ @SuppressWarnings({"unchecked"})
+ public void initialize(Configuration cfg) {
+ verCfg = VersionsConfiguration.getFor(cfg);
+ }
+
+ public VersionsConfiguration getVerCfg() {
+ return verCfg;
+ }
+}
Added: core/trunk/envers/src/main/java/org/jboss/envers/exception/NotVersionedException.java
===================================================================
--- core/trunk/envers/src/main/java/org/jboss/envers/exception/NotVersionedException.java (rev 0)
+++ core/trunk/envers/src/main/java/org/jboss/envers/exception/NotVersionedException.java 2008-10-27 18:56:31 UTC (rev 15406)
@@ -0,0 +1,38 @@
+/*
+ * Envers. http://www.jboss.org/envers
+ *
+ * Copyright 2008 Red Hat Middleware, LLC. All rights reserved.
+ *
+ * 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, v. 2.1.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT A 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, v.2.1 along with this distribution; if not, write to the Free
+ * Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+ * 02110-1301, USA.
+ *
+ * Red Hat Author(s): Adam Warski
+ */
+package org.jboss.envers.exception;
+
+/**
+ * @author Adam Warski (adam at warski dot org)
+ */
+public class NotVersionedException extends VersionsException {
+ private final String entityName;
+
+ public NotVersionedException(String entityName, String message) {
+ super(message);
+ this.entityName = entityName;
+ }
+
+ public String getEntityName() {
+ return entityName;
+ }
+}
Added: core/trunk/envers/src/main/java/org/jboss/envers/exception/RevisionDoesNotExistException.java
===================================================================
--- core/trunk/envers/src/main/java/org/jboss/envers/exception/RevisionDoesNotExistException.java (rev 0)
+++ core/trunk/envers/src/main/java/org/jboss/envers/exception/RevisionDoesNotExistException.java 2008-10-27 18:56:31 UTC (rev 15406)
@@ -0,0 +1,50 @@
+/*
+ * Envers. http://www.jboss.org/envers
+ *
+ * Copyright 2008 Red Hat Middleware, LLC. All rights reserved.
+ *
+ * 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, v. 2.1.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT A 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, v.2.1 along with this distribution; if not, write to the Free
+ * Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+ * 02110-1301, USA.
+ *
+ * Red Hat Author(s): Adam Warski
+ */
+package org.jboss.envers.exception;
+
+import java.util.Date;
+
+/**
+ * @author Adam Warski (adam at warski dot org)
+ */
+public class RevisionDoesNotExistException extends VersionsException {
+ private Number revision;
+ private Date date;
+
+ public RevisionDoesNotExistException(Number revision) {
+ super("Revision " + revision + " does not exist.");
+ this.revision = revision;
+ }
+
+ public RevisionDoesNotExistException(Date date) {
+ super("There is no revision before or at " + date + ".");
+ this.date = date;
+ }
+
+ public Number getRevision() {
+ return revision;
+ }
+
+ public Date getDate() {
+ return date;
+ }
+}
Added: core/trunk/envers/src/main/java/org/jboss/envers/exception/VersionsException.java
===================================================================
--- core/trunk/envers/src/main/java/org/jboss/envers/exception/VersionsException.java (rev 0)
+++ core/trunk/envers/src/main/java/org/jboss/envers/exception/VersionsException.java 2008-10-27 18:56:31 UTC (rev 15406)
@@ -0,0 +1,41 @@
+/*
+ * Envers. http://www.jboss.org/envers
+ *
+ * Copyright 2008 Red Hat Middleware, LLC. All rights reserved.
+ *
+ * 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, v. 2.1.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT A 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, v.2.1 along with this distribution; if not, write to the Free
+ * Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+ * 02110-1301, USA.
+ *
+ * Red Hat Author(s): Adam Warski
+ */
+package org.jboss.envers.exception;
+
+import org.hibernate.HibernateException;
+
+/**
+ * @author Adam Warski (adam at warski dot org)
+ */
+public class VersionsException extends HibernateException {
+ public VersionsException(String message) {
+ super(message);
+ }
+
+ public VersionsException(String message, Throwable cause) {
+ super(message, cause);
+ }
+
+ public VersionsException(Throwable cause) {
+ super(cause);
+ }
+}
Added: core/trunk/envers/src/main/java/org/jboss/envers/query/RevisionProperty.java
===================================================================
--- core/trunk/envers/src/main/java/org/jboss/envers/query/RevisionProperty.java (rev 0)
+++ core/trunk/envers/src/main/java/org/jboss/envers/query/RevisionProperty.java 2008-10-27 18:56:31 UTC (rev 15406)
@@ -0,0 +1,127 @@
+/*
+ * Envers. http://www.jboss.org/envers
+ *
+ * Copyright 2008 Red Hat Middleware, LLC. All rights reserved.
+ *
+ * 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, v. 2.1.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT A 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, v.2.1 along with this distribution; if not, write to the Free
+ * Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+ * 02110-1301, USA.
+ *
+ * Red Hat Author(s): Adam Warski
+ */
+package org.jboss.envers.query;
+
+import org.jboss.envers.query.criteria.VersionsCriterion;
+import org.jboss.envers.query.criteria.RevisionVersionsExpression;
+import org.jboss.envers.query.order.VersionsOrder;
+import org.jboss.envers.query.order.RevisionVersionsOrder;
+import org.jboss.envers.query.projection.VersionsProjection;
+import org.jboss.envers.query.projection.RevisionVersionsProjection;
+import org.jboss.envers.configuration.VersionsConfiguration;
+import org.jboss.envers.tools.Triple;
+
+/**
+ * @author Adam Warski (adam at warski dot org)
+ */
+ at SuppressWarnings({"JavaDoc"})
+public class RevisionProperty implements VersionsProjection {
+ private RevisionProperty() { }
+
+ /**
+ * Apply a "greater than" constraint on the revision number
+ */
+ public static VersionsCriterion gt(Integer revision) {
+ return new RevisionVersionsExpression(revision, ">");
+ }
+
+ /**
+ * Apply a "greater than or equal" constraint on the revision number
+ */
+ public static VersionsCriterion ge(Integer revision) {
+ return new RevisionVersionsExpression(revision, ">=");
+ }
+
+ /**
+ * Apply a "less than" constraint on the revision number
+ */
+ public static VersionsCriterion lt(Integer revision) {
+ return new RevisionVersionsExpression(revision, "<");
+ }
+
+ /**
+ * Apply a "less than or equal" constraint on the revision number
+ */
+ public static VersionsCriterion le(Integer revision) {
+ return new RevisionVersionsExpression(revision, "<=");
+ }
+
+ /**
+ * Sort the results by revision in ascending order
+ */
+ public static VersionsOrder asc() {
+ return new RevisionVersionsOrder(true);
+ }
+
+ /**
+ * Sort the results by revision in descending order
+ */
+ public static VersionsOrder desc() {
+ return new RevisionVersionsOrder(false);
+ }
+
+ /**
+ * Select the maximum revision
+ */
+ public static VersionsProjection max() {
+ return new RevisionVersionsProjection(RevisionVersionsProjection.ProjectionType.MAX);
+ }
+
+ /**
+ * Select the minimum revision
+ */
+ public static VersionsProjection min() {
+ return new RevisionVersionsProjection(RevisionVersionsProjection.ProjectionType.MIN);
+ }
+
+ /**
+ * Count revisions
+ */
+ public static VersionsProjection count() {
+ return new RevisionVersionsProjection(RevisionVersionsProjection.ProjectionType.COUNT);
+ }
+
+ /**
+ * Count distinct revisions
+ */
+ public static VersionsProjection countDistinct() {
+ return new RevisionVersionsProjection(RevisionVersionsProjection.ProjectionType.COUNT_DISTINCT);
+ }
+
+ /**
+ * Distinct revisions
+ */
+ public static VersionsProjection distinct() {
+ return new RevisionVersionsProjection(RevisionVersionsProjection.ProjectionType.DISTINCT);
+ }
+
+ /**
+ * Projection the revision number
+ */
+ public static VersionsProjection revisionNumber() {
+ return new RevisionProperty();
+ }
+
+ public Triple<String, String, Boolean> getData(VersionsConfiguration verCfg) {
+ return Triple.make(null, verCfg.getVerEntCfg().getRevisionPropPath(), false);
+ }
+}
Added: core/trunk/envers/src/main/java/org/jboss/envers/query/RevisionTypeProperty.java
===================================================================
--- core/trunk/envers/src/main/java/org/jboss/envers/query/RevisionTypeProperty.java (rev 0)
+++ core/trunk/envers/src/main/java/org/jboss/envers/query/RevisionTypeProperty.java 2008-10-27 18:56:31 UTC (rev 15406)
@@ -0,0 +1,45 @@
+/*
+ * Envers. http://www.jboss.org/envers
+ *
+ * Copyright 2008 Red Hat Middleware, LLC. All rights reserved.
+ *
+ * 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, v. 2.1.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT A 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, v.2.1 along with this distribution; if not, write to the Free
+ * Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+ * 02110-1301, USA.
+ *
+ * Red Hat Author(s): Adam Warski
+ */
+package org.jboss.envers.query;
+
+import org.jboss.envers.query.projection.VersionsProjection;
+import org.jboss.envers.configuration.VersionsConfiguration;
+import org.jboss.envers.tools.Triple;
+
+/**
+ * @author Adam Warski (adam at warski dot org)
+ */
+ at SuppressWarnings({"JavaDoc"})
+public class RevisionTypeProperty implements VersionsProjection {
+ private RevisionTypeProperty() { }
+
+ /**
+ * Projection on the revision type
+ */
+ public static VersionsProjection revisionType() {
+ return new RevisionTypeProperty();
+ }
+
+ public Triple<String, String, Boolean> getData(VersionsConfiguration verCfg) {
+ return Triple.make(null, verCfg.getVerEntCfg().getRevisionTypePropName(), false);
+ }
+}
\ No newline at end of file
Added: core/trunk/envers/src/main/java/org/jboss/envers/query/VersionsQuery.java
===================================================================
--- core/trunk/envers/src/main/java/org/jboss/envers/query/VersionsQuery.java (rev 0)
+++ core/trunk/envers/src/main/java/org/jboss/envers/query/VersionsQuery.java 2008-10-27 18:56:31 UTC (rev 15406)
@@ -0,0 +1,72 @@
+/*
+ * Envers. http://www.jboss.org/envers
+ *
+ * Copyright 2008 Red Hat Middleware, LLC. All rights reserved.
+ *
+ * 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, v. 2.1.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT A 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, v.2.1 along with this distribution; if not, write to the Free
+ * Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+ * 02110-1301, USA.
+ *
+ * Red Hat Author(s): Adam Warski
+ */
+package org.jboss.envers.query;
+
+import org.jboss.envers.query.criteria.VersionsCriterion;
+import org.jboss.envers.query.projection.VersionsProjection;
+import org.jboss.envers.query.order.VersionsOrder;
+import org.jboss.envers.exception.VersionsException;
+import org.hibernate.FlushMode;
+import org.hibernate.CacheMode;
+import org.hibernate.LockMode;
+
+import javax.persistence.NonUniqueResultException;
+import javax.persistence.NoResultException;
+import java.util.List;
+
+/**
+ * @author Adam Warski (adam at warski dot org)
+ * @see org.hibernate.Criteria
+ */
+public interface VersionsQuery {
+ List getResultList() throws VersionsException;
+
+ Object getSingleResult() throws VersionsException, NonUniqueResultException, NoResultException;
+
+ VersionsQuery add(VersionsCriterion criterion);
+
+ VersionsQuery addProjection(String function, String propertyName);
+
+ VersionsQuery addProjection(VersionsProjection projection);
+
+ VersionsQuery addOrder(String propertyName, boolean asc);
+
+ VersionsQuery addOrder(VersionsOrder order);
+
+ VersionsQuery setMaxResults(int maxResults);
+
+ VersionsQuery setFirstResult(int firstResult);
+
+ VersionsQuery setCacheable(boolean cacheable);
+
+ VersionsQuery setCacheRegion(String cacheRegion);
+
+ VersionsQuery setComment(String comment);
+
+ VersionsQuery setFlushMode(FlushMode flushMode);
+
+ VersionsQuery setCacheMode(CacheMode cacheMode);
+
+ VersionsQuery setTimeout(int timeout);
+
+ VersionsQuery setLockMode(LockMode lockMode);
+}
Added: core/trunk/envers/src/main/java/org/jboss/envers/query/VersionsQueryCreator.java
===================================================================
--- core/trunk/envers/src/main/java/org/jboss/envers/query/VersionsQueryCreator.java (rev 0)
+++ core/trunk/envers/src/main/java/org/jboss/envers/query/VersionsQueryCreator.java 2008-10-27 18:56:31 UTC (rev 15406)
@@ -0,0 +1,80 @@
+/*
+ * Envers. http://www.jboss.org/envers
+ *
+ * Copyright 2008 Red Hat Middleware, LLC. All rights reserved.
+ *
+ * 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, v. 2.1.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT A 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, v.2.1 along with this distribution; if not, write to the Free
+ * Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+ * 02110-1301, USA.
+ *
+ * Red Hat Author(s): Adam Warski
+ */
+package org.jboss.envers.query;
+
+import org.jboss.envers.reader.VersionsReaderImplementor;
+import org.jboss.envers.query.impl.EntitiesAtRevisionQuery;
+import org.jboss.envers.query.impl.RevisionsOfEntityQuery;
+import static org.jboss.envers.tools.ArgumentsTools.*;
+import org.jboss.envers.configuration.VersionsConfiguration;
+
+/**
+ * @author Adam Warski (adam at warski dot org)
+ */
+public class VersionsQueryCreator {
+ private final VersionsConfiguration verCfg;
+ private final VersionsReaderImplementor versionsReaderImplementor;
+
+ public VersionsQueryCreator(VersionsConfiguration verCfg, VersionsReaderImplementor versionsReaderImplementor) {
+ this.verCfg = verCfg;
+ this.versionsReaderImplementor = versionsReaderImplementor;
+ }
+
+ /**
+ * Creates a query, which will return entities satisfying some conditions (specified later),
+ * at a given revision.
+ * @param c Class of the entities for which to query.
+ * @param revision Revision number at which to execute the query.
+ * @return A query for entities at a given revision, to which conditions can be added and which
+ * can then be executed. The result of the query will be a list of entities (beans), unless a
+ * projection is added.
+ */
+ public VersionsQuery forEntitiesAtRevision(Class<?> c, Number revision) {
+ checkNotNull(revision, "Entity revision");
+ checkPositive(revision, "Entity revision");
+ return new EntitiesAtRevisionQuery(verCfg, versionsReaderImplementor, c, revision);
+ }
+
+ /**
+ * Creates a query, which selects the revisions, at which the given entity was modified.
+ * Unless an explicit projection is set, the result will be a list of three-element arrays, containing:
+ * <ol>
+ * <li>the entity instance</li>
+ * <li>revision entity, corresponding to the revision at which the entity was modified. If no custom
+ * revision entity is used, this will be an instance of {@link org.jboss.envers.DefaultRevisionEntity}</li>
+ * <li>type of the revision (an enum instance of class {@link org.jboss.envers.RevisionType})</li>.
+ * </ol>
+ * Additional conditions that the results must satisfy may be specified.
+ * @param c Class of the entities for which to query.
+ * @param selectEntitiesOnly If true, instead of a list of three-element arrays, a list of entites will be
+ * returned as a result of executing this query.
+ * @param selectDeletedEntities If true, also revisions where entities were deleted will be returned. The additional
+ * entities will have revision type "delete", and contain no data (all fields null), except for the id field.
+ * @return A query for revisions at which instances of the given entity were modified, to which
+ * conditions can be added (for example - a specific id of an entity of class <code>c</code>), and which
+ * can then be executed. The results of the query will be sorted in ascending order by the revision number,
+ * unless an order or projection is added.
+ */
+ public VersionsQuery forRevisionsOfEntity(Class<?> c, boolean selectEntitiesOnly, boolean selectDeletedEntities) {
+ return new RevisionsOfEntityQuery(verCfg, versionsReaderImplementor, c, selectEntitiesOnly,selectDeletedEntities);
+ }
+}
Added: core/trunk/envers/src/main/java/org/jboss/envers/query/VersionsRestrictions.java
===================================================================
--- core/trunk/envers/src/main/java/org/jboss/envers/query/VersionsRestrictions.java (rev 0)
+++ core/trunk/envers/src/main/java/org/jboss/envers/query/VersionsRestrictions.java 2008-10-27 18:56:31 UTC (rev 15406)
@@ -0,0 +1,242 @@
+/*
+ * Envers. http://www.jboss.org/envers
+ *
+ * Copyright 2008 Red Hat Middleware, LLC. All rights reserved.
+ *
+ * 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, v. 2.1.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT A 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, v.2.1 along with this distribution; if not, write to the Free
+ * Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+ * 02110-1301, USA.
+ *
+ * Red Hat Author(s): Adam Warski
+ */
+package org.jboss.envers.query;
+
+import org.jboss.envers.query.criteria.*;
+import org.hibernate.criterion.MatchMode;
+
+import java.util.Collection;
+
+/**
+ * TODO: ilike
+ * @author Adam Warski (adam at warski dot org)
+ * @see org.hibernate.criterion.Restrictions
+ */
+ at SuppressWarnings({"JavaDoc"})
+public class VersionsRestrictions {
+ private VersionsRestrictions() { }
+
+ /**
+ * Apply an "equal" constraint to the identifier property.
+ */
+ public static VersionsCriterion idEq(Object value) {
+ return new IdentifierEqVersionsExpression(value);
+ }
+
+ /**
+ * Apply an "equal" constraint to the named property
+ */
+ public static VersionsCriterion eq(String propertyName, Object value) {
+ return new SimpleVersionsExpression(propertyName, value, "=");
+ }
+
+ /**
+ * Apply a "not equal" constraint to the named property
+ */
+ public static VersionsCriterion ne(String propertyName, Object value) {
+ return new SimpleVersionsExpression(propertyName, value, "<>");
+ }
+
+ /**
+ * Apply an "equal" constraint on an id of a related entity
+ */
+ public static VersionsCriterion relatedIdEq(String propertyName, Object id) {
+ return new RelatedVersionsExpression(propertyName, id, true);
+ }
+
+ /**
+ * Apply a "not equal" constraint to the named property
+ */
+ public static VersionsCriterion relatedIdNe(String propertyName, Object id) {
+ return new RelatedVersionsExpression(propertyName, id, false);
+ }
+
+ /**
+ * Apply a "like" constraint to the named property
+ */
+ public static VersionsCriterion like(String propertyName, Object value) {
+ return new SimpleVersionsExpression(propertyName, value, " like ");
+ }
+
+ /**
+ * Apply a "like" constraint to the named property
+ */
+ public static VersionsCriterion like(String propertyName, String value, MatchMode matchMode) {
+ return new SimpleVersionsExpression(propertyName, matchMode.toMatchString(value), " like " );
+ }
+
+ /**
+ * Apply a "greater than" constraint to the named property
+ */
+ public static VersionsCriterion gt(String propertyName, Object value) {
+ return new SimpleVersionsExpression(propertyName, value, ">");
+ }
+
+ /**
+ * Apply a "less than" constraint to the named property
+ */
+ public static VersionsCriterion lt(String propertyName, Object value) {
+ return new SimpleVersionsExpression(propertyName, value, "<");
+ }
+
+ /**
+ * Apply a "less than or equal" constraint to the named property
+ */
+ public static VersionsCriterion le(String propertyName, Object value) {
+ return new SimpleVersionsExpression(propertyName, value, "<=");
+ }
+
+ /**
+ * Apply a "greater than or equal" constraint to the named property
+ */
+ public static VersionsCriterion ge(String propertyName, Object value) {
+ return new SimpleVersionsExpression(propertyName, value, ">=");
+ }
+
+ /**
+ * Apply a "between" constraint to the named property
+ */
+ public static VersionsCriterion between(String propertyName, Object lo, Object hi) {
+ return new BetweenVersionsExpression(propertyName, lo, hi);
+ }
+
+ /**
+ * Apply an "in" constraint to the named property
+ */
+ public static VersionsCriterion in(String propertyName, Object[] values) {
+ return new InVersionsExpression(propertyName, values);
+ }
+
+ /**
+ * Apply an "in" constraint to the named property
+ */
+ public static VersionsCriterion in(String propertyName, Collection values) {
+ return new InVersionsExpression(propertyName, values.toArray());
+ }
+
+ /**
+ * Apply an "is null" constraint to the named property
+ */
+ public static VersionsCriterion isNull(String propertyName) {
+ return new NullVersionsExpression(propertyName);
+ }
+
+ /**
+ * Apply an "equal" constraint to two properties
+ */
+ public static VersionsCriterion eqProperty(String propertyName, String otherPropertyName) {
+ return new PropertyVersionsExpression(propertyName, otherPropertyName, "=");
+ }
+
+ /**
+ * Apply a "not equal" constraint to two properties
+ */
+ public static VersionsCriterion neProperty(String propertyName, String otherPropertyName) {
+ return new PropertyVersionsExpression(propertyName, otherPropertyName, "<>");
+ }
+
+ /**
+ * Apply a "less than" constraint to two properties
+ */
+ public static VersionsCriterion ltProperty(String propertyName, String otherPropertyName) {
+ return new PropertyVersionsExpression(propertyName, otherPropertyName, "<");
+ }
+
+ /**
+ * Apply a "less than or equal" constraint to two properties
+ */
+ public static VersionsCriterion leProperty(String propertyName, String otherPropertyName) {
+ return new PropertyVersionsExpression(propertyName, otherPropertyName, "<=");
+ }
+
+ /**
+ * Apply a "greater than" constraint to two properties
+ */
+ public static VersionsCriterion gtProperty(String propertyName, String otherPropertyName) {
+ return new PropertyVersionsExpression(propertyName, otherPropertyName, ">");
+ }
+
+ /**
+ * Apply a "greater than or equal" constraint to two properties
+ */
+ public static VersionsCriterion geProperty(String propertyName, String otherPropertyName) {
+ return new PropertyVersionsExpression(propertyName, otherPropertyName, ">=");
+ }
+
+ /**
+ * Apply an "is not null" constraint to the named property
+ */
+ public static VersionsCriterion isNotNull(String propertyName) {
+ return new NotNullVersionsExpression(propertyName);
+ }
+
+ /**
+ * Return the conjuction of two expressions
+ */
+ public static VersionsCriterion and(VersionsCriterion lhs, VersionsCriterion rhs) {
+ return new LogicalVersionsExpression(lhs, rhs, "and");
+ }
+
+ /**
+ * Return the disjuction of two expressions
+ */
+ public static VersionsCriterion or(VersionsCriterion lhs, VersionsCriterion rhs) {
+ return new LogicalVersionsExpression(lhs, rhs, "or");
+ }
+
+ /**
+ * Return the negation of an expression
+ */
+ public static VersionsCriterion not(VersionsCriterion expression) {
+ return new NotVersionsExpression(expression);
+ }
+
+ /**
+ * Group expressions together in a single conjunction (A and B and C...)
+ */
+ public static VersionsConjunction conjunction() {
+ return new VersionsConjunction();
+ }
+
+ /**
+ * Group expressions together in a single disjunction (A or B or C...)
+ */
+ public static VersionsDisjunction disjunction() {
+ return new VersionsDisjunction();
+ }
+
+ /**
+ * Apply a "maximalize property" constraint.
+ */
+ public static AggregatedFieldVersionsExpression maximizeProperty(String propertyName) {
+ return new AggregatedFieldVersionsExpression(propertyName,
+ AggregatedFieldVersionsExpression.AggregatedMode.MAX);
+ }
+
+ /**
+ * Apply a "minimize property" constraint.
+ */
+ public static AggregatedFieldVersionsExpression minimizeProperty(String propertyName) {
+ return new AggregatedFieldVersionsExpression(propertyName,
+ AggregatedFieldVersionsExpression.AggregatedMode.MIN);
+ }
+}
Added: core/trunk/envers/src/main/java/org/jboss/envers/query/criteria/AggregatedFieldVersionsExpression.java
===================================================================
--- core/trunk/envers/src/main/java/org/jboss/envers/query/criteria/AggregatedFieldVersionsExpression.java (rev 0)
+++ core/trunk/envers/src/main/java/org/jboss/envers/query/criteria/AggregatedFieldVersionsExpression.java 2008-10-27 18:56:31 UTC (rev 15406)
@@ -0,0 +1,80 @@
+/*
+ * Envers. http://www.jboss.org/envers
+ *
+ * Copyright 2008 Red Hat Middleware, LLC. All rights reserved.
+ *
+ * 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, v. 2.1.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT A 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, v.2.1 along with this distribution; if not, write to the Free
+ * Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+ * 02110-1301, USA.
+ *
+ * Red Hat Author(s): Adam Warski
+ */
+package org.jboss.envers.query.criteria;
+
+import org.jboss.envers.configuration.VersionsConfiguration;
+import org.jboss.envers.tools.query.QueryBuilder;
+import org.jboss.envers.tools.query.Parameters;
+
+import java.util.List;
+import java.util.ArrayList;
+
+/**
+ * @author Adam Warski (adam at warski dot org)
+ */
+public class AggregatedFieldVersionsExpression implements VersionsCriterion, ExtendableCriterion {
+ public static enum AggregatedMode {
+ MAX,
+ MIN
+ }
+
+ private String propertyName;
+ private AggregatedMode mode;
+ private List<VersionsCriterion> criterions;
+
+ public AggregatedFieldVersionsExpression(String propertyName, AggregatedMode mode) {
+ this.propertyName = propertyName;
+ this.mode = mode;
+ criterions = new ArrayList<VersionsCriterion>();
+ }
+
+ public AggregatedFieldVersionsExpression add(VersionsCriterion criterion) {
+ criterions.add(criterion);
+ return this;
+ }
+
+ public void addToQuery(VersionsConfiguration verCfg, String entityName, QueryBuilder qb, Parameters parameters) {
+ CriteriaTools.checkPropertyNotARelation(verCfg, entityName, propertyName);
+
+ // This will be the aggregated query, containing all the specified conditions
+ QueryBuilder subQb = qb.newSubQueryBuilder();
+
+ // Adding all specified conditions both to the main query, as well as to the
+ // aggregated one.
+ for (VersionsCriterion versionsCriteria : criterions) {
+ versionsCriteria.addToQuery(verCfg, entityName, qb, parameters);
+ versionsCriteria.addToQuery(verCfg, entityName, subQb, subQb.getRootParameters());
+ }
+
+ // Setting the desired projection of the aggregated query
+ switch (mode) {
+ case MIN:
+ subQb.addProjection("min", propertyName, false);
+ break;
+ case MAX:
+ subQb.addProjection("max", propertyName, false);
+ }
+
+ // Adding the constrain on the result of the aggregated criteria
+ parameters.addWhere(propertyName, "=", subQb);
+ }
+}
\ No newline at end of file
Added: core/trunk/envers/src/main/java/org/jboss/envers/query/criteria/BetweenVersionsExpression.java
===================================================================
--- core/trunk/envers/src/main/java/org/jboss/envers/query/criteria/BetweenVersionsExpression.java (rev 0)
+++ core/trunk/envers/src/main/java/org/jboss/envers/query/criteria/BetweenVersionsExpression.java 2008-10-27 18:56:31 UTC (rev 15406)
@@ -0,0 +1,47 @@
+/*
+ * Envers. http://www.jboss.org/envers
+ *
+ * Copyright 2008 Red Hat Middleware, LLC. All rights reserved.
+ *
+ * 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, v. 2.1.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT A 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, v.2.1 along with this distribution; if not, write to the Free
+ * Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+ * 02110-1301, USA.
+ *
+ * Red Hat Author(s): Adam Warski
+ */
+package org.jboss.envers.query.criteria;
+
+import org.jboss.envers.configuration.VersionsConfiguration;
+import org.jboss.envers.tools.query.QueryBuilder;
+import org.jboss.envers.tools.query.Parameters;
+
+/**
+ * @author Adam Warski (adam at warski dot org)
+ */
+public class BetweenVersionsExpression implements VersionsCriterion {
+ private String propertyName;
+ private Object lo;
+ private Object hi;
+
+ public BetweenVersionsExpression(String propertyName, Object lo, Object hi) {
+ this.propertyName = propertyName;
+ this.lo = lo;
+ this.hi = hi;
+ }
+
+ public void addToQuery(VersionsConfiguration verCfg, String entityName, QueryBuilder qb, Parameters parameters) {
+ CriteriaTools.checkPropertyNotARelation(verCfg, entityName, propertyName);
+ parameters.addWhereWithParam(propertyName, ">=", lo);
+ parameters.addWhereWithParam(propertyName, "<=", hi);
+ }
+}
Added: core/trunk/envers/src/main/java/org/jboss/envers/query/criteria/CriteriaTools.java
===================================================================
--- core/trunk/envers/src/main/java/org/jboss/envers/query/criteria/CriteriaTools.java (rev 0)
+++ core/trunk/envers/src/main/java/org/jboss/envers/query/criteria/CriteriaTools.java 2008-10-27 18:56:31 UTC (rev 15406)
@@ -0,0 +1,58 @@
+/*
+ * Envers. http://www.jboss.org/envers
+ *
+ * Copyright 2008 Red Hat Middleware, LLC. All rights reserved.
+ *
+ * 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, v. 2.1.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT A 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, v.2.1 along with this distribution; if not, write to the Free
+ * Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+ * 02110-1301, USA.
+ *
+ * Red Hat Author(s): Adam Warski
+ */
+package org.jboss.envers.query.criteria;
+
+import org.jboss.envers.exception.VersionsException;
+import org.jboss.envers.entities.RelationDescription;
+import org.jboss.envers.entities.RelationType;
+import org.jboss.envers.configuration.VersionsConfiguration;
+
+/**
+ * @author Adam Warski (adam at warski dot org)
+ */
+public class CriteriaTools {
+ private CriteriaTools() { }
+
+ public static void checkPropertyNotARelation(VersionsConfiguration verCfg, String entityName,
+ String propertyName) throws VersionsException {
+ if (verCfg.getEntCfg().get(entityName).isRelation(propertyName)) {
+ throw new VersionsException("This criterion cannot be used on a property that is " +
+ "a relation to another property.");
+ }
+ }
+
+ public static RelationDescription getRelatedEntity(VersionsConfiguration verCfg, String entityName,
+ String propertyName) throws VersionsException {
+ RelationDescription relationDesc = verCfg.getEntCfg().getRelationDescription(entityName, propertyName);
+
+ if (relationDesc == null) {
+ return null;
+ }
+
+ if (relationDesc.getRelationType() == RelationType.TO_ONE) {
+ return relationDesc;
+ }
+
+ throw new VersionsException("This type of relation (" + entityName + "." + propertyName +
+ ") isn't supported and can't be used in queries.");
+ }
+}
Added: core/trunk/envers/src/main/java/org/jboss/envers/query/criteria/ExtendableCriterion.java
===================================================================
--- core/trunk/envers/src/main/java/org/jboss/envers/query/criteria/ExtendableCriterion.java (rev 0)
+++ core/trunk/envers/src/main/java/org/jboss/envers/query/criteria/ExtendableCriterion.java 2008-10-27 18:56:31 UTC (rev 15406)
@@ -0,0 +1,29 @@
+/*
+ * Envers. http://www.jboss.org/envers
+ *
+ * Copyright 2008 Red Hat Middleware, LLC. All rights reserved.
+ *
+ * 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, v. 2.1.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT A 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, v.2.1 along with this distribution; if not, write to the Free
+ * Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+ * 02110-1301, USA.
+ *
+ * Red Hat Author(s): Adam Warski
+ */
+package org.jboss.envers.query.criteria;
+
+/**
+ * @author Adam Warski (adam at warski dot org)
+ */
+public interface ExtendableCriterion {
+ public ExtendableCriterion add(VersionsCriterion criterion);
+}
Added: core/trunk/envers/src/main/java/org/jboss/envers/query/criteria/IdentifierEqVersionsExpression.java
===================================================================
--- core/trunk/envers/src/main/java/org/jboss/envers/query/criteria/IdentifierEqVersionsExpression.java (rev 0)
+++ core/trunk/envers/src/main/java/org/jboss/envers/query/criteria/IdentifierEqVersionsExpression.java 2008-10-27 18:56:31 UTC (rev 15406)
@@ -0,0 +1,42 @@
+/*
+ * Envers. http://www.jboss.org/envers
+ *
+ * Copyright 2008 Red Hat Middleware, LLC. All rights reserved.
+ *
+ * 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, v. 2.1.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT A 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, v.2.1 along with this distribution; if not, write to the Free
+ * Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+ * 02110-1301, USA.
+ *
+ * Red Hat Author(s): Adam Warski
+ */
+package org.jboss.envers.query.criteria;
+
+import org.jboss.envers.configuration.VersionsConfiguration;
+import org.jboss.envers.tools.query.QueryBuilder;
+import org.jboss.envers.tools.query.Parameters;
+
+/**
+ * @author Adam Warski (adam at warski dot org)
+ */
+public class IdentifierEqVersionsExpression implements VersionsCriterion {
+ private Object id;
+
+ public IdentifierEqVersionsExpression(Object id) {
+ this.id = id;
+ }
+
+ public void addToQuery(VersionsConfiguration verCfg, String entityName, QueryBuilder qb, Parameters parameters) {
+ verCfg.getEntCfg().get(entityName).getIdMapper()
+ .addIdEqualsToQuery(parameters, id, verCfg.getVerEntCfg().getOriginalIdPropName(), true);
+ }
+}
Added: core/trunk/envers/src/main/java/org/jboss/envers/query/criteria/InVersionsExpression.java
===================================================================
--- core/trunk/envers/src/main/java/org/jboss/envers/query/criteria/InVersionsExpression.java (rev 0)
+++ core/trunk/envers/src/main/java/org/jboss/envers/query/criteria/InVersionsExpression.java 2008-10-27 18:56:31 UTC (rev 15406)
@@ -0,0 +1,44 @@
+/*
+ * Envers. http://www.jboss.org/envers
+ *
+ * Copyright 2008 Red Hat Middleware, LLC. All rights reserved.
+ *
+ * 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, v. 2.1.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT A 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, v.2.1 along with this distribution; if not, write to the Free
+ * Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+ * 02110-1301, USA.
+ *
+ * Red Hat Author(s): Adam Warski
+ */
+package org.jboss.envers.query.criteria;
+
+import org.jboss.envers.configuration.VersionsConfiguration;
+import org.jboss.envers.tools.query.QueryBuilder;
+import org.jboss.envers.tools.query.Parameters;
+
+/**
+ * @author Adam Warski (adam at warski dot org)
+ */
+public class InVersionsExpression implements VersionsCriterion {
+ private String propertyName;
+ private Object[] values;
+
+ public InVersionsExpression(String propertyName, Object[] values) {
+ this.propertyName = propertyName;
+ this.values = values;
+ }
+
+ public void addToQuery(VersionsConfiguration verCfg, String entityName, QueryBuilder qb, Parameters parameters) {
+ CriteriaTools.checkPropertyNotARelation(verCfg, entityName, propertyName);
+ parameters.addWhereWithParams(propertyName, "in (", values, ")");
+ }
+}
Added: core/trunk/envers/src/main/java/org/jboss/envers/query/criteria/LogicalVersionsExpression.java
===================================================================
--- core/trunk/envers/src/main/java/org/jboss/envers/query/criteria/LogicalVersionsExpression.java (rev 0)
+++ core/trunk/envers/src/main/java/org/jboss/envers/query/criteria/LogicalVersionsExpression.java 2008-10-27 18:56:31 UTC (rev 15406)
@@ -0,0 +1,48 @@
+/*
+ * Envers. http://www.jboss.org/envers
+ *
+ * Copyright 2008 Red Hat Middleware, LLC. All rights reserved.
+ *
+ * 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, v. 2.1.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT A 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, v.2.1 along with this distribution; if not, write to the Free
+ * Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+ * 02110-1301, USA.
+ *
+ * Red Hat Author(s): Adam Warski
+ */
+package org.jboss.envers.query.criteria;
+
+import org.jboss.envers.configuration.VersionsConfiguration;
+import org.jboss.envers.tools.query.QueryBuilder;
+import org.jboss.envers.tools.query.Parameters;
+
+/**
+ * @author Adam Warski (adam at warski dot org)
+ */
+public class LogicalVersionsExpression implements VersionsCriterion {
+ private VersionsCriterion lhs;
+ private VersionsCriterion rhs;
+ private String op;
+
+ public LogicalVersionsExpression(VersionsCriterion lhs, VersionsCriterion rhs, String op) {
+ this.lhs = lhs;
+ this.rhs = rhs;
+ this.op = op;
+ }
+
+ public void addToQuery(VersionsConfiguration verCfg, String entityName, QueryBuilder qb, Parameters parameters) {
+ Parameters opParameters = parameters.addSubParameters(op);
+
+ lhs.addToQuery(verCfg, entityName, qb, opParameters.addSubParameters("and"));
+ rhs.addToQuery(verCfg, entityName, qb, opParameters.addSubParameters("and"));
+ }
+}
Added: core/trunk/envers/src/main/java/org/jboss/envers/query/criteria/NotNullVersionsExpression.java
===================================================================
--- core/trunk/envers/src/main/java/org/jboss/envers/query/criteria/NotNullVersionsExpression.java (rev 0)
+++ core/trunk/envers/src/main/java/org/jboss/envers/query/criteria/NotNullVersionsExpression.java 2008-10-27 18:56:31 UTC (rev 15406)
@@ -0,0 +1,48 @@
+/*
+ * Envers. http://www.jboss.org/envers
+ *
+ * Copyright 2008 Red Hat Middleware, LLC. All rights reserved.
+ *
+ * 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, v. 2.1.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT A 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, v.2.1 along with this distribution; if not, write to the Free
+ * Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+ * 02110-1301, USA.
+ *
+ * Red Hat Author(s): Adam Warski
+ */
+package org.jboss.envers.query.criteria;
+
+import org.jboss.envers.entities.RelationDescription;
+import org.jboss.envers.configuration.VersionsConfiguration;
+import org.jboss.envers.tools.query.QueryBuilder;
+import org.jboss.envers.tools.query.Parameters;
+
+/**
+ * @author Adam Warski (adam at warski dot org)
+ */
+public class NotNullVersionsExpression implements VersionsCriterion {
+ private String propertyName;
+
+ public NotNullVersionsExpression(String propertyName) {
+ this.propertyName = propertyName;
+ }
+
+ public void addToQuery(VersionsConfiguration verCfg, String entityName, QueryBuilder qb, Parameters parameters) {
+ RelationDescription relatedEntity = CriteriaTools.getRelatedEntity(verCfg, entityName, propertyName);
+
+ if (relatedEntity == null) {
+ parameters.addWhereWithParam(propertyName, "<>", null);
+ } else {
+ relatedEntity.getIdMapper().addIdEqualsToQuery(parameters, null, propertyName, false);
+ }
+ }
+}
Added: core/trunk/envers/src/main/java/org/jboss/envers/query/criteria/NotVersionsExpression.java
===================================================================
--- core/trunk/envers/src/main/java/org/jboss/envers/query/criteria/NotVersionsExpression.java (rev 0)
+++ core/trunk/envers/src/main/java/org/jboss/envers/query/criteria/NotVersionsExpression.java 2008-10-27 18:56:31 UTC (rev 15406)
@@ -0,0 +1,41 @@
+/*
+ * Envers. http://www.jboss.org/envers
+ *
+ * Copyright 2008 Red Hat Middleware, LLC. All rights reserved.
+ *
+ * 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, v. 2.1.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT A 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, v.2.1 along with this distribution; if not, write to the Free
+ * Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+ * 02110-1301, USA.
+ *
+ * Red Hat Author(s): Adam Warski
+ */
+package org.jboss.envers.query.criteria;
+
+import org.jboss.envers.configuration.VersionsConfiguration;
+import org.jboss.envers.tools.query.QueryBuilder;
+import org.jboss.envers.tools.query.Parameters;
+
+/**
+ * @author Adam Warski (adam at warski dot org)
+ */
+public class NotVersionsExpression implements VersionsCriterion {
+ private VersionsCriterion criterion;
+
+ public NotVersionsExpression(VersionsCriterion criterion) {
+ this.criterion = criterion;
+ }
+
+ public void addToQuery(VersionsConfiguration verCfg, String entityName, QueryBuilder qb, Parameters parameters) {
+ criterion.addToQuery(verCfg, entityName, qb, parameters.addNegatedParameters());
+ }
+}
Added: core/trunk/envers/src/main/java/org/jboss/envers/query/criteria/NullVersionsExpression.java
===================================================================
--- core/trunk/envers/src/main/java/org/jboss/envers/query/criteria/NullVersionsExpression.java (rev 0)
+++ core/trunk/envers/src/main/java/org/jboss/envers/query/criteria/NullVersionsExpression.java 2008-10-27 18:56:31 UTC (rev 15406)
@@ -0,0 +1,48 @@
+/*
+ * Envers. http://www.jboss.org/envers
+ *
+ * Copyright 2008 Red Hat Middleware, LLC. All rights reserved.
+ *
+ * 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, v. 2.1.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT A 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, v.2.1 along with this distribution; if not, write to the Free
+ * Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+ * 02110-1301, USA.
+ *
+ * Red Hat Author(s): Adam Warski
+ */
+package org.jboss.envers.query.criteria;
+
+import org.jboss.envers.entities.RelationDescription;
+import org.jboss.envers.configuration.VersionsConfiguration;
+import org.jboss.envers.tools.query.QueryBuilder;
+import org.jboss.envers.tools.query.Parameters;
+
+/**
+ * @author Adam Warski (adam at warski dot org)
+ */
+public class NullVersionsExpression implements VersionsCriterion {
+ private String propertyName;
+
+ public NullVersionsExpression(String propertyName) {
+ this.propertyName = propertyName;
+ }
+
+ public void addToQuery(VersionsConfiguration verCfg, String entityName, QueryBuilder qb, Parameters parameters) {
+ RelationDescription relatedEntity = CriteriaTools.getRelatedEntity(verCfg, entityName, propertyName);
+
+ if (relatedEntity == null) {
+ parameters.addWhereWithParam(propertyName, "=", null);
+ } else {
+ relatedEntity.getIdMapper().addIdEqualsToQuery(parameters, null, propertyName, true);
+ }
+ }
+}
Added: core/trunk/envers/src/main/java/org/jboss/envers/query/criteria/PropertyVersionsExpression.java
===================================================================
--- core/trunk/envers/src/main/java/org/jboss/envers/query/criteria/PropertyVersionsExpression.java (rev 0)
+++ core/trunk/envers/src/main/java/org/jboss/envers/query/criteria/PropertyVersionsExpression.java 2008-10-27 18:56:31 UTC (rev 15406)
@@ -0,0 +1,47 @@
+/*
+ * Envers. http://www.jboss.org/envers
+ *
+ * Copyright 2008 Red Hat Middleware, LLC. All rights reserved.
+ *
+ * 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, v. 2.1.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT A 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, v.2.1 along with this distribution; if not, write to the Free
+ * Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+ * 02110-1301, USA.
+ *
+ * Red Hat Author(s): Adam Warski
+ */
+package org.jboss.envers.query.criteria;
+
+import org.jboss.envers.configuration.VersionsConfiguration;
+import org.jboss.envers.tools.query.QueryBuilder;
+import org.jboss.envers.tools.query.Parameters;
+
+/**
+ * @author Adam Warski (adam at warski dot org)
+ */
+public class PropertyVersionsExpression implements VersionsCriterion {
+ private String propertyName;
+ private String otherPropertyName;
+ private String op;
+
+ public PropertyVersionsExpression(String propertyName, String otherPropertyName, String op) {
+ this.propertyName = propertyName;
+ this.otherPropertyName = otherPropertyName;
+ this.op = op;
+ }
+
+ public void addToQuery(VersionsConfiguration verCfg, String entityName, QueryBuilder qb, Parameters parameters) {
+ CriteriaTools.checkPropertyNotARelation(verCfg, entityName, propertyName);
+ CriteriaTools.checkPropertyNotARelation(verCfg, entityName, otherPropertyName);
+ parameters.addWhere(propertyName, op, otherPropertyName);
+ }
+}
Added: core/trunk/envers/src/main/java/org/jboss/envers/query/criteria/RelatedVersionsExpression.java
===================================================================
--- core/trunk/envers/src/main/java/org/jboss/envers/query/criteria/RelatedVersionsExpression.java (rev 0)
+++ core/trunk/envers/src/main/java/org/jboss/envers/query/criteria/RelatedVersionsExpression.java 2008-10-27 18:56:31 UTC (rev 15406)
@@ -0,0 +1,54 @@
+/*
+ * Envers. http://www.jboss.org/envers
+ *
+ * Copyright 2008 Red Hat Middleware, LLC. All rights reserved.
+ *
+ * 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, v. 2.1.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT A 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, v.2.1 along with this distribution; if not, write to the Free
+ * Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+ * 02110-1301, USA.
+ *
+ * Red Hat Author(s): Adam Warski
+ */
+package org.jboss.envers.query.criteria;
+
+import org.jboss.envers.exception.VersionsException;
+import org.jboss.envers.entities.RelationDescription;
+import org.jboss.envers.configuration.VersionsConfiguration;
+import org.jboss.envers.tools.query.QueryBuilder;
+import org.jboss.envers.tools.query.Parameters;
+
+/**
+ * @author Adam Warski (adam at warski dot org)
+ */
+public class RelatedVersionsExpression implements VersionsCriterion {
+ private String propertyName;
+ private Object id;
+ private boolean equals;
+
+ public RelatedVersionsExpression(String propertyName, Object id, boolean equals) {
+ this.propertyName = propertyName;
+ this.id = id;
+ this.equals = equals;
+ }
+
+ public void addToQuery(VersionsConfiguration verCfg, String entityName, QueryBuilder qb, Parameters parameters) {
+ RelationDescription relatedEntity = CriteriaTools.getRelatedEntity(verCfg, entityName, propertyName);
+
+ if (relatedEntity == null) {
+ throw new VersionsException("This criterion can only be used on a property that is " +
+ "a relation to another property.");
+ } else {
+ relatedEntity.getIdMapper().addIdEqualsToQuery(parameters, id, propertyName, equals);
+ }
+ }
+}
\ No newline at end of file
Added: core/trunk/envers/src/main/java/org/jboss/envers/query/criteria/RevisionVersionsExpression.java
===================================================================
--- core/trunk/envers/src/main/java/org/jboss/envers/query/criteria/RevisionVersionsExpression.java (rev 0)
+++ core/trunk/envers/src/main/java/org/jboss/envers/query/criteria/RevisionVersionsExpression.java 2008-10-27 18:56:31 UTC (rev 15406)
@@ -0,0 +1,43 @@
+/*
+ * Envers. http://www.jboss.org/envers
+ *
+ * Copyright 2008 Red Hat Middleware, LLC. All rights reserved.
+ *
+ * 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, v. 2.1.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT A 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, v.2.1 along with this distribution; if not, write to the Free
+ * Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+ * 02110-1301, USA.
+ *
+ * Red Hat Author(s): Adam Warski
+ */
+package org.jboss.envers.query.criteria;
+
+import org.jboss.envers.configuration.VersionsConfiguration;
+import org.jboss.envers.tools.query.QueryBuilder;
+import org.jboss.envers.tools.query.Parameters;
+
+/**
+ * @author Adam Warski (adam at warski dot org)
+ */
+public class RevisionVersionsExpression implements VersionsCriterion {
+ private Object value;
+ private String op;
+
+ public RevisionVersionsExpression(Object value, String op) {
+ this.value = value;
+ this.op = op;
+ }
+
+ public void addToQuery(VersionsConfiguration verCfg, String entityName, QueryBuilder qb, Parameters parameters) {
+ parameters.addWhereWithParam(verCfg.getVerEntCfg().getRevisionPropPath(), op, value);
+ }
+}
\ No newline at end of file
Added: core/trunk/envers/src/main/java/org/jboss/envers/query/criteria/SimpleVersionsExpression.java
===================================================================
--- core/trunk/envers/src/main/java/org/jboss/envers/query/criteria/SimpleVersionsExpression.java (rev 0)
+++ core/trunk/envers/src/main/java/org/jboss/envers/query/criteria/SimpleVersionsExpression.java 2008-10-27 18:56:31 UTC (rev 15406)
@@ -0,0 +1,60 @@
+/*
+ * Envers. http://www.jboss.org/envers
+ *
+ * Copyright 2008 Red Hat Middleware, LLC. All rights reserved.
+ *
+ * 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, v. 2.1.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT A 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, v.2.1 along with this distribution; if not, write to the Free
+ * Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+ * 02110-1301, USA.
+ *
+ * Red Hat Author(s): Adam Warski
+ */
+package org.jboss.envers.query.criteria;
+
+import org.jboss.envers.exception.VersionsException;
+import org.jboss.envers.entities.RelationDescription;
+import org.jboss.envers.configuration.VersionsConfiguration;
+import org.jboss.envers.tools.query.QueryBuilder;
+import org.jboss.envers.tools.query.Parameters;
+
+/**
+ * @author Adam Warski (adam at warski dot org)
+ */
+public class SimpleVersionsExpression implements VersionsCriterion {
+ private String propertyName;
+ private Object value;
+ private String op;
+
+ public SimpleVersionsExpression(String propertyName, Object value, String op) {
+ this.propertyName = propertyName;
+ this.value = value;
+ this.op = op;
+ }
+
+ public void addToQuery(VersionsConfiguration verCfg, String entityName, QueryBuilder qb, Parameters parameters) {
+ RelationDescription relatedEntity = CriteriaTools.getRelatedEntity(verCfg, entityName, propertyName);
+
+ if (relatedEntity == null) {
+ parameters.addWhereWithParam(propertyName, op, value);
+ } else {
+ if (!"=".equals(op) && !"<>".equals(op)) {
+ throw new VersionsException("This type of operation: " + op + " (" + entityName + "." + propertyName +
+ ") isn't supported and can't be used in queries.");
+ }
+
+ Object id = relatedEntity.getIdMapper().mapToIdFromEntity(value);
+
+ relatedEntity.getIdMapper().addIdEqualsToQuery(parameters, id, propertyName, "=".equals(op));
+ }
+ }
+}
Added: core/trunk/envers/src/main/java/org/jboss/envers/query/criteria/VersionsConjunction.java
===================================================================
--- core/trunk/envers/src/main/java/org/jboss/envers/query/criteria/VersionsConjunction.java (rev 0)
+++ core/trunk/envers/src/main/java/org/jboss/envers/query/criteria/VersionsConjunction.java 2008-10-27 18:56:31 UTC (rev 15406)
@@ -0,0 +1,53 @@
+/*
+ * Envers. http://www.jboss.org/envers
+ *
+ * Copyright 2008 Red Hat Middleware, LLC. All rights reserved.
+ *
+ * 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, v. 2.1.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT A 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, v.2.1 along with this distribution; if not, write to the Free
+ * Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+ * 02110-1301, USA.
+ *
+ * Red Hat Author(s): Adam Warski
+ */
+package org.jboss.envers.query.criteria;
+
+import org.jboss.envers.configuration.VersionsConfiguration;
+import org.jboss.envers.tools.query.QueryBuilder;
+import org.jboss.envers.tools.query.Parameters;
+
+import java.util.ArrayList;
+import java.util.List;
+
+/**
+ * @author Adam Warski (adam at warski dot org)
+ */
+public class VersionsConjunction implements VersionsCriterion, ExtendableCriterion {
+ private List<VersionsCriterion> criterions;
+
+ public VersionsConjunction() {
+ criterions = new ArrayList<VersionsCriterion>();
+ }
+
+ public VersionsConjunction add(VersionsCriterion criterion) {
+ criterions.add(criterion);
+ return this;
+ }
+
+ public void addToQuery(VersionsConfiguration verCfg, String entityName, QueryBuilder qb, Parameters parameters) {
+ Parameters andParameters = parameters.addSubParameters(Parameters.AND);
+
+ for (VersionsCriterion criterion : criterions) {
+ criterion.addToQuery(verCfg, entityName, qb, andParameters);
+ }
+ }
+}
Added: core/trunk/envers/src/main/java/org/jboss/envers/query/criteria/VersionsCriterion.java
===================================================================
--- core/trunk/envers/src/main/java/org/jboss/envers/query/criteria/VersionsCriterion.java (rev 0)
+++ core/trunk/envers/src/main/java/org/jboss/envers/query/criteria/VersionsCriterion.java 2008-10-27 18:56:31 UTC (rev 15406)
@@ -0,0 +1,33 @@
+/*
+ * Envers. http://www.jboss.org/envers
+ *
+ * Copyright 2008 Red Hat Middleware, LLC. All rights reserved.
+ *
+ * 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, v. 2.1.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT A 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, v.2.1 along with this distribution; if not, write to the Free
+ * Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+ * 02110-1301, USA.
+ *
+ * Red Hat Author(s): Adam Warski
+ */
+package org.jboss.envers.query.criteria;
+
+import org.jboss.envers.configuration.VersionsConfiguration;
+import org.jboss.envers.tools.query.QueryBuilder;
+import org.jboss.envers.tools.query.Parameters;
+
+/**
+ * @author Adam Warski (adam at warski dot org)
+ */
+public interface VersionsCriterion {
+ void addToQuery(VersionsConfiguration verCfg, String entityName, QueryBuilder qb, Parameters parameters);
+}
Added: core/trunk/envers/src/main/java/org/jboss/envers/query/criteria/VersionsDisjunction.java
===================================================================
--- core/trunk/envers/src/main/java/org/jboss/envers/query/criteria/VersionsDisjunction.java (rev 0)
+++ core/trunk/envers/src/main/java/org/jboss/envers/query/criteria/VersionsDisjunction.java 2008-10-27 18:56:31 UTC (rev 15406)
@@ -0,0 +1,53 @@
+/*
+ * Envers. http://www.jboss.org/envers
+ *
+ * Copyright 2008 Red Hat Middleware, LLC. All rights reserved.
+ *
+ * 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, v. 2.1.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT A 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, v.2.1 along with this distribution; if not, write to the Free
+ * Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+ * 02110-1301, USA.
+ *
+ * Red Hat Author(s): Adam Warski
+ */
+package org.jboss.envers.query.criteria;
+
+import org.jboss.envers.configuration.VersionsConfiguration;
+import org.jboss.envers.tools.query.QueryBuilder;
+import org.jboss.envers.tools.query.Parameters;
+
+import java.util.List;
+import java.util.ArrayList;
+
+/**
+ * @author Adam Warski (adam at warski dot org)
+ */
+public class VersionsDisjunction implements VersionsCriterion, ExtendableCriterion {
+ private List<VersionsCriterion> criterions;
+
+ public VersionsDisjunction() {
+ criterions = new ArrayList<VersionsCriterion>();
+ }
+
+ public VersionsDisjunction add(VersionsCriterion criterion) {
+ criterions.add(criterion);
+ return this;
+ }
+
+ public void addToQuery(VersionsConfiguration verCfg, String entityName, QueryBuilder qb, Parameters parameters) {
+ Parameters orParameters = parameters.addSubParameters(Parameters.OR);
+
+ for (VersionsCriterion criterion : criterions) {
+ criterion.addToQuery(verCfg, entityName, qb, orParameters);
+ }
+ }
+}
\ No newline at end of file
Added: core/trunk/envers/src/main/java/org/jboss/envers/query/impl/AbstractVersionsQuery.java
===================================================================
--- core/trunk/envers/src/main/java/org/jboss/envers/query/impl/AbstractVersionsQuery.java (rev 0)
+++ core/trunk/envers/src/main/java/org/jboss/envers/query/impl/AbstractVersionsQuery.java 2008-10-27 18:56:31 UTC (rev 15406)
@@ -0,0 +1,210 @@
+/*
+ * Envers. http://www.jboss.org/envers
+ *
+ * Copyright 2008 Red Hat Middleware, LLC. All rights reserved.
+ *
+ * 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, v. 2.1.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT A 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, v.2.1 along with this distribution; if not, write to the Free
+ * Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+ * 02110-1301, USA.
+ *
+ * Red Hat Author(s): Adam Warski
+ */
+package org.jboss.envers.query.impl;
+
+import org.jboss.envers.reader.VersionsReaderImplementor;
+import org.jboss.envers.entities.EntityInstantiator;
+import org.jboss.envers.query.criteria.VersionsCriterion;
+import org.jboss.envers.query.VersionsQuery;
+import org.jboss.envers.query.order.VersionsOrder;
+import org.jboss.envers.query.projection.VersionsProjection;
+import org.jboss.envers.exception.VersionsException;
+import org.jboss.envers.configuration.VersionsConfiguration;
+import org.jboss.envers.tools.Pair;
+import org.jboss.envers.tools.Triple;
+import org.jboss.envers.tools.query.QueryBuilder;
+import org.hibernate.*;
+
+import javax.persistence.NonUniqueResultException;
+import javax.persistence.NoResultException;
+import java.util.List;
+import java.util.ArrayList;
+import java.util.Map;
+import java.util.HashMap;
+
+/**
+ * @author Adam Warski (adam at warski dot org)
+ */
+public abstract class AbstractVersionsQuery implements VersionsQuery {
+ protected EntityInstantiator entityInstantiator;
+ protected List<VersionsCriterion> criterions;
+
+ protected String entityName;
+ protected String versionsEntityName;
+ protected QueryBuilder qb;
+
+ protected boolean hasProjection;
+ protected boolean hasOrder;
+
+ protected final VersionsConfiguration verCfg;
+ private final VersionsReaderImplementor versionsReader;
+
+ protected AbstractVersionsQuery(VersionsConfiguration verCfg, VersionsReaderImplementor versionsReader,
+ Class<?> cls) {
+ this.verCfg = verCfg;
+ this.versionsReader = versionsReader;
+
+ criterions = new ArrayList<VersionsCriterion>();
+ entityInstantiator = new EntityInstantiator(verCfg, versionsReader);
+
+ entityName = cls.getName();
+ versionsEntityName = verCfg.getVerEntCfg().getVersionsEntityName(entityName);
+
+ qb = new QueryBuilder(versionsEntityName, "e");
+ }
+
+ protected List buildAndExecuteQuery() {
+ StringBuilder querySb = new StringBuilder();
+ Map<String, Object> queryParamValues = new HashMap<String, Object>();
+
+ qb.build(querySb, queryParamValues);
+
+ Query query = versionsReader.getSession().createQuery(querySb.toString());
+ for (Map.Entry<String, Object> paramValue : queryParamValues.entrySet()) {
+ query.setParameter(paramValue.getKey(), paramValue.getValue());
+ }
+
+ setQueryProperties(query);
+
+ return query.list();
+ }
+
+ public abstract List list() throws VersionsException;
+
+ public List getResultList() throws VersionsException {
+ return list();
+ }
+
+ public Object getSingleResult() throws VersionsException, NonUniqueResultException, NoResultException {
+ List result = list();
+
+ if (result == null || result.size() == 0) {
+ throw new NoResultException();
+ }
+
+ if (result.size() > 1) {
+ throw new NonUniqueResultException();
+ }
+
+ return result.get(0);
+ }
+
+ public VersionsQuery add(VersionsCriterion criterion) {
+ criterions.add(criterion);
+ return this;
+ }
+
+ // Projection and order
+
+ public VersionsQuery addProjection(String function, String propertyName) {
+ hasProjection = true;
+ qb.addProjection(function, propertyName, false);
+ return this;
+ }
+
+ public VersionsQuery addProjection(VersionsProjection projection) {
+ Triple<String, String, Boolean> projectionData = projection.getData(verCfg);
+ hasProjection = true;
+ qb.addProjection(projectionData.getFirst(), projectionData.getSecond(), projectionData.getThird());
+ return this;
+ }
+
+ public VersionsQuery addOrder(String propertyName, boolean asc) {
+ hasOrder = true;
+ qb.addOrder(propertyName, asc);
+ return this;
+ }
+
+ public VersionsQuery addOrder(VersionsOrder order) {
+ Pair<String, Boolean> orderData = order.getData(verCfg);
+ return addOrder(orderData.getFirst(), orderData.getSecond());
+ }
+
+ // Query properties
+
+ private Integer maxResults;
+ private Integer firstResult;
+ private Boolean cacheable;
+ private String cacheRegion;
+ private String comment;
+ private FlushMode flushMode;
+ private CacheMode cacheMode;
+ private Integer timeout;
+ private LockMode lockMode;
+
+ public VersionsQuery setMaxResults(int maxResults) {
+ this.maxResults = maxResults;
+ return this;
+ }
+
+ public VersionsQuery setFirstResult(int firstResult) {
+ this.firstResult = firstResult;
+ return this;
+ }
+
+ public VersionsQuery setCacheable(boolean cacheable) {
+ this.cacheable = cacheable;
+ return this;
+ }
+
+ public VersionsQuery setCacheRegion(String cacheRegion) {
+ this.cacheRegion = cacheRegion;
+ return this;
+ }
+
+ public VersionsQuery setComment(String comment) {
+ this.comment = comment;
+ return this;
+ }
+
+ public VersionsQuery setFlushMode(FlushMode flushMode) {
+ this.flushMode = flushMode;
+ return this;
+ }
+
+ public VersionsQuery setCacheMode(CacheMode cacheMode) {
+ this.cacheMode = cacheMode;
+ return this;
+ }
+
+ public VersionsQuery setTimeout(int timeout) {
+ this.timeout = timeout;
+ return this;
+ }
+
+ public VersionsQuery setLockMode(LockMode lockMode) {
+ this.lockMode = lockMode;
+ return this;
+ }
+
+ protected void setQueryProperties(Query query) {
+ if (maxResults != null) query.setMaxResults(maxResults);
+ if (firstResult != null) query.setFirstResult(firstResult);
+ if (cacheable != null) query.setCacheable(cacheable);
+ if (cacheRegion != null) query.setCacheRegion(cacheRegion);
+ if (comment != null) query.setComment(comment);
+ if (flushMode != null) query.setFlushMode(flushMode);
+ if (cacheMode != null) query.setCacheMode(cacheMode);
+ if (timeout != null) query.setTimeout(timeout);
+ if (lockMode != null) query.setLockMode("e", lockMode);
+ }
+}
Added: core/trunk/envers/src/main/java/org/jboss/envers/query/impl/EntitiesAtRevisionQuery.java
===================================================================
--- core/trunk/envers/src/main/java/org/jboss/envers/query/impl/EntitiesAtRevisionQuery.java (rev 0)
+++ core/trunk/envers/src/main/java/org/jboss/envers/query/impl/EntitiesAtRevisionQuery.java 2008-10-27 18:56:31 UTC (rev 15406)
@@ -0,0 +1,93 @@
+/*
+ * Envers. http://www.jboss.org/envers
+ *
+ * Copyright 2008 Red Hat Middleware, LLC. All rights reserved.
+ *
+ * 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, v. 2.1.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT A 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, v.2.1 along with this distribution; if not, write to the Free
+ * Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+ * 02110-1301, USA.
+ *
+ * Red Hat Author(s): Adam Warski
+ */
+package org.jboss.envers.query.impl;
+
+import org.jboss.envers.reader.VersionsReaderImplementor;
+import org.jboss.envers.query.criteria.VersionsCriterion;
+import org.jboss.envers.RevisionType;
+import org.jboss.envers.tools.query.QueryBuilder;
+import org.jboss.envers.configuration.VersionsEntitiesConfiguration;
+import org.jboss.envers.configuration.VersionsConfiguration;
+
+import java.util.List;
+import java.util.ArrayList;
+
+/**
+ * @author Adam Warski (adam at warski dot org)
+ */
+public class EntitiesAtRevisionQuery extends AbstractVersionsQuery {
+ private final Number revision;
+
+ public EntitiesAtRevisionQuery(VersionsConfiguration verCfg,
+ VersionsReaderImplementor versionsReader, Class<?> cls,
+ Number revision) {
+ super(verCfg, versionsReader, cls);
+ this.revision = revision;
+ }
+
+ @SuppressWarnings({"unchecked"})
+ public List list() {
+ /*
+ The query that should be executed in the versions table:
+ SELECT e FROM ent_ver e WHERE
+ (all specified conditions, transformed, on the "e" entity) AND
+ e.revision_type != DEL AND
+ e.revision = (SELECT max(e2.revision) FROM ent_ver e2 WHERE
+ e2.revision <= :revision AND e2.originalId.id = e.originalId.id)
+ */
+
+ QueryBuilder maxRevQb = qb.newSubQueryBuilder(versionsEntityName, "e2");
+
+ VersionsEntitiesConfiguration verEntCfg = verCfg.getVerEntCfg();
+
+ String revisionPropertyPath = verEntCfg.getRevisionPropPath();
+ String originalIdPropertyName = verEntCfg.getOriginalIdPropName();
+
+ // SELECT max(e2.revision)
+ maxRevQb.addProjection("max", revisionPropertyPath, false);
+ // e2.revision <= :revision
+ maxRevQb.getRootParameters().addWhereWithParam(revisionPropertyPath, "<=", revision);
+ // e2.id = e.id
+ verCfg.getEntCfg().get(entityName).getIdMapper().addIdsEqualToQuery(maxRevQb.getRootParameters(),
+ "e." + originalIdPropertyName, "e2." + originalIdPropertyName);
+
+ // e.revision_type != DEL AND
+ qb.getRootParameters().addWhereWithParam(verEntCfg.getRevisionTypePropName(), "<>", RevisionType.DEL);
+ // e.revision = (SELECT max(...) ...)
+ qb.getRootParameters().addWhere(revisionPropertyPath, verCfg.getGlobalCfg().getCorrelatedSubqueryOperator(), maxRevQb);
+ // all specified conditions
+ for (VersionsCriterion criterion : criterions) {
+ criterion.addToQuery(verCfg, entityName, qb, qb.getRootParameters());
+ }
+
+ List queryResult = buildAndExecuteQuery();
+
+ if (hasProjection) {
+ return queryResult;
+ } else {
+ List result = new ArrayList();
+ entityInstantiator.addInstancesFromVersionsEntities(entityName, result, queryResult, revision);
+
+ return result;
+ }
+ }
+}
Added: core/trunk/envers/src/main/java/org/jboss/envers/query/impl/RevisionsOfEntityQuery.java
===================================================================
--- core/trunk/envers/src/main/java/org/jboss/envers/query/impl/RevisionsOfEntityQuery.java (rev 0)
+++ core/trunk/envers/src/main/java/org/jboss/envers/query/impl/RevisionsOfEntityQuery.java 2008-10-27 18:56:31 UTC (rev 15406)
@@ -0,0 +1,135 @@
+/*
+ * Envers. http://www.jboss.org/envers
+ *
+ * Copyright 2008 Red Hat Middleware, LLC. All rights reserved.
+ *
+ * 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, v. 2.1.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT A 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, v.2.1 along with this distribution; if not, write to the Free
+ * Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+ * 02110-1301, USA.
+ *
+ * Red Hat Author(s): Adam Warski
+ */
+package org.jboss.envers.query.impl;
+
+import org.jboss.envers.exception.VersionsException;
+import org.jboss.envers.reader.VersionsReaderImplementor;
+import org.jboss.envers.query.criteria.VersionsCriterion;
+import org.jboss.envers.RevisionType;
+import org.jboss.envers.configuration.VersionsEntitiesConfiguration;
+import org.jboss.envers.configuration.VersionsConfiguration;
+import org.hibernate.proxy.HibernateProxy;
+
+import java.util.List;
+import java.util.ArrayList;
+import java.util.Map;
+
+/**
+ * @author Adam Warski (adam at warski dot org)
+ */
+public class RevisionsOfEntityQuery extends AbstractVersionsQuery {
+ private final boolean selectEntitiesOnly;
+ private final boolean selectDeletedEntities;
+
+ public RevisionsOfEntityQuery(VersionsConfiguration verCfg,
+ VersionsReaderImplementor versionsReader,
+ Class<?> cls, boolean selectEntitiesOnly,
+ boolean selectDeletedEntities) {
+ super(verCfg, versionsReader, cls);
+
+ this.selectEntitiesOnly = selectEntitiesOnly;
+ this.selectDeletedEntities = selectDeletedEntities;
+ }
+
+ private Number getRevisionNumber(Map versionsEntity) {
+ VersionsEntitiesConfiguration verEntCfg = verCfg.getVerEntCfg();
+
+ String originalId = verEntCfg.getOriginalIdPropName();
+ String revisionPropertyName = verEntCfg.getRevisionPropName();
+
+ Object revisionInfoObject = ((Map) versionsEntity.get(originalId)).get(revisionPropertyName);
+
+ if (revisionInfoObject instanceof HibernateProxy) {
+ return (Number) ((HibernateProxy) revisionInfoObject).getHibernateLazyInitializer().getIdentifier();
+ } else {
+ // Not a proxy - must be read from cache or with a join
+ return verCfg.getRevisionInfoNumberReader().getRevisionNumber(revisionInfoObject);
+ }
+ }
+
+ @SuppressWarnings({"unchecked"})
+ public List list() throws VersionsException {
+ VersionsEntitiesConfiguration verEntCfg = verCfg.getVerEntCfg();
+
+ /*
+ The query that should be executed in the versions table:
+ SELECT e (unless another projection is specified) FROM ent_ver e, rev_entity r WHERE
+ e.revision_type != DEL (if selectDeletedEntities == false) AND
+ e.revision = r.revision AND
+ (all specified conditions, transformed, on the "e" entity)
+ ORDER BY e.revision ASC (unless another order or projection is specified)
+ */
+ if (!selectDeletedEntities) {
+ // e.revision_type != DEL AND
+ qb.getRootParameters().addWhereWithParam(verEntCfg.getRevisionTypePropName(), "<>", RevisionType.DEL);
+ }
+
+ // all specified conditions, transformed
+ for (VersionsCriterion criterion : criterions) {
+ criterion.addToQuery(verCfg, entityName, qb, qb.getRootParameters());
+ }
+
+ if (!hasProjection && !hasOrder) {
+ String revisionPropertyPath = verEntCfg.getRevisionPropPath();
+ qb.addOrder(revisionPropertyPath, true);
+ }
+
+ if (!selectEntitiesOnly) {
+ qb.addFrom(verCfg.getVerEntCfg().getRevisionInfoEntityName(), "r");
+ qb.getRootParameters().addWhere(verCfg.getVerEntCfg().getRevisionPropPath(), true, "=", "r.id", false);
+ }
+
+ List<Object> queryResult = buildAndExecuteQuery();
+ if (hasProjection) {
+ return queryResult;
+ } else {
+ List entities = new ArrayList();
+ String revisionTypePropertyName = verEntCfg.getRevisionTypePropName();
+
+ for (Object resultRow : queryResult) {
+ Map versionsEntity;
+ Object revisionData;
+
+ if (selectEntitiesOnly) {
+ versionsEntity = (Map) resultRow;
+ revisionData = null;
+ } else {
+ Object[] arrayResultRow = (Object[]) resultRow;
+ versionsEntity = (Map) arrayResultRow[0];
+ revisionData = arrayResultRow[1];
+ }
+
+ Number revision = getRevisionNumber(versionsEntity);
+
+ Object entity = entityInstantiator.createInstanceFromVersionsEntity(entityName, versionsEntity, revision);
+
+ if (!selectEntitiesOnly) {
+ entities.add(new Object[] { entity, revisionData, versionsEntity.get(revisionTypePropertyName) });
+ } else {
+ entities.add(entity);
+ }
+ }
+
+ return entities;
+ }
+ }
+}
Added: core/trunk/envers/src/main/java/org/jboss/envers/query/order/RevisionVersionsOrder.java
===================================================================
--- core/trunk/envers/src/main/java/org/jboss/envers/query/order/RevisionVersionsOrder.java (rev 0)
+++ core/trunk/envers/src/main/java/org/jboss/envers/query/order/RevisionVersionsOrder.java 2008-10-27 18:56:31 UTC (rev 15406)
@@ -0,0 +1,41 @@
+/*
+ * Envers. http://www.jboss.org/envers
+ *
+ * Copyright 2008 Red Hat Middleware, LLC. All rights reserved.
+ *
+ * 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, v. 2.1.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT A 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, v.2.1 along with this distribution; if not, write to the Free
+ * Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+ * 02110-1301, USA.
+ *
+ * Red Hat Author(s): Adam Warski
+ */
+package org.jboss.envers.query.order;
+
+import org.jboss.envers.configuration.VersionsConfiguration;
+import org.jboss.envers.tools.Pair;
+
+/**
+ * @author Adam Warski (adam at warski dot org)
+ */
+public class RevisionVersionsOrder implements VersionsOrder {
+ private final boolean asc;
+
+ public RevisionVersionsOrder(boolean asc) {
+ this.asc = asc;
+ }
+
+ public Pair<String, Boolean> getData(VersionsConfiguration verCfg) {
+ String revisionPropPath = verCfg.getVerEntCfg().getRevisionPropPath();
+ return Pair.make(revisionPropPath, asc);
+ }
+}
Added: core/trunk/envers/src/main/java/org/jboss/envers/query/order/VersionsOrder.java
===================================================================
--- core/trunk/envers/src/main/java/org/jboss/envers/query/order/VersionsOrder.java (rev 0)
+++ core/trunk/envers/src/main/java/org/jboss/envers/query/order/VersionsOrder.java 2008-10-27 18:56:31 UTC (rev 15406)
@@ -0,0 +1,36 @@
+/*
+ * Envers. http://www.jboss.org/envers
+ *
+ * Copyright 2008 Red Hat Middleware, LLC. All rights reserved.
+ *
+ * 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, v. 2.1.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT A 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, v.2.1 along with this distribution; if not, write to the Free
+ * Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+ * 02110-1301, USA.
+ *
+ * Red Hat Author(s): Adam Warski
+ */
+package org.jboss.envers.query.order;
+
+import org.jboss.envers.configuration.VersionsConfiguration;
+import org.jboss.envers.tools.Pair;
+
+/**
+ * @author Adam Warski (adam at warski dot org)
+ */
+public interface VersionsOrder {
+ /**
+ * @param verCfg Configuration.
+ * @return A pair: (property name, ascending?).
+ */
+ Pair<String, Boolean> getData(VersionsConfiguration verCfg);
+}
Added: core/trunk/envers/src/main/java/org/jboss/envers/query/projection/RevisionVersionsProjection.java
===================================================================
--- core/trunk/envers/src/main/java/org/jboss/envers/query/projection/RevisionVersionsProjection.java (rev 0)
+++ core/trunk/envers/src/main/java/org/jboss/envers/query/projection/RevisionVersionsProjection.java 2008-10-27 18:56:31 UTC (rev 15406)
@@ -0,0 +1,58 @@
+/*
+ * Envers. http://www.jboss.org/envers
+ *
+ * Copyright 2008 Red Hat Middleware, LLC. All rights reserved.
+ *
+ * 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, v. 2.1.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT A 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, v.2.1 along with this distribution; if not, write to the Free
+ * Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+ * 02110-1301, USA.
+ *
+ * Red Hat Author(s): Adam Warski
+ */
+package org.jboss.envers.query.projection;
+
+import org.jboss.envers.configuration.VersionsConfiguration;
+import org.jboss.envers.tools.Triple;
+
+/**
+ * @author Adam Warski (adam at warski dot org)
+ */
+public class RevisionVersionsProjection implements VersionsProjection {
+ public static enum ProjectionType {
+ MAX,
+ MIN,
+ COUNT,
+ COUNT_DISTINCT,
+ DISTINCT
+ }
+
+ private final ProjectionType type;
+
+ public RevisionVersionsProjection(ProjectionType type) {
+ this.type = type;
+ }
+
+ public Triple<String, String, Boolean> getData(VersionsConfiguration verCfg) {
+ String revisionPropPath = verCfg.getVerEntCfg().getRevisionPropPath();
+
+ switch (type) {
+ case MAX: return Triple.make("max", revisionPropPath, false);
+ case MIN: return Triple.make("min", revisionPropPath, false);
+ case COUNT: return Triple.make("count", revisionPropPath, false);
+ case COUNT_DISTINCT: return Triple.make("count", revisionPropPath, true);
+ case DISTINCT: return Triple.make(null, revisionPropPath, true);
+ }
+
+ throw new IllegalArgumentException("Unknown type " + type + ".");
+ }
+}
Added: core/trunk/envers/src/main/java/org/jboss/envers/query/projection/VersionsProjection.java
===================================================================
--- core/trunk/envers/src/main/java/org/jboss/envers/query/projection/VersionsProjection.java (rev 0)
+++ core/trunk/envers/src/main/java/org/jboss/envers/query/projection/VersionsProjection.java 2008-10-27 18:56:31 UTC (rev 15406)
@@ -0,0 +1,38 @@
+/*
+ * Envers. http://www.jboss.org/envers
+ *
+ * Copyright 2008 Red Hat Middleware, LLC. All rights reserved.
+ *
+ * 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, v. 2.1.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT A 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, v.2.1 along with this distribution; if not, write to the Free
+ * Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+ * 02110-1301, USA.
+ *
+ * Red Hat Author(s): Adam Warski
+ */
+package org.jboss.envers.query.projection;
+
+import org.jboss.envers.configuration.VersionsConfiguration;
+import org.jboss.envers.tools.Pair;
+import org.jboss.envers.tools.Triple;
+
+/**
+ * @author Adam Warski (adam at warski dot org)
+ */
+public interface VersionsProjection {
+ /**
+ *
+ * @param verCfg Configuration.
+ * @return A triple: (function name - possibly null, property name, add distinct?).
+ */
+ Triple<String, String, Boolean> getData(VersionsConfiguration verCfg);
+}
Added: core/trunk/envers/src/main/java/org/jboss/envers/reader/FirstLevelCache.java
===================================================================
--- core/trunk/envers/src/main/java/org/jboss/envers/reader/FirstLevelCache.java (rev 0)
+++ core/trunk/envers/src/main/java/org/jboss/envers/reader/FirstLevelCache.java 2008-10-27 18:56:31 UTC (rev 15406)
@@ -0,0 +1,32 @@
+package org.jboss.envers.reader;
+
+import org.jboss.envers.tools.Triple;
+import static org.jboss.envers.tools.Triple.*;
+import static org.jboss.envers.tools.Tools.newHashMap;
+
+import java.util.Map;
+
+/**
+ * First level cache for versioned entities, versions reader-scoped. Each entity is uniquely identified by a
+ * revision number and entity id.
+ * @author Adam Warski (adam at warski dot org)
+ */
+public class FirstLevelCache {
+ private final Map<Triple<String, Number, Object>, Object> cache;
+
+ public FirstLevelCache() {
+ cache = newHashMap();
+ }
+
+ public Object get(String entityName, Number revision, Object id) {
+ return cache.get(make(entityName, revision, id));
+ }
+
+ public void put(String entityName, Number revision, Object id, Object entity) {
+ cache.put(make(entityName, revision, id), entity);
+ }
+
+ public boolean contains(String entityName, Number revision, Object id) {
+ return cache.containsKey(make(entityName, revision, id));
+ }
+}
Added: core/trunk/envers/src/main/java/org/jboss/envers/reader/VersionsReaderImpl.java
===================================================================
--- core/trunk/envers/src/main/java/org/jboss/envers/reader/VersionsReaderImpl.java (rev 0)
+++ core/trunk/envers/src/main/java/org/jboss/envers/reader/VersionsReaderImpl.java 2008-10-27 18:56:31 UTC (rev 15406)
@@ -0,0 +1,194 @@
+/*
+ * Envers. http://www.jboss.org/envers
+ *
+ * Copyright 2008 Red Hat Middleware, LLC. All rights reserved.
+ *
+ * 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, v. 2.1.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT A 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, v.2.1 along with this distribution; if not, write to the Free
+ * Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+ * 02110-1301, USA.
+ *
+ * Red Hat Author(s): Adam Warski
+ */
+package org.jboss.envers.reader;
+
+import org.hibernate.NonUniqueResultException;
+import org.hibernate.Session;
+import org.hibernate.Query;
+import org.hibernate.engine.SessionImplementor;
+import org.jboss.envers.configuration.VersionsConfiguration;
+import org.jboss.envers.exception.VersionsException;
+import org.jboss.envers.exception.NotVersionedException;
+import org.jboss.envers.exception.RevisionDoesNotExistException;
+
+import javax.persistence.NoResultException;
+
+import static org.jboss.envers.tools.ArgumentsTools.*;
+import org.jboss.envers.query.VersionsQueryCreator;
+import org.jboss.envers.query.VersionsRestrictions;
+import org.jboss.envers.query.RevisionProperty;
+
+import java.util.*;
+
+/**
+ * @author Adam Warski (adam at warski dot org)
+ */
+public class VersionsReaderImpl implements VersionsReaderImplementor {
+ private final VersionsConfiguration verCfg;
+ private final SessionImplementor sessionImplementor;
+ private final Session session;
+ private final FirstLevelCache firstLevelCache;
+
+ public VersionsReaderImpl(VersionsConfiguration verCfg, Session session,
+ SessionImplementor sessionImplementor) {
+ this.verCfg = verCfg;
+ this.sessionImplementor = sessionImplementor;
+ this.session = session;
+
+ firstLevelCache = new FirstLevelCache();
+ }
+
+ private void checkSession() {
+ if (!session.isOpen()) {
+ throw new IllegalStateException("The associated entity manager is closed!");
+ }
+ }
+
+ public SessionImplementor getSessionImplementor() {
+ return sessionImplementor;
+ }
+
+ public Session getSession() {
+ return session;
+ }
+
+ public FirstLevelCache getFirstLevelCache() {
+ return firstLevelCache;
+ }
+
+ @SuppressWarnings({"unchecked"})
+ public <T> T find(Class<T> cls, Object primaryKey, Number revision) throws
+ IllegalArgumentException, NotVersionedException, IllegalStateException {
+ checkNotNull(cls, "Entity class");
+ checkNotNull(primaryKey, "Primary key");
+ checkNotNull(revision, "Entity revision");
+ checkPositive(revision, "Entity revision");
+ checkSession();
+
+ String entityName = cls.getName();
+
+ if (!verCfg.getEntCfg().isVersioned(entityName)) {
+ throw new NotVersionedException(entityName, entityName + " is not versioned!");
+ }
+
+ if (firstLevelCache.contains(entityName, revision, primaryKey)) {
+ return (T) firstLevelCache.get(entityName, revision, primaryKey);
+ }
+
+ Object result;
+ try {
+ // The result is put into the cache by the entity instantiator called from the query
+ result = createQuery().forEntitiesAtRevision(cls, revision)
+ .add(VersionsRestrictions.idEq(primaryKey)).getSingleResult();
+ } catch (NoResultException e) {
+ result = null;
+ } catch (NonUniqueResultException e) {
+ throw new VersionsException(e);
+ }
+
+ return (T) result;
+ }
+
+ @SuppressWarnings({"unchecked"})
+ public List<Number> getRevisions(Class<?> cls, Object primaryKey)
+ throws IllegalArgumentException, NotVersionedException, IllegalStateException {
+ // todo: if a class is not versioned from the beginning, there's a missing ADD rev - what then?
+ checkNotNull(cls, "Entity class");
+ checkNotNull(primaryKey, "Primary key");
+ checkSession();
+
+ String entityName = cls.getName();
+
+ if (!verCfg.getEntCfg().isVersioned(entityName)) {
+ throw new NotVersionedException(entityName, entityName + " is not versioned!");
+ }
+
+ return createQuery().forRevisionsOfEntity(cls, false, true)
+ .addProjection(RevisionProperty.revisionNumber())
+ .add(VersionsRestrictions.idEq(primaryKey))
+ .getResultList();
+ }
+
+ public Date getRevisionDate(Number revision) throws IllegalArgumentException, RevisionDoesNotExistException,
+ IllegalStateException{
+ checkNotNull(revision, "Entity revision");
+ checkPositive(revision, "Entity revision");
+ checkSession();
+
+ Query query = verCfg.getRevisionInfoQueryCreator().getRevisionDateQuery(session, revision);
+
+ try {
+ Long timestamp = (Long) query.uniqueResult();
+ if (timestamp == null) {
+ throw new RevisionDoesNotExistException(revision);
+ }
+
+ return new Date(timestamp);
+ } catch (NonUniqueResultException e) {
+ throw new VersionsException(e);
+ }
+ }
+
+ public Number getRevisionNumberForDate(Date date) {
+ checkNotNull(date, "Date of revision");
+ checkSession();
+
+ Query query = verCfg.getRevisionInfoQueryCreator().getRevisionNumberForDateQuery(session, date);
+
+ try {
+ Number res = (Number) query.uniqueResult();
+ if (res == null) {
+ throw new RevisionDoesNotExistException(date);
+ }
+
+ return res;
+ } catch (NonUniqueResultException e) {
+ throw new VersionsException(e);
+ }
+ }
+
+ @SuppressWarnings({"unchecked"})
+ public <T> T findRevision(Class<T> revisionEntityClass, Number revision) throws IllegalArgumentException,
+ RevisionDoesNotExistException, IllegalStateException {
+ checkNotNull(revision, "Entity revision");
+ checkPositive(revision, "Entity revision");
+ checkSession();
+
+ Query query = verCfg.getRevisionInfoQueryCreator().getRevisionQuery(session, revision);
+
+ try {
+ T revisionData = (T) query.uniqueResult();
+
+ if (revisionData == null) {
+ throw new RevisionDoesNotExistException(revision);
+ }
+
+ return revisionData;
+ } catch (NonUniqueResultException e) {
+ throw new VersionsException(e);
+ }
+ }
+
+ public VersionsQueryCreator createQuery() {
+ return new VersionsQueryCreator(verCfg, this);
+ }
+}
Added: core/trunk/envers/src/main/java/org/jboss/envers/reader/VersionsReaderImplementor.java
===================================================================
--- core/trunk/envers/src/main/java/org/jboss/envers/reader/VersionsReaderImplementor.java (rev 0)
+++ core/trunk/envers/src/main/java/org/jboss/envers/reader/VersionsReaderImplementor.java 2008-10-27 18:56:31 UTC (rev 15406)
@@ -0,0 +1,36 @@
+/*
+ * Envers. http://www.jboss.org/envers
+ *
+ * Copyright 2008 Red Hat Middleware, LLC. All rights reserved.
+ *
+ * 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, v. 2.1.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT A 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, v.2.1 along with this distribution; if not, write to the Free
+ * Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+ * 02110-1301, USA.
+ *
+ * Red Hat Author(s): Adam Warski
+ */
+package org.jboss.envers.reader;
+
+import org.hibernate.engine.SessionImplementor;
+import org.hibernate.Session;
+import org.jboss.envers.VersionsReader;
+
+/**
+ * An interface exposed by a VersionsReader to library-facing classes.
+ * @author Adam Warski (adam at warski dot org)
+ */
+public interface VersionsReaderImplementor extends VersionsReader {
+ SessionImplementor getSessionImplementor();
+ Session getSession();
+ FirstLevelCache getFirstLevelCache();
+}
Added: core/trunk/envers/src/main/java/org/jboss/envers/revisioninfo/DefaultRevisionInfoGenerator.java
===================================================================
--- core/trunk/envers/src/main/java/org/jboss/envers/revisioninfo/DefaultRevisionInfoGenerator.java (rev 0)
+++ core/trunk/envers/src/main/java/org/jboss/envers/revisioninfo/DefaultRevisionInfoGenerator.java 2008-10-27 18:56:31 UTC (rev 15406)
@@ -0,0 +1,84 @@
+/*
+ * Envers. http://www.jboss.org/envers
+ *
+ * Copyright 2008 Red Hat Middleware, LLC. All rights reserved.
+ *
+ * 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, v. 2.1.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT A 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, v.2.1 along with this distribution; if not, write to the Free
+ * Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+ * 02110-1301, USA.
+ *
+ * Red Hat Author(s): Adam Warski
+ */
+package org.jboss.envers.revisioninfo;
+
+import org.jboss.envers.RevisionListener;
+import org.jboss.envers.tools.reflection.ReflectionTools;
+import org.hibernate.MappingException;
+import org.hibernate.Session;
+import org.hibernate.property.Setter;
+
+/**
+ * @author Adam Warski (adam at warski dot org)
+ */
+public class DefaultRevisionInfoGenerator implements RevisionInfoGenerator {
+ private final String revisionInfoEntityName;
+ private final RevisionListener listener;
+ private final Setter revisionTimestampSetter;
+ private final Class<?> revisionInfoClass;
+
+ public DefaultRevisionInfoGenerator(String revisionInfoEntityName, Class<?> revisionInfoClass,
+ Class<? extends RevisionListener> listenerClass,
+ String revisionInfoTimestampName) {
+ this.revisionInfoEntityName = revisionInfoEntityName;
+ this.revisionInfoClass = revisionInfoClass;
+
+ revisionTimestampSetter = ReflectionTools.getSetter(revisionInfoClass, revisionInfoTimestampName);
+
+ if (!listenerClass.equals(RevisionListener.class)) {
+ // This is not the default value.
+ try {
+ listener = listenerClass.newInstance();
+ } catch (InstantiationException e) {
+ throw new MappingException(e);
+ } catch (IllegalAccessException e) {
+ throw new MappingException(e);
+ }
+ } else {
+ // Default listener - none
+ listener = null;
+ }
+ }
+
+ private Object newRevision() {
+ Object revisionInfo;
+ try {
+ revisionInfo = revisionInfoClass.newInstance();
+ } catch (Exception e) {
+ throw new RuntimeException(e);
+ }
+
+ revisionTimestampSetter.set(revisionInfo, System.currentTimeMillis(), null);
+
+ if (listener != null) {
+ listener.newRevision(revisionInfo);
+ }
+
+ return revisionInfo;
+ }
+
+ public Object generate(Session session) {
+ Object revisionData = newRevision();
+ session.save(revisionInfoEntityName, revisionData);
+ return revisionData;
+ }
+}
Added: core/trunk/envers/src/main/java/org/jboss/envers/revisioninfo/RevisionInfoGenerator.java
===================================================================
--- core/trunk/envers/src/main/java/org/jboss/envers/revisioninfo/RevisionInfoGenerator.java (rev 0)
+++ core/trunk/envers/src/main/java/org/jboss/envers/revisioninfo/RevisionInfoGenerator.java 2008-10-27 18:56:31 UTC (rev 15406)
@@ -0,0 +1,31 @@
+/*
+ * Envers. http://www.jboss.org/envers
+ *
+ * Copyright 2008 Red Hat Middleware, LLC. All rights reserved.
+ *
+ * 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, v. 2.1.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT A 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, v.2.1 along with this distribution; if not, write to the Free
+ * Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+ * 02110-1301, USA.
+ *
+ * Red Hat Author(s): Adam Warski
+ */
+package org.jboss.envers.revisioninfo;
+
+import org.hibernate.Session;
+
+/**
+ * @author Adam Warski (adam at warski dot org)
+ */
+public interface RevisionInfoGenerator {
+ Object generate(Session session);
+}
Added: core/trunk/envers/src/main/java/org/jboss/envers/revisioninfo/RevisionInfoNumberReader.java
===================================================================
--- core/trunk/envers/src/main/java/org/jboss/envers/revisioninfo/RevisionInfoNumberReader.java (rev 0)
+++ core/trunk/envers/src/main/java/org/jboss/envers/revisioninfo/RevisionInfoNumberReader.java 2008-10-27 18:56:31 UTC (rev 15406)
@@ -0,0 +1,40 @@
+/*
+ * Envers. http://www.jboss.org/envers
+ *
+ * Copyright 2008 Red Hat Middleware, LLC. All rights reserved.
+ *
+ * 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, v. 2.1.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT A 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, v.2.1 along with this distribution; if not, write to the Free
+ * Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+ * 02110-1301, USA.
+ *
+ * Red Hat Author(s): Adam Warski
+ */
+package org.jboss.envers.revisioninfo;
+
+import org.jboss.envers.tools.reflection.ReflectionTools;
+import org.hibernate.property.Getter;
+
+/**
+ * Gets a revision number from a persisted revision info entity.
+ * @author Adam Warski (adam at warski dot org)
+ */
+public class RevisionInfoNumberReader {
+ private final Getter revisionIdGetter;
+ public RevisionInfoNumberReader(Class<?> revisionInfoClass, String revisionInfoIdName) {
+ revisionIdGetter = ReflectionTools.getGetter(revisionInfoClass, revisionInfoIdName);
+ }
+
+ public Number getRevisionNumber(Object revision) {
+ return (Number) revisionIdGetter.get(revision);
+ }
+}
Added: core/trunk/envers/src/main/java/org/jboss/envers/revisioninfo/RevisionInfoQueryCreator.java
===================================================================
--- core/trunk/envers/src/main/java/org/jboss/envers/revisioninfo/RevisionInfoQueryCreator.java (rev 0)
+++ core/trunk/envers/src/main/java/org/jboss/envers/revisioninfo/RevisionInfoQueryCreator.java 2008-10-27 18:56:31 UTC (rev 15406)
@@ -0,0 +1,71 @@
+/*
+ * JBoss, Home of Professional Open Source
+ *
+ * Copyright 2008, Red Hat Middleware LLC, and others contributors as indicated
+ * by the @authors tag. All rights reserved.
+ *
+ * See the copyright.txt in the distribution for a full listing of individual
+ * contributors. 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, v. 2.1.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT A 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, v.2.1 along with this distribution; if not, write to the Free
+ * Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+ * 02110-1301, USA.
+ *
+ * Red Hat Author(s): Adam Warski
+ */
+package org.jboss.envers.revisioninfo;
+
+import org.hibernate.Session;
+import org.hibernate.Query;
+
+import java.util.Date;
+
+/**
+ * @author Adam Warski (adam at warski dot org)
+ */
+public class RevisionInfoQueryCreator {
+ private final String revisionDateQuery;
+ private final String revisionNumberForDateQuery;
+ private final String revisionQuery;
+
+ public RevisionInfoQueryCreator(String revisionInfoEntityName, String revisionInfoIdName,
+ String revisionInfoTimestampName) {
+ revisionDateQuery = new StringBuilder()
+ .append("select rev.").append(revisionInfoTimestampName)
+ .append(" from ").append(revisionInfoEntityName)
+ .append(" rev where ").append(revisionInfoIdName).append(" = :_revision_number")
+ .toString();
+
+ revisionNumberForDateQuery = new StringBuilder()
+ .append("select max(rev.").append(revisionInfoIdName)
+ .append(") from ").append(revisionInfoEntityName)
+ .append(" rev where ").append(revisionInfoTimestampName).append(" <= :_revision_date")
+ .toString();
+
+ revisionQuery = new StringBuilder()
+ .append("select rev from ").append(revisionInfoEntityName)
+ .append(" rev where ").append(revisionInfoIdName)
+ .append(" = :_revision_number")
+ .toString();
+ }
+
+ public Query getRevisionDateQuery(Session session, Number revision) {
+ return session.createQuery(revisionDateQuery).setParameter("_revision_number", revision);
+ }
+
+ public Query getRevisionNumberForDateQuery(Session session, Date date) {
+ return session.createQuery(revisionNumberForDateQuery).setParameter("_revision_date", date.getTime());
+ }
+
+ public Query getRevisionQuery(Session session, Number revision) {
+ return session.createQuery(revisionQuery).setParameter("_revision_number", revision);
+ }
+}
Added: core/trunk/envers/src/main/java/org/jboss/envers/synchronization/VersionsSync.java
===================================================================
--- core/trunk/envers/src/main/java/org/jboss/envers/synchronization/VersionsSync.java (rev 0)
+++ core/trunk/envers/src/main/java/org/jboss/envers/synchronization/VersionsSync.java 2008-10-27 18:56:31 UTC (rev 15406)
@@ -0,0 +1,154 @@
+/*
+ * Envers. http://www.jboss.org/envers
+ *
+ * Copyright 2008 Red Hat Middleware, LLC. All rights reserved.
+ *
+ * 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, v. 2.1.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT A 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, v.2.1 along with this distribution; if not, write to the Free
+ * Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+ * 02110-1301, USA.
+ *
+ * Red Hat Author(s): Adam Warski
+ */
+package org.jboss.envers.synchronization;
+
+import org.hibernate.Session;
+import org.hibernate.Transaction;
+import org.hibernate.FlushMode;
+import org.hibernate.event.EventSource;
+import org.jboss.envers.synchronization.work.VersionsWorkUnit;
+import org.jboss.envers.tools.Pair;
+import org.jboss.envers.revisioninfo.RevisionInfoGenerator;
+
+import javax.transaction.Synchronization;
+import java.util.*;
+
+/**
+ * @author Adam Warski (adam at warski dot org)
+ */
+public class VersionsSync implements Synchronization {
+ private final RevisionInfoGenerator revisionInfoGenerator;
+ private final VersionsSyncManager manager;
+ private final EventSource session;
+
+ private final Transaction transaction;
+ private final LinkedList<VersionsWorkUnit> workUnits;
+ private final Queue<VersionsWorkUnit> undoQueue;
+ private final Map<Pair<String, Object>, VersionsWorkUnit> usedIds;
+
+ private Object revisionData;
+
+ public VersionsSync(VersionsSyncManager manager, EventSource session, RevisionInfoGenerator revisionInfoGenerator) {
+ this.manager = manager;
+ this.session = session;
+ this.revisionInfoGenerator = revisionInfoGenerator;
+
+ transaction = session.getTransaction();
+ workUnits = new LinkedList<VersionsWorkUnit>();
+ undoQueue = new LinkedList<VersionsWorkUnit>();
+ usedIds = new HashMap<Pair<String, Object>, VersionsWorkUnit>();
+ }
+
+ private void removeWorkUnit(VersionsWorkUnit vwu) {
+ workUnits.remove(vwu);
+ if (vwu.isPerformed()) {
+ // If this work unit has already been performed, it must be deleted (undone) first.
+ undoQueue.offer(vwu);
+ }
+ }
+
+ public void addWorkUnit(VersionsWorkUnit vwu) {
+ if (vwu.containsWork()) {
+ Object entityId = vwu.getEntityId();
+
+ if (entityId == null) {
+ // Just adding the work unit - it's not associated with any persistent entity.
+ workUnits.offer(vwu);
+ } else {
+ String entityName = vwu.getEntityName();
+ Pair<String, Object> usedIdsKey = Pair.make(entityName, entityId);
+
+ if (usedIds.containsKey(usedIdsKey)) {
+ VersionsWorkUnit other = usedIds.get(usedIdsKey);
+
+ // The entity with entityId has two work units; checking which one should be kept.
+ switch (vwu.dispatch(other)) {
+ case FIRST:
+ // Simply not adding the second
+ break;
+
+ case SECOND:
+ removeWorkUnit(other);
+ usedIds.put(usedIdsKey, vwu);
+ workUnits.offer(vwu);
+ break;
+
+ case NONE:
+ removeWorkUnit(other);
+ break;
+ }
+ } else {
+ usedIds.put(usedIdsKey, vwu);
+ workUnits.offer(vwu);
+ }
+ }
+ }
+ }
+
+ private void executeInSession(Session session) {
+ if (revisionData == null) {
+ revisionData = revisionInfoGenerator.generate(session);
+ }
+
+ VersionsWorkUnit vwu;
+
+ // First undoing any performed work units
+ while ((vwu = undoQueue.poll()) != null) {
+ vwu.undo(session);
+ }
+
+ while ((vwu = workUnits.poll()) != null) {
+ vwu.perform(session, revisionData);
+ }
+ }
+
+ public void beforeCompletion() {
+ if (workUnits.size() == 0 && undoQueue.size() == 0) {
+ return;
+ }
+
+ // see: http://www.jboss.com/index.html?module=bb&op=viewtopic&p=4178431
+ if (FlushMode.isManualFlushMode(session.getFlushMode()) || session.isClosed()) {
+ Session temporarySession = null;
+ try {
+ temporarySession = session.getFactory().openTemporarySession();
+
+ executeInSession(temporarySession);
+
+ temporarySession.flush();
+ } finally {
+ if (temporarySession != null) {
+ temporarySession.close();
+ }
+ }
+ } else {
+ executeInSession(session);
+
+ // Explicity flushing the session, as the auto-flush may have already happened.
+ session.flush();
+ }
+ }
+
+ public void afterCompletion(int i) {
+ manager.remove(transaction);
+ }
+}
Added: core/trunk/envers/src/main/java/org/jboss/envers/synchronization/VersionsSyncManager.java
===================================================================
--- core/trunk/envers/src/main/java/org/jboss/envers/synchronization/VersionsSyncManager.java (rev 0)
+++ core/trunk/envers/src/main/java/org/jboss/envers/synchronization/VersionsSyncManager.java 2008-10-27 18:56:31 UTC (rev 15406)
@@ -0,0 +1,63 @@
+/*
+ * Envers. http://www.jboss.org/envers
+ *
+ * Copyright 2008 Red Hat Middleware, LLC. All rights reserved.
+ *
+ * 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, v. 2.1.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT A 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, v.2.1 along with this distribution; if not, write to the Free
+ * Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+ * 02110-1301, USA.
+ *
+ * Red Hat Author(s): Adam Warski
+ */
+package org.jboss.envers.synchronization;
+
+import org.jboss.envers.tools.ConcurrentReferenceHashMap;
+import org.jboss.envers.revisioninfo.RevisionInfoGenerator;
+import org.hibernate.Transaction;
+import org.hibernate.event.EventSource;
+
+import java.util.Map;
+
+/**
+ * @author Adam Warski (adam at warski dot org)
+ */
+public class VersionsSyncManager {
+ private final Map<Transaction, VersionsSync> versionsSyncs;
+ private final RevisionInfoGenerator revisionInfoGenerator;
+
+ public VersionsSyncManager(RevisionInfoGenerator revisionInfoGenerator) {
+ versionsSyncs = new ConcurrentReferenceHashMap<Transaction, VersionsSync>(10,
+ ConcurrentReferenceHashMap.ReferenceType.WEAK,
+ ConcurrentReferenceHashMap.ReferenceType.STRONG);
+
+ this.revisionInfoGenerator = revisionInfoGenerator;
+ }
+
+ public VersionsSync get(EventSource session) {
+ Transaction transaction = session.getTransaction();
+
+ VersionsSync verSync = versionsSyncs.get(transaction);
+ if (verSync == null) {
+ verSync = new VersionsSync(this, session, revisionInfoGenerator);
+ versionsSyncs.put(transaction, verSync);
+
+ transaction.registerSynchronization(verSync);
+ }
+
+ return verSync;
+ }
+
+ public void remove(Transaction transaction) {
+ versionsSyncs.remove(transaction);
+ }
+}
Added: core/trunk/envers/src/main/java/org/jboss/envers/synchronization/work/AbstractVersionsWorkUnit.java
===================================================================
--- core/trunk/envers/src/main/java/org/jboss/envers/synchronization/work/AbstractVersionsWorkUnit.java (rev 0)
+++ core/trunk/envers/src/main/java/org/jboss/envers/synchronization/work/AbstractVersionsWorkUnit.java 2008-10-27 18:56:31 UTC (rev 15406)
@@ -0,0 +1,83 @@
+/*
+ * Envers. http://www.jboss.org/envers
+ *
+ * Copyright 2008 Red Hat Middleware, LLC. All rights reserved.
+ *
+ * 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, v. 2.1.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT A 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, v.2.1 along with this distribution; if not, write to the Free
+ * Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+ * 02110-1301, USA.
+ *
+ * Red Hat Author(s): Adam Warski
+ */
+package org.jboss.envers.synchronization.work;
+
+import org.jboss.envers.configuration.VersionsEntitiesConfiguration;
+import org.jboss.envers.configuration.VersionsConfiguration;
+import org.jboss.envers.RevisionType;
+import org.hibernate.Session;
+
+import java.util.Map;
+import java.util.HashMap;
+import java.io.Serializable;
+
+/**
+ * @author Adam Warski (adam at warski dot org)
+ */
+public abstract class AbstractVersionsWorkUnit implements VersionsWorkUnit {
+ protected final VersionsConfiguration verCfg;
+ protected final Serializable id;
+
+ private final String entityName;
+
+ private Object performedData;
+
+ protected AbstractVersionsWorkUnit(String entityName, VersionsConfiguration verCfg, Serializable id) {
+ this.verCfg = verCfg;
+ this.id = id;
+ this.entityName = entityName;
+ }
+
+ protected void fillDataWithId(Map<String, Object> data, Object revision, RevisionType revisionType) {
+ VersionsEntitiesConfiguration entitiesCfg = verCfg.getVerEntCfg();
+
+ Map<String, Object> originalId = new HashMap<String, Object>();
+ originalId.put(entitiesCfg.getRevisionPropName(), revision);
+
+ verCfg.getEntCfg().get(getEntityName()).getIdMapper().mapToMapFromId(originalId, id);
+ data.put(entitiesCfg.getRevisionTypePropName(), revisionType);
+ data.put(entitiesCfg.getOriginalIdPropName(), originalId);
+ }
+
+ public Object getEntityId() {
+ return id;
+ }
+
+ public boolean isPerformed() {
+ return performedData != null;
+ }
+
+ public String getEntityName() {
+ return entityName;
+ }
+
+ protected void setPerformed(Object performedData) {
+ this.performedData = performedData;
+ }
+
+ public void undo(Session session) {
+ if (isPerformed()) {
+ session.delete(verCfg.getVerEntCfg().getVersionsEntityName(getEntityName()), performedData);
+ session.flush();
+ }
+ }
+}
Added: core/trunk/envers/src/main/java/org/jboss/envers/synchronization/work/AddWorkUnit.java
===================================================================
--- core/trunk/envers/src/main/java/org/jboss/envers/synchronization/work/AddWorkUnit.java (rev 0)
+++ core/trunk/envers/src/main/java/org/jboss/envers/synchronization/work/AddWorkUnit.java 2008-10-27 18:56:31 UTC (rev 15406)
@@ -0,0 +1,82 @@
+/*
+ * Envers. http://www.jboss.org/envers
+ *
+ * Copyright 2008 Red Hat Middleware, LLC. All rights reserved.
+ *
+ * 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, v. 2.1.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT A 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, v.2.1 along with this distribution; if not, write to the Free
+ * Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+ * 02110-1301, USA.
+ *
+ * Red Hat Author(s): Adam Warski
+ */
+package org.jboss.envers.synchronization.work;
+
+import org.jboss.envers.configuration.VersionsConfiguration;
+import org.jboss.envers.RevisionType;
+import org.hibernate.persister.entity.EntityPersister;
+import org.hibernate.Session;
+
+import java.io.Serializable;
+import java.util.Map;
+import java.util.HashMap;
+
+/**
+ * @author Adam Warski (adam at warski dot org)
+ */
+public class AddWorkUnit extends AbstractVersionsWorkUnit implements VersionsWorkUnit {
+ private final Object[] state;
+ private final String[] propertyNames;
+
+ public AddWorkUnit(String entityName, VersionsConfiguration verCfg, Serializable id,
+ EntityPersister entityPersister, Object[] state) {
+ super(entityName, verCfg, id);
+
+ this.state = state;
+ this.propertyNames = entityPersister.getPropertyNames();
+ }
+
+ public boolean containsWork() {
+ return true;
+ }
+
+ public void perform(Session session, Object revisionData) {
+ Map<String, Object> data = new HashMap<String, Object>();
+ fillDataWithId(data, revisionData, RevisionType.ADD);
+
+ verCfg.getEntCfg().get(getEntityName()).getPropertyMapper().map(data, propertyNames, state, null);
+
+ session.save(verCfg.getVerEntCfg().getVersionsEntityName(getEntityName()), data);
+
+ setPerformed(data);
+ }
+
+ public KeepCheckResult check(AddWorkUnit second) {
+ return KeepCheckResult.FIRST;
+ }
+
+ public KeepCheckResult check(ModWorkUnit second) {
+ return KeepCheckResult.SECOND;
+ }
+
+ public KeepCheckResult check(DelWorkUnit second) {
+ return KeepCheckResult.NONE;
+ }
+
+ public KeepCheckResult check(CollectionChangeWorkUnit second) {
+ return KeepCheckResult.FIRST;
+ }
+
+ public KeepCheckResult dispatch(KeepCheckVisitor first) {
+ return first.check(this);
+ }
+}
Added: core/trunk/envers/src/main/java/org/jboss/envers/synchronization/work/CollectionChangeWorkUnit.java
===================================================================
--- core/trunk/envers/src/main/java/org/jboss/envers/synchronization/work/CollectionChangeWorkUnit.java (rev 0)
+++ core/trunk/envers/src/main/java/org/jboss/envers/synchronization/work/CollectionChangeWorkUnit.java 2008-10-27 18:56:31 UTC (rev 15406)
@@ -0,0 +1,78 @@
+/*
+ * Envers. http://www.jboss.org/envers
+ *
+ * Copyright 2008 Red Hat Middleware, LLC. All rights reserved.
+ *
+ * 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, v. 2.1.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT A 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, v.2.1 along with this distribution; if not, write to the Free
+ * Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+ * 02110-1301, USA.
+ *
+ * Red Hat Author(s): Adam Warski
+ */
+package org.jboss.envers.synchronization.work;
+
+import org.hibernate.Session;
+import org.jboss.envers.configuration.VersionsConfiguration;
+import org.jboss.envers.RevisionType;
+
+import java.io.Serializable;
+import java.util.Map;
+import java.util.HashMap;
+
+/**
+ * @author Adam Warski (adam at warski dot org)
+ */
+public class CollectionChangeWorkUnit extends AbstractVersionsWorkUnit implements VersionsWorkUnit {
+ private final Object entity;
+
+ public CollectionChangeWorkUnit(String entityName, VersionsConfiguration verCfg, Serializable id, Object entity) {
+ super(entityName, verCfg, id);
+
+ this.entity = entity;
+ }
+
+ public boolean containsWork() {
+ return true;
+ }
+
+ public void perform(Session session, Object revisionData) {
+ Map<String, Object> data = new HashMap<String, Object>();
+ fillDataWithId(data, revisionData, RevisionType.MOD);
+
+ verCfg.getEntCfg().get(getEntityName()).getPropertyMapper().mapToMapFromEntity(data, entity, null);
+
+ session.save(verCfg.getVerEntCfg().getVersionsEntityName(getEntityName()), data);
+
+ setPerformed(data);
+ }
+
+ public KeepCheckResult check(AddWorkUnit second) {
+ return KeepCheckResult.SECOND;
+ }
+
+ public KeepCheckResult check(ModWorkUnit second) {
+ return KeepCheckResult.SECOND;
+ }
+
+ public KeepCheckResult check(DelWorkUnit second) {
+ return KeepCheckResult.SECOND;
+ }
+
+ public KeepCheckResult check(CollectionChangeWorkUnit second) {
+ return KeepCheckResult.FIRST;
+ }
+
+ public KeepCheckResult dispatch(KeepCheckVisitor first) {
+ return first.check(this);
+ }
+}
Added: core/trunk/envers/src/main/java/org/jboss/envers/synchronization/work/DelWorkUnit.java
===================================================================
--- core/trunk/envers/src/main/java/org/jboss/envers/synchronization/work/DelWorkUnit.java (rev 0)
+++ core/trunk/envers/src/main/java/org/jboss/envers/synchronization/work/DelWorkUnit.java 2008-10-27 18:56:31 UTC (rev 15406)
@@ -0,0 +1,72 @@
+/*
+ * Envers. http://www.jboss.org/envers
+ *
+ * Copyright 2008 Red Hat Middleware, LLC. All rights reserved.
+ *
+ * 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, v. 2.1.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT A 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, v.2.1 along with this distribution; if not, write to the Free
+ * Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+ * 02110-1301, USA.
+ *
+ * Red Hat Author(s): Adam Warski
+ */
+package org.jboss.envers.synchronization.work;
+
+import org.jboss.envers.configuration.VersionsConfiguration;
+import org.jboss.envers.RevisionType;
+import org.hibernate.Session;
+
+import java.io.Serializable;
+import java.util.Map;
+import java.util.HashMap;
+
+/**
+ * @author Adam Warski (adam at warski dot org)
+ */
+public class DelWorkUnit extends AbstractVersionsWorkUnit implements VersionsWorkUnit {
+ public DelWorkUnit(String entityName, VersionsConfiguration verCfg, Serializable id) {
+ super(entityName, verCfg, id);
+ }
+
+ public boolean containsWork() {
+ return true;
+ }
+
+ public void perform(Session session, Object revisionData) {
+ Map<String, Object> data = new HashMap<String, Object>();
+ fillDataWithId(data, revisionData, RevisionType.DEL);
+
+ session.save(verCfg.getVerEntCfg().getVersionsEntityName(getEntityName()), data);
+
+ setPerformed(data);
+ }
+
+ public KeepCheckResult check(AddWorkUnit second) {
+ return KeepCheckResult.NONE;
+ }
+
+ public KeepCheckResult check(ModWorkUnit second) {
+ return KeepCheckResult.NONE;
+ }
+
+ public KeepCheckResult check(DelWorkUnit second) {
+ return KeepCheckResult.FIRST;
+ }
+
+ public KeepCheckResult check(CollectionChangeWorkUnit second) {
+ return KeepCheckResult.FIRST;
+ }
+
+ public KeepCheckResult dispatch(KeepCheckVisitor first) {
+ return first.check(this);
+ }
+}
\ No newline at end of file
Added: core/trunk/envers/src/main/java/org/jboss/envers/synchronization/work/KeepCheckDispatcher.java
===================================================================
--- core/trunk/envers/src/main/java/org/jboss/envers/synchronization/work/KeepCheckDispatcher.java (rev 0)
+++ core/trunk/envers/src/main/java/org/jboss/envers/synchronization/work/KeepCheckDispatcher.java 2008-10-27 18:56:31 UTC (rev 15406)
@@ -0,0 +1,35 @@
+/*
+ * Envers. http://www.jboss.org/envers
+ *
+ * Copyright 2008 Red Hat Middleware, LLC. All rights reserved.
+ *
+ * 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, v. 2.1.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT A 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, v.2.1 along with this distribution; if not, write to the Free
+ * Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+ * 02110-1301, USA.
+ *
+ * Red Hat Author(s): Adam Warski
+ */
+package org.jboss.envers.synchronization.work;
+
+/**
+ * Visitor patter dispatcher.
+ * @author Adam Warski (adam at warski dot org)
+ */
+public interface KeepCheckDispatcher {
+ /**
+ * Shuold be invoked on the second work unit.
+ * @param first First work unit (that is, the one added earlier).
+ * @return Which work unit should be kept.
+ */
+ KeepCheckResult dispatch(KeepCheckVisitor first);
+}
Added: core/trunk/envers/src/main/java/org/jboss/envers/synchronization/work/KeepCheckResult.java
===================================================================
--- core/trunk/envers/src/main/java/org/jboss/envers/synchronization/work/KeepCheckResult.java (rev 0)
+++ core/trunk/envers/src/main/java/org/jboss/envers/synchronization/work/KeepCheckResult.java 2008-10-27 18:56:31 UTC (rev 15406)
@@ -0,0 +1,33 @@
+/*
+ * Envers. http://www.jboss.org/envers
+ *
+ * Copyright 2008 Red Hat Middleware, LLC. All rights reserved.
+ *
+ * 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, v. 2.1.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT A 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, v.2.1 along with this distribution; if not, write to the Free
+ * Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+ * 02110-1301, USA.
+ *
+ * Red Hat Author(s): Adam Warski
+ */
+package org.jboss.envers.synchronization.work;
+
+/**
+ * Possible outcomes of selecting which work unit to keep, in case there are two work units for the same entity
+ * with the same id.
+ * @author Adam Warski (adam at warski dot org)
+ */
+public enum KeepCheckResult {
+ FIRST,
+ SECOND,
+ NONE
+}
Added: core/trunk/envers/src/main/java/org/jboss/envers/synchronization/work/KeepCheckVisitor.java
===================================================================
--- core/trunk/envers/src/main/java/org/jboss/envers/synchronization/work/KeepCheckVisitor.java (rev 0)
+++ core/trunk/envers/src/main/java/org/jboss/envers/synchronization/work/KeepCheckVisitor.java 2008-10-27 18:56:31 UTC (rev 15406)
@@ -0,0 +1,33 @@
+/*
+ * Envers. http://www.jboss.org/envers
+ *
+ * Copyright 2008 Red Hat Middleware, LLC. All rights reserved.
+ *
+ * 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, v. 2.1.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT A 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, v.2.1 along with this distribution; if not, write to the Free
+ * Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+ * 02110-1301, USA.
+ *
+ * Red Hat Author(s): Adam Warski
+ */
+package org.jboss.envers.synchronization.work;
+
+/**
+ * Visitor pattern visitor. All methods should be invoked on the first work unit.
+ * @author Adam Warski (adam at warski dot org)
+ */
+public interface KeepCheckVisitor {
+ KeepCheckResult check(AddWorkUnit second);
+ KeepCheckResult check(ModWorkUnit second);
+ KeepCheckResult check(DelWorkUnit second);
+ KeepCheckResult check(CollectionChangeWorkUnit second);
+}
Added: core/trunk/envers/src/main/java/org/jboss/envers/synchronization/work/ModWorkUnit.java
===================================================================
--- core/trunk/envers/src/main/java/org/jboss/envers/synchronization/work/ModWorkUnit.java (rev 0)
+++ core/trunk/envers/src/main/java/org/jboss/envers/synchronization/work/ModWorkUnit.java 2008-10-27 18:56:31 UTC (rev 15406)
@@ -0,0 +1,80 @@
+/*
+ * Envers. http://www.jboss.org/envers
+ *
+ * Copyright 2008 Red Hat Middleware, LLC. All rights reserved.
+ *
+ * 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, v. 2.1.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT A 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, v.2.1 along with this distribution; if not, write to the Free
+ * Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+ * 02110-1301, USA.
+ *
+ * Red Hat Author(s): Adam Warski
+ */
+package org.jboss.envers.synchronization.work;
+
+import org.jboss.envers.configuration.VersionsConfiguration;
+import org.jboss.envers.RevisionType;
+import org.hibernate.persister.entity.EntityPersister;
+import org.hibernate.Session;
+
+import java.io.Serializable;
+import java.util.Map;
+import java.util.HashMap;
+
+/**
+ * @author Adam Warski (adam at warski dot org)
+ */
+public class ModWorkUnit extends AbstractVersionsWorkUnit implements VersionsWorkUnit {
+ private final Map<String, Object> data;
+ private final boolean changes;
+
+ public ModWorkUnit(String entityName, VersionsConfiguration verCfg, Serializable id,
+ EntityPersister entityPersister, Object[] newState, Object[] oldState) {
+ super(entityName, verCfg, id);
+
+ data = new HashMap<String, Object>();
+ changes = verCfg.getEntCfg().get(getEntityName()).getPropertyMapper().map(data, entityPersister.getPropertyNames(),
+ newState, oldState);
+ }
+
+ public boolean containsWork() {
+ return changes;
+ }
+
+ public void perform(Session session, Object revisionData) {
+ fillDataWithId(data, revisionData, RevisionType.MOD);
+
+ session.save(verCfg.getVerEntCfg().getVersionsEntityName(getEntityName()), data);
+
+ setPerformed(data);
+ }
+
+ public KeepCheckResult check(AddWorkUnit second) {
+ return KeepCheckResult.FIRST;
+ }
+
+ public KeepCheckResult check(ModWorkUnit second) {
+ return KeepCheckResult.SECOND;
+ }
+
+ public KeepCheckResult check(DelWorkUnit second) {
+ return KeepCheckResult.SECOND;
+ }
+
+ public KeepCheckResult check(CollectionChangeWorkUnit second) {
+ return KeepCheckResult.FIRST;
+ }
+
+ public KeepCheckResult dispatch(KeepCheckVisitor first) {
+ return first.check(this);
+ }
+}
\ No newline at end of file
Added: core/trunk/envers/src/main/java/org/jboss/envers/synchronization/work/PersistentCollectionChangeWorkUnit.java
===================================================================
--- core/trunk/envers/src/main/java/org/jboss/envers/synchronization/work/PersistentCollectionChangeWorkUnit.java (rev 0)
+++ core/trunk/envers/src/main/java/org/jboss/envers/synchronization/work/PersistentCollectionChangeWorkUnit.java 2008-10-27 18:56:31 UTC (rev 15406)
@@ -0,0 +1,98 @@
+/*
+ * JBoss, Home of Professional Open Source
+ *
+ * Copyright 2008, Red Hat Middleware LLC, and others contributors as indicated
+ * by the @authors tag. All rights reserved.
+ *
+ * See the copyright.txt in the distribution for a full listing of individual
+ * contributors. 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, v. 2.1.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT A 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, v.2.1 along with this distribution; if not, write to the Free
+ * Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+ * 02110-1301, USA.
+ *
+ * Red Hat Author(s): Adam Warski
+ */
+package org.jboss.envers.synchronization.work;
+
+import org.hibernate.Session;
+import org.hibernate.collection.PersistentCollection;
+import org.jboss.envers.configuration.VersionsConfiguration;
+import org.jboss.envers.configuration.VersionsEntitiesConfiguration;
+import org.jboss.envers.entities.mapper.PersistentCollectionChangeData;
+
+import java.io.Serializable;
+import java.util.List;
+import java.util.Map;
+
+/**
+ * @author Adam Warski (adam at warski dot org)
+ */
+public class PersistentCollectionChangeWorkUnit extends AbstractVersionsWorkUnit implements VersionsWorkUnit {
+ private final List<PersistentCollectionChangeData> collectionChanges;
+ private final String referencingPropertyName;
+
+ public PersistentCollectionChangeWorkUnit(String entityName, VersionsConfiguration verCfg,
+ PersistentCollection collection, String role,
+ Serializable snapshot, Serializable id) {
+ super(entityName, verCfg, null);
+
+ referencingPropertyName = role.substring(entityName.length() + 1);
+
+ collectionChanges = verCfg.getEntCfg().get(getEntityName()).getPropertyMapper()
+ .mapCollectionChanges(referencingPropertyName, collection, snapshot, id);
+ }
+
+ public boolean containsWork() {
+ return collectionChanges != null && collectionChanges.size() != 0;
+ }
+
+ @SuppressWarnings({"unchecked"})
+ public void perform(Session session, Object revisionData) {
+ VersionsEntitiesConfiguration entitiesCfg = verCfg.getVerEntCfg();
+
+ for (PersistentCollectionChangeData persistentCollectionChangeData : collectionChanges) {
+ // Setting the revision number
+ ((Map<String, Object>) persistentCollectionChangeData.getData().get(entitiesCfg.getOriginalIdPropName()))
+ .put(entitiesCfg.getRevisionPropName(), revisionData);
+
+ session.save(persistentCollectionChangeData.getEntityName(), persistentCollectionChangeData.getData());
+ }
+ }
+
+ public String getReferencingPropertyName() {
+ return referencingPropertyName;
+ }
+
+ public List<PersistentCollectionChangeData> getCollectionChanges() {
+ return collectionChanges;
+ }
+
+ public KeepCheckResult check(AddWorkUnit second) {
+ return null;
+ }
+
+ public KeepCheckResult check(ModWorkUnit second) {
+ return null;
+ }
+
+ public KeepCheckResult check(DelWorkUnit second) {
+ return null;
+ }
+
+ public KeepCheckResult check(CollectionChangeWorkUnit second) {
+ return null;
+ }
+
+ public KeepCheckResult dispatch(KeepCheckVisitor first) {
+ return null;
+ }
+}
Added: core/trunk/envers/src/main/java/org/jboss/envers/synchronization/work/VersionsWorkUnit.java
===================================================================
--- core/trunk/envers/src/main/java/org/jboss/envers/synchronization/work/VersionsWorkUnit.java (rev 0)
+++ core/trunk/envers/src/main/java/org/jboss/envers/synchronization/work/VersionsWorkUnit.java 2008-10-27 18:56:31 UTC (rev 15406)
@@ -0,0 +1,39 @@
+/*
+ * Envers. http://www.jboss.org/envers
+ *
+ * Copyright 2008 Red Hat Middleware, LLC. All rights reserved.
+ *
+ * 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, v. 2.1.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT A 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, v.2.1 along with this distribution; if not, write to the Free
+ * Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+ * 02110-1301, USA.
+ *
+ * Red Hat Author(s): Adam Warski
+ */
+package org.jboss.envers.synchronization.work;
+
+import org.hibernate.Session;
+
+/**
+ * @author Adam Warski (adam at warski dot org)
+ */
+public interface VersionsWorkUnit extends KeepCheckVisitor, KeepCheckDispatcher {
+ Object getEntityId();
+ String getEntityName();
+
+ boolean containsWork();
+
+ boolean isPerformed();
+
+ void perform(Session session, Object revisionData);
+ void undo(Session session);
+}
Added: core/trunk/envers/src/main/java/org/jboss/envers/tools/ArgumentsTools.java
===================================================================
--- core/trunk/envers/src/main/java/org/jboss/envers/tools/ArgumentsTools.java (rev 0)
+++ core/trunk/envers/src/main/java/org/jboss/envers/tools/ArgumentsTools.java 2008-10-27 18:56:31 UTC (rev 15406)
@@ -0,0 +1,39 @@
+/*
+ * Envers. http://www.jboss.org/envers
+ *
+ * Copyright 2008 Red Hat Middleware, LLC. All rights reserved.
+ *
+ * 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, v. 2.1.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT A 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, v.2.1 along with this distribution; if not, write to the Free
+ * Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+ * 02110-1301, USA.
+ *
+ * Red Hat Author(s): Adam Warski
+ */
+package org.jboss.envers.tools;
+
+/**
+ * @author Adam Warski (adam at warski dot org)
+ */
+public class ArgumentsTools {
+ public static void checkNotNull(Object o, String paramName) {
+ if (o == null) {
+ throw new IllegalArgumentException(paramName + " cannot be null.");
+ }
+ }
+
+ public static void checkPositive(Number i, String paramName) {
+ if (i.longValue() <= 0l) {
+ throw new IllegalArgumentException(paramName + " has to be greater than 0.");
+ }
+ }
+}
Added: core/trunk/envers/src/main/java/org/jboss/envers/tools/ArraysTools.java
===================================================================
--- core/trunk/envers/src/main/java/org/jboss/envers/tools/ArraysTools.java (rev 0)
+++ core/trunk/envers/src/main/java/org/jboss/envers/tools/ArraysTools.java 2008-10-27 18:56:31 UTC (rev 15406)
@@ -0,0 +1,37 @@
+/*
+ * Envers. http://www.jboss.org/envers
+ *
+ * Copyright 2008 Red Hat Middleware, LLC. All rights reserved.
+ *
+ * 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, v. 2.1.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT A 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, v.2.1 along with this distribution; if not, write to the Free
+ * Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+ * 02110-1301, USA.
+ *
+ * Red Hat Author(s): Adam Warski
+ */
+package org.jboss.envers.tools;
+
+/**
+ * @author Adam Warski (adam at warski dot org)
+ */
+public class ArraysTools {
+ public static <T> boolean arrayIncludesInstanceOf(T[] array, Class<?> cls) {
+ for (T obj : array) {
+ if (cls.isAssignableFrom(obj.getClass())) {
+ return true;
+ }
+ }
+
+ return false;
+ }
+}
Added: core/trunk/envers/src/main/java/org/jboss/envers/tools/ConcurrentReferenceHashMap.java
===================================================================
--- core/trunk/envers/src/main/java/org/jboss/envers/tools/ConcurrentReferenceHashMap.java (rev 0)
+++ core/trunk/envers/src/main/java/org/jboss/envers/tools/ConcurrentReferenceHashMap.java 2008-10-27 18:56:31 UTC (rev 15406)
@@ -0,0 +1,1710 @@
+/*
+ * Written by Doug Lea with assistance from members of JCP JSR-166
+ * Expert Group and released to the public domain, as explained at
+ * http://creativecommons.org/licenses/publicdomain
+ */
+
+package org.jboss.envers.tools;
+
+import java.io.IOException;
+import java.io.Serializable;
+import java.lang.ref.Reference;
+import java.lang.ref.ReferenceQueue;
+import java.lang.ref.SoftReference;
+import java.lang.ref.WeakReference;
+import java.util.AbstractCollection;
+import java.util.AbstractMap;
+import java.util.AbstractSet;
+import java.util.Collection;
+import java.util.ConcurrentModificationException;
+import java.util.EnumSet;
+import java.util.Enumeration;
+import java.util.HashMap;
+import java.util.Hashtable;
+import java.util.IdentityHashMap;
+import java.util.Iterator;
+import java.util.Map;
+import java.util.NoSuchElementException;
+import java.util.Set;
+import java.util.concurrent.locks.ReentrantLock;
+
+/**
+ * An advanced hash table supporting configurable garbage collection semantics
+ * of keys and values, optional referential-equality, full concurrency of
+ * retrievals, and adjustable expected concurrency for updates.
+ *
+ * This table is designed around specific advanced use-cases. If there is any
+ * doubt whether this table is for you, you most likely should be using
+ * {@link java.util.concurrent.ConcurrentHashMap} instead.
+ *
+ * This table supports strong, weak, and soft keys and values. By default keys
+ * are weak, and values are strong. Such a configuration offers similar behavior
+ * to {@link java.util.WeakHashMap}, entries of this table are periodically
+ * removed once their corresponding keys are no longer referenced outside of
+ * this table. In other words, this table will not prevent a key from being
+ * discarded by the garbage collector. Once a key has been discarded by the
+ * collector, the corresponding entry is no longer visible to this table;
+ * however, the entry may occupy space until a future table operation decides to
+ * reclaim it. For this reason, summary functions such as <tt>size</tt> and
+ * <tt>isEmpty</tt> might return a value greater than the observed number of
+ * entries. In order to support a high level of concurrency, stale entries are
+ * only reclaimed during blocking (usually mutating) operations.
+ *
+ * Enabling soft keys allows entries in this table to remain until their space
+ * is absolutely needed by the garbage collector. This is unlike weak keys which
+ * can be reclaimed as soon as they are no longer referenced by a normal strong
+ * reference. The primary use case for soft keys is a cache, which ideally
+ * occupies memory that is not in use for as long as possible.
+ *
+ * By default, values are held using a normal strong reference. This provides
+ * the commonly desired guarantee that a value will always have at least the
+ * same life-span as it's key. For this reason, care should be taken to ensure
+ * that a value never refers, either directly or indirectly, to its key, thereby
+ * preventing reclamation. If this is unavoidable, then it is recommended to use
+ * the same reference type in use for the key. However, it should be noted that
+ * non-strong values may disappear before their corresponding key.
+ *
+ * While this table does allow the use of both strong keys and values, it is
+ * recommended to use {@link java.util.concurrent.ConcurrentHashMap} for such a
+ * configuration, since it is optimized for that case.
+ *
+ * Just like {@link java.util.concurrent.ConcurrentHashMap}, this class obeys
+ * the same functional specification as {@link java.util.Hashtable}, and
+ * includes versions of methods corresponding to each method of
+ * <tt>Hashtable</tt>. However, even though all operations are thread-safe,
+ * retrieval operations do <em>not</em> entail locking, and there is
+ * <em>not</em> any support for locking the entire table in a way that
+ * prevents all access. This class is fully interoperable with
+ * <tt>Hashtable</tt> in programs that rely on its thread safety but not on
+ * its synchronization details.
+ *
+ * <p>
+ * Retrieval operations (including <tt>get</tt>) generally do not block, so
+ * may overlap with update operations (including <tt>put</tt> and
+ * <tt>remove</tt>). Retrievals reflect the results of the most recently
+ * <em>completed</em> update operations holding upon their onset. For
+ * aggregate operations such as <tt>putAll</tt> and <tt>clear</tt>,
+ * concurrent retrievals may reflect insertion or removal of only some entries.
+ * Similarly, Iterators and Enumerations return elements reflecting the state of
+ * the hash table at some point at or since the creation of the
+ * iterator/enumeration. They do <em>not</em> throw
+ * {@link ConcurrentModificationException}. However, iterators are designed to
+ * be used by only one thread at a time.
+ *
+ * <p>
+ * The allowed concurrency among update operations is guided by the optional
+ * <tt>concurrencyLevel</tt> constructor argument (default <tt>16</tt>),
+ * which is used as a hint for internal sizing. The table is internally
+ * partitioned to try to permit the indicated number of concurrent updates
+ * without contention. Because placement in hash tables is essentially random,
+ * the actual concurrency will vary. Ideally, you should choose a value to
+ * accommodate as many threads as will ever concurrently modify the table. Using
+ * a significantly higher value than you need can waste space and time, and a
+ * significantly lower value can lead to thread contention. But overestimates
+ * and underestimates within an order of magnitude do not usually have much
+ * noticeable impact. A value of one is appropriate when it is known that only
+ * one thread will modify and all others will only read. Also, resizing this or
+ * any other kind of hash table is a relatively slow operation, so, when
+ * possible, it is a good idea to provide estimates of expected table sizes in
+ * constructors.
+ *
+ * <p>
+ * This class and its views and iterators implement all of the <em>optional</em>
+ * methods of the {@link Map} and {@link Iterator} interfaces.
+ *
+ * <p>
+ * Like {@link Hashtable} but unlike {@link HashMap}, this class does
+ * <em>not</em> allow <tt>null</tt> to be used as a key or value.
+ *
+ * <p>
+ * This class is a member of the <a href="{@docRoot}/../technotes/guides/collections/index.html">
+ * Java Collections Framework</a>.
+ *
+ * @author Doug Lea
+ * @author Jason T. Greene
+ * @param <K> the type of keys maintained by this map
+ * @param <V> the type of mapped values
+ */
+public class ConcurrentReferenceHashMap<K, V> extends AbstractMap<K, V>
+ implements java.util.concurrent.ConcurrentMap<K, V>, Serializable {
+ private static final long serialVersionUID = 7249069246763182397L;
+
+ /*
+ * The basic strategy is to subdivide the table among Segments,
+ * each of which itself is a concurrently readable hash table.
+ */
+
+ /**
+ * An option specifying which Java reference type should be used to refer
+ * to a key and/or value.
+ */
+ public static enum ReferenceType {
+ /** Indicates a normal Java strong reference should be used */
+ STRONG,
+ /** Indicates a {@link WeakReference} should be used */
+ WEAK,
+ /** Indicates a {@link SoftReference} should be used */
+ SOFT
+ };
+
+
+ public static enum Option {
+ /** Indicates that referential-equality (== instead of .equals()) should
+ * be used when locating keys. This offers similar behavior to {@link IdentityHashMap} */
+ IDENTITY_COMPARISONS
+ };
+
+ /* ---------------- Constants -------------- */
+
+ static final ReferenceType DEFAULT_KEY_TYPE = ReferenceType.WEAK;
+
+ static final ReferenceType DEFAULT_VALUE_TYPE = ReferenceType.STRONG;
+
+
+ /**
+ * The default initial capacity for this table,
+ * used when not otherwise specified in a constructor.
+ */
+ static final int DEFAULT_INITIAL_CAPACITY = 16;
+
+ /**
+ * The default load factor for this table, used when not
+ * otherwise specified in a constructor.
+ */
+ static final float DEFAULT_LOAD_FACTOR = 0.75f;
+
+ /**
+ * The default concurrency level for this table, used when not
+ * otherwise specified in a constructor.
+ */
+ static final int DEFAULT_CONCURRENCY_LEVEL = 16;
+
+ /**
+ * The maximum capacity, used if a higher value is implicitly
+ * specified by either of the constructors with arguments. MUST
+ * be a power of two <= 1<<30 to ensure that entries are indexable
+ * using ints.
+ */
+ static final int MAXIMUM_CAPACITY = 1 << 30;
+
+ /**
+ * The maximum number of segments to allow; used to bound
+ * constructor arguments.
+ */
+ static final int MAX_SEGMENTS = 1 << 16; // slightly conservative
+
+ /**
+ * Number of unsynchronized retries in size and containsValue
+ * methods before resorting to locking. This is used to avoid
+ * unbounded retries if tables undergo continuous modification
+ * which would make it impossible to obtain an accurate result.
+ */
+ static final int RETRIES_BEFORE_LOCK = 2;
+
+ /* ---------------- Fields -------------- */
+
+ /**
+ * Mask value for indexing into segments. The upper bits of a
+ * key's hash code are used to choose the segment.
+ */
+ final int segmentMask;
+
+ /**
+ * Shift value for indexing within segments.
+ */
+ final int segmentShift;
+
+ /**
+ * The segments, each of which is a specialized hash table
+ */
+ final Segment<K,V>[] segments;
+
+ boolean identityComparisons;
+
+ transient Set<K> keySet;
+ transient Set<Map.Entry<K,V>> entrySet;
+ transient Collection<V> values;
+
+ /* ---------------- Small Utilities -------------- */
+
+ /**
+ * Applies a supplemental hash function to a given hashCode, which
+ * defends against poor quality hash functions. This is critical
+ * because ConcurrentReferenceHashMap uses power-of-two length hash tables,
+ * that otherwise encounter collisions for hashCodes that do not
+ * differ in lower or upper bits.
+ */
+ private static int hash(int h) {
+ // Spread bits to regularize both segment and index locations,
+ // using variant of single-word Wang/Jenkins hash.
+ h += (h << 15) ^ 0xffffcd7d;
+ h ^= (h >>> 10);
+ h += (h << 3);
+ h ^= (h >>> 6);
+ h += (h << 2) + (h << 14);
+ return h ^ (h >>> 16);
+ }
+
+ /**
+ * Returns the segment that should be used for key with given hash
+ * @param hash the hash code for the key
+ * @return the segment
+ */
+ final Segment<K,V> segmentFor(int hash) {
+ return segments[(hash >>> segmentShift) & segmentMask];
+ }
+
+ private int hashOf(Object key) {
+ return hash(identityComparisons ?
+ System.identityHashCode(key) : key.hashCode());
+ }
+
+ /* ---------------- Inner Classes -------------- */
+
+ static interface KeyReference {
+ int keyHash();
+ Object keyRef();
+ }
+
+ /**
+ * A weak-key reference which stores the key hash needed for reclamation.
+ */
+ static final class WeakKeyReference<K> extends WeakReference<K> implements KeyReference {
+ final int hash;
+ WeakKeyReference(K key, int hash, ReferenceQueue<Object> refQueue) {
+ super(key, refQueue);
+ this.hash = hash;
+ }
+ public final int keyHash() {
+ return hash;
+ }
+
+ public final Object keyRef() {
+ return this;
+ }
+ }
+
+ /**
+ * A soft-key reference which stores the key hash needed for reclamation.
+ */
+ static final class SoftKeyReference<K> extends SoftReference<K> implements KeyReference {
+ final int hash;
+ SoftKeyReference(K key, int hash, ReferenceQueue<Object> refQueue) {
+ super(key, refQueue);
+ this.hash = hash;
+ }
+ public final int keyHash() {
+ return hash;
+ }
+
+ public final Object keyRef() {
+ return this;
+ }
+ }
+
+ static final class WeakValueReference<V> extends WeakReference<V> implements KeyReference {
+ final Object keyRef;
+ final int hash;
+ WeakValueReference(V value, Object keyRef, int hash, ReferenceQueue<Object> refQueue) {
+ super(value, refQueue);
+ this.keyRef = keyRef;
+ this.hash = hash;
+ }
+
+ public final int keyHash() {
+ return hash;
+ }
+
+ public final Object keyRef() {
+ return keyRef;
+ }
+ }
+
+ static final class SoftValueReference<V> extends SoftReference<V> implements KeyReference {
+ final Object keyRef;
+ final int hash;
+ SoftValueReference(V value, Object keyRef, int hash, ReferenceQueue<Object> refQueue) {
+ super(value, refQueue);
+ this.keyRef = keyRef;
+ this.hash = hash;
+ }
+ public final int keyHash() {
+ return hash;
+ }
+
+ public final Object keyRef() {
+ return keyRef;
+ }
+ }
+
+ /**
+ * ConcurrentReferenceHashMap list entry. Note that this is never exported
+ * out as a user-visible Map.Entry.
+ *
+ * Because the value field is volatile, not final, it is legal wrt
+ * the Java Memory Model for an unsynchronized reader to see null
+ * instead of initial value when read via a data race. Although a
+ * reordering leading to this is not likely to ever actually
+ * occur, the Segment.readValueUnderLock method is used as a
+ * backup in case a null (pre-initialized) value is ever seen in
+ * an unsynchronized access method.
+ */
+ static final class HashEntry<K,V> {
+ final Object keyRef;
+ final int hash;
+ volatile Object valueRef;
+ final HashEntry<K,V> next;
+
+ HashEntry(K key, int hash, HashEntry<K,V> next, V value,
+ ReferenceType keyType, ReferenceType valueType,
+ ReferenceQueue<Object> refQueue) {
+ this.hash = hash;
+ this.next = next;
+ this.keyRef = newKeyReference(key, keyType, refQueue);
+ this.valueRef = newValueReference(value, valueType, refQueue);
+ }
+
+ final Object newKeyReference(K key, ReferenceType keyType,
+ ReferenceQueue<Object> refQueue) {
+ if (keyType == ReferenceType.WEAK)
+ return new WeakKeyReference<K>(key, hash, refQueue);
+ if (keyType == ReferenceType.SOFT)
+ return new SoftKeyReference<K>(key, hash, refQueue);
+
+ return key;
+ }
+
+ final Object newValueReference(V value, ReferenceType valueType,
+ ReferenceQueue<Object> refQueue) {
+ if (valueType == ReferenceType.WEAK)
+ return new WeakValueReference<V>(value, keyRef, hash, refQueue);
+ if (valueType == ReferenceType.SOFT)
+ return new SoftValueReference<V>(value, keyRef, hash, refQueue);
+
+ return value;
+ }
+
+ @SuppressWarnings("unchecked")
+ final K key() {
+ if (keyRef instanceof KeyReference)
+ return ((Reference<K>)keyRef).get();
+
+ return (K) keyRef;
+ }
+
+ final V value() {
+ return dereferenceValue(valueRef);
+ }
+
+ @SuppressWarnings("unchecked")
+ final V dereferenceValue(Object value) {
+ if (value instanceof KeyReference)
+ return ((Reference<V>)value).get();
+
+ return (V) value;
+ }
+
+ final void setValue(V value, ReferenceType valueType, ReferenceQueue<Object> refQueue) {
+ this.valueRef = newValueReference(value, valueType, refQueue);
+ }
+
+ @SuppressWarnings("unchecked")
+ static final <K,V> HashEntry<K,V>[] newArray(int i) {
+ return new HashEntry[i];
+ }
+ }
+
+ /**
+ * Segments are specialized versions of hash tables. This
+ * subclasses from ReentrantLock opportunistically, just to
+ * simplify some locking and avoid separate construction.
+ */
+ static final class Segment<K,V> extends ReentrantLock implements Serializable {
+ /*
+ * Segments maintain a table of entry lists that are ALWAYS
+ * kept in a consistent state, so can be read without locking.
+ * Next fields of nodes are immutable (final). All list
+ * additions are performed at the front of each bin. This
+ * makes it easy to check changes, and also fast to traverse.
+ * When nodes would otherwise be changed, new nodes are
+ * created to replace them. This works well for hash tables
+ * since the bin lists tend to be short. (The average length
+ * is less than two for the default load factor threshold.)
+ *
+ * Read operations can thus proceed without locking, but rely
+ * on selected uses of volatiles to ensure that completed
+ * write operations performed by other threads are
+ * noticed. For most purposes, the "count" field, tracking the
+ * number of elements, serves as that volatile variable
+ * ensuring visibility. This is convenient because this field
+ * needs to be read in many read operations anyway:
+ *
+ * - All (unsynchronized) read operations must first read the
+ * "count" field, and should not look at table entries if
+ * it is 0.
+ *
+ * - All (synchronized) write operations should write to
+ * the "count" field after structurally changing any bin.
+ * The operations must not take any action that could even
+ * momentarily cause a concurrent read operation to see
+ * inconsistent data. This is made easier by the nature of
+ * the read operations in Map. For example, no operation
+ * can reveal that the table has grown but the threshold
+ * has not yet been updated, so there are no atomicity
+ * requirements for this with respect to reads.
+ *
+ * As a guide, all critical volatile reads and writes to the
+ * count field are marked in code comments.
+ */
+
+ private static final long serialVersionUID = 2249069246763182397L;
+
+ /**
+ * The number of elements in this segment's region.
+ */
+ transient volatile int count;
+
+ /**
+ * Number of updates that alter the size of the table. This is
+ * used during bulk-read methods to make sure they see a
+ * consistent snapshot: If modCounts change during a traversal
+ * of segments computing size or checking containsValue, then
+ * we might have an inconsistent view of state so (usually)
+ * must retry.
+ */
+ transient int modCount;
+
+ /**
+ * The table is rehashed when its size exceeds this threshold.
+ * (The value of this field is always <tt>(int)(capacity *
+ * loadFactor)</tt>.)
+ */
+ transient int threshold;
+
+ /**
+ * The per-segment table.
+ */
+ transient volatile HashEntry<K,V>[] table;
+
+ /**
+ * The load factor for the hash table. Even though this value
+ * is same for all segments, it is replicated to avoid needing
+ * links to outer object.
+ * @serial
+ */
+ final float loadFactor;
+
+ /**
+ * The collected weak-key reference queue for this segment.
+ * This should be (re)initialized whenever table is assigned,
+ */
+ transient volatile ReferenceQueue<Object> refQueue;
+
+ final ReferenceType keyType;
+
+ final ReferenceType valueType;
+
+ final boolean identityComparisons;
+
+ Segment(int initialCapacity, float lf, ReferenceType keyType,
+ ReferenceType valueType, boolean identityComparisons) {
+ loadFactor = lf;
+ this.keyType = keyType;
+ this.valueType = valueType;
+ this.identityComparisons = identityComparisons;
+ setTable(HashEntry.<K,V>newArray(initialCapacity));
+ }
+
+ @SuppressWarnings("unchecked")
+ static final <K,V> Segment<K,V>[] newArray(int i) {
+ return new Segment[i];
+ }
+
+ private boolean keyEq(Object src, Object dest) {
+ return identityComparisons ? src == dest : src.equals(dest);
+ }
+
+ /**
+ * Sets table to new HashEntry array.
+ * Call only while holding lock or in constructor.
+ */
+ void setTable(HashEntry<K,V>[] newTable) {
+ threshold = (int)(newTable.length * loadFactor);
+ table = newTable;
+ refQueue = new ReferenceQueue<Object>();
+ }
+
+ /**
+ * Returns properly casted first entry of bin for given hash.
+ */
+ HashEntry<K,V> getFirst(int hash) {
+ HashEntry<K,V>[] tab = table;
+ return tab[hash & (tab.length - 1)];
+ }
+
+ HashEntry<K,V> newHashEntry(K key, int hash, HashEntry<K, V> next, V value) {
+ return new HashEntry<K,V>(key, hash, next, value, keyType, valueType, refQueue);
+ }
+
+ /**
+ * Reads value field of an entry under lock. Called if value
+ * field ever appears to be null. This is possible only if a
+ * compiler happens to reorder a HashEntry initialization with
+ * its table assignment, which is legal under memory model
+ * but is not known to ever occur.
+ */
+ V readValueUnderLock(HashEntry<K,V> e) {
+ lock();
+ try {
+ removeStale();
+ return e.value();
+ } finally {
+ unlock();
+ }
+ }
+
+ /* Specialized implementations of map methods */
+
+ V get(Object key, int hash) {
+ if (count != 0) { // read-volatile
+ HashEntry<K,V> e = getFirst(hash);
+ while (e != null) {
+ if (e.hash == hash && keyEq(key, e.key())) {
+ Object opaque = e.valueRef;
+ if (opaque != null)
+ return e.dereferenceValue(opaque);
+
+ return readValueUnderLock(e); // recheck
+ }
+ e = e.next;
+ }
+ }
+ return null;
+ }
+
+ boolean containsKey(Object key, int hash) {
+ if (count != 0) { // read-volatile
+ HashEntry<K,V> e = getFirst(hash);
+ while (e != null) {
+ if (e.hash == hash && keyEq(key, e.key()))
+ return true;
+ e = e.next;
+ }
+ }
+ return false;
+ }
+
+ boolean containsValue(Object value) {
+ if (count != 0) { // read-volatile
+ HashEntry<K,V>[] tab = table;
+ int len = tab.length;
+ for (int i = 0 ; i < len; i++) {
+ for (HashEntry<K,V> e = tab[i]; e != null; e = e.next) {
+ Object opaque = e.valueRef;
+ V v;
+
+ if (opaque == null)
+ v = readValueUnderLock(e); // recheck
+ else
+ v = e.dereferenceValue(opaque);
+
+ if (value.equals(v))
+ return true;
+ }
+ }
+ }
+ return false;
+ }
+
+ boolean replace(K key, int hash, V oldValue, V newValue) {
+ lock();
+ try {
+ removeStale();
+ HashEntry<K,V> e = getFirst(hash);
+ while (e != null && (e.hash != hash || !keyEq(key, e.key())))
+ e = e.next;
+
+ boolean replaced = false;
+ if (e != null && oldValue.equals(e.value())) {
+ replaced = true;
+ e.setValue(newValue, valueType, refQueue);
+ }
+ return replaced;
+ } finally {
+ unlock();
+ }
+ }
+
+ V replace(K key, int hash, V newValue) {
+ lock();
+ try {
+ removeStale();
+ HashEntry<K,V> e = getFirst(hash);
+ while (e != null && (e.hash != hash || !keyEq(key, e.key())))
+ e = e.next;
+
+ V oldValue = null;
+ if (e != null) {
+ oldValue = e.value();
+ e.setValue(newValue, valueType, refQueue);
+ }
+ return oldValue;
+ } finally {
+ unlock();
+ }
+ }
+
+
+ V put(K key, int hash, V value, boolean onlyIfAbsent) {
+ lock();
+ try {
+ removeStale();
+ int c = count;
+ if (c++ > threshold) {// ensure capacity
+ int reduced = rehash();
+ if (reduced > 0) // adjust from possible weak cleanups
+ count = (c -= reduced) - 1; // write-volatile
+ }
+
+ HashEntry<K,V>[] tab = table;
+ int index = hash & (tab.length - 1);
+ HashEntry<K,V> first = tab[index];
+ HashEntry<K,V> e = first;
+ while (e != null && (e.hash != hash || !keyEq(key, e.key())))
+ e = e.next;
+
+ V oldValue;
+ if (e != null) {
+ oldValue = e.value();
+ if (!onlyIfAbsent)
+ e.setValue(value, valueType, refQueue);
+ }
+ else {
+ oldValue = null;
+ ++modCount;
+ tab[index] = newHashEntry(key, hash, first, value);
+ count = c; // write-volatile
+ }
+ return oldValue;
+ } finally {
+ unlock();
+ }
+ }
+
+ int rehash() {
+ HashEntry<K,V>[] oldTable = table;
+ int oldCapacity = oldTable.length;
+ if (oldCapacity >= MAXIMUM_CAPACITY)
+ return 0;
+
+ /*
+ * Reclassify nodes in each list to new Map. Because we are
+ * using power-of-two expansion, the elements from each bin
+ * must either stay at same index, or move with a power of two
+ * offset. We eliminate unnecessary node creation by catching
+ * cases where old nodes can be reused because their next
+ * fields won't change. Statistically, at the default
+ * threshold, only about one-sixth of them need cloning when
+ * a table doubles. The nodes they replace will be garbage
+ * collectable as soon as they are no longer referenced by any
+ * reader thread that may be in the midst of traversing table
+ * right now.
+ */
+
+ HashEntry<K,V>[] newTable = HashEntry.newArray(oldCapacity<<1);
+ threshold = (int)(newTable.length * loadFactor);
+ int sizeMask = newTable.length - 1;
+ int reduce = 0;
+ for (int i = 0; i < oldCapacity ; i++) {
+ // We need to guarantee that any existing reads of old Map can
+ // proceed. So we cannot yet null out each bin.
+ HashEntry<K,V> e = oldTable[i];
+
+ if (e != null) {
+ HashEntry<K,V> next = e.next;
+ int idx = e.hash & sizeMask;
+
+ // Single node on list
+ if (next == null)
+ newTable[idx] = e;
+
+ else {
+ // Reuse trailing consecutive sequence at same slot
+ HashEntry<K,V> lastRun = e;
+ int lastIdx = idx;
+ for (HashEntry<K,V> last = next;
+ last != null;
+ last = last.next) {
+ int k = last.hash & sizeMask;
+ if (k != lastIdx) {
+ lastIdx = k;
+ lastRun = last;
+ }
+ }
+ newTable[lastIdx] = lastRun;
+ // Clone all remaining nodes
+ for (HashEntry<K,V> p = e; p != lastRun; p = p.next) {
+ // Skip GC'd weak refs
+ K key = p.key();
+ if (key == null) {
+ reduce++;
+ continue;
+ }
+ int k = p.hash & sizeMask;
+ HashEntry<K,V> n = newTable[k];
+ newTable[k] = newHashEntry(key, p.hash, n, p.value());
+ }
+ }
+ }
+ }
+ table = newTable;
+ return reduce;
+ }
+
+ /**
+ * Remove; match on key only if value null, else match both.
+ */
+ V remove(Object key, int hash, Object value, boolean refRemove) {
+ lock();
+ try {
+ if (!refRemove)
+ removeStale();
+ int c = count - 1;
+ HashEntry<K,V>[] tab = table;
+ int index = hash & (tab.length - 1);
+ HashEntry<K,V> first = tab[index];
+ HashEntry<K,V> e = first;
+ // a ref remove operation compares the Reference instance
+ while (e != null && key != e.keyRef
+ && (refRemove || hash != e.hash || !keyEq(key, e.key())))
+ e = e.next;
+
+ V oldValue = null;
+ if (e != null) {
+ V v = e.value();
+ if (value == null || value.equals(v)) {
+ oldValue = v;
+ // All entries following removed node can stay
+ // in list, but all preceding ones need to be
+ // cloned.
+ ++modCount;
+ HashEntry<K,V> newFirst = e.next;
+ for (HashEntry<K,V> p = first; p != e; p = p.next) {
+ K pKey = p.key();
+ if (pKey == null) { // Skip GC'd keys
+ c--;
+ continue;
+ }
+
+ newFirst = newHashEntry(pKey, p.hash, newFirst, p.value());
+ }
+ tab[index] = newFirst;
+ count = c; // write-volatile
+ }
+ }
+ return oldValue;
+ } finally {
+ unlock();
+ }
+ }
+
+ final void removeStale() {
+ KeyReference ref;
+ while ((ref = (KeyReference) refQueue.poll()) != null) {
+ remove(ref.keyRef(), ref.keyHash(), null, true);
+ }
+ }
+
+ void clear() {
+ if (count != 0) {
+ lock();
+ try {
+ HashEntry<K,V>[] tab = table;
+ for (int i = 0; i < tab.length ; i++)
+ tab[i] = null;
+ ++modCount;
+ // replace the reference queue to avoid unnecessary stale cleanups
+ refQueue = new ReferenceQueue<Object>();
+ count = 0; // write-volatile
+ } finally {
+ unlock();
+ }
+ }
+ }
+ }
+
+
+
+ /* ---------------- Public operations -------------- */
+
+ /**
+ * Creates a new, empty map with the specified initial
+ * capacity, reference types, load factor and concurrency level.
+ *
+ * Behavioral changing options such as {@link Option#IDENTITY_COMPARISONS}
+ * can also be specified.
+ *
+ * @param initialCapacity the initial capacity. The implementation
+ * performs internal sizing to accommodate this many elements.
+ * @param loadFactor the load factor threshold, used to control resizing.
+ * Resizing may be performed when the average number of elements per
+ * bin exceeds this threshold.
+ * @param concurrencyLevel the estimated number of concurrently
+ * updating threads. The implementation performs internal sizing
+ * to try to accommodate this many threads.
+ * @param keyType the reference type to use for keys
+ * @param valueType the reference type to use for values
+ * @param options the behavioral options
+ * @throws IllegalArgumentException if the initial capacity is
+ * negative or the load factor or concurrencyLevel are
+ * nonpositive.
+ */
+ public ConcurrentReferenceHashMap(int initialCapacity,
+ float loadFactor, int concurrencyLevel,
+ ReferenceType keyType, ReferenceType valueType,
+ EnumSet<Option> options) {
+ if (!(loadFactor > 0) || initialCapacity < 0 || concurrencyLevel <= 0)
+ throw new IllegalArgumentException();
+
+ if (concurrencyLevel > MAX_SEGMENTS)
+ concurrencyLevel = MAX_SEGMENTS;
+
+ // Find power-of-two sizes best matching arguments
+ int sshift = 0;
+ int ssize = 1;
+ while (ssize < concurrencyLevel) {
+ ++sshift;
+ ssize <<= 1;
+ }
+ segmentShift = 32 - sshift;
+ segmentMask = ssize - 1;
+ this.segments = Segment.newArray(ssize);
+
+ if (initialCapacity > MAXIMUM_CAPACITY)
+ initialCapacity = MAXIMUM_CAPACITY;
+ int c = initialCapacity / ssize;
+ if (c * ssize < initialCapacity)
+ ++c;
+ int cap = 1;
+ while (cap < c)
+ cap <<= 1;
+
+ identityComparisons = options != null && options.contains(Option.IDENTITY_COMPARISONS);
+
+ for (int i = 0; i < this.segments.length; ++i)
+ this.segments[i] = new Segment<K,V>(cap, loadFactor,
+ keyType, valueType, identityComparisons);
+ }
+
+ /**
+ * Creates a new, empty map with the specified initial
+ * capacity, load factor and concurrency level.
+ *
+ * @param initialCapacity the initial capacity. The implementation
+ * performs internal sizing to accommodate this many elements.
+ * @param loadFactor the load factor threshold, used to control resizing.
+ * Resizing may be performed when the average number of elements per
+ * bin exceeds this threshold.
+ * @param concurrencyLevel the estimated number of concurrently
+ * updating threads. The implementation performs internal sizing
+ * to try to accommodate this many threads.
+ * @throws IllegalArgumentException if the initial capacity is
+ * negative or the load factor or concurrencyLevel are
+ * nonpositive.
+ */
+ public ConcurrentReferenceHashMap(int initialCapacity,
+ float loadFactor, int concurrencyLevel) {
+ this(initialCapacity, loadFactor, concurrencyLevel,
+ DEFAULT_KEY_TYPE, DEFAULT_VALUE_TYPE, null);
+ }
+
+ /**
+ * Creates a new, empty map with the specified initial capacity
+ * and load factor and with the default reference types (weak keys,
+ * strong values), and concurrencyLevel (16).
+ *
+ * @param initialCapacity The implementation performs internal
+ * sizing to accommodate this many elements.
+ * @param loadFactor the load factor threshold, used to control resizing.
+ * Resizing may be performed when the average number of elements per
+ * bin exceeds this threshold.
+ * @throws IllegalArgumentException if the initial capacity of
+ * elements is negative or the load factor is nonpositive
+ *
+ * @since 1.6
+ */
+ public ConcurrentReferenceHashMap(int initialCapacity, float loadFactor) {
+ this(initialCapacity, loadFactor, DEFAULT_CONCURRENCY_LEVEL);
+ }
+
+
+ /**
+ * Creates a new, empty map with the specified initial capacity,
+ * reference types and with default load factor (0.75) and concurrencyLevel (16).
+ *
+ * @param initialCapacity the initial capacity. The implementation
+ * performs internal sizing to accommodate this many elements.
+ * @param keyType the reference type to use for keys
+ * @param valueType the reference type to use for values
+ * @throws IllegalArgumentException if the initial capacity of
+ * elements is negative.
+ */
+ public ConcurrentReferenceHashMap(int initialCapacity,
+ ReferenceType keyType, ReferenceType valueType) {
+ this(initialCapacity, DEFAULT_LOAD_FACTOR, DEFAULT_CONCURRENCY_LEVEL,
+ keyType, valueType, null);
+ }
+
+ /**
+ * Creates a new, empty map with the specified initial capacity,
+ * and with default reference types (weak keys, strong values),
+ * load factor (0.75) and concurrencyLevel (16).
+ *
+ * @param initialCapacity the initial capacity. The implementation
+ * performs internal sizing to accommodate this many elements.
+ * @throws IllegalArgumentException if the initial capacity of
+ * elements is negative.
+ */
+ public ConcurrentReferenceHashMap(int initialCapacity) {
+ this(initialCapacity, DEFAULT_LOAD_FACTOR, DEFAULT_CONCURRENCY_LEVEL);
+ }
+
+ /**
+ * Creates a new, empty map with a default initial capacity (16),
+ * reference types (weak keys, strong values), default
+ * load factor (0.75) and concurrencyLevel (16).
+ */
+ public ConcurrentReferenceHashMap() {
+ this(DEFAULT_INITIAL_CAPACITY, DEFAULT_LOAD_FACTOR, DEFAULT_CONCURRENCY_LEVEL);
+ }
+
+ /**
+ * Creates a new map with the same mappings as the given map.
+ * The map is created with a capacity of 1.5 times the number
+ * of mappings in the given map or 16 (whichever is greater),
+ * and a default load factor (0.75) and concurrencyLevel (16).
+ *
+ * @param m the map
+ */
+ public ConcurrentReferenceHashMap(Map<? extends K, ? extends V> m) {
+ this(Math.max((int) (m.size() / DEFAULT_LOAD_FACTOR) + 1,
+ DEFAULT_INITIAL_CAPACITY),
+ DEFAULT_LOAD_FACTOR, DEFAULT_CONCURRENCY_LEVEL);
+ putAll(m);
+ }
+
+ /**
+ * Returns <tt>true</tt> if this map contains no key-value mappings.
+ *
+ * @return <tt>true</tt> if this map contains no key-value mappings
+ */
+ public boolean isEmpty() {
+ final Segment<K,V>[] segments = this.segments;
+ /*
+ * We keep track of per-segment modCounts to avoid ABA
+ * problems in which an element in one segment was added and
+ * in another removed during traversal, in which case the
+ * table was never actually empty at any point. Note the
+ * similar use of modCounts in the size() and containsValue()
+ * methods, which are the only other methods also susceptible
+ * to ABA problems.
+ */
+ int[] mc = new int[segments.length];
+ int mcsum = 0;
+ for (int i = 0; i < segments.length; ++i) {
+ if (segments[i].count != 0)
+ return false;
+ else
+ mcsum += mc[i] = segments[i].modCount;
+ }
+ // If mcsum happens to be zero, then we know we got a snapshot
+ // before any modifications at all were made. This is
+ // probably common enough to bother tracking.
+ if (mcsum != 0) {
+ for (int i = 0; i < segments.length; ++i) {
+ if (segments[i].count != 0 ||
+ mc[i] != segments[i].modCount)
+ return false;
+ }
+ }
+ return true;
+ }
+
+ /**
+ * Returns the number of key-value mappings in this map. If the
+ * map contains more than <tt>Integer.MAX_VALUE</tt> elements, returns
+ * <tt>Integer.MAX_VALUE</tt>.
+ *
+ * @return the number of key-value mappings in this map
+ */
+ public int size() {
+ final Segment<K,V>[] segments = this.segments;
+ long sum = 0;
+ long check = 0;
+ int[] mc = new int[segments.length];
+ // Try a few times to get accurate count. On failure due to
+ // continuous async changes in table, resort to locking.
+ for (int k = 0; k < RETRIES_BEFORE_LOCK; ++k) {
+ check = 0;
+ sum = 0;
+ int mcsum = 0;
+ for (int i = 0; i < segments.length; ++i) {
+ sum += segments[i].count;
+ mcsum += mc[i] = segments[i].modCount;
+ }
+ if (mcsum != 0) {
+ for (int i = 0; i < segments.length; ++i) {
+ check += segments[i].count;
+ if (mc[i] != segments[i].modCount) {
+ check = -1; // force retry
+ break;
+ }
+ }
+ }
+ if (check == sum)
+ break;
+ }
+ if (check != sum) { // Resort to locking all segments
+ sum = 0;
+ for (int i = 0; i < segments.length; ++i)
+ segments[i].lock();
+ for (int i = 0; i < segments.length; ++i)
+ sum += segments[i].count;
+ for (int i = 0; i < segments.length; ++i)
+ segments[i].unlock();
+ }
+ if (sum > Integer.MAX_VALUE)
+ return Integer.MAX_VALUE;
+ else
+ return (int)sum;
+ }
+
+ /**
+ * Returns the value to which the specified key is mapped,
+ * or {@code null} if this map contains no mapping for the key.
+ *
+ * <p>More formally, if this map contains a mapping from a key
+ * {@code k} to a value {@code v} such that {@code key.equals(k)},
+ * then this method returns {@code v}; otherwise it returns
+ * {@code null}. (There can be at most one such mapping.)
+ *
+ * @throws NullPointerException if the specified key is null
+ */
+ public V get(Object key) {
+ int hash = hashOf(key);
+ return segmentFor(hash).get(key, hash);
+ }
+
+ /**
+ * Tests if the specified object is a key in this table.
+ *
+ * @param key possible key
+ * @return <tt>true</tt> if and only if the specified object
+ * is a key in this table, as determined by the
+ * <tt>equals</tt> method; <tt>false</tt> otherwise.
+ * @throws NullPointerException if the specified key is null
+ */
+ public boolean containsKey(Object key) {
+ int hash = hashOf(key);
+ return segmentFor(hash).containsKey(key, hash);
+ }
+
+ /**
+ * Returns <tt>true</tt> if this map maps one or more keys to the
+ * specified value. Note: This method requires a full internal
+ * traversal of the hash table, and so is much slower than
+ * method <tt>containsKey</tt>.
+ *
+ * @param value value whose presence in this map is to be tested
+ * @return <tt>true</tt> if this map maps one or more keys to the
+ * specified value
+ * @throws NullPointerException if the specified value is null
+ */
+ public boolean containsValue(Object value) {
+ if (value == null)
+ throw new NullPointerException();
+
+ // See explanation of modCount use above
+
+ final Segment<K,V>[] segments = this.segments;
+ int[] mc = new int[segments.length];
+
+ // Try a few times without locking
+ for (int k = 0; k < RETRIES_BEFORE_LOCK; ++k) {
+ int sum = 0;
+ int mcsum = 0;
+ for (int i = 0; i < segments.length; ++i) {
+ int c = segments[i].count;
+ mcsum += mc[i] = segments[i].modCount;
+ if (segments[i].containsValue(value))
+ return true;
+ }
+ boolean cleanSweep = true;
+ if (mcsum != 0) {
+ for (int i = 0; i < segments.length; ++i) {
+ int c = segments[i].count;
+ if (mc[i] != segments[i].modCount) {
+ cleanSweep = false;
+ break;
+ }
+ }
+ }
+ if (cleanSweep)
+ return false;
+ }
+ // Resort to locking all segments
+ for (int i = 0; i < segments.length; ++i)
+ segments[i].lock();
+ boolean found = false;
+ try {
+ for (int i = 0; i < segments.length; ++i) {
+ if (segments[i].containsValue(value)) {
+ found = true;
+ break;
+ }
+ }
+ } finally {
+ for (int i = 0; i < segments.length; ++i)
+ segments[i].unlock();
+ }
+ return found;
+ }
+
+ /**
+ * Legacy method testing if some key maps into the specified value
+ * in this table. This method is identical in functionality to
+ * {@link #containsValue}, and exists solely to ensure
+ * full compatibility with class {@link java.util.Hashtable},
+ * which supported this method prior to introduction of the
+ * Java Collections framework.
+
+ * @param value a value to search for
+ * @return <tt>true</tt> if and only if some key maps to the
+ * <tt>value</tt> argument in this table as
+ * determined by the <tt>equals</tt> method;
+ * <tt>false</tt> otherwise
+ * @throws NullPointerException if the specified value is null
+ */
+ public boolean contains(Object value) {
+ return containsValue(value);
+ }
+
+ /**
+ * Maps the specified key to the specified value in this table.
+ * Neither the key nor the value can be null.
+ *
+ * <p> The value can be retrieved by calling the <tt>get</tt> method
+ * with a key that is equal to the original key.
+ *
+ * @param key key with which the specified value is to be associated
+ * @param value value to be associated with the specified key
+ * @return the previous value associated with <tt>key</tt>, or
+ * <tt>null</tt> if there was no mapping for <tt>key</tt>
+ * @throws NullPointerException if the specified key or value is null
+ */
+ public V put(K key, V value) {
+ if (value == null)
+ throw new NullPointerException();
+ int hash = hashOf(key);
+ return segmentFor(hash).put(key, hash, value, false);
+ }
+
+ /**
+ * {@inheritDoc}
+ *
+ * @return the previous value associated with the specified key,
+ * or <tt>null</tt> if there was no mapping for the key
+ * @throws NullPointerException if the specified key or value is null
+ */
+ public V putIfAbsent(K key, V value) {
+ if (value == null)
+ throw new NullPointerException();
+ int hash = hashOf(key);
+ return segmentFor(hash).put(key, hash, value, true);
+ }
+
+ /**
+ * Copies all of the mappings from the specified map to this one.
+ * These mappings replace any mappings that this map had for any of the
+ * keys currently in the specified map.
+ *
+ * @param m mappings to be stored in this map
+ */
+ public void putAll(Map<? extends K, ? extends V> m) {
+ for (Map.Entry<? extends K, ? extends V> e : m.entrySet())
+ put(e.getKey(), e.getValue());
+ }
+
+ /**
+ * Removes the key (and its corresponding value) from this map.
+ * This method does nothing if the key is not in the map.
+ *
+ * @param key the key that needs to be removed
+ * @return the previous value associated with <tt>key</tt>, or
+ * <tt>null</tt> if there was no mapping for <tt>key</tt>
+ * @throws NullPointerException if the specified key is null
+ */
+ public V remove(Object key) {
+ int hash = hashOf(key);
+ return segmentFor(hash).remove(key, hash, null, false);
+ }
+
+ /**
+ * {@inheritDoc}
+ *
+ * @throws NullPointerException if the specified key is null
+ */
+ public boolean remove(Object key, Object value) {
+ int hash = hashOf(key);
+ if (value == null)
+ return false;
+ return segmentFor(hash).remove(key, hash, value, false) != null;
+ }
+
+ /**
+ * {@inheritDoc}
+ *
+ * @throws NullPointerException if any of the arguments are null
+ */
+ public boolean replace(K key, V oldValue, V newValue) {
+ if (oldValue == null || newValue == null)
+ throw new NullPointerException();
+ int hash = hashOf(key);
+ return segmentFor(hash).replace(key, hash, oldValue, newValue);
+ }
+
+ /**
+ * {@inheritDoc}
+ *
+ * @return the previous value associated with the specified key,
+ * or <tt>null</tt> if there was no mapping for the key
+ * @throws NullPointerException if the specified key or value is null
+ */
+ public V replace(K key, V value) {
+ if (value == null)
+ throw new NullPointerException();
+ int hash = hashOf(key);
+ return segmentFor(hash).replace(key, hash, value);
+ }
+
+ /**
+ * Removes all of the mappings from this map.
+ */
+ public void clear() {
+ for (int i = 0; i < segments.length; ++i)
+ segments[i].clear();
+ }
+
+ /**
+ * Removes any stale entries whose keys have been finalized. Use of this
+ * method is normally not necessary since stale entries are automatically
+ * removed lazily, when blocking operations are required. However, there
+ * are some cases where this operation should be performed eagerly, such
+ * as cleaning up old references to a ClassLoader in a multi-classloader
+ * environment.
+ *
+ * Note: this method will acquire locks, one at a time, across all segments
+ * of this table, so if it is to be used, it should be used sparingly.
+ */
+ public void purgeStaleEntries() {
+ for (int i = 0; i < segments.length; ++i)
+ segments[i].removeStale();
+ }
+
+
+ /**
+ * Returns a {@link Set} view of the keys contained in this map.
+ * The set is backed by the map, so changes to the map are
+ * reflected in the set, and vice-versa. The set supports element
+ * removal, which removes the corresponding mapping from this map,
+ * via the <tt>Iterator.remove</tt>, <tt>Set.remove</tt>,
+ * <tt>removeAll</tt>, <tt>retainAll</tt>, and <tt>clear</tt>
+ * operations. It does not support the <tt>add</tt> or
+ * <tt>addAll</tt> operations.
+ *
+ * <p>The view's <tt>iterator</tt> is a "weakly consistent" iterator
+ * that will never throw {@link ConcurrentModificationException},
+ * and guarantees to traverse elements as they existed upon
+ * construction of the iterator, and may (but is not guaranteed to)
+ * reflect any modifications subsequent to construction.
+ */
+ public Set<K> keySet() {
+ Set<K> ks = keySet;
+ return (ks != null) ? ks : (keySet = new KeySet());
+ }
+
+ /**
+ * Returns a {@link Collection} view of the values contained in this map.
+ * The collection is backed by the map, so changes to the map are
+ * reflected in the collection, and vice-versa. The collection
+ * supports element removal, which removes the corresponding
+ * mapping from this map, via the <tt>Iterator.remove</tt>,
+ * <tt>Collection.remove</tt>, <tt>removeAll</tt>,
+ * <tt>retainAll</tt>, and <tt>clear</tt> operations. It does not
+ * support the <tt>add</tt> or <tt>addAll</tt> operations.
+ *
+ * <p>The view's <tt>iterator</tt> is a "weakly consistent" iterator
+ * that will never throw {@link ConcurrentModificationException},
+ * and guarantees to traverse elements as they existed upon
+ * construction of the iterator, and may (but is not guaranteed to)
+ * reflect any modifications subsequent to construction.
+ */
+ public Collection<V> values() {
+ Collection<V> vs = values;
+ return (vs != null) ? vs : (values = new Values());
+ }
+
+ /**
+ * Returns a {@link Set} view of the mappings contained in this map.
+ * The set is backed by the map, so changes to the map are
+ * reflected in the set, and vice-versa. The set supports element
+ * removal, which removes the corresponding mapping from the map,
+ * via the <tt>Iterator.remove</tt>, <tt>Set.remove</tt>,
+ * <tt>removeAll</tt>, <tt>retainAll</tt>, and <tt>clear</tt>
+ * operations. It does not support the <tt>add</tt> or
+ * <tt>addAll</tt> operations.
+ *
+ * <p>The view's <tt>iterator</tt> is a "weakly consistent" iterator
+ * that will never throw {@link ConcurrentModificationException},
+ * and guarantees to traverse elements as they existed upon
+ * construction of the iterator, and may (but is not guaranteed to)
+ * reflect any modifications subsequent to construction.
+ */
+ public Set<Map.Entry<K,V>> entrySet() {
+ Set<Map.Entry<K,V>> es = entrySet;
+ return (es != null) ? es : (entrySet = new EntrySet());
+ }
+
+ /**
+ * Returns an enumeration of the keys in this table.
+ *
+ * @return an enumeration of the keys in this table
+ * @see #keySet()
+ */
+ public Enumeration<K> keys() {
+ return new KeyIterator();
+ }
+
+ /**
+ * Returns an enumeration of the values in this table.
+ *
+ * @return an enumeration of the values in this table
+ * @see #values()
+ */
+ public Enumeration<V> elements() {
+ return new ValueIterator();
+ }
+
+ /* ---------------- Iterator Support -------------- */
+
+ abstract class HashIterator {
+ int nextSegmentIndex;
+ int nextTableIndex;
+ HashEntry<K,V>[] currentTable;
+ HashEntry<K, V> nextEntry;
+ HashEntry<K, V> lastReturned;
+ K currentKey; // Strong reference to weak key (prevents gc)
+
+ HashIterator() {
+ nextSegmentIndex = segments.length - 1;
+ nextTableIndex = -1;
+ advance();
+ }
+
+ public boolean hasMoreElements() { return hasNext(); }
+
+ final void advance() {
+ if (nextEntry != null && (nextEntry = nextEntry.next) != null)
+ return;
+
+ while (nextTableIndex >= 0) {
+ if ( (nextEntry = currentTable[nextTableIndex--]) != null)
+ return;
+ }
+
+ while (nextSegmentIndex >= 0) {
+ Segment<K,V> seg = segments[nextSegmentIndex--];
+ if (seg.count != 0) {
+ currentTable = seg.table;
+ for (int j = currentTable.length - 1; j >= 0; --j) {
+ if ( (nextEntry = currentTable[j]) != null) {
+ nextTableIndex = j - 1;
+ return;
+ }
+ }
+ }
+ }
+ }
+
+ public boolean hasNext() {
+ while (nextEntry != null) {
+ if (nextEntry.key() != null)
+ return true;
+ advance();
+ }
+
+ return false;
+ }
+
+ HashEntry<K,V> nextEntry() {
+ do {
+ if (nextEntry == null)
+ throw new NoSuchElementException();
+
+ lastReturned = nextEntry;
+ currentKey = lastReturned.key();
+ advance();
+ } while (currentKey == null); // Skip GC'd keys
+
+ return lastReturned;
+ }
+
+ public void remove() {
+ if (lastReturned == null)
+ throw new IllegalStateException();
+ ConcurrentReferenceHashMap.this.remove(currentKey);
+ lastReturned = null;
+ }
+ }
+
+ final class KeyIterator
+ extends HashIterator
+ implements Iterator<K>, Enumeration<K>
+ {
+ public K next() { return super.nextEntry().key(); }
+ public K nextElement() { return super.nextEntry().key(); }
+ }
+
+ final class ValueIterator
+ extends HashIterator
+ implements Iterator<V>, Enumeration<V>
+ {
+ public V next() { return super.nextEntry().value(); }
+ public V nextElement() { return super.nextEntry().value(); }
+ }
+
+ /*
+ * This class is needed for JDK5 compatibility.
+ */
+ static class SimpleEntry<K, V> implements Entry<K, V>,
+ java.io.Serializable {
+ private static final long serialVersionUID = -8499721149061103585L;
+
+ private final K key;
+ private V value;
+
+ public SimpleEntry(K key, V value) {
+ this.key = key;
+ this.value = value;
+ }
+
+ public SimpleEntry(Entry<? extends K, ? extends V> entry) {
+ this.key = entry.getKey();
+ this.value = entry.getValue();
+ }
+
+ public K getKey() {
+ return key;
+ }
+
+ public V getValue() {
+ return value;
+ }
+
+ public V setValue(V value) {
+ V oldValue = this.value;
+ this.value = value;
+ return oldValue;
+ }
+
+ public boolean equals(Object o) {
+ if (!(o instanceof Map.Entry))
+ return false;
+ @SuppressWarnings("unchecked")
+ Map.Entry e = (Map.Entry) o;
+ return eq(key, e.getKey()) && eq(value, e.getValue());
+ }
+
+ public int hashCode() {
+ return (key == null ? 0 : key.hashCode())
+ ^ (value == null ? 0 : value.hashCode());
+ }
+
+ public String toString() {
+ return key + "=" + value;
+ }
+
+ private static boolean eq(Object o1, Object o2) {
+ return o1 == null ? o2 == null : o1.equals(o2);
+ }
+ }
+
+
+ /**
+ * Custom Entry class used by EntryIterator.next(), that relays setValue
+ * changes to the underlying map.
+ */
+ final class WriteThroughEntry extends SimpleEntry<K,V>
+ {
+ private static final long serialVersionUID = -7900634345345313646L;
+
+ WriteThroughEntry(K k, V v) {
+ super(k,v);
+ }
+
+ /**
+ * Set our entry's value and write through to the map. The
+ * value to return is somewhat arbitrary here. Since a
+ * WriteThroughEntry does not necessarily track asynchronous
+ * changes, the most recent "previous" value could be
+ * different from what we return (or could even have been
+ * removed in which case the put will re-establish). We do not
+ * and cannot guarantee more.
+ */
+ public V setValue(V value) {
+ if (value == null) throw new NullPointerException();
+ V v = super.setValue(value);
+ ConcurrentReferenceHashMap.this.put(getKey(), value);
+ return v;
+ }
+ }
+
+ final class EntryIterator
+ extends HashIterator
+ implements Iterator<Entry<K,V>>
+ {
+ public Map.Entry<K,V> next() {
+ HashEntry<K,V> e = super.nextEntry();
+ return new WriteThroughEntry(e.key(), e.value());
+ }
+ }
+
+ final class KeySet extends AbstractSet<K> {
+ public Iterator<K> iterator() {
+ return new KeyIterator();
+ }
+ public int size() {
+ return ConcurrentReferenceHashMap.this.size();
+ }
+ public boolean isEmpty() {
+ return ConcurrentReferenceHashMap.this.isEmpty();
+ }
+ public boolean contains(Object o) {
+ return ConcurrentReferenceHashMap.this.containsKey(o);
+ }
+ public boolean remove(Object o) {
+ return ConcurrentReferenceHashMap.this.remove(o) != null;
+ }
+ public void clear() {
+ ConcurrentReferenceHashMap.this.clear();
+ }
+ }
+
+ final class Values extends AbstractCollection<V> {
+ public Iterator<V> iterator() {
+ return new ValueIterator();
+ }
+ public int size() {
+ return ConcurrentReferenceHashMap.this.size();
+ }
+ public boolean isEmpty() {
+ return ConcurrentReferenceHashMap.this.isEmpty();
+ }
+ public boolean contains(Object o) {
+ return ConcurrentReferenceHashMap.this.containsValue(o);
+ }
+ public void clear() {
+ ConcurrentReferenceHashMap.this.clear();
+ }
+ }
+
+ final class EntrySet extends AbstractSet<Map.Entry<K,V>> {
+ public Iterator<Map.Entry<K,V>> iterator() {
+ return new EntryIterator();
+ }
+ public boolean contains(Object o) {
+ if (!(o instanceof Map.Entry))
+ return false;
+ Map.Entry<?,?> e = (Map.Entry<?,?>)o;
+ V v = ConcurrentReferenceHashMap.this.get(e.getKey());
+ return v != null && v.equals(e.getValue());
+ }
+ public boolean remove(Object o) {
+ if (!(o instanceof Map.Entry))
+ return false;
+ Map.Entry<?,?> e = (Map.Entry<?,?>)o;
+ return ConcurrentReferenceHashMap.this.remove(e.getKey(), e.getValue());
+ }
+ public int size() {
+ return ConcurrentReferenceHashMap.this.size();
+ }
+ public boolean isEmpty() {
+ return ConcurrentReferenceHashMap.this.isEmpty();
+ }
+ public void clear() {
+ ConcurrentReferenceHashMap.this.clear();
+ }
+ }
+
+ /* ---------------- Serialization Support -------------- */
+
+ /**
+ * Save the state of the <tt>ConcurrentReferenceHashMap</tt> instance to a
+ * stream (i.e., serialize it).
+ * @param s the stream
+ * @serialData
+ * the key (Object) and value (Object)
+ * for each key-value mapping, followed by a null pair.
+ * The key-value mappings are emitted in no particular order.
+ */
+ private void writeObject(java.io.ObjectOutputStream s) throws IOException {
+ s.defaultWriteObject();
+
+ for (int k = 0; k < segments.length; ++k) {
+ Segment<K,V> seg = segments[k];
+ seg.lock();
+ try {
+ HashEntry<K,V>[] tab = seg.table;
+ for (int i = 0; i < tab.length; ++i) {
+ for (HashEntry<K,V> e = tab[i]; e != null; e = e.next) {
+ K key = e.key();
+ if (key == null) // Skip GC'd keys
+ continue;
+
+ s.writeObject(key);
+ s.writeObject(e.value());
+ }
+ }
+ } finally {
+ seg.unlock();
+ }
+ }
+ s.writeObject(null);
+ s.writeObject(null);
+ }
+
+ /**
+ * Reconstitute the <tt>ConcurrentReferenceHashMap</tt> instance from a
+ * stream (i.e., deserialize it).
+ * @param s the stream
+ */
+ @SuppressWarnings("unchecked")
+ private void readObject(java.io.ObjectInputStream s)
+ throws IOException, ClassNotFoundException {
+ s.defaultReadObject();
+
+ // Initialize each segment to be minimally sized, and let grow.
+ for (int i = 0; i < segments.length; ++i) {
+ segments[i].setTable(new HashEntry[1]);
+ }
+
+ // Read the keys and values, and put the mappings in the table
+ for (;;) {
+ K key = (K) s.readObject();
+ V value = (V) s.readObject();
+ if (key == null)
+ break;
+ put(key, value);
+ }
+ }
+}
Added: core/trunk/envers/src/main/java/org/jboss/envers/tools/HibernateVersion.java
===================================================================
--- core/trunk/envers/src/main/java/org/jboss/envers/tools/HibernateVersion.java (rev 0)
+++ core/trunk/envers/src/main/java/org/jboss/envers/tools/HibernateVersion.java 2008-10-27 18:56:31 UTC (rev 15406)
@@ -0,0 +1,46 @@
+/*
+ * Envers. http://www.jboss.org/envers
+ *
+ * Copyright 2008 Red Hat Middleware, LLC. All rights reserved.
+ *
+ * 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, v. 2.1.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT A 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, v.2.1 along with this distribution; if not, write to the Free
+ * Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+ * 02110-1301, USA.
+ *
+ * Red Hat Author(s): Adam Warski
+ */
+package org.jboss.envers.tools;
+
+import org.hibernate.cfg.Environment;
+import org.hibernate.MappingException;
+
+/**
+ * @author Adam Warski (adam at warski dot org)
+ */
+public class HibernateVersion {
+ private static String version;
+
+ public static String get() {
+ if (version == null) {
+ try {
+ version = (String) Environment.class.getField("VERSION").get(null);
+ } catch (IllegalAccessException e) {
+ throw new MappingException(e);
+ } catch (NoSuchFieldException e) {
+ throw new MappingException(e);
+ }
+ }
+
+ return version;
+ }
+}
Added: core/trunk/envers/src/main/java/org/jboss/envers/tools/MutableBoolean.java
===================================================================
--- core/trunk/envers/src/main/java/org/jboss/envers/tools/MutableBoolean.java (rev 0)
+++ core/trunk/envers/src/main/java/org/jboss/envers/tools/MutableBoolean.java 2008-10-27 18:56:31 UTC (rev 15406)
@@ -0,0 +1,48 @@
+/*
+ * Envers. http://www.jboss.org/envers
+ *
+ * Copyright 2008 Red Hat Middleware, LLC. All rights reserved.
+ *
+ * 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, v. 2.1.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT A 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, v.2.1 along with this distribution; if not, write to the Free
+ * Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+ * 02110-1301, USA.
+ *
+ * Red Hat Author(s): Adam Warski
+ */
+package org.jboss.envers.tools;
+
+/**
+ * @author Adam Warski (adam at warski dot org)
+ */
+public class MutableBoolean {
+ private boolean value;
+
+ public MutableBoolean() {
+ }
+
+ public MutableBoolean(boolean value) {
+ this.value = value;
+ }
+
+ public boolean isSet() {
+ return value;
+ }
+
+ public void set() {
+ value = true;
+ }
+
+ public void unset() {
+ value = false;
+ }
+}
Added: core/trunk/envers/src/main/java/org/jboss/envers/tools/MutableInteger.java
===================================================================
--- core/trunk/envers/src/main/java/org/jboss/envers/tools/MutableInteger.java (rev 0)
+++ core/trunk/envers/src/main/java/org/jboss/envers/tools/MutableInteger.java 2008-10-27 18:56:31 UTC (rev 15406)
@@ -0,0 +1,36 @@
+/*
+ * Envers. http://www.jboss.org/envers
+ *
+ * Copyright 2008 Red Hat Middleware, LLC. All rights reserved.
+ *
+ * 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, v. 2.1.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT A 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, v.2.1 along with this distribution; if not, write to the Free
+ * Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+ * 02110-1301, USA.
+ *
+ * Red Hat Author(s): Adam Warski
+ */
+package org.jboss.envers.tools;
+
+/**
+ * @author Adam Warski (adam at warski dot org)
+ */
+public class MutableInteger {
+ private int value;
+
+ public MutableInteger() {
+ }
+
+ public int getAndIncrease() {
+ return value++;
+ }
+}
\ No newline at end of file
Added: core/trunk/envers/src/main/java/org/jboss/envers/tools/Pair.java
===================================================================
--- core/trunk/envers/src/main/java/org/jboss/envers/tools/Pair.java (rev 0)
+++ core/trunk/envers/src/main/java/org/jboss/envers/tools/Pair.java 2008-10-27 18:56:31 UTC (rev 15406)
@@ -0,0 +1,69 @@
+/*
+ * Envers. http://www.jboss.org/envers
+ *
+ * Copyright 2008 Red Hat Middleware, LLC. All rights reserved.
+ *
+ * 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, v. 2.1.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT A 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, v.2.1 along with this distribution; if not, write to the Free
+ * Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+ * 02110-1301, USA.
+ *
+ * Red Hat Author(s): Adam Warski
+ */
+package org.jboss.envers.tools;
+
+/**
+ * A pair of objects.
+ * @param <T1>
+ * @param <T2>
+ * @author Adam Warski (adamw at aster.pl)
+ */
+public class Pair<T1, T2> {
+ private T1 obj1;
+ private T2 obj2;
+
+ public Pair(T1 obj1, T2 obj2) {
+ this.obj1 = obj1;
+ this.obj2 = obj2;
+ }
+
+ public T1 getFirst() {
+ return obj1;
+ }
+
+ public T2 getSecond() {
+ return obj2;
+ }
+
+ public boolean equals(Object o) {
+ if (this == o) return true;
+ if (!(o instanceof Pair)) return false;
+
+ Pair pair = (Pair) o;
+
+ if (obj1 != null ? !obj1.equals(pair.obj1) : pair.obj1 != null) return false;
+ if (obj2 != null ? !obj2.equals(pair.obj2) : pair.obj2 != null) return false;
+
+ return true;
+ }
+
+ public int hashCode() {
+ int result;
+ result = (obj1 != null ? obj1.hashCode() : 0);
+ result = 31 * result + (obj2 != null ? obj2.hashCode() : 0);
+ return result;
+ }
+
+ public static <T1, T2> Pair<T1, T2> make(T1 obj1, T2 obj2) {
+ return new Pair<T1, T2>(obj1, obj2);
+ }
+}
Added: core/trunk/envers/src/main/java/org/jboss/envers/tools/StringTools.java
===================================================================
--- core/trunk/envers/src/main/java/org/jboss/envers/tools/StringTools.java (rev 0)
+++ core/trunk/envers/src/main/java/org/jboss/envers/tools/StringTools.java 2008-10-27 18:56:31 UTC (rev 15406)
@@ -0,0 +1,72 @@
+/*
+ * Envers. http://www.jboss.org/envers
+ *
+ * Copyright 2008 Red Hat Middleware, LLC. All rights reserved.
+ *
+ * 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, v. 2.1.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT A 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, v.2.1 along with this distribution; if not, write to the Free
+ * Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+ * 02110-1301, USA.
+ *
+ * Red Hat Author(s): Adam Warski
+ */
+package org.jboss.envers.tools;
+
+import java.util.Iterator;
+
+/**
+ * @author Adam Warski (adam at warski dot org)
+ */
+public class StringTools {
+ public static boolean isEmpty(String s) {
+ return s == null || "".equals(s);
+ }
+
+ /**
+ * @param s String, from which to get the last component.
+ * @return The last component of the dot-separated string <code>s</code>. For example, for a string
+ * "a.b.c", the result is "c".
+ */
+ public static String getLastComponent(String s) {
+ if (s == null) {
+ return null;
+ }
+
+ int lastDot = s.lastIndexOf(".");
+ if (lastDot == -1) {
+ return s;
+ } else {
+ return s.substring(lastDot + 1);
+ }
+ }
+
+ /**
+ * To the given string builder, appends all strings in the given iterator, separating them with the given
+ * separator. For example, for an interator "a" "b" "c" and separator ":" the output is "a:b:c".
+ * @param sb String builder, to which to append.
+ * @param contents Strings to be appended.
+ * @param separator Separator between subsequent content.
+ */
+ public static void append(StringBuilder sb, Iterator<String> contents, String separator) {
+ boolean isFirst = true;
+
+ while (contents.hasNext()) {
+ if (!isFirst) {
+ sb.append(separator);
+ }
+
+ sb.append(contents.next());
+
+ isFirst = false;
+ }
+ }
+}
Added: core/trunk/envers/src/main/java/org/jboss/envers/tools/Tools.java
===================================================================
--- core/trunk/envers/src/main/java/org/jboss/envers/tools/Tools.java (rev 0)
+++ core/trunk/envers/src/main/java/org/jboss/envers/tools/Tools.java 2008-10-27 18:56:31 UTC (rev 15406)
@@ -0,0 +1,79 @@
+/*
+ * Envers. http://www.jboss.org/envers
+ *
+ * Copyright 2008 Red Hat Middleware, LLC. All rights reserved.
+ *
+ * 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, v. 2.1.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT A 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, v.2.1 along with this distribution; if not, write to the Free
+ * Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+ * 02110-1301, USA.
+ *
+ * Red Hat Author(s): Adam Warski
+ */
+package org.jboss.envers.tools;
+
+import java.util.*;
+
+/**
+ * @author Adam Warski (adam at warski dot org)
+ */
+public class Tools {
+ public static <K,V> Map<K,V> newHashMap() {
+ return new HashMap<K,V>();
+ }
+
+ public static boolean objectsEqual(Object obj1, Object obj2) {
+ if (obj1 == null) {
+ return obj2 == null;
+ }
+
+ return obj1.equals(obj2);
+ }
+
+ public static <T> List<T> iteratorToList(Iterator<T> iter) {
+ List<T> ret = new ArrayList<T>();
+ while (iter.hasNext()) {
+ ret.add(iter.next());
+ }
+
+ return ret;
+ }
+
+ public static boolean iteratorsContentEqual(Iterator iter1, Iterator iter2) {
+ while (iter1.hasNext() && iter2.hasNext()) {
+ if (!iter1.next().equals(iter2.next())) {
+ return false;
+ }
+ }
+
+ if (iter1.hasNext() || iter2.hasNext()) {
+ return false;
+ }
+
+ return true;
+ }
+
+ /**
+ * Transforms a list of arbitrary elements to a list of index-element pairs.
+ * @param list List to transform.
+ * @return A list of pairs: ((0, element_at_index_0), (1, element_at_index_1), ...)
+ */
+ public static <T> List<Pair<Integer, T>> listToIndexElementPairList(List<T> list) {
+ List<Pair<Integer, T>> ret = new ArrayList<Pair<Integer, T>>();
+ Iterator<T> listIter = list.iterator();
+ for (int i=0; i<list.size(); i++) {
+ ret.add(Pair.make(i, listIter.next()));
+ }
+
+ return ret;
+ }
+}
Added: core/trunk/envers/src/main/java/org/jboss/envers/tools/Triple.java
===================================================================
--- core/trunk/envers/src/main/java/org/jboss/envers/tools/Triple.java (rev 0)
+++ core/trunk/envers/src/main/java/org/jboss/envers/tools/Triple.java 2008-10-27 18:56:31 UTC (rev 15406)
@@ -0,0 +1,78 @@
+/*
+ * Envers. http://www.jboss.org/envers
+ *
+ * Copyright 2008 Red Hat Middleware, LLC. All rights reserved.
+ *
+ * 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, v. 2.1.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT A 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, v.2.1 along with this distribution; if not, write to the Free
+ * Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+ * 02110-1301, USA.
+ *
+ * Red Hat Author(s): Adam Warski
+ */
+package org.jboss.envers.tools;
+
+/**
+ * A triple of objects.
+ * @param <T1>
+ * @param <T2>
+ * @param <T3>
+ * @author Adam Warski (adamw at aster.pl)
+ */
+public class Triple<T1, T2, T3> {
+ private T1 obj1;
+ private T2 obj2;
+ private T3 obj3;
+
+ public Triple(T1 obj1, T2 obj2, T3 obj3) {
+ this.obj1 = obj1;
+ this.obj2 = obj2;
+ this.obj3 = obj3;
+ }
+
+ public T1 getFirst() {
+ return obj1;
+ }
+
+ public T2 getSecond() {
+ return obj2;
+ }
+
+ public T3 getThird() {
+ return obj3;
+ }
+
+ public boolean equals(Object o) {
+ if (this == o) return true;
+ if (!(o instanceof Triple)) return false;
+
+ Triple triple = (Triple) o;
+
+ if (obj1 != null ? !obj1.equals(triple.obj1) : triple.obj1 != null) return false;
+ if (obj2 != null ? !obj2.equals(triple.obj2) : triple.obj2 != null) return false;
+ if (obj3 != null ? !obj3.equals(triple.obj3) : triple.obj3 != null) return false;
+
+ return true;
+ }
+
+ public int hashCode() {
+ int result;
+ result = (obj1 != null ? obj1.hashCode() : 0);
+ result = 31 * result + (obj2 != null ? obj2.hashCode() : 0);
+ result = 31 * result + (obj3 != null ? obj3.hashCode() : 0);
+ return result;
+ }
+
+ public static <T1, T2, T3> Triple<T1, T2, T3> make(T1 obj1, T2 obj2, T3 obj3) {
+ return new Triple<T1, T2, T3>(obj1, obj2, obj3);
+ }
+}
\ No newline at end of file
Added: core/trunk/envers/src/main/java/org/jboss/envers/tools/graph/GraphDefiner.java
===================================================================
--- core/trunk/envers/src/main/java/org/jboss/envers/tools/graph/GraphDefiner.java (rev 0)
+++ core/trunk/envers/src/main/java/org/jboss/envers/tools/graph/GraphDefiner.java 2008-10-27 18:56:31 UTC (rev 15406)
@@ -0,0 +1,36 @@
+/*
+ * Envers. http://www.jboss.org/envers
+ *
+ * Copyright 2008 Red Hat Middleware, LLC. All rights reserved.
+ *
+ * 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, v. 2.1.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT A 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, v.2.1 along with this distribution; if not, write to the Free
+ * Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+ * 02110-1301, USA.
+ *
+ * Red Hat Author(s): Adam Warski
+ */
+package org.jboss.envers.tools.graph;
+
+import java.util.List;
+
+/**
+ * Defines a graph, where each vertex has a representation, which identifies uniquely a value.
+ * Representations are comparable, values - not.
+ * @author Adam Warski (adam at warski dot org)
+ */
+public interface GraphDefiner<V, R> {
+ R getRepresentation(V v);
+ V getValue(R r);
+ List<V> getNeighbours(V v);
+ List<V> getValues();
+}
Added: core/trunk/envers/src/main/java/org/jboss/envers/tools/graph/GraphTopologicalSort.java
===================================================================
--- core/trunk/envers/src/main/java/org/jboss/envers/tools/graph/GraphTopologicalSort.java (rev 0)
+++ core/trunk/envers/src/main/java/org/jboss/envers/tools/graph/GraphTopologicalSort.java 2008-10-27 18:56:31 UTC (rev 15406)
@@ -0,0 +1,66 @@
+/*
+ * Envers. http://www.jboss.org/envers
+ *
+ * Copyright 2008 Red Hat Middleware, LLC. All rights reserved.
+ *
+ * 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, v. 2.1.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT A 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, v.2.1 along with this distribution; if not, write to the Free
+ * Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+ * 02110-1301, USA.
+ *
+ * Red Hat Author(s): Adam Warski
+ */
+package org.jboss.envers.tools.graph;
+
+import java.util.List;
+import java.util.Map;
+import java.util.HashMap;
+import java.util.ArrayList;
+
+/**
+ * @author Adam Warski (adam at warski dot org)
+ */
+public class GraphTopologicalSort {
+ /**
+ * Sorts a graph topologically.
+ * @param definer Defines a graph (values and representations) to sort.
+ * @return Values of the graph, sorted topologically.
+ */
+ public static <V, R> List<V> sort(GraphDefiner<V, R> definer) {
+ List<V> values = definer.getValues();
+ Map<R, Vertex<R>> vertices = new HashMap<R, Vertex<R>>();
+
+ // Creating a vertex for each representation
+ for (V v : values) {
+ R rep = definer.getRepresentation(v);
+ vertices.put(rep, new Vertex<R>(rep));
+ }
+
+ // Connecting neighbourhooding vertices
+ for (V v : values) {
+ for (V vn : definer.getNeighbours(v)) {
+ vertices.get(definer.getRepresentation(v)).addNeighbour(vertices.get(definer.getRepresentation(vn)));
+ }
+ }
+
+ // Sorting the representations
+ List<R> sortedReps = new TopologicalSort<R>().sort(vertices.values());
+
+ // Transforming the sorted representations to sorted values
+ List<V> sortedValues = new ArrayList<V>(sortedReps.size());
+ for (R rep : sortedReps) {
+ sortedValues.add(definer.getValue(rep));
+ }
+
+ return sortedValues;
+ }
+}
Added: core/trunk/envers/src/main/java/org/jboss/envers/tools/graph/TopologicalSort.java
===================================================================
--- core/trunk/envers/src/main/java/org/jboss/envers/tools/graph/TopologicalSort.java (rev 0)
+++ core/trunk/envers/src/main/java/org/jboss/envers/tools/graph/TopologicalSort.java 2008-10-27 18:56:31 UTC (rev 15406)
@@ -0,0 +1,66 @@
+/*
+ * Envers. http://www.jboss.org/envers
+ *
+ * Copyright 2008 Red Hat Middleware, LLC. All rights reserved.
+ *
+ * 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, v. 2.1.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT A 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, v.2.1 along with this distribution; if not, write to the Free
+ * Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+ * 02110-1301, USA.
+ *
+ * Red Hat Author(s): Adam Warski
+ */
+package org.jboss.envers.tools.graph;
+
+import java.util.*;
+
+/**
+ * Topological sorting of a graph - based on DFS.
+ * @author Adam Warski (adam at warski dot org)
+ */
+public class TopologicalSort<R> {
+ private List<R> sorted;
+ private int time;
+
+ private void process(Vertex<R> v) {
+ if (v.getStartTime() != 0) {
+ // alread processed
+ return;
+ }
+
+ v.setStartTime(time++);
+
+ for (Vertex<R> n : v.getNeighbours()) {
+ process(n);
+ }
+
+ v.setEndTime(time++);
+
+ sorted.add(v.getRepresentation());
+ }
+
+ public List<R> sort(Collection<Vertex<R>> vertices) {
+ sorted = new ArrayList<R>(vertices.size());
+
+ time = 1;
+
+ for (Vertex<R> v : vertices) {
+ if (v.getEndTime() == 0) {
+ process(v);
+ }
+ }
+
+ Collections.reverse(sorted);
+
+ return sorted;
+ }
+}
Added: core/trunk/envers/src/main/java/org/jboss/envers/tools/graph/Vertex.java
===================================================================
--- core/trunk/envers/src/main/java/org/jboss/envers/tools/graph/Vertex.java (rev 0)
+++ core/trunk/envers/src/main/java/org/jboss/envers/tools/graph/Vertex.java 2008-10-27 18:56:31 UTC (rev 15406)
@@ -0,0 +1,72 @@
+/*
+ * Envers. http://www.jboss.org/envers
+ *
+ * Copyright 2008 Red Hat Middleware, LLC. All rights reserved.
+ *
+ * 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, v. 2.1.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT A 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, v.2.1 along with this distribution; if not, write to the Free
+ * Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+ * 02110-1301, USA.
+ *
+ * Red Hat Author(s): Adam Warski
+ */
+package org.jboss.envers.tools.graph;
+
+import java.util.List;
+import java.util.ArrayList;
+
+/**
+ * A graph vertex - stores its representation, neighbours, start and end time in (D|B)FS.
+ * @author Adam Warski (adam at warski dot org)
+ */
+public class Vertex<R> {
+ private final R representation;
+ private final List<Vertex<R>> neighbours;
+
+ private int startTime;
+ private int endTime;
+
+ public Vertex(R representation) {
+ this.representation = representation;
+ this.neighbours = new ArrayList<Vertex<R>>();
+ this.startTime = 0;
+ this.endTime = 0;
+ }
+
+ public R getRepresentation() {
+ return representation;
+ }
+
+ public List<Vertex<R>> getNeighbours() {
+ return neighbours;
+ }
+
+ public void addNeighbour(Vertex<R> n) {
+ neighbours.add(n);
+ }
+
+ public int getStartTime() {
+ return startTime;
+ }
+
+ public void setStartTime(int startTime) {
+ this.startTime = startTime;
+ }
+
+ public int getEndTime() {
+ return endTime;
+ }
+
+ public void setEndTime(int endTime) {
+ this.endTime = endTime;
+ }
+}
Added: core/trunk/envers/src/main/java/org/jboss/envers/tools/log/YLog.java
===================================================================
--- core/trunk/envers/src/main/java/org/jboss/envers/tools/log/YLog.java (rev 0)
+++ core/trunk/envers/src/main/java/org/jboss/envers/tools/log/YLog.java 2008-10-27 18:56:31 UTC (rev 15406)
@@ -0,0 +1,90 @@
+/*
+ * Envers. http://www.jboss.org/envers
+ *
+ * Copyright 2008 Red Hat Middleware, LLC. All rights reserved.
+ *
+ * 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, v. 2.1.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT A 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, v.2.1 along with this distribution; if not, write to the Free
+ * Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+ * 02110-1301, USA.
+ *
+ * Red Hat Author(s): Adam Warski
+ */
+package org.jboss.envers.tools.log;
+
+import org.jboss.envers.exception.VersionsException;
+
+import java.lang.reflect.Method;
+import java.lang.reflect.InvocationTargetException;
+
+/**
+ * A simple logger facade which delegates through reflection to a logging delegate.
+ * @author Adam Warski (adam at warski dot org)
+ */
+public class YLog {
+ private final Object delegate;
+ private final Method errorMethod;
+ private final Method warnMethod;
+ private final Method infoMethod;
+
+ public YLog(Object delegate, Class<?> argClass) {
+ this.delegate = delegate;
+
+ try {
+ errorMethod = delegate.getClass().getMethod("error", argClass);
+ } catch (NoSuchMethodException e) {
+ throw new VersionsException(e);
+ }
+
+ try {
+ warnMethod = delegate.getClass().getMethod("warn", argClass);
+ } catch (NoSuchMethodException e) {
+ throw new VersionsException(e);
+ }
+
+ try {
+ infoMethod = delegate.getClass().getMethod("info", argClass);
+ } catch (NoSuchMethodException e) {
+ throw new VersionsException(e);
+ }
+ }
+
+ public void error(String message) {
+ try {
+ errorMethod.invoke(delegate, message);
+ } catch (IllegalAccessException e) {
+ throw new VersionsException(e);
+ } catch (InvocationTargetException e) {
+ throw new VersionsException(e);
+ }
+ }
+
+ public void warn(String message) {
+ try {
+ warnMethod.invoke(delegate, message);
+ } catch (IllegalAccessException e) {
+ throw new VersionsException(e);
+ } catch (InvocationTargetException e) {
+ throw new VersionsException(e);
+ }
+ }
+
+ public void info(String message) {
+ try {
+ infoMethod.invoke(delegate, message);
+ } catch (IllegalAccessException e) {
+ throw new VersionsException(e);
+ } catch (InvocationTargetException e) {
+ throw new VersionsException(e);
+ }
+ }
+}
Added: core/trunk/envers/src/main/java/org/jboss/envers/tools/log/YLogManager.java
===================================================================
--- core/trunk/envers/src/main/java/org/jboss/envers/tools/log/YLogManager.java (rev 0)
+++ core/trunk/envers/src/main/java/org/jboss/envers/tools/log/YLogManager.java 2008-10-27 18:56:31 UTC (rev 15406)
@@ -0,0 +1,86 @@
+/*
+ * Envers. http://www.jboss.org/envers
+ *
+ * Copyright 2008 Red Hat Middleware, LLC. All rights reserved.
+ *
+ * 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, v. 2.1.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT A 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, v.2.1 along with this distribution; if not, write to the Free
+ * Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+ * 02110-1301, USA.
+ *
+ * Red Hat Author(s): Adam Warski
+ */
+package org.jboss.envers.tools.log;
+
+import org.jboss.envers.exception.VersionsException;
+
+import java.lang.reflect.Method;
+import java.lang.reflect.InvocationTargetException;
+
+/**
+ * A class for creating logging facades either to loggers obtained from
+ * <code>org.apache.commons.logging.LogFactory</code> (in Hibernate 3.2.x) or from
+ * <code>org.slf4j.LoggerFactory</code> (in Hibernate 3.3.x).
+ * @author Adam Warski (adam at warski dot org)
+ */
+public class YLogManager {
+ private Method getLogMethod;
+ private Class argClass;
+
+ private YLogManager() {
+ ClassLoader cl = YLogManager.class.getClassLoader();
+
+ try {
+ Class<?> logFactoryClass = cl.loadClass("org.apache.commons.logging.LogFactory");
+ try {
+ getLogMethod = logFactoryClass.getMethod("getLog", Class.class);
+ argClass = Object.class;
+ } catch (NoSuchMethodException e) {
+ throw new VersionsException("No 'getLog' method in org.apache.commons.logging.LogFactory.");
+ }
+ } catch (ClassNotFoundException e) {
+ try {
+ Class<?> loggerFactoryClass = cl.loadClass("org.slf4j.LoggerFactory");
+ try {
+ getLogMethod = loggerFactoryClass.getMethod("getLogger", Class.class);
+ argClass = String.class;
+ } catch (NoSuchMethodException e1) {
+ throw new VersionsException("No 'getLogger' method in org.slf4j.LoggerFactory.");
+ }
+ } catch (ClassNotFoundException e1) {
+ throw new VersionsException("No org.apache.commons.logging.LogFactory or org.slf4j.LoggerFactory found.");
+ }
+ }
+ }
+
+ public YLog getLog(Class<?> cls) {
+ try {
+ return new YLog(getLogMethod.invoke(null, cls), argClass);
+ } catch (IllegalAccessException e) {
+ throw new VersionsException(e);
+ } catch (InvocationTargetException e) {
+ throw new VersionsException(e);
+ }
+ }
+
+ //
+
+ private static YLogManager instance;
+
+ public static synchronized YLogManager getLogManager() {
+ if (instance == null) {
+ instance = new YLogManager();
+ }
+
+ return instance;
+ }
+}
Added: core/trunk/envers/src/main/java/org/jboss/envers/tools/query/Parameters.java
===================================================================
--- core/trunk/envers/src/main/java/org/jboss/envers/tools/query/Parameters.java (rev 0)
+++ core/trunk/envers/src/main/java/org/jboss/envers/tools/query/Parameters.java 2008-10-27 18:56:31 UTC (rev 15406)
@@ -0,0 +1,242 @@
+/*
+ * JBoss, Home of Professional Open Source
+ *
+ * Copyright 2008, Red Hat Middleware LLC, and others contributors as indicated
+ * by the @authors tag. All rights reserved.
+ *
+ * See the copyright.txt in the distribution for a full listing of individual
+ * contributors. 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, v. 2.1.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT A 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, v.2.1 along with this distribution; if not, write to the Free
+ * Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+ * 02110-1301, USA.
+ *
+ * Red Hat Author(s): Adam Warski
+ */
+package org.jboss.envers.tools.query;
+
+import org.jboss.envers.tools.MutableInteger;
+import org.jboss.envers.tools.MutableBoolean;
+
+import java.util.List;
+import java.util.ArrayList;
+import java.util.Map;
+import java.util.HashMap;
+
+/**
+ * Parameters of a query, built using {@link QueryBuilder}.
+ * @author Adam Warski (adam at warski dot org)
+ */
+public class Parameters {
+ public final static String AND = "and";
+ public final static String OR = "or";
+
+ /**
+ * Main alias of the entity.
+ */
+ private final String alias;
+ /**
+ * Connective between these parameters - "and" or "or".
+ */
+ private final String connective;
+ /**
+ * For use by the parameter generator. Must be the same in all "child" (and parent) parameters.
+ */
+ private final MutableInteger queryParamCounter;
+
+ /**
+ * A list of sub-parameters (parameters with a different connective).
+ */
+ private final List<Parameters> subParameters;
+ /**
+ * A list of negated parameters.
+ */
+ private final List<Parameters> negatedParameters;
+ /**
+ * A list of complete where-expressions.
+ */
+ private final List<String> expressions;
+ /**
+ * Values of parameters used in expressions.
+ */
+ private final Map<String, Object> localQueryParamValues;
+
+ Parameters(String alias, String connective, MutableInteger queryParamCounter) {
+ this.alias = alias;
+ this.connective = connective;
+ this.queryParamCounter = queryParamCounter;
+
+ subParameters = new ArrayList<Parameters>();
+ negatedParameters = new ArrayList<Parameters>();
+ expressions = new ArrayList<String>();
+ localQueryParamValues = new HashMap<String, Object>();
+ }
+
+ private String generateQueryParam() {
+ return "_p" + queryParamCounter.getAndIncrease();
+ }
+
+ /**
+ * Adds sub-parameters with a new connective. That is, the parameters will be grouped in parentheses in the
+ * generated query, e.g.: ... and (exp1 or exp2) and ..., assuming the old connective is "and", and the
+ * new connective is "or".
+ * @param newConnective New connective of the parameters.
+ * @return Sub-parameters with the given connective.
+ */
+ public Parameters addSubParameters(String newConnective) {
+ if (connective.equals(newConnective)) {
+ return this;
+ } else {
+ Parameters newParams = new Parameters(alias, newConnective, queryParamCounter);
+ subParameters.add(newParams);
+ return newParams;
+ }
+ }
+
+ /**
+ * Adds negated parameters, by default with the "and" connective. These paremeters will be grouped in parentheses
+ * in the generated query and negated, e.g. ... not (exp1 and exp2) ...
+ * @return Negated sub paremters.
+ */
+ public Parameters addNegatedParameters() {
+ Parameters newParams = new Parameters(alias, AND, queryParamCounter);
+ negatedParameters.add(newParams);
+ return newParams;
+ }
+
+ public void addWhere(String left, String op, String right) {
+ addWhere(left, true, op, right, true);
+ }
+
+ public void addWhere(String left, boolean addAliasLeft, String op, String right, boolean addAliasRight) {
+ StringBuilder expression = new StringBuilder();
+
+ if (addAliasLeft) { expression.append(alias).append("."); }
+ expression.append(left);
+
+ expression.append(" ").append(op).append(" ");
+
+ if (addAliasRight) { expression.append(alias).append("."); }
+ expression.append(right);
+
+ expressions.add(expression.toString());
+ }
+
+ public void addWhereWithParam(String left, String op, Object paramValue) {
+ addWhereWithParam(left, true, op, paramValue);
+ }
+
+ public void addWhereWithParam(String left, boolean addAlias, String op, Object paramValue) {
+ String paramName = generateQueryParam();
+ localQueryParamValues.put(paramName, paramValue);
+
+ addWhereWithNamedParam(left, addAlias, op, paramName);
+ }
+
+ public void addWhereWithNamedParam(String left, String op, String paramName) {
+ addWhereWithNamedParam(left, true, op, paramName);
+ }
+
+ public void addWhereWithNamedParam(String left, boolean addAlias, String op, String paramName) {
+ StringBuilder expression = new StringBuilder();
+
+ if (addAlias) { expression.append(alias).append("."); }
+ expression.append(left);
+ expression.append(" ").append(op).append(" ");
+ expression.append(":").append(paramName);
+
+ expressions.add(expression.toString());
+ }
+
+ public void addWhereWithParams(String left, String opStart, Object[] paramValues, String opEnd) {
+ StringBuilder expression = new StringBuilder();
+
+ expression.append(alias).append(".").append(left).append(" ").append(opStart);
+
+ for (int i=0; i<paramValues.length; i++) {
+ Object paramValue = paramValues[i];
+ String paramName = generateQueryParam();
+ localQueryParamValues.put(paramName, paramValue);
+ expression.append(":").append(paramName);
+
+ if (i != paramValues.length-1) {
+ expression.append(", ");
+ }
+ }
+
+ expression.append(opEnd);
+
+ expressions.add(expression.toString());
+ }
+
+ public void addWhere(String left, String op, QueryBuilder right) {
+ addWhere(left, true, op, right);
+ }
+
+ public void addWhere(String left, boolean addAlias, String op, QueryBuilder right) {
+ StringBuilder expression = new StringBuilder();
+
+ if (addAlias) {
+ expression.append(alias).append(".");
+ }
+
+ expression.append(left);
+
+ expression.append(" ").append(op).append(" ");
+
+ expression.append("(");
+ right.build(expression, localQueryParamValues);
+ expression.append(")");
+
+ expressions.add(expression.toString());
+ }
+
+ private void append(StringBuilder sb, String toAppend, MutableBoolean isFirst) {
+ if (!isFirst.isSet()) {
+ sb.append(" ").append(connective).append(" ");
+ }
+
+ sb.append(toAppend);
+
+ isFirst.unset();
+ }
+
+ boolean isEmpty() {
+ return expressions.size() == 0 && subParameters.size() == 0 && negatedParameters.size() == 0;
+ }
+
+ void build(StringBuilder sb, Map<String, Object> queryParamValues) {
+ MutableBoolean isFirst = new MutableBoolean(true);
+
+ for (String expression : expressions) {
+ append(sb, expression, isFirst);
+ }
+
+ for (Parameters sub : subParameters) {
+ if (!subParameters.isEmpty()) {
+ append(sb, "(", isFirst);
+ sub.build(sb, queryParamValues);
+ sb.append(")");
+ }
+ }
+
+ for (Parameters negated : negatedParameters) {
+ if (!negatedParameters.isEmpty()) {
+ append(sb, "not (", isFirst);
+ negated.build(sb, queryParamValues);
+ sb.append(")");
+ }
+ }
+
+ queryParamValues.putAll(localQueryParamValues);
+ }
+}
+
Added: core/trunk/envers/src/main/java/org/jboss/envers/tools/query/QueryBuilder.java
===================================================================
--- core/trunk/envers/src/main/java/org/jboss/envers/tools/query/QueryBuilder.java (rev 0)
+++ core/trunk/envers/src/main/java/org/jboss/envers/tools/query/QueryBuilder.java 2008-10-27 18:56:31 UTC (rev 15406)
@@ -0,0 +1,200 @@
+/*
+ * JBoss, Home of Professional Open Source
+ *
+ * Copyright 2008, Red Hat Middleware LLC, and others contributors as indicated
+ * by the @authors tag. All rights reserved.
+ *
+ * See the copyright.txt in the distribution for a full listing of individual
+ * contributors. 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, v. 2.1.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT A 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, v.2.1 along with this distribution; if not, write to the Free
+ * Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+ * 02110-1301, USA.
+ *
+ * Red Hat Author(s): Adam Warski
+ */
+package org.jboss.envers.tools.query;
+
+import org.jboss.envers.tools.MutableInteger;
+import org.jboss.envers.tools.Pair;
+import org.jboss.envers.tools.StringTools;
+
+import java.util.Map;
+import java.util.List;
+import java.util.ArrayList;
+
+/**
+ * A class for incrementaly building a HQL query.
+ * @author Adam Warski (adam at warski dot org)
+ */
+public class QueryBuilder {
+ private final String entityName;
+ private final String alias;
+
+ /**
+ * For use by alias generator (in case an alias is not provided by the user).
+ */
+ private final MutableInteger aliasCounter;
+ /**
+ * For use by parameter generator, in {@link Parameters}. This counter must be
+ * the same in all parameters and sub-queries of this query.
+ */
+ private final MutableInteger paramCounter;
+ /**
+ * Main "where" parameters for this query.
+ */
+ private final Parameters rootParameters;
+
+ /**
+ * A list of pairs (from entity name, alias name).
+ */
+ private final List<Pair<String, String>> froms;
+ /**
+ * A list of pairs (property name, order ascending?).
+ */
+ private final List<Pair<String, Boolean>> orders;
+ /**
+ * A list of complete projection definitions: either a sole property name, or a function(property name).
+ */
+ private final List<String> projections;
+
+ /**
+ *
+ * @param entityName Main entity which should be selected.
+ * @param alias Alias of the entity
+ */
+ public QueryBuilder(String entityName, String alias) {
+ this(entityName, alias, new MutableInteger(), new MutableInteger());
+ }
+
+ private QueryBuilder(String entityName, String alias, MutableInteger aliasCounter, MutableInteger paramCounter) {
+ this.entityName = entityName;
+ this.alias = alias;
+ this.aliasCounter = aliasCounter;
+ this.paramCounter = paramCounter;
+
+ rootParameters = new Parameters(alias, "and", paramCounter);
+
+ froms = new ArrayList<Pair<String, String>>();
+ orders = new ArrayList<Pair<String, Boolean>>();
+ projections = new ArrayList<String>();
+
+ addFrom(entityName, alias);
+ }
+
+ /**
+ * Add an entity from which to select.
+ * @param entityName Name of the entity from which to select.
+ * @param alias Alias of the entity. Should be different than all other aliases.
+ */
+ public void addFrom(String entityName, String alias) {
+ froms.add(Pair.make(entityName, alias));
+ }
+
+ private String generateAlias() {
+ return "_e" + aliasCounter.getAndIncrease();
+ }
+
+ /**
+ * @return A sub-query builder for the same entity (with an auto-generated alias). The sub-query can
+ * be later used as a value of a parameter.
+ */
+ public QueryBuilder newSubQueryBuilder() {
+ return newSubQueryBuilder(entityName, generateAlias());
+ }
+
+ /**
+ * @param entityName Entity name, which will be the main entity for the sub-query.
+ * @param alias Alias of the entity, which can later be used in parameters.
+ * @return A sub-query builder for the given entity, with the given alias. The sub-query can
+ * be later used as a value of a parameter.
+ */
+ public QueryBuilder newSubQueryBuilder(String entityName, String alias) {
+ return new QueryBuilder(entityName, alias, aliasCounter, paramCounter);
+ }
+
+ public Parameters getRootParameters() {
+ return rootParameters;
+ }
+
+ public void addOrder(String propertyName, boolean ascending) {
+ orders.add(Pair.make(propertyName, ascending));
+ }
+
+ public void addProjection(String function, String propertyName, boolean distinct) {
+ addProjection(function, propertyName, distinct, true);
+ }
+
+ public void addProjection(String function, String propertyName, boolean distinct, boolean addAlias) {
+ if (function == null) {
+ projections.add((distinct ? "distinct " : "") + (addAlias ? alias+ "." : "") + propertyName);
+ } else {
+ projections.add(function + "(" + (distinct ? "distinct " : "") + (addAlias ? alias + "." : "") + propertyName + ")");
+ }
+ }
+
+ /**
+ * Builds the given query, appending results to the given string buffer, and adding all query parameter values
+ * that are used to the map provided.
+ * @param sb String builder to which the query will be appended.
+ * @param queryParamValues Map to which name and values of parameters used in the query should be added.
+ */
+ public void build(StringBuilder sb, Map<String, Object> queryParamValues) {
+ sb.append("select ");
+ if (projections.size() > 0) {
+ // all projections separated with commas
+ StringTools.append(sb, projections.iterator(), ", ");
+ } else {
+ // all aliases separated with commas
+ StringTools.append(sb, getAliasList().iterator(), ", ");
+ }
+ sb.append(" from ");
+ // all from entities with aliases, separated with commas
+ StringTools.append(sb, getFromList().iterator(), ", ");
+ // where part - rootParameters
+ if (!rootParameters.isEmpty()) {
+ sb.append(" where ");
+ rootParameters.build(sb, queryParamValues);
+ }
+ // orders
+ if (orders.size() > 0) {
+ sb.append(" order by ");
+ StringTools.append(sb, getOrderList().iterator(), ", ");
+ }
+ }
+
+ private List<String> getAliasList() {
+ List<String> aliasList = new ArrayList<String>();
+ for (Pair<String, String> from : froms) {
+ aliasList.add(from.getSecond());
+ }
+
+ return aliasList;
+ }
+
+ private List<String> getFromList() {
+ List<String> fromList = new ArrayList<String>();
+ for (Pair<String, String> from : froms) {
+ fromList.add(from.getFirst() + " " + from.getSecond());
+ }
+
+ return fromList;
+ }
+
+ private List<String> getOrderList() {
+ List<String> orderList = new ArrayList<String>();
+ for (Pair<String, Boolean> order : orders) {
+ orderList.add(alias + "." + order.getFirst() + " " + (order.getSecond() ? "asc" : "desc"));
+ }
+
+ return orderList;
+ }
+}
Added: core/trunk/envers/src/main/java/org/jboss/envers/tools/reflection/ReflectionTools.java
===================================================================
--- core/trunk/envers/src/main/java/org/jboss/envers/tools/reflection/ReflectionTools.java (rev 0)
+++ core/trunk/envers/src/main/java/org/jboss/envers/tools/reflection/ReflectionTools.java 2008-10-27 18:56:31 UTC (rev 15406)
@@ -0,0 +1,83 @@
+/*
+ * Envers. http://www.jboss.org/envers
+ *
+ * Copyright 2008 Red Hat Middleware, LLC. All rights reserved.
+ *
+ * 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, v. 2.1.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT A 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, v.2.1 along with this distribution; if not, write to the Free
+ * Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+ * 02110-1301, USA.
+ *
+ * Red Hat Author(s): Adam Warski
+ */
+package org.jboss.envers.tools.reflection;
+
+import org.hibernate.property.PropertyAccessor;
+import org.hibernate.property.BasicPropertyAccessor;
+import org.hibernate.property.Getter;
+import org.hibernate.property.Setter;
+import org.hibernate.util.ReflectHelper;
+import org.jboss.envers.exception.VersionsException;
+import org.jboss.envers.tools.Pair;
+import org.jboss.envers.tools.ConcurrentReferenceHashMap;
+
+import java.util.Map;
+
+import static org.jboss.envers.tools.Pair.make;
+
+/**
+ * @author Adam Warski (adam at warski dot org)
+ */
+public class ReflectionTools {
+ private static final Map<Pair<Class, String>, Getter> getterCache =
+ new ConcurrentReferenceHashMap<Pair<Class, String>, Getter>(10,
+ ConcurrentReferenceHashMap.ReferenceType.SOFT,
+ ConcurrentReferenceHashMap.ReferenceType.SOFT);
+ private static final Map<Pair<Class, String>, Setter> setterCache =
+ new ConcurrentReferenceHashMap<Pair<Class, String>, Setter>(10,
+ ConcurrentReferenceHashMap.ReferenceType.SOFT,
+ ConcurrentReferenceHashMap.ReferenceType.SOFT);
+
+ private static final PropertyAccessor BASIC_PROPERTY_ACCESSOR = new BasicPropertyAccessor();
+
+ public static Class<?> loadClass(String name) {
+ try {
+ return Thread.currentThread().getContextClassLoader().loadClass(name);
+ } catch (ClassNotFoundException e) {
+ throw new VersionsException(e);
+ }
+ }
+
+ public static Getter getGetter(Class cls, String propertyName) {
+ Pair<Class, String> key = make(cls, propertyName);
+ Getter value = getterCache.get(key);
+ if (value == null) {
+ value = ReflectHelper.getGetter(cls, propertyName);
+ // It's ok if two getters are generated concurrently
+ getterCache.put(key, value);
+ }
+
+ return value;
+ }
+
+ public static Setter getSetter(Class cls, String propertyName) {
+ Pair<Class, String> key = make(cls, propertyName);
+ Setter value = setterCache.get(key);
+ if (value == null) {
+ value = BASIC_PROPERTY_ACCESSOR.getSetter(cls, propertyName);
+ // It's ok if two setters are generated concurrently
+ setterCache.put(key, value);
+ }
+
+ return value;
+ }
+}
Added: core/trunk/envers/src/main/java/org/jboss/envers/tools/reflection/YClass.java
===================================================================
--- core/trunk/envers/src/main/java/org/jboss/envers/tools/reflection/YClass.java (rev 0)
+++ core/trunk/envers/src/main/java/org/jboss/envers/tools/reflection/YClass.java 2008-10-27 18:56:31 UTC (rev 15406)
@@ -0,0 +1,96 @@
+/*
+ * Envers. http://www.jboss.org/envers
+ *
+ * Copyright 2008 Red Hat Middleware, LLC. All rights reserved.
+ *
+ * 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, v. 2.1.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT A 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, v.2.1 along with this distribution; if not, write to the Free
+ * Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+ * 02110-1301, USA.
+ *
+ * Red Hat Author(s): Adam Warski
+ */
+package org.jboss.envers.tools.reflection;
+
+import org.jboss.envers.exception.VersionsException;
+
+import java.util.List;
+import java.util.ArrayList;
+import java.lang.annotation.Annotation;
+import java.lang.reflect.InvocationTargetException;
+
+/**
+ * @author Adam Warski (adam at warski dot org)
+ */
+public class YClass {
+ private final YMethodsAndClasses ymc;
+ private final Object delegate;
+
+ public YClass(YMethodsAndClasses ymc, Object delegate) {
+ this.ymc = ymc;
+ this.delegate = delegate;
+ }
+
+ Object getDelegate() {
+ return delegate;
+ }
+
+ public String getName() {
+ try {
+ return (String) ymc.getXClass_getNameMethod().invoke(delegate);
+ } catch (IllegalAccessException e) {
+ throw new VersionsException(e);
+ } catch (InvocationTargetException e) {
+ throw new VersionsException(e);
+ }
+ }
+
+ public YClass getSuperclass() {
+ try {
+ return new YClass(ymc, ymc.getXClass_getSuperclassMethod().invoke(delegate));
+ } catch (IllegalAccessException e) {
+ throw new VersionsException(e);
+ } catch (InvocationTargetException e) {
+ throw new VersionsException(e);
+ }
+ }
+
+ public List<YProperty> getDeclaredProperties(String accessMode) {
+ List delegates;
+
+ try {
+ delegates = (List) ymc.getXClass_getDeclaredPropertiesMethod().invoke(delegate, accessMode);
+ } catch (IllegalAccessException e) {
+ throw new VersionsException(e);
+ } catch (InvocationTargetException e) {
+ throw new VersionsException(e);
+ }
+
+ List<YProperty> ret = new ArrayList<YProperty>();
+ for (Object delegate : delegates) {
+ ret.add(new YProperty(ymc, delegate));
+ }
+
+ return ret;
+ }
+
+ public <T extends Annotation> T getAnnotation(Class<T> annotation) {
+ try {
+ //noinspection unchecked
+ return (T) ymc.getXClass_getAnnotationMethod().invoke(delegate, annotation);
+ } catch (IllegalAccessException e) {
+ throw new VersionsException(e);
+ } catch (InvocationTargetException e) {
+ throw new VersionsException(e);
+ }
+ }
+}
Added: core/trunk/envers/src/main/java/org/jboss/envers/tools/reflection/YMethodsAndClasses.java
===================================================================
--- core/trunk/envers/src/main/java/org/jboss/envers/tools/reflection/YMethodsAndClasses.java (rev 0)
+++ core/trunk/envers/src/main/java/org/jboss/envers/tools/reflection/YMethodsAndClasses.java 2008-10-27 18:56:31 UTC (rev 15406)
@@ -0,0 +1,119 @@
+/*
+ * Envers. http://www.jboss.org/envers
+ *
+ * Copyright 2008 Red Hat Middleware, LLC. All rights reserved.
+ *
+ * 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, v. 2.1.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT A 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, v.2.1 along with this distribution; if not, write to the Free
+ * Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+ * 02110-1301, USA.
+ *
+ * Red Hat Author(s): Adam Warski
+ */
+package org.jboss.envers.tools.reflection;
+
+import org.jboss.envers.exception.VersionsException;
+
+import java.lang.reflect.Method;
+
+/**
+ * @author Adam Warski (adam at warski dot org)
+ */
+public class YMethodsAndClasses {
+ private final Method reflectionManager_classForNameMethod;
+ private final Method reflectionManager_equalsMethod;
+
+ private final Method xClass_getNameMethod;
+ private final Method xClass_getSuperclassMethod;
+ private final Method xClass_getDeclaredPropertiesMethod;
+ private final Method xClass_getAnnotationMethod;
+
+ private final Method xProperty_getNameMethod;
+ private final Method xProperty_getAnnotationMethod;
+ private final Method xProperty_getTypeMethod;
+
+ public YMethodsAndClasses(Class<?> delegateClass) throws Exception {
+ // Initializing classes
+ ClassLoader cl = YMethodsAndClasses.class.getClassLoader();
+
+ Class xClassClass;
+ try {
+ xClassClass = cl.loadClass("org.hibernate.annotations.common.reflection.XClass");
+ } catch (ClassNotFoundException e) {
+ try {
+ xClassClass = cl.loadClass("org.hibernate.reflection.XClass");
+ } catch (ClassNotFoundException e1) {
+ throw new VersionsException("No XClass found.");
+ }
+ }
+
+ Class xPropertyClass;
+ try {
+ xPropertyClass = cl.loadClass("org.hibernate.annotations.common.reflection.XProperty");
+ } catch (ClassNotFoundException e) {
+ try {
+ xPropertyClass = cl.loadClass("org.hibernate.reflection.XProperty");
+ } catch (ClassNotFoundException e1) {
+ throw new VersionsException("No XProperty found.");
+ }
+ }
+
+ // Initializing methods
+ reflectionManager_classForNameMethod = delegateClass.getMethod("classForName", String.class, Class.class);
+ reflectionManager_equalsMethod = delegateClass.getMethod("equals", xClassClass, Class.class);
+
+ xClass_getNameMethod = xClassClass.getMethod("getName");
+ xClass_getSuperclassMethod = xClassClass.getMethod("getSuperclass");
+ xClass_getDeclaredPropertiesMethod = xClassClass.getMethod("getDeclaredProperties", String.class);
+ xClass_getAnnotationMethod = xClassClass.getMethod("getAnnotation", Class.class);
+
+ xProperty_getNameMethod = xPropertyClass.getMethod("getName");
+ xProperty_getTypeMethod = xPropertyClass.getMethod("getType");
+ xProperty_getAnnotationMethod = xPropertyClass.getMethod("getAnnotation", Class.class);
+ }
+
+ public Method getXClass_getNameMethod() {
+ return xClass_getNameMethod;
+ }
+
+ public Method getXClass_getSuperclassMethod() {
+ return xClass_getSuperclassMethod;
+ }
+
+ public Method getXClass_getDeclaredPropertiesMethod() {
+ return xClass_getDeclaredPropertiesMethod;
+ }
+
+ public Method getXClass_getAnnotationMethod() {
+ return xClass_getAnnotationMethod;
+ }
+
+ public Method getXProperty_getNameMethod() {
+ return xProperty_getNameMethod;
+ }
+
+ public Method getXProperty_getAnnotationMethod() {
+ return xProperty_getAnnotationMethod;
+ }
+
+ public Method getXProperty_getTypeMethod() {
+ return xProperty_getTypeMethod;
+ }
+
+ public Method getReflectionManager_classForNameMethod() {
+ return reflectionManager_classForNameMethod;
+ }
+
+ public Method getReflectionManager_equalsMethod() {
+ return reflectionManager_equalsMethod;
+ }
+}
Added: core/trunk/envers/src/main/java/org/jboss/envers/tools/reflection/YProperty.java
===================================================================
--- core/trunk/envers/src/main/java/org/jboss/envers/tools/reflection/YProperty.java (rev 0)
+++ core/trunk/envers/src/main/java/org/jboss/envers/tools/reflection/YProperty.java 2008-10-27 18:56:31 UTC (rev 15406)
@@ -0,0 +1,71 @@
+/*
+ * Envers. http://www.jboss.org/envers
+ *
+ * Copyright 2008 Red Hat Middleware, LLC. All rights reserved.
+ *
+ * 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, v. 2.1.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT A 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, v.2.1 along with this distribution; if not, write to the Free
+ * Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+ * 02110-1301, USA.
+ *
+ * Red Hat Author(s): Adam Warski
+ */
+package org.jboss.envers.tools.reflection;
+
+import org.jboss.envers.exception.VersionsException;
+
+import java.lang.annotation.Annotation;
+import java.lang.reflect.InvocationTargetException;
+
+/**
+ * @author Adam Warski (adam at warski dot org)
+ */
+public class YProperty {
+ private final YMethodsAndClasses ymc;
+ private final Object delegate;
+
+ public YProperty(YMethodsAndClasses ymc, Object delegate) {
+ this.ymc = ymc;
+ this.delegate = delegate;
+ }
+
+ public String getName() {
+ try {
+ return (String) ymc.getXProperty_getNameMethod().invoke(delegate);
+ } catch (IllegalAccessException e) {
+ throw new VersionsException(e);
+ } catch (InvocationTargetException e) {
+ throw new VersionsException(e);
+ }
+ }
+
+ public <T extends Annotation> T getAnnotation(Class<T> annotation) {
+ try {
+ //noinspection unchecked
+ return (T) ymc.getXProperty_getAnnotationMethod().invoke(delegate, annotation);
+ } catch (IllegalAccessException e) {
+ throw new VersionsException(e);
+ } catch (InvocationTargetException e) {
+ throw new VersionsException(e);
+ }
+ }
+
+ public YClass getType() {
+ try {
+ return new YClass(ymc, ymc.getXProperty_getTypeMethod().invoke(delegate));
+ } catch (IllegalAccessException e) {
+ throw new VersionsException(e);
+ } catch (InvocationTargetException e) {
+ throw new VersionsException(e);
+ }
+ }
+}
Added: core/trunk/envers/src/main/java/org/jboss/envers/tools/reflection/YReflectionManager.java
===================================================================
--- core/trunk/envers/src/main/java/org/jboss/envers/tools/reflection/YReflectionManager.java (rev 0)
+++ core/trunk/envers/src/main/java/org/jboss/envers/tools/reflection/YReflectionManager.java 2008-10-27 18:56:31 UTC (rev 15406)
@@ -0,0 +1,80 @@
+/*
+ * Envers. http://www.jboss.org/envers
+ *
+ * Copyright 2008 Red Hat Middleware, LLC. All rights reserved.
+ *
+ * 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, v. 2.1.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT A 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, v.2.1 along with this distribution; if not, write to the Free
+ * Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+ * 02110-1301, USA.
+ *
+ * Red Hat Author(s): Adam Warski
+ */
+package org.jboss.envers.tools.reflection;
+
+import org.hibernate.cfg.Configuration;
+import org.hibernate.MappingException;
+import org.jboss.envers.exception.VersionsException;
+
+import java.lang.reflect.InvocationTargetException;
+
+/**
+ * A reflection manager which proxies either to the old classes from package org.hibernate.reflection,
+ * or to the new classed from package org.hibernate.annotations.common.reflection.
+ * @author Adam Warski (adam at warski dot org)
+ */
+public class YReflectionManager {
+ private final Object delegate;
+ private final YMethodsAndClasses ymc;
+
+ public YReflectionManager(Configuration cfg) throws Exception {
+ Object delegateTemp;
+ try {
+ delegateTemp = cfg.getClass().getMethod("getReflectionManager").invoke(cfg);
+ } catch (NoSuchMethodException e) {
+ // TODO - what if there it's a pure Hibernate envirionment?
+ delegateTemp = ReflectionTools
+ .loadClass("org.hibernate.cfg.annotations.reflection.EJB3ReflectionManager")
+ .newInstance();
+ }
+ delegate = delegateTemp;
+ ymc = new YMethodsAndClasses(delegate.getClass());
+ }
+
+ public YClass classForName(String className, Class<?> caller) throws ClassNotFoundException {
+ try {
+ return new YClass(ymc, ymc.getReflectionManager_classForNameMethod().invoke(delegate, className, caller));
+ } catch (IllegalAccessException e) {
+ throw new VersionsException(e);
+ } catch (InvocationTargetException e) {
+ throw new VersionsException(e);
+ }
+ }
+
+ public <T> boolean equals(YClass class1, java.lang.Class<T> class2) {
+ try {
+ return (Boolean) ymc.getReflectionManager_equalsMethod().invoke(delegate, class1.getDelegate(), class2);
+ } catch (IllegalAccessException e) {
+ throw new VersionsException(e);
+ } catch (InvocationTargetException e) {
+ throw new VersionsException(e);
+ }
+ }
+
+ public static YReflectionManager get(Configuration cfg) {
+ try {
+ return new YReflectionManager(cfg);
+ } catch (Exception e) {
+ throw new MappingException(e);
+ }
+ }
+}
Added: core/trunk/envers/src/main/resources/META-INF/COPYING.txt
===================================================================
--- core/trunk/envers/src/main/resources/META-INF/COPYING.txt (rev 0)
+++ core/trunk/envers/src/main/resources/META-INF/COPYING.txt 2008-10-27 18:56:31 UTC (rev 15406)
@@ -0,0 +1,466 @@
+ GNU LESSER GENERAL PUBLIC LICENSE
+ Version 2.1, February 1999
+
+ Copyright (C) 1991, 1999 Free Software Foundation, Inc.
+ 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ Everyone is permitted to copy and distribute verbatim copies
+ of this license document, but changing it is not allowed.
+
+[This is the first released version of the Lesser GPL. It also counts
+ as the successor of the GNU Library Public License, version 2, hence
+ the version number 2.1.]
+
+ Preamble
+
+ The licenses for most software are designed to take away your
+freedom to share and change it. By contrast, the GNU General Public
+Licenses are intended to guarantee your freedom to share and change
+free software--to make sure the software is free for all its users.
+
+ This license, the Lesser General Public License, applies to some
+specially designated software packages--typically libraries--of the
+Free Software Foundation and other authors who decide to use it. You
+can use it too, but we suggest you first think carefully about whether
+this license or the ordinary General Public License is the better
+strategy to use in any particular case, based on the explanations below.
+
+ When we speak of free software, we are referring to freedom of use,
+not price. Our General Public Licenses are designed to make sure that
+you have the freedom to distribute copies of free software (and charge
+for this service if you wish); that you receive source code or can get
+it if you want it; that you can change the software and use pieces of
+it in new free programs; and that you are informed that you can do
+these things.
+
+ To protect your rights, we need to make restrictions that forbid
+distributors to deny you these rights or to ask you to surrender these
+rights. These restrictions translate to certain responsibilities for
+you if you distribute copies of the library or if you modify it.
+
+ For example, if you distribute copies of the library, whether gratis
+or for a fee, you must give the recipients all the rights that we gave
+you. You must make sure that they, too, receive or can get the source
+code. If you link other code with the library, you must provide
+complete object files to the recipients, so that they can relink them
+with the library after making changes to the library and recompiling
+it. And you must show them these terms so they know their rights.
+
+ We protect your rights with a two-step method: (1) we copyright the
+library, and (2) we offer you this license, which gives you legal
+permission to copy, distribute and/or modify the library.
+
+ To protect each distributor, we want to make it very clear that
+there is no warranty for the free library. Also, if the library is
+modified by someone else and passed on, the recipients should know
+that what they have is not the original version, so that the original
+author's reputation will not be affected by problems that might be
+introduced by others.
+
+
+ Finally, software patents pose a constant threat to the existence of
+any free program. We wish to make sure that a company cannot
+effectively restrict the users of a free program by obtaining a
+restrictive license from a patent holder. Therefore, we insist that
+any patent license obtained for a version of the library must be
+consistent with the full freedom of use specified in this license.
+
+ Most GNU software, including some libraries, is covered by the
+ordinary GNU General Public License. This license, the GNU Lesser
+General Public License, applies to certain designated libraries, and
+is quite different from the ordinary General Public License. We use
+this license for certain libraries in order to permit linking those
+libraries into non-free programs.
+
+ When a program is linked with a library, whether statically or using
+a shared library, the combination of the two is legally speaking a
+combined work, a derivative of the original library. The ordinary
+General Public License therefore permits such linking only if the
+entire combination fits its criteria of freedom. The Lesser General
+Public License permits more lax criteria for linking other code with
+the library.
+
+ We call this license the "Lesser" General Public License because it
+does Less to protect the user's freedom than the ordinary General
+Public License. It also provides other free software developers Less
+of an advantage over competing non-free programs. These disadvantages
+are the reason we use the ordinary General Public License for many
+libraries. However, the Lesser license provides advantages in certain
+special circumstances.
+
+ For example, on rare occasions, there may be a special need to
+encourage the widest possible use of a certain library, so that it becomes
+a de-facto standard. To achieve this, non-free programs must be
+allowed to use the library. A more frequent case is that a free
+library does the same job as widely used non-free libraries. In this
+case, there is little to gain by limiting the free library to free
+software only, so we use the Lesser General Public License.
+
+ In other cases, permission to use a particular library in non-free
+programs enables a greater number of people to use a large body of
+free software. For example, permission to use the GNU C Library in
+non-free programs enables many more people to use the whole GNU
+operating system, as well as its variant, the GNU/Linux operating
+system.
+
+ Although the Lesser General Public License is Less protective of the
+users' freedom, it does ensure that the user of a program that is
+linked with the Library has the freedom and the wherewithal to run
+that program using a modified version of the Library.
+
+ The precise terms and conditions for copying, distribution and
+modification follow. Pay close attention to the difference between a
+"work based on the library" and a "work that uses the library". The
+former contains code derived from the library, whereas the latter must
+be combined with the library in order to run.
+
+
+ GNU LESSER GENERAL PUBLIC LICENSE
+ TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
+
+ 0. This License Agreement applies to any software library or other
+program which contains a notice placed by the copyright holder or
+other authorized party saying it may be distributed under the terms of
+this Lesser General Public License (also called "this License").
+Each licensee is addressed as "you".
+
+ A "library" means a collection of software functions and/or data
+prepared so as to be conveniently linked with application programs
+(which use some of those functions and data) to form executables.
+
+ The "Library", below, refers to any such software library or work
+which has been distributed under these terms. A "work based on the
+Library" means either the Library or any derivative work under
+copyright law: that is to say, a work containing the Library or a
+portion of it, either verbatim or with modifications and/or translated
+straightforwardly into another language. (Hereinafter, translation is
+included without limitation in the term "modification".)
+
+ "Source code" for a work means the preferred form of the work for
+making modifications to it. For a library, complete source code means
+all the source code for all modules it contains, plus any associated
+interface definition files, plus the scripts used to control compilation
+and installation of the library.
+
+ Activities other than copying, distribution and modification are not
+covered by this License; they are outside its scope. The act of
+running a program using the Library is not restricted, and output from
+such a program is covered only if its contents constitute a work based
+on the Library (independent of the use of the Library in a tool for
+writing it). Whether that is true depends on what the Library does
+and what the program that uses the Library does.
+
+ 1. You may copy and distribute verbatim copies of the Library's
+complete source code as you receive it, in any medium, provided that
+you conspicuously and appropriately publish on each copy an
+appropriate copyright notice and disclaimer of warranty; keep intact
+all the notices that refer to this License and to the absence of any
+warranty; and distribute a copy of this License along with the
+Library.
+
+ You may charge a fee for the physical act of transferring a copy,
+and you may at your option offer warranty protection in exchange for a
+fee.
+
+
+ 2. You may modify your copy or copies of the Library or any portion
+of it, thus forming a work based on the Library, and copy and
+distribute such modifications or work under the terms of Section 1
+above, provided that you also meet all of these conditions:
+
+ a) The modified work must itself be a software library.
+
+ b) You must cause the files modified to carry prominent notices
+ stating that you changed the files and the date of any change.
+
+ c) You must cause the whole of the work to be licensed at no
+ charge to all third parties under the terms of this License.
+
+ d) If a facility in the modified Library refers to a function or a
+ table of data to be supplied by an application program that uses
+ the facility, other than as an argument passed when the facility
+ is invoked, then you must make a good faith effort to ensure that,
+ in the event an application does not supply such function or
+ table, the facility still operates, and performs whatever part of
+ its purpose remains meaningful.
+
+ (For example, a function in a library to compute square roots has
+ a purpose that is entirely well-defined independent of the
+ application. Therefore, Subsection 2d requires that any
+ application-supplied function or table used by this function must
+ be optional: if the application does not supply it, the square
+ root function must still compute square roots.)
+
+These requirements apply to the modified work as a whole. If
+identifiable sections of that work are not derived from the Library,
+and can be reasonably considered independent and separate works in
+themselves, then this License, and its terms, do not apply to those
+sections when you distribute them as separate works. But when you
+distribute the same sections as part of a whole which is a work based
+on the Library, the distribution of the whole must be on the terms of
+this License, whose permissions for other licensees extend to the
+entire whole, and thus to each and every part regardless of who wrote
+it.
+
+Thus, it is not the intent of this section to claim rights or contest
+your rights to work written entirely by you; rather, the intent is to
+exercise the right to control the distribution of derivative or
+collective works based on the Library.
+
+In addition, mere aggregation of another work not based on the Library
+with the Library (or with a work based on the Library) on a volume of
+a storage or distribution medium does not bring the other work under
+the scope of this License.
+
+ 3. You may opt to apply the terms of the ordinary GNU General Public
+License instead of this License to a given copy of the Library. To do
+this, you must alter all the notices that refer to this License, so
+that they refer to the ordinary GNU General Public License, version 2,
+instead of to this License. (If a newer version than version 2 of the
+ordinary GNU General Public License has appeared, then you can specify
+that version instead if you wish.) Do not make any other change in
+these notices.
+
+
+ Once this change is made in a given copy, it is irreversible for
+that copy, so the ordinary GNU General Public License applies to all
+subsequent copies and derivative works made from that copy.
+
+ This option is useful when you wish to copy part of the code of
+the Library into a program that is not a library.
+
+ 4. You may copy and distribute the Library (or a portion or
+derivative of it, under Section 2) in object code or executable form
+under the terms of Sections 1 and 2 above provided that you accompany
+it with the complete corresponding machine-readable source code, which
+must be distributed under the terms of Sections 1 and 2 above on a
+medium customarily used for software interchange.
+
+ If distribution of object code is made by offering access to copy
+from a designated place, then offering equivalent access to copy the
+source code from the same place satisfies the requirement to
+distribute the source code, even though third parties are not
+compelled to copy the source along with the object code.
+
+ 5. A program that contains no derivative of any portion of the
+Library, but is designed to work with the Library by being compiled or
+linked with it, is called a "work that uses the Library". Such a
+work, in isolation, is not a derivative work of the Library, and
+therefore falls outside the scope of this License.
+
+ However, linking a "work that uses the Library" with the Library
+creates an executable that is a derivative of the Library (because it
+contains portions of the Library), rather than a "work that uses the
+library". The executable is therefore covered by this License.
+Section 6 states terms for distribution of such executables.
+
+ When a "work that uses the Library" uses material from a header file
+that is part of the Library, the object code for the work may be a
+derivative work of the Library even though the source code is not.
+Whether this is true is especially significant if the work can be
+linked without the Library, or if the work is itself a library. The
+threshold for this to be true is not precisely defined by law.
+
+ If such an object file uses only numerical parameters, data
+structure layouts and accessors, and small macros and small inline
+functions (ten lines or less in length), then the use of the object
+file is unrestricted, regardless of whether it is legally a derivative
+work. (Executables containing this object code plus portions of the
+Library will still fall under Section 6.)
+
+ Otherwise, if the work is a derivative of the Library, you may
+distribute the object code for the work under the terms of Section 6.
+Any executables containing that work also fall under Section 6,
+whether or not they are linked directly with the Library itself.
+
+
+ 6. As an exception to the Sections above, you may also combine or
+link a "work that uses the Library" with the Library to produce a
+work containing portions of the Library, and distribute that work
+under terms of your choice, provided that the terms permit
+modification of the work for the customer's own use and reverse
+engineering for debugging such modifications.
+
+ You must give prominent notice with each copy of the work that the
+Library is used in it and that the Library and its use are covered by
+this License. You must supply a copy of this License. If the work
+during execution displays copyright notices, you must include the
+copyright notice for the Library among them, as well as a reference
+directing the user to the copy of this License. Also, you must do one
+of these things:
+
+ a) Accompany the work with the complete corresponding
+ machine-readable source code for the Library including whatever
+ changes were used in the work (which must be distributed under
+ Sections 1 and 2 above); and, if the work is an executable linked
+ with the Library, with the complete machine-readable "work that
+ uses the Library", as object code and/or source code, so that the
+ user can modify the Library and then relink to produce a modified
+ executable containing the modified Library. (It is understood
+ that the user who changes the contents of definitions files in the
+ Library will not necessarily be able to recompile the application
+ to use the modified definitions.)
+
+ b) Use a suitable shared library mechanism for linking with the
+ Library. A suitable mechanism is one that (1) uses at run time a
+ copy of the library already present on the user's computer system,
+ rather than copying library functions into the executable, and (2)
+ will operate properly with a modified version of the library, if
+ the user installs one, as long as the modified version is
+ interface-compatible with the version that the work was made with.
+
+ c) Accompany the work with a written offer, valid for at
+ least three years, to give the same user the materials
+ specified in Subsection 6a, above, for a charge no more
+ than the cost of performing this distribution.
+
+ d) If distribution of the work is made by offering access to copy
+ from a designated place, offer equivalent access to copy the above
+ specified materials from the same place.
+
+ e) Verify that the user has already received a copy of these
+ materials or that you have already sent this user a copy.
+
+ For an executable, the required form of the "work that uses the
+Library" must include any data and utility programs needed for
+reproducing the executable from it. However, as a special exception,
+the materials to be distributed need not include anything that is
+normally distributed (in either source or binary form) with the major
+components (compiler, kernel, and so on) of the operating system on
+which the executable runs, unless that component itself accompanies
+the executable.
+
+ It may happen that this requirement contradicts the license
+restrictions of other proprietary libraries that do not normally
+accompany the operating system. Such a contradiction means you cannot
+use both them and the Library together in an executable that you
+distribute.
+
+
+ 7. You may place library facilities that are a work based on the
+Library side-by-side in a single library together with other library
+facilities not covered by this License, and distribute such a combined
+library, provided that the separate distribution of the work based on
+the Library and of the other library facilities is otherwise
+permitted, and provided that you do these two things:
+
+ a) Accompany the combined library with a copy of the same work
+ based on the Library, uncombined with any other library
+ facilities. This must be distributed under the terms of the
+ Sections above.
+
+ b) Give prominent notice with the combined library of the fact
+ that part of it is a work based on the Library, and explaining
+ where to find the accompanying uncombined form of the same work.
+
+ 8. You may not copy, modify, sublicense, link with, or distribute
+the Library except as expressly provided under this License. Any
+attempt otherwise to copy, modify, sublicense, link with, or
+distribute the Library is void, and will automatically terminate your
+rights under this License. However, parties who have received copies,
+or rights, from you under this License will not have their licenses
+terminated so long as such parties remain in full compliance.
+
+ 9. You are not required to accept this License, since you have not
+signed it. However, nothing else grants you permission to modify or
+distribute the Library or its derivative works. These actions are
+prohibited by law if you do not accept this License. Therefore, by
+modifying or distributing the Library (or any work based on the
+Library), you indicate your acceptance of this License to do so, and
+all its terms and conditions for copying, distributing or modifying
+the Library or works based on it.
+
+ 10. Each time you redistribute the Library (or any work based on the
+Library), the recipient automatically receives a license from the
+original licensor to copy, distribute, link with or modify the Library
+subject to these terms and conditions. You may not impose any further
+restrictions on the recipients' exercise of the rights granted herein.
+You are not responsible for enforcing compliance by third parties with
+this License.
+
+
+ 11. If, as a consequence of a court judgment or allegation of patent
+infringement or for any other reason (not limited to patent issues),
+conditions are imposed on you (whether by court order, agreement or
+otherwise) that contradict the conditions of this License, they do not
+excuse you from the conditions of this License. If you cannot
+distribute so as to satisfy simultaneously your obligations under this
+License and any other pertinent obligations, then as a consequence you
+may not distribute the Library at all. For example, if a patent
+license would not permit royalty-free redistribution of the Library by
+all those who receive copies directly or indirectly through you, then
+the only way you could satisfy both it and this License would be to
+refrain entirely from distribution of the Library.
+
+If any portion of this section is held invalid or unenforceable under any
+particular circumstance, the balance of the section is intended to apply,
+and the section as a whole is intended to apply in other circumstances.
+
+It is not the purpose of this section to induce you to infringe any
+patents or other property right claims or to contest validity of any
+such claims; this section has the sole purpose of protecting the
+integrity of the free software distribution system which is
+implemented by public license practices. Many people have made
+generous contributions to the wide range of software distributed
+through that system in reliance on consistent application of that
+system; it is up to the author/donor to decide if he or she is willing
+to distribute software through any other system and a licensee cannot
+impose that choice.
+
+This section is intended to make thoroughly clear what is believed to
+be a consequence of the rest of this License.
+
+ 12. If the distribution and/or use of the Library is restricted in
+certain countries either by patents or by copyrighted interfaces, the
+original copyright holder who places the Library under this License may add
+an explicit geographical distribution limitation excluding those countries,
+so that distribution is permitted only in or among countries not thus
+excluded. In such case, this License incorporates the limitation as if
+written in the body of this License.
+
+ 13. The Free Software Foundation may publish revised and/or new
+versions of the Lesser General Public License from time to time.
+Such new versions will be similar in spirit to the present version,
+but may differ in detail to address new problems or concerns.
+
+Each version is given a distinguishing version number. If the Library
+specifies a version number of this License which applies to it and
+"any later version", you have the option of following the terms and
+conditions either of that version or of any later version published by
+the Free Software Foundation. If the Library does not specify a
+license version number, you may choose any version ever published by
+the Free Software Foundation.
+
+
+ 14. If you wish to incorporate parts of the Library into other free
+programs whose distribution conditions are incompatible with these,
+write to the author to ask for permission. For software which is
+copyrighted by the Free Software Foundation, write to the Free
+Software Foundation; we sometimes make exceptions for this. Our
+decision will be guided by the two goals of preserving the free status
+of all derivatives of our free software and of promoting the sharing
+and reuse of software generally.
+
+ NO WARRANTY
+
+ 15. BECAUSE THE LIBRARY IS LICENSED FREE OF CHARGE, THERE IS NO
+WARRANTY FOR THE LIBRARY, TO THE EXTENT PERMITTED BY APPLICABLE LAW.
+EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR
+OTHER PARTIES PROVIDE THE LIBRARY "AS IS" WITHOUT WARRANTY OF ANY
+KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE
+IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE
+LIBRARY IS WITH YOU. SHOULD THE LIBRARY PROVE DEFECTIVE, YOU ASSUME
+THE COST OF ALL NECESSARY SERVICING, REPAIR OR CORRECTION.
+
+ 16. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN
+WRITING WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY
+AND/OR REDISTRIBUTE THE LIBRARY AS PERMITTED ABOVE, BE LIABLE TO YOU
+FOR DAMAGES, INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR
+CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OR INABILITY TO USE THE
+LIBRARY (INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR DATA BEING
+RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD PARTIES OR A
+FAILURE OF THE LIBRARY TO OPERATE WITH ANY OTHER SOFTWARE), EVEN IF
+SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH
+DAMAGES.
+
+ END OF TERMS AND CONDITIONS
\ No newline at end of file
Added: core/trunk/envers/src/main/resources/META-INF/copyright.txt
===================================================================
--- core/trunk/envers/src/main/resources/META-INF/copyright.txt (rev 0)
+++ core/trunk/envers/src/main/resources/META-INF/copyright.txt 2008-10-27 18:56:31 UTC (rev 15406)
@@ -0,0 +1 @@
+(c) 2008, Adam Warski, JBoss Inc.
\ No newline at end of file
Added: core/trunk/envers/src/test/java/org/jboss/envers/test/AbstractEntityTest.java
===================================================================
--- core/trunk/envers/src/test/java/org/jboss/envers/test/AbstractEntityTest.java (rev 0)
+++ core/trunk/envers/src/test/java/org/jboss/envers/test/AbstractEntityTest.java 2008-10-27 18:56:31 UTC (rev 15406)
@@ -0,0 +1,55 @@
+package org.jboss.envers.test;
+
+import org.hibernate.ejb.Ejb3Configuration;
+import org.testng.annotations.BeforeClass;
+import org.testng.annotations.BeforeMethod;
+import org.jboss.envers.VersionsReader;
+import org.jboss.envers.VersionsReaderFactory;
+
+import javax.persistence.EntityManager;
+import javax.persistence.EntityManagerFactory;
+import java.io.IOException;
+
+/**
+ * @author Adam Warski (adam at warski dot org)
+ */
+public abstract class AbstractEntityTest {
+ private EntityManagerFactory emf;
+ private EntityManager entityManager;
+ private VersionsReader versionsReader;
+ private Ejb3Configuration cfg;
+
+ public abstract void configure(Ejb3Configuration cfg);
+
+ @BeforeMethod
+ public void newEntityManager() {
+ if (entityManager != null) {
+ entityManager.close();
+ }
+
+ entityManager = emf.createEntityManager();
+ versionsReader = VersionsReaderFactory.get(entityManager);
+ }
+
+ @BeforeClass
+ public void init() throws IOException {
+ cfg = new Ejb3Configuration();
+ cfg.configure("hibernate.test.cfg.xml");
+ configure(cfg);
+ emf = cfg.buildEntityManagerFactory();
+
+ newEntityManager();
+ }
+
+ public EntityManager getEntityManager() {
+ return entityManager;
+ }
+
+ public VersionsReader getVersionsReader() {
+ return versionsReader;
+ }
+
+ public Ejb3Configuration getCfg() {
+ return cfg;
+ }
+}
Added: core/trunk/envers/src/test/java/org/jboss/envers/test/entities/IntTestEntity.java
===================================================================
--- core/trunk/envers/src/test/java/org/jboss/envers/test/entities/IntTestEntity.java (rev 0)
+++ core/trunk/envers/src/test/java/org/jboss/envers/test/entities/IntTestEntity.java 2008-10-27 18:56:31 UTC (rev 15406)
@@ -0,0 +1,71 @@
+package org.jboss.envers.test.entities;
+
+import org.jboss.envers.Versioned;
+
+import javax.persistence.Entity;
+import javax.persistence.Id;
+import javax.persistence.GeneratedValue;
+
+/**
+ * @author Adam Warski (adam at warski dot org)
+ */
+ at Entity
+public class IntTestEntity {
+ @Id
+ @GeneratedValue
+ private Integer id;
+
+ @Versioned
+ private Integer number;
+
+ public IntTestEntity() {
+ }
+
+ public IntTestEntity(Integer number, Integer id) {
+ this.id = id;
+ this.number = number;
+ }
+
+ public IntTestEntity(Integer number) {
+ this.number = number;
+ }
+
+ public Integer getId() {
+ return id;
+ }
+
+ public void setId(Integer id) {
+ this.id = id;
+ }
+
+ public Integer getNumber() {
+ return number;
+ }
+
+ public void setNumber(Integer number) {
+ this.number = number;
+ }
+
+ public boolean equals(Object o) {
+ if (this == o) return true;
+ if (!(o instanceof IntTestEntity)) return false;
+
+ IntTestEntity that = (IntTestEntity) o;
+
+ if (id != null ? !id.equals(that.id) : that.id != null) return false;
+ if (number != null ? !number.equals(that.number) : that.number != null) return false;
+
+ return true;
+ }
+
+ public int hashCode() {
+ int result;
+ result = (id != null ? id.hashCode() : 0);
+ result = 31 * result + (number != null ? number.hashCode() : 0);
+ return result;
+ }
+
+ public String toString() {
+ return "ITE(id = " + id + ", number = " + number + ")";
+ }
+}
\ No newline at end of file
Added: core/trunk/envers/src/test/java/org/jboss/envers/test/entities/StrIntTestEntity.java
===================================================================
--- core/trunk/envers/src/test/java/org/jboss/envers/test/entities/StrIntTestEntity.java (rev 0)
+++ core/trunk/envers/src/test/java/org/jboss/envers/test/entities/StrIntTestEntity.java 2008-10-27 18:56:31 UTC (rev 15406)
@@ -0,0 +1,86 @@
+package org.jboss.envers.test.entities;
+
+import org.jboss.envers.Versioned;
+
+import javax.persistence.Entity;
+import javax.persistence.Id;
+import javax.persistence.GeneratedValue;
+
+/**
+ * @author Adam Warski (adam at warski dot org)
+ */
+ at Entity
+public class StrIntTestEntity {
+ @Id
+ @GeneratedValue
+ private Integer id;
+
+ @Versioned
+ private String str1;
+
+ @Versioned
+ private Integer number;
+
+ public StrIntTestEntity() {
+ }
+
+ public StrIntTestEntity(String str1, Integer number, Integer id) {
+ this.id = id;
+ this.str1 = str1;
+ this.number = number;
+ }
+
+ public StrIntTestEntity(String str1, Integer number) {
+ this.str1 = str1;
+ this.number = number;
+ }
+
+ public Integer getId() {
+ return id;
+ }
+
+ public void setId(Integer id) {
+ this.id = id;
+ }
+
+ public String getStr1() {
+ return str1;
+ }
+
+ public void setStr1(String str1) {
+ this.str1 = str1;
+ }
+
+ public Integer getNumber() {
+ return number;
+ }
+
+ public void setNumber(Integer number) {
+ this.number = number;
+ }
+
+ public boolean equals(Object o) {
+ if (this == o) return true;
+ if (!(o instanceof StrIntTestEntity)) return false;
+
+ StrIntTestEntity that = (StrIntTestEntity) o;
+
+ if (id != null ? !id.equals(that.id) : that.id != null) return false;
+ if (number != null ? !number.equals(that.number) : that.number != null) return false;
+ if (str1 != null ? !str1.equals(that.str1) : that.str1 != null) return false;
+
+ return true;
+ }
+
+ public int hashCode() {
+ int result;
+ result = (id != null ? id.hashCode() : 0);
+ result = 31 * result + (str1 != null ? str1.hashCode() : 0);
+ result = 31 * result + (number != null ? number.hashCode() : 0);
+ return result;
+ }
+
+ public String toString() {
+ return "SITE(id = " + id + ", str1 = " + str1 + ", number = " + number + ")";
+ }
+}
\ No newline at end of file
Added: core/trunk/envers/src/test/java/org/jboss/envers/test/entities/StrTestEntity.java
===================================================================
--- core/trunk/envers/src/test/java/org/jboss/envers/test/entities/StrTestEntity.java (rev 0)
+++ core/trunk/envers/src/test/java/org/jboss/envers/test/entities/StrTestEntity.java 2008-10-27 18:56:31 UTC (rev 15406)
@@ -0,0 +1,71 @@
+package org.jboss.envers.test.entities;
+
+import org.jboss.envers.Versioned;
+
+import javax.persistence.Entity;
+import javax.persistence.Id;
+import javax.persistence.GeneratedValue;
+
+/**
+ * @author Adam Warski (adam at warski dot org)
+ */
+ at Entity
+public class StrTestEntity {
+ @Id
+ @GeneratedValue
+ private Integer id;
+
+ @Versioned
+ private String str;
+
+ public StrTestEntity() {
+ }
+
+ public StrTestEntity(String str, Integer id) {
+ this.str = str;
+ this.id = id;
+ }
+
+ public StrTestEntity(String str) {
+ this.str = str;
+ }
+
+ public Integer getId() {
+ return id;
+ }
+
+ public void setId(Integer id) {
+ this.id = id;
+ }
+
+ public String getStr() {
+ return str;
+ }
+
+ public void setStr(String str) {
+ this.str = str;
+ }
+
+ public boolean equals(Object o) {
+ if (this == o) return true;
+ if (!(o instanceof StrTestEntity)) return false;
+
+ StrTestEntity that = (StrTestEntity) o;
+
+ if (id != null ? !id.equals(that.id) : that.id != null) return false;
+ if (str != null ? !str.equals(that.str) : that.str != null) return false;
+
+ return true;
+ }
+
+ public int hashCode() {
+ int result;
+ result = (id != null ? id.hashCode() : 0);
+ result = 31 * result + (str != null ? str.hashCode() : 0);
+ return result;
+ }
+
+ public String toString() {
+ return "STE(id = " + id + ", str = " + str + ")";
+ }
+}
\ No newline at end of file
Added: core/trunk/envers/src/test/java/org/jboss/envers/test/entities/UnversionedEntity.java
===================================================================
--- core/trunk/envers/src/test/java/org/jboss/envers/test/entities/UnversionedEntity.java (rev 0)
+++ core/trunk/envers/src/test/java/org/jboss/envers/test/entities/UnversionedEntity.java 2008-10-27 18:56:31 UTC (rev 15406)
@@ -0,0 +1,86 @@
+package org.jboss.envers.test.entities;
+
+import org.jboss.envers.Versioned;
+import org.jboss.envers.Unversioned;
+
+import javax.persistence.Id;
+import javax.persistence.Basic;
+import javax.persistence.Entity;
+import javax.persistence.GeneratedValue;
+
+/**
+ * @author Adam Warski (adam at warski dot org)
+ */
+ at Entity
+ at Versioned
+public class UnversionedEntity {
+ @Id
+ @GeneratedValue
+ private Integer id;
+
+ @Basic
+ private String data1;
+
+ @Basic
+ @Unversioned
+ private String data2;
+
+ public UnversionedEntity() {
+ }
+
+ public UnversionedEntity(String data1, String data2) {
+ this.data1 = data1;
+ this.data2 = data2;
+ }
+
+ public UnversionedEntity(Integer id, String data1, String data2) {
+ this.id = id;
+ this.data1 = data1;
+ this.data2 = data2;
+ }
+
+ public Integer getId() {
+ return id;
+ }
+
+ public void setId(Integer id) {
+ this.id = id;
+ }
+
+ public String getData1() {
+ return data1;
+ }
+
+ public void setData1(String data1) {
+ this.data1 = data1;
+ }
+
+ public String getData2() {
+ return data2;
+ }
+
+ public void setData2(String data2) {
+ this.data2 = data2;
+ }
+
+ public boolean equals(Object o) {
+ if (this == o) return true;
+ if (!(o instanceof UnversionedEntity)) return false;
+
+ UnversionedEntity that = (UnversionedEntity) o;
+
+ if (data1 != null ? !data1.equals(that.data1) : that.data1 != null) return false;
+ if (data2 != null ? !data2.equals(that.data2) : that.data2 != null) return false;
+ if (id != null ? !id.equals(that.id) : that.id != null) return false;
+
+ return true;
+ }
+
+ public int hashCode() {
+ int result;
+ result = (id != null ? id.hashCode() : 0);
+ result = 31 * result + (data1 != null ? data1.hashCode() : 0);
+ result = 31 * result + (data2 != null ? data2.hashCode() : 0);
+ return result;
+ }
+}
Added: core/trunk/envers/src/test/java/org/jboss/envers/test/entities/UnversionedStrTestEntity.java
===================================================================
--- core/trunk/envers/src/test/java/org/jboss/envers/test/entities/UnversionedStrTestEntity.java (rev 0)
+++ core/trunk/envers/src/test/java/org/jboss/envers/test/entities/UnversionedStrTestEntity.java 2008-10-27 18:56:31 UTC (rev 15406)
@@ -0,0 +1,70 @@
+package org.jboss.envers.test.entities;
+
+import org.jboss.envers.Versioned;
+
+import javax.persistence.Entity;
+import javax.persistence.Id;
+import javax.persistence.GeneratedValue;
+
+/**
+ * @author Adam Warski (adam at warski dot org)
+ */
+ at Entity
+public class UnversionedStrTestEntity {
+ @Id
+ @GeneratedValue
+ private Integer id;
+
+ private String str;
+
+ public UnversionedStrTestEntity() {
+ }
+
+ public UnversionedStrTestEntity(String str, Integer id) {
+ this.str = str;
+ this.id = id;
+ }
+
+ public UnversionedStrTestEntity(String str) {
+ this.str = str;
+ }
+
+ public Integer getId() {
+ return id;
+ }
+
+ public void setId(Integer id) {
+ this.id = id;
+ }
+
+ public String getStr() {
+ return str;
+ }
+
+ public void setStr(String str) {
+ this.str = str;
+ }
+
+ public boolean equals(Object o) {
+ if (this == o) return true;
+ if (!(o instanceof UnversionedStrTestEntity)) return false;
+
+ UnversionedStrTestEntity that = (UnversionedStrTestEntity) o;
+
+ if (id != null ? !id.equals(that.id) : that.id != null) return false;
+ if (str != null ? !str.equals(that.str) : that.str != null) return false;
+
+ return true;
+ }
+
+ public int hashCode() {
+ int result;
+ result = (id != null ? id.hashCode() : 0);
+ result = 31 * result + (str != null ? str.hashCode() : 0);
+ return result;
+ }
+
+ public String toString() {
+ return "USTE(id = " + id + ", str = " + str + ")";
+ }
+}
\ No newline at end of file
Added: core/trunk/envers/src/test/java/org/jboss/envers/test/entities/collection/EnumSetEntity.java
===================================================================
--- core/trunk/envers/src/test/java/org/jboss/envers/test/entities/collection/EnumSetEntity.java (rev 0)
+++ core/trunk/envers/src/test/java/org/jboss/envers/test/entities/collection/EnumSetEntity.java 2008-10-27 18:56:31 UTC (rev 15406)
@@ -0,0 +1,79 @@
+package org.jboss.envers.test.entities.collection;
+
+import org.jboss.envers.Versioned;
+import org.hibernate.annotations.CollectionOfElements;
+
+import javax.persistence.*;
+import java.util.Set;
+import java.util.HashSet;
+
+/**
+ * @author Adam Warski (adam at warski dot org)
+ */
+ at Entity
+public class EnumSetEntity {
+ public static enum E1 { X, Y }
+ public static enum E2 { A, B }
+
+ @Id
+ @GeneratedValue
+ private Integer id;
+
+ @Versioned
+ @CollectionOfElements
+ @Enumerated(EnumType.STRING)
+ private Set<E1> enums1;
+
+ @Versioned
+ @CollectionOfElements
+ @Enumerated(EnumType.ORDINAL)
+ private Set<E2> enums2;
+
+ public EnumSetEntity() {
+ enums1 = new HashSet<E1>();
+ enums2 = new HashSet<E2>();
+ }
+
+ public Integer getId() {
+ return id;
+ }
+
+ public void setId(Integer id) {
+ this.id = id;
+ }
+
+ public Set<E1> getEnums1() {
+ return enums1;
+ }
+
+ public void setEnums1(Set<E1> enums1) {
+ this.enums1 = enums1;
+ }
+
+ public Set<E2> getEnums2() {
+ return enums2;
+ }
+
+ public void setEnums2(Set<E2> enums2) {
+ this.enums2 = enums2;
+ }
+
+ public boolean equals(Object o) {
+ if (this == o) return true;
+ if (!(o instanceof EnumSetEntity)) return false;
+
+ EnumSetEntity that = (EnumSetEntity) o;
+
+ if (id != null ? !id.equals(that.id) : that.id != null) return false;
+
+ return true;
+ }
+
+ public int hashCode() {
+ return (id != null ? id.hashCode() : 0);
+ }
+
+ public String toString() {
+ return "ESE(id = " + id + ", enums1 = " + enums1 + ", enums2 = " + enums2 + ")";
+ }
+}
\ No newline at end of file
Added: core/trunk/envers/src/test/java/org/jboss/envers/test/entities/collection/StringListEntity.java
===================================================================
--- core/trunk/envers/src/test/java/org/jboss/envers/test/entities/collection/StringListEntity.java (rev 0)
+++ core/trunk/envers/src/test/java/org/jboss/envers/test/entities/collection/StringListEntity.java 2008-10-27 18:56:31 UTC (rev 15406)
@@ -0,0 +1,65 @@
+package org.jboss.envers.test.entities.collection;
+
+import org.jboss.envers.Versioned;
+import org.hibernate.annotations.CollectionOfElements;
+import org.hibernate.annotations.IndexColumn;
+
+import javax.persistence.Entity;
+import javax.persistence.Id;
+import javax.persistence.GeneratedValue;
+import java.util.List;
+import java.util.ArrayList;
+
+/**
+ * @author Adam Warski (adam at warski dot org)
+ */
+ at Entity
+public class StringListEntity {
+ @Id
+ @GeneratedValue
+ private Integer id;
+
+ @Versioned
+ @CollectionOfElements
+ @IndexColumn(name = "list_index")
+ private List<String> strings;
+
+ public StringListEntity() {
+ strings = new ArrayList<String>();
+ }
+
+ public Integer getId() {
+ return id;
+ }
+
+ public void setId(Integer id) {
+ this.id = id;
+ }
+
+ public List<String> getStrings() {
+ return strings;
+ }
+
+ public void setStrings(List<String> strings) {
+ this.strings = strings;
+ }
+
+ public boolean equals(Object o) {
+ if (this == o) return true;
+ if (!(o instanceof StringListEntity)) return false;
+
+ StringListEntity that = (StringListEntity) o;
+
+ if (id != null ? !id.equals(that.id) : that.id != null) return false;
+
+ return true;
+ }
+
+ public int hashCode() {
+ return (id != null ? id.hashCode() : 0);
+ }
+
+ public String toString() {
+ return "SLE(id = " + id + ", strings = " + strings + ")";
+ }
+}
\ No newline at end of file
Added: core/trunk/envers/src/test/java/org/jboss/envers/test/entities/collection/StringMapEntity.java
===================================================================
--- core/trunk/envers/src/test/java/org/jboss/envers/test/entities/collection/StringMapEntity.java (rev 0)
+++ core/trunk/envers/src/test/java/org/jboss/envers/test/entities/collection/StringMapEntity.java 2008-10-27 18:56:31 UTC (rev 15406)
@@ -0,0 +1,63 @@
+package org.jboss.envers.test.entities.collection;
+
+import org.jboss.envers.Versioned;
+import org.hibernate.annotations.CollectionOfElements;
+
+import javax.persistence.Entity;
+import javax.persistence.Id;
+import javax.persistence.GeneratedValue;
+import java.util.Map;
+import java.util.HashMap;
+
+/**
+ * @author Adam Warski (adam at warski dot org)
+ */
+ at Entity
+public class StringMapEntity {
+ @Id
+ @GeneratedValue
+ private Integer id;
+
+ @Versioned
+ @CollectionOfElements
+ private Map<String, String> strings;
+
+ public StringMapEntity() {
+ strings = new HashMap<String, String>();
+ }
+
+ public Integer getId() {
+ return id;
+ }
+
+ public void setId(Integer id) {
+ this.id = id;
+ }
+
+ public Map<String, String> getStrings() {
+ return strings;
+ }
+
+ public void setStrings(Map<String, String> strings) {
+ this.strings = strings;
+ }
+
+ public boolean equals(Object o) {
+ if (this == o) return true;
+ if (!(o instanceof StringMapEntity)) return false;
+
+ StringMapEntity that = (StringMapEntity) o;
+
+ if (id != null ? !id.equals(that.id) : that.id != null) return false;
+
+ return true;
+ }
+
+ public int hashCode() {
+ return (id != null ? id.hashCode() : 0);
+ }
+
+ public String toString() {
+ return "SME(id = " + id + ", strings = " + strings + ")";
+ }
+}
\ No newline at end of file
Added: core/trunk/envers/src/test/java/org/jboss/envers/test/entities/collection/StringSetEntity.java
===================================================================
--- core/trunk/envers/src/test/java/org/jboss/envers/test/entities/collection/StringSetEntity.java (rev 0)
+++ core/trunk/envers/src/test/java/org/jboss/envers/test/entities/collection/StringSetEntity.java 2008-10-27 18:56:31 UTC (rev 15406)
@@ -0,0 +1,63 @@
+package org.jboss.envers.test.entities.collection;
+
+import org.jboss.envers.Versioned;
+import org.hibernate.annotations.CollectionOfElements;
+
+import javax.persistence.Entity;
+import javax.persistence.Id;
+import javax.persistence.GeneratedValue;
+import java.util.Set;
+import java.util.HashSet;
+
+/**
+ * @author Adam Warski (adam at warski dot org)
+ */
+ at Entity
+public class StringSetEntity {
+ @Id
+ @GeneratedValue
+ private Integer id;
+
+ @Versioned
+ @CollectionOfElements
+ private Set<String> strings;
+
+ public StringSetEntity() {
+ strings = new HashSet<String>();
+ }
+
+ public Integer getId() {
+ return id;
+ }
+
+ public void setId(Integer id) {
+ this.id = id;
+ }
+
+ public Set<String> getStrings() {
+ return strings;
+ }
+
+ public void setStrings(Set<String> strings) {
+ this.strings = strings;
+ }
+
+ public boolean equals(Object o) {
+ if (this == o) return true;
+ if (!(o instanceof StringSetEntity)) return false;
+
+ StringSetEntity that = (StringSetEntity) o;
+
+ if (id != null ? !id.equals(that.id) : that.id != null) return false;
+
+ return true;
+ }
+
+ public int hashCode() {
+ return (id != null ? id.hashCode() : 0);
+ }
+
+ public String toString() {
+ return "SSE(id = " + id + ", strings = " + strings + ")";
+ }
+}
\ No newline at end of file
Added: core/trunk/envers/src/test/java/org/jboss/envers/test/entities/components/Component1.java
===================================================================
--- core/trunk/envers/src/test/java/org/jboss/envers/test/entities/components/Component1.java (rev 0)
+++ core/trunk/envers/src/test/java/org/jboss/envers/test/entities/components/Component1.java 2008-10-27 18:56:31 UTC (rev 15406)
@@ -0,0 +1,57 @@
+package org.jboss.envers.test.entities.components;
+
+/**
+ * @author Adam Warski (adam at warski dot org)
+ */
+public class Component1 {
+ private String str1;
+
+ private String str2;
+
+ public Component1(String str1, String str2) {
+ this.str1 = str1;
+ this.str2 = str2;
+ }
+
+ public Component1() {
+ }
+
+ public String getStr2() {
+ return str2;
+ }
+
+ public void setStr2(String str2) {
+ this.str2 = str2;
+ }
+
+ public String getStr1() {
+ return str1;
+ }
+
+ public void setStr1(String str1) {
+ this.str1 = str1;
+ }
+
+ public boolean equals(Object o) {
+ if (this == o) return true;
+ if (!(o instanceof Component1)) return false;
+
+ Component1 that = (Component1) o;
+
+ if (str1 != null ? !str1.equals(that.str1) : that.str1 != null) return false;
+ if (str2 != null ? !str2.equals(that.str2) : that.str2 != null) return false;
+
+ return true;
+ }
+
+ public int hashCode() {
+ int result;
+ result = (str1 != null ? str1.hashCode() : 0);
+ result = 31 * result + (str2 != null ? str2.hashCode() : 0);
+ return result;
+ }
+
+ public String toString() {
+ return "Comp1(str1 = " + str1 + ", " + str2 + ")";
+ }
+}
Added: core/trunk/envers/src/test/java/org/jboss/envers/test/entities/components/Component2.java
===================================================================
--- core/trunk/envers/src/test/java/org/jboss/envers/test/entities/components/Component2.java (rev 0)
+++ core/trunk/envers/src/test/java/org/jboss/envers/test/entities/components/Component2.java 2008-10-27 18:56:31 UTC (rev 15406)
@@ -0,0 +1,57 @@
+package org.jboss.envers.test.entities.components;
+
+/**
+ * @author Adam Warski (adam at warski dot org)
+ */
+public class Component2 {
+ private String str5;
+
+ private String str6;
+
+ public Component2(String str5, String str6) {
+ this.str5 = str5;
+ this.str6 = str6;
+ }
+
+ public Component2() {
+ }
+
+ public String getStr5() {
+ return str5;
+ }
+
+ public void setStr5(String str5) {
+ this.str5 = str5;
+ }
+
+ public String getStr6() {
+ return str6;
+ }
+
+ public void setStr6(String str6) {
+ this.str6 = str6;
+ }
+
+ public boolean equals(Object o) {
+ if (this == o) return true;
+ if (!(o instanceof Component2)) return false;
+
+ Component2 that = (Component2) o;
+
+ if (str5 != null ? !str5.equals(that.str5) : that.str5 != null) return false;
+ if (str6 != null ? !str6.equals(that.str6) : that.str6 != null) return false;
+
+ return true;
+ }
+
+ public int hashCode() {
+ int result;
+ result = (str5 != null ? str5.hashCode() : 0);
+ result = 31 * result + (str6 != null ? str6.hashCode() : 0);
+ return result;
+ }
+
+ public String toString() {
+ return "Comp2(str1 = " + str5 + ", " + str6 + ")";
+ }
+}
Added: core/trunk/envers/src/test/java/org/jboss/envers/test/entities/components/ComponentTestEntity.java
===================================================================
--- core/trunk/envers/src/test/java/org/jboss/envers/test/entities/components/ComponentTestEntity.java (rev 0)
+++ core/trunk/envers/src/test/java/org/jboss/envers/test/entities/components/ComponentTestEntity.java 2008-10-27 18:56:31 UTC (rev 15406)
@@ -0,0 +1,89 @@
+package org.jboss.envers.test.entities.components;
+
+import org.jboss.envers.Versioned;
+
+import javax.persistence.Entity;
+import javax.persistence.Id;
+import javax.persistence.GeneratedValue;
+import javax.persistence.Embedded;
+
+/**
+ * @author Adam Warski (adam at warski dot org)
+ */
+ at Entity
+public class ComponentTestEntity {
+ @Id
+ @GeneratedValue
+ private Integer id;
+
+ @Embedded
+ @Versioned
+ private Component1 comp1;
+
+ @Embedded
+ private Component2 comp2;
+
+ public ComponentTestEntity() {
+ }
+
+ public ComponentTestEntity(Integer id, Component1 comp1, Component2 comp2) {
+ this.id = id;
+ this.comp1 = comp1;
+ this.comp2 = comp2;
+ }
+
+ public ComponentTestEntity(Component1 comp1, Component2 comp2) {
+ this.comp1 = comp1;
+ this.comp2 = comp2;
+ }
+
+ public Integer getId() {
+ return id;
+ }
+
+ public void setId(Integer id) {
+ this.id = id;
+ }
+
+ public Component1 getComp1() {
+ return comp1;
+ }
+
+ public void setComp1(Component1 comp1) {
+ this.comp1 = comp1;
+ }
+
+ public Component2 getComp2() {
+ return comp2;
+ }
+
+ public void setComp2(Component2 comp2) {
+ this.comp2 = comp2;
+ }
+
+ public boolean equals(Object o) {
+ if (this == o) return true;
+ if (!(o instanceof ComponentTestEntity)) return false;
+
+ ComponentTestEntity that = (ComponentTestEntity) o;
+
+ if (comp1 != null ? !comp1.equals(that.comp1) : that.comp1 != null) return false;
+ if (comp2 != null ? !comp2.equals(that.comp2) : that.comp2 != null) return false;
+ if (id != null ? !id.equals(that.id) : that.id != null) return false;
+
+ return true;
+ }
+
+ public int hashCode() {
+ int result;
+ result = (id != null ? id.hashCode() : 0);
+ result = 31 * result + (comp1 != null ? comp1.hashCode() : 0);
+ result = 31 * result + (comp2 != null ? comp2.hashCode() : 0);
+ return result;
+ }
+
+ public String toString() {
+ return "CTE(id = " + id + ", comp1 = " + comp1 + ", comp2 = " + comp2 + ")";
+ }
+}
+
Added: core/trunk/envers/src/test/java/org/jboss/envers/test/entities/customtype/Component.java
===================================================================
--- core/trunk/envers/src/test/java/org/jboss/envers/test/entities/customtype/Component.java (rev 0)
+++ core/trunk/envers/src/test/java/org/jboss/envers/test/entities/customtype/Component.java 2008-10-27 18:56:31 UTC (rev 15406)
@@ -0,0 +1,54 @@
+package org.jboss.envers.test.entities.customtype;
+
+import java.io.Serializable;
+
+/**
+ * @author Adam Warski (adam at warski dot org)
+ */
+public class Component implements Serializable {
+ private String prop1;
+ private int prop2;
+
+ public Component(String prop1, int prop2) {
+ this.prop1 = prop1;
+ this.prop2 = prop2;
+ }
+
+ public Component() {
+ }
+
+ public String getProp1() {
+ return prop1;
+ }
+
+ public void setProp1(String prop1) {
+ this.prop1 = prop1;
+ }
+
+ public int getProp2() {
+ return prop2;
+ }
+
+ public void setProp2(int prop2) {
+ this.prop2 = prop2;
+ }
+
+ public boolean equals(Object o) {
+ if (this == o) return true;
+ if (!(o instanceof Component)) return false;
+
+ Component that = (Component) o;
+
+ if (prop2 != that.prop2) return false;
+ if (prop1 != null ? !prop1.equals(that.prop1) : that.prop1 != null) return false;
+
+ return true;
+ }
+
+ public int hashCode() {
+ int result;
+ result = (prop1 != null ? prop1.hashCode() : 0);
+ result = 31 * result + prop2;
+ return result;
+ }
+}
Added: core/trunk/envers/src/test/java/org/jboss/envers/test/entities/customtype/CompositeCustomTypeEntity.java
===================================================================
--- core/trunk/envers/src/test/java/org/jboss/envers/test/entities/customtype/CompositeCustomTypeEntity.java (rev 0)
+++ core/trunk/envers/src/test/java/org/jboss/envers/test/entities/customtype/CompositeCustomTypeEntity.java 2008-10-27 18:56:31 UTC (rev 15406)
@@ -0,0 +1,74 @@
+package org.jboss.envers.test.entities.customtype;
+
+import org.jboss.envers.Versioned;
+import org.hibernate.annotations.TypeDef;
+import org.hibernate.annotations.Type;
+import org.hibernate.annotations.Columns;
+
+import javax.persistence.Entity;
+import javax.persistence.Id;
+import javax.persistence.GeneratedValue;
+import javax.persistence.Column;
+
+/**
+ * @author Adam Warski (adam at warski dot org)
+ */
+ at Entity
+ at TypeDef(name = "comp", typeClass = CompositeTestUserType.class)
+public class CompositeCustomTypeEntity {
+ @Id
+ @GeneratedValue
+ private Integer id;
+
+ @Versioned
+ @Type(type = "comp")
+ @Columns(columns = { @Column(name = "str"), @Column(name = "num") })
+ private Component component;
+
+ public CompositeCustomTypeEntity() {
+ }
+
+ public CompositeCustomTypeEntity(Integer id, Component component) {
+ this.id = id;
+ this.component = component;
+ }
+
+ public Integer getId() {
+ return id;
+ }
+
+ public void setId(Integer id) {
+ this.id = id;
+ }
+
+ public Component getComponent() {
+ return component;
+ }
+
+ public void setComponent(Component component) {
+ this.component = component;
+ }
+
+ public boolean equals(Object o) {
+ if (this == o) return true;
+ if (!(o instanceof CompositeCustomTypeEntity)) return false;
+
+ CompositeCustomTypeEntity that = (CompositeCustomTypeEntity) o;
+
+ if (component != null ? !component.equals(that.component) : that.component != null) return false;
+ if (id != null ? !id.equals(that.id) : that.id != null) return false;
+
+ return true;
+ }
+
+ public int hashCode() {
+ int result;
+ result = (id != null ? id.hashCode() : 0);
+ result = 31 * result + (component != null ? component.hashCode() : 0);
+ return result;
+ }
+
+ public String toString() {
+ return "CCTE(id = " + id + ", component = " + component + ")";
+ }
+}
Added: core/trunk/envers/src/test/java/org/jboss/envers/test/entities/customtype/CompositeTestUserType.java
===================================================================
--- core/trunk/envers/src/test/java/org/jboss/envers/test/entities/customtype/CompositeTestUserType.java (rev 0)
+++ core/trunk/envers/src/test/java/org/jboss/envers/test/entities/customtype/CompositeTestUserType.java 2008-10-27 18:56:31 UTC (rev 15406)
@@ -0,0 +1,117 @@
+package org.jboss.envers.test.entities.customtype;
+
+import org.hibernate.HibernateException;
+import org.hibernate.Hibernate;
+import org.hibernate.usertype.CompositeUserType;
+import org.hibernate.engine.SessionImplementor;
+import org.hibernate.type.Type;
+
+import java.sql.ResultSet;
+import java.sql.SQLException;
+import java.sql.PreparedStatement;
+import java.io.Serializable;
+
+/**
+ * @author Andrew DePue
+ * @author Adam Warski (adam at warski dot org)
+ */
+public class CompositeTestUserType implements CompositeUserType {
+ public String[] getPropertyNames() {
+ return new String[] { "prop1", "prop2" };
+ }
+
+ public Type[] getPropertyTypes() {
+ return new Type[] { Hibernate.STRING, Hibernate.INTEGER };
+ }
+
+ public Object getPropertyValue(final Object component, final int property) throws HibernateException {
+ Component comp = (Component) component;
+ if (property == 0) {
+ return comp.getProp1();
+ } else {
+ return comp.getProp2();
+ }
+ }
+
+ public void setPropertyValue(final Object component, final int property, final Object value) throws HibernateException {
+ Component comp = (Component) component;
+ if (property == 0) {
+ comp.setProp1((String) value);
+ } else {
+ comp.setProp2((Integer) value);
+ }
+ }
+
+ public Class returnedClass() {
+ return Component.class;
+ }
+
+ public boolean equals(final Object x, final Object y) throws HibernateException {
+ //noinspection ObjectEquality
+ if (x == y) {
+ return true;
+ }
+
+ if (x == null || y == null) {
+ return false;
+ }
+
+ return x.equals(y);
+ }
+
+ public int hashCode(final Object x) throws HibernateException {
+ return x.hashCode();
+ }
+
+ public Object nullSafeGet(final ResultSet rs, final String[] names,
+ final SessionImplementor session,
+ final Object owner) throws HibernateException, SQLException {
+ if (rs.wasNull()) {
+ return null;
+ }
+ final String prop1 = rs.getString(names[0]);
+ if (prop1 == null) {
+ return null;
+ }
+ final int prop2 = rs.getInt(names[1]);
+
+ return new Component(prop1, prop2);
+ }
+
+ public void nullSafeSet(final PreparedStatement st, final Object value,
+ final int index, final SessionImplementor session)
+ throws HibernateException, SQLException
+ {
+ if (value == null) {
+ st.setNull(index, Hibernate.STRING.sqlType());
+ st.setNull(index + 1, Hibernate.INTEGER.sqlType());
+ } else {
+ final Component comp = (Component) value;
+ st.setString(index, comp.getProp1());
+ st.setInt(index + 1, comp.getProp2());
+ }
+ }
+
+ public Object deepCopy(final Object value) throws HibernateException {
+ Component comp = (Component) value;
+ return new Component(comp.getProp1(), comp.getProp2());
+ }
+
+ public boolean isMutable() {
+ return true;
+ }
+
+ public Serializable disassemble(final Object value, final SessionImplementor session) throws HibernateException {
+ return (Serializable) value;
+ }
+
+ public Object assemble(final Serializable cached, final SessionImplementor session,
+ final Object owner) throws HibernateException {
+ return cached;
+ }
+
+ public Object replace(Object original, Object target,
+ SessionImplementor session, Object owner) throws HibernateException {
+ return original;
+ }
+}
\ No newline at end of file
Added: core/trunk/envers/src/test/java/org/jboss/envers/test/entities/customtype/ParametrizedCustomTypeEntity.java
===================================================================
--- core/trunk/envers/src/test/java/org/jboss/envers/test/entities/customtype/ParametrizedCustomTypeEntity.java (rev 0)
+++ core/trunk/envers/src/test/java/org/jboss/envers/test/entities/customtype/ParametrizedCustomTypeEntity.java 2008-10-27 18:56:31 UTC (rev 15406)
@@ -0,0 +1,73 @@
+package org.jboss.envers.test.entities.customtype;
+
+import org.jboss.envers.Versioned;
+import org.hibernate.annotations.TypeDef;
+import org.hibernate.annotations.Type;
+import org.hibernate.annotations.Parameter;
+
+import javax.persistence.Entity;
+import javax.persistence.Id;
+import javax.persistence.GeneratedValue;
+
+/**
+ * @author Adam Warski (adam at warski dot org)
+ */
+ at Entity
+ at TypeDef(name = "param", typeClass = ParametrizedTestUserType.class,
+ parameters = { @Parameter(name="param1", value = "x"), @Parameter(name="param2", value = "y") })
+public class ParametrizedCustomTypeEntity {
+ @Id
+ @GeneratedValue
+ private Integer id;
+
+ @Versioned
+ @Type(type = "param")
+ private String str;
+
+ public ParametrizedCustomTypeEntity() {
+ }
+
+ public ParametrizedCustomTypeEntity(Integer id, String str) {
+ this.id = id;
+ this.str = str;
+ }
+
+ public Integer getId() {
+ return id;
+ }
+
+ public void setId(Integer id) {
+ this.id = id;
+ }
+
+ public String getStr() {
+ return str;
+ }
+
+ public void setStr(String str) {
+ this.str = str;
+ }
+
+ public boolean equals(Object o) {
+ if (this == o) return true;
+ if (!(o instanceof ParametrizedCustomTypeEntity)) return false;
+
+ ParametrizedCustomTypeEntity that = (ParametrizedCustomTypeEntity) o;
+
+ if (id != null ? !id.equals(that.id) : that.id != null) return false;
+ if (str != null ? !str.equals(that.str) : that.str != null) return false;
+
+ return true;
+ }
+
+ public int hashCode() {
+ int result;
+ result = (id != null ? id.hashCode() : 0);
+ result = 31 * result + (str != null ? str.hashCode() : 0);
+ return result;
+ }
+
+ public String toString() {
+ return "PCTE(id = " + id + ", str = " + str + ")";
+ }
+}
\ No newline at end of file
Added: core/trunk/envers/src/test/java/org/jboss/envers/test/entities/customtype/ParametrizedTestUserType.java
===================================================================
--- core/trunk/envers/src/test/java/org/jboss/envers/test/entities/customtype/ParametrizedTestUserType.java (rev 0)
+++ core/trunk/envers/src/test/java/org/jboss/envers/test/entities/customtype/ParametrizedTestUserType.java 2008-10-27 18:56:31 UTC (rev 15406)
@@ -0,0 +1,92 @@
+package org.jboss.envers.test.entities.customtype;
+
+import java.io.Serializable;
+import java.sql.PreparedStatement;
+import java.sql.ResultSet;
+import java.sql.SQLException;
+import java.sql.Types;
+import java.util.Properties;
+
+import org.hibernate.HibernateException;
+import org.hibernate.Hibernate;
+import org.hibernate.usertype.ParameterizedType;
+import org.hibernate.usertype.UserType;
+
+/**
+ * @author Adam Warski (adam at warski dot org)
+ */
+public class ParametrizedTestUserType implements UserType, ParameterizedType {
+ private static final int[] TYPES = new int[] { Types.VARCHAR };
+
+ private String param1;
+ private String param2;
+
+ public void setParameterValues(Properties parameters) {
+ param1 = parameters.getProperty("param1");
+ param2 = parameters.getProperty("param2");
+ }
+
+ public Class returnedClass() {
+ return String.class;
+ }
+
+ public Object nullSafeGet(ResultSet rs, String[] names, Object owner) throws HibernateException, SQLException {
+ return Hibernate.STRING.nullSafeGet(rs, names[0]);
+ }
+
+ public void nullSafeSet(PreparedStatement st, Object value, int index) throws HibernateException, SQLException {
+ if (value != null) {
+ String v = (String) value;
+ if (!v.startsWith(param1)) {
+ v = param1 + v;
+ }
+ if (!v.endsWith(param2)) {
+ v = v + param2;
+ }
+ Hibernate.STRING.nullSafeSet(st, v, index);
+ } else {
+ Hibernate.STRING.nullSafeSet(st, value, index);
+ }
+ }
+
+ public int[] sqlTypes() {
+ return TYPES;
+ }
+
+ public Object assemble(Serializable cached, Object owner) throws HibernateException {
+ return cached;
+ }
+
+ public Object deepCopy(Object value) throws HibernateException {
+ return value;
+ }
+
+ public Serializable disassemble(Object value) throws HibernateException {
+ return (Serializable) value;
+ }
+
+ public boolean equals(Object x, Object y) throws HibernateException {
+ //noinspection ObjectEquality
+ if (x == y) {
+ return true;
+ }
+
+ if (x == null || y == null) {
+ return false;
+ }
+
+ return x.equals(y);
+ }
+
+ public int hashCode(Object x) throws HibernateException {
+ return x.hashCode();
+ }
+
+ public boolean isMutable() {
+ return false;
+ }
+
+ public Object replace(Object original, Object target, Object owner) throws HibernateException {
+ return original;
+ }
+}
Added: core/trunk/envers/src/test/java/org/jboss/envers/test/entities/ids/EmbId.java
===================================================================
--- core/trunk/envers/src/test/java/org/jboss/envers/test/entities/ids/EmbId.java (rev 0)
+++ core/trunk/envers/src/test/java/org/jboss/envers/test/entities/ids/EmbId.java 2008-10-27 18:56:31 UTC (rev 15406)
@@ -0,0 +1,60 @@
+package org.jboss.envers.test.entities.ids;
+
+import javax.persistence.Embeddable;
+import java.io.Serializable;
+
+/**
+ * @author Adam Warski (adam at warski dot org)
+ */
+ at Embeddable
+public class EmbId implements Serializable {
+ private Integer x;
+ private Integer y;
+
+ public EmbId() {
+ }
+
+ public EmbId(Integer x, Integer y) {
+ this.x = x;
+ this.y = y;
+ }
+
+ public Integer getX() {
+ return x;
+ }
+
+ public void setX(Integer x) {
+ this.x = x;
+ }
+
+ public Integer getY() {
+ return y;
+ }
+
+ public void setY(Integer y) {
+ this.y = y;
+ }
+
+ public boolean equals(Object o) {
+ if (this == o) return true;
+ if (!(o instanceof EmbId)) return false;
+
+ EmbId embId = (EmbId) o;
+
+ if (x != null ? !x.equals(embId.x) : embId.x != null) return false;
+ if (y != null ? !y.equals(embId.y) : embId.y != null) return false;
+
+ return true;
+ }
+
+ public int hashCode() {
+ int result;
+ result = (x != null ? x.hashCode() : 0);
+ result = 31 * result + (y != null ? y.hashCode() : 0);
+ return result;
+ }
+
+ public String toString() {
+ return "EmbId(" + x + ", " + y + ")";
+ }
+}
\ No newline at end of file
Added: core/trunk/envers/src/test/java/org/jboss/envers/test/entities/ids/EmbIdTestEntity.java
===================================================================
--- core/trunk/envers/src/test/java/org/jboss/envers/test/entities/ids/EmbIdTestEntity.java (rev 0)
+++ core/trunk/envers/src/test/java/org/jboss/envers/test/entities/ids/EmbIdTestEntity.java 2008-10-27 18:56:31 UTC (rev 15406)
@@ -0,0 +1,66 @@
+package org.jboss.envers.test.entities.ids;
+
+import org.jboss.envers.Versioned;
+import org.jboss.envers.test.entities.ids.EmbId;
+
+import javax.persistence.Entity;
+import javax.persistence.EmbeddedId;
+
+/**
+ * @author Adam Warski (adam at warski dot org)
+ */
+ at Entity
+public class EmbIdTestEntity {
+ @EmbeddedId
+ private EmbId id;
+
+ @Versioned
+ private String str1;
+
+ public EmbIdTestEntity() {
+ }
+
+ public EmbIdTestEntity(String str1) {
+ this.str1 = str1;
+ }
+
+ public EmbIdTestEntity(EmbId id, String str1) {
+ this.id = id;
+ this.str1 = str1;
+ }
+
+ public EmbId getId() {
+ return id;
+ }
+
+ public void setId(EmbId id) {
+ this.id = id;
+ }
+
+ public String getStr1() {
+ return str1;
+ }
+
+ public void setStr1(String str1) {
+ this.str1 = str1;
+ }
+
+ public boolean equals(Object o) {
+ if (this == o) return true;
+ if (!(o instanceof EmbIdTestEntity)) return false;
+
+ EmbIdTestEntity that = (EmbIdTestEntity) o;
+
+ if (id != null ? !id.equals(that.id) : that.id != null) return false;
+ if (str1 != null ? !str1.equals(that.str1) : that.str1 != null) return false;
+
+ return true;
+ }
+
+ public int hashCode() {
+ int result;
+ result = (id != null ? id.hashCode() : 0);
+ result = 31 * result + (str1 != null ? str1.hashCode() : 0);
+ return result;
+ }
+}
Added: core/trunk/envers/src/test/java/org/jboss/envers/test/entities/ids/MulId.java
===================================================================
--- core/trunk/envers/src/test/java/org/jboss/envers/test/entities/ids/MulId.java (rev 0)
+++ core/trunk/envers/src/test/java/org/jboss/envers/test/entities/ids/MulId.java 2008-10-27 18:56:31 UTC (rev 15406)
@@ -0,0 +1,59 @@
+package org.jboss.envers.test.entities.ids;
+
+import java.io.Serializable;
+
+/**
+ * @author Adam Warski (adam at warski dot org)
+ */
+public class MulId implements Serializable {
+ private Integer id1;
+
+ private Integer id2;
+
+ public MulId() {
+ }
+
+ public MulId(Integer id1, Integer id2) {
+ this.id1 = id1;
+ this.id2 = id2;
+ }
+
+ public Integer getId1() {
+ return id1;
+ }
+
+ public void setId1(Integer id1) {
+ this.id1 = id1;
+ }
+
+ public Integer getId2() {
+ return id2;
+ }
+
+ public void setId2(Integer id2) {
+ this.id2 = id2;
+ }
+
+ public boolean equals(Object o) {
+ if (this == o) return true;
+ if (!(o instanceof MulId)) return false;
+
+ MulId mulId = (MulId) o;
+
+ if (id1 != null ? !id1.equals(mulId.id1) : mulId.id1 != null) return false;
+ if (id2 != null ? !id2.equals(mulId.id2) : mulId.id2 != null) return false;
+
+ return true;
+ }
+
+ public int hashCode() {
+ int result;
+ result = (id1 != null ? id1.hashCode() : 0);
+ result = 31 * result + (id2 != null ? id2.hashCode() : 0);
+ return result;
+ }
+
+ public String toString() {
+ return "MulId(" + id1 + ", " + id2 + ")";
+ }
+}
\ No newline at end of file
Added: core/trunk/envers/src/test/java/org/jboss/envers/test/entities/ids/MulIdTestEntity.java
===================================================================
--- core/trunk/envers/src/test/java/org/jboss/envers/test/entities/ids/MulIdTestEntity.java (rev 0)
+++ core/trunk/envers/src/test/java/org/jboss/envers/test/entities/ids/MulIdTestEntity.java 2008-10-27 18:56:31 UTC (rev 15406)
@@ -0,0 +1,82 @@
+package org.jboss.envers.test.entities.ids;
+
+import org.jboss.envers.Versioned;
+import org.jboss.envers.test.entities.ids.MulId;
+
+import javax.persistence.Entity;
+import javax.persistence.IdClass;
+import javax.persistence.Id;
+
+/**
+ * @author Adam Warski (adam at warski dot org)
+ */
+ at Entity
+ at IdClass(MulId.class)
+public class MulIdTestEntity {
+ @Id
+ private Integer id1;
+
+ @Id
+ private Integer id2;
+
+ @Versioned
+ private String str1;
+
+ public MulIdTestEntity() {
+ }
+
+ public MulIdTestEntity(String str1) {
+ this.str1 = str1;
+ }
+
+ public MulIdTestEntity(Integer id1, Integer id2, String str1) {
+ this.id1 = id1;
+ this.id2 = id2;
+ this.str1 = str1;
+ }
+
+ public Integer getId1() {
+ return id1;
+ }
+
+ public void setId1(Integer id1) {
+ this.id1 = id1;
+ }
+
+ public Integer getId2() {
+ return id2;
+ }
+
+ public void setId2(Integer id2) {
+ this.id2 = id2;
+ }
+
+ public String getStr1() {
+ return str1;
+ }
+
+ public void setStr1(String str1) {
+ this.str1 = str1;
+ }
+
+ public boolean equals(Object o) {
+ if (this == o) return true;
+ if (!(o instanceof MulIdTestEntity)) return false;
+
+ MulIdTestEntity that = (MulIdTestEntity) o;
+
+ if (id1 != null ? !id1.equals(that.id1) : that.id1 != null) return false;
+ if (id2 != null ? !id2.equals(that.id2) : that.id2 != null) return false;
+ if (str1 != null ? !str1.equals(that.str1) : that.str1 != null) return false;
+
+ return true;
+ }
+
+ public int hashCode() {
+ int result;
+ result = (id1 != null ? id1.hashCode() : 0);
+ result = 31 * result + (id2 != null ? id2.hashCode() : 0);
+ result = 31 * result + (str1 != null ? str1.hashCode() : 0);
+ return result;
+ }
+}
Added: core/trunk/envers/src/test/java/org/jboss/envers/test/entities/manytomany/ListOwnedEntity.java
===================================================================
--- core/trunk/envers/src/test/java/org/jboss/envers/test/entities/manytomany/ListOwnedEntity.java (rev 0)
+++ core/trunk/envers/src/test/java/org/jboss/envers/test/entities/manytomany/ListOwnedEntity.java 2008-10-27 18:56:31 UTC (rev 15406)
@@ -0,0 +1,84 @@
+package org.jboss.envers.test.entities.manytomany;
+
+import org.jboss.envers.Versioned;
+
+import javax.persistence.Entity;
+import javax.persistence.Id;
+import javax.persistence.ManyToMany;
+import java.util.List;
+
+/**
+ * Many-to-many not-owning entity
+ * @author Adam Warski (adam at warski dot org)
+ */
+ at Entity
+public class ListOwnedEntity {
+ @Id
+ private Integer id;
+
+ @Versioned
+ private String data;
+
+ @Versioned
+ @ManyToMany(mappedBy="references")
+ private List<ListOwningEntity> referencing;
+
+ public ListOwnedEntity() {
+ }
+
+ public ListOwnedEntity(Integer id, String data) {
+ this.id = id;
+ this.data = data;
+ }
+
+ public ListOwnedEntity(String data) {
+ this.data = data;
+ }
+
+ public Integer getId() {
+ return id;
+ }
+
+ public void setId(Integer id) {
+ this.id = id;
+ }
+
+ public String getData() {
+ return data;
+ }
+
+ public void setData(String data) {
+ this.data = data;
+ }
+
+ public List<ListOwningEntity> getReferencing() {
+ return referencing;
+ }
+
+ public void setReferencing(List<ListOwningEntity> referencing) {
+ this.referencing = referencing;
+ }
+
+ public boolean equals(Object o) {
+ if (this == o) return true;
+ if (!(o instanceof ListOwnedEntity)) return false;
+
+ ListOwnedEntity that = (ListOwnedEntity) o;
+
+ if (data != null ? !data.equals(that.data) : that.data != null) return false;
+ if (id != null ? !id.equals(that.id) : that.id != null) return false;
+
+ return true;
+ }
+
+ public int hashCode() {
+ int result;
+ result = (id != null ? id.hashCode() : 0);
+ result = 31 * result + (data != null ? data.hashCode() : 0);
+ return result;
+ }
+
+ public String toString() {
+ return "SetOwnedEntity(id = " + id + ", data = " + data + ")";
+ }
+}
\ No newline at end of file
Added: core/trunk/envers/src/test/java/org/jboss/envers/test/entities/manytomany/ListOwningEntity.java
===================================================================
--- core/trunk/envers/src/test/java/org/jboss/envers/test/entities/manytomany/ListOwningEntity.java (rev 0)
+++ core/trunk/envers/src/test/java/org/jboss/envers/test/entities/manytomany/ListOwningEntity.java 2008-10-27 18:56:31 UTC (rev 15406)
@@ -0,0 +1,81 @@
+package org.jboss.envers.test.entities.manytomany;
+
+import org.jboss.envers.Versioned;
+
+import javax.persistence.*;
+import java.util.List;
+
+/**
+ * Entity owning the many-to-many relation
+ * @author Adam Warski (adam at warski dot org)
+ */
+ at Entity
+public class ListOwningEntity {
+ @Id
+ private Integer id;
+
+ @Versioned
+ private String data;
+
+ @Versioned
+ @ManyToMany
+ private List<ListOwnedEntity> references;
+
+ public ListOwningEntity() { }
+
+ public ListOwningEntity(Integer id, String data) {
+ this.id = id;
+ this.data = data;
+ }
+
+ public ListOwningEntity(String data) {
+ this.data = data;
+ }
+
+ public Integer getId() {
+ return id;
+ }
+
+ public void setId(Integer id) {
+ this.id = id;
+ }
+
+ public String getData() {
+ return data;
+ }
+
+ public void setData(String data) {
+ this.data = data;
+ }
+
+ public List<ListOwnedEntity> getReferences() {
+ return references;
+ }
+
+ public void setReferences(List<ListOwnedEntity> references) {
+ this.references = references;
+ }
+
+ public boolean equals(Object o) {
+ if (this == o) return true;
+ if (!(o instanceof ListOwningEntity)) return false;
+
+ ListOwningEntity that = (ListOwningEntity) o;
+
+ if (data != null ? !data.equals(that.data) : that.data != null) return false;
+ if (id != null ? !id.equals(that.id) : that.id != null) return false;
+
+ return true;
+ }
+
+ public int hashCode() {
+ int result;
+ result = (id != null ? id.hashCode() : 0);
+ result = 31 * result + (data != null ? data.hashCode() : 0);
+ return result;
+ }
+
+ public String toString() {
+ return "SetOwningEntity(id = " + id + ", data = " + data + ")";
+ }
+}
\ No newline at end of file
Added: core/trunk/envers/src/test/java/org/jboss/envers/test/entities/manytomany/MapOwnedEntity.java
===================================================================
--- core/trunk/envers/src/test/java/org/jboss/envers/test/entities/manytomany/MapOwnedEntity.java (rev 0)
+++ core/trunk/envers/src/test/java/org/jboss/envers/test/entities/manytomany/MapOwnedEntity.java 2008-10-27 18:56:31 UTC (rev 15406)
@@ -0,0 +1,84 @@
+package org.jboss.envers.test.entities.manytomany;
+
+import org.jboss.envers.Versioned;
+
+import javax.persistence.Entity;
+import javax.persistence.Id;
+import javax.persistence.ManyToMany;
+import java.util.Set;
+
+/**
+ * Many-to-many not-owning entity
+ * @author Adam Warski (adam at warski dot org)
+ */
+ at Entity
+public class MapOwnedEntity {
+ @Id
+ private Integer id;
+
+ @Versioned
+ private String data;
+
+ @Versioned
+ @ManyToMany(mappedBy="references")
+ private Set<MapOwningEntity> referencing;
+
+ public MapOwnedEntity() {
+ }
+
+ public MapOwnedEntity(Integer id, String data) {
+ this.id = id;
+ this.data = data;
+ }
+
+ public MapOwnedEntity(String data) {
+ this.data = data;
+ }
+
+ public Integer getId() {
+ return id;
+ }
+
+ public void setId(Integer id) {
+ this.id = id;
+ }
+
+ public String getData() {
+ return data;
+ }
+
+ public void setData(String data) {
+ this.data = data;
+ }
+
+ public Set<MapOwningEntity> getReferencing() {
+ return referencing;
+ }
+
+ public void setReferencing(Set<MapOwningEntity> referencing) {
+ this.referencing = referencing;
+ }
+
+ public boolean equals(Object o) {
+ if (this == o) return true;
+ if (!(o instanceof MapOwnedEntity)) return false;
+
+ MapOwnedEntity that = (MapOwnedEntity) o;
+
+ if (data != null ? !data.equals(that.data) : that.data != null) return false;
+ if (id != null ? !id.equals(that.id) : that.id != null) return false;
+
+ return true;
+ }
+
+ public int hashCode() {
+ int result;
+ result = (id != null ? id.hashCode() : 0);
+ result = 31 * result + (data != null ? data.hashCode() : 0);
+ return result;
+ }
+
+ public String toString() {
+ return "MapOwnedEntity(id = " + id + ", data = " + data + ")";
+ }
+}
\ No newline at end of file
Added: core/trunk/envers/src/test/java/org/jboss/envers/test/entities/manytomany/MapOwningEntity.java
===================================================================
--- core/trunk/envers/src/test/java/org/jboss/envers/test/entities/manytomany/MapOwningEntity.java (rev 0)
+++ core/trunk/envers/src/test/java/org/jboss/envers/test/entities/manytomany/MapOwningEntity.java 2008-10-27 18:56:31 UTC (rev 15406)
@@ -0,0 +1,82 @@
+package org.jboss.envers.test.entities.manytomany;
+
+import org.jboss.envers.Versioned;
+
+import javax.persistence.*;
+import java.util.Map;
+import java.util.HashMap;
+
+/**
+ * Entity owning the many-to-many relation
+ * @author Adam Warski (adam at warski dot org)
+ */
+ at Entity
+public class MapOwningEntity {
+ @Id
+ private Integer id;
+
+ @Versioned
+ private String data;
+
+ @Versioned
+ @ManyToMany
+ private Map<String, MapOwnedEntity> references = new HashMap<String, MapOwnedEntity>();
+
+ public MapOwningEntity() { }
+
+ public MapOwningEntity(Integer id, String data) {
+ this.id = id;
+ this.data = data;
+ }
+
+ public MapOwningEntity(String data) {
+ this.data = data;
+ }
+
+ public Integer getId() {
+ return id;
+ }
+
+ public void setId(Integer id) {
+ this.id = id;
+ }
+
+ public String getData() {
+ return data;
+ }
+
+ public void setData(String data) {
+ this.data = data;
+ }
+
+ public Map<String, MapOwnedEntity> getReferences() {
+ return references;
+ }
+
+ public void setReferences(Map<String, MapOwnedEntity> references) {
+ this.references = references;
+ }
+
+ public boolean equals(Object o) {
+ if (this == o) return true;
+ if (!(o instanceof MapOwningEntity)) return false;
+
+ MapOwningEntity that = (MapOwningEntity) o;
+
+ if (data != null ? !data.equals(that.data) : that.data != null) return false;
+ if (id != null ? !id.equals(that.id) : that.id != null) return false;
+
+ return true;
+ }
+
+ public int hashCode() {
+ int result;
+ result = (id != null ? id.hashCode() : 0);
+ result = 31 * result + (data != null ? data.hashCode() : 0);
+ return result;
+ }
+
+ public String toString() {
+ return "MapOwningEntity(id = " + id + ", data = " + data + ")";
+ }
+}
\ No newline at end of file
Added: core/trunk/envers/src/test/java/org/jboss/envers/test/entities/manytomany/SetOwnedEntity.java
===================================================================
--- core/trunk/envers/src/test/java/org/jboss/envers/test/entities/manytomany/SetOwnedEntity.java (rev 0)
+++ core/trunk/envers/src/test/java/org/jboss/envers/test/entities/manytomany/SetOwnedEntity.java 2008-10-27 18:56:31 UTC (rev 15406)
@@ -0,0 +1,84 @@
+package org.jboss.envers.test.entities.manytomany;
+
+import org.jboss.envers.Versioned;
+
+import javax.persistence.Entity;
+import javax.persistence.Id;
+import javax.persistence.ManyToMany;
+import java.util.Set;
+
+/**
+ * Many-to-many not-owning entity
+ * @author Adam Warski (adam at warski dot org)
+ */
+ at Entity
+public class SetOwnedEntity {
+ @Id
+ private Integer id;
+
+ @Versioned
+ private String data;
+
+ @Versioned
+ @ManyToMany(mappedBy="references")
+ private Set<SetOwningEntity> referencing;
+
+ public SetOwnedEntity() {
+ }
+
+ public SetOwnedEntity(Integer id, String data) {
+ this.id = id;
+ this.data = data;
+ }
+
+ public SetOwnedEntity(String data) {
+ this.data = data;
+ }
+
+ public Integer getId() {
+ return id;
+ }
+
+ public void setId(Integer id) {
+ this.id = id;
+ }
+
+ public String getData() {
+ return data;
+ }
+
+ public void setData(String data) {
+ this.data = data;
+ }
+
+ public Set<SetOwningEntity> getReferencing() {
+ return referencing;
+ }
+
+ public void setReferencing(Set<SetOwningEntity> referencing) {
+ this.referencing = referencing;
+ }
+
+ public boolean equals(Object o) {
+ if (this == o) return true;
+ if (!(o instanceof SetOwnedEntity)) return false;
+
+ SetOwnedEntity that = (SetOwnedEntity) o;
+
+ if (data != null ? !data.equals(that.data) : that.data != null) return false;
+ if (id != null ? !id.equals(that.id) : that.id != null) return false;
+
+ return true;
+ }
+
+ public int hashCode() {
+ int result;
+ result = (id != null ? id.hashCode() : 0);
+ result = 31 * result + (data != null ? data.hashCode() : 0);
+ return result;
+ }
+
+ public String toString() {
+ return "SetOwnedEntity(id = " + id + ", data = " + data + ")";
+ }
+}
\ No newline at end of file
Added: core/trunk/envers/src/test/java/org/jboss/envers/test/entities/manytomany/SetOwningEntity.java
===================================================================
--- core/trunk/envers/src/test/java/org/jboss/envers/test/entities/manytomany/SetOwningEntity.java (rev 0)
+++ core/trunk/envers/src/test/java/org/jboss/envers/test/entities/manytomany/SetOwningEntity.java 2008-10-27 18:56:31 UTC (rev 15406)
@@ -0,0 +1,81 @@
+package org.jboss.envers.test.entities.manytomany;
+
+import org.jboss.envers.Versioned;
+
+import javax.persistence.*;
+import java.util.Set;
+
+/**
+ * Entity owning the many-to-many relation
+ * @author Adam Warski (adam at warski dot org)
+ */
+ at Entity
+public class SetOwningEntity {
+ @Id
+ private Integer id;
+
+ @Versioned
+ private String data;
+
+ @Versioned
+ @ManyToMany
+ private Set<SetOwnedEntity> references;
+
+ public SetOwningEntity() { }
+
+ public SetOwningEntity(Integer id, String data) {
+ this.id = id;
+ this.data = data;
+ }
+
+ public SetOwningEntity(String data) {
+ this.data = data;
+ }
+
+ public Integer getId() {
+ return id;
+ }
+
+ public void setId(Integer id) {
+ this.id = id;
+ }
+
+ public String getData() {
+ return data;
+ }
+
+ public void setData(String data) {
+ this.data = data;
+ }
+
+ public Set<SetOwnedEntity> getReferences() {
+ return references;
+ }
+
+ public void setReferences(Set<SetOwnedEntity> references) {
+ this.references = references;
+ }
+
+ public boolean equals(Object o) {
+ if (this == o) return true;
+ if (!(o instanceof SetOwningEntity)) return false;
+
+ SetOwningEntity that = (SetOwningEntity) o;
+
+ if (data != null ? !data.equals(that.data) : that.data != null) return false;
+ if (id != null ? !id.equals(that.id) : that.id != null) return false;
+
+ return true;
+ }
+
+ public int hashCode() {
+ int result;
+ result = (id != null ? id.hashCode() : 0);
+ result = 31 * result + (data != null ? data.hashCode() : 0);
+ return result;
+ }
+
+ public String toString() {
+ return "SetOwningEntity(id = " + id + ", data = " + data + ")";
+ }
+}
\ No newline at end of file
Added: core/trunk/envers/src/test/java/org/jboss/envers/test/entities/manytomany/unidirectional/ListUniEntity.java
===================================================================
--- core/trunk/envers/src/test/java/org/jboss/envers/test/entities/manytomany/unidirectional/ListUniEntity.java (rev 0)
+++ core/trunk/envers/src/test/java/org/jboss/envers/test/entities/manytomany/unidirectional/ListUniEntity.java 2008-10-27 18:56:31 UTC (rev 15406)
@@ -0,0 +1,82 @@
+package org.jboss.envers.test.entities.manytomany.unidirectional;
+
+import org.jboss.envers.Versioned;
+import org.jboss.envers.test.entities.StrTestEntity;
+
+import javax.persistence.*;
+import java.util.List;
+
+/**
+ * Entity owning the many-to-many relation
+ * @author Adam Warski (adam at warski dot org)
+ */
+ at Entity
+public class ListUniEntity {
+ @Id
+ private Integer id;
+
+ @Versioned
+ private String data;
+
+ @Versioned
+ @ManyToMany
+ private List<StrTestEntity> references;
+
+ public ListUniEntity() { }
+
+ public ListUniEntity(Integer id, String data) {
+ this.id = id;
+ this.data = data;
+ }
+
+ public ListUniEntity(String data) {
+ this.data = data;
+ }
+
+ public Integer getId() {
+ return id;
+ }
+
+ public void setId(Integer id) {
+ this.id = id;
+ }
+
+ public String getData() {
+ return data;
+ }
+
+ public void setData(String data) {
+ this.data = data;
+ }
+
+ public List<StrTestEntity> getReferences() {
+ return references;
+ }
+
+ public void setReferences(List<StrTestEntity> references) {
+ this.references = references;
+ }
+
+ public boolean equals(Object o) {
+ if (this == o) return true;
+ if (!(o instanceof ListUniEntity)) return false;
+
+ ListUniEntity that = (ListUniEntity) o;
+
+ if (data != null ? !data.equals(that.data) : that.data != null) return false;
+ if (id != null ? !id.equals(that.id) : that.id != null) return false;
+
+ return true;
+ }
+
+ public int hashCode() {
+ int result;
+ result = (id != null ? id.hashCode() : 0);
+ result = 31 * result + (data != null ? data.hashCode() : 0);
+ return result;
+ }
+
+ public String toString() {
+ return "ListUniEntity(id = " + id + ", data = " + data + ")";
+ }
+}
\ No newline at end of file
Added: core/trunk/envers/src/test/java/org/jboss/envers/test/entities/manytomany/unidirectional/MapUniEntity.java
===================================================================
--- core/trunk/envers/src/test/java/org/jboss/envers/test/entities/manytomany/unidirectional/MapUniEntity.java (rev 0)
+++ core/trunk/envers/src/test/java/org/jboss/envers/test/entities/manytomany/unidirectional/MapUniEntity.java 2008-10-27 18:56:31 UTC (rev 15406)
@@ -0,0 +1,85 @@
+package org.jboss.envers.test.entities.manytomany.unidirectional;
+
+import org.jboss.envers.Versioned;
+import org.jboss.envers.test.entities.StrTestEntity;
+
+import javax.persistence.Entity;
+import javax.persistence.Id;
+import javax.persistence.ManyToMany;
+import java.util.Map;
+
+/**
+ * Entity with a map from a string to an entity
+ * @author Adam Warski (adam at warski dot org)
+ */
+ at Entity
+public class MapUniEntity {
+ @Id
+ private Integer id;
+
+ @Versioned
+ private String data;
+
+ @Versioned
+ @ManyToMany
+ private Map<String, StrTestEntity> map;
+
+ public MapUniEntity() {
+ }
+
+ public MapUniEntity(Integer id, String data) {
+ this.id = id;
+ this.data = data;
+ }
+
+ public MapUniEntity(String data) {
+ this.data = data;
+ }
+
+ public Integer getId() {
+ return id;
+ }
+
+ public void setId(Integer id) {
+ this.id = id;
+ }
+
+ public String getData() {
+ return data;
+ }
+
+ public void setData(String data) {
+ this.data = data;
+ }
+
+ public Map<String, StrTestEntity> getMap() {
+ return map;
+ }
+
+ public void setMap(Map<String, StrTestEntity> map) {
+ this.map = map;
+ }
+
+ public boolean equals(Object o) {
+ if (this == o) return true;
+ if (!(o instanceof MapUniEntity)) return false;
+
+ MapUniEntity that = (MapUniEntity) o;
+
+ if (data != null ? !data.equals(that.data) : that.data != null) return false;
+ if (id != null ? !id.equals(that.id) : that.id != null) return false;
+
+ return true;
+ }
+
+ public int hashCode() {
+ int result;
+ result = (id != null ? id.hashCode() : 0);
+ result = 31 * result + (data != null ? data.hashCode() : 0);
+ return result;
+ }
+
+ public String toString() {
+ return "MapUniEntity(id = " + id + ", data = " + data + ")";
+ }
+}
\ No newline at end of file
Added: core/trunk/envers/src/test/java/org/jboss/envers/test/entities/manytomany/unidirectional/SetUniEntity.java
===================================================================
--- core/trunk/envers/src/test/java/org/jboss/envers/test/entities/manytomany/unidirectional/SetUniEntity.java (rev 0)
+++ core/trunk/envers/src/test/java/org/jboss/envers/test/entities/manytomany/unidirectional/SetUniEntity.java 2008-10-27 18:56:31 UTC (rev 15406)
@@ -0,0 +1,82 @@
+package org.jboss.envers.test.entities.manytomany.unidirectional;
+
+import org.jboss.envers.Versioned;
+import org.jboss.envers.test.entities.StrTestEntity;
+
+import javax.persistence.*;
+import java.util.Set;
+
+/**
+ * Entity owning the many-to-many relation
+ * @author Adam Warski (adam at warski dot org)
+ */
+ at Entity
+public class SetUniEntity {
+ @Id
+ private Integer id;
+
+ @Versioned
+ private String data;
+
+ @Versioned
+ @ManyToMany
+ private Set<StrTestEntity> references;
+
+ public SetUniEntity() { }
+
+ public SetUniEntity(Integer id, String data) {
+ this.id = id;
+ this.data = data;
+ }
+
+ public SetUniEntity(String data) {
+ this.data = data;
+ }
+
+ public Integer getId() {
+ return id;
+ }
+
+ public void setId(Integer id) {
+ this.id = id;
+ }
+
+ public String getData() {
+ return data;
+ }
+
+ public void setData(String data) {
+ this.data = data;
+ }
+
+ public Set<StrTestEntity> getReferences() {
+ return references;
+ }
+
+ public void setReferences(Set<StrTestEntity> references) {
+ this.references = references;
+ }
+
+ public boolean equals(Object o) {
+ if (this == o) return true;
+ if (!(o instanceof SetUniEntity)) return false;
+
+ SetUniEntity that = (SetUniEntity) o;
+
+ if (data != null ? !data.equals(that.data) : that.data != null) return false;
+ if (id != null ? !id.equals(that.id) : that.id != null) return false;
+
+ return true;
+ }
+
+ public int hashCode() {
+ int result;
+ result = (id != null ? id.hashCode() : 0);
+ result = 31 * result + (data != null ? data.hashCode() : 0);
+ return result;
+ }
+
+ public String toString() {
+ return "SetUniEntity(id = " + id + ", data = " + data + ")";
+ }
+}
\ No newline at end of file
Added: core/trunk/envers/src/test/java/org/jboss/envers/test/entities/onetomany/CollectionRefEdEntity.java
===================================================================
--- core/trunk/envers/src/test/java/org/jboss/envers/test/entities/onetomany/CollectionRefEdEntity.java (rev 0)
+++ core/trunk/envers/src/test/java/org/jboss/envers/test/entities/onetomany/CollectionRefEdEntity.java 2008-10-27 18:56:31 UTC (rev 15406)
@@ -0,0 +1,84 @@
+package org.jboss.envers.test.entities.onetomany;
+
+import org.jboss.envers.Versioned;
+
+import javax.persistence.Entity;
+import javax.persistence.Id;
+import javax.persistence.OneToMany;
+import java.util.Collection;
+
+/**
+ * ReferencEd entity
+ * @author Adam Warski (adam at warski dot org)
+ */
+ at Entity
+public class CollectionRefEdEntity {
+ @Id
+ private Integer id;
+
+ @Versioned
+ private String data;
+
+ @Versioned
+ @OneToMany(mappedBy="reference")
+ private Collection<CollectionRefIngEntity> reffering;
+
+ public CollectionRefEdEntity() {
+ }
+
+ public CollectionRefEdEntity(Integer id, String data) {
+ this.id = id;
+ this.data = data;
+ }
+
+ public CollectionRefEdEntity(String data) {
+ this.data = data;
+ }
+
+ public Integer getId() {
+ return id;
+ }
+
+ public void setId(Integer id) {
+ this.id = id;
+ }
+
+ public String getData() {
+ return data;
+ }
+
+ public void setData(String data) {
+ this.data = data;
+ }
+
+ public Collection<CollectionRefIngEntity> getReffering() {
+ return reffering;
+ }
+
+ public void setReffering(Collection<CollectionRefIngEntity> reffering) {
+ this.reffering = reffering;
+ }
+
+ public boolean equals(Object o) {
+ if (this == o) return true;
+ if (!(o instanceof CollectionRefEdEntity)) return false;
+
+ CollectionRefEdEntity that = (CollectionRefEdEntity) o;
+
+ if (data != null ? !data.equals(that.data) : that.data != null) return false;
+ if (id != null ? !id.equals(that.id) : that.id != null) return false;
+
+ return true;
+ }
+
+ public int hashCode() {
+ int result;
+ result = (id != null ? id.hashCode() : 0);
+ result = 31 * result + (data != null ? data.hashCode() : 0);
+ return result;
+ }
+
+ public String toString() {
+ return "CollectionRefEdEntity(id = " + id + ", data = " + data + ")";
+ }
+}
\ No newline at end of file
Added: core/trunk/envers/src/test/java/org/jboss/envers/test/entities/onetomany/CollectionRefIngEntity.java
===================================================================
--- core/trunk/envers/src/test/java/org/jboss/envers/test/entities/onetomany/CollectionRefIngEntity.java (rev 0)
+++ core/trunk/envers/src/test/java/org/jboss/envers/test/entities/onetomany/CollectionRefIngEntity.java 2008-10-27 18:56:31 UTC (rev 15406)
@@ -0,0 +1,82 @@
+package org.jboss.envers.test.entities.onetomany;
+
+import org.jboss.envers.Versioned;
+
+import javax.persistence.*;
+
+/**
+ * ReferencIng entity
+ * @author Adam Warski (adam at warski dot org)
+ */
+ at Entity
+public class CollectionRefIngEntity {
+ @Id
+ private Integer id;
+
+ @Versioned
+ private String data;
+
+ @Versioned
+ @ManyToOne
+ private CollectionRefEdEntity reference;
+
+ public CollectionRefIngEntity() { }
+
+ public CollectionRefIngEntity(Integer id, String data, CollectionRefEdEntity reference) {
+ this.id = id;
+ this.data = data;
+ this.reference = reference;
+ }
+
+ public CollectionRefIngEntity(String data, CollectionRefEdEntity reference) {
+ this.data = data;
+ this.reference = reference;
+ }
+
+ public Integer getId() {
+ return id;
+ }
+
+ public void setId(Integer id) {
+ this.id = id;
+ }
+
+ public String getData() {
+ return data;
+ }
+
+ public void setData(String data) {
+ this.data = data;
+ }
+
+ public CollectionRefEdEntity getReference() {
+ return reference;
+ }
+
+ public void setReference(CollectionRefEdEntity reference) {
+ this.reference = reference;
+ }
+
+ public boolean equals(Object o) {
+ if (this == o) return true;
+ if (!(o instanceof CollectionRefIngEntity)) return false;
+
+ CollectionRefIngEntity that = (CollectionRefIngEntity) o;
+
+ if (data != null ? !data.equals(that.data) : that.data != null) return false;
+ if (id != null ? !id.equals(that.id) : that.id != null) return false;
+
+ return true;
+ }
+
+ public int hashCode() {
+ int result;
+ result = (id != null ? id.hashCode() : 0);
+ result = 31 * result + (data != null ? data.hashCode() : 0);
+ return result;
+ }
+
+ public String toString() {
+ return "CollectionRefIngEntity(id = " + id + ", data = " + data + ")";
+ }
+}
\ No newline at end of file
Added: core/trunk/envers/src/test/java/org/jboss/envers/test/entities/onetomany/ListRefEdEntity.java
===================================================================
--- core/trunk/envers/src/test/java/org/jboss/envers/test/entities/onetomany/ListRefEdEntity.java (rev 0)
+++ core/trunk/envers/src/test/java/org/jboss/envers/test/entities/onetomany/ListRefEdEntity.java 2008-10-27 18:56:31 UTC (rev 15406)
@@ -0,0 +1,84 @@
+package org.jboss.envers.test.entities.onetomany;
+
+import org.jboss.envers.Versioned;
+
+import javax.persistence.Entity;
+import javax.persistence.Id;
+import javax.persistence.OneToMany;
+import java.util.List;
+
+/**
+ * ReferencEd entity
+ * @author Adam Warski (adam at warski dot org)
+ */
+ at Entity
+public class ListRefEdEntity {
+ @Id
+ private Integer id;
+
+ @Versioned
+ private String data;
+
+ @Versioned
+ @OneToMany(mappedBy="reference")
+ private List<ListRefIngEntity> reffering;
+
+ public ListRefEdEntity() {
+ }
+
+ public ListRefEdEntity(Integer id, String data) {
+ this.id = id;
+ this.data = data;
+ }
+
+ public ListRefEdEntity(String data) {
+ this.data = data;
+ }
+
+ public Integer getId() {
+ return id;
+ }
+
+ public void setId(Integer id) {
+ this.id = id;
+ }
+
+ public String getData() {
+ return data;
+ }
+
+ public void setData(String data) {
+ this.data = data;
+ }
+
+ public List<ListRefIngEntity> getReffering() {
+ return reffering;
+ }
+
+ public void setReffering(List<ListRefIngEntity> reffering) {
+ this.reffering = reffering;
+ }
+
+ public boolean equals(Object o) {
+ if (this == o) return true;
+ if (!(o instanceof ListRefEdEntity)) return false;
+
+ ListRefEdEntity that = (ListRefEdEntity) o;
+
+ if (data != null ? !data.equals(that.data) : that.data != null) return false;
+ if (id != null ? !id.equals(that.id) : that.id != null) return false;
+
+ return true;
+ }
+
+ public int hashCode() {
+ int result;
+ result = (id != null ? id.hashCode() : 0);
+ result = 31 * result + (data != null ? data.hashCode() : 0);
+ return result;
+ }
+
+ public String toString() {
+ return "ListRefEdEntity(id = " + id + ", data = " + data + ")";
+ }
+}
\ No newline at end of file
Added: core/trunk/envers/src/test/java/org/jboss/envers/test/entities/onetomany/ListRefIngEntity.java
===================================================================
--- core/trunk/envers/src/test/java/org/jboss/envers/test/entities/onetomany/ListRefIngEntity.java (rev 0)
+++ core/trunk/envers/src/test/java/org/jboss/envers/test/entities/onetomany/ListRefIngEntity.java 2008-10-27 18:56:31 UTC (rev 15406)
@@ -0,0 +1,82 @@
+package org.jboss.envers.test.entities.onetomany;
+
+import org.jboss.envers.Versioned;
+
+import javax.persistence.*;
+
+/**
+ * ReferencIng entity
+ * @author Adam Warski (adam at warski dot org)
+ */
+ at Entity
+public class ListRefIngEntity {
+ @Id
+ private Integer id;
+
+ @Versioned
+ private String data;
+
+ @Versioned
+ @ManyToOne
+ private ListRefEdEntity reference;
+
+ public ListRefIngEntity() { }
+
+ public ListRefIngEntity(Integer id, String data, ListRefEdEntity reference) {
+ this.id = id;
+ this.data = data;
+ this.reference = reference;
+ }
+
+ public ListRefIngEntity(String data, ListRefEdEntity reference) {
+ this.data = data;
+ this.reference = reference;
+ }
+
+ public Integer getId() {
+ return id;
+ }
+
+ public void setId(Integer id) {
+ this.id = id;
+ }
+
+ public String getData() {
+ return data;
+ }
+
+ public void setData(String data) {
+ this.data = data;
+ }
+
+ public ListRefEdEntity getReference() {
+ return reference;
+ }
+
+ public void setReference(ListRefEdEntity reference) {
+ this.reference = reference;
+ }
+
+ public boolean equals(Object o) {
+ if (this == o) return true;
+ if (!(o instanceof ListRefIngEntity)) return false;
+
+ ListRefIngEntity that = (ListRefIngEntity) o;
+
+ if (data != null ? !data.equals(that.data) : that.data != null) return false;
+ if (id != null ? !id.equals(that.id) : that.id != null) return false;
+
+ return true;
+ }
+
+ public int hashCode() {
+ int result;
+ result = (id != null ? id.hashCode() : 0);
+ result = 31 * result + (data != null ? data.hashCode() : 0);
+ return result;
+ }
+
+ public String toString() {
+ return "ListRefIngEntity(id = " + id + ", data = " + data + ")";
+ }
+}
\ No newline at end of file
Added: core/trunk/envers/src/test/java/org/jboss/envers/test/entities/onetomany/SetRefEdEntity.java
===================================================================
--- core/trunk/envers/src/test/java/org/jboss/envers/test/entities/onetomany/SetRefEdEntity.java (rev 0)
+++ core/trunk/envers/src/test/java/org/jboss/envers/test/entities/onetomany/SetRefEdEntity.java 2008-10-27 18:56:31 UTC (rev 15406)
@@ -0,0 +1,84 @@
+package org.jboss.envers.test.entities.onetomany;
+
+import org.jboss.envers.Versioned;
+
+import javax.persistence.Entity;
+import javax.persistence.Id;
+import javax.persistence.OneToMany;
+import java.util.Set;
+
+/**
+ * ReferencEd entity
+ * @author Adam Warski (adam at warski dot org)
+ */
+ at Entity
+public class SetRefEdEntity {
+ @Id
+ private Integer id;
+
+ @Versioned
+ private String data;
+
+ @Versioned
+ @OneToMany(mappedBy="reference")
+ private Set<SetRefIngEntity> reffering;
+
+ public SetRefEdEntity() {
+ }
+
+ public SetRefEdEntity(Integer id, String data) {
+ this.id = id;
+ this.data = data;
+ }
+
+ public SetRefEdEntity(String data) {
+ this.data = data;
+ }
+
+ public Integer getId() {
+ return id;
+ }
+
+ public void setId(Integer id) {
+ this.id = id;
+ }
+
+ public String getData() {
+ return data;
+ }
+
+ public void setData(String data) {
+ this.data = data;
+ }
+
+ public Set<SetRefIngEntity> getReffering() {
+ return reffering;
+ }
+
+ public void setReffering(Set<SetRefIngEntity> reffering) {
+ this.reffering = reffering;
+ }
+
+ public boolean equals(Object o) {
+ if (this == o) return true;
+ if (!(o instanceof SetRefEdEntity)) return false;
+
+ SetRefEdEntity that = (SetRefEdEntity) o;
+
+ if (data != null ? !data.equals(that.data) : that.data != null) return false;
+ if (id != null ? !id.equals(that.id) : that.id != null) return false;
+
+ return true;
+ }
+
+ public int hashCode() {
+ int result;
+ result = (id != null ? id.hashCode() : 0);
+ result = 31 * result + (data != null ? data.hashCode() : 0);
+ return result;
+ }
+
+ public String toString() {
+ return "SetRefEdEntity(id = " + id + ", data = " + data + ")";
+ }
+}
Added: core/trunk/envers/src/test/java/org/jboss/envers/test/entities/onetomany/SetRefIngEntity.java
===================================================================
--- core/trunk/envers/src/test/java/org/jboss/envers/test/entities/onetomany/SetRefIngEntity.java (rev 0)
+++ core/trunk/envers/src/test/java/org/jboss/envers/test/entities/onetomany/SetRefIngEntity.java 2008-10-27 18:56:31 UTC (rev 15406)
@@ -0,0 +1,87 @@
+package org.jboss.envers.test.entities.onetomany;
+
+import org.jboss.envers.Versioned;
+
+import javax.persistence.*;
+
+/**
+ * ReferencIng entity
+ * @author Adam Warski (adam at warski dot org)
+ */
+ at Entity
+public class SetRefIngEntity {
+ @Id
+ private Integer id;
+
+ @Versioned
+ private String data;
+
+ @Versioned
+ @ManyToOne
+ private SetRefEdEntity reference;
+
+ public SetRefIngEntity() { }
+
+ public SetRefIngEntity(Integer id, String data, SetRefEdEntity reference) {
+ this.id = id;
+ this.data = data;
+ this.reference = reference;
+ }
+
+ public SetRefIngEntity(String data, SetRefEdEntity reference) {
+ this.data = data;
+ this.reference = reference;
+ }
+
+ public SetRefIngEntity(Integer id, String data) {
+ this.id = id;
+ this.data = data;
+ }
+
+ public Integer getId() {
+ return id;
+ }
+
+ public void setId(Integer id) {
+ this.id = id;
+ }
+
+ public String getData() {
+ return data;
+ }
+
+ public void setData(String data) {
+ this.data = data;
+ }
+
+ public SetRefEdEntity getReference() {
+ return reference;
+ }
+
+ public void setReference(SetRefEdEntity reference) {
+ this.reference = reference;
+ }
+
+ public boolean equals(Object o) {
+ if (this == o) return true;
+ if (!(o instanceof SetRefIngEntity)) return false;
+
+ SetRefIngEntity that = (SetRefIngEntity) o;
+
+ if (data != null ? !data.equals(that.data) : that.data != null) return false;
+ if (id != null ? !id.equals(that.id) : that.id != null) return false;
+
+ return true;
+ }
+
+ public int hashCode() {
+ int result;
+ result = (id != null ? id.hashCode() : 0);
+ result = 31 * result + (data != null ? data.hashCode() : 0);
+ return result;
+ }
+
+ public String toString() {
+ return "SetRefIngEntity(id = " + id + ", data = " + data + ")";
+ }
+}
Added: core/trunk/envers/src/test/java/org/jboss/envers/test/entities/onetomany/detached/DoubleSetRefCollEntity.java
===================================================================
--- core/trunk/envers/src/test/java/org/jboss/envers/test/entities/onetomany/detached/DoubleSetRefCollEntity.java (rev 0)
+++ core/trunk/envers/src/test/java/org/jboss/envers/test/entities/onetomany/detached/DoubleSetRefCollEntity.java 2008-10-27 18:56:31 UTC (rev 15406)
@@ -0,0 +1,100 @@
+package org.jboss.envers.test.entities.onetomany.detached;
+
+import org.jboss.envers.Versioned;
+import org.jboss.envers.test.entities.StrTestEntity;
+
+import javax.persistence.Entity;
+import javax.persistence.Id;
+import javax.persistence.OneToMany;
+import javax.persistence.JoinTable;
+import java.util.Set;
+
+/**
+ * Set collection of references entity
+ * @author Adam Warski (adam at warski dot org)
+ */
+ at Entity
+public class DoubleSetRefCollEntity {
+ @Id
+ private Integer id;
+
+ @Versioned
+ private String data;
+
+ @Versioned
+ @OneToMany
+ @JoinTable(name = "DOUBLE_STR_1")
+ private Set<StrTestEntity> collection;
+
+ @Versioned
+ @OneToMany
+ @JoinTable(name = "DOUBLE_STR_2")
+ private Set<StrTestEntity> collection2;
+
+ public DoubleSetRefCollEntity() {
+ }
+
+ public DoubleSetRefCollEntity(Integer id, String data) {
+ this.id = id;
+ this.data = data;
+ }
+
+ public DoubleSetRefCollEntity(String data) {
+ this.data = data;
+ }
+
+ public Integer getId() {
+ return id;
+ }
+
+ public void setId(Integer id) {
+ this.id = id;
+ }
+
+ public String getData() {
+ return data;
+ }
+
+ public void setData(String data) {
+ this.data = data;
+ }
+
+ public Set<StrTestEntity> getCollection() {
+ return collection;
+ }
+
+ public void setCollection(Set<StrTestEntity> collection) {
+ this.collection = collection;
+ }
+
+ public Set<StrTestEntity> getCollection2() {
+ return collection2;
+ }
+
+ public void setCollection2(Set<StrTestEntity> collection2) {
+ this.collection2 = collection2;
+ }
+
+ public boolean equals(Object o) {
+ if (this == o) return true;
+ if (!(o instanceof DoubleSetRefCollEntity)) return false;
+
+ DoubleSetRefCollEntity that = (DoubleSetRefCollEntity) o;
+
+ if (data != null ? !data.equals(that.data) : that.data != null) return false;
+ if (id != null ? !id.equals(that.id) : that.id != null) return false;
+
+ return true;
+ }
+
+ public int hashCode() {
+ int result;
+ result = (id != null ? id.hashCode() : 0);
+ result = 31 * result + (data != null ? data.hashCode() : 0);
+ return result;
+ }
+
+ public String toString() {
+ return "DoubleSetRefEdEntity(id = " + id + ", data = " + data + ")";
+ }
+}
\ No newline at end of file
Added: core/trunk/envers/src/test/java/org/jboss/envers/test/entities/onetomany/detached/ListRefCollEntity.java
===================================================================
--- core/trunk/envers/src/test/java/org/jboss/envers/test/entities/onetomany/detached/ListRefCollEntity.java (rev 0)
+++ core/trunk/envers/src/test/java/org/jboss/envers/test/entities/onetomany/detached/ListRefCollEntity.java 2008-10-27 18:56:31 UTC (rev 15406)
@@ -0,0 +1,85 @@
+package org.jboss.envers.test.entities.onetomany.detached;
+
+import org.jboss.envers.Versioned;
+import org.jboss.envers.test.entities.StrTestEntity;
+
+import javax.persistence.Entity;
+import javax.persistence.Id;
+import javax.persistence.OneToMany;
+import java.util.List;
+
+/**
+ * Set collection of references entity
+ * @author Adam Warski (adam at warski dot org)
+ */
+ at Entity
+public class ListRefCollEntity {
+ @Id
+ private Integer id;
+
+ @Versioned
+ private String data;
+
+ @Versioned
+ @OneToMany
+ private List<StrTestEntity> collection;
+
+ public ListRefCollEntity() {
+ }
+
+ public ListRefCollEntity(Integer id, String data) {
+ this.id = id;
+ this.data = data;
+ }
+
+ public ListRefCollEntity(String data) {
+ this.data = data;
+ }
+
+ public Integer getId() {
+ return id;
+ }
+
+ public void setId(Integer id) {
+ this.id = id;
+ }
+
+ public String getData() {
+ return data;
+ }
+
+ public void setData(String data) {
+ this.data = data;
+ }
+
+ public List<StrTestEntity> getCollection() {
+ return collection;
+ }
+
+ public void setCollection(List<StrTestEntity> collection) {
+ this.collection = collection;
+ }
+
+ public boolean equals(Object o) {
+ if (this == o) return true;
+ if (!(o instanceof ListRefCollEntity)) return false;
+
+ ListRefCollEntity that = (ListRefCollEntity) o;
+
+ if (data != null ? !data.equals(that.data) : that.data != null) return false;
+ if (id != null ? !id.equals(that.id) : that.id != null) return false;
+
+ return true;
+ }
+
+ public int hashCode() {
+ int result;
+ result = (id != null ? id.hashCode() : 0);
+ result = 31 * result + (data != null ? data.hashCode() : 0);
+ return result;
+ }
+
+ public String toString() {
+ return "SetRefEdEntity(id = " + id + ", data = " + data + ")";
+ }
+}
\ No newline at end of file
Added: core/trunk/envers/src/test/java/org/jboss/envers/test/entities/onetomany/detached/SetJoinColumnRefCollEntity.java
===================================================================
--- core/trunk/envers/src/test/java/org/jboss/envers/test/entities/onetomany/detached/SetJoinColumnRefCollEntity.java (rev 0)
+++ core/trunk/envers/src/test/java/org/jboss/envers/test/entities/onetomany/detached/SetJoinColumnRefCollEntity.java 2008-10-27 18:56:31 UTC (rev 15406)
@@ -0,0 +1,87 @@
+package org.jboss.envers.test.entities.onetomany.detached;
+
+import org.jboss.envers.Versioned;
+import org.jboss.envers.test.entities.StrTestEntity;
+
+import javax.persistence.Entity;
+import javax.persistence.Id;
+import javax.persistence.OneToMany;
+import javax.persistence.JoinColumn;
+import java.util.Set;
+
+/**
+ * A detached relation to another entity, with a @OneToMany+ at JoinColumn mapping.
+ * @author Adam Warski (adam at warski dot org)
+ */
+ at Entity
+public class SetJoinColumnRefCollEntity {
+ @Id
+ private Integer id;
+
+ @Versioned
+ private String data;
+
+ @Versioned
+ @OneToMany
+ @JoinColumn(name = "SJCR_ID")
+ private Set<StrTestEntity> collection;
+
+ public SetJoinColumnRefCollEntity() {
+ }
+
+ public SetJoinColumnRefCollEntity(Integer id, String data) {
+ this.id = id;
+ this.data = data;
+ }
+
+ public SetJoinColumnRefCollEntity(String data) {
+ this.data = data;
+ }
+
+ public Integer getId() {
+ return id;
+ }
+
+ public void setId(Integer id) {
+ this.id = id;
+ }
+
+ public String getData() {
+ return data;
+ }
+
+ public void setData(String data) {
+ this.data = data;
+ }
+
+ public Set<StrTestEntity> getCollection() {
+ return collection;
+ }
+
+ public void setCollection(Set<StrTestEntity> collection) {
+ this.collection = collection;
+ }
+
+ public boolean equals(Object o) {
+ if (this == o) return true;
+ if (!(o instanceof SetJoinColumnRefCollEntity)) return false;
+
+ SetJoinColumnRefCollEntity that = (SetJoinColumnRefCollEntity) o;
+
+ if (data != null ? !data.equals(that.data) : that.data != null) return false;
+ if (id != null ? !id.equals(that.id) : that.id != null) return false;
+
+ return true;
+ }
+
+ public int hashCode() {
+ int result;
+ result = (id != null ? id.hashCode() : 0);
+ result = 31 * result + (data != null ? data.hashCode() : 0);
+ return result;
+ }
+
+ public String toString() {
+ return "SetJoinColumnRefCollEntity(id = " + id + ", data = " + data + ")";
+ }
+}
\ No newline at end of file
Added: core/trunk/envers/src/test/java/org/jboss/envers/test/entities/onetomany/detached/SetRefCollEntity.java
===================================================================
--- core/trunk/envers/src/test/java/org/jboss/envers/test/entities/onetomany/detached/SetRefCollEntity.java (rev 0)
+++ core/trunk/envers/src/test/java/org/jboss/envers/test/entities/onetomany/detached/SetRefCollEntity.java 2008-10-27 18:56:31 UTC (rev 15406)
@@ -0,0 +1,85 @@
+package org.jboss.envers.test.entities.onetomany.detached;
+
+import org.jboss.envers.Versioned;
+import org.jboss.envers.test.entities.StrTestEntity;
+
+import javax.persistence.Entity;
+import javax.persistence.Id;
+import javax.persistence.OneToMany;
+import java.util.Set;
+
+/**
+ * Set collection of references entity
+ * @author Adam Warski (adam at warski dot org)
+ */
+ at Entity
+public class SetRefCollEntity {
+ @Id
+ private Integer id;
+
+ @Versioned
+ private String data;
+
+ @Versioned
+ @OneToMany
+ private Set<StrTestEntity> collection;
+
+ public SetRefCollEntity() {
+ }
+
+ public SetRefCollEntity(Integer id, String data) {
+ this.id = id;
+ this.data = data;
+ }
+
+ public SetRefCollEntity(String data) {
+ this.data = data;
+ }
+
+ public Integer getId() {
+ return id;
+ }
+
+ public void setId(Integer id) {
+ this.id = id;
+ }
+
+ public String getData() {
+ return data;
+ }
+
+ public void setData(String data) {
+ this.data = data;
+ }
+
+ public Set<StrTestEntity> getCollection() {
+ return collection;
+ }
+
+ public void setCollection(Set<StrTestEntity> collection) {
+ this.collection = collection;
+ }
+
+ public boolean equals(Object o) {
+ if (this == o) return true;
+ if (!(o instanceof SetRefCollEntity)) return false;
+
+ SetRefCollEntity that = (SetRefCollEntity) o;
+
+ if (data != null ? !data.equals(that.data) : that.data != null) return false;
+ if (id != null ? !id.equals(that.id) : that.id != null) return false;
+
+ return true;
+ }
+
+ public int hashCode() {
+ int result;
+ result = (id != null ? id.hashCode() : 0);
+ result = 31 * result + (data != null ? data.hashCode() : 0);
+ return result;
+ }
+
+ public String toString() {
+ return "SetRefEdEntity(id = " + id + ", data = " + data + ")";
+ }
+}
\ No newline at end of file
Added: core/trunk/envers/src/test/java/org/jboss/envers/test/entities/onetomany/detached/ids/SetRefCollEntityEmbId.java
===================================================================
--- core/trunk/envers/src/test/java/org/jboss/envers/test/entities/onetomany/detached/ids/SetRefCollEntityEmbId.java (rev 0)
+++ core/trunk/envers/src/test/java/org/jboss/envers/test/entities/onetomany/detached/ids/SetRefCollEntityEmbId.java 2008-10-27 18:56:31 UTC (rev 15406)
@@ -0,0 +1,86 @@
+package org.jboss.envers.test.entities.onetomany.detached.ids;
+
+import org.jboss.envers.Versioned;
+import org.jboss.envers.test.entities.ids.EmbId;
+import org.jboss.envers.test.entities.ids.EmbIdTestEntity;
+
+import javax.persistence.Entity;
+import javax.persistence.OneToMany;
+import javax.persistence.EmbeddedId;
+import java.util.Set;
+
+/**
+ * Set collection of references entity
+ * @author Adam Warski (adam at warski dot org)
+ */
+ at Entity
+public class SetRefCollEntityEmbId {
+ @EmbeddedId
+ private EmbId id;
+
+ @Versioned
+ private String data;
+
+ @Versioned
+ @OneToMany
+ private Set<EmbIdTestEntity> collection;
+
+ public SetRefCollEntityEmbId() {
+ }
+
+ public SetRefCollEntityEmbId(EmbId id, String data) {
+ this.id = id;
+ this.data = data;
+ }
+
+ public SetRefCollEntityEmbId(String data) {
+ this.data = data;
+ }
+
+ public EmbId getId() {
+ return id;
+ }
+
+ public void setId(EmbId id) {
+ this.id = id;
+ }
+
+ public String getData() {
+ return data;
+ }
+
+ public void setData(String data) {
+ this.data = data;
+ }
+
+ public Set<EmbIdTestEntity> getCollection() {
+ return collection;
+ }
+
+ public void setCollection(Set<EmbIdTestEntity> collection) {
+ this.collection = collection;
+ }
+
+ public boolean equals(Object o) {
+ if (this == o) return true;
+ if (!(o instanceof SetRefCollEntityEmbId)) return false;
+
+ SetRefCollEntityEmbId that = (SetRefCollEntityEmbId) o;
+
+ if (data != null ? !data.equals(that.data) : that.data != null) return false;
+ if (id != null ? !id.equals(that.id) : that.id != null) return false;
+
+ return true;
+ }
+
+ public int hashCode() {
+ int result;
+ result = (id != null ? id.hashCode() : 0);
+ result = 31 * result + (data != null ? data.hashCode() : 0);
+ return result;
+ }
+
+ public String toString() {
+ return "SetRefCollEntityEmbId(id = " + id + ", data = " + data + ")";
+ }
+}
\ No newline at end of file
Added: core/trunk/envers/src/test/java/org/jboss/envers/test/entities/onetomany/detached/ids/SetRefCollEntityMulId.java
===================================================================
--- core/trunk/envers/src/test/java/org/jboss/envers/test/entities/onetomany/detached/ids/SetRefCollEntityMulId.java (rev 0)
+++ core/trunk/envers/src/test/java/org/jboss/envers/test/entities/onetomany/detached/ids/SetRefCollEntityMulId.java 2008-10-27 18:56:31 UTC (rev 15406)
@@ -0,0 +1,99 @@
+package org.jboss.envers.test.entities.onetomany.detached.ids;
+
+import org.jboss.envers.Versioned;
+import org.jboss.envers.test.entities.ids.MulIdTestEntity;
+import org.jboss.envers.test.entities.ids.MulId;
+
+import javax.persistence.*;
+import java.util.Set;
+
+/**
+ * Set collection of references entity
+ * @author Adam Warski (adam at warski dot org)
+ */
+ at Entity
+ at IdClass(MulId.class)
+public class SetRefCollEntityMulId {
+ @Id
+ private Integer id1;
+
+ @Id
+ private Integer id2;
+
+ @Versioned
+ private String data;
+
+ @Versioned
+ @OneToMany
+ private Set<MulIdTestEntity> collection;
+
+ public SetRefCollEntityMulId() {
+ }
+
+ public SetRefCollEntityMulId(Integer id1, Integer id2, String data) {
+ this.id1 = id1;
+ this.id2 = id2;
+ this.data = data;
+ }
+
+ public SetRefCollEntityMulId(String data) {
+ this.data = data;
+ }
+
+ public Integer getId1() {
+ return id1;
+ }
+
+ public void setId1(Integer id1) {
+ this.id1 = id1;
+ }
+
+ public Integer getId2() {
+ return id2;
+ }
+
+ public void setId2(Integer id2) {
+ this.id2 = id2;
+ }
+
+ public String getData() {
+ return data;
+ }
+
+ public void setData(String data) {
+ this.data = data;
+ }
+
+ public Set<MulIdTestEntity> getCollection() {
+ return collection;
+ }
+
+ public void setCollection(Set<MulIdTestEntity> collection) {
+ this.collection = collection;
+ }
+
+ public boolean equals(Object o) {
+ if (this == o) return true;
+ if (!(o instanceof SetRefCollEntityMulId)) return false;
+
+ SetRefCollEntityMulId that = (SetRefCollEntityMulId) o;
+
+ if (data != null ? !data.equals(that.data) : that.data != null) return false;
+ if (id1 != null ? !id1.equals(that.id1) : that.id1 != null) return false;
+ if (id2 != null ? !id2.equals(that.id2) : that.id2 != null) return false;
+
+ return true;
+ }
+
+ public int hashCode() {
+ int result;
+ result = (id1 != null ? id1.hashCode() : 0);
+ result = 31 * result + (id2 != null ? id2.hashCode() : 0);
+ result = 31 * result + (data != null ? data.hashCode() : 0);
+ return result;
+ }
+
+ public String toString() {
+ return "SetRefCollEntityMulId(id1 = " + id1 + ", id2 = " + id2 + ", data = " + data + ")";
+ }
+}
\ No newline at end of file
Added: core/trunk/envers/src/test/java/org/jboss/envers/test/entities/onetomany/ids/SetRefEdEmbIdEntity.java
===================================================================
--- core/trunk/envers/src/test/java/org/jboss/envers/test/entities/onetomany/ids/SetRefEdEmbIdEntity.java (rev 0)
+++ core/trunk/envers/src/test/java/org/jboss/envers/test/entities/onetomany/ids/SetRefEdEmbIdEntity.java 2008-10-27 18:56:31 UTC (rev 15406)
@@ -0,0 +1,85 @@
+package org.jboss.envers.test.entities.onetomany.ids;
+
+import org.jboss.envers.Versioned;
+import org.jboss.envers.test.entities.ids.EmbId;
+
+import javax.persistence.Entity;
+import javax.persistence.OneToMany;
+import javax.persistence.EmbeddedId;
+import java.util.Set;
+
+/**
+ * ReferencEd entity
+ * @author Adam Warski (adam at warski dot org)
+ */
+ at Entity
+public class SetRefEdEmbIdEntity {
+ @EmbeddedId
+ private EmbId id;
+
+ @Versioned
+ private String data;
+
+ @Versioned
+ @OneToMany(mappedBy="reference")
+ private Set<SetRefIngEmbIdEntity> reffering;
+
+ public SetRefEdEmbIdEntity() {
+ }
+
+ public SetRefEdEmbIdEntity(EmbId id, String data) {
+ this.id = id;
+ this.data = data;
+ }
+
+ public SetRefEdEmbIdEntity(String data) {
+ this.data = data;
+ }
+
+ public EmbId getId() {
+ return id;
+ }
+
+ public void setId(EmbId id) {
+ this.id = id;
+ }
+
+ public String getData() {
+ return data;
+ }
+
+ public void setData(String data) {
+ this.data = data;
+ }
+
+ public Set<SetRefIngEmbIdEntity> getReffering() {
+ return reffering;
+ }
+
+ public void setReffering(Set<SetRefIngEmbIdEntity> reffering) {
+ this.reffering = reffering;
+ }
+
+ public boolean equals(Object o) {
+ if (this == o) return true;
+ if (!(o instanceof SetRefEdEmbIdEntity)) return false;
+
+ SetRefEdEmbIdEntity that = (SetRefEdEmbIdEntity) o;
+
+ if (data != null ? !data.equals(that.data) : that.data != null) return false;
+ if (id != null ? !id.equals(that.id) : that.id != null) return false;
+
+ return true;
+ }
+
+ public int hashCode() {
+ int result;
+ result = (id != null ? id.hashCode() : 0);
+ result = 31 * result + (data != null ? data.hashCode() : 0);
+ return result;
+ }
+
+ public String toString() {
+ return "SetRefEdEmbIdEntity(id = " + id + ", data = " + data + ")";
+ }
+}
\ No newline at end of file
Added: core/trunk/envers/src/test/java/org/jboss/envers/test/entities/onetomany/ids/SetRefEdMulIdEntity.java
===================================================================
--- core/trunk/envers/src/test/java/org/jboss/envers/test/entities/onetomany/ids/SetRefEdMulIdEntity.java (rev 0)
+++ core/trunk/envers/src/test/java/org/jboss/envers/test/entities/onetomany/ids/SetRefEdMulIdEntity.java 2008-10-27 18:56:31 UTC (rev 15406)
@@ -0,0 +1,107 @@
+package org.jboss.envers.test.entities.onetomany.ids;
+
+import org.jboss.envers.Versioned;
+import org.jboss.envers.test.entities.ids.MulId;
+
+import javax.persistence.Entity;
+import javax.persistence.Id;
+import javax.persistence.OneToMany;
+import javax.persistence.IdClass;
+import java.util.Set;
+
+/**
+ * ReferencEd entity
+ * @author Adam Warski (adam at warski dot org)
+ */
+ at Entity
+ at IdClass(MulId.class)
+public class SetRefEdMulIdEntity {
+ @Id
+ private Integer id1;
+
+ @Id
+ private Integer id2;
+
+ @Versioned
+ private String data;
+
+ @Versioned
+ @OneToMany(mappedBy="reference")
+ private Set<SetRefIngMulIdEntity> reffering;
+
+ public SetRefEdMulIdEntity() {
+ }
+
+ public SetRefEdMulIdEntity(MulId id, String data) {
+ this.id1 = id.getId1();
+ this.id2 = id.getId2();
+ this.data = data;
+ }
+
+ public SetRefEdMulIdEntity(Integer id1, Integer id2, String data) {
+ this.id1 = id1;
+ this.id2 = id2;
+ this.data = data;
+ }
+
+ public SetRefEdMulIdEntity(String data) {
+ this.data = data;
+ }
+
+ public Integer getId1() {
+ return id1;
+ }
+
+ public void setId1(Integer id1) {
+ this.id1 = id1;
+ }
+
+ public Integer getId2() {
+ return id2;
+ }
+
+ public void setId2(Integer id2) {
+ this.id2 = id2;
+ }
+
+ public String getData() {
+ return data;
+ }
+
+ public void setData(String data) {
+ this.data = data;
+ }
+
+ public Set<SetRefIngMulIdEntity> getReffering() {
+ return reffering;
+ }
+
+ public void setReffering(Set<SetRefIngMulIdEntity> reffering) {
+ this.reffering = reffering;
+ }
+
+ public boolean equals(Object o) {
+ if (this == o) return true;
+ if (!(o instanceof SetRefEdMulIdEntity)) return false;
+
+ SetRefEdMulIdEntity that = (SetRefEdMulIdEntity) o;
+
+ if (data != null ? !data.equals(that.data) : that.data != null) return false;
+ if (id1 != null ? !id1.equals(that.id1) : that.id1 != null) return false;
+ if (id2 != null ? !id2.equals(that.id2) : that.id2 != null) return false;
+
+ return true;
+ }
+
+ public int hashCode() {
+ int result;
+ result = (id1 != null ? id1.hashCode() : 0);
+ result = 31 * result + (id2 != null ? id2.hashCode() : 0);
+ result = 31 * result + (data != null ? data.hashCode() : 0);
+ return result;
+ }
+
+ public String toString() {
+ return "SetRefEdMulIdEntity(id1 = " + id1 + ", id2 = " + id2 + ", data = " + data + ")";
+ }
+}
\ No newline at end of file
Added: core/trunk/envers/src/test/java/org/jboss/envers/test/entities/onetomany/ids/SetRefIngEmbIdEntity.java
===================================================================
--- core/trunk/envers/src/test/java/org/jboss/envers/test/entities/onetomany/ids/SetRefIngEmbIdEntity.java (rev 0)
+++ core/trunk/envers/src/test/java/org/jboss/envers/test/entities/onetomany/ids/SetRefIngEmbIdEntity.java 2008-10-27 18:56:31 UTC (rev 15406)
@@ -0,0 +1,83 @@
+package org.jboss.envers.test.entities.onetomany.ids;
+
+import org.jboss.envers.Versioned;
+import org.jboss.envers.test.entities.ids.EmbId;
+
+import javax.persistence.*;
+
+/**
+ * ReferencIng entity
+ * @author Adam Warski (adam at warski dot org)
+ */
+ at Entity
+public class SetRefIngEmbIdEntity {
+ @EmbeddedId
+ private EmbId id;
+
+ @Versioned
+ private String data;
+
+ @Versioned
+ @ManyToOne
+ private SetRefEdEmbIdEntity reference;
+
+ public SetRefIngEmbIdEntity() { }
+
+ public SetRefIngEmbIdEntity(EmbId id, String data, SetRefEdEmbIdEntity reference) {
+ this.id = id;
+ this.data = data;
+ this.reference = reference;
+ }
+
+ public SetRefIngEmbIdEntity(String data, SetRefEdEmbIdEntity reference) {
+ this.data = data;
+ this.reference = reference;
+ }
+
+ public EmbId getId() {
+ return id;
+ }
+
+ public void setId(EmbId id) {
+ this.id = id;
+ }
+
+ public String getData() {
+ return data;
+ }
+
+ public void setData(String data) {
+ this.data = data;
+ }
+
+ public SetRefEdEmbIdEntity getReference() {
+ return reference;
+ }
+
+ public void setReference(SetRefEdEmbIdEntity reference) {
+ this.reference = reference;
+ }
+
+ public boolean equals(Object o) {
+ if (this == o) return true;
+ if (!(o instanceof SetRefIngEmbIdEntity)) return false;
+
+ SetRefIngEmbIdEntity that = (SetRefIngEmbIdEntity) o;
+
+ if (data != null ? !data.equals(that.data) : that.data != null) return false;
+ if (id != null ? !id.equals(that.id) : that.id != null) return false;
+
+ return true;
+ }
+
+ public int hashCode() {
+ int result;
+ result = (id != null ? id.hashCode() : 0);
+ result = 31 * result + (data != null ? data.hashCode() : 0);
+ return result;
+ }
+
+ public String toString() {
+ return "SetRefIngEmbIdEntity(id = " + id + ", data = " + data + ")";
+ }
+}
\ No newline at end of file
Added: core/trunk/envers/src/test/java/org/jboss/envers/test/entities/onetomany/ids/SetRefIngMulIdEntity.java
===================================================================
--- core/trunk/envers/src/test/java/org/jboss/envers/test/entities/onetomany/ids/SetRefIngMulIdEntity.java (rev 0)
+++ core/trunk/envers/src/test/java/org/jboss/envers/test/entities/onetomany/ids/SetRefIngMulIdEntity.java 2008-10-27 18:56:31 UTC (rev 15406)
@@ -0,0 +1,105 @@
+package org.jboss.envers.test.entities.onetomany.ids;
+
+import org.jboss.envers.Versioned;
+import org.jboss.envers.test.entities.ids.MulId;
+
+import javax.persistence.*;
+
+/**
+ * ReferencIng entity
+ * @author Adam Warski (adam at warski dot org)
+ */
+ at Entity
+ at IdClass(MulId.class)
+public class SetRefIngMulIdEntity {
+ @Id
+ private Integer id1;
+
+ @Id
+ private Integer id2;
+
+ @Versioned
+ private String data;
+
+ @Versioned
+ @ManyToOne
+ private SetRefEdMulIdEntity reference;
+
+ public SetRefIngMulIdEntity() { }
+
+ public SetRefIngMulIdEntity(MulId id, String data, SetRefEdMulIdEntity reference) {
+ this.id1 = id.getId1();
+ this.id2 = id.getId2();
+ this.data = data;
+ this.reference = reference;
+ }
+
+ public SetRefIngMulIdEntity(Integer id1, Integer id2, String data, SetRefEdMulIdEntity reference) {
+ this.id1 = id1;
+ this.id2 = id2;
+ this.data = data;
+ this.reference = reference;
+ }
+
+ public SetRefIngMulIdEntity(String data, SetRefEdMulIdEntity reference) {
+ this.data = data;
+ this.reference = reference;
+ }
+
+ public Integer getId1() {
+ return id1;
+ }
+
+ public void setId1(Integer id1) {
+ this.id1 = id1;
+ }
+
+ public Integer getId2() {
+ return id2;
+ }
+
+ public void setId2(Integer id2) {
+ this.id2 = id2;
+ }
+
+ public String getData() {
+ return data;
+ }
+
+ public void setData(String data) {
+ this.data = data;
+ }
+
+ public SetRefEdMulIdEntity getReference() {
+ return reference;
+ }
+
+ public void setReference(SetRefEdMulIdEntity reference) {
+ this.reference = reference;
+ }
+
+ public boolean equals(Object o) {
+ if (this == o) return true;
+ if (!(o instanceof SetRefIngMulIdEntity)) return false;
+
+ SetRefIngMulIdEntity that = (SetRefIngMulIdEntity) o;
+
+ if (data != null ? !data.equals(that.data) : that.data != null) return false;
+ if (id1 != null ? !id1.equals(that.id1) : that.id1 != null) return false;
+ if (id2 != null ? !id2.equals(that.id2) : that.id2 != null) return false;
+
+ return true;
+ }
+
+ public int hashCode() {
+ int result;
+ result = (id1 != null ? id1.hashCode() : 0);
+ result = 31 * result + (id2 != null ? id2.hashCode() : 0);
+ result = 31 * result + (data != null ? data.hashCode() : 0);
+ return result;
+ }
+
+ public String toString() {
+ return "SetRefIngMulIdEntity(id1 = " + id1 + ", id2 = " + id2 + ", data = " + data + ")";
+ }
+}
\ No newline at end of file
Added: core/trunk/envers/src/test/java/org/jboss/envers/test/entities/reventity/CustomPropertyAccessRevEntity.java
===================================================================
--- core/trunk/envers/src/test/java/org/jboss/envers/test/entities/reventity/CustomPropertyAccessRevEntity.java (rev 0)
+++ core/trunk/envers/src/test/java/org/jboss/envers/test/entities/reventity/CustomPropertyAccessRevEntity.java 2008-10-27 18:56:31 UTC (rev 15406)
@@ -0,0 +1,59 @@
+package org.jboss.envers.test.entities.reventity;
+
+import org.jboss.envers.RevisionNumber;
+import org.jboss.envers.RevisionTimestamp;
+import org.jboss.envers.RevisionEntity;
+
+import javax.persistence.Id;
+import javax.persistence.GeneratedValue;
+import javax.persistence.Entity;
+
+/**
+ * @author Adam Warski (adam at warski dot org)
+ */
+ at Entity
+ at RevisionEntity
+public class CustomPropertyAccessRevEntity {
+ private int customId;
+
+ private long customTimestamp;
+
+ @Id
+ @GeneratedValue
+ @RevisionNumber
+ public int getCustomId() {
+ return customId;
+ }
+
+ public void setCustomId(int customId) {
+ this.customId = customId;
+ }
+
+ @RevisionTimestamp
+ public long getCustomTimestamp() {
+ return customTimestamp;
+ }
+
+ public void setCustomTimestamp(long customTimestamp) {
+ this.customTimestamp = customTimestamp;
+ }
+
+ public boolean equals(Object o) {
+ if (this == o) return true;
+ if (!(o instanceof CustomPropertyAccessRevEntity)) return false;
+
+ CustomPropertyAccessRevEntity that = (CustomPropertyAccessRevEntity) o;
+
+ if (customId != that.customId) return false;
+ if (customTimestamp != that.customTimestamp) return false;
+
+ return true;
+ }
+
+ public int hashCode() {
+ int result;
+ result = customId;
+ result = 31 * result + (int) (customTimestamp ^ (customTimestamp >>> 32));
+ return result;
+ }
+}
\ No newline at end of file
Added: core/trunk/envers/src/test/java/org/jboss/envers/test/entities/reventity/CustomRevEntity.java
===================================================================
--- core/trunk/envers/src/test/java/org/jboss/envers/test/entities/reventity/CustomRevEntity.java (rev 0)
+++ core/trunk/envers/src/test/java/org/jboss/envers/test/entities/reventity/CustomRevEntity.java 2008-10-27 18:56:31 UTC (rev 15406)
@@ -0,0 +1,59 @@
+package org.jboss.envers.test.entities.reventity;
+
+import org.jboss.envers.RevisionNumber;
+import org.jboss.envers.RevisionTimestamp;
+import org.jboss.envers.RevisionEntity;
+
+import javax.persistence.Id;
+import javax.persistence.GeneratedValue;
+import javax.persistence.Entity;
+
+/**
+ * @author Adam Warski (adam at warski dot org)
+ */
+ at Entity
+ at RevisionEntity
+public class CustomRevEntity {
+ @Id
+ @GeneratedValue
+ @RevisionNumber
+ private int customId;
+
+ @RevisionTimestamp
+ private long customTimestamp;
+
+ public int getCustomId() {
+ return customId;
+ }
+
+ public void setCustomId(int customId) {
+ this.customId = customId;
+ }
+
+ public long getCustomTimestamp() {
+ return customTimestamp;
+ }
+
+ public void setCustomTimestamp(long customTimestamp) {
+ this.customTimestamp = customTimestamp;
+ }
+
+ public boolean equals(Object o) {
+ if (this == o) return true;
+ if (!(o instanceof CustomRevEntity)) return false;
+
+ CustomRevEntity that = (CustomRevEntity) o;
+
+ if (customId != that.customId) return false;
+ if (customTimestamp != that.customTimestamp) return false;
+
+ return true;
+ }
+
+ public int hashCode() {
+ int result;
+ result = customId;
+ result = 31 * result + (int) (customTimestamp ^ (customTimestamp >>> 32));
+ return result;
+ }
+}
Added: core/trunk/envers/src/test/java/org/jboss/envers/test/integration/basic/BasicTestEntity1.java
===================================================================
--- core/trunk/envers/src/test/java/org/jboss/envers/test/integration/basic/BasicTestEntity1.java (rev 0)
+++ core/trunk/envers/src/test/java/org/jboss/envers/test/integration/basic/BasicTestEntity1.java 2008-10-27 18:56:31 UTC (rev 15406)
@@ -0,0 +1,82 @@
+package org.jboss.envers.test.integration.basic;
+
+import org.jboss.envers.Versioned;
+
+import javax.persistence.Entity;
+import javax.persistence.Id;
+import javax.persistence.GeneratedValue;
+
+/**
+ * @author Adam Warski (adam at warski dot org)
+ */
+ at Entity
+public class BasicTestEntity1 {
+ @Id
+ @GeneratedValue
+ private Integer id;
+
+ @Versioned
+ private String str1;
+
+ @Versioned
+ private long long1;
+
+ public BasicTestEntity1() {
+ }
+
+ public BasicTestEntity1(String str1, long long1) {
+ this.str1 = str1;
+ this.long1 = long1;
+ }
+
+ public BasicTestEntity1(Integer id, String str1, long long1) {
+ this.id = id;
+ this.str1 = str1;
+ this.long1 = long1;
+ }
+
+ public Integer getId() {
+ return id;
+ }
+
+ public void setId(Integer id) {
+ this.id = id;
+ }
+
+ public String getStr1() {
+ return str1;
+ }
+
+ public void setStr1(String str1) {
+ this.str1 = str1;
+ }
+
+ public long getLong1() {
+ return long1;
+ }
+
+ public void setLong1(long long1) {
+ this.long1 = long1;
+ }
+
+ public boolean equals(Object o) {
+ if (this == o) return true;
+ if (!(o instanceof BasicTestEntity1)) return false;
+
+ BasicTestEntity1 that = (BasicTestEntity1) o;
+
+ if (long1 != that.long1) return false;
+ if (id != null ? !id.equals(that.id) : that.id != null) return false;
+ if (str1 != null ? !str1.equals(that.str1) : that.str1 != null) return false;
+
+ return true;
+ }
+
+ public int hashCode() {
+ int result;
+ result = (id != null ? id.hashCode() : 0);
+ result = 31 * result + (str1 != null ? str1.hashCode() : 0);
+ result = 31 * result + (int) (long1 ^ (long1 >>> 32));
+ return result;
+ }
+}
Added: core/trunk/envers/src/test/java/org/jboss/envers/test/integration/basic/BasicTestEntity2.java
===================================================================
--- core/trunk/envers/src/test/java/org/jboss/envers/test/integration/basic/BasicTestEntity2.java (rev 0)
+++ core/trunk/envers/src/test/java/org/jboss/envers/test/integration/basic/BasicTestEntity2.java 2008-10-27 18:56:31 UTC (rev 15406)
@@ -0,0 +1,81 @@
+package org.jboss.envers.test.integration.basic;
+
+import org.jboss.envers.Versioned;
+
+import javax.persistence.Entity;
+import javax.persistence.Id;
+import javax.persistence.GeneratedValue;
+
+/**
+ * @author Adam Warski (adam at warski dot org)
+ */
+ at Entity
+public class BasicTestEntity2 {
+ @Id
+ @GeneratedValue
+ private Integer id;
+
+ @Versioned
+ private String str1;
+
+ private String str2;
+
+ public BasicTestEntity2() {
+ }
+
+ public BasicTestEntity2(String str1, String str2) {
+ this.str1 = str1;
+ this.str2 = str2;
+ }
+
+ public BasicTestEntity2(Integer id, String str1, String str2) {
+ this.id = id;
+ this.str1 = str1;
+ this.str2 = str2;
+ }
+
+ public Integer getId() {
+ return id;
+ }
+
+ public void setId(Integer id) {
+ this.id = id;
+ }
+
+ public String getStr1() {
+ return str1;
+ }
+
+ public void setStr1(String str1) {
+ this.str1 = str1;
+ }
+
+ public String getStr2() {
+ return str2;
+ }
+
+ public void setStr2(String str2) {
+ this.str2 = str2;
+ }
+
+ public boolean equals(Object o) {
+ if (this == o) return true;
+ if (!(o instanceof BasicTestEntity2)) return false;
+
+ BasicTestEntity2 that = (BasicTestEntity2) o;
+
+ if (id != null ? !id.equals(that.id) : that.id != null) return false;
+ if (str1 != null ? !str1.equals(that.str1) : that.str1 != null) return false;
+ if (str2 != null ? !str2.equals(that.str2) : that.str2 != null) return false;
+
+ return true;
+ }
+
+ public int hashCode() {
+ int result;
+ result = (id != null ? id.hashCode() : 0);
+ result = 31 * result + (str1 != null ? str1.hashCode() : 0);
+ result = 31 * result + (str2 != null ? str2.hashCode() : 0);
+ return result;
+ }
+}
\ No newline at end of file
Added: core/trunk/envers/src/test/java/org/jboss/envers/test/integration/basic/BasicTestEntity3.java
===================================================================
--- core/trunk/envers/src/test/java/org/jboss/envers/test/integration/basic/BasicTestEntity3.java (rev 0)
+++ core/trunk/envers/src/test/java/org/jboss/envers/test/integration/basic/BasicTestEntity3.java 2008-10-27 18:56:31 UTC (rev 15406)
@@ -0,0 +1,78 @@
+package org.jboss.envers.test.integration.basic;
+
+import javax.persistence.Entity;
+import javax.persistence.Id;
+import javax.persistence.GeneratedValue;
+
+/**
+ * @author Adam Warski (adam at warski dot org)
+ */
+ at Entity
+public class BasicTestEntity3 {
+ @Id
+ @GeneratedValue
+ private Integer id;
+
+ private String str1;
+
+ private String str2;
+
+ public BasicTestEntity3() {
+ }
+
+ public BasicTestEntity3(String str1, String str2) {
+ this.str1 = str1;
+ this.str2 = str2;
+ }
+
+ public BasicTestEntity3(Integer id, String str1, String str2) {
+ this.id = id;
+ this.str1 = str1;
+ this.str2 = str2;
+ }
+
+ public Integer getId() {
+ return id;
+ }
+
+ public void setId(Integer id) {
+ this.id = id;
+ }
+
+ public String getStr1() {
+ return str1;
+ }
+
+ public void setStr1(String str1) {
+ this.str1 = str1;
+ }
+
+ public String getStr2() {
+ return str2;
+ }
+
+ public void setStr2(String str2) {
+ this.str2 = str2;
+ }
+
+ public boolean equals(Object o) {
+ if (this == o) return true;
+ if (!(o instanceof BasicTestEntity3)) return false;
+
+ BasicTestEntity3 that = (BasicTestEntity3) o;
+
+ if (id != null ? !id.equals(that.id) : that.id != null) return false;
+ if (str1 != null ? !str1.equals(that.str1) : that.str1 != null) return false;
+ if (str2 != null ? !str2.equals(that.str2) : that.str2 != null) return false;
+
+ return true;
+ }
+
+ public int hashCode() {
+ int result;
+ result = (id != null ? id.hashCode() : 0);
+ result = 31 * result + (str1 != null ? str1.hashCode() : 0);
+ result = 31 * result + (str2 != null ? str2.hashCode() : 0);
+ return result;
+ }
+}
\ No newline at end of file
Added: core/trunk/envers/src/test/java/org/jboss/envers/test/integration/basic/BasicTestEntity4.java
===================================================================
--- core/trunk/envers/src/test/java/org/jboss/envers/test/integration/basic/BasicTestEntity4.java (rev 0)
+++ core/trunk/envers/src/test/java/org/jboss/envers/test/integration/basic/BasicTestEntity4.java 2008-10-27 18:56:31 UTC (rev 15406)
@@ -0,0 +1,81 @@
+package org.jboss.envers.test.integration.basic;
+
+import org.jboss.envers.Versioned;
+
+import javax.persistence.Entity;
+import javax.persistence.Id;
+import javax.persistence.GeneratedValue;
+
+/**
+ * @author Adam Warski (adam at warski dot org)
+ */
+ at Entity
+ at Versioned
+public class BasicTestEntity4 {
+ @Id
+ @GeneratedValue
+ private Integer id;
+
+ private String str1;
+
+ private String str2;
+
+ public BasicTestEntity4() {
+ }
+
+ public BasicTestEntity4(String str1, String str2) {
+ this.str1 = str1;
+ this.str2 = str2;
+ }
+
+ public BasicTestEntity4(Integer id, String str1, String str2) {
+ this.id = id;
+ this.str1 = str1;
+ this.str2 = str2;
+ }
+
+ public Integer getId() {
+ return id;
+ }
+
+ public void setId(Integer id) {
+ this.id = id;
+ }
+
+ public String getStr1() {
+ return str1;
+ }
+
+ public void setStr1(String str1) {
+ this.str1 = str1;
+ }
+
+ public String getStr2() {
+ return str2;
+ }
+
+ public void setStr2(String str2) {
+ this.str2 = str2;
+ }
+
+ public boolean equals(Object o) {
+ if (this == o) return true;
+ if (!(o instanceof BasicTestEntity4)) return false;
+
+ BasicTestEntity4 that = (BasicTestEntity4) o;
+
+ if (id != null ? !id.equals(that.id) : that.id != null) return false;
+ if (str1 != null ? !str1.equals(that.str1) : that.str1 != null) return false;
+ if (str2 != null ? !str2.equals(that.str2) : that.str2 != null) return false;
+
+ return true;
+ }
+
+ public int hashCode() {
+ int result;
+ result = (id != null ? id.hashCode() : 0);
+ result = 31 * result + (str1 != null ? str1.hashCode() : 0);
+ result = 31 * result + (str2 != null ? str2.hashCode() : 0);
+ return result;
+ }
+}
\ No newline at end of file
Added: core/trunk/envers/src/test/java/org/jboss/envers/test/integration/basic/Delete.java
===================================================================
--- core/trunk/envers/src/test/java/org/jboss/envers/test/integration/basic/Delete.java (rev 0)
+++ core/trunk/envers/src/test/java/org/jboss/envers/test/integration/basic/Delete.java 2008-10-27 18:56:31 UTC (rev 15406)
@@ -0,0 +1,113 @@
+package org.jboss.envers.test.integration.basic;
+
+import org.jboss.envers.test.AbstractEntityTest;
+import org.hibernate.ejb.Ejb3Configuration;
+import org.testng.annotations.BeforeClass;
+import org.testng.annotations.Test;
+
+import javax.persistence.EntityManager;
+import java.util.Arrays;
+
+/**
+ * @author Adam Warski (adam at warski dot org)
+ */
+public class Delete extends AbstractEntityTest {
+ private Integer id1;
+ private Integer id2;
+ private Integer id3;
+
+ public void configure(Ejb3Configuration cfg) {
+ cfg.addAnnotatedClass(BasicTestEntity2.class);
+ }
+
+ @BeforeClass(dependsOnMethods = "init")
+ public void initData() {
+ // Revision 1
+ EntityManager em = getEntityManager();
+ em.getTransaction().begin();
+
+ BasicTestEntity2 bte1 = new BasicTestEntity2("x", "a");
+ BasicTestEntity2 bte2 = new BasicTestEntity2("y", "b");
+ BasicTestEntity2 bte3 = new BasicTestEntity2("z", "c");
+ em.persist(bte1);
+ em.persist(bte2);
+ em.persist(bte3);
+
+ em.getTransaction().commit();
+
+ // Revision 2
+ em = getEntityManager();
+ em.getTransaction().begin();
+
+ bte1 = em.find(BasicTestEntity2.class, bte1.getId());
+ bte2 = em.find(BasicTestEntity2.class, bte2.getId());
+ bte3 = em.find(BasicTestEntity2.class, bte3.getId());
+ bte1.setStr1("x2");
+ bte2.setStr2("b2");
+ em.remove(bte3);
+
+ em.getTransaction().commit();
+
+ // Revision 3
+ em = getEntityManager();
+ em.getTransaction().begin();
+
+ bte2 = em.find(BasicTestEntity2.class, bte2.getId());
+ em.remove(bte2);
+
+ em.getTransaction().commit();
+
+ // Revision 4
+ em = getEntityManager();
+ em.getTransaction().begin();
+
+ bte1 = em.find(BasicTestEntity2.class, bte1.getId());
+ em.remove(bte1);
+
+ em.getTransaction().commit();
+
+ id1 = bte1.getId();
+ id2 = bte2.getId();
+ id3 = bte3.getId();
+ }
+
+ @Test
+ public void testRevisionsCounts() {
+ assert Arrays.asList(1, 2, 4).equals(getVersionsReader().getRevisions(BasicTestEntity2.class, id1));
+
+ assert Arrays.asList(1, 3).equals(getVersionsReader().getRevisions(BasicTestEntity2.class, id2));
+
+ assert Arrays.asList(1, 2).equals(getVersionsReader().getRevisions(BasicTestEntity2.class, id3));
+ }
+
+ @Test
+ public void testHistoryOfId1() {
+ BasicTestEntity2 ver1 = new BasicTestEntity2(id1, "x", null);
+ BasicTestEntity2 ver2 = new BasicTestEntity2(id1, "x2", null);
+
+ assert getVersionsReader().find(BasicTestEntity2.class, id1, 1).equals(ver1);
+ assert getVersionsReader().find(BasicTestEntity2.class, id1, 2).equals(ver2);
+ assert getVersionsReader().find(BasicTestEntity2.class, id1, 3).equals(ver2);
+ assert getVersionsReader().find(BasicTestEntity2.class, id1, 4) == null;
+ }
+
+ @Test
+ public void testHistoryOfId2() {
+ BasicTestEntity2 ver1 = new BasicTestEntity2(id2, "y", null);
+
+ assert getVersionsReader().find(BasicTestEntity2.class, id2, 1).equals(ver1);
+ assert getVersionsReader().find(BasicTestEntity2.class, id2, 2).equals(ver1);
+ assert getVersionsReader().find(BasicTestEntity2.class, id2, 3) == null;
+ assert getVersionsReader().find(BasicTestEntity2.class, id2, 4) == null;
+ }
+
+ @Test
+ public void testHistoryOfId3() {
+ BasicTestEntity2 ver1 = new BasicTestEntity2(id3, "z", null);
+
+ assert getVersionsReader().find(BasicTestEntity2.class, id3, 1).equals(ver1);
+ assert getVersionsReader().find(BasicTestEntity2.class, id3, 2) == null;
+ assert getVersionsReader().find(BasicTestEntity2.class, id3, 3) == null;
+ assert getVersionsReader().find(BasicTestEntity2.class, id3, 4) == null;
+ }
+}
Added: core/trunk/envers/src/test/java/org/jboss/envers/test/integration/basic/GlobalVersioned.java
===================================================================
--- core/trunk/envers/src/test/java/org/jboss/envers/test/integration/basic/GlobalVersioned.java (rev 0)
+++ core/trunk/envers/src/test/java/org/jboss/envers/test/integration/basic/GlobalVersioned.java 2008-10-27 18:56:31 UTC (rev 15406)
@@ -0,0 +1,50 @@
+package org.jboss.envers.test.integration.basic;
+
+import org.jboss.envers.test.AbstractEntityTest;
+import org.hibernate.ejb.Ejb3Configuration;
+import org.testng.annotations.Test;
+import org.testng.annotations.BeforeClass;
+
+import javax.persistence.EntityManager;
+import java.util.Arrays;
+
+/**
+ * @author Adam Warski (adam at warski dot org)
+ */
+public class GlobalVersioned extends AbstractEntityTest {
+ private Integer id1;
+
+ public void configure(Ejb3Configuration cfg) {
+ cfg.addAnnotatedClass(BasicTestEntity4.class);
+ }
+
+ @BeforeClass(dependsOnMethods = "init")
+ public void initData() {
+ EntityManager em = getEntityManager();
+ em.getTransaction().begin();
+ BasicTestEntity4 bte1 = new BasicTestEntity4("x", "y");
+ em.persist(bte1);
+ id1 = bte1.getId();
+ em.getTransaction().commit();
+
+ em.getTransaction().begin();
+ bte1 = em.find(BasicTestEntity4.class, id1);
+ bte1.setStr1("a");
+ bte1.setStr2("b");
+ em.getTransaction().commit();
+ }
+
+ @Test
+ public void testRevisionsCounts() {
+ assert Arrays.asList(1, 2).equals(getVersionsReader().getRevisions(BasicTestEntity4.class, id1));
+ }
+
+ @Test
+ public void testHistoryOfId1() {
+ BasicTestEntity4 ver1 = new BasicTestEntity4(id1, "x", "y");
+ BasicTestEntity4 ver2 = new BasicTestEntity4(id1, "a", "b");
+
+ assert getVersionsReader().find(BasicTestEntity4.class, id1, 1).equals(ver1);
+ assert getVersionsReader().find(BasicTestEntity4.class, id1, 2).equals(ver2);
+ }
+}
\ No newline at end of file
Added: core/trunk/envers/src/test/java/org/jboss/envers/test/integration/basic/ManyOperationsInTransaction.java
===================================================================
--- core/trunk/envers/src/test/java/org/jboss/envers/test/integration/basic/ManyOperationsInTransaction.java (rev 0)
+++ core/trunk/envers/src/test/java/org/jboss/envers/test/integration/basic/ManyOperationsInTransaction.java 2008-10-27 18:56:31 UTC (rev 15406)
@@ -0,0 +1,103 @@
+package org.jboss.envers.test.integration.basic;
+
+import org.jboss.envers.test.AbstractEntityTest;
+import org.hibernate.ejb.Ejb3Configuration;
+import org.testng.annotations.BeforeClass;
+import org.testng.annotations.Test;
+
+import javax.persistence.EntityManager;
+import java.util.Arrays;
+
+/**
+ * @author Adam Warski (adam at warski dot org)
+ */
+public class ManyOperationsInTransaction extends AbstractEntityTest {
+ private Integer id1;
+ private Integer id2;
+ private Integer id3;
+
+ public void configure(Ejb3Configuration cfg) {
+ cfg.addAnnotatedClass(BasicTestEntity1.class);
+ }
+
+ @BeforeClass(dependsOnMethods = "init")
+ public void initData() {
+ // Revision 1
+ EntityManager em = getEntityManager();
+ em.getTransaction().begin();
+
+ BasicTestEntity1 bte1 = new BasicTestEntity1("x", 1);
+ BasicTestEntity1 bte2 = new BasicTestEntity1("y", 20);
+ em.persist(bte1);
+ em.persist(bte2);
+
+ em.getTransaction().commit();
+
+ // Revision 2
+ em.getTransaction().begin();
+
+ bte1 = em.find(BasicTestEntity1.class, bte1.getId());
+ bte2 = em.find(BasicTestEntity1.class, bte2.getId());
+ BasicTestEntity1 bte3 = new BasicTestEntity1("z", 300);
+ bte1.setStr1("x2");
+ bte2.setLong1(21);
+ em.persist(bte3);
+
+ em.getTransaction().commit();
+
+ // Revision 3
+ em.getTransaction().begin();
+
+ bte2 = em.find(BasicTestEntity1.class, bte2.getId());
+ bte3 = em.find(BasicTestEntity1.class, bte3.getId());
+ bte2.setStr1("y3");
+ bte2.setLong1(22);
+ bte3.setStr1("z3");
+
+ em.getTransaction().commit();
+
+ id1 = bte1.getId();
+ id2 = bte2.getId();
+ id3 = bte3.getId();
+ }
+
+ @Test
+ public void testRevisionsCounts() {
+ assert Arrays.asList(1, 2).equals(getVersionsReader().getRevisions(BasicTestEntity1.class, id1));
+
+ assert Arrays.asList(1, 2, 3).equals(getVersionsReader().getRevisions(BasicTestEntity1.class, id2));
+
+ assert Arrays.asList(2, 3).equals(getVersionsReader().getRevisions(BasicTestEntity1.class, id3));
+ }
+
+ @Test
+ public void testHistoryOfId1() {
+ BasicTestEntity1 ver1 = new BasicTestEntity1(id1, "x", 1);
+ BasicTestEntity1 ver2 = new BasicTestEntity1(id1, "x2", 1);
+
+ assert getVersionsReader().find(BasicTestEntity1.class, id1, 1).equals(ver1);
+ assert getVersionsReader().find(BasicTestEntity1.class, id1, 2).equals(ver2);
+ assert getVersionsReader().find(BasicTestEntity1.class, id1, 3).equals(ver2);
+ }
+
+ @Test
+ public void testHistoryOfId2() {
+ BasicTestEntity1 ver1 = new BasicTestEntity1(id2, "y", 20);
+ BasicTestEntity1 ver2 = new BasicTestEntity1(id2, "y", 21);
+ BasicTestEntity1 ver3 = new BasicTestEntity1(id2, "y3", 22);
+
+ assert getVersionsReader().find(BasicTestEntity1.class, id2, 1).equals(ver1);
+ assert getVersionsReader().find(BasicTestEntity1.class, id2, 2).equals(ver2);
+ assert getVersionsReader().find(BasicTestEntity1.class, id2, 3).equals(ver3);
+ }
+
+ @Test
+ public void testHistoryOfId3() {
+ BasicTestEntity1 ver1 = new BasicTestEntity1(id3, "z", 300);
+ BasicTestEntity1 ver2 = new BasicTestEntity1(id3, "z3", 300);
+
+ assert getVersionsReader().find(BasicTestEntity1.class, id3, 1) == null;
+ assert getVersionsReader().find(BasicTestEntity1.class, id3, 2).equals(ver1);
+ assert getVersionsReader().find(BasicTestEntity1.class, id3, 3).equals(ver2);
+ }
+}
Added: core/trunk/envers/src/test/java/org/jboss/envers/test/integration/basic/NotVersioned.java
===================================================================
--- core/trunk/envers/src/test/java/org/jboss/envers/test/integration/basic/NotVersioned.java (rev 0)
+++ core/trunk/envers/src/test/java/org/jboss/envers/test/integration/basic/NotVersioned.java 2008-10-27 18:56:31 UTC (rev 15406)
@@ -0,0 +1,46 @@
+package org.jboss.envers.test.integration.basic;
+
+import org.jboss.envers.test.AbstractEntityTest;
+import org.jboss.envers.exception.NotVersionedException;
+import org.hibernate.ejb.Ejb3Configuration;
+import org.testng.annotations.Test;
+import org.testng.annotations.BeforeClass;
+
+import javax.persistence.EntityManager;
+
+/**
+ * @author Adam Warski (adam at warski dot org)
+ */
+public class NotVersioned extends AbstractEntityTest {
+ private Integer id1;
+
+ public void configure(Ejb3Configuration cfg) {
+ cfg.addAnnotatedClass(BasicTestEntity3.class);
+ }
+
+ @BeforeClass(dependsOnMethods = "init")
+ public void initData() {
+ EntityManager em = getEntityManager();
+ em.getTransaction().begin();
+ BasicTestEntity3 bte1 = new BasicTestEntity3("x", "y");
+ em.persist(bte1);
+ id1 = bte1.getId();
+ em.getTransaction().commit();
+
+ em.getTransaction().begin();
+ bte1 = em.find(BasicTestEntity3.class, id1);
+ bte1.setStr1("a");
+ bte1.setStr2("b");
+ em.getTransaction().commit();
+ }
+
+ @Test(expectedExceptions = NotVersionedException.class)
+ public void testRevisionsCounts() {
+ getVersionsReader().getRevisions(BasicTestEntity3.class, id1);
+ }
+
+ @Test(expectedExceptions = NotVersionedException.class)
+ public void testHistoryOfId1() {
+ getVersionsReader().find(BasicTestEntity3.class, id1, 1);
+ }
+}
\ No newline at end of file
Added: core/trunk/envers/src/test/java/org/jboss/envers/test/integration/basic/NullProperties.java
===================================================================
--- core/trunk/envers/src/test/java/org/jboss/envers/test/integration/basic/NullProperties.java (rev 0)
+++ core/trunk/envers/src/test/java/org/jboss/envers/test/integration/basic/NullProperties.java 2008-10-27 18:56:31 UTC (rev 15406)
@@ -0,0 +1,78 @@
+package org.jboss.envers.test.integration.basic;
+
+import org.jboss.envers.test.AbstractEntityTest;
+import org.hibernate.ejb.Ejb3Configuration;
+import org.testng.annotations.Test;
+import org.testng.annotations.BeforeClass;
+
+import javax.persistence.EntityManager;
+import java.util.Arrays;
+
+/**
+ * @author Adam Warski (adam at warski dot org)
+ */
+public class NullProperties extends AbstractEntityTest {
+ private Integer id1;
+ private Integer id2;
+
+ public void configure(Ejb3Configuration cfg) {
+ cfg.addAnnotatedClass(BasicTestEntity1.class);
+ }
+
+ private Integer addNewEntity(String str, long lng) {
+ EntityManager em = getEntityManager();
+ em.getTransaction().begin();
+ BasicTestEntity1 bte1 = new BasicTestEntity1(str, lng);
+ em.persist(bte1);
+ em.getTransaction().commit();
+
+ return bte1.getId();
+ }
+
+ private void modifyEntity(Integer id, String str, long lng) {
+ EntityManager em = getEntityManager();
+ em.getTransaction().begin();
+ BasicTestEntity1 bte1 = em.find(BasicTestEntity1.class, id);
+ bte1.setLong1(lng);
+ bte1.setStr1(str);
+ em.getTransaction().commit();
+ }
+
+ @BeforeClass(dependsOnMethods = "init")
+ public void initData() {
+ id1 = addNewEntity("x", 1); // rev 1
+ id2 = addNewEntity(null, 20); // rev 2
+
+ modifyEntity(id1, null, 1); // rev 3
+ modifyEntity(id2, "y2", 20); // rev 4
+ }
+
+ @Test
+ public void testRevisionsCounts() {
+ assert Arrays.asList(1, 3).equals(getVersionsReader().getRevisions(BasicTestEntity1.class, id1));
+
+ assert Arrays.asList(2, 4).equals(getVersionsReader().getRevisions(BasicTestEntity1.class, id2));
+ }
+
+ @Test
+ public void testHistoryOfId1() {
+ BasicTestEntity1 ver1 = new BasicTestEntity1(id1, "x", 1);
+ BasicTestEntity1 ver2 = new BasicTestEntity1(id1, null, 1);
+
+ assert getVersionsReader().find(BasicTestEntity1.class, id1, 1).equals(ver1);
+ assert getVersionsReader().find(BasicTestEntity1.class, id1, 2).equals(ver1);
+ assert getVersionsReader().find(BasicTestEntity1.class, id1, 3).equals(ver2);
+ assert getVersionsReader().find(BasicTestEntity1.class, id1, 4).equals(ver2);
+ }
+
+ @Test
+ public void testHistoryOfId2() {
+ BasicTestEntity1 ver1 = new BasicTestEntity1(id2, null, 20);
+ BasicTestEntity1 ver2 = new BasicTestEntity1(id2, "y2", 20);
+
+ assert getVersionsReader().find(BasicTestEntity1.class, id2, 1) == null;
+ assert getVersionsReader().find(BasicTestEntity1.class, id2, 2).equals(ver1);
+ assert getVersionsReader().find(BasicTestEntity1.class, id2, 3).equals(ver1);
+ assert getVersionsReader().find(BasicTestEntity1.class, id2, 4).equals(ver2);
+ }
+}
\ No newline at end of file
Added: core/trunk/envers/src/test/java/org/jboss/envers/test/integration/basic/Simple.java
===================================================================
--- core/trunk/envers/src/test/java/org/jboss/envers/test/integration/basic/Simple.java (rev 0)
+++ core/trunk/envers/src/test/java/org/jboss/envers/test/integration/basic/Simple.java 2008-10-27 18:56:31 UTC (rev 15406)
@@ -0,0 +1,50 @@
+package org.jboss.envers.test.integration.basic;
+
+import org.jboss.envers.test.AbstractEntityTest;
+import org.jboss.envers.test.entities.IntTestEntity;
+import org.hibernate.ejb.Ejb3Configuration;
+import org.testng.annotations.Test;
+import org.testng.annotations.BeforeClass;
+
+import javax.persistence.EntityManager;
+import java.util.Arrays;
+
+/**
+ * @author Adam Warski (adam at warski dot org)
+ */
+public class Simple extends AbstractEntityTest {
+ private Integer id1;
+
+ public void configure(Ejb3Configuration cfg) {
+ cfg.addAnnotatedClass(IntTestEntity.class);
+ }
+
+ @BeforeClass(dependsOnMethods = "init")
+ public void initData() {
+ EntityManager em = getEntityManager();
+ em.getTransaction().begin();
+ IntTestEntity ite = new IntTestEntity(10);
+ em.persist(ite);
+ id1 = ite.getId();
+ em.getTransaction().commit();
+
+ em.getTransaction().begin();
+ ite = em.find(IntTestEntity.class, id1);
+ ite.setNumber(20);
+ em.getTransaction().commit();
+ }
+
+ @Test
+ public void testRevisionsCounts() {
+ assert Arrays.asList(1, 2).equals(getVersionsReader().getRevisions(IntTestEntity.class, id1));
+ }
+
+ @Test
+ public void testHistoryOfId1() {
+ IntTestEntity ver1 = new IntTestEntity(10, id1);
+ IntTestEntity ver2 = new IntTestEntity(20, id1);
+
+ assert getVersionsReader().find(IntTestEntity.class, id1, 1).equals(ver1);
+ assert getVersionsReader().find(IntTestEntity.class, id1, 2).equals(ver2);
+ }
+}
\ No newline at end of file
Added: core/trunk/envers/src/test/java/org/jboss/envers/test/integration/basic/SingleOperationInTransaction.java
===================================================================
--- core/trunk/envers/src/test/java/org/jboss/envers/test/integration/basic/SingleOperationInTransaction.java (rev 0)
+++ core/trunk/envers/src/test/java/org/jboss/envers/test/integration/basic/SingleOperationInTransaction.java 2008-10-27 18:56:31 UTC (rev 15406)
@@ -0,0 +1,136 @@
+package org.jboss.envers.test.integration.basic;
+
+import org.jboss.envers.test.AbstractEntityTest;
+import org.jboss.envers.exception.RevisionDoesNotExistException;
+import org.hibernate.ejb.Ejb3Configuration;
+import org.testng.annotations.Test;
+import org.testng.annotations.BeforeClass;
+
+import javax.persistence.EntityManager;
+import java.util.Arrays;
+
+/**
+ * @author Adam Warski (adam at warski dot org)
+ */
+public class SingleOperationInTransaction extends AbstractEntityTest {
+ private Integer id1;
+ private Integer id2;
+ private Integer id3;
+
+ public void configure(Ejb3Configuration cfg) {
+ cfg.addAnnotatedClass(BasicTestEntity1.class);
+ }
+
+ private Integer addNewEntity(String str, long lng) {
+ EntityManager em = getEntityManager();
+ em.getTransaction().begin();
+ BasicTestEntity1 bte1 = new BasicTestEntity1(str, lng);
+ em.persist(bte1);
+ em.getTransaction().commit();
+
+ return bte1.getId();
+ }
+
+ private void modifyEntity(Integer id, String str, long lng) {
+ EntityManager em = getEntityManager();
+ em.getTransaction().begin();
+ BasicTestEntity1 bte1 = em.find(BasicTestEntity1.class, id);
+ bte1.setLong1(lng);
+ bte1.setStr1(str);
+ em.getTransaction().commit();
+ }
+
+ @BeforeClass(dependsOnMethods = "init")
+ public void initData() {
+ id1 = addNewEntity("x", 1); // rev 1
+ id2 = addNewEntity("y", 20); // rev 2
+ id3 = addNewEntity("z", 30); // rev 3
+
+ modifyEntity(id1, "x2", 2); // rev 4
+ modifyEntity(id2, "y2", 20); // rev 5
+ modifyEntity(id1, "x3", 3); // rev 6
+ modifyEntity(id1, "x3", 3); // no rev
+ modifyEntity(id2, "y3", 21); // rev 7
+ }
+
+ @Test
+ public void testRevisionsCounts() {
+ assert Arrays.asList(1, 4, 6).equals(getVersionsReader().getRevisions(BasicTestEntity1.class, id1));
+
+ assert Arrays.asList(2, 5, 7).equals(getVersionsReader().getRevisions(BasicTestEntity1.class, id2));
+
+ assert Arrays.asList(3).equals(getVersionsReader().getRevisions(BasicTestEntity1.class, id3));
+ }
+
+ @Test
+ public void testRevisionsDates() {
+ for (int i=1; i<7; i++) {
+ assert getVersionsReader().getRevisionDate(i).getTime() <=
+ getVersionsReader().getRevisionDate(i+1).getTime();
+ }
+ }
+
+ @Test(expectedExceptions = RevisionDoesNotExistException.class)
+ public void testNotExistingRevision() {
+ getVersionsReader().getRevisionDate(8);
+ }
+
+ @Test(expectedExceptions = IllegalArgumentException.class)
+ public void testIllegalRevision() {
+ getVersionsReader().getRevisionDate(0);
+ }
+
+ @Test
+ public void testHistoryOfId1() {
+ BasicTestEntity1 ver1 = new BasicTestEntity1(id1, "x", 1);
+ BasicTestEntity1 ver2 = new BasicTestEntity1(id1, "x2", 2);
+ BasicTestEntity1 ver3 = new BasicTestEntity1(id1, "x3", 3);
+
+ assert getVersionsReader().find(BasicTestEntity1.class, id1, 1).equals(ver1);
+ assert getVersionsReader().find(BasicTestEntity1.class, id1, 2).equals(ver1);
+ assert getVersionsReader().find(BasicTestEntity1.class, id1, 3).equals(ver1);
+ assert getVersionsReader().find(BasicTestEntity1.class, id1, 4).equals(ver2);
+ assert getVersionsReader().find(BasicTestEntity1.class, id1, 5).equals(ver2);
+ assert getVersionsReader().find(BasicTestEntity1.class, id1, 6).equals(ver3);
+ assert getVersionsReader().find(BasicTestEntity1.class, id1, 7).equals(ver3);
+ }
+
+ @Test
+ public void testHistoryOfId2() {
+ BasicTestEntity1 ver1 = new BasicTestEntity1(id2, "y", 20);
+ BasicTestEntity1 ver2 = new BasicTestEntity1(id2, "y2", 20);
+ BasicTestEntity1 ver3 = new BasicTestEntity1(id2, "y3", 21);
+
+ assert getVersionsReader().find(BasicTestEntity1.class, id2, 1) == null;
+ assert getVersionsReader().find(BasicTestEntity1.class, id2, 2).equals(ver1);
+ assert getVersionsReader().find(BasicTestEntity1.class, id2, 3).equals(ver1);
+ assert getVersionsReader().find(BasicTestEntity1.class, id2, 4).equals(ver1);
+ assert getVersionsReader().find(BasicTestEntity1.class, id2, 5).equals(ver2);
+ assert getVersionsReader().find(BasicTestEntity1.class, id2, 6).equals(ver2);
+ assert getVersionsReader().find(BasicTestEntity1.class, id2, 7).equals(ver3);
+ }
+
+ @Test
+ public void testHistoryOfId3() {
+ BasicTestEntity1 ver1 = new BasicTestEntity1(id3, "z", 30);
+
+ assert getVersionsReader().find(BasicTestEntity1.class, id3, 1) == null;
+ assert getVersionsReader().find(BasicTestEntity1.class, id3, 2) == null;
+ assert getVersionsReader().find(BasicTestEntity1.class, id3, 3).equals(ver1);
+ assert getVersionsReader().find(BasicTestEntity1.class, id3, 4).equals(ver1);
+ assert getVersionsReader().find(BasicTestEntity1.class, id3, 5).equals(ver1);
+ assert getVersionsReader().find(BasicTestEntity1.class, id3, 6).equals(ver1);
+ assert getVersionsReader().find(BasicTestEntity1.class, id3, 7).equals(ver1);
+ }
+
+ @Test
+ public void testHistoryOfNotExistingEntity() {
+ assert getVersionsReader().find(BasicTestEntity1.class, id1+id2+id3, 1) == null;
+ assert getVersionsReader().find(BasicTestEntity1.class, id1+id2+id3, 7) == null;
+ }
+
+ @Test
+ public void testRevisionsOfNotExistingEntity() {
+ assert getVersionsReader().getRevisions(BasicTestEntity1.class, id1+id2+id3).size() == 0;
+ }
+}
Added: core/trunk/envers/src/test/java/org/jboss/envers/test/integration/basic/UnversionedPropertiesChange.java
===================================================================
--- core/trunk/envers/src/test/java/org/jboss/envers/test/integration/basic/UnversionedPropertiesChange.java (rev 0)
+++ core/trunk/envers/src/test/java/org/jboss/envers/test/integration/basic/UnversionedPropertiesChange.java 2008-10-27 18:56:31 UTC (rev 15406)
@@ -0,0 +1,61 @@
+package org.jboss.envers.test.integration.basic;
+
+import org.jboss.envers.test.AbstractEntityTest;
+import org.hibernate.ejb.Ejb3Configuration;
+import org.testng.annotations.BeforeClass;
+import org.testng.annotations.Test;
+
+import javax.persistence.EntityManager;
+import java.util.Arrays;
+
+/**
+ * @author Adam Warski (adam at warski dot org)
+ */
+public class UnversionedPropertiesChange extends AbstractEntityTest {
+ private Integer id1;
+
+ public void configure(Ejb3Configuration cfg) {
+ cfg.addAnnotatedClass(BasicTestEntity2.class);
+ }
+
+ private Integer addNewEntity(String str1, String str2) {
+ EntityManager em = getEntityManager();
+ em.getTransaction().begin();
+ BasicTestEntity2 bte2 = new BasicTestEntity2(str1, str2);
+ em.persist(bte2);
+ em.getTransaction().commit();
+
+ return bte2.getId();
+ }
+
+ private void modifyEntity(Integer id, String str1, String str2) {
+ EntityManager em = getEntityManager();
+ em.getTransaction().begin();
+ BasicTestEntity2 bte2 = em.find(BasicTestEntity2.class, id);
+ bte2.setStr1(str1);
+ bte2.setStr2(str2);
+ em.getTransaction().commit();
+ }
+
+ @BeforeClass(dependsOnMethods = "init")
+ public void initData() {
+ id1 = addNewEntity("x", "a"); // rev 1
+ modifyEntity(id1, "x", "a"); // no rev
+ modifyEntity(id1, "y", "b"); // rev 2
+ modifyEntity(id1, "y", "c"); // no rev
+ }
+
+ @Test
+ public void testRevisionsCounts() {
+ assert Arrays.asList(1, 2).equals(getVersionsReader().getRevisions(BasicTestEntity2.class, id1));
+ }
+
+ @Test
+ public void testHistoryOfId1() {
+ BasicTestEntity2 ver1 = new BasicTestEntity2(id1, "x", null);
+ BasicTestEntity2 ver2 = new BasicTestEntity2(id1, "y", null);
+
+ assert getVersionsReader().find(BasicTestEntity2.class, id1, 1).equals(ver1);
+ assert getVersionsReader().find(BasicTestEntity2.class, id1, 2).equals(ver2);
+ }
+}
Added: core/trunk/envers/src/test/java/org/jboss/envers/test/integration/basic/UnversionedProperty.java
===================================================================
--- core/trunk/envers/src/test/java/org/jboss/envers/test/integration/basic/UnversionedProperty.java (rev 0)
+++ core/trunk/envers/src/test/java/org/jboss/envers/test/integration/basic/UnversionedProperty.java 2008-10-27 18:56:31 UTC (rev 15406)
@@ -0,0 +1,54 @@
+package org.jboss.envers.test.integration.basic;
+
+import org.hibernate.ejb.Ejb3Configuration;
+import org.testng.annotations.BeforeClass;
+import org.testng.annotations.Test;
+import org.jboss.envers.test.entities.UnversionedEntity;
+import org.jboss.envers.test.AbstractEntityTest;
+
+import javax.persistence.EntityManager;
+import java.util.Arrays;
+
+/**
+ * @author Adam Warski (adam at warski dot org)
+ */
+public class UnversionedProperty extends AbstractEntityTest {
+ private Integer id1;
+
+ public void configure(Ejb3Configuration cfg) {
+ cfg.addAnnotatedClass(UnversionedEntity.class);
+ }
+
+ @BeforeClass(dependsOnMethods = "init")
+ public void initData() {
+ EntityManager em = getEntityManager();
+
+ // Rev 1
+ em.getTransaction().begin();
+ UnversionedEntity ue1 = new UnversionedEntity("a1", "b1");
+ em.persist(ue1);
+ id1 = ue1.getId();
+ em.getTransaction().commit();
+
+ // Rev 2
+ em.getTransaction().begin();
+ ue1 = em.find(UnversionedEntity.class, id1);
+ ue1.setData1("a2");
+ ue1.setData2("b2");
+ em.getTransaction().commit();
+ }
+
+ @Test
+ public void testRevisionsCounts() {
+ assert Arrays.asList(1, 2).equals(getVersionsReader().getRevisions(UnversionedEntity.class, id1));
+ }
+
+ @Test
+ public void testHistoryOfId1() {
+ UnversionedEntity rev1 = new UnversionedEntity(id1, "a1", null);
+ UnversionedEntity rev2 = new UnversionedEntity(id1, "a2", null);
+
+ assert getVersionsReader().find(UnversionedEntity.class, id1, 1).equals(rev1);
+ assert getVersionsReader().find(UnversionedEntity.class, id1, 2).equals(rev2);
+ }
+}
Added: core/trunk/envers/src/test/java/org/jboss/envers/test/integration/cache/OneToManyCache.java
===================================================================
--- core/trunk/envers/src/test/java/org/jboss/envers/test/integration/cache/OneToManyCache.java (rev 0)
+++ core/trunk/envers/src/test/java/org/jboss/envers/test/integration/cache/OneToManyCache.java 2008-10-27 18:56:31 UTC (rev 15406)
@@ -0,0 +1,120 @@
+package org.jboss.envers.test.integration.cache;
+
+import org.jboss.envers.test.AbstractEntityTest;
+import org.jboss.envers.test.entities.onetomany.SetRefEdEntity;
+import org.jboss.envers.test.entities.onetomany.SetRefIngEntity;
+import org.testng.annotations.BeforeClass;
+import org.testng.annotations.Test;
+import org.hibernate.ejb.Ejb3Configuration;
+
+import javax.persistence.EntityManager;
+
+/**
+ * @author Adam Warski (adam at warski dot org)
+ */
+ at SuppressWarnings({"ObjectEquality"})
+public class OneToManyCache extends AbstractEntityTest {
+ private Integer ed1_id;
+ private Integer ed2_id;
+
+ private Integer ing1_id;
+ private Integer ing2_id;
+
+ public void configure(Ejb3Configuration cfg) {
+ cfg.addAnnotatedClass(SetRefEdEntity.class);
+ cfg.addAnnotatedClass(SetRefIngEntity.class);
+ }
+
+ @BeforeClass(dependsOnMethods = "init")
+ public void initData() {
+ EntityManager em = getEntityManager();
+
+ SetRefEdEntity ed1 = new SetRefEdEntity(1, "data_ed_1");
+ SetRefEdEntity ed2 = new SetRefEdEntity(2, "data_ed_2");
+
+ SetRefIngEntity ing1 = new SetRefIngEntity(1, "data_ing_1");
+ SetRefIngEntity ing2 = new SetRefIngEntity(2, "data_ing_2");
+
+ // Revision 1
+ em.getTransaction().begin();
+
+ em.persist(ed1);
+ em.persist(ed2);
+
+ ing1.setReference(ed1);
+ ing2.setReference(ed1);
+
+ em.persist(ing1);
+ em.persist(ing2);
+
+ em.getTransaction().commit();
+
+ // Revision 2
+ em.getTransaction().begin();
+
+ ing1 = em.find(SetRefIngEntity.class, ing1.getId());
+ ing2 = em.find(SetRefIngEntity.class, ing2.getId());
+ ed2 = em.find(SetRefEdEntity.class, ed2.getId());
+
+ ing1.setReference(ed2);
+ ing2.setReference(ed2);
+
+ em.getTransaction().commit();
+
+ //
+
+ ed1_id = ed1.getId();
+ ed2_id = ed2.getId();
+
+ ing1_id = ing1.getId();
+ ing2_id = ing2.getId();
+ }
+
+ @Test
+ public void testCacheReferenceAccessAfterFind() {
+ SetRefEdEntity ed1_rev1 = getVersionsReader().find(SetRefEdEntity.class, ed1_id, 1);
+
+ SetRefIngEntity ing1_rev1 = getVersionsReader().find(SetRefIngEntity.class, ing1_id, 1);
+ SetRefIngEntity ing2_rev1 = getVersionsReader().find(SetRefIngEntity.class, ing2_id, 1);
+
+ // It should be exactly the same object
+ assert ing1_rev1.getReference() == ed1_rev1;
+ assert ing2_rev1.getReference() == ed1_rev1;
+ }
+
+ @Test
+ public void testCacheReferenceAccessAfterCollectionAccessRev1() {
+ SetRefEdEntity ed1_rev1 = getVersionsReader().find(SetRefEdEntity.class, ed1_id, 1);
+
+ // It should be exactly the same object
+ assert ed1_rev1.getReffering().size() == 2;
+ for (SetRefIngEntity setRefIngEntity : ed1_rev1.getReffering()) {
+ assert setRefIngEntity.getReference() == ed1_rev1;
+ }
+ }
+
+ @Test
+ public void testCacheReferenceAccessAfterCollectionAccessRev2() {
+ SetRefEdEntity ed2_rev2 = getVersionsReader().find(SetRefEdEntity.class, ed2_id, 2);
+
+ assert ed2_rev2.getReffering().size() == 2;
+ for (SetRefIngEntity setRefIngEntity : ed2_rev2.getReffering()) {
+ assert setRefIngEntity.getReference() == ed2_rev2;
+ }
+ }
+
+ @Test
+ public void testCacheFindAfterCollectionAccessRev1() {
+ SetRefEdEntity ed1_rev1 = getVersionsReader().find(SetRefEdEntity.class, ed1_id, 1);
+
+ // Reading the collection
+ assert ed1_rev1.getReffering().size() == 2;
+
+ SetRefIngEntity ing1_rev1 = getVersionsReader().find(SetRefIngEntity.class, ing1_id, 1);
+ SetRefIngEntity ing2_rev1 = getVersionsReader().find(SetRefIngEntity.class, ing2_id, 1);
+
+ for (SetRefIngEntity setRefIngEntity : ed1_rev1.getReffering()) {
+ assert setRefIngEntity == ing1_rev1 || setRefIngEntity == ing2_rev1;
+ }
+ }
+}
\ No newline at end of file
Added: core/trunk/envers/src/test/java/org/jboss/envers/test/integration/cache/OneToOneCache.java
===================================================================
--- core/trunk/envers/src/test/java/org/jboss/envers/test/integration/cache/OneToOneCache.java (rev 0)
+++ core/trunk/envers/src/test/java/org/jboss/envers/test/integration/cache/OneToOneCache.java 2008-10-27 18:56:31 UTC (rev 15406)
@@ -0,0 +1,80 @@
+package org.jboss.envers.test.integration.cache;
+
+import org.jboss.envers.test.AbstractEntityTest;
+import org.jboss.envers.test.integration.onetoone.bidirectional.BiRefEdEntity;
+import org.jboss.envers.test.integration.onetoone.bidirectional.BiRefIngEntity;
+import org.hibernate.ejb.Ejb3Configuration;
+import org.testng.annotations.BeforeClass;
+import org.testng.annotations.Test;
+
+import javax.persistence.EntityManager;
+
+/**
+ * @author Adam Warski (adam at warski dot org)
+ */
+ at SuppressWarnings({"ObjectEquality"})
+public class OneToOneCache extends AbstractEntityTest {
+ private Integer ed1_id;
+ private Integer ed2_id;
+
+ private Integer ing1_id;
+
+ public void configure(Ejb3Configuration cfg) {
+ cfg.addAnnotatedClass(BiRefEdEntity.class);
+ cfg.addAnnotatedClass(BiRefIngEntity.class);
+ }
+
+ @BeforeClass(dependsOnMethods = "init")
+ public void initData() {
+ BiRefEdEntity ed1 = new BiRefEdEntity(1, "data_ed_1");
+ BiRefEdEntity ed2 = new BiRefEdEntity(2, "data_ed_2");
+
+ BiRefIngEntity ing1 = new BiRefIngEntity(3, "data_ing_1");
+
+ // Revision 1
+ EntityManager em = getEntityManager();
+ em.getTransaction().begin();
+
+ ing1.setReference(ed1);
+
+ em.persist(ed1);
+ em.persist(ed2);
+
+ em.persist(ing1);
+
+ em.getTransaction().commit();
+
+ // Revision 2
+ em.getTransaction().begin();
+
+ ing1 = em.find(BiRefIngEntity.class, ing1.getId());
+ ed2 = em.find(BiRefEdEntity.class, ed2.getId());
+
+ ing1.setReference(ed2);
+
+ em.getTransaction().commit();
+
+ //
+
+ ed1_id = ed1.getId();
+ ed2_id = ed2.getId();
+
+ ing1_id = ing1.getId();
+ }
+
+ @Test
+ public void testCacheReferenceAccessAfterFindRev1() {
+ BiRefEdEntity ed1_rev1 = getVersionsReader().find(BiRefEdEntity.class, ed1_id, 1);
+ BiRefIngEntity ing1_rev1 = getVersionsReader().find(BiRefIngEntity.class, ing1_id, 1);
+
+ assert ing1_rev1.getReference() == ed1_rev1;
+ }
+
+ @Test
+ public void testCacheReferenceAccessAfterFindRev2() {
+ BiRefEdEntity ed2_rev2 = getVersionsReader().find(BiRefEdEntity.class, ed2_id, 2);
+ BiRefIngEntity ing1_rev2 = getVersionsReader().find(BiRefIngEntity.class, ing1_id, 2);
+
+ assert ing1_rev2.getReference() == ed2_rev2;
+ }
+}
\ No newline at end of file
Added: core/trunk/envers/src/test/java/org/jboss/envers/test/integration/cache/QueryCache.java
===================================================================
--- core/trunk/envers/src/test/java/org/jboss/envers/test/integration/cache/QueryCache.java (rev 0)
+++ core/trunk/envers/src/test/java/org/jboss/envers/test/integration/cache/QueryCache.java 2008-10-27 18:56:31 UTC (rev 15406)
@@ -0,0 +1,63 @@
+package org.jboss.envers.test.integration.cache;
+
+import org.jboss.envers.test.AbstractEntityTest;
+import org.jboss.envers.test.entities.IntTestEntity;
+import org.hibernate.ejb.Ejb3Configuration;
+import org.testng.annotations.Test;
+import org.testng.annotations.BeforeClass;
+
+import javax.persistence.EntityManager;
+import java.util.List;
+
+/**
+ * @author Adam Warski (adam at warski dot org)
+ */
+ at SuppressWarnings({"ObjectEquality"})
+public class QueryCache extends AbstractEntityTest {
+ private Integer id1;
+
+ public void configure(Ejb3Configuration cfg) {
+ cfg.addAnnotatedClass(IntTestEntity.class);
+ }
+
+ @BeforeClass(dependsOnMethods = "init")
+ public void initData() {
+ // Revision 1
+ EntityManager em = getEntityManager();
+ em.getTransaction().begin();
+ IntTestEntity ite = new IntTestEntity(10);
+ em.persist(ite);
+ id1 = ite.getId();
+ em.getTransaction().commit();
+
+ // Revision 2
+ em.getTransaction().begin();
+ ite = em.find(IntTestEntity.class, id1);
+ ite.setNumber(20);
+ em.getTransaction().commit();
+ }
+
+ @Test
+ public void testCacheFindAfterRevisionsOfEntityQuery() {
+ List entsFromQuery = getVersionsReader().createQuery()
+ .forRevisionsOfEntity(IntTestEntity.class, true, false)
+ .getResultList();
+
+ IntTestEntity entFromFindRev1 = getVersionsReader().find(IntTestEntity.class, id1, 1);
+ IntTestEntity entFromFindRev2 = getVersionsReader().find(IntTestEntity.class, id1, 2);
+
+ assert entFromFindRev1 == entsFromQuery.get(0);
+ assert entFromFindRev2 == entsFromQuery.get(1);
+ }
+
+ @Test
+ public void testCacheFindAfterEntitiesAtRevisionQuery() {
+ IntTestEntity entFromQuery = (IntTestEntity) getVersionsReader().createQuery()
+ .forEntitiesAtRevision(IntTestEntity.class, 1)
+ .getSingleResult();
+
+ IntTestEntity entFromFind = getVersionsReader().find(IntTestEntity.class, id1, 1);
+
+ assert entFromFind == entFromQuery;
+ }
+}
\ No newline at end of file
Added: core/trunk/envers/src/test/java/org/jboss/envers/test/integration/collection/EnumSet.java
===================================================================
--- core/trunk/envers/src/test/java/org/jboss/envers/test/integration/collection/EnumSet.java (rev 0)
+++ core/trunk/envers/src/test/java/org/jboss/envers/test/integration/collection/EnumSet.java 2008-10-27 18:56:31 UTC (rev 15406)
@@ -0,0 +1,85 @@
+package org.jboss.envers.test.integration.collection;
+
+import org.jboss.envers.test.AbstractEntityTest;
+import org.jboss.envers.test.tools.TestTools;
+import org.jboss.envers.test.entities.collection.EnumSetEntity;
+import org.testng.annotations.BeforeClass;
+import org.testng.annotations.Test;
+import org.hibernate.ejb.Ejb3Configuration;
+
+import javax.persistence.EntityManager;
+import java.util.Arrays;
+
+import static org.jboss.envers.test.entities.collection.EnumSetEntity.*;
+
+/**
+ * @author Adam Warski (adam at warski dot org)
+ */
+public class EnumSet extends AbstractEntityTest {
+ private Integer sse1_id;
+
+ public void configure(Ejb3Configuration cfg) {
+ cfg.addAnnotatedClass(EnumSetEntity.class);
+ }
+
+ @BeforeClass(dependsOnMethods = "init")
+ public void initData() {
+ EntityManager em = getEntityManager();
+
+ EnumSetEntity sse1 = new EnumSetEntity();
+
+ // Revision 1 (sse1: initialy 1 element)
+ em.getTransaction().begin();
+
+ sse1.getEnums1().add(E1.X);
+ sse1.getEnums2().add(E2.A);
+
+ em.persist(sse1);
+
+ em.getTransaction().commit();
+
+ // Revision 2 (sse1: adding 1 element/removing a non-existing element)
+ em.getTransaction().begin();
+
+ sse1 = em.find(EnumSetEntity.class, sse1.getId());
+
+ sse1.getEnums1().add(E1.Y);
+ sse1.getEnums2().remove(E2.B);
+
+ em.getTransaction().commit();
+
+ // Revision 3 (sse1: removing 1 element/adding an exisiting element)
+ em.getTransaction().begin();
+
+ sse1 = em.find(EnumSetEntity.class, sse1.getId());
+
+ sse1.getEnums1().remove(E1.X);
+ sse1.getEnums2().add(E2.A);
+
+ em.getTransaction().commit();
+
+ //
+
+ sse1_id = sse1.getId();
+ }
+
+ @Test
+ public void testRevisionsCounts() {
+ assert Arrays.asList(1, 2, 3).equals(getVersionsReader().getRevisions(EnumSetEntity.class, sse1_id));
+ }
+
+ @Test
+ public void testHistoryOfSse1() {
+ EnumSetEntity rev1 = getVersionsReader().find(EnumSetEntity.class, sse1_id, 1);
+ EnumSetEntity rev2 = getVersionsReader().find(EnumSetEntity.class, sse1_id, 2);
+ EnumSetEntity rev3 = getVersionsReader().find(EnumSetEntity.class, sse1_id, 3);
+
+ assert rev1.getEnums1().equals(TestTools.makeSet(E1.X));
+ assert rev2.getEnums1().equals(TestTools.makeSet(E1.X, E1.Y));
+ assert rev3.getEnums1().equals(TestTools.makeSet(E1.Y));
+
+ assert rev1.getEnums2().equals(TestTools.makeSet(E2.A));
+ assert rev2.getEnums2().equals(TestTools.makeSet(E2.A));
+ assert rev3.getEnums2().equals(TestTools.makeSet(E2.A));
+ }
+}
\ No newline at end of file
Added: core/trunk/envers/src/test/java/org/jboss/envers/test/integration/collection/StringList.java
===================================================================
--- core/trunk/envers/src/test/java/org/jboss/envers/test/integration/collection/StringList.java (rev 0)
+++ core/trunk/envers/src/test/java/org/jboss/envers/test/integration/collection/StringList.java 2008-10-27 18:56:31 UTC (rev 15406)
@@ -0,0 +1,101 @@
+package org.jboss.envers.test.integration.collection;
+
+import org.jboss.envers.test.AbstractEntityTest;
+import org.jboss.envers.test.tools.TestTools;
+import org.jboss.envers.test.entities.collection.StringListEntity;
+import org.testng.annotations.BeforeClass;
+import org.testng.annotations.Test;
+import org.hibernate.ejb.Ejb3Configuration;
+
+import javax.persistence.EntityManager;
+import java.util.Arrays;
+import java.util.Collections;
+
+/**
+ * @author Adam Warski (adam at warski dot org)
+ */
+public class StringList extends AbstractEntityTest {
+ private Integer sle1_id;
+ private Integer sle2_id;
+
+ public void configure(Ejb3Configuration cfg) {
+ cfg.addAnnotatedClass(StringListEntity.class);
+ }
+
+ @BeforeClass(dependsOnMethods = "init")
+ public void initData() {
+ EntityManager em = getEntityManager();
+
+ StringListEntity sle1 = new StringListEntity();
+ StringListEntity sle2 = new StringListEntity();
+
+ // Revision 1 (sle1: initialy empty, sle2: initialy 2 elements)
+ em.getTransaction().begin();
+
+ sle2.getStrings().add("sle2_string1");
+ sle2.getStrings().add("sle2_string2");
+
+ em.persist(sle1);
+ em.persist(sle2);
+
+ em.getTransaction().commit();
+
+ // Revision 2 (sle1: adding 2 elements, sle2: adding an existing element)
+ em.getTransaction().begin();
+
+ sle1 = em.find(StringListEntity.class, sle1.getId());
+ sle2 = em.find(StringListEntity.class, sle2.getId());
+
+ sle1.getStrings().add("sle1_string1");
+ sle1.getStrings().add("sle1_string2");
+
+ sle2.getStrings().add("sle2_string1");
+
+ em.getTransaction().commit();
+
+ // Revision 3 (sle1: replacing an element at index 0, sle2: removing an element at index 0)
+ em.getTransaction().begin();
+
+ sle1 = em.find(StringListEntity.class, sle1.getId());
+ sle2 = em.find(StringListEntity.class, sle2.getId());
+
+ sle1.getStrings().set(0, "sle1_string3");
+
+ sle2.getStrings().remove(0);
+
+ em.getTransaction().commit();
+
+ //
+
+ sle1_id = sle1.getId();
+ sle2_id = sle2.getId();
+ }
+
+ @Test
+ public void testRevisionsCounts() {
+ assert Arrays.asList(1, 2, 3).equals(getVersionsReader().getRevisions(StringListEntity.class, sle1_id));
+ assert Arrays.asList(1, 2, 3).equals(getVersionsReader().getRevisions(StringListEntity.class, sle2_id));
+ }
+
+ @Test
+ public void testHistoryOfSle1() {
+ StringListEntity rev1 = getVersionsReader().find(StringListEntity.class, sle1_id, 1);
+ StringListEntity rev2 = getVersionsReader().find(StringListEntity.class, sle1_id, 2);
+ StringListEntity rev3 = getVersionsReader().find(StringListEntity.class, sle1_id, 3);
+
+ assert rev1.getStrings().equals(Collections.EMPTY_LIST);
+ assert rev2.getStrings().equals(TestTools.makeList("sle1_string1", "sle1_string2"));
+ assert rev3.getStrings().equals(TestTools.makeList("sle1_string3", "sle1_string2"));
+ }
+
+ @Test
+ public void testHistoryOfSse2() {
+ StringListEntity rev1 = getVersionsReader().find(StringListEntity.class, sle2_id, 1);
+ StringListEntity rev2 = getVersionsReader().find(StringListEntity.class, sle2_id, 2);
+ StringListEntity rev3 = getVersionsReader().find(StringListEntity.class, sle2_id, 3);
+
+ assert rev1.getStrings().equals(TestTools.makeList("sle2_string1", "sle2_string2"));
+ assert rev2.getStrings().equals(TestTools.makeList("sle2_string1", "sle2_string2", "sle2_string1"));
+ assert rev3.getStrings().equals(TestTools.makeList("sle2_string2", "sle2_string1"));
+ }
+}
\ No newline at end of file
Added: core/trunk/envers/src/test/java/org/jboss/envers/test/integration/collection/StringMap.java
===================================================================
--- core/trunk/envers/src/test/java/org/jboss/envers/test/integration/collection/StringMap.java (rev 0)
+++ core/trunk/envers/src/test/java/org/jboss/envers/test/integration/collection/StringMap.java 2008-10-27 18:56:31 UTC (rev 15406)
@@ -0,0 +1,112 @@
+package org.jboss.envers.test.integration.collection;
+
+import org.jboss.envers.test.AbstractEntityTest;
+import org.jboss.envers.test.tools.TestTools;
+import org.jboss.envers.test.entities.collection.StringMapEntity;
+import org.testng.annotations.BeforeClass;
+import org.testng.annotations.Test;
+import org.hibernate.ejb.Ejb3Configuration;
+
+import javax.persistence.EntityManager;
+import java.util.Arrays;
+import java.util.Collections;
+
+/**
+ * @author Adam Warski (adam at warski dot org)
+ */
+public class StringMap extends AbstractEntityTest {
+ private Integer sme1_id;
+ private Integer sme2_id;
+
+ public void configure(Ejb3Configuration cfg) {
+ cfg.addAnnotatedClass(StringMapEntity.class);
+ }
+
+ @BeforeClass(dependsOnMethods = "init")
+ public void initData() {
+ EntityManager em = getEntityManager();
+
+ StringMapEntity sme1 = new StringMapEntity();
+ StringMapEntity sme2 = new StringMapEntity();
+
+ // Revision 1 (sme1: initialy empty, sme2: initialy 1 mapping)
+ em.getTransaction().begin();
+
+ sme2.getStrings().put("1", "a");
+
+ em.persist(sme1);
+ em.persist(sme2);
+
+ em.getTransaction().commit();
+
+ // Revision 2 (sme1: adding 2 mappings, sme2: no changes)
+ em.getTransaction().begin();
+
+ sme1 = em.find(StringMapEntity.class, sme1.getId());
+ sme2 = em.find(StringMapEntity.class, sme2.getId());
+
+ sme1.getStrings().put("1", "a");
+ sme1.getStrings().put("2", "b");
+
+ em.getTransaction().commit();
+
+ // Revision 3 (sme1: removing an existing mapping, sme2: replacing a value)
+ em.getTransaction().begin();
+
+ sme1 = em.find(StringMapEntity.class, sme1.getId());
+ sme2 = em.find(StringMapEntity.class, sme2.getId());
+
+ sme1.getStrings().remove("1");
+ sme2.getStrings().put("1", "b");
+
+ em.getTransaction().commit();
+
+ // No revision (sme1: removing a non-existing mapping, sme2: replacing with the same value)
+ em.getTransaction().begin();
+
+ sme1 = em.find(StringMapEntity.class, sme1.getId());
+ sme2 = em.find(StringMapEntity.class, sme2.getId());
+
+ sme1.getStrings().remove("3");
+ sme2.getStrings().put("1", "b");
+
+ em.getTransaction().commit();
+
+ //
+
+ sme1_id = sme1.getId();
+ sme2_id = sme2.getId();
+ }
+
+ @Test
+ public void testRevisionsCounts() {
+ assert Arrays.asList(1, 2, 3).equals(getVersionsReader().getRevisions(StringMapEntity.class, sme1_id));
+ assert Arrays.asList(1, 3).equals(getVersionsReader().getRevisions(StringMapEntity.class, sme2_id));
+ }
+
+ @Test
+ public void testHistoryOfSse1() {
+ StringMapEntity rev1 = getVersionsReader().find(StringMapEntity.class, sme1_id, 1);
+ StringMapEntity rev2 = getVersionsReader().find(StringMapEntity.class, sme1_id, 2);
+ StringMapEntity rev3 = getVersionsReader().find(StringMapEntity.class, sme1_id, 3);
+ StringMapEntity rev4 = getVersionsReader().find(StringMapEntity.class, sme1_id, 4);
+
+ assert rev1.getStrings().equals(Collections.EMPTY_MAP);
+ assert rev2.getStrings().equals(TestTools.makeMap("1", "a", "2", "b"));
+ assert rev3.getStrings().equals(TestTools.makeMap("2", "b"));
+ assert rev4.getStrings().equals(TestTools.makeMap("2", "b"));
+ }
+
+ @Test
+ public void testHistoryOfSse2() {
+ StringMapEntity rev1 = getVersionsReader().find(StringMapEntity.class, sme2_id, 1);
+ StringMapEntity rev2 = getVersionsReader().find(StringMapEntity.class, sme2_id, 2);
+ StringMapEntity rev3 = getVersionsReader().find(StringMapEntity.class, sme2_id, 3);
+ StringMapEntity rev4 = getVersionsReader().find(StringMapEntity.class, sme2_id, 4);
+
+ assert rev1.getStrings().equals(TestTools.makeMap("1", "a"));
+ assert rev2.getStrings().equals(TestTools.makeMap("1", "a"));
+ assert rev3.getStrings().equals(TestTools.makeMap("1", "b"));
+ assert rev4.getStrings().equals(TestTools.makeMap("1", "b"));
+ }
+}
\ No newline at end of file
Added: core/trunk/envers/src/test/java/org/jboss/envers/test/integration/collection/StringSet.java
===================================================================
--- core/trunk/envers/src/test/java/org/jboss/envers/test/integration/collection/StringSet.java (rev 0)
+++ core/trunk/envers/src/test/java/org/jboss/envers/test/integration/collection/StringSet.java 2008-10-27 18:56:31 UTC (rev 15406)
@@ -0,0 +1,100 @@
+package org.jboss.envers.test.integration.collection;
+
+import org.jboss.envers.test.AbstractEntityTest;
+import org.jboss.envers.test.tools.TestTools;
+import org.jboss.envers.test.entities.collection.StringSetEntity;
+import org.testng.annotations.BeforeClass;
+import org.testng.annotations.Test;
+import org.hibernate.ejb.Ejb3Configuration;
+
+import javax.persistence.EntityManager;
+import java.util.Arrays;
+import java.util.Collections;
+
+/**
+ * @author Adam Warski (adam at warski dot org)
+ */
+public class StringSet extends AbstractEntityTest {
+ private Integer sse1_id;
+ private Integer sse2_id;
+
+ public void configure(Ejb3Configuration cfg) {
+ cfg.addAnnotatedClass(StringSetEntity.class);
+ }
+
+ @BeforeClass(dependsOnMethods = "init")
+ public void initData() {
+ EntityManager em = getEntityManager();
+
+ StringSetEntity sse1 = new StringSetEntity();
+ StringSetEntity sse2 = new StringSetEntity();
+
+ // Revision 1 (sse1: initialy empty, sse2: initialy 2 elements)
+ em.getTransaction().begin();
+
+ sse2.getStrings().add("sse2_string1");
+ sse2.getStrings().add("sse2_string2");
+
+ em.persist(sse1);
+ em.persist(sse2);
+
+ em.getTransaction().commit();
+
+ // Revision 2 (sse1: adding 2 elements, sse2: adding an existing element)
+ em.getTransaction().begin();
+
+ sse1 = em.find(StringSetEntity.class, sse1.getId());
+ sse2 = em.find(StringSetEntity.class, sse2.getId());
+
+ sse1.getStrings().add("sse1_string1");
+ sse1.getStrings().add("sse1_string2");
+
+ sse2.getStrings().add("sse2_string1");
+
+ em.getTransaction().commit();
+
+ // Revision 3 (sse1: removing a non-existing element, sse2: removing one element)
+ em.getTransaction().begin();
+
+ sse1 = em.find(StringSetEntity.class, sse1.getId());
+ sse2 = em.find(StringSetEntity.class, sse2.getId());
+
+ sse1.getStrings().remove("sse1_string3");
+ sse2.getStrings().remove("sse2_string1");
+
+ em.getTransaction().commit();
+
+ //
+
+ sse1_id = sse1.getId();
+ sse2_id = sse2.getId();
+ }
+
+ @Test
+ public void testRevisionsCounts() {
+ assert Arrays.asList(1, 2).equals(getVersionsReader().getRevisions(StringSetEntity.class, sse1_id));
+ assert Arrays.asList(1, 3).equals(getVersionsReader().getRevisions(StringSetEntity.class, sse2_id));
+ }
+
+ @Test
+ public void testHistoryOfSse1() {
+ StringSetEntity rev1 = getVersionsReader().find(StringSetEntity.class, sse1_id, 1);
+ StringSetEntity rev2 = getVersionsReader().find(StringSetEntity.class, sse1_id, 2);
+ StringSetEntity rev3 = getVersionsReader().find(StringSetEntity.class, sse1_id, 3);
+
+ assert rev1.getStrings().equals(Collections.EMPTY_SET);
+ assert rev2.getStrings().equals(TestTools.makeSet("sse1_string1", "sse1_string2"));
+ assert rev3.getStrings().equals(TestTools.makeSet("sse1_string1", "sse1_string2"));
+ }
+
+ @Test
+ public void testHistoryOfSse2() {
+ StringSetEntity rev1 = getVersionsReader().find(StringSetEntity.class, sse2_id, 1);
+ StringSetEntity rev2 = getVersionsReader().find(StringSetEntity.class, sse2_id, 2);
+ StringSetEntity rev3 = getVersionsReader().find(StringSetEntity.class, sse2_id, 3);
+
+ assert rev1.getStrings().equals(TestTools.makeSet("sse2_string1", "sse2_string2"));
+ assert rev2.getStrings().equals(TestTools.makeSet("sse2_string1", "sse2_string2"));
+ assert rev3.getStrings().equals(TestTools.makeSet("sse2_string2"));
+ }
+}
\ No newline at end of file
Added: core/trunk/envers/src/test/java/org/jboss/envers/test/integration/collection/mapkey/ComponentMapKey.java
===================================================================
--- core/trunk/envers/src/test/java/org/jboss/envers/test/integration/collection/mapkey/ComponentMapKey.java (rev 0)
+++ core/trunk/envers/src/test/java/org/jboss/envers/test/integration/collection/mapkey/ComponentMapKey.java 2008-10-27 18:56:31 UTC (rev 15406)
@@ -0,0 +1,88 @@
+package org.jboss.envers.test.integration.collection.mapkey;
+
+import org.jboss.envers.test.AbstractEntityTest;
+import org.jboss.envers.test.tools.TestTools;
+import org.jboss.envers.test.entities.components.ComponentTestEntity;
+import org.jboss.envers.test.entities.components.Component1;
+import org.jboss.envers.test.entities.components.Component2;
+import org.testng.annotations.BeforeClass;
+import org.testng.annotations.Test;
+import org.hibernate.ejb.Ejb3Configuration;
+
+import javax.persistence.EntityManager;
+import java.util.Arrays;
+
+/**
+ * @author Adam Warski (adam at warski dot org)
+ */
+public class ComponentMapKey extends AbstractEntityTest {
+ private Integer cmke_id;
+
+ private Integer cte1_id;
+ private Integer cte2_id;
+
+ public void configure(Ejb3Configuration cfg) {
+ cfg.addAnnotatedClass(ComponentMapKeyEntity.class);
+ cfg.addAnnotatedClass(ComponentTestEntity.class);
+ }
+
+ @BeforeClass(dependsOnMethods = "init")
+ public void initData() {
+ EntityManager em = getEntityManager();
+
+ ComponentMapKeyEntity imke = new ComponentMapKeyEntity();
+
+ // Revision 1 (intialy 1 mapping)
+ em.getTransaction().begin();
+
+ ComponentTestEntity cte1 = new ComponentTestEntity(new Component1("x1", "y2"), new Component2("a1", "b2"));
+ ComponentTestEntity cte2 = new ComponentTestEntity(new Component1("x1", "y2"), new Component2("a1", "b2"));
+
+ em.persist(cte1);
+ em.persist(cte2);
+
+ imke.getIdmap().put(cte1.getComp1(), cte1);
+
+ em.persist(imke);
+
+ em.getTransaction().commit();
+
+ // Revision 2 (sse1: adding 1 mapping)
+ em.getTransaction().begin();
+
+ cte2 = em.find(ComponentTestEntity.class, cte2.getId());
+ imke = em.find(ComponentMapKeyEntity.class, imke.getId());
+
+ imke.getIdmap().put(cte2.getComp1(), cte2);
+
+ em.getTransaction().commit();
+
+ //
+
+ cmke_id = imke.getId();
+
+ cte1_id = cte1.getId();
+ cte2_id = cte2.getId();
+ }
+
+ @Test
+ public void testRevisionsCounts() {
+ assert Arrays.asList(1, 2).equals(getVersionsReader().getRevisions(ComponentMapKeyEntity.class, cmke_id));
+ }
+
+ @Test
+ public void testHistoryOfImke() {
+ ComponentTestEntity cte1 = getEntityManager().find(ComponentTestEntity.class, cte1_id);
+ ComponentTestEntity cte2 = getEntityManager().find(ComponentTestEntity.class, cte2_id);
+
+ // These fields are unversioned.
+ cte1.setComp2(null);
+ cte2.setComp2(null);
+
+ ComponentMapKeyEntity rev1 = getVersionsReader().find(ComponentMapKeyEntity.class, cmke_id, 1);
+ ComponentMapKeyEntity rev2 = getVersionsReader().find(ComponentMapKeyEntity.class, cmke_id, 2);
+
+ assert rev1.getIdmap().equals(TestTools.makeMap(cte1.getComp1(), cte1));
+ assert rev2.getIdmap().equals(TestTools.makeMap(cte1.getComp1(), cte1, cte2.getComp1(), cte2));
+ }
+}
\ No newline at end of file
Added: core/trunk/envers/src/test/java/org/jboss/envers/test/integration/collection/mapkey/ComponentMapKeyEntity.java
===================================================================
--- core/trunk/envers/src/test/java/org/jboss/envers/test/integration/collection/mapkey/ComponentMapKeyEntity.java (rev 0)
+++ core/trunk/envers/src/test/java/org/jboss/envers/test/integration/collection/mapkey/ComponentMapKeyEntity.java 2008-10-27 18:56:31 UTC (rev 15406)
@@ -0,0 +1,63 @@
+package org.jboss.envers.test.integration.collection.mapkey;
+
+import org.jboss.envers.Versioned;
+import org.jboss.envers.test.entities.components.Component1;
+import org.jboss.envers.test.entities.components.ComponentTestEntity;
+
+import javax.persistence.*;
+import java.util.Map;
+import java.util.HashMap;
+
+/**
+ * @author Adam Warski (adam at warski dot org)
+ */
+ at Entity
+public class ComponentMapKeyEntity {
+ @Id
+ @GeneratedValue
+ private Integer id;
+
+ @Versioned
+ @ManyToMany
+ @MapKey(name = "comp1")
+ private Map<Component1, ComponentTestEntity> idmap;
+
+ public ComponentMapKeyEntity() {
+ idmap = new HashMap<Component1, ComponentTestEntity>();
+ }
+
+ public Integer getId() {
+ return id;
+ }
+
+ public void setId(Integer id) {
+ this.id = id;
+ }
+
+ public Map<Component1, ComponentTestEntity> getIdmap() {
+ return idmap;
+ }
+
+ public void setIdmap(Map<Component1, ComponentTestEntity> idmap) {
+ this.idmap = idmap;
+ }
+
+ public boolean equals(Object o) {
+ if (this == o) return true;
+ if (!(o instanceof ComponentMapKeyEntity)) return false;
+
+ ComponentMapKeyEntity that = (ComponentMapKeyEntity) o;
+
+ if (id != null ? !id.equals(that.id) : that.id != null) return false;
+
+ return true;
+ }
+
+ public int hashCode() {
+ return (id != null ? id.hashCode() : 0);
+ }
+
+ public String toString() {
+ return "CMKE(id = " + id + ", idmap = " + idmap + ")";
+ }
+}
\ No newline at end of file
Added: core/trunk/envers/src/test/java/org/jboss/envers/test/integration/collection/mapkey/IdMapKey.java
===================================================================
--- core/trunk/envers/src/test/java/org/jboss/envers/test/integration/collection/mapkey/IdMapKey.java (rev 0)
+++ core/trunk/envers/src/test/java/org/jboss/envers/test/integration/collection/mapkey/IdMapKey.java 2008-10-27 18:56:31 UTC (rev 15406)
@@ -0,0 +1,82 @@
+package org.jboss.envers.test.integration.collection.mapkey;
+
+import org.jboss.envers.test.AbstractEntityTest;
+import org.jboss.envers.test.tools.TestTools;
+import org.jboss.envers.test.entities.StrTestEntity;
+import org.testng.annotations.BeforeClass;
+import org.testng.annotations.Test;
+import org.hibernate.ejb.Ejb3Configuration;
+
+import javax.persistence.EntityManager;
+import java.util.Arrays;
+
+/**
+ * @author Adam Warski (adam at warski dot org)
+ */
+public class IdMapKey extends AbstractEntityTest {
+ private Integer imke_id;
+
+ private Integer ste1_id;
+ private Integer ste2_id;
+
+ public void configure(Ejb3Configuration cfg) {
+ cfg.addAnnotatedClass(IdMapKeyEntity.class);
+ cfg.addAnnotatedClass(StrTestEntity.class);
+ }
+
+ @BeforeClass(dependsOnMethods = "init")
+ public void initData() {
+ EntityManager em = getEntityManager();
+
+ IdMapKeyEntity imke = new IdMapKeyEntity();
+
+ // Revision 1 (intialy 1 mapping)
+ em.getTransaction().begin();
+
+ StrTestEntity ste1 = new StrTestEntity("x");
+ StrTestEntity ste2 = new StrTestEntity("y");
+
+ em.persist(ste1);
+ em.persist(ste2);
+
+ imke.getIdmap().put(ste1.getId(), ste1);
+
+ em.persist(imke);
+
+ em.getTransaction().commit();
+
+ // Revision 2 (sse1: adding 1 mapping)
+ em.getTransaction().begin();
+
+ ste2 = em.find(StrTestEntity.class, ste2.getId());
+ imke = em.find(IdMapKeyEntity.class, imke.getId());
+
+ imke.getIdmap().put(ste2.getId(), ste2);
+
+ em.getTransaction().commit();
+
+ //
+
+ imke_id = imke.getId();
+
+ ste1_id = ste1.getId();
+ ste2_id = ste2.getId();
+ }
+
+ @Test
+ public void testRevisionsCounts() {
+ assert Arrays.asList(1, 2).equals(getVersionsReader().getRevisions(IdMapKeyEntity.class, imke_id));
+ }
+
+ @Test
+ public void testHistoryOfImke() {
+ StrTestEntity ste1 = getEntityManager().find(StrTestEntity.class, ste1_id);
+ StrTestEntity ste2 = getEntityManager().find(StrTestEntity.class, ste2_id);
+
+ IdMapKeyEntity rev1 = getVersionsReader().find(IdMapKeyEntity.class, imke_id, 1);
+ IdMapKeyEntity rev2 = getVersionsReader().find(IdMapKeyEntity.class, imke_id, 2);
+
+ assert rev1.getIdmap().equals(TestTools.makeMap(ste1.getId(), ste1));
+ assert rev2.getIdmap().equals(TestTools.makeMap(ste1.getId(), ste1, ste2.getId(), ste2));
+ }
+}
\ No newline at end of file
Added: core/trunk/envers/src/test/java/org/jboss/envers/test/integration/collection/mapkey/IdMapKeyEntity.java
===================================================================
--- core/trunk/envers/src/test/java/org/jboss/envers/test/integration/collection/mapkey/IdMapKeyEntity.java (rev 0)
+++ core/trunk/envers/src/test/java/org/jboss/envers/test/integration/collection/mapkey/IdMapKeyEntity.java 2008-10-27 18:56:31 UTC (rev 15406)
@@ -0,0 +1,62 @@
+package org.jboss.envers.test.integration.collection.mapkey;
+
+import org.jboss.envers.Versioned;
+import org.jboss.envers.test.entities.StrTestEntity;
+
+import javax.persistence.*;
+import java.util.Map;
+import java.util.HashMap;
+
+/**
+ * @author Adam Warski (adam at warski dot org)
+ */
+ at Entity
+public class IdMapKeyEntity {
+ @Id
+ @GeneratedValue
+ private Integer id;
+
+ @Versioned
+ @ManyToMany
+ @MapKey
+ private Map<Integer, StrTestEntity> idmap;
+
+ public IdMapKeyEntity() {
+ idmap = new HashMap<Integer, StrTestEntity>();
+ }
+
+ public Integer getId() {
+ return id;
+ }
+
+ public void setId(Integer id) {
+ this.id = id;
+ }
+
+ public Map<Integer, StrTestEntity> getIdmap() {
+ return idmap;
+ }
+
+ public void setIdmap(Map<Integer, StrTestEntity> idmap) {
+ this.idmap = idmap;
+ }
+
+ public boolean equals(Object o) {
+ if (this == o) return true;
+ if (!(o instanceof IdMapKeyEntity)) return false;
+
+ IdMapKeyEntity that = (IdMapKeyEntity) o;
+
+ if (id != null ? !id.equals(that.id) : that.id != null) return false;
+
+ return true;
+ }
+
+ public int hashCode() {
+ return (id != null ? id.hashCode() : 0);
+ }
+
+ public String toString() {
+ return "IMKE(id = " + id + ", idmap = " + idmap + ")";
+ }
+}
\ No newline at end of file
Added: core/trunk/envers/src/test/java/org/jboss/envers/test/integration/components/Components.java
===================================================================
--- core/trunk/envers/src/test/java/org/jboss/envers/test/integration/components/Components.java (rev 0)
+++ core/trunk/envers/src/test/java/org/jboss/envers/test/integration/components/Components.java 2008-10-27 18:56:31 UTC (rev 15406)
@@ -0,0 +1,125 @@
+package org.jboss.envers.test.integration.components;
+
+import org.jboss.envers.test.AbstractEntityTest;
+import org.jboss.envers.test.entities.components.Component1;
+import org.jboss.envers.test.entities.components.Component2;
+import org.jboss.envers.test.entities.components.ComponentTestEntity;
+import org.hibernate.ejb.Ejb3Configuration;
+import org.testng.annotations.BeforeClass;
+import org.testng.annotations.Test;
+
+import javax.persistence.EntityManager;
+import java.util.Arrays;
+
+/**
+ * @author Adam Warski (adam at warski dot org)
+ */
+public class Components extends AbstractEntityTest {
+ private Integer id1;
+ private Integer id2;
+ private Integer id3;
+
+ public void configure(Ejb3Configuration cfg) {
+ cfg.addAnnotatedClass(ComponentTestEntity.class);
+ }
+
+ @BeforeClass(dependsOnMethods = "init")
+ public void initData() {
+ // Revision 1
+ EntityManager em = getEntityManager();
+ em.getTransaction().begin();
+
+ ComponentTestEntity cte1 = new ComponentTestEntity(new Component1("a", "b"), new Component2("x", "y"));
+ ComponentTestEntity cte2 = new ComponentTestEntity(new Component1("a2", "b2"), new Component2("x2", "y2"));
+ ComponentTestEntity cte3 = new ComponentTestEntity(new Component1("a3", "b3"), new Component2("x3", "y3"));
+
+ em.persist(cte1);
+ em.persist(cte2);
+ em.persist(cte3);
+
+ em.getTransaction().commit();
+
+ // Revision 2
+ em = getEntityManager();
+ em.getTransaction().begin();
+
+ cte1 = em.find(ComponentTestEntity.class, cte1.getId());
+ cte2 = em.find(ComponentTestEntity.class, cte2.getId());
+ cte3 = em.find(ComponentTestEntity.class, cte3.getId());
+
+ cte1.setComp1(new Component1("a'", "b'"));
+ cte2.getComp1().setStr1("a2'");
+ cte3.getComp2().setStr6("y3'");
+
+ em.getTransaction().commit();
+
+ // Revision 3
+ em = getEntityManager();
+ em.getTransaction().begin();
+
+ cte1 = em.find(ComponentTestEntity.class, cte1.getId());
+ cte2 = em.find(ComponentTestEntity.class, cte2.getId());
+ cte3 = em.find(ComponentTestEntity.class, cte3.getId());
+
+ cte1.setComp2(new Component2("x'", "y'"));
+ cte3.getComp1().setStr2("b3'");
+
+ em.getTransaction().commit();
+
+ // Revision 4
+ em = getEntityManager();
+ em.getTransaction().begin();
+
+ cte2 = em.find(ComponentTestEntity.class, cte2.getId());
+
+ em.remove(cte2);
+
+ em.getTransaction().commit();
+
+ id1 = cte1.getId();
+ id2 = cte2.getId();
+ id3 = cte3.getId();
+ }
+
+ @Test
+ public void testRevisionsCounts() {
+ assert Arrays.asList(1, 2).equals(getVersionsReader().getRevisions(ComponentTestEntity.class, id1));
+
+ assert Arrays.asList(1, 2, 4).equals(getVersionsReader().getRevisions(ComponentTestEntity.class, id2));
+
+ assert Arrays.asList(1, 3).equals(getVersionsReader().getRevisions(ComponentTestEntity.class, id3));
+ }
+
+ @Test
+ public void testHistoryOfId1() {
+ ComponentTestEntity ver1 = new ComponentTestEntity(id1, new Component1("a", "b"), null);
+ ComponentTestEntity ver2 = new ComponentTestEntity(id1, new Component1("a'", "b'"), null);
+
+ assert getVersionsReader().find(ComponentTestEntity.class, id1, 1).equals(ver1);
+ assert getVersionsReader().find(ComponentTestEntity.class, id1, 2).equals(ver2);
+ assert getVersionsReader().find(ComponentTestEntity.class, id1, 3).equals(ver2);
+ assert getVersionsReader().find(ComponentTestEntity.class, id1, 4).equals(ver2);
+ }
+
+ @Test
+ public void testHistoryOfId2() {
+ ComponentTestEntity ver1 = new ComponentTestEntity(id2, new Component1("a2", "b2"), null);
+ ComponentTestEntity ver2 = new ComponentTestEntity(id2, new Component1("a2'", "b2"), null);
+
+ assert getVersionsReader().find(ComponentTestEntity.class, id2, 1).equals(ver1);
+ assert getVersionsReader().find(ComponentTestEntity.class, id2, 2).equals(ver2);
+ assert getVersionsReader().find(ComponentTestEntity.class, id2, 3).equals(ver2);
+ assert getVersionsReader().find(ComponentTestEntity.class, id2, 4) == null;
+ }
+
+ @Test
+ public void testHistoryOfId3() {
+ ComponentTestEntity ver1 = new ComponentTestEntity(id3, new Component1("a3", "b3"), null);
+ ComponentTestEntity ver2 = new ComponentTestEntity(id3, new Component1("a3", "b3'"), null);
+
+ assert getVersionsReader().find(ComponentTestEntity.class, id3, 1).equals(ver1);
+ assert getVersionsReader().find(ComponentTestEntity.class, id3, 2).equals(ver1);
+ assert getVersionsReader().find(ComponentTestEntity.class, id3, 3).equals(ver2);
+ assert getVersionsReader().find(ComponentTestEntity.class, id3, 4).equals(ver2);
+ }
+}
Added: core/trunk/envers/src/test/java/org/jboss/envers/test/integration/customtype/CompositeCustom.java
===================================================================
--- core/trunk/envers/src/test/java/org/jboss/envers/test/integration/customtype/CompositeCustom.java (rev 0)
+++ core/trunk/envers/src/test/java/org/jboss/envers/test/integration/customtype/CompositeCustom.java 2008-10-27 18:56:31 UTC (rev 15406)
@@ -0,0 +1,76 @@
+package org.jboss.envers.test.integration.customtype;
+
+import org.jboss.envers.test.AbstractEntityTest;
+import org.jboss.envers.test.entities.customtype.CompositeCustomTypeEntity;
+import org.jboss.envers.test.entities.customtype.Component;
+import org.testng.annotations.BeforeClass;
+import org.testng.annotations.Test;
+import org.hibernate.ejb.Ejb3Configuration;
+
+import javax.persistence.EntityManager;
+import java.util.Arrays;
+
+/**
+ * @author Adam Warski (adam at warski dot org)
+ */
+public class CompositeCustom extends AbstractEntityTest {
+ private Integer ccte_id;
+
+ public void configure(Ejb3Configuration cfg) {
+ cfg.addAnnotatedClass(CompositeCustomTypeEntity.class);
+ }
+
+ @BeforeClass(dependsOnMethods = "init")
+ public void initData() {
+ EntityManager em = getEntityManager();
+
+ CompositeCustomTypeEntity ccte = new CompositeCustomTypeEntity();
+
+ // Revision 1 (persisting 1 entity)
+ em.getTransaction().begin();
+
+ ccte.setComponent(new Component("a", 1));
+
+ em.persist(ccte);
+
+ em.getTransaction().commit();
+
+ // Revision 2 (changing the component)
+ em.getTransaction().begin();
+
+ ccte = em.find(CompositeCustomTypeEntity.class, ccte.getId());
+
+ ccte.getComponent().setProp1("b");
+
+ em.getTransaction().commit();
+
+ // Revision 3 (replacing the component)
+ em.getTransaction().begin();
+
+ ccte = em.find(CompositeCustomTypeEntity.class, ccte.getId());
+
+ ccte.setComponent(new Component("c", 3));
+
+ em.getTransaction().commit();
+
+ //
+
+ ccte_id = ccte.getId();
+ }
+
+ @Test
+ public void testRevisionsCounts() {
+ assert Arrays.asList(1, 2, 3).equals(getVersionsReader().getRevisions(CompositeCustomTypeEntity.class, ccte_id));
+ }
+
+ @Test
+ public void testHistoryOfCcte() {
+ CompositeCustomTypeEntity rev1 = getVersionsReader().find(CompositeCustomTypeEntity.class, ccte_id, 1);
+ CompositeCustomTypeEntity rev2 = getVersionsReader().find(CompositeCustomTypeEntity.class, ccte_id, 2);
+ CompositeCustomTypeEntity rev3 = getVersionsReader().find(CompositeCustomTypeEntity.class, ccte_id, 3);
+
+ assert rev1.getComponent().equals(new Component("a", 1));
+ assert rev2.getComponent().equals(new Component("b", 1));
+ assert rev3.getComponent().equals(new Component("c", 3));
+ }
+}
\ No newline at end of file
Added: core/trunk/envers/src/test/java/org/jboss/envers/test/integration/customtype/ParametrizedCustom.java
===================================================================
--- core/trunk/envers/src/test/java/org/jboss/envers/test/integration/customtype/ParametrizedCustom.java (rev 0)
+++ core/trunk/envers/src/test/java/org/jboss/envers/test/integration/customtype/ParametrizedCustom.java 2008-10-27 18:56:31 UTC (rev 15406)
@@ -0,0 +1,64 @@
+package org.jboss.envers.test.integration.customtype;
+
+import org.jboss.envers.test.AbstractEntityTest;
+import org.jboss.envers.test.entities.customtype.ParametrizedCustomTypeEntity;
+import org.testng.annotations.BeforeClass;
+import org.testng.annotations.Test;
+import org.hibernate.ejb.Ejb3Configuration;
+
+import javax.persistence.EntityManager;
+import java.util.Arrays;
+
+/**
+ * @author Adam Warski (adam at warski dot org)
+ */
+public class ParametrizedCustom extends AbstractEntityTest {
+ private Integer pcte_id;
+
+ public void configure(Ejb3Configuration cfg) {
+ cfg.addAnnotatedClass(ParametrizedCustomTypeEntity.class);
+ }
+
+ @BeforeClass(dependsOnMethods = "init")
+ public void initData() {
+ EntityManager em = getEntityManager();
+
+ ParametrizedCustomTypeEntity pcte = new ParametrizedCustomTypeEntity();
+
+ // Revision 1 (persisting 1 entity)
+ em.getTransaction().begin();
+
+ pcte.setStr("U");
+
+ em.persist(pcte);
+
+ em.getTransaction().commit();
+
+ // Revision 2 (changing the value)
+ em.getTransaction().begin();
+
+ pcte = em.find(ParametrizedCustomTypeEntity.class, pcte.getId());
+
+ pcte.setStr("V");
+
+ em.getTransaction().commit();
+
+ //
+
+ pcte_id = pcte.getId();
+ }
+
+ @Test
+ public void testRevisionsCounts() {
+ assert Arrays.asList(1, 2).equals(getVersionsReader().getRevisions(ParametrizedCustomTypeEntity.class, pcte_id));
+ }
+
+ @Test
+ public void testHistoryOfCcte() {
+ ParametrizedCustomTypeEntity rev1 = getVersionsReader().find(ParametrizedCustomTypeEntity.class, pcte_id, 1);
+ ParametrizedCustomTypeEntity rev2 = getVersionsReader().find(ParametrizedCustomTypeEntity.class, pcte_id, 2);
+
+ assert "xUy".equals(rev1.getStr());
+ assert "xVy".equals(rev2.getStr());
+ }
+}
\ No newline at end of file
Added: core/trunk/envers/src/test/java/org/jboss/envers/test/integration/data/DateTestEntity.java
===================================================================
--- core/trunk/envers/src/test/java/org/jboss/envers/test/integration/data/DateTestEntity.java (rev 0)
+++ core/trunk/envers/src/test/java/org/jboss/envers/test/integration/data/DateTestEntity.java 2008-10-27 18:56:31 UTC (rev 15406)
@@ -0,0 +1,77 @@
+package org.jboss.envers.test.integration.data;
+
+import org.jboss.envers.Versioned;
+
+import javax.persistence.Entity;
+import javax.persistence.Id;
+import javax.persistence.GeneratedValue;
+import java.util.Date;
+
+/**
+ * @author Adam Warski (adam at warski dot org)
+ */
+ at Entity
+public class DateTestEntity {
+ @Id
+ @GeneratedValue
+ private Integer id;
+
+ @Versioned
+ private Date date;
+
+ public DateTestEntity() {
+ }
+
+ public DateTestEntity(Date date) {
+ this.date = date;
+ }
+
+ public DateTestEntity(Integer id, Date date) {
+ this.id = id;
+ this.date = date;
+ }
+
+ public Integer getId() {
+ return id;
+ }
+
+ public void setId(Integer id) {
+ this.id = id;
+ }
+
+ public Date getDate() {
+ return date;
+ }
+
+ public void setDate(Date date) {
+ this.date = date;
+ }
+
+ public boolean equals(Object o) {
+ if (this == o) return true;
+ if (!(o instanceof DateTestEntity)) return false;
+
+ DateTestEntity that = (DateTestEntity) o;
+
+ if (date != null) {
+ if (that.date == null) {
+ return false;
+ }
+
+ if (date.getTime() != that.date.getTime()) {
+ return false;
+ }
+ }
+
+ if (id != null ? !id.equals(that.id) : that.id != null) return false;
+
+ return true;
+ }
+
+ public int hashCode() {
+ int result;
+ result = (id != null ? id.hashCode() : 0);
+ result = 31 * result + (date != null ? date.hashCode() : 0);
+ return result;
+ }
+}
\ No newline at end of file
Added: core/trunk/envers/src/test/java/org/jboss/envers/test/integration/data/Dates.java
===================================================================
--- core/trunk/envers/src/test/java/org/jboss/envers/test/integration/data/Dates.java (rev 0)
+++ core/trunk/envers/src/test/java/org/jboss/envers/test/integration/data/Dates.java 2008-10-27 18:56:31 UTC (rev 15406)
@@ -0,0 +1,50 @@
+package org.jboss.envers.test.integration.data;
+
+import org.jboss.envers.test.AbstractEntityTest;
+import org.hibernate.ejb.Ejb3Configuration;
+import org.testng.annotations.Test;
+import org.testng.annotations.BeforeClass;
+
+import javax.persistence.EntityManager;
+import java.util.Arrays;
+import java.util.Date;
+
+/**
+ * @author Adam Warski (adam at warski dot org)
+ */
+public class Dates extends AbstractEntityTest {
+ private Integer id1;
+
+ public void configure(Ejb3Configuration cfg) {
+ cfg.addAnnotatedClass(DateTestEntity.class);
+ }
+
+ @BeforeClass(dependsOnMethods = "init")
+ public void initData() {
+ EntityManager em = getEntityManager();
+ em.getTransaction().begin();
+ DateTestEntity dte = new DateTestEntity(new Date(12345000));
+ em.persist(dte);
+ id1 = dte.getId();
+ em.getTransaction().commit();
+
+ em.getTransaction().begin();
+ dte = em.find(DateTestEntity.class, id1);
+ dte.setDate(new Date(45678000));
+ em.getTransaction().commit();
+ }
+
+ @Test
+ public void testRevisionsCounts() {
+ assert Arrays.asList(1, 2).equals(getVersionsReader().getRevisions(DateTestEntity.class, id1));
+ }
+
+ @Test
+ public void testHistoryOfId1() {
+ DateTestEntity ver1 = new DateTestEntity(id1, new Date(12345000));
+ DateTestEntity ver2 = new DateTestEntity(id1, new Date(45678000));
+
+ assert getVersionsReader().find(DateTestEntity.class, id1, 1).equals(ver1);
+ assert getVersionsReader().find(DateTestEntity.class, id1, 2).equals(ver2);
+ }
+}
\ No newline at end of file
Added: core/trunk/envers/src/test/java/org/jboss/envers/test/integration/data/EnumTestEntity.java
===================================================================
--- core/trunk/envers/src/test/java/org/jboss/envers/test/integration/data/EnumTestEntity.java (rev 0)
+++ core/trunk/envers/src/test/java/org/jboss/envers/test/integration/data/EnumTestEntity.java 2008-10-27 18:56:31 UTC (rev 15406)
@@ -0,0 +1,84 @@
+package org.jboss.envers.test.integration.data;
+
+import org.jboss.envers.Versioned;
+
+import javax.persistence.*;
+
+/**
+ * @author Adam Warski (adam at warski dot org)
+ */
+ at Entity
+ at Versioned
+public class EnumTestEntity {
+ @Id
+ @GeneratedValue
+ private Integer id;
+
+ public enum E1 { X, Y }
+ public enum E2 { A, B }
+
+ @Enumerated(EnumType.STRING)
+ private E1 enum1;
+
+ @Enumerated(EnumType.ORDINAL)
+ private E2 enum2;
+
+ public EnumTestEntity() {
+ }
+
+ public EnumTestEntity(E1 enum1, E2 enum2) {
+ this.enum1 = enum1;
+ this.enum2 = enum2;
+ }
+
+ public EnumTestEntity(Integer id, E1 enum1, E2 enum2) {
+ this.id = id;
+ this.enum1 = enum1;
+ this.enum2 = enum2;
+ }
+
+ public Integer getId() {
+ return id;
+ }
+
+ public void setId(Integer id) {
+ this.id = id;
+ }
+
+ public E1 getEnum1() {
+ return enum1;
+ }
+
+ public void setEnum1(E1 enum1) {
+ this.enum1 = enum1;
+ }
+
+ public E2 getEnum2() {
+ return enum2;
+ }
+
+ public void setEnum2(E2 enum2) {
+ this.enum2 = enum2;
+ }
+
+ public boolean equals(Object o) {
+ if (this == o) return true;
+ if (!(o instanceof EnumTestEntity)) return false;
+
+ EnumTestEntity that = (EnumTestEntity) o;
+
+ if (enum1 != that.enum1) return false;
+ if (enum2 != that.enum2) return false;
+ if (id != null ? !id.equals(that.id) : that.id != null) return false;
+
+ return true;
+ }
+
+ public int hashCode() {
+ int result;
+ result = (id != null ? id.hashCode() : 0);
+ result = 31 * result + (enum1 != null ? enum1.hashCode() : 0);
+ result = 31 * result + (enum2 != null ? enum2.hashCode() : 0);
+ return result;
+ }
+}
Added: core/trunk/envers/src/test/java/org/jboss/envers/test/integration/data/Enums.java
===================================================================
--- core/trunk/envers/src/test/java/org/jboss/envers/test/integration/data/Enums.java (rev 0)
+++ core/trunk/envers/src/test/java/org/jboss/envers/test/integration/data/Enums.java 2008-10-27 18:56:31 UTC (rev 15406)
@@ -0,0 +1,52 @@
+package org.jboss.envers.test.integration.data;
+
+import org.jboss.envers.test.AbstractEntityTest;
+import org.hibernate.ejb.Ejb3Configuration;
+import org.testng.annotations.Test;
+import org.testng.annotations.BeforeClass;
+
+import javax.persistence.EntityManager;
+import java.util.Arrays;
+
+/**
+ * @author Adam Warski (adam at warski dot org)
+ */
+public class Enums extends AbstractEntityTest {
+ private Integer id1;
+
+ public void configure(Ejb3Configuration cfg) {
+ cfg.addAnnotatedClass(EnumTestEntity.class);
+ }
+
+ @BeforeClass(dependsOnMethods = "init")
+ public void initData() {
+ EntityManager em = getEntityManager();
+ em.getTransaction().begin();
+ EnumTestEntity ete = new EnumTestEntity(EnumTestEntity.E1.X, EnumTestEntity.E2.A);
+ em.persist(ete);
+ id1 = ete.getId();
+ em.getTransaction().commit();
+
+ em.getTransaction().begin();
+ ete = em.find(EnumTestEntity.class, id1);
+ ete.setEnum1(EnumTestEntity.E1.Y);
+ ete.setEnum2(EnumTestEntity.E2.B);
+ em.getTransaction().commit();
+
+ newEntityManager();
+ }
+
+ @Test
+ public void testRevisionsCounts() {
+ assert Arrays.asList(1, 2).equals(getVersionsReader().getRevisions(EnumTestEntity.class, id1));
+ }
+
+ @Test
+ public void testHistoryOfId1() {
+ EnumTestEntity ver1 = new EnumTestEntity(id1, EnumTestEntity.E1.X, EnumTestEntity.E2.A);
+ EnumTestEntity ver2 = new EnumTestEntity(id1, EnumTestEntity.E1.Y, EnumTestEntity.E2.B);
+
+ assert getVersionsReader().find(EnumTestEntity.class, id1, 1).equals(ver1);
+ assert getVersionsReader().find(EnumTestEntity.class, id1, 2).equals(ver2);
+ }
+}
\ No newline at end of file
Added: core/trunk/envers/src/test/java/org/jboss/envers/test/integration/data/LobTestEntity.java
===================================================================
--- core/trunk/envers/src/test/java/org/jboss/envers/test/integration/data/LobTestEntity.java (rev 0)
+++ core/trunk/envers/src/test/java/org/jboss/envers/test/integration/data/LobTestEntity.java 2008-10-27 18:56:31 UTC (rev 15406)
@@ -0,0 +1,102 @@
+package org.jboss.envers.test.integration.data;
+
+import org.jboss.envers.Versioned;
+
+import javax.persistence.Entity;
+import javax.persistence.Id;
+import javax.persistence.GeneratedValue;
+import javax.persistence.Lob;
+import java.util.Arrays;
+
+/**
+ * @author Adam Warski (adam at warski dot org)
+ */
+ at Entity
+public class LobTestEntity {
+ @Id
+ @GeneratedValue
+ private Integer id;
+
+ @Lob
+ @Versioned
+ private String stringLob;
+
+ @Lob
+ @Versioned
+ private byte[] byteLob;
+
+ @Lob
+ @Versioned
+ private char[] charLob;
+
+ public LobTestEntity() {
+ }
+
+ public LobTestEntity(String stringLob, byte[] byteLob, char[] charLob) {
+ this.stringLob = stringLob;
+ this.byteLob = byteLob;
+ this.charLob = charLob;
+ }
+
+ public LobTestEntity(Integer id, String stringLob, byte[] byteLob, char[] charLob) {
+ this.id = id;
+ this.stringLob = stringLob;
+ this.byteLob = byteLob;
+ this.charLob = charLob;
+ }
+
+ public Integer getId() {
+ return id;
+ }
+
+ public void setId(Integer id) {
+ this.id = id;
+ }
+
+ public String getStringLob() {
+ return stringLob;
+ }
+
+ public void setStringLob(String stringLob) {
+ this.stringLob = stringLob;
+ }
+
+ public byte[] getByteLob() {
+ return byteLob;
+ }
+
+ public void setByteLob(byte[] byteLob) {
+ this.byteLob = byteLob;
+ }
+
+ public char[] getCharLob() {
+ return charLob;
+ }
+
+ public void setCharLob(char[] charLob) {
+ this.charLob = charLob;
+ }
+
+ public boolean equals(Object o) {
+ if (this == o) return true;
+ if (!(o instanceof LobTestEntity)) return false;
+
+ LobTestEntity that = (LobTestEntity) o;
+
+ if (!Arrays.equals(byteLob, that.byteLob)) return false;
+ if (!Arrays.equals(charLob, that.charLob)) return false;
+ if (id != null ? !id.equals(that.id) : that.id != null) return false;
+ if (stringLob != null ? !stringLob.equals(that.stringLob) : that.stringLob != null) return false;
+
+ return true;
+ }
+
+ public int hashCode() {
+ int result;
+ result = (id != null ? id.hashCode() : 0);
+ result = 31 * result + (stringLob != null ? stringLob.hashCode() : 0);
+ result = 31 * result + (byteLob != null ? Arrays.hashCode(byteLob) : 0);
+ result = 31 * result + (charLob != null ? Arrays.hashCode(charLob) : 0);
+ return result;
+ }
+}
\ No newline at end of file
Added: core/trunk/envers/src/test/java/org/jboss/envers/test/integration/data/Lobs.java
===================================================================
--- core/trunk/envers/src/test/java/org/jboss/envers/test/integration/data/Lobs.java (rev 0)
+++ core/trunk/envers/src/test/java/org/jboss/envers/test/integration/data/Lobs.java 2008-10-27 18:56:31 UTC (rev 15406)
@@ -0,0 +1,51 @@
+package org.jboss.envers.test.integration.data;
+
+import org.jboss.envers.test.AbstractEntityTest;
+import org.hibernate.ejb.Ejb3Configuration;
+import org.testng.annotations.Test;
+import org.testng.annotations.BeforeClass;
+
+import javax.persistence.EntityManager;
+import java.util.Arrays;
+
+/**
+ * @author Adam Warski (adam at warski dot org)
+ */
+public class Lobs extends AbstractEntityTest {
+ private Integer id1;
+
+ public void configure(Ejb3Configuration cfg) {
+ cfg.addAnnotatedClass(LobTestEntity.class);
+ }
+
+ @BeforeClass(dependsOnMethods = "init")
+ public void initData() {
+ EntityManager em = getEntityManager();
+ em.getTransaction().begin();
+ LobTestEntity lte = new LobTestEntity("abc", new byte[] { 0, 1, 2 }, new char[] { 'x', 'y', 'z' });
+ em.persist(lte);
+ id1 = lte.getId();
+ em.getTransaction().commit();
+
+ em.getTransaction().begin();
+ lte = em.find(LobTestEntity.class, id1);
+ lte.setStringLob("def");
+ lte.setByteLob(new byte[] { 3, 4, 5 });
+ lte.setCharLob(new char[] { 'h', 'i', 'j' });
+ em.getTransaction().commit();
+ }
+
+ @Test
+ public void testRevisionsCounts() {
+ assert Arrays.asList(1, 2).equals(getVersionsReader().getRevisions(LobTestEntity.class, id1));
+ }
+
+ @Test
+ public void testHistoryOfId1() {
+ LobTestEntity ver1 = new LobTestEntity(id1, "abc", new byte[] { 0, 1, 2 }, new char[] { 'x', 'y', 'z' });
+ LobTestEntity ver2 = new LobTestEntity(id1, "def", new byte[] { 3, 4, 5 }, new char[] { 'h', 'i', 'j' });
+
+ assert getVersionsReader().find(LobTestEntity.class, id1, 1).equals(ver1);
+ assert getVersionsReader().find(LobTestEntity.class, id1, 2).equals(ver2);
+ }
+}
\ No newline at end of file
Added: core/trunk/envers/src/test/java/org/jboss/envers/test/integration/data/SerObject.java
===================================================================
--- core/trunk/envers/src/test/java/org/jboss/envers/test/integration/data/SerObject.java (rev 0)
+++ core/trunk/envers/src/test/java/org/jboss/envers/test/integration/data/SerObject.java 2008-10-27 18:56:31 UTC (rev 15406)
@@ -0,0 +1,42 @@
+package org.jboss.envers.test.integration.data;
+
+import java.io.Serializable;
+
+/**
+ * @author Adam Warski (adam at warski dot org)
+ */
+public class SerObject implements Serializable {
+ static final long serialVersionUID = 982352321924L;
+
+ private String data;
+
+ public SerObject() {
+ }
+
+ public SerObject(String data) {
+ this.data = data;
+ }
+
+ public String getData() {
+ return data;
+ }
+
+ public void setData(String data) {
+ this.data = data;
+ }
+
+ public boolean equals(Object o) {
+ if (this == o) return true;
+ if (!(o instanceof SerObject)) return false;
+
+ SerObject serObject = (SerObject) o;
+
+ if (data != null ? !data.equals(serObject.data) : serObject.data != null) return false;
+
+ return true;
+ }
+
+ public int hashCode() {
+ return (data != null ? data.hashCode() : 0);
+ }
+}
Added: core/trunk/envers/src/test/java/org/jboss/envers/test/integration/data/SerializableTestEntity.java
===================================================================
--- core/trunk/envers/src/test/java/org/jboss/envers/test/integration/data/SerializableTestEntity.java (rev 0)
+++ core/trunk/envers/src/test/java/org/jboss/envers/test/integration/data/SerializableTestEntity.java 2008-10-27 18:56:31 UTC (rev 15406)
@@ -0,0 +1,68 @@
+package org.jboss.envers.test.integration.data;
+
+import org.jboss.envers.Versioned;
+
+import javax.persistence.Entity;
+import javax.persistence.Id;
+import javax.persistence.GeneratedValue;
+import java.util.Date;
+
+/**
+ * @author Adam Warski (adam at warski dot org)
+ */
+ at Entity
+public class SerializableTestEntity {
+ @Id
+ @GeneratedValue
+ private Integer id;
+
+ @Versioned
+ private SerObject obj;
+
+ public SerializableTestEntity() {
+ }
+
+ public SerializableTestEntity(SerObject obj) {
+ this.obj = obj;
+ }
+
+ public SerializableTestEntity(Integer id, SerObject obj) {
+ this.obj = obj;
+ this.id = id;
+ }
+
+ public Integer getId() {
+ return id;
+ }
+
+ public void setId(Integer id) {
+ this.id = id;
+ }
+
+ public SerObject getObj() {
+ return obj;
+ }
+
+ public void setObj(SerObject obj) {
+ this.obj = obj;
+ }
+
+ public boolean equals(Object o) {
+ if (this == o) return true;
+ if (!(o instanceof SerializableTestEntity)) return false;
+
+ SerializableTestEntity that = (SerializableTestEntity) o;
+
+ if (id != null ? !id.equals(that.id) : that.id != null) return false;
+ if (obj != null ? !obj.equals(that.obj) : that.obj != null) return false;
+
+ return true;
+ }
+
+ public int hashCode() {
+ int result;
+ result = (id != null ? id.hashCode() : 0);
+ result = 31 * result + (obj != null ? obj.hashCode() : 0);
+ return result;
+ }
+}
\ No newline at end of file
Added: core/trunk/envers/src/test/java/org/jboss/envers/test/integration/data/Serializables.java
===================================================================
--- core/trunk/envers/src/test/java/org/jboss/envers/test/integration/data/Serializables.java (rev 0)
+++ core/trunk/envers/src/test/java/org/jboss/envers/test/integration/data/Serializables.java 2008-10-27 18:56:31 UTC (rev 15406)
@@ -0,0 +1,49 @@
+package org.jboss.envers.test.integration.data;
+
+import org.jboss.envers.test.AbstractEntityTest;
+import org.hibernate.ejb.Ejb3Configuration;
+import org.testng.annotations.Test;
+import org.testng.annotations.BeforeClass;
+
+import javax.persistence.EntityManager;
+import java.util.Arrays;
+
+/**
+ * @author Adam Warski (adam at warski dot org)
+ */
+public class Serializables extends AbstractEntityTest {
+ private Integer id1;
+
+ public void configure(Ejb3Configuration cfg) {
+ cfg.addAnnotatedClass(SerializableTestEntity.class);
+ }
+
+ @BeforeClass(dependsOnMethods = "init")
+ public void initData() {
+ EntityManager em = getEntityManager();
+ em.getTransaction().begin();
+ SerializableTestEntity ste = new SerializableTestEntity(new SerObject("d1"));
+ em.persist(ste);
+ id1 = ste.getId();
+ em.getTransaction().commit();
+
+ em.getTransaction().begin();
+ ste = em.find(SerializableTestEntity.class, id1);
+ ste.setObj(new SerObject("d2"));
+ em.getTransaction().commit();
+ }
+
+ @Test
+ public void testRevisionsCounts() {
+ assert Arrays.asList(1, 2).equals(getVersionsReader().getRevisions(SerializableTestEntity.class, id1));
+ }
+
+ @Test
+ public void testHistoryOfId1() {
+ SerializableTestEntity ver1 = new SerializableTestEntity(id1, new SerObject("d1"));
+ SerializableTestEntity ver2 = new SerializableTestEntity(id1, new SerObject("d2"));
+
+ assert getVersionsReader().find(SerializableTestEntity.class, id1, 1).equals(ver1);
+ assert getVersionsReader().find(SerializableTestEntity.class, id1, 2).equals(ver2);
+ }
+}
\ No newline at end of file
Added: core/trunk/envers/src/test/java/org/jboss/envers/test/integration/flush/AbstractFlushTest.java
===================================================================
--- core/trunk/envers/src/test/java/org/jboss/envers/test/integration/flush/AbstractFlushTest.java (rev 0)
+++ core/trunk/envers/src/test/java/org/jboss/envers/test/integration/flush/AbstractFlushTest.java 2008-10-27 18:56:31 UTC (rev 15406)
@@ -0,0 +1,43 @@
+package org.jboss.envers.test.integration.flush;
+
+import org.jboss.envers.test.AbstractEntityTest;
+import org.jboss.envers.test.entities.StrTestEntity;
+import org.hibernate.FlushMode;
+import org.hibernate.Session;
+import org.hibernate.ejb.Ejb3Configuration;
+import org.testng.annotations.BeforeClass;
+
+import javax.persistence.EntityManager;
+import java.io.IOException;
+
+/**
+ * @author Adam Warski (adam at warski dot org)
+ */
+public abstract class AbstractFlushTest extends AbstractEntityTest {
+ public abstract FlushMode getFlushMode();
+
+ public void configure(Ejb3Configuration cfg) {
+ cfg.addAnnotatedClass(StrTestEntity.class);
+ }
+
+ private static Session getSession(EntityManager em) {
+ Object delegate = em.getDelegate();
+ if (delegate instanceof Session) {
+ return (Session) delegate;
+ } else if (delegate instanceof EntityManager) {
+ Object delegate2 = ((EntityManager) delegate).getDelegate();
+
+ if (delegate2 instanceof Session) {
+ return (Session) delegate2;
+ }
+ }
+
+ throw new RuntimeException("Invalid entity manager");
+ }
+
+ @BeforeClass(dependsOnMethods = "init")
+ public void initFlush() throws IOException {
+ Session session = getSession(getEntityManager());
+ session.setFlushMode(getFlushMode());
+ }
+}
Added: core/trunk/envers/src/test/java/org/jboss/envers/test/integration/flush/DoubleFlushAddDel.java
===================================================================
--- core/trunk/envers/src/test/java/org/jboss/envers/test/integration/flush/DoubleFlushAddDel.java (rev 0)
+++ core/trunk/envers/src/test/java/org/jboss/envers/test/integration/flush/DoubleFlushAddDel.java 2008-10-27 18:56:31 UTC (rev 15406)
@@ -0,0 +1,52 @@
+package org.jboss.envers.test.integration.flush;
+
+import org.testng.annotations.BeforeClass;
+import org.testng.annotations.Test;
+import org.hibernate.FlushMode;
+import org.jboss.envers.test.entities.StrTestEntity;
+
+import javax.persistence.EntityManager;
+import java.util.Arrays;
+
+/**
+ * @author Adam Warski (adam at warski dot org)
+ */
+public class DoubleFlushAddDel extends AbstractFlushTest {
+ private Integer id;
+
+ public FlushMode getFlushMode() {
+ return FlushMode.MANUAL;
+ }
+
+ @BeforeClass(dependsOnMethods = "initFlush")
+ public void initData() {
+ // Revision 1
+ EntityManager em = getEntityManager();
+ em.getTransaction().begin();
+
+ StrTestEntity fe = new StrTestEntity("x");
+ em.persist(fe);
+
+ em.flush();
+
+ em.remove(em.find(StrTestEntity.class, fe.getId()));
+
+ em.flush();
+
+ em.getTransaction().commit();
+
+ //
+
+ id = fe.getId();
+ }
+
+ @Test
+ public void testRevisionsCounts() {
+ assert Arrays.asList().equals(getVersionsReader().getRevisions(StrTestEntity.class, id));
+ }
+
+ @Test
+ public void testHistoryOfId() {
+ assert getVersionsReader().find(StrTestEntity.class, id, 1) == null;
+ }
+}
\ No newline at end of file
Added: core/trunk/envers/src/test/java/org/jboss/envers/test/integration/flush/DoubleFlushAddMod.java
===================================================================
--- core/trunk/envers/src/test/java/org/jboss/envers/test/integration/flush/DoubleFlushAddMod.java (rev 0)
+++ core/trunk/envers/src/test/java/org/jboss/envers/test/integration/flush/DoubleFlushAddMod.java 2008-10-27 18:56:31 UTC (rev 15406)
@@ -0,0 +1,66 @@
+package org.jboss.envers.test.integration.flush;
+
+import org.testng.annotations.BeforeClass;
+import org.testng.annotations.Test;
+import org.hibernate.FlushMode;
+import org.jboss.envers.test.entities.StrTestEntity;
+
+import javax.persistence.EntityManager;
+import java.util.Arrays;
+
+/**
+ * @author Adam Warski (adam at warski dot org)
+ */
+public class DoubleFlushAddMod extends AbstractFlushTest {
+ private Integer id;
+
+ public FlushMode getFlushMode() {
+ return FlushMode.MANUAL;
+ }
+
+ @BeforeClass(dependsOnMethods = "initFlush")
+ public void initData() {
+ // Revision 1
+ EntityManager em = getEntityManager();
+ em.getTransaction().begin();
+
+ StrTestEntity fe = new StrTestEntity("x");
+ em.persist(fe);
+
+ em.flush();
+
+ fe.setStr("y");
+
+ em.flush();
+
+ em.getTransaction().commit();
+
+ // Revision 2
+ em.getTransaction().begin();
+
+ fe = em.find(StrTestEntity.class, fe.getId());
+
+ fe.setStr("z");
+ em.flush();
+
+ em.getTransaction().commit();
+
+ //
+
+ id = fe.getId();
+ }
+
+ @Test
+ public void testRevisionsCounts() {
+ assert Arrays.asList(1, 2).equals(getVersionsReader().getRevisions(StrTestEntity.class, id));
+ }
+
+ @Test
+ public void testHistoryOfId() {
+ StrTestEntity ver1 = new StrTestEntity("y", id);
+ StrTestEntity ver2 = new StrTestEntity("z", id);
+
+ assert getVersionsReader().find(StrTestEntity.class, id, 1).equals(ver1);
+ assert getVersionsReader().find(StrTestEntity.class, id, 2).equals(ver2);
+ }
+}
\ No newline at end of file
Added: core/trunk/envers/src/test/java/org/jboss/envers/test/integration/flush/DoubleFlushModDel.java
===================================================================
--- core/trunk/envers/src/test/java/org/jboss/envers/test/integration/flush/DoubleFlushModDel.java (rev 0)
+++ core/trunk/envers/src/test/java/org/jboss/envers/test/integration/flush/DoubleFlushModDel.java 2008-10-27 18:56:31 UTC (rev 15406)
@@ -0,0 +1,62 @@
+package org.jboss.envers.test.integration.flush;
+
+import org.testng.annotations.BeforeClass;
+import org.testng.annotations.Test;
+import org.hibernate.FlushMode;
+import org.jboss.envers.test.entities.StrTestEntity;
+
+import javax.persistence.EntityManager;
+import java.util.Arrays;
+
+/**
+ * @author Adam Warski (adam at warski dot org)
+ */
+public class DoubleFlushModDel extends AbstractFlushTest {
+ private Integer id;
+
+ public FlushMode getFlushMode() {
+ return FlushMode.MANUAL;
+ }
+
+ @BeforeClass(dependsOnMethods = "initFlush")
+ public void initData() {
+ // Revision 1
+ EntityManager em = getEntityManager();
+ em.getTransaction().begin();
+
+ StrTestEntity fe = new StrTestEntity("x");
+ em.persist(fe);
+
+ em.getTransaction().commit();
+
+ // Revision 2
+ em.getTransaction().begin();
+
+ fe = em.find(StrTestEntity.class, fe.getId());
+
+ fe.setStr("y");
+ em.flush();
+
+ em.remove(em.find(StrTestEntity.class, fe.getId()));
+ em.flush();
+
+ em.getTransaction().commit();
+
+ //
+
+ id = fe.getId();
+ }
+
+ @Test
+ public void testRevisionsCounts() {
+ assert Arrays.asList(1, 2).equals(getVersionsReader().getRevisions(StrTestEntity.class, id));
+ }
+
+ @Test
+ public void testHistoryOfId() {
+ StrTestEntity ver1 = new StrTestEntity("x", id);
+
+ assert getVersionsReader().find(StrTestEntity.class, id, 1).equals(ver1);
+ assert getVersionsReader().find(StrTestEntity.class, id, 2) == null;
+ }
+}
\ No newline at end of file
Added: core/trunk/envers/src/test/java/org/jboss/envers/test/integration/flush/DoubleFlushModMod.java
===================================================================
--- core/trunk/envers/src/test/java/org/jboss/envers/test/integration/flush/DoubleFlushModMod.java (rev 0)
+++ core/trunk/envers/src/test/java/org/jboss/envers/test/integration/flush/DoubleFlushModMod.java 2008-10-27 18:56:31 UTC (rev 15406)
@@ -0,0 +1,63 @@
+package org.jboss.envers.test.integration.flush;
+
+import org.testng.annotations.BeforeClass;
+import org.testng.annotations.Test;
+import org.hibernate.FlushMode;
+import org.jboss.envers.test.entities.StrTestEntity;
+
+import javax.persistence.EntityManager;
+import java.util.Arrays;
+
+/**
+ * @author Adam Warski (adam at warski dot org)
+ */
+public class DoubleFlushModMod extends AbstractFlushTest {
+ private Integer id;
+
+ public FlushMode getFlushMode() {
+ return FlushMode.MANUAL;
+ }
+
+ @BeforeClass(dependsOnMethods = "initFlush")
+ public void initData() {
+ // Revision 1
+ EntityManager em = getEntityManager();
+ em.getTransaction().begin();
+
+ StrTestEntity fe = new StrTestEntity("x");
+ em.persist(fe);
+
+ em.getTransaction().commit();
+
+ // Revision 2
+ em.getTransaction().begin();
+
+ fe = em.find(StrTestEntity.class, fe.getId());
+
+ fe.setStr("y");
+ em.flush();
+
+ fe.setStr("z");
+ em.flush();
+
+ em.getTransaction().commit();
+
+ //
+
+ id = fe.getId();
+ }
+
+ @Test
+ public void testRevisionsCounts() {
+ assert Arrays.asList(1, 2).equals(getVersionsReader().getRevisions(StrTestEntity.class, id));
+ }
+
+ @Test
+ public void testHistoryOfId() {
+ StrTestEntity ver1 = new StrTestEntity("x", id);
+ StrTestEntity ver2 = new StrTestEntity("z", id);
+
+ assert getVersionsReader().find(StrTestEntity.class, id, 1).equals(ver1);
+ assert getVersionsReader().find(StrTestEntity.class, id, 2).equals(ver2);
+ }
+}
\ No newline at end of file
Added: core/trunk/envers/src/test/java/org/jboss/envers/test/integration/flush/ManualFlush.java
===================================================================
--- core/trunk/envers/src/test/java/org/jboss/envers/test/integration/flush/ManualFlush.java (rev 0)
+++ core/trunk/envers/src/test/java/org/jboss/envers/test/integration/flush/ManualFlush.java 2008-10-27 18:56:31 UTC (rev 15406)
@@ -0,0 +1,75 @@
+package org.jboss.envers.test.integration.flush;
+
+import org.testng.annotations.BeforeClass;
+import org.testng.annotations.Test;
+import org.hibernate.FlushMode;
+import org.jboss.envers.test.entities.StrTestEntity;
+
+import javax.persistence.EntityManager;
+import java.util.Arrays;
+
+/**
+ * @author Adam Warski (adam at warski dot org)
+ */
+public class ManualFlush extends AbstractFlushTest {
+ private Integer id;
+
+ public FlushMode getFlushMode() {
+ return FlushMode.MANUAL;
+ }
+
+ @BeforeClass(dependsOnMethods = "initFlush")
+ public void initData() {
+ // Revision 1
+ EntityManager em = getEntityManager();
+ em.getTransaction().begin();
+
+ StrTestEntity fe = new StrTestEntity("x");
+ em.persist(fe);
+
+ em.getTransaction().commit();
+
+ // No revision - we change the data, but do not flush the session
+ em.getTransaction().begin();
+
+ fe = em.find(StrTestEntity.class, fe.getId());
+ fe.setStr("y");
+
+ em.getTransaction().commit();
+
+ // Revision 2 - only the first change should be saved
+ em.getTransaction().begin();
+
+ fe = em.find(StrTestEntity.class, fe.getId());
+ fe.setStr("z");
+ em.flush();
+
+ fe = em.find(StrTestEntity.class, fe.getId());
+ fe.setStr("z2");
+
+ em.getTransaction().commit();
+
+ //
+
+ id = fe.getId();
+ }
+
+ @Test
+ public void testRevisionsCounts() {
+ assert Arrays.asList(1, 2).equals(getVersionsReader().getRevisions(StrTestEntity.class, id));
+ }
+
+ @Test
+ public void testHistoryOfId() {
+ StrTestEntity ver1 = new StrTestEntity("x", id);
+ StrTestEntity ver2 = new StrTestEntity("z", id);
+
+ assert getVersionsReader().find(StrTestEntity.class, id, 1).equals(ver1);
+ assert getVersionsReader().find(StrTestEntity.class, id, 2).equals(ver2);
+ }
+
+ @Test
+ public void testCurrent() {
+ assert getEntityManager().find(StrTestEntity.class, id).equals(new StrTestEntity("z", id));
+ }
+}
Added: core/trunk/envers/src/test/java/org/jboss/envers/test/integration/ids/CompositeIds.java
===================================================================
--- core/trunk/envers/src/test/java/org/jboss/envers/test/integration/ids/CompositeIds.java (rev 0)
+++ core/trunk/envers/src/test/java/org/jboss/envers/test/integration/ids/CompositeIds.java 2008-10-27 18:56:31 UTC (rev 15406)
@@ -0,0 +1,155 @@
+package org.jboss.envers.test.integration.ids;
+
+import org.jboss.envers.test.AbstractEntityTest;
+import org.jboss.envers.test.entities.ids.EmbId;
+import org.jboss.envers.test.entities.ids.MulId;
+import org.jboss.envers.test.entities.ids.EmbIdTestEntity;
+import org.jboss.envers.test.entities.ids.MulIdTestEntity;
+import org.hibernate.ejb.Ejb3Configuration;
+import org.testng.annotations.BeforeClass;
+import org.testng.annotations.Test;
+
+import javax.persistence.EntityManager;
+import java.util.Arrays;
+
+/**
+ * @author Adam Warski (adam at warski dot org)
+ */
+public class CompositeIds extends AbstractEntityTest {
+ private EmbId id1;
+ private EmbId id2;
+ private MulId id3;
+ private MulId id4;
+
+ public void configure(Ejb3Configuration cfg) {
+ cfg.addAnnotatedClass(EmbIdTestEntity.class);
+ cfg.addAnnotatedClass(MulIdTestEntity.class);
+ }
+
+ @BeforeClass(dependsOnMethods = "init")
+ public void initData() {
+ id1 = new EmbId(1, 2);
+ id2 = new EmbId(10, 20);
+ id3 = new MulId(100, 101);
+ id4 = new MulId(102, 103);
+
+ // Revision 1
+ EntityManager em = getEntityManager();
+ em.getTransaction().begin();
+
+ em.persist(new EmbIdTestEntity(id1, "x"));
+ em.persist(new MulIdTestEntity(id3.getId1(), id3.getId2(), "a"));
+
+ em.getTransaction().commit();
+
+ // Revision 2
+ em = getEntityManager();
+ em.getTransaction().begin();
+
+ em.persist(new EmbIdTestEntity(id2, "y"));
+ em.persist(new MulIdTestEntity(id4.getId1(), id4.getId2(), "b"));
+
+ em.getTransaction().commit();
+
+ // Revision 3
+ em = getEntityManager();
+ em.getTransaction().begin();
+
+ EmbIdTestEntity ete1 = em.find(EmbIdTestEntity.class, id1);
+ EmbIdTestEntity ete2 = em.find(EmbIdTestEntity.class, id2);
+ MulIdTestEntity mte3 = em.find(MulIdTestEntity.class, id3);
+ MulIdTestEntity mte4 = em.find(MulIdTestEntity.class, id4);
+
+ ete1.setStr1("x2");
+ ete2.setStr1("y2");
+ mte3.setStr1("a2");
+ mte4.setStr1("b2");
+
+ em.getTransaction().commit();
+
+ // Revision 4
+ em = getEntityManager();
+ em.getTransaction().begin();
+
+ ete1 = em.find(EmbIdTestEntity.class, id1);
+ ete2 = em.find(EmbIdTestEntity.class, id2);
+ mte3 = em.find(MulIdTestEntity.class, id3);
+
+ em.remove(ete1);
+ em.remove(mte3);
+
+ ete2.setStr1("y3");
+
+ em.getTransaction().commit();
+
+ // Revision 5
+ em = getEntityManager();
+ em.getTransaction().begin();
+
+ ete2 = em.find(EmbIdTestEntity.class, id2);
+
+ em.remove(ete2);
+
+ em.getTransaction().commit();
+ }
+
+ @Test
+ public void testRevisionsCounts() {
+ assert Arrays.asList(1, 3, 4).equals(getVersionsReader().getRevisions(EmbIdTestEntity.class, id1));
+
+ assert Arrays.asList(2, 3, 4, 5).equals(getVersionsReader().getRevisions(EmbIdTestEntity.class, id2));
+
+ assert Arrays.asList(1, 3, 4).equals(getVersionsReader().getRevisions(MulIdTestEntity.class, id3));
+
+ assert Arrays.asList(2, 3).equals(getVersionsReader().getRevisions(MulIdTestEntity.class, id4));
+ }
+
+ @Test
+ public void testHistoryOfId1() {
+ EmbIdTestEntity ver1 = new EmbIdTestEntity(id1, "x");
+ EmbIdTestEntity ver2 = new EmbIdTestEntity(id1, "x2");
+
+ assert getVersionsReader().find(EmbIdTestEntity.class, id1, 1).equals(ver1);
+ assert getVersionsReader().find(EmbIdTestEntity.class, id1, 2).equals(ver1);
+ assert getVersionsReader().find(EmbIdTestEntity.class, id1, 3).equals(ver2);
+ assert getVersionsReader().find(EmbIdTestEntity.class, id1, 4) == null;
+ assert getVersionsReader().find(EmbIdTestEntity.class, id1, 5) == null;
+ }
+
+ @Test
+ public void testHistoryOfId2() {
+ EmbIdTestEntity ver1 = new EmbIdTestEntity(id2, "y");
+ EmbIdTestEntity ver2 = new EmbIdTestEntity(id2, "y2");
+ EmbIdTestEntity ver3 = new EmbIdTestEntity(id2, "y3");
+
+ assert getVersionsReader().find(EmbIdTestEntity.class, id2, 1) == null;
+ assert getVersionsReader().find(EmbIdTestEntity.class, id2, 2).equals(ver1);
+ assert getVersionsReader().find(EmbIdTestEntity.class, id2, 3).equals(ver2);
+ assert getVersionsReader().find(EmbIdTestEntity.class, id2, 4).equals(ver3);
+ assert getVersionsReader().find(EmbIdTestEntity.class, id2, 5) == null;
+ }
+
+ @Test
+ public void testHistoryOfId3() {
+ MulIdTestEntity ver1 = new MulIdTestEntity(id3.getId1(), id3.getId2(), "a");
+ MulIdTestEntity ver2 = new MulIdTestEntity(id3.getId1(), id3.getId2(), "a2");
+
+ assert getVersionsReader().find(MulIdTestEntity.class, id3, 1).equals(ver1);
+ assert getVersionsReader().find(MulIdTestEntity.class, id3, 2).equals(ver1);
+ assert getVersionsReader().find(MulIdTestEntity.class, id3, 3).equals(ver2);
+ assert getVersionsReader().find(MulIdTestEntity.class, id3, 4) == null;
+ assert getVersionsReader().find(MulIdTestEntity.class, id3, 5) == null;
+ }
+
+ @Test
+ public void testHistoryOfId4() {
+ MulIdTestEntity ver1 = new MulIdTestEntity(id4.getId1(), id4.getId2(), "b");
+ MulIdTestEntity ver2 = new MulIdTestEntity(id4.getId1(), id4.getId2(), "b2");
+
+ assert getVersionsReader().find(MulIdTestEntity.class, id4, 1) == null;
+ assert getVersionsReader().find(MulIdTestEntity.class, id4, 2).equals(ver1);
+ assert getVersionsReader().find(MulIdTestEntity.class, id4, 3).equals(ver2);
+ assert getVersionsReader().find(MulIdTestEntity.class, id4, 4).equals(ver2);
+ assert getVersionsReader().find(MulIdTestEntity.class, id4, 5).equals(ver2);
+ }
+}
Added: core/trunk/envers/src/test/java/org/jboss/envers/test/integration/inheritance/single/ChildEntity.java
===================================================================
--- core/trunk/envers/src/test/java/org/jboss/envers/test/integration/inheritance/single/ChildEntity.java (rev 0)
+++ core/trunk/envers/src/test/java/org/jboss/envers/test/integration/inheritance/single/ChildEntity.java 2008-10-27 18:56:31 UTC (rev 15406)
@@ -0,0 +1,59 @@
+package org.jboss.envers.test.integration.inheritance.single;
+
+import org.jboss.envers.Versioned;
+
+import javax.persistence.*;
+
+/**
+ * @author Adam Warski (adam at warski dot org)
+ */
+ at Entity
+ at DiscriminatorValue("2")
+ at Versioned
+public class ChildEntity extends ParentEntity {
+ @Basic
+ private Long number;
+
+ public ChildEntity() {
+ }
+
+ public ChildEntity(String data, Long number) {
+ super(data);
+ this.number = number;
+ }
+
+ public ChildEntity(Integer id, String data, Long number) {
+ super(id, data);
+ this.number = number;
+ }
+
+ public Long getNumber() {
+ return number;
+ }
+
+ public void setNumber(Long number) {
+ this.number = number;
+ }
+
+ public boolean equals(Object o) {
+ if (this == o) return true;
+ if (!(o instanceof ChildEntity)) return false;
+ if (!super.equals(o)) return false;
+
+ ChildEntity childEntity = (ChildEntity) o;
+
+ if (number != null ? !number.equals(childEntity.number) : childEntity.number != null) return false;
+
+ return true;
+ }
+
+ public int hashCode() {
+ int result = super.hashCode();
+ result = 31 * result + (number != null ? number.hashCode() : 0);
+ return result;
+ }
+
+ public String toString() {
+ return "ChildEntity(id = " + getId() + ", data = " + getData() + ", number = " + number + ")";
+ }
+}
\ No newline at end of file
Added: core/trunk/envers/src/test/java/org/jboss/envers/test/integration/inheritance/single/ChildVersioning.java
===================================================================
--- core/trunk/envers/src/test/java/org/jboss/envers/test/integration/inheritance/single/ChildVersioning.java (rev 0)
+++ core/trunk/envers/src/test/java/org/jboss/envers/test/integration/inheritance/single/ChildVersioning.java 2008-10-27 18:56:31 UTC (rev 15406)
@@ -0,0 +1,68 @@
+package org.jboss.envers.test.integration.inheritance.single;
+
+import org.hibernate.ejb.Ejb3Configuration;
+import org.testng.annotations.BeforeClass;
+import org.testng.annotations.Test;
+import org.jboss.envers.test.AbstractEntityTest;
+
+import javax.persistence.EntityManager;
+import java.util.Arrays;
+
+/**
+ * @author Adam Warski (adam at warski dot org)
+ */
+public class ChildVersioning extends AbstractEntityTest {
+ private Integer id1;
+
+ public void configure(Ejb3Configuration cfg) {
+ cfg.addAnnotatedClass(ChildEntity.class);
+ cfg.addAnnotatedClass(ParentEntity.class);
+ }
+
+ @BeforeClass(dependsOnMethods = "init")
+ public void initData() {
+ EntityManager em = getEntityManager();
+
+ // Rev 1
+ em.getTransaction().begin();
+ ChildEntity ce = new ChildEntity("x", 1l);
+ em.persist(ce);
+ id1 = ce.getId();
+ em.getTransaction().commit();
+
+ // Rev 2
+ em.getTransaction().begin();
+ ce = em.find(ChildEntity.class, id1);
+ ce.setData("y");
+ ce.setNumber(2l);
+ em.getTransaction().commit();
+ }
+
+ @Test
+ public void testRevisionsCounts() {
+ assert Arrays.asList(1, 2).equals(getVersionsReader().getRevisions(ChildEntity.class, id1));
+ }
+
+ @Test
+ public void testHistoryOfChildId1() {
+ ChildEntity ver1 = new ChildEntity(id1, "x", 1l);
+ ChildEntity ver2 = new ChildEntity(id1, "y", 2l);
+
+ assert getVersionsReader().find(ChildEntity.class, id1, 1).equals(ver1);
+ assert getVersionsReader().find(ChildEntity.class, id1, 2).equals(ver2);
+
+ assert getVersionsReader().find(ParentEntity.class, id1, 1).equals(ver1);
+ assert getVersionsReader().find(ParentEntity.class, id1, 2).equals(ver2);
+ }
+
+ @Test
+ public void testPolymorphicQuery() {
+ ChildEntity childVer1 = new ChildEntity(id1, "x", 1l);
+
+ assert getVersionsReader().createQuery().forEntitiesAtRevision(ChildEntity.class, 1).getSingleResult()
+ .equals(childVer1);
+
+ assert getVersionsReader().createQuery().forEntitiesAtRevision(ParentEntity.class, 1).getSingleResult()
+ .equals(childVer1);
+ }
+}
Added: core/trunk/envers/src/test/java/org/jboss/envers/test/integration/inheritance/single/ParentEntity.java
===================================================================
--- core/trunk/envers/src/test/java/org/jboss/envers/test/integration/inheritance/single/ParentEntity.java (rev 0)
+++ core/trunk/envers/src/test/java/org/jboss/envers/test/integration/inheritance/single/ParentEntity.java 2008-10-27 18:56:31 UTC (rev 15406)
@@ -0,0 +1,73 @@
+package org.jboss.envers.test.integration.inheritance.single;
+
+import org.jboss.envers.Versioned;
+
+import javax.persistence.*;
+
+/**
+ * @author Adam Warski (adam at warski dot org)
+ */
+ at Entity
+ at Inheritance(strategy = InheritanceType.SINGLE_TABLE)
+ at DiscriminatorColumn(name = "discriminator", discriminatorType = DiscriminatorType.INTEGER)
+ at DiscriminatorValue("1")
+ at Versioned
+public class ParentEntity {
+ @Id
+ @GeneratedValue
+ private Integer id;
+
+ @Basic
+ private String data;
+
+ public ParentEntity() {
+ }
+
+ public ParentEntity(String data) {
+ this.data = data;
+ }
+
+ public ParentEntity(Integer id, String data) {
+ this.id = id;
+ this.data = data;
+ }
+
+ public Integer getId() {
+ return id;
+ }
+
+ public void setId(Integer id) {
+ this.id = id;
+ }
+
+ public String getData() {
+ return data;
+ }
+
+ public void setData(String data) {
+ this.data = data;
+ }
+
+ public boolean equals(Object o) {
+ if (this == o) return true;
+ if (!(o instanceof ParentEntity)) return false;
+
+ ParentEntity that = (ParentEntity) o;
+
+ if (data != null ? !data.equals(that.data) : that.data != null) return false;
+ if (id != null ? !id.equals(that.id) : that.id != null) return false;
+
+ return true;
+ }
+
+ public int hashCode() {
+ int result;
+ result = (id != null ? id.hashCode() : 0);
+ result = 31 * result + (data != null ? data.hashCode() : 0);
+ return result;
+ }
+
+ public String toString() {
+ return "ParentEntity(id = " + getId() + ", data = " + getData() + ")";
+ }
+}
\ No newline at end of file
Added: core/trunk/envers/src/test/java/org/jboss/envers/test/integration/inheritance/single/ParentVersioning.java
===================================================================
--- core/trunk/envers/src/test/java/org/jboss/envers/test/integration/inheritance/single/ParentVersioning.java (rev 0)
+++ core/trunk/envers/src/test/java/org/jboss/envers/test/integration/inheritance/single/ParentVersioning.java 2008-10-27 18:56:31 UTC (rev 15406)
@@ -0,0 +1,69 @@
+package org.jboss.envers.test.integration.inheritance.single;
+
+import org.hibernate.ejb.Ejb3Configuration;
+import org.testng.annotations.BeforeClass;
+import org.testng.annotations.Test;
+import org.jboss.envers.test.AbstractEntityTest;
+
+import javax.persistence.EntityManager;
+import java.util.Arrays;
+
+/**
+ * @author Adam Warski (adam at warski dot org)
+ */
+public class ParentVersioning extends AbstractEntityTest {
+ private Integer id1;
+
+ public void configure(Ejb3Configuration cfg) {
+ cfg.addAnnotatedClass(ChildEntity.class);
+ cfg.addAnnotatedClass(ParentEntity.class);
+ }
+
+ @BeforeClass(dependsOnMethods = "init")
+ public void initData() {
+ EntityManager em = getEntityManager();
+
+ // Rev 1
+ em.getTransaction().begin();
+ ParentEntity pe = new ParentEntity("x");
+ em.persist(pe);
+ id1 = pe.getId();
+ em.getTransaction().commit();
+
+ // Rev 2
+ em.getTransaction().begin();
+ pe = em.find(ParentEntity.class, id1);
+ pe.setData("y");
+ em.getTransaction().commit();
+ }
+
+ @Test
+ public void testRevisionsCounts() {
+ assert Arrays.asList(1, 2).equals(getVersionsReader().getRevisions(ParentEntity.class, id1));
+ }
+
+ @Test
+ public void testHistoryOfChildId1() {
+ assert getVersionsReader().find(ChildEntity.class, id1, 1) == null;
+ assert getVersionsReader().find(ChildEntity.class, id1, 2) == null;
+ }
+
+ @Test
+ public void testHistoryOfParentId1() {
+ ParentEntity ver1 = new ParentEntity(id1, "x");
+ ParentEntity ver2 = new ParentEntity(id1, "y");
+
+ assert getVersionsReader().find(ParentEntity.class, id1, 1).equals(ver1);
+ assert getVersionsReader().find(ParentEntity.class, id1, 2).equals(ver2);
+ }
+
+ @Test
+ public void testPolymorphicQuery() {
+ ParentEntity parentVer1 = new ParentEntity(id1, "x");
+
+ assert getVersionsReader().createQuery().forEntitiesAtRevision(ParentEntity.class, 1).getSingleResult()
+ .equals(parentVer1);
+ assert getVersionsReader().createQuery().forEntitiesAtRevision(ChildEntity.class, 1)
+ .getResultList().size() == 0;
+ }
+}
\ No newline at end of file
Added: core/trunk/envers/src/test/java/org/jboss/envers/test/integration/inheritance/single/childrelation/ChildIngEntity.java
===================================================================
--- core/trunk/envers/src/test/java/org/jboss/envers/test/integration/inheritance/single/childrelation/ChildIngEntity.java (rev 0)
+++ core/trunk/envers/src/test/java/org/jboss/envers/test/integration/inheritance/single/childrelation/ChildIngEntity.java 2008-10-27 18:56:31 UTC (rev 15406)
@@ -0,0 +1,70 @@
+package org.jboss.envers.test.integration.inheritance.single.childrelation;
+
+import org.jboss.envers.Versioned;
+
+import javax.persistence.*;
+
+/**
+ * @author Adam Warski (adam at warski dot org)
+ */
+ at Entity
+ at DiscriminatorValue("2")
+ at Versioned
+public class ChildIngEntity extends ParentNotIngEntity {
+ @Basic
+ private Long number;
+
+ @ManyToOne
+ private ReferencedEntity referenced;
+
+ public ChildIngEntity() {
+ }
+
+ public ChildIngEntity(String data, Long number) {
+ super(data);
+ this.number = number;
+ }
+
+ public ChildIngEntity(Integer id, String data, Long number) {
+ super(id, data);
+ this.number = number;
+ }
+
+ public Long getNumber() {
+ return number;
+ }
+
+ public void setNumber(Long number) {
+ this.number = number;
+ }
+
+ public ReferencedEntity getReferenced() {
+ return referenced;
+ }
+
+ public void setReferenced(ReferencedEntity referenced) {
+ this.referenced = referenced;
+ }
+
+ public boolean equals(Object o) {
+ if (this == o) return true;
+ if (!(o instanceof ChildIngEntity)) return false;
+ if (!super.equals(o)) return false;
+
+ ChildIngEntity childEntity = (ChildIngEntity) o;
+
+ if (number != null ? !number.equals(childEntity.number) : childEntity.number != null) return false;
+
+ return true;
+ }
+
+ public int hashCode() {
+ int result = super.hashCode();
+ result = 31 * result + (number != null ? number.hashCode() : 0);
+ return result;
+ }
+
+ public String toString() {
+ return "ChildIngEntity(id = " + getId() + ", data = " + getData() + ", number = " + number + ")";
+ }
+}
\ No newline at end of file
Added: core/trunk/envers/src/test/java/org/jboss/envers/test/integration/inheritance/single/childrelation/ChildReferencing.java
===================================================================
--- core/trunk/envers/src/test/java/org/jboss/envers/test/integration/inheritance/single/childrelation/ChildReferencing.java (rev 0)
+++ core/trunk/envers/src/test/java/org/jboss/envers/test/integration/inheritance/single/childrelation/ChildReferencing.java 2008-10-27 18:56:31 UTC (rev 15406)
@@ -0,0 +1,97 @@
+package org.jboss.envers.test.integration.inheritance.single.childrelation;
+
+import org.hibernate.ejb.Ejb3Configuration;
+import org.testng.annotations.BeforeClass;
+import org.testng.annotations.Test;
+import org.jboss.envers.test.AbstractEntityTest;
+import org.jboss.envers.test.tools.TestTools;
+
+import javax.persistence.EntityManager;
+import java.util.Arrays;
+
+/**
+ * @author Adam Warski (adam at warski dot org)
+ */
+public class ChildReferencing extends AbstractEntityTest {
+ private Integer re_id1;
+ private Integer re_id2;
+ private Integer c_id;
+
+ public void configure(Ejb3Configuration cfg) {
+ cfg.addAnnotatedClass(ChildIngEntity.class);
+ cfg.addAnnotatedClass(ParentNotIngEntity.class);
+ cfg.addAnnotatedClass(ReferencedEntity.class);
+ }
+
+ @BeforeClass(dependsOnMethods = "init")
+ public void initData() {
+ EntityManager em = getEntityManager();
+
+ // Rev 1
+ em.getTransaction().begin();
+
+ ReferencedEntity re1 = new ReferencedEntity();
+ em.persist(re1);
+ re_id1 = re1.getId();
+
+ ReferencedEntity re2 = new ReferencedEntity();
+ em.persist(re2);
+ re_id2 = re2.getId();
+
+ em.getTransaction().commit();
+
+ // Rev 2
+ em.getTransaction().begin();
+
+ re1 = em.find(ReferencedEntity.class, re_id1);
+
+ ChildIngEntity cie = new ChildIngEntity("y", 1l);
+ cie.setReferenced(re1);
+ em.persist(cie);
+ c_id = cie.getId();
+
+ em.getTransaction().commit();
+
+ // Rev 3
+ em.getTransaction().begin();
+
+ re2 = em.find(ReferencedEntity.class, re_id2);
+ cie = em.find(ChildIngEntity.class, c_id);
+
+ cie.setReferenced(re2);
+
+ em.getTransaction().commit();
+ }
+
+ @Test
+ public void testRevisionsCounts() {
+ assert Arrays.asList(1, 2, 3).equals(getVersionsReader().getRevisions(ReferencedEntity.class, re_id1));
+ assert Arrays.asList(1, 3).equals(getVersionsReader().getRevisions(ReferencedEntity.class, re_id2));
+ assert Arrays.asList(2, 3).equals(getVersionsReader().getRevisions(ChildIngEntity.class, c_id));
+ }
+
+ @Test
+ public void testHistoryOfReferencedCollection1() {
+ assert getVersionsReader().find(ReferencedEntity.class, re_id1, 1).getReferencing().size() == 0;
+ assert getVersionsReader().find(ReferencedEntity.class, re_id1, 2).getReferencing().equals(
+ TestTools.makeSet(new ChildIngEntity(c_id, "y", 1l)));
+ assert getVersionsReader().find(ReferencedEntity.class, re_id1, 3).getReferencing().size() == 0;
+ }
+
+ @Test
+ public void testHistoryOfReferencedCollection2() {
+ assert getVersionsReader().find(ReferencedEntity.class, re_id2, 1).getReferencing().size() == 0;
+ assert getVersionsReader().find(ReferencedEntity.class, re_id2, 2).getReferencing().size() == 0;
+ assert getVersionsReader().find(ReferencedEntity.class, re_id2, 3).getReferencing().equals(
+ TestTools.makeSet(new ChildIngEntity(c_id, "y", 1l)));
+ }
+
+ @Test
+ public void testChildHistory() {
+ assert getVersionsReader().find(ChildIngEntity.class, c_id, 1) == null;
+ assert getVersionsReader().find(ChildIngEntity.class, c_id, 2).getReferenced().equals(
+ new ReferencedEntity(re_id1));
+ assert getVersionsReader().find(ChildIngEntity.class, c_id, 3).getReferenced().equals(
+ new ReferencedEntity(re_id2));
+ }
+}
\ No newline at end of file
Added: core/trunk/envers/src/test/java/org/jboss/envers/test/integration/inheritance/single/childrelation/ParentNotIngEntity.java
===================================================================
--- core/trunk/envers/src/test/java/org/jboss/envers/test/integration/inheritance/single/childrelation/ParentNotIngEntity.java (rev 0)
+++ core/trunk/envers/src/test/java/org/jboss/envers/test/integration/inheritance/single/childrelation/ParentNotIngEntity.java 2008-10-27 18:56:31 UTC (rev 15406)
@@ -0,0 +1,73 @@
+package org.jboss.envers.test.integration.inheritance.single.childrelation;
+
+import org.jboss.envers.Versioned;
+
+import javax.persistence.*;
+
+/**
+ * @author Adam Warski (adam at warski dot org)
+ */
+ at Entity
+ at Inheritance(strategy = InheritanceType.SINGLE_TABLE)
+ at DiscriminatorColumn(name = "discriminator", discriminatorType = DiscriminatorType.INTEGER)
+ at DiscriminatorValue("1")
+ at Versioned
+public class ParentNotIngEntity {
+ @Id
+ @GeneratedValue
+ private Integer id;
+
+ @Basic
+ private String data;
+
+ public ParentNotIngEntity() {
+ }
+
+ public ParentNotIngEntity(String data) {
+ this.data = data;
+ }
+
+ public ParentNotIngEntity(Integer id, String data) {
+ this.id = id;
+ this.data = data;
+ }
+
+ public Integer getId() {
+ return id;
+ }
+
+ public void setId(Integer id) {
+ this.id = id;
+ }
+
+ public String getData() {
+ return data;
+ }
+
+ public void setData(String data) {
+ this.data = data;
+ }
+
+ public boolean equals(Object o) {
+ if (this == o) return true;
+ if (!(o instanceof ParentNotIngEntity)) return false;
+
+ ParentNotIngEntity that = (ParentNotIngEntity) o;
+
+ if (data != null ? !data.equals(that.data) : that.data != null) return false;
+ if (id != null ? !id.equals(that.id) : that.id != null) return false;
+
+ return true;
+ }
+
+ public int hashCode() {
+ int result;
+ result = (id != null ? id.hashCode() : 0);
+ result = 31 * result + (data != null ? data.hashCode() : 0);
+ return result;
+ }
+
+ public String toString() {
+ return "ParentNotIngEntity(id = " + getId() + ", data = " + getData() + ")";
+ }
+}
\ No newline at end of file
Added: core/trunk/envers/src/test/java/org/jboss/envers/test/integration/inheritance/single/childrelation/ReferencedEntity.java
===================================================================
--- core/trunk/envers/src/test/java/org/jboss/envers/test/integration/inheritance/single/childrelation/ReferencedEntity.java (rev 0)
+++ core/trunk/envers/src/test/java/org/jboss/envers/test/integration/inheritance/single/childrelation/ReferencedEntity.java 2008-10-27 18:56:31 UTC (rev 15406)
@@ -0,0 +1,61 @@
+package org.jboss.envers.test.integration.inheritance.single.childrelation;
+
+import org.jboss.envers.Versioned;
+
+import javax.persistence.Entity;
+import javax.persistence.OneToMany;
+import javax.persistence.Id;
+import javax.persistence.GeneratedValue;
+import java.util.Set;
+
+/**
+ * @author Adam Warski (adam at warski dot org)
+ */
+ at Entity
+ at Versioned
+public class ReferencedEntity {
+ @Id
+ @GeneratedValue
+ private Integer id;
+
+ @OneToMany(mappedBy = "referenced")
+ private Set<ChildIngEntity> referencing;
+
+ public ReferencedEntity(Integer id) {
+ this.id = id;
+ }
+
+ public ReferencedEntity() {
+ }
+
+ public Set<ChildIngEntity> getReferencing() {
+ return referencing;
+ }
+
+ public void setReferencing(Set<ChildIngEntity> referencing) {
+ this.referencing = referencing;
+ }
+
+ public Integer getId() {
+ return id;
+ }
+
+ public void setId(Integer id) {
+ this.id = id;
+ }
+
+ public boolean equals(Object o) {
+ if (this == o) return true;
+ if (!(o instanceof ReferencedEntity)) return false;
+
+ ReferencedEntity that = (ReferencedEntity) o;
+
+ if (id != null ? !id.equals(that.id) : that.id != null) return false;
+
+ return true;
+ }
+
+ public int hashCode() {
+ return id;
+ }
+}
\ No newline at end of file
Added: core/trunk/envers/src/test/java/org/jboss/envers/test/integration/inheritance/single/relation/ChildIngEntity.java
===================================================================
--- core/trunk/envers/src/test/java/org/jboss/envers/test/integration/inheritance/single/relation/ChildIngEntity.java (rev 0)
+++ core/trunk/envers/src/test/java/org/jboss/envers/test/integration/inheritance/single/relation/ChildIngEntity.java 2008-10-27 18:56:31 UTC (rev 15406)
@@ -0,0 +1,59 @@
+package org.jboss.envers.test.integration.inheritance.single.relation;
+
+import org.jboss.envers.Versioned;
+
+import javax.persistence.*;
+
+/**
+ * @author Adam Warski (adam at warski dot org)
+ */
+ at Entity
+ at DiscriminatorValue("2")
+ at Versioned
+public class ChildIngEntity extends ParentIngEntity {
+ @Basic
+ private Long number;
+
+ public ChildIngEntity() {
+ }
+
+ public ChildIngEntity(String data, Long number) {
+ super(data);
+ this.number = number;
+ }
+
+ public ChildIngEntity(Integer id, String data, Long number) {
+ super(id, data);
+ this.number = number;
+ }
+
+ public Long getNumber() {
+ return number;
+ }
+
+ public void setNumber(Long number) {
+ this.number = number;
+ }
+
+ public boolean equals(Object o) {
+ if (this == o) return true;
+ if (!(o instanceof ChildIngEntity)) return false;
+ if (!super.equals(o)) return false;
+
+ ChildIngEntity childEntity = (ChildIngEntity) o;
+
+ if (number != null ? !number.equals(childEntity.number) : childEntity.number != null) return false;
+
+ return true;
+ }
+
+ public int hashCode() {
+ int result = super.hashCode();
+ result = 31 * result + (number != null ? number.hashCode() : 0);
+ return result;
+ }
+
+ public String toString() {
+ return "ChildIngEntity(id = " + getId() + ", data = " + getData() + ", number = " + number + ")";
+ }
+}
\ No newline at end of file
Added: core/trunk/envers/src/test/java/org/jboss/envers/test/integration/inheritance/single/relation/ParentIngEntity.java
===================================================================
--- core/trunk/envers/src/test/java/org/jboss/envers/test/integration/inheritance/single/relation/ParentIngEntity.java (rev 0)
+++ core/trunk/envers/src/test/java/org/jboss/envers/test/integration/inheritance/single/relation/ParentIngEntity.java 2008-10-27 18:56:31 UTC (rev 15406)
@@ -0,0 +1,84 @@
+package org.jboss.envers.test.integration.inheritance.single.relation;
+
+import org.jboss.envers.Versioned;
+
+import javax.persistence.*;
+
+/**
+ * @author Adam Warski (adam at warski dot org)
+ */
+ at Entity
+ at Inheritance(strategy = InheritanceType.SINGLE_TABLE)
+ at DiscriminatorColumn(name = "discriminator", discriminatorType = DiscriminatorType.INTEGER)
+ at DiscriminatorValue("1")
+ at Versioned
+public class ParentIngEntity {
+ @Id
+ @GeneratedValue
+ private Integer id;
+
+ @Basic
+ private String data;
+
+ @ManyToOne
+ private ReferencedEntity referenced;
+
+ public ParentIngEntity() {
+ }
+
+ public ParentIngEntity(String data) {
+ this.data = data;
+ }
+
+ public ParentIngEntity(Integer id, String data) {
+ this.id = id;
+ this.data = data;
+ }
+
+ public Integer getId() {
+ return id;
+ }
+
+ public void setId(Integer id) {
+ this.id = id;
+ }
+
+ public String getData() {
+ return data;
+ }
+
+ public void setData(String data) {
+ this.data = data;
+ }
+
+ public ReferencedEntity getReferenced() {
+ return referenced;
+ }
+
+ public void setReferenced(ReferencedEntity referenced) {
+ this.referenced = referenced;
+ }
+
+ public boolean equals(Object o) {
+ if (this == o) return true;
+ if (!(o instanceof ParentIngEntity)) return false;
+
+ ParentIngEntity that = (ParentIngEntity) o;
+
+ if (data != null ? !data.equals(that.data) : that.data != null) return false;
+ if (id != null ? !id.equals(that.id) : that.id != null) return false;
+
+ return true;
+ }
+
+ public int hashCode() {
+ int result;
+ result = (id != null ? id.hashCode() : 0);
+ result = 31 * result + (data != null ? data.hashCode() : 0);
+ return result;
+ }
+
+ public String toString() {
+ return "ParentIngEntity(id = " + getId() + ", data = " + getData() + ")";
+ }
+}
\ No newline at end of file
Added: core/trunk/envers/src/test/java/org/jboss/envers/test/integration/inheritance/single/relation/PolymorphicCollection.java
===================================================================
--- core/trunk/envers/src/test/java/org/jboss/envers/test/integration/inheritance/single/relation/PolymorphicCollection.java (rev 0)
+++ core/trunk/envers/src/test/java/org/jboss/envers/test/integration/inheritance/single/relation/PolymorphicCollection.java 2008-10-27 18:56:31 UTC (rev 15406)
@@ -0,0 +1,79 @@
+package org.jboss.envers.test.integration.inheritance.single.relation;
+
+import org.hibernate.ejb.Ejb3Configuration;
+import org.testng.annotations.BeforeClass;
+import org.testng.annotations.Test;
+import org.jboss.envers.test.AbstractEntityTest;
+import org.jboss.envers.test.tools.TestTools;
+
+import javax.persistence.EntityManager;
+import java.util.Arrays;
+
+/**
+ * @author Adam Warski (adam at warski dot org)
+ */
+public class PolymorphicCollection extends AbstractEntityTest {
+ private Integer ed_id1;
+ private Integer c_id;
+ private Integer p_id;
+
+ public void configure(Ejb3Configuration cfg) {
+ cfg.addAnnotatedClass(ChildIngEntity.class);
+ cfg.addAnnotatedClass(ParentIngEntity.class);
+ cfg.addAnnotatedClass(ReferencedEntity.class);
+ }
+
+ @BeforeClass(dependsOnMethods = "init")
+ public void initData() {
+ EntityManager em = getEntityManager();
+
+ // Rev 1
+ em.getTransaction().begin();
+
+ ReferencedEntity re = new ReferencedEntity();
+ em.persist(re);
+ ed_id1 = re.getId();
+
+ em.getTransaction().commit();
+
+ // Rev 2
+ em.getTransaction().begin();
+
+ re = em.find(ReferencedEntity.class, ed_id1);
+
+ ParentIngEntity pie = new ParentIngEntity("x");
+ pie.setReferenced(re);
+ em.persist(pie);
+ p_id = pie.getId();
+
+ em.getTransaction().commit();
+
+ // Rev 3
+ em.getTransaction().begin();
+
+ re = em.find(ReferencedEntity.class, ed_id1);
+
+ ChildIngEntity cie = new ChildIngEntity("y", 1l);
+ cie.setReferenced(re);
+ em.persist(cie);
+ c_id = cie.getId();
+
+ em.getTransaction().commit();
+ }
+
+ @Test
+ public void testRevisionsCounts() {
+ assert Arrays.asList(1, 2, 3).equals(getVersionsReader().getRevisions(ReferencedEntity.class, ed_id1));
+ assert Arrays.asList(2).equals(getVersionsReader().getRevisions(ParentIngEntity.class, p_id));
+ assert Arrays.asList(3).equals(getVersionsReader().getRevisions(ChildIngEntity.class, c_id));
+ }
+
+ @Test
+ public void testHistoryOfReferencedCollection() {
+ assert getVersionsReader().find(ReferencedEntity.class, ed_id1, 1).getReferencing().size() == 0;
+ assert getVersionsReader().find(ReferencedEntity.class, ed_id1, 2).getReferencing().equals(
+ TestTools.makeSet(new ParentIngEntity(p_id, "x")));
+ assert getVersionsReader().find(ReferencedEntity.class, ed_id1, 3).getReferencing().equals(
+ TestTools.makeSet(new ParentIngEntity(p_id, "x"), new ChildIngEntity(c_id, "y", 1l)));
+ }
+}
\ No newline at end of file
Added: core/trunk/envers/src/test/java/org/jboss/envers/test/integration/inheritance/single/relation/ReferencedEntity.java
===================================================================
--- core/trunk/envers/src/test/java/org/jboss/envers/test/integration/inheritance/single/relation/ReferencedEntity.java (rev 0)
+++ core/trunk/envers/src/test/java/org/jboss/envers/test/integration/inheritance/single/relation/ReferencedEntity.java 2008-10-27 18:56:31 UTC (rev 15406)
@@ -0,0 +1,54 @@
+package org.jboss.envers.test.integration.inheritance.single.relation;
+
+import org.jboss.envers.Versioned;
+
+import javax.persistence.Entity;
+import javax.persistence.OneToMany;
+import javax.persistence.Id;
+import javax.persistence.GeneratedValue;
+import java.util.Set;
+
+/**
+ * @author Adam Warski (adam at warski dot org)
+ */
+ at Entity
+ at Versioned
+public class ReferencedEntity {
+ @Id
+ @GeneratedValue
+ private Integer id;
+
+ @OneToMany(mappedBy = "referenced")
+ private Set<ParentIngEntity> referencing;
+
+ public Set<ParentIngEntity> getReferencing() {
+ return referencing;
+ }
+
+ public void setReferencing(Set<ParentIngEntity> referencing) {
+ this.referencing = referencing;
+ }
+
+ public Integer getId() {
+ return id;
+ }
+
+ public void setId(Integer id) {
+ this.id = id;
+ }
+
+ public boolean equals(Object o) {
+ if (this == o) return true;
+ if (!(o instanceof ReferencedEntity)) return false;
+
+ ReferencedEntity that = (ReferencedEntity) o;
+
+ if (id != null ? !id.equals(that.id) : that.id != null) return false;
+
+ return true;
+ }
+
+ public int hashCode() {
+ return id;
+ }
+}
Added: core/trunk/envers/src/test/java/org/jboss/envers/test/integration/manytomany/BasicList.java
===================================================================
--- core/trunk/envers/src/test/java/org/jboss/envers/test/integration/manytomany/BasicList.java (rev 0)
+++ core/trunk/envers/src/test/java/org/jboss/envers/test/integration/manytomany/BasicList.java 2008-10-27 18:56:31 UTC (rev 15406)
@@ -0,0 +1,189 @@
+package org.jboss.envers.test.integration.manytomany;
+
+import org.jboss.envers.test.AbstractEntityTest;
+import org.jboss.envers.test.entities.manytomany.ListOwningEntity;
+import org.jboss.envers.test.entities.manytomany.ListOwnedEntity;
+import org.jboss.envers.test.tools.TestTools;
+import org.testng.annotations.BeforeClass;
+import org.testng.annotations.Test;
+import org.hibernate.ejb.Ejb3Configuration;
+
+import javax.persistence.EntityManager;
+import java.util.Arrays;
+import java.util.Collections;
+import java.util.ArrayList;
+
+/**
+ * @author Adam Warski (adam at warski dot org)
+ */
+public class BasicList extends AbstractEntityTest {
+ private Integer ed1_id;
+ private Integer ed2_id;
+
+ private Integer ing1_id;
+ private Integer ing2_id;
+
+ public void configure(Ejb3Configuration cfg) {
+ cfg.addAnnotatedClass(ListOwningEntity.class);
+ cfg.addAnnotatedClass(ListOwnedEntity.class);
+ }
+
+ @BeforeClass(dependsOnMethods = "init")
+ public void initData() {
+ EntityManager em = getEntityManager();
+
+ ListOwnedEntity ed1 = new ListOwnedEntity(1, "data_ed_1");
+ ListOwnedEntity ed2 = new ListOwnedEntity(2, "data_ed_2");
+
+ ListOwningEntity ing1 = new ListOwningEntity(3, "data_ing_1");
+ ListOwningEntity ing2 = new ListOwningEntity(4, "data_ing_2");
+
+ // Revision 1
+ em.getTransaction().begin();
+
+ em.persist(ed1);
+ em.persist(ed2);
+ em.persist(ing1);
+ em.persist(ing2);
+
+ em.getTransaction().commit();
+
+ // Revision 2
+
+ em.getTransaction().begin();
+
+ ing1 = em.find(ListOwningEntity.class, ing1.getId());
+ ing2 = em.find(ListOwningEntity.class, ing2.getId());
+ ed1 = em.find(ListOwnedEntity.class, ed1.getId());
+ ed2 = em.find(ListOwnedEntity.class, ed2.getId());
+
+ ing1.setReferences(new ArrayList<ListOwnedEntity>());
+ ing1.getReferences().add(ed1);
+
+ ing2.setReferences(new ArrayList<ListOwnedEntity>());
+ ing2.getReferences().add(ed1);
+ ing2.getReferences().add(ed2);
+
+ em.getTransaction().commit();
+
+ // Revision 3
+ em.getTransaction().begin();
+
+ ing1 = em.find(ListOwningEntity.class, ing1.getId());
+ ed2 = em.find(ListOwnedEntity.class, ed2.getId());
+ ed1 = em.find(ListOwnedEntity.class, ed1.getId());
+
+ ing1.getReferences().add(ed2);
+
+ em.getTransaction().commit();
+
+ // Revision 4
+ em.getTransaction().begin();
+
+ ing1 = em.find(ListOwningEntity.class, ing1.getId());
+ ed2 = em.find(ListOwnedEntity.class, ed2.getId());
+ ed1 = em.find(ListOwnedEntity.class, ed1.getId());
+
+ ing1.getReferences().remove(ed1);
+
+ em.getTransaction().commit();
+
+ // Revision 5
+ em.getTransaction().begin();
+
+ ing1 = em.find(ListOwningEntity.class, ing1.getId());
+
+ ing1.setReferences(null);
+
+ em.getTransaction().commit();
+
+ //
+
+ ed1_id = ed1.getId();
+ ed2_id = ed2.getId();
+
+ ing1_id = ing1.getId();
+ ing2_id = ing2.getId();
+ }
+
+ @Test
+ public void testRevisionsCounts() {
+ assert Arrays.asList(1, 2, 4).equals(getVersionsReader().getRevisions(ListOwnedEntity.class, ed1_id));
+ assert Arrays.asList(1, 2, 3, 5).equals(getVersionsReader().getRevisions(ListOwnedEntity.class, ed2_id));
+
+ assert Arrays.asList(1, 2, 3, 4, 5).equals(getVersionsReader().getRevisions(ListOwningEntity.class, ing1_id));
+ assert Arrays.asList(1, 2).equals(getVersionsReader().getRevisions(ListOwningEntity.class, ing2_id));
+ }
+
+ @Test
+ public void testHistoryOfEdId1() {
+ ListOwningEntity ing1 = getEntityManager().find(ListOwningEntity.class, ing1_id);
+ ListOwningEntity ing2 = getEntityManager().find(ListOwningEntity.class, ing2_id);
+
+ ListOwnedEntity rev1 = getVersionsReader().find(ListOwnedEntity.class, ed1_id, 1);
+ ListOwnedEntity rev2 = getVersionsReader().find(ListOwnedEntity.class, ed1_id, 2);
+ ListOwnedEntity rev3 = getVersionsReader().find(ListOwnedEntity.class, ed1_id, 3);
+ ListOwnedEntity rev4 = getVersionsReader().find(ListOwnedEntity.class, ed1_id, 4);
+ ListOwnedEntity rev5 = getVersionsReader().find(ListOwnedEntity.class, ed1_id, 5);
+
+ assert rev1.getReferencing().equals(Collections.EMPTY_LIST);
+ assert TestTools.checkList(rev2.getReferencing(), ing1, ing2);
+ assert TestTools.checkList(rev3.getReferencing(), ing1, ing2);
+ assert TestTools.checkList(rev4.getReferencing(), ing2);
+ assert TestTools.checkList(rev5.getReferencing(), ing2);
+ }
+
+ @Test
+ public void testHistoryOfEdId2() {
+ ListOwningEntity ing1 = getEntityManager().find(ListOwningEntity.class, ing1_id);
+ ListOwningEntity ing2 = getEntityManager().find(ListOwningEntity.class, ing2_id);
+
+ ListOwnedEntity rev1 = getVersionsReader().find(ListOwnedEntity.class, ed2_id, 1);
+ ListOwnedEntity rev2 = getVersionsReader().find(ListOwnedEntity.class, ed2_id, 2);
+ ListOwnedEntity rev3 = getVersionsReader().find(ListOwnedEntity.class, ed2_id, 3);
+ ListOwnedEntity rev4 = getVersionsReader().find(ListOwnedEntity.class, ed2_id, 4);
+ ListOwnedEntity rev5 = getVersionsReader().find(ListOwnedEntity.class, ed2_id, 5);
+
+ assert rev1.getReferencing().equals(Collections.EMPTY_LIST);
+ assert TestTools.checkList(rev2.getReferencing(), ing2);
+ assert TestTools.checkList(rev3.getReferencing(), ing1, ing2);
+ assert TestTools.checkList(rev4.getReferencing(), ing1, ing2);
+ assert TestTools.checkList(rev5.getReferencing(), ing2);
+ }
+
+ @Test
+ public void testHistoryOfEdIng1() {
+ ListOwnedEntity ed1 = getEntityManager().find(ListOwnedEntity.class, ed1_id);
+ ListOwnedEntity ed2 = getEntityManager().find(ListOwnedEntity.class, ed2_id);
+
+ ListOwningEntity rev1 = getVersionsReader().find(ListOwningEntity.class, ing1_id, 1);
+ ListOwningEntity rev2 = getVersionsReader().find(ListOwningEntity.class, ing1_id, 2);
+ ListOwningEntity rev3 = getVersionsReader().find(ListOwningEntity.class, ing1_id, 3);
+ ListOwningEntity rev4 = getVersionsReader().find(ListOwningEntity.class, ing1_id, 4);
+ ListOwningEntity rev5 = getVersionsReader().find(ListOwningEntity.class, ing1_id, 5);
+
+ assert rev1.getReferences().equals(Collections.EMPTY_LIST);
+ assert TestTools.checkList(rev2.getReferences(), ed1);
+ assert TestTools.checkList(rev3.getReferences(), ed1, ed2);
+ assert TestTools.checkList(rev4.getReferences(), ed2);
+ assert rev5.getReferences().equals(Collections.EMPTY_LIST);
+ }
+
+ @Test
+ public void testHistoryOfEdIng2() {
+ ListOwnedEntity ed1 = getEntityManager().find(ListOwnedEntity.class, ed1_id);
+ ListOwnedEntity ed2 = getEntityManager().find(ListOwnedEntity.class, ed2_id);
+
+ ListOwningEntity rev1 = getVersionsReader().find(ListOwningEntity.class, ing2_id, 1);
+ ListOwningEntity rev2 = getVersionsReader().find(ListOwningEntity.class, ing2_id, 2);
+ ListOwningEntity rev3 = getVersionsReader().find(ListOwningEntity.class, ing2_id, 3);
+ ListOwningEntity rev4 = getVersionsReader().find(ListOwningEntity.class, ing2_id, 4);
+ ListOwningEntity rev5 = getVersionsReader().find(ListOwningEntity.class, ing2_id, 5);
+
+ assert rev1.getReferences().equals(Collections.EMPTY_LIST);
+ assert TestTools.checkList(rev2.getReferences(), ed1, ed2);
+ assert TestTools.checkList(rev3.getReferences(), ed1, ed2);
+ assert TestTools.checkList(rev4.getReferences(), ed1, ed2);
+ assert TestTools.checkList(rev5.getReferences(), ed1, ed2);
+ }
+}
\ No newline at end of file
Added: core/trunk/envers/src/test/java/org/jboss/envers/test/integration/manytomany/BasicMap.java
===================================================================
--- core/trunk/envers/src/test/java/org/jboss/envers/test/integration/manytomany/BasicMap.java (rev 0)
+++ core/trunk/envers/src/test/java/org/jboss/envers/test/integration/manytomany/BasicMap.java 2008-10-27 18:56:31 UTC (rev 15406)
@@ -0,0 +1,163 @@
+package org.jboss.envers.test.integration.manytomany;
+
+import org.jboss.envers.test.AbstractEntityTest;
+import org.jboss.envers.test.entities.manytomany.MapOwningEntity;
+import org.jboss.envers.test.entities.manytomany.MapOwnedEntity;
+import org.jboss.envers.test.tools.TestTools;
+import org.testng.annotations.BeforeClass;
+import org.testng.annotations.Test;
+import org.hibernate.ejb.Ejb3Configuration;
+
+import javax.persistence.EntityManager;
+import java.util.Arrays;
+import java.util.Collections;
+import java.util.HashMap;
+
+/**
+ * @author Adam Warski (adam at warski dot org)
+ */
+public class BasicMap extends AbstractEntityTest {
+ private Integer ed1_id;
+ private Integer ed2_id;
+
+ private Integer ing1_id;
+ private Integer ing2_id;
+
+ public void configure(Ejb3Configuration cfg) {
+ cfg.addAnnotatedClass(MapOwningEntity.class);
+ cfg.addAnnotatedClass(MapOwnedEntity.class);
+ }
+
+ @BeforeClass(dependsOnMethods = "init")
+ public void initData() {
+ EntityManager em = getEntityManager();
+
+ MapOwnedEntity ed1 = new MapOwnedEntity(1, "data_ed_1");
+ MapOwnedEntity ed2 = new MapOwnedEntity(2, "data_ed_2");
+
+ MapOwningEntity ing1 = new MapOwningEntity(3, "data_ing_1");
+ MapOwningEntity ing2 = new MapOwningEntity(4, "data_ing_2");
+
+ // Revision 1 (ing1: initialy empty, ing2: one mapping)
+ em.getTransaction().begin();
+
+ ing2.getReferences().put("2", ed2);
+
+ em.persist(ed1);
+ em.persist(ed2);
+ em.persist(ing1);
+ em.persist(ing2);
+
+ em.getTransaction().commit();
+
+ // Revision 2 (ing1: adding two mappings, ing2: replacing an existing mapping)
+
+ em.getTransaction().begin();
+
+ ing1 = em.find(MapOwningEntity.class, ing1.getId());
+ ing2 = em.find(MapOwningEntity.class, ing2.getId());
+ ed1 = em.find(MapOwnedEntity.class, ed1.getId());
+ ed2 = em.find(MapOwnedEntity.class, ed2.getId());
+
+ ing1.getReferences().put("1", ed1);
+ ing1.getReferences().put("2", ed1);
+
+ ing2.getReferences().put("2", ed1);
+
+ em.getTransaction().commit();
+
+ // No revision (ing1: adding an existing mapping, ing2: removing a non existing mapping)
+ em.getTransaction().begin();
+
+ ing1 = em.find(MapOwningEntity.class, ing1.getId());
+ ing2 = em.find(MapOwningEntity.class, ing2.getId());
+
+ ing1.getReferences().put("1", ed1);
+
+ ing2.getReferences().remove("3");
+
+ em.getTransaction().commit();
+
+ // Revision 3 (ing1: clearing, ing2: replacing with a new map)
+ em.getTransaction().begin();
+
+ ing1 = em.find(MapOwningEntity.class, ing1.getId());
+ ed1 = em.find(MapOwnedEntity.class, ed1.getId());
+
+ ing1.getReferences().clear();
+ ing2.setReferences(new HashMap<String, MapOwnedEntity>());
+ ing2.getReferences().put("1", ed2);
+
+ em.getTransaction().commit();
+ //
+
+ ed1_id = ed1.getId();
+ ed2_id = ed2.getId();
+
+ ing1_id = ing1.getId();
+ ing2_id = ing2.getId();
+ }
+
+ @Test
+ public void testRevisionsCounts() {
+ assert Arrays.asList(1, 2, 3).equals(getVersionsReader().getRevisions(MapOwnedEntity.class, ed1_id));
+ assert Arrays.asList(1, 2, 3).equals(getVersionsReader().getRevisions(MapOwnedEntity.class, ed2_id));
+
+ assert Arrays.asList(1, 2, 3).equals(getVersionsReader().getRevisions(MapOwningEntity.class, ing1_id));
+ assert Arrays.asList(1, 2, 3).equals(getVersionsReader().getRevisions(MapOwningEntity.class, ing2_id));
+ }
+
+ @Test
+ public void testHistoryOfEdId1() {
+ MapOwningEntity ing1 = getEntityManager().find(MapOwningEntity.class, ing1_id);
+ MapOwningEntity ing2 = getEntityManager().find(MapOwningEntity.class, ing2_id);
+
+ MapOwnedEntity rev1 = getVersionsReader().find(MapOwnedEntity.class, ed1_id, 1);
+ MapOwnedEntity rev2 = getVersionsReader().find(MapOwnedEntity.class, ed1_id, 2);
+ MapOwnedEntity rev3 = getVersionsReader().find(MapOwnedEntity.class, ed1_id, 3);
+
+ assert rev1.getReferencing().equals(Collections.EMPTY_SET);
+ assert rev2.getReferencing().equals(TestTools.makeSet(ing1, ing2));
+ assert rev3.getReferencing().equals(Collections.EMPTY_SET);
+ }
+
+ @Test
+ public void testHistoryOfEdId2() {
+ MapOwningEntity ing2 = getEntityManager().find(MapOwningEntity.class, ing2_id);
+
+ MapOwnedEntity rev1 = getVersionsReader().find(MapOwnedEntity.class, ed2_id, 1);
+ MapOwnedEntity rev2 = getVersionsReader().find(MapOwnedEntity.class, ed2_id, 2);
+ MapOwnedEntity rev3 = getVersionsReader().find(MapOwnedEntity.class, ed2_id, 3);
+
+ assert rev1.getReferencing().equals(TestTools.makeSet(ing2));
+ assert rev2.getReferencing().equals(Collections.EMPTY_SET);
+ assert rev3.getReferencing().equals(TestTools.makeSet(ing2));
+ }
+
+ @Test
+ public void testHistoryOfEdIng1() {
+ MapOwnedEntity ed1 = getEntityManager().find(MapOwnedEntity.class, ed1_id);
+
+ MapOwningEntity rev1 = getVersionsReader().find(MapOwningEntity.class, ing1_id, 1);
+ MapOwningEntity rev2 = getVersionsReader().find(MapOwningEntity.class, ing1_id, 2);
+ MapOwningEntity rev3 = getVersionsReader().find(MapOwningEntity.class, ing1_id, 3);
+
+ assert rev1.getReferences().equals(Collections.EMPTY_MAP);
+ assert rev2.getReferences().equals(TestTools.makeMap("1", ed1, "2", ed1));
+ assert rev3.getReferences().equals(Collections.EMPTY_MAP);
+ }
+
+ @Test
+ public void testHistoryOfEdIng2() {
+ MapOwnedEntity ed1 = getEntityManager().find(MapOwnedEntity.class, ed1_id);
+ MapOwnedEntity ed2 = getEntityManager().find(MapOwnedEntity.class, ed2_id);
+
+ MapOwningEntity rev1 = getVersionsReader().find(MapOwningEntity.class, ing2_id, 1);
+ MapOwningEntity rev2 = getVersionsReader().find(MapOwningEntity.class, ing2_id, 2);
+ MapOwningEntity rev3 = getVersionsReader().find(MapOwningEntity.class, ing2_id, 3);
+
+ assert rev1.getReferences().equals(TestTools.makeMap("2", ed2));
+ assert rev2.getReferences().equals(TestTools.makeMap("2", ed1));
+ assert rev3.getReferences().equals(TestTools.makeMap("1", ed2));
+ }
+}
\ No newline at end of file
Added: core/trunk/envers/src/test/java/org/jboss/envers/test/integration/manytomany/BasicSet.java
===================================================================
--- core/trunk/envers/src/test/java/org/jboss/envers/test/integration/manytomany/BasicSet.java (rev 0)
+++ core/trunk/envers/src/test/java/org/jboss/envers/test/integration/manytomany/BasicSet.java 2008-10-27 18:56:31 UTC (rev 15406)
@@ -0,0 +1,189 @@
+package org.jboss.envers.test.integration.manytomany;
+
+import org.jboss.envers.test.AbstractEntityTest;
+import org.jboss.envers.test.entities.manytomany.SetOwningEntity;
+import org.jboss.envers.test.entities.manytomany.SetOwnedEntity;
+import org.jboss.envers.test.tools.TestTools;
+import org.testng.annotations.BeforeClass;
+import org.testng.annotations.Test;
+import org.hibernate.ejb.Ejb3Configuration;
+
+import javax.persistence.EntityManager;
+import java.util.Arrays;
+import java.util.Collections;
+import java.util.HashSet;
+
+/**
+ * @author Adam Warski (adam at warski dot org)
+ */
+public class BasicSet extends AbstractEntityTest {
+ private Integer ed1_id;
+ private Integer ed2_id;
+
+ private Integer ing1_id;
+ private Integer ing2_id;
+
+ public void configure(Ejb3Configuration cfg) {
+ cfg.addAnnotatedClass(SetOwningEntity.class);
+ cfg.addAnnotatedClass(SetOwnedEntity.class);
+ }
+
+ @BeforeClass(dependsOnMethods = "init")
+ public void initData() {
+ EntityManager em = getEntityManager();
+
+ SetOwnedEntity ed1 = new SetOwnedEntity(1, "data_ed_1");
+ SetOwnedEntity ed2 = new SetOwnedEntity(2, "data_ed_2");
+
+ SetOwningEntity ing1 = new SetOwningEntity(3, "data_ing_1");
+ SetOwningEntity ing2 = new SetOwningEntity(4, "data_ing_2");
+
+ // Revision 1
+ em.getTransaction().begin();
+
+ em.persist(ed1);
+ em.persist(ed2);
+ em.persist(ing1);
+ em.persist(ing2);
+
+ em.getTransaction().commit();
+
+ // Revision 2
+
+ em.getTransaction().begin();
+
+ ing1 = em.find(SetOwningEntity.class, ing1.getId());
+ ing2 = em.find(SetOwningEntity.class, ing2.getId());
+ ed1 = em.find(SetOwnedEntity.class, ed1.getId());
+ ed2 = em.find(SetOwnedEntity.class, ed2.getId());
+
+ ing1.setReferences(new HashSet<SetOwnedEntity>());
+ ing1.getReferences().add(ed1);
+
+ ing2.setReferences(new HashSet<SetOwnedEntity>());
+ ing2.getReferences().add(ed1);
+ ing2.getReferences().add(ed2);
+
+ em.getTransaction().commit();
+
+ // Revision 3
+ em.getTransaction().begin();
+
+ ing1 = em.find(SetOwningEntity.class, ing1.getId());
+ ed2 = em.find(SetOwnedEntity.class, ed2.getId());
+ ed1 = em.find(SetOwnedEntity.class, ed1.getId());
+
+ ing1.getReferences().add(ed2);
+
+ em.getTransaction().commit();
+
+ // Revision 4
+ em.getTransaction().begin();
+
+ ing1 = em.find(SetOwningEntity.class, ing1.getId());
+ ed2 = em.find(SetOwnedEntity.class, ed2.getId());
+ ed1 = em.find(SetOwnedEntity.class, ed1.getId());
+
+ ing1.getReferences().remove(ed1);
+
+ em.getTransaction().commit();
+
+ // Revision 5
+ em.getTransaction().begin();
+
+ ing1 = em.find(SetOwningEntity.class, ing1.getId());
+
+ ing1.setReferences(null);
+
+ em.getTransaction().commit();
+
+ //
+
+ ed1_id = ed1.getId();
+ ed2_id = ed2.getId();
+
+ ing1_id = ing1.getId();
+ ing2_id = ing2.getId();
+ }
+
+ @Test
+ public void testRevisionsCounts() {
+ assert Arrays.asList(1, 2, 4).equals(getVersionsReader().getRevisions(SetOwnedEntity.class, ed1_id));
+ assert Arrays.asList(1, 2, 3, 5).equals(getVersionsReader().getRevisions(SetOwnedEntity.class, ed2_id));
+
+ assert Arrays.asList(1, 2, 3, 4, 5).equals(getVersionsReader().getRevisions(SetOwningEntity.class, ing1_id));
+ assert Arrays.asList(1, 2).equals(getVersionsReader().getRevisions(SetOwningEntity.class, ing2_id));
+ }
+
+ @Test
+ public void testHistoryOfEdId1() {
+ SetOwningEntity ing1 = getEntityManager().find(SetOwningEntity.class, ing1_id);
+ SetOwningEntity ing2 = getEntityManager().find(SetOwningEntity.class, ing2_id);
+
+ SetOwnedEntity rev1 = getVersionsReader().find(SetOwnedEntity.class, ed1_id, 1);
+ SetOwnedEntity rev2 = getVersionsReader().find(SetOwnedEntity.class, ed1_id, 2);
+ SetOwnedEntity rev3 = getVersionsReader().find(SetOwnedEntity.class, ed1_id, 3);
+ SetOwnedEntity rev4 = getVersionsReader().find(SetOwnedEntity.class, ed1_id, 4);
+ SetOwnedEntity rev5 = getVersionsReader().find(SetOwnedEntity.class, ed1_id, 5);
+
+ assert rev1.getReferencing().equals(Collections.EMPTY_SET);
+ assert rev2.getReferencing().equals(TestTools.makeSet(ing1, ing2));
+ assert rev3.getReferencing().equals(TestTools.makeSet(ing1, ing2));
+ assert rev4.getReferencing().equals(TestTools.makeSet(ing2));
+ assert rev5.getReferencing().equals(TestTools.makeSet(ing2));
+ }
+
+ @Test
+ public void testHistoryOfEdId2() {
+ SetOwningEntity ing1 = getEntityManager().find(SetOwningEntity.class, ing1_id);
+ SetOwningEntity ing2 = getEntityManager().find(SetOwningEntity.class, ing2_id);
+
+ SetOwnedEntity rev1 = getVersionsReader().find(SetOwnedEntity.class, ed2_id, 1);
+ SetOwnedEntity rev2 = getVersionsReader().find(SetOwnedEntity.class, ed2_id, 2);
+ SetOwnedEntity rev3 = getVersionsReader().find(SetOwnedEntity.class, ed2_id, 3);
+ SetOwnedEntity rev4 = getVersionsReader().find(SetOwnedEntity.class, ed2_id, 4);
+ SetOwnedEntity rev5 = getVersionsReader().find(SetOwnedEntity.class, ed2_id, 5);
+
+ assert rev1.getReferencing().equals(Collections.EMPTY_SET);
+ assert rev2.getReferencing().equals(TestTools.makeSet(ing2));
+ assert rev3.getReferencing().equals(TestTools.makeSet(ing1, ing2));
+ assert rev4.getReferencing().equals(TestTools.makeSet(ing1, ing2));
+ assert rev5.getReferencing().equals(TestTools.makeSet(ing2));
+ }
+
+ @Test
+ public void testHistoryOfEdIng1() {
+ SetOwnedEntity ed1 = getEntityManager().find(SetOwnedEntity.class, ed1_id);
+ SetOwnedEntity ed2 = getEntityManager().find(SetOwnedEntity.class, ed2_id);
+
+ SetOwningEntity rev1 = getVersionsReader().find(SetOwningEntity.class, ing1_id, 1);
+ SetOwningEntity rev2 = getVersionsReader().find(SetOwningEntity.class, ing1_id, 2);
+ SetOwningEntity rev3 = getVersionsReader().find(SetOwningEntity.class, ing1_id, 3);
+ SetOwningEntity rev4 = getVersionsReader().find(SetOwningEntity.class, ing1_id, 4);
+ SetOwningEntity rev5 = getVersionsReader().find(SetOwningEntity.class, ing1_id, 5);
+
+ assert rev1.getReferences().equals(Collections.EMPTY_SET);
+ assert rev2.getReferences().equals(TestTools.makeSet(ed1));
+ assert rev3.getReferences().equals(TestTools.makeSet(ed1, ed2));
+ assert rev4.getReferences().equals(TestTools.makeSet(ed2));
+ assert rev5.getReferences().equals(Collections.EMPTY_SET);
+ }
+
+ @Test
+ public void testHistoryOfEdIng2() {
+ SetOwnedEntity ed1 = getEntityManager().find(SetOwnedEntity.class, ed1_id);
+ SetOwnedEntity ed2 = getEntityManager().find(SetOwnedEntity.class, ed2_id);
+
+ SetOwningEntity rev1 = getVersionsReader().find(SetOwningEntity.class, ing2_id, 1);
+ SetOwningEntity rev2 = getVersionsReader().find(SetOwningEntity.class, ing2_id, 2);
+ SetOwningEntity rev3 = getVersionsReader().find(SetOwningEntity.class, ing2_id, 3);
+ SetOwningEntity rev4 = getVersionsReader().find(SetOwningEntity.class, ing2_id, 4);
+ SetOwningEntity rev5 = getVersionsReader().find(SetOwningEntity.class, ing2_id, 5);
+
+ assert rev1.getReferences().equals(Collections.EMPTY_SET);
+ assert rev2.getReferences().equals(TestTools.makeSet(ed1, ed2));
+ assert rev3.getReferences().equals(TestTools.makeSet(ed1, ed2));
+ assert rev4.getReferences().equals(TestTools.makeSet(ed1, ed2));
+ assert rev5.getReferences().equals(TestTools.makeSet(ed1, ed2));
+ }
+}
\ No newline at end of file
Added: core/trunk/envers/src/test/java/org/jboss/envers/test/integration/manytomany/ternary/TernaryMap.java
===================================================================
--- core/trunk/envers/src/test/java/org/jboss/envers/test/integration/manytomany/ternary/TernaryMap.java (rev 0)
+++ core/trunk/envers/src/test/java/org/jboss/envers/test/integration/manytomany/ternary/TernaryMap.java 2008-10-27 18:56:31 UTC (rev 15406)
@@ -0,0 +1,176 @@
+package org.jboss.envers.test.integration.manytomany.ternary;
+
+import org.jboss.envers.test.AbstractEntityTest;
+import org.jboss.envers.test.entities.StrTestEntity;
+import org.jboss.envers.test.entities.IntTestEntity;
+import org.jboss.envers.test.tools.TestTools;
+import org.testng.annotations.BeforeClass;
+import org.testng.annotations.Test;
+import org.hibernate.ejb.Ejb3Configuration;
+
+import javax.persistence.EntityManager;
+import java.util.Arrays;
+
+/**
+ * @author Adam Warski (adam at warski dot org)
+ */
+public class TernaryMap extends AbstractEntityTest {
+ private Integer str1_id;
+ private Integer str2_id;
+
+ private Integer int1_id;
+ private Integer int2_id;
+
+ private Integer map1_id;
+ private Integer map2_id;
+
+ public void configure(Ejb3Configuration cfg) {
+ cfg.addAnnotatedClass(TernaryMapEntity.class);
+ cfg.addAnnotatedClass(StrTestEntity.class);
+ cfg.addAnnotatedClass(IntTestEntity.class);
+ }
+
+ @BeforeClass(dependsOnMethods = "init")
+ public void initData() {
+ EntityManager em = getEntityManager();
+
+ StrTestEntity str1 = new StrTestEntity("a");
+ StrTestEntity str2 = new StrTestEntity("b");
+
+ IntTestEntity int1 = new IntTestEntity(1);
+ IntTestEntity int2 = new IntTestEntity(2);
+
+ TernaryMapEntity map1 = new TernaryMapEntity();
+ TernaryMapEntity map2 = new TernaryMapEntity();
+
+ // Revision 1 (map1: initialy one mapping int1 -> str1, map2: empty)
+ em.getTransaction().begin();
+
+ em.persist(str1);
+ em.persist(str2);
+ em.persist(int1);
+ em.persist(int2);
+
+ map1.getMap().put(int1, str1);
+
+ em.persist(map1);
+ em.persist(map2);
+
+ em.getTransaction().commit();
+
+ // Revision 2 (map1: replacing the mapping, map2: adding two mappings)
+
+ em.getTransaction().begin();
+
+ map1 = em.find(TernaryMapEntity.class, map1.getId());
+ map2 = em.find(TernaryMapEntity.class, map2.getId());
+
+ str1 = em.find(StrTestEntity.class, str1.getId());
+ str2 = em.find(StrTestEntity.class, str2.getId());
+
+ int1 = em.find(IntTestEntity.class, int1.getId());
+ int2 = em.find(IntTestEntity.class, int2.getId());
+
+ map1.getMap().put(int1, str2);
+
+ map2.getMap().put(int1, str1);
+ map2.getMap().put(int2, str1);
+
+ em.getTransaction().commit();
+
+ // Revision 3 (map1: removing a non-existing mapping, adding an existing mapping - no changes, map2: removing a mapping)
+ em.getTransaction().begin();
+
+ map1 = em.find(TernaryMapEntity.class, map1.getId());
+ map2 = em.find(TernaryMapEntity.class, map2.getId());
+
+ str2 = em.find(StrTestEntity.class, str2.getId());
+
+ int1 = em.find(IntTestEntity.class, int1.getId());
+ int2 = em.find(IntTestEntity.class, int2.getId());
+
+ map1.getMap().remove(int2);
+ map1.getMap().put(int1, str2);
+
+ map2.getMap().remove(int1);
+
+ em.getTransaction().commit();
+
+ // Revision 4 (map1: adding a mapping, map2: adding a mapping)
+ em.getTransaction().begin();
+
+ map1 = em.find(TernaryMapEntity.class, map1.getId());
+ map2 = em.find(TernaryMapEntity.class, map2.getId());
+
+ str2 = em.find(StrTestEntity.class, str2.getId());
+
+ int1 = em.find(IntTestEntity.class, int1.getId());
+ int2 = em.find(IntTestEntity.class, int2.getId());
+
+ map1.getMap().put(int2, str2);
+
+ map2.getMap().put(int1, str2);
+
+ em.getTransaction().commit();
+ //
+
+ map1_id = map1.getId();
+ map2_id = map2.getId();
+
+ str1_id = str1.getId();
+ str2_id = str2.getId();
+
+ int1_id = int1.getId();
+ int2_id = int2.getId();
+ }
+
+ @Test
+ public void testRevisionsCounts() {
+ assert Arrays.asList(1, 2, 4).equals(getVersionsReader().getRevisions(TernaryMapEntity.class, map1_id));
+ assert Arrays.asList(1, 2, 3, 4).equals(getVersionsReader().getRevisions(TernaryMapEntity.class, map2_id));
+
+ assert Arrays.asList(1).equals(getVersionsReader().getRevisions(StrTestEntity.class, str1_id));
+ assert Arrays.asList(1).equals(getVersionsReader().getRevisions(StrTestEntity.class, str2_id));
+
+ assert Arrays.asList(1).equals(getVersionsReader().getRevisions(IntTestEntity.class, int1_id));
+ assert Arrays.asList(1).equals(getVersionsReader().getRevisions(IntTestEntity.class, int2_id));
+ }
+
+ @Test
+ public void testHistoryOfMap1() {
+ StrTestEntity str1 = getEntityManager().find(StrTestEntity.class, str1_id);
+ StrTestEntity str2 = getEntityManager().find(StrTestEntity.class, str2_id);
+
+ IntTestEntity int1 = getEntityManager().find(IntTestEntity.class, int1_id);
+ IntTestEntity int2 = getEntityManager().find(IntTestEntity.class, int2_id);
+
+ TernaryMapEntity rev1 = getVersionsReader().find(TernaryMapEntity.class, map1_id, 1);
+ TernaryMapEntity rev2 = getVersionsReader().find(TernaryMapEntity.class, map1_id, 2);
+ TernaryMapEntity rev3 = getVersionsReader().find(TernaryMapEntity.class, map1_id, 3);
+ TernaryMapEntity rev4 = getVersionsReader().find(TernaryMapEntity.class, map1_id, 4);
+
+ assert rev1.getMap().equals(TestTools.makeMap(int1, str1));
+ assert rev2.getMap().equals(TestTools.makeMap(int1, str2));
+ assert rev3.getMap().equals(TestTools.makeMap(int1, str2));
+ assert rev4.getMap().equals(TestTools.makeMap(int1, str2, int2, str2));
+ }
+
+ @Test
+ public void testHistoryOfMap2() {
+ StrTestEntity str1 = getEntityManager().find(StrTestEntity.class, str1_id);
+ StrTestEntity str2 = getEntityManager().find(StrTestEntity.class, str2_id);
+
+ IntTestEntity int1 = getEntityManager().find(IntTestEntity.class, int1_id);
+ IntTestEntity int2 = getEntityManager().find(IntTestEntity.class, int2_id);
+
+ TernaryMapEntity rev1 = getVersionsReader().find(TernaryMapEntity.class, map2_id, 1);
+ TernaryMapEntity rev2 = getVersionsReader().find(TernaryMapEntity.class, map2_id, 2);
+ TernaryMapEntity rev3 = getVersionsReader().find(TernaryMapEntity.class, map2_id, 3);
+ TernaryMapEntity rev4 = getVersionsReader().find(TernaryMapEntity.class, map2_id, 4);
+
+ assert rev1.getMap().equals(TestTools.makeMap());
+ assert rev2.getMap().equals(TestTools.makeMap(int1, str1, int2, str1));
+ assert rev3.getMap().equals(TestTools.makeMap(int2, str1));
+ assert rev4.getMap().equals(TestTools.makeMap(int1, str2, int2, str1));
+ }
+}
\ No newline at end of file
Added: core/trunk/envers/src/test/java/org/jboss/envers/test/integration/manytomany/ternary/TernaryMapEntity.java
===================================================================
--- core/trunk/envers/src/test/java/org/jboss/envers/test/integration/manytomany/ternary/TernaryMapEntity.java (rev 0)
+++ core/trunk/envers/src/test/java/org/jboss/envers/test/integration/manytomany/ternary/TernaryMapEntity.java 2008-10-27 18:56:31 UTC (rev 15406)
@@ -0,0 +1,67 @@
+package org.jboss.envers.test.integration.manytomany.ternary;
+
+import org.jboss.envers.Versioned;
+import org.jboss.envers.test.entities.IntTestEntity;
+import org.jboss.envers.test.entities.StrTestEntity;
+import org.hibernate.annotations.MapKeyManyToMany;
+
+import javax.persistence.Entity;
+import javax.persistence.Id;
+import javax.persistence.GeneratedValue;
+import javax.persistence.ManyToMany;
+import java.util.Map;
+import java.util.HashMap;
+
+/**
+ * @author Adam Warski (adam at warski dot org)
+ */
+ at Entity
+public class TernaryMapEntity {
+ @Id
+ @GeneratedValue
+ private Integer id;
+
+ @Versioned
+ @ManyToMany
+ @MapKeyManyToMany
+ private Map<IntTestEntity, StrTestEntity> map;
+
+ public TernaryMapEntity() {
+ map = new HashMap<IntTestEntity, StrTestEntity>();
+ }
+
+ public Integer getId() {
+ return id;
+ }
+
+ public void setId(Integer id) {
+ this.id = id;
+ }
+
+ public Map<IntTestEntity, StrTestEntity> getMap() {
+ return map;
+ }
+
+ public void setMap(Map<IntTestEntity, StrTestEntity> map) {
+ this.map = map;
+ }
+
+ public boolean equals(Object o) {
+ if (this == o) return true;
+ if (!(o instanceof TernaryMapEntity)) return false;
+
+ TernaryMapEntity that = (TernaryMapEntity) o;
+
+ if (id != null ? !id.equals(that.id) : that.id != null) return false;
+
+ return true;
+ }
+
+ public int hashCode() {
+ return (id != null ? id.hashCode() : 0);
+ }
+
+ public String toString() {
+ return "TME(id = " + id + ", map = " + map + ")";
+ }
+}
\ No newline at end of file
Added: core/trunk/envers/src/test/java/org/jboss/envers/test/integration/manytomany/unidirectional/BasicUniList.java
===================================================================
--- core/trunk/envers/src/test/java/org/jboss/envers/test/integration/manytomany/unidirectional/BasicUniList.java (rev 0)
+++ core/trunk/envers/src/test/java/org/jboss/envers/test/integration/manytomany/unidirectional/BasicUniList.java 2008-10-27 18:56:31 UTC (rev 15406)
@@ -0,0 +1,153 @@
+package org.jboss.envers.test.integration.manytomany.unidirectional;
+
+import org.jboss.envers.test.AbstractEntityTest;
+import org.jboss.envers.test.entities.manytomany.unidirectional.ListUniEntity;
+import org.jboss.envers.test.entities.StrTestEntity;
+import org.jboss.envers.test.tools.TestTools;
+import org.testng.annotations.BeforeClass;
+import org.testng.annotations.Test;
+import org.hibernate.ejb.Ejb3Configuration;
+
+import javax.persistence.EntityManager;
+import java.util.Arrays;
+import java.util.Collections;
+import java.util.ArrayList;
+
+/**
+ * @author Adam Warski (adam at warski dot org)
+ */
+public class BasicUniList extends AbstractEntityTest {
+ private Integer ed1_id;
+ private Integer ed2_id;
+
+ private Integer ing1_id;
+ private Integer ing2_id;
+
+ public void configure(Ejb3Configuration cfg) {
+ cfg.addAnnotatedClass(ListUniEntity.class);
+ cfg.addAnnotatedClass(StrTestEntity.class);
+ }
+
+ @BeforeClass(dependsOnMethods = "init")
+ public void initData() {
+ EntityManager em = getEntityManager();
+
+ StrTestEntity ed1 = new StrTestEntity("data_ed_1");
+ StrTestEntity ed2 = new StrTestEntity("data_ed_2");
+
+ ListUniEntity ing1 = new ListUniEntity(3, "data_ing_1");
+ ListUniEntity ing2 = new ListUniEntity(4, "data_ing_2");
+
+ // Revision 1
+ em.getTransaction().begin();
+
+ em.persist(ed1);
+ em.persist(ed2);
+ em.persist(ing1);
+ em.persist(ing2);
+
+ em.getTransaction().commit();
+
+ // Revision 2
+
+ em.getTransaction().begin();
+
+ ing1 = em.find(ListUniEntity.class, ing1.getId());
+ ing2 = em.find(ListUniEntity.class, ing2.getId());
+ ed1 = em.find(StrTestEntity.class, ed1.getId());
+ ed2 = em.find(StrTestEntity.class, ed2.getId());
+
+ ing1.setReferences(new ArrayList<StrTestEntity>());
+ ing1.getReferences().add(ed1);
+
+ ing2.setReferences(new ArrayList<StrTestEntity>());
+ ing2.getReferences().add(ed1);
+ ing2.getReferences().add(ed2);
+
+ em.getTransaction().commit();
+
+ // Revision 3
+ em.getTransaction().begin();
+
+ ing1 = em.find(ListUniEntity.class, ing1.getId());
+ ed2 = em.find(StrTestEntity.class, ed2.getId());
+ ed1 = em.find(StrTestEntity.class, ed1.getId());
+
+ ing1.getReferences().add(ed2);
+
+ em.getTransaction().commit();
+
+ // Revision 4
+ em.getTransaction().begin();
+
+ ing1 = em.find(ListUniEntity.class, ing1.getId());
+ ed2 = em.find(StrTestEntity.class, ed2.getId());
+ ed1 = em.find(StrTestEntity.class, ed1.getId());
+
+ ing1.getReferences().remove(ed1);
+
+ em.getTransaction().commit();
+
+ // Revision 5
+ em.getTransaction().begin();
+
+ ing1 = em.find(ListUniEntity.class, ing1.getId());
+
+ ing1.setReferences(null);
+
+ em.getTransaction().commit();
+
+ //
+
+ ed1_id = ed1.getId();
+ ed2_id = ed2.getId();
+
+ ing1_id = ing1.getId();
+ ing2_id = ing2.getId();
+ }
+
+ @Test
+ public void testRevisionsCounts() {
+ assert Arrays.asList(1).equals(getVersionsReader().getRevisions(StrTestEntity.class, ed1_id));
+ assert Arrays.asList(1).equals(getVersionsReader().getRevisions(StrTestEntity.class, ed2_id));
+
+ assert Arrays.asList(1, 2, 3, 4, 5).equals(getVersionsReader().getRevisions(ListUniEntity.class, ing1_id));
+ assert Arrays.asList(1, 2).equals(getVersionsReader().getRevisions(ListUniEntity.class, ing2_id));
+ }
+
+ @Test
+ public void testHistoryOfEdIng1() {
+ StrTestEntity ed1 = getEntityManager().find(StrTestEntity.class, ed1_id);
+ StrTestEntity ed2 = getEntityManager().find(StrTestEntity.class, ed2_id);
+
+ ListUniEntity rev1 = getVersionsReader().find(ListUniEntity.class, ing1_id, 1);
+ ListUniEntity rev2 = getVersionsReader().find(ListUniEntity.class, ing1_id, 2);
+ ListUniEntity rev3 = getVersionsReader().find(ListUniEntity.class, ing1_id, 3);
+ ListUniEntity rev4 = getVersionsReader().find(ListUniEntity.class, ing1_id, 4);
+ ListUniEntity rev5 = getVersionsReader().find(ListUniEntity.class, ing1_id, 5);
+
+ assert rev1.getReferences().equals(Collections.EMPTY_LIST);
+ assert TestTools.checkList(rev2.getReferences(), ed1);
+ assert TestTools.checkList(rev3.getReferences(), ed1, ed2);
+ assert TestTools.checkList(rev4.getReferences(), ed2);
+ assert rev5.getReferences().equals(Collections.EMPTY_LIST);
+ }
+
+ @Test
+ public void testHistoryOfEdIng2() {
+ StrTestEntity ed1 = getEntityManager().find(StrTestEntity.class, ed1_id);
+ StrTestEntity ed2 = getEntityManager().find(StrTestEntity.class, ed2_id);
+
+ ListUniEntity rev1 = getVersionsReader().find(ListUniEntity.class, ing2_id, 1);
+ ListUniEntity rev2 = getVersionsReader().find(ListUniEntity.class, ing2_id, 2);
+ ListUniEntity rev3 = getVersionsReader().find(ListUniEntity.class, ing2_id, 3);
+ ListUniEntity rev4 = getVersionsReader().find(ListUniEntity.class, ing2_id, 4);
+ ListUniEntity rev5 = getVersionsReader().find(ListUniEntity.class, ing2_id, 5);
+
+ assert rev1.getReferences().equals(Collections.EMPTY_LIST);
+ assert TestTools.checkList(rev2.getReferences(), ed1, ed2);
+ assert TestTools.checkList(rev3.getReferences(), ed1, ed2);
+ assert TestTools.checkList(rev4.getReferences(), ed1, ed2);
+ assert TestTools.checkList(rev5.getReferences(), ed1, ed2);
+ }
+}
\ No newline at end of file
Added: core/trunk/envers/src/test/java/org/jboss/envers/test/integration/manytomany/unidirectional/BasicUniMap.java
===================================================================
--- core/trunk/envers/src/test/java/org/jboss/envers/test/integration/manytomany/unidirectional/BasicUniMap.java (rev 0)
+++ core/trunk/envers/src/test/java/org/jboss/envers/test/integration/manytomany/unidirectional/BasicUniMap.java 2008-10-27 18:56:31 UTC (rev 15406)
@@ -0,0 +1,115 @@
+package org.jboss.envers.test.integration.manytomany.unidirectional;
+
+import org.jboss.envers.test.AbstractEntityTest;
+import org.jboss.envers.test.entities.manytomany.unidirectional.MapUniEntity;
+import org.jboss.envers.test.entities.StrTestEntity;
+import org.jboss.envers.test.tools.TestTools;
+import org.hibernate.ejb.Ejb3Configuration;
+import org.testng.annotations.BeforeClass;
+import org.testng.annotations.Test;
+
+import javax.persistence.EntityManager;
+import java.util.Arrays;
+import java.util.HashMap;
+
+/**
+ * @author Adam Warski (adam at warski dot org)
+ */
+public class BasicUniMap extends AbstractEntityTest {
+ private Integer str1_id;
+ private Integer str2_id;
+
+ private Integer coll1_id;
+
+ public void configure(Ejb3Configuration cfg) {
+ cfg.addAnnotatedClass(StrTestEntity.class);
+ cfg.addAnnotatedClass(MapUniEntity.class);
+ }
+
+ @BeforeClass(dependsOnMethods = "init")
+ public void initData() {
+ EntityManager em = getEntityManager();
+
+ StrTestEntity str1 = new StrTestEntity("str1");
+ StrTestEntity str2 = new StrTestEntity("str2");
+
+ MapUniEntity coll1 = new MapUniEntity(3, "coll1");
+
+ // Revision 1 (coll1: initialy one mapping)
+ em.getTransaction().begin();
+
+ em.persist(str1);
+ em.persist(str2);
+
+ coll1.setMap(new HashMap<String, StrTestEntity>());
+ coll1.getMap().put("1", str1);
+ em.persist(coll1);
+
+ em.getTransaction().commit();
+
+ // Revision 2 (coll1: adding one mapping)
+ em.getTransaction().begin();
+
+ str2 = em.find(StrTestEntity.class, str2.getId());
+ coll1 = em.find(MapUniEntity.class, coll1.getId());
+
+ coll1.getMap().put("2", str2);
+
+ em.getTransaction().commit();
+
+ // Revision 3 (coll1: replacing one mapping)
+ em.getTransaction().begin();
+
+ str1 = em.find(StrTestEntity.class, str1.getId());
+ coll1 = em.find(MapUniEntity.class, coll1.getId());
+
+ coll1.getMap().put("2", str1);
+
+ em.getTransaction().commit();
+
+ // Revision 4 (coll1: removing one mapping)
+ em.getTransaction().begin();
+
+ coll1 = em.find(MapUniEntity.class, coll1.getId());
+
+ coll1.getMap().remove("1");
+
+ em.getTransaction().commit();
+
+ //
+
+ str1_id = str1.getId();
+ str2_id = str2.getId();
+
+ coll1_id = coll1.getId();
+ }
+
+ @Test
+ public void testRevisionsCounts() {
+ assert Arrays.asList(1, 2, 3, 4).equals(getVersionsReader().getRevisions(MapUniEntity.class, coll1_id));
+
+ assert Arrays.asList(1).equals(getVersionsReader().getRevisions(StrTestEntity.class, str1_id));
+ assert Arrays.asList(1).equals(getVersionsReader().getRevisions(StrTestEntity.class, str2_id));
+ }
+
+ @Test
+ public void testHistoryOfColl1() {
+ StrTestEntity str1 = getEntityManager().find(StrTestEntity.class, str1_id);
+ StrTestEntity str2 = getEntityManager().find(StrTestEntity.class, str2_id);
+
+ MapUniEntity rev1 = getVersionsReader().find(MapUniEntity.class, coll1_id, 1);
+ MapUniEntity rev2 = getVersionsReader().find(MapUniEntity.class, coll1_id, 2);
+ MapUniEntity rev3 = getVersionsReader().find(MapUniEntity.class, coll1_id, 3);
+ MapUniEntity rev4 = getVersionsReader().find(MapUniEntity.class, coll1_id, 4);
+
+ assert rev1.getMap().equals(TestTools.makeMap("1", str1));
+ assert rev2.getMap().equals(TestTools.makeMap("1", str1, "2", str2));
+ assert rev3.getMap().equals(TestTools.makeMap("1", str1, "2", str1));
+ assert rev4.getMap().equals(TestTools.makeMap("2", str1));
+
+ assert "coll1".equals(rev1.getData());
+ assert "coll1".equals(rev2.getData());
+ assert "coll1".equals(rev3.getData());
+ assert "coll1".equals(rev4.getData());
+ }
+}
\ No newline at end of file
Added: core/trunk/envers/src/test/java/org/jboss/envers/test/integration/manytomany/unidirectional/BasicUniSet.java
===================================================================
--- core/trunk/envers/src/test/java/org/jboss/envers/test/integration/manytomany/unidirectional/BasicUniSet.java (rev 0)
+++ core/trunk/envers/src/test/java/org/jboss/envers/test/integration/manytomany/unidirectional/BasicUniSet.java 2008-10-27 18:56:31 UTC (rev 15406)
@@ -0,0 +1,153 @@
+package org.jboss.envers.test.integration.manytomany.unidirectional;
+
+import org.jboss.envers.test.AbstractEntityTest;
+import org.jboss.envers.test.entities.manytomany.unidirectional.SetUniEntity;
+import org.jboss.envers.test.entities.StrTestEntity;
+import org.jboss.envers.test.tools.TestTools;
+import org.testng.annotations.BeforeClass;
+import org.testng.annotations.Test;
+import org.hibernate.ejb.Ejb3Configuration;
+
+import javax.persistence.EntityManager;
+import java.util.Arrays;
+import java.util.Collections;
+import java.util.HashSet;
+
+/**
+ * @author Adam Warski (adam at warski dot org)
+ */
+public class BasicUniSet extends AbstractEntityTest {
+ private Integer ed1_id;
+ private Integer ed2_id;
+
+ private Integer ing1_id;
+ private Integer ing2_id;
+
+ public void configure(Ejb3Configuration cfg) {
+ cfg.addAnnotatedClass(SetUniEntity.class);
+ cfg.addAnnotatedClass(StrTestEntity.class);
+ }
+
+ @BeforeClass(dependsOnMethods = "init")
+ public void initData() {
+ EntityManager em = getEntityManager();
+
+ StrTestEntity ed1 = new StrTestEntity("data_ed_1");
+ StrTestEntity ed2 = new StrTestEntity("data_ed_2");
+
+ SetUniEntity ing1 = new SetUniEntity(3, "data_ing_1");
+ SetUniEntity ing2 = new SetUniEntity(4, "data_ing_2");
+
+ // Revision 1
+ em.getTransaction().begin();
+
+ em.persist(ed1);
+ em.persist(ed2);
+ em.persist(ing1);
+ em.persist(ing2);
+
+ em.getTransaction().commit();
+
+ // Revision 2
+
+ em.getTransaction().begin();
+
+ ing1 = em.find(SetUniEntity.class, ing1.getId());
+ ing2 = em.find(SetUniEntity.class, ing2.getId());
+ ed1 = em.find(StrTestEntity.class, ed1.getId());
+ ed2 = em.find(StrTestEntity.class, ed2.getId());
+
+ ing1.setReferences(new HashSet<StrTestEntity>());
+ ing1.getReferences().add(ed1);
+
+ ing2.setReferences(new HashSet<StrTestEntity>());
+ ing2.getReferences().add(ed1);
+ ing2.getReferences().add(ed2);
+
+ em.getTransaction().commit();
+
+ // Revision 3
+ em.getTransaction().begin();
+
+ ing1 = em.find(SetUniEntity.class, ing1.getId());
+ ed2 = em.find(StrTestEntity.class, ed2.getId());
+ ed1 = em.find(StrTestEntity.class, ed1.getId());
+
+ ing1.getReferences().add(ed2);
+
+ em.getTransaction().commit();
+
+ // Revision 4
+ em.getTransaction().begin();
+
+ ing1 = em.find(SetUniEntity.class, ing1.getId());
+ ed2 = em.find(StrTestEntity.class, ed2.getId());
+ ed1 = em.find(StrTestEntity.class, ed1.getId());
+
+ ing1.getReferences().remove(ed1);
+
+ em.getTransaction().commit();
+
+ // Revision 5
+ em.getTransaction().begin();
+
+ ing1 = em.find(SetUniEntity.class, ing1.getId());
+
+ ing1.setReferences(null);
+
+ em.getTransaction().commit();
+
+ //
+
+ ed1_id = ed1.getId();
+ ed2_id = ed2.getId();
+
+ ing1_id = ing1.getId();
+ ing2_id = ing2.getId();
+ }
+
+ @Test
+ public void testRevisionsCounts() {
+ assert Arrays.asList(1).equals(getVersionsReader().getRevisions(StrTestEntity.class, ed1_id));
+ assert Arrays.asList(1).equals(getVersionsReader().getRevisions(StrTestEntity.class, ed2_id));
+
+ assert Arrays.asList(1, 2, 3, 4, 5).equals(getVersionsReader().getRevisions(SetUniEntity.class, ing1_id));
+ assert Arrays.asList(1, 2).equals(getVersionsReader().getRevisions(SetUniEntity.class, ing2_id));
+ }
+
+ @Test
+ public void testHistoryOfEdIng1() {
+ StrTestEntity ed1 = getEntityManager().find(StrTestEntity.class, ed1_id);
+ StrTestEntity ed2 = getEntityManager().find(StrTestEntity.class, ed2_id);
+
+ SetUniEntity rev1 = getVersionsReader().find(SetUniEntity.class, ing1_id, 1);
+ SetUniEntity rev2 = getVersionsReader().find(SetUniEntity.class, ing1_id, 2);
+ SetUniEntity rev3 = getVersionsReader().find(SetUniEntity.class, ing1_id, 3);
+ SetUniEntity rev4 = getVersionsReader().find(SetUniEntity.class, ing1_id, 4);
+ SetUniEntity rev5 = getVersionsReader().find(SetUniEntity.class, ing1_id, 5);
+
+ assert rev1.getReferences().equals(Collections.EMPTY_SET);
+ assert rev2.getReferences().equals(TestTools.makeSet(ed1));
+ assert rev3.getReferences().equals(TestTools.makeSet(ed1, ed2));
+ assert rev4.getReferences().equals(TestTools.makeSet(ed2));
+ assert rev5.getReferences().equals(Collections.EMPTY_SET);
+ }
+
+ @Test
+ public void testHistoryOfEdIng2() {
+ StrTestEntity ed1 = getEntityManager().find(StrTestEntity.class, ed1_id);
+ StrTestEntity ed2 = getEntityManager().find(StrTestEntity.class, ed2_id);
+
+ SetUniEntity rev1 = getVersionsReader().find(SetUniEntity.class, ing2_id, 1);
+ SetUniEntity rev2 = getVersionsReader().find(SetUniEntity.class, ing2_id, 2);
+ SetUniEntity rev3 = getVersionsReader().find(SetUniEntity.class, ing2_id, 3);
+ SetUniEntity rev4 = getVersionsReader().find(SetUniEntity.class, ing2_id, 4);
+ SetUniEntity rev5 = getVersionsReader().find(SetUniEntity.class, ing2_id, 5);
+
+ assert rev1.getReferences().equals(Collections.EMPTY_SET);
+ assert rev2.getReferences().equals(TestTools.makeSet(ed1, ed2));
+ assert rev3.getReferences().equals(TestTools.makeSet(ed1, ed2));
+ assert rev4.getReferences().equals(TestTools.makeSet(ed1, ed2));
+ assert rev5.getReferences().equals(TestTools.makeSet(ed1, ed2));
+ }
+}
\ No newline at end of file
Added: core/trunk/envers/src/test/java/org/jboss/envers/test/integration/naming/BasicNaming.java
===================================================================
--- core/trunk/envers/src/test/java/org/jboss/envers/test/integration/naming/BasicNaming.java (rev 0)
+++ core/trunk/envers/src/test/java/org/jboss/envers/test/integration/naming/BasicNaming.java 2008-10-27 18:56:31 UTC (rev 15406)
@@ -0,0 +1,91 @@
+package org.jboss.envers.test.integration.naming;
+
+import org.jboss.envers.test.AbstractEntityTest;
+import org.hibernate.ejb.Ejb3Configuration;
+import org.testng.annotations.BeforeClass;
+import org.testng.annotations.Test;
+
+import javax.persistence.EntityManager;
+import java.util.Arrays;
+
+/**
+ * @author Adam Warski (adam at warski dot org)
+ */
+public class BasicNaming extends AbstractEntityTest {
+ private Integer id1;
+ private Integer id2;
+
+ public void configure(Ejb3Configuration cfg) {
+ cfg.addAnnotatedClass(NamingTestEntity1.class);
+ }
+
+ @BeforeClass(dependsOnMethods = "init")
+ public void initData() {
+ NamingTestEntity1 nte1 = new NamingTestEntity1("data1");
+ NamingTestEntity1 nte2 = new NamingTestEntity1("data2");
+
+ // Revision 1
+ EntityManager em = getEntityManager();
+ em.getTransaction().begin();
+
+ em.persist(nte1);
+ em.persist(nte2);
+
+ em.getTransaction().commit();
+
+ // Revision 2
+ em.getTransaction().begin();
+
+ nte1 = em.find(NamingTestEntity1.class, nte1.getId());
+ nte1.setData("data1'");
+
+ em.getTransaction().commit();
+
+ // Revision 3
+ em.getTransaction().begin();
+
+ nte2 = em.find(NamingTestEntity1.class, nte2.getId());
+ nte2.setData("data2'");
+
+ em.getTransaction().commit();
+
+ //
+
+ id1 = nte1.getId();
+ id2 = nte2.getId();
+ }
+
+ @Test
+ public void testRevisionsCounts() {
+ assert Arrays.asList(1, 2).equals(getVersionsReader().getRevisions(NamingTestEntity1.class, id1));
+
+ assert Arrays.asList(1, 3).equals(getVersionsReader().getRevisions(NamingTestEntity1.class, id2));
+ }
+
+ @Test
+ public void testHistoryOfId1() {
+ NamingTestEntity1 ver1 = new NamingTestEntity1(id1, "data1");
+ NamingTestEntity1 ver2 = new NamingTestEntity1(id1, "data1'");
+
+ assert getVersionsReader().find(NamingTestEntity1.class, id1, 1).equals(ver1);
+ assert getVersionsReader().find(NamingTestEntity1.class, id1, 2).equals(ver2);
+ assert getVersionsReader().find(NamingTestEntity1.class, id1, 3).equals(ver2);
+ }
+
+ @Test
+ public void testHistoryOfId2() {
+ NamingTestEntity1 ver1 = new NamingTestEntity1(id2, "data2");
+ NamingTestEntity1 ver2 = new NamingTestEntity1(id2, "data2'");
+
+ assert getVersionsReader().find(NamingTestEntity1.class, id2, 1).equals(ver1);
+ assert getVersionsReader().find(NamingTestEntity1.class, id2, 2).equals(ver1);
+ assert getVersionsReader().find(NamingTestEntity1.class, id2, 3).equals(ver2);
+ }
+
+ @Test
+ public void testTableName() {
+ assert "naming_test_entity_1_versions".equals(
+ getCfg().getClassMapping("org.jboss.envers.test.integration.naming.NamingTestEntity1_versions")
+ .getTable().getName());
+ }
+}
Added: core/trunk/envers/src/test/java/org/jboss/envers/test/integration/naming/DetachedNamingTestEntity.java
===================================================================
--- core/trunk/envers/src/test/java/org/jboss/envers/test/integration/naming/DetachedNamingTestEntity.java (rev 0)
+++ core/trunk/envers/src/test/java/org/jboss/envers/test/integration/naming/DetachedNamingTestEntity.java 2008-10-27 18:56:31 UTC (rev 15406)
@@ -0,0 +1,85 @@
+package org.jboss.envers.test.integration.naming;
+
+import org.jboss.envers.Versioned;
+import org.jboss.envers.test.entities.StrTestEntity;
+
+import javax.persistence.*;
+import java.util.Set;
+
+/**
+ * @author Adam Warski (adam at warski dot org)
+ */
+ at Entity
+public class DetachedNamingTestEntity {
+ @Id
+ private Integer id;
+
+ @Versioned
+ private String data;
+
+ @Versioned
+ @OneToMany
+ @JoinTable(name = "UNI_NAMING_TEST",
+ joinColumns = @JoinColumn(name = "ID_1"),
+ inverseJoinColumns = @JoinColumn(name = "ID_2"))
+ private Set<StrTestEntity> collection;
+
+ public DetachedNamingTestEntity() {
+ }
+
+ public DetachedNamingTestEntity(Integer id, String data) {
+ this.id = id;
+ this.data = data;
+ }
+
+ public DetachedNamingTestEntity(String data) {
+ this.data = data;
+ }
+
+ public Integer getId() {
+ return id;
+ }
+
+ public void setId(Integer id) {
+ this.id = id;
+ }
+
+ public String getData() {
+ return data;
+ }
+
+ public void setData(String data) {
+ this.data = data;
+ }
+
+ public Set<StrTestEntity> getCollection() {
+ return collection;
+ }
+
+ public void setCollection(Set<StrTestEntity> collection) {
+ this.collection = collection;
+ }
+
+ public boolean equals(Object o) {
+ if (this == o) return true;
+ if (!(o instanceof DetachedNamingTestEntity)) return false;
+
+ DetachedNamingTestEntity that = (DetachedNamingTestEntity) o;
+
+ if (data != null ? !data.equals(that.data) : that.data != null) return false;
+ if (id != null ? !id.equals(that.id) : that.id != null) return false;
+
+ return true;
+ }
+
+ public int hashCode() {
+ int result;
+ result = (id != null ? id.hashCode() : 0);
+ result = 31 * result + (data != null ? data.hashCode() : 0);
+ return result;
+ }
+
+ public String toString() {
+ return "DetachedNamingTestEntity(id = " + id + ", data = " + data + ")";
+ }
+}
Added: core/trunk/envers/src/test/java/org/jboss/envers/test/integration/naming/JoinNaming.java
===================================================================
--- core/trunk/envers/src/test/java/org/jboss/envers/test/integration/naming/JoinNaming.java (rev 0)
+++ core/trunk/envers/src/test/java/org/jboss/envers/test/integration/naming/JoinNaming.java 2008-10-27 18:56:31 UTC (rev 15406)
@@ -0,0 +1,113 @@
+package org.jboss.envers.test.integration.naming;
+
+import org.jboss.envers.test.AbstractEntityTest;
+import org.hibernate.ejb.Ejb3Configuration;
+import org.hibernate.mapping.Column;
+import org.testng.annotations.BeforeClass;
+import org.testng.annotations.Test;
+
+import javax.persistence.EntityManager;
+import java.util.Arrays;
+import java.util.Iterator;
+
+/**
+ * @author Adam Warski (adam at warski dot org)
+ */
+public class JoinNaming extends AbstractEntityTest {
+ private Integer ed_id1;
+ private Integer ed_id2;
+ private Integer ing_id1;
+
+ public void configure(Ejb3Configuration cfg) {
+ cfg.addAnnotatedClass(JoinNamingRefEdEntity.class);
+ cfg.addAnnotatedClass(JoinNamingRefIngEntity.class);
+ }
+
+ @BeforeClass(dependsOnMethods = "init")
+ public void initData() {
+ JoinNamingRefEdEntity ed1 = new JoinNamingRefEdEntity("data1");
+ JoinNamingRefEdEntity ed2 = new JoinNamingRefEdEntity("data2");
+
+ JoinNamingRefIngEntity ing1 = new JoinNamingRefIngEntity("x", ed1);
+
+ // Revision 1
+ EntityManager em = getEntityManager();
+ em.getTransaction().begin();
+
+ em.persist(ed1);
+ em.persist(ed2);
+ em.persist(ing1);
+
+ em.getTransaction().commit();
+
+ // Revision 2
+ em.getTransaction().begin();
+
+ ed2 = em.find(JoinNamingRefEdEntity.class, ed2.getId());
+
+ ing1 = em.find(JoinNamingRefIngEntity.class, ing1.getId());
+ ing1.setData("y");
+ ing1.setReference(ed2);
+
+ em.getTransaction().commit();
+
+ //
+
+ ed_id1 = ed1.getId();
+ ed_id2 = ed2.getId();
+ ing_id1 = ing1.getId();
+ }
+
+ @Test
+ public void testRevisionsCounts() {
+ assert Arrays.asList(1, 2).equals(getVersionsReader().getRevisions(JoinNamingRefEdEntity.class, ed_id1));
+ assert Arrays.asList(1, 2).equals(getVersionsReader().getRevisions(JoinNamingRefEdEntity.class, ed_id2));
+ assert Arrays.asList(1, 2).equals(getVersionsReader().getRevisions(JoinNamingRefIngEntity.class, ing_id1));
+ }
+
+ @Test
+ public void testHistoryOfEdId1() {
+ JoinNamingRefEdEntity ver1 = new JoinNamingRefEdEntity(ed_id1, "data1");
+
+ assert getVersionsReader().find(JoinNamingRefEdEntity.class, ed_id1, 1).equals(ver1);
+ assert getVersionsReader().find(JoinNamingRefEdEntity.class, ed_id1, 2).equals(ver1);
+ }
+
+ @Test
+ public void testHistoryOfEdId2() {
+ JoinNamingRefEdEntity ver1 = new JoinNamingRefEdEntity(ed_id2, "data2");
+
+ assert getVersionsReader().find(JoinNamingRefEdEntity.class, ed_id2, 1).equals(ver1);
+ assert getVersionsReader().find(JoinNamingRefEdEntity.class, ed_id2, 2).equals(ver1);
+ }
+
+ @Test
+ public void testHistoryOfIngId1() {
+ JoinNamingRefIngEntity ver1 = new JoinNamingRefIngEntity(ing_id1, "x", null);
+ JoinNamingRefIngEntity ver2 = new JoinNamingRefIngEntity(ing_id1, "y", null);
+
+ assert getVersionsReader().find(JoinNamingRefIngEntity.class, ing_id1, 1).equals(ver1);
+ assert getVersionsReader().find(JoinNamingRefIngEntity.class, ing_id1, 2).equals(ver2);
+
+ assert getVersionsReader().find(JoinNamingRefIngEntity.class, ing_id1, 1).getReference().equals(
+ new JoinNamingRefEdEntity(ed_id1, "data1"));
+ assert getVersionsReader().find(JoinNamingRefIngEntity.class, ing_id1, 2).getReference().equals(
+ new JoinNamingRefEdEntity(ed_id2, "data2"));
+ }
+
+ @SuppressWarnings({"unchecked"})
+ @Test
+ public void testJoinColumnName() {
+ Iterator<Column> columns =
+ getCfg().getClassMapping("org.jboss.envers.test.integration.naming.JoinNamingRefIngEntity_versions")
+ .getProperty("reference").getColumnIterator();
+
+ while (columns.hasNext()) {
+ if ("jnree_column_reference".equals(columns.next().getName())) {
+ return;
+ }
+ }
+
+ assert false;
+ }
+}
\ No newline at end of file
Added: core/trunk/envers/src/test/java/org/jboss/envers/test/integration/naming/JoinNamingRefEdEntity.java
===================================================================
--- core/trunk/envers/src/test/java/org/jboss/envers/test/integration/naming/JoinNamingRefEdEntity.java (rev 0)
+++ core/trunk/envers/src/test/java/org/jboss/envers/test/integration/naming/JoinNamingRefEdEntity.java 2008-10-27 18:56:31 UTC (rev 15406)
@@ -0,0 +1,84 @@
+package org.jboss.envers.test.integration.naming;
+
+import org.jboss.envers.Versioned;
+
+import javax.persistence.*;
+import java.util.List;
+
+/**
+ * ReferencEd entity
+ * @author Adam Warski (adam at warski dot org)
+ */
+ at Entity
+public class JoinNamingRefEdEntity {
+ @Id
+ @GeneratedValue
+ @Column(name = "jnree_id")
+ private Integer id;
+
+ @Versioned
+ private String data;
+
+ @Versioned
+ @OneToMany(mappedBy="reference")
+ private List<JoinNamingRefIngEntity> reffering;
+
+ public JoinNamingRefEdEntity() {
+ }
+
+ public JoinNamingRefEdEntity(Integer id, String data) {
+ this.id = id;
+ this.data = data;
+ }
+
+ public JoinNamingRefEdEntity(String data) {
+ this.data = data;
+ }
+
+ public Integer getId() {
+ return id;
+ }
+
+ public void setId(Integer id) {
+ this.id = id;
+ }
+
+ public String getData() {
+ return data;
+ }
+
+ public void setData(String data) {
+ this.data = data;
+ }
+
+ public List<JoinNamingRefIngEntity> getReffering() {
+ return reffering;
+ }
+
+ public void setReffering(List<JoinNamingRefIngEntity> reffering) {
+ this.reffering = reffering;
+ }
+
+ public boolean equals(Object o) {
+ if (this == o) return true;
+ if (!(o instanceof JoinNamingRefEdEntity)) return false;
+
+ JoinNamingRefEdEntity that = (JoinNamingRefEdEntity) o;
+
+ if (data != null ? !data.equals(that.data) : that.data != null) return false;
+ if (id != null ? !id.equals(that.id) : that.id != null) return false;
+
+ return true;
+ }
+
+ public int hashCode() {
+ int result;
+ result = (id != null ? id.hashCode() : 0);
+ result = 31 * result + (data != null ? data.hashCode() : 0);
+ return result;
+ }
+
+ public String toString() {
+ return "JoinNamingRefEdEntity(id = " + id + ", data = " + data + ")";
+ }
+}
\ No newline at end of file
Added: core/trunk/envers/src/test/java/org/jboss/envers/test/integration/naming/JoinNamingRefIngEntity.java
===================================================================
--- core/trunk/envers/src/test/java/org/jboss/envers/test/integration/naming/JoinNamingRefIngEntity.java (rev 0)
+++ core/trunk/envers/src/test/java/org/jboss/envers/test/integration/naming/JoinNamingRefIngEntity.java 2008-10-27 18:56:31 UTC (rev 15406)
@@ -0,0 +1,85 @@
+package org.jboss.envers.test.integration.naming;
+
+import org.jboss.envers.Versioned;
+
+import javax.persistence.*;
+
+/**
+ * ReferencIng entity
+ * @author Adam Warski (adam at warski dot org)
+ */
+ at Entity
+public class JoinNamingRefIngEntity {
+ @Id
+ @GeneratedValue
+ @Column(name = "jnrie_id")
+ private Integer id;
+
+ @Versioned
+ private String data;
+
+ @Versioned
+ @ManyToOne
+ @JoinColumn(name = "jnree_column_reference")
+ private JoinNamingRefEdEntity reference;
+
+ public JoinNamingRefIngEntity() { }
+
+ public JoinNamingRefIngEntity(Integer id, String data, JoinNamingRefEdEntity reference) {
+ this.id = id;
+ this.data = data;
+ this.reference = reference;
+ }
+
+ public JoinNamingRefIngEntity(String data, JoinNamingRefEdEntity reference) {
+ this.data = data;
+ this.reference = reference;
+ }
+
+ public Integer getId() {
+ return id;
+ }
+
+ public void setId(Integer id) {
+ this.id = id;
+ }
+
+ public String getData() {
+ return data;
+ }
+
+ public void setData(String data) {
+ this.data = data;
+ }
+
+ public JoinNamingRefEdEntity getReference() {
+ return reference;
+ }
+
+ public void setReference(JoinNamingRefEdEntity reference) {
+ this.reference = reference;
+ }
+
+ public boolean equals(Object o) {
+ if (this == o) return true;
+ if (!(o instanceof JoinNamingRefIngEntity)) return false;
+
+ JoinNamingRefIngEntity that = (JoinNamingRefIngEntity) o;
+
+ if (data != null ? !data.equals(that.data) : that.data != null) return false;
+ if (id != null ? !id.equals(that.id) : that.id != null) return false;
+
+ return true;
+ }
+
+ public int hashCode() {
+ int result;
+ result = (id != null ? id.hashCode() : 0);
+ result = 31 * result + (data != null ? data.hashCode() : 0);
+ return result;
+ }
+
+ public String toString() {
+ return "JoinNamingRefIngEntity(id = " + id + ", data = " + data + ")";
+ }
+}
\ No newline at end of file
Added: core/trunk/envers/src/test/java/org/jboss/envers/test/integration/naming/NamingTestEntity1.java
===================================================================
--- core/trunk/envers/src/test/java/org/jboss/envers/test/integration/naming/NamingTestEntity1.java (rev 0)
+++ core/trunk/envers/src/test/java/org/jboss/envers/test/integration/naming/NamingTestEntity1.java 2008-10-27 18:56:31 UTC (rev 15406)
@@ -0,0 +1,70 @@
+package org.jboss.envers.test.integration.naming;
+
+import org.jboss.envers.Versioned;
+import org.jboss.envers.VersionsTable;
+
+import javax.persistence.*;
+
+/**
+ * @author Adam Warski (adam at warski dot org)
+ */
+ at Entity
+ at Table(name="naming_test_entity_1")
+ at VersionsTable("naming_test_entity_1_versions")
+public class NamingTestEntity1 {
+ @Id
+ @GeneratedValue
+ @Column(name = "nte_id")
+ private Integer id;
+
+ @Column(name = "nte_data")
+ @Versioned
+ private String data;
+
+ public NamingTestEntity1() {
+ }
+
+ public NamingTestEntity1(String data) {
+ this.data = data;
+ }
+
+ public NamingTestEntity1(Integer id, String data) {
+ this.id = id;
+ this.data = data;
+ }
+
+ public Integer getId() {
+ return id;
+ }
+
+ public void setId(Integer id) {
+ this.id = id;
+ }
+
+ public String getData() {
+ return data;
+ }
+
+ public void setData(String data) {
+ this.data = data;
+ }
+
+ public boolean equals(Object o) {
+ if (this == o) return true;
+ if (!(o instanceof NamingTestEntity1)) return false;
+
+ NamingTestEntity1 that = (NamingTestEntity1) o;
+
+ if (data != null ? !data.equals(that.data) : that.data != null) return false;
+ if (id != null ? !id.equals(that.id) : that.id != null) return false;
+
+ return true;
+ }
+
+ public int hashCode() {
+ int result;
+ result = (id != null ? id.hashCode() : 0);
+ result = 31 * result + (data != null ? data.hashCode() : 0);
+ return result;
+ }
+}
Added: core/trunk/envers/src/test/java/org/jboss/envers/test/integration/naming/OneToManyUnidirectionalNaming.java
===================================================================
--- core/trunk/envers/src/test/java/org/jboss/envers/test/integration/naming/OneToManyUnidirectionalNaming.java (rev 0)
+++ core/trunk/envers/src/test/java/org/jboss/envers/test/integration/naming/OneToManyUnidirectionalNaming.java 2008-10-27 18:56:31 UTC (rev 15406)
@@ -0,0 +1,107 @@
+package org.jboss.envers.test.integration.naming;
+
+import org.jboss.envers.test.AbstractEntityTest;
+import org.jboss.envers.test.entities.StrTestEntity;
+import org.jboss.envers.test.tools.TestTools;
+import org.hibernate.ejb.Ejb3Configuration;
+import org.hibernate.mapping.Column;
+import org.testng.annotations.BeforeClass;
+import org.testng.annotations.Test;
+
+import javax.persistence.EntityManager;
+import java.util.Arrays;
+import java.util.Iterator;
+import java.util.HashSet;
+
+/**
+ * @author Adam Warski (adam at warski dot org)
+ */
+public class OneToManyUnidirectionalNaming extends AbstractEntityTest {
+ private Integer uni1_id;
+ private Integer str1_id;
+
+ public void configure(Ejb3Configuration cfg) {
+ cfg.addAnnotatedClass(DetachedNamingTestEntity.class);
+ cfg.addAnnotatedClass(StrTestEntity.class);
+ }
+
+ @BeforeClass(dependsOnMethods = "init")
+ public void initData() {
+ DetachedNamingTestEntity uni1 = new DetachedNamingTestEntity(1, "data1");
+ StrTestEntity str1 = new StrTestEntity("str1");
+
+ // Revision 1
+ EntityManager em = getEntityManager();
+ em.getTransaction().begin();
+
+ uni1.setCollection(new HashSet<StrTestEntity>());
+ em.persist(uni1);
+ em.persist(str1);
+
+ em.getTransaction().commit();
+
+ // Revision 2
+ em.getTransaction().begin();
+
+ uni1 = em.find(DetachedNamingTestEntity.class, uni1.getId());
+ str1 = em.find(StrTestEntity.class, str1.getId());
+ uni1.getCollection().add(str1);
+
+ em.getTransaction().commit();
+
+ //
+
+ uni1_id = uni1.getId();
+ str1_id = str1.getId();
+ }
+
+ @Test
+ public void testRevisionsCounts() {
+ assert Arrays.asList(1, 2).equals(getVersionsReader().getRevisions(DetachedNamingTestEntity.class, uni1_id));
+ assert Arrays.asList(1).equals(getVersionsReader().getRevisions(StrTestEntity.class, str1_id));
+ }
+
+ @Test
+ public void testHistoryOfUniId1() {
+ StrTestEntity str1 = getEntityManager().find(StrTestEntity.class, str1_id);
+
+ DetachedNamingTestEntity rev1 = getVersionsReader().find(DetachedNamingTestEntity.class, uni1_id, 1);
+ DetachedNamingTestEntity rev2 = getVersionsReader().find(DetachedNamingTestEntity.class, uni1_id, 2);
+
+ assert rev1.getCollection().equals(TestTools.makeSet());
+ assert rev2.getCollection().equals(TestTools.makeSet(str1));
+
+ assert "data1".equals(rev1.getData());
+ assert "data1".equals(rev2.getData());
+ }
+
+ private final static String MIDDLE_VERSIONS_ENTITY_NAME = "UNI_NAMING_TEST_versions";
+ @Test
+ public void testTableName() {
+ assert MIDDLE_VERSIONS_ENTITY_NAME.equals(
+ getCfg().getClassMapping(MIDDLE_VERSIONS_ENTITY_NAME).getTable().getName());
+ }
+
+ @SuppressWarnings({"unchecked"})
+ @Test
+ public void testJoinColumnName() {
+ Iterator<Column> columns =
+ getCfg().getClassMapping(MIDDLE_VERSIONS_ENTITY_NAME).getTable().getColumnIterator();
+
+ boolean id1Found = false;
+ boolean id2Found = false;
+
+ while (columns.hasNext()) {
+ Column column = columns.next();
+ if ("ID_1".equals(column.getName())) {
+ id1Found = true;
+ }
+
+ if ("ID_2".equals(column.getName())) {
+ id2Found = true;
+ }
+ }
+
+ assert id1Found && id2Found;
+ }
+}
Added: core/trunk/envers/src/test/java/org/jboss/envers/test/integration/naming/VersionsJoinTableNaming.java
===================================================================
--- core/trunk/envers/src/test/java/org/jboss/envers/test/integration/naming/VersionsJoinTableNaming.java (rev 0)
+++ core/trunk/envers/src/test/java/org/jboss/envers/test/integration/naming/VersionsJoinTableNaming.java 2008-10-27 18:56:31 UTC (rev 15406)
@@ -0,0 +1,108 @@
+package org.jboss.envers.test.integration.naming;
+
+import org.jboss.envers.test.AbstractEntityTest;
+import org.jboss.envers.test.entities.StrTestEntity;
+import org.jboss.envers.test.tools.TestTools;
+import org.hibernate.ejb.Ejb3Configuration;
+import org.hibernate.mapping.Column;
+import org.testng.annotations.BeforeClass;
+import org.testng.annotations.Test;
+
+import javax.persistence.EntityManager;
+import java.util.Arrays;
+import java.util.Iterator;
+import java.util.HashSet;
+
+/**
+ * @author Adam Warski (adam at warski dot org)
+ */
+public class VersionsJoinTableNaming extends AbstractEntityTest {
+ private Integer uni1_id;
+ private Integer str1_id;
+
+ public void configure(Ejb3Configuration cfg) {
+ cfg.addAnnotatedClass(VersionsJoinTableTestEntity.class);
+ cfg.addAnnotatedClass(StrTestEntity.class);
+ }
+
+ @BeforeClass(dependsOnMethods = "init")
+ public void initData() {
+ VersionsJoinTableTestEntity uni1 = new VersionsJoinTableTestEntity(1, "data1");
+ StrTestEntity str1 = new StrTestEntity("str1");
+
+ // Revision 1
+ EntityManager em = getEntityManager();
+ em.getTransaction().begin();
+
+ uni1.setCollection(new HashSet<StrTestEntity>());
+ em.persist(uni1);
+ em.persist(str1);
+
+ em.getTransaction().commit();
+
+ // Revision 2
+ em.getTransaction().begin();
+
+ uni1 = em.find(VersionsJoinTableTestEntity.class, uni1.getId());
+ str1 = em.find(StrTestEntity.class, str1.getId());
+ uni1.getCollection().add(str1);
+
+ em.getTransaction().commit();
+
+ //
+
+ uni1_id = uni1.getId();
+ str1_id = str1.getId();
+ }
+
+ @Test
+ public void testRevisionsCounts() {
+ assert Arrays.asList(1, 2).equals(getVersionsReader().getRevisions(VersionsJoinTableTestEntity.class, uni1_id));
+ assert Arrays.asList(1).equals(getVersionsReader().getRevisions(StrTestEntity.class, str1_id));
+ }
+
+ @Test
+ public void testHistoryOfUniId1() {
+ StrTestEntity str1 = getEntityManager().find(StrTestEntity.class, str1_id);
+
+ VersionsJoinTableTestEntity rev1 = getVersionsReader().find(VersionsJoinTableTestEntity.class, uni1_id, 1);
+ VersionsJoinTableTestEntity rev2 = getVersionsReader().find(VersionsJoinTableTestEntity.class, uni1_id, 2);
+
+ assert rev1.getCollection().equals(TestTools.makeSet());
+ assert rev2.getCollection().equals(TestTools.makeSet(str1));
+
+ assert "data1".equals(rev1.getData());
+ assert "data1".equals(rev2.getData());
+ }
+
+ private final static String MIDDLE_VERSIONS_ENTITY_NAME = "VERSIONS_JOIN_TABLE_TEST";
+
+ @Test
+ public void testTableName() {
+ assert MIDDLE_VERSIONS_ENTITY_NAME.equals(
+ getCfg().getClassMapping(MIDDLE_VERSIONS_ENTITY_NAME).getTable().getName());
+ }
+
+ @SuppressWarnings({"unchecked"})
+ @Test
+ public void testJoinColumnName() {
+ Iterator<Column> columns =
+ getCfg().getClassMapping(MIDDLE_VERSIONS_ENTITY_NAME).getTable().getColumnIterator();
+
+ boolean id1Found = false;
+ boolean id2Found = false;
+
+ while (columns.hasNext()) {
+ Column column = columns.next();
+ if ("VJT_ID".equals(column.getName())) {
+ id1Found = true;
+ }
+
+ if ("STR_ID".equals(column.getName())) {
+ id2Found = true;
+ }
+ }
+
+ assert id1Found && id2Found;
+ }
+}
\ No newline at end of file
Added: core/trunk/envers/src/test/java/org/jboss/envers/test/integration/naming/VersionsJoinTableTestEntity.java
===================================================================
--- core/trunk/envers/src/test/java/org/jboss/envers/test/integration/naming/VersionsJoinTableTestEntity.java (rev 0)
+++ core/trunk/envers/src/test/java/org/jboss/envers/test/integration/naming/VersionsJoinTableTestEntity.java 2008-10-27 18:56:31 UTC (rev 15406)
@@ -0,0 +1,85 @@
+package org.jboss.envers.test.integration.naming;
+
+import org.jboss.envers.Versioned;
+import org.jboss.envers.VersionsJoinTable;
+import org.jboss.envers.test.entities.StrTestEntity;
+
+import javax.persistence.*;
+import java.util.Set;
+
+/**
+ * @author Adam Warski (adam at warski dot org)
+ */
+ at Entity
+public class VersionsJoinTableTestEntity {
+ @Id
+ private Integer id;
+
+ @Versioned
+ private String data;
+
+ @Versioned
+ @OneToMany
+ @JoinColumn(name = "VJT_ID")
+ @VersionsJoinTable(name = "VERSIONS_JOIN_TABLE_TEST", inverseJoinColumns = @JoinColumn(name = "STR_ID"))
+ private Set<StrTestEntity> collection;
+
+ public VersionsJoinTableTestEntity() {
+ }
+
+ public VersionsJoinTableTestEntity(Integer id, String data) {
+ this.id = id;
+ this.data = data;
+ }
+
+ public VersionsJoinTableTestEntity(String data) {
+ this.data = data;
+ }
+
+ public Integer getId() {
+ return id;
+ }
+
+ public void setId(Integer id) {
+ this.id = id;
+ }
+
+ public String getData() {
+ return data;
+ }
+
+ public void setData(String data) {
+ this.data = data;
+ }
+
+ public Set<StrTestEntity> getCollection() {
+ return collection;
+ }
+
+ public void setCollection(Set<StrTestEntity> collection) {
+ this.collection = collection;
+ }
+
+ public boolean equals(Object o) {
+ if (this == o) return true;
+ if (!(o instanceof VersionsJoinTableTestEntity)) return false;
+
+ VersionsJoinTableTestEntity that = (VersionsJoinTableTestEntity) o;
+
+ if (data != null ? !data.equals(that.data) : that.data != null) return false;
+ if (id != null ? !id.equals(that.id) : that.id != null) return false;
+
+ return true;
+ }
+
+ public int hashCode() {
+ int result;
+ result = (id != null ? id.hashCode() : 0);
+ result = 31 * result + (data != null ? data.hashCode() : 0);
+ return result;
+ }
+
+ public String toString() {
+ return "VersionsJoinTableTestEntity(id = " + id + ", data = " + data + ")";
+ }
+}
\ No newline at end of file
Added: core/trunk/envers/src/test/java/org/jboss/envers/test/integration/naming/ids/EmbIdNaming.java
===================================================================
--- core/trunk/envers/src/test/java/org/jboss/envers/test/integration/naming/ids/EmbIdNaming.java (rev 0)
+++ core/trunk/envers/src/test/java/org/jboss/envers/test/integration/naming/ids/EmbIdNaming.java 2008-10-27 18:56:31 UTC (rev 15406)
@@ -0,0 +1,66 @@
+package org.jboss.envers.test.integration.naming.ids;
+
+import org.jboss.envers.test.entities.ids.EmbId;
+
+import javax.persistence.Embeddable;
+import javax.persistence.Column;
+import java.io.Serializable;
+
+/**
+ * @author Adam Warski (adam at warski dot org)
+ */
+ at Embeddable
+public class EmbIdNaming implements Serializable {
+ @Column(name = "XX")
+ private Integer x;
+
+ @Column(name = "YY")
+ private Integer y;
+
+ public EmbIdNaming() {
+ }
+
+ public EmbIdNaming(Integer x, Integer y) {
+ this.x = x;
+ this.y = y;
+ }
+
+ public Integer getX() {
+ return x;
+ }
+
+ public void setX(Integer x) {
+ this.x = x;
+ }
+
+ public Integer getY() {
+ return y;
+ }
+
+ public void setY(Integer y) {
+ this.y = y;
+ }
+
+ public boolean equals(Object o) {
+ if (this == o) return true;
+ if (!(o instanceof EmbIdNaming)) return false;
+
+ EmbIdNaming embId = (EmbIdNaming) o;
+
+ if (x != null ? !x.equals(embId.x) : embId.x != null) return false;
+ if (y != null ? !y.equals(embId.y) : embId.y != null) return false;
+
+ return true;
+ }
+
+ public int hashCode() {
+ int result;
+ result = (x != null ? x.hashCode() : 0);
+ result = 31 * result + (y != null ? y.hashCode() : 0);
+ return result;
+ }
+
+ public String toString() {
+ return "EmbIdNaming(" + x + ", " + y + ")";
+ }
+}
\ No newline at end of file
Added: core/trunk/envers/src/test/java/org/jboss/envers/test/integration/naming/ids/JoinEmbIdNaming.java
===================================================================
--- core/trunk/envers/src/test/java/org/jboss/envers/test/integration/naming/ids/JoinEmbIdNaming.java (rev 0)
+++ core/trunk/envers/src/test/java/org/jboss/envers/test/integration/naming/ids/JoinEmbIdNaming.java 2008-10-27 18:56:31 UTC (rev 15406)
@@ -0,0 +1,117 @@
+package org.jboss.envers.test.integration.naming.ids;
+
+import org.jboss.envers.test.AbstractEntityTest;
+import org.hibernate.ejb.Ejb3Configuration;
+import org.hibernate.mapping.Column;
+import org.testng.annotations.BeforeClass;
+import org.testng.annotations.Test;
+
+import javax.persistence.EntityManager;
+import java.util.Arrays;
+import java.util.Iterator;
+
+/**
+ * @author Adam Warski (adam at warski dot org)
+ */
+public class JoinEmbIdNaming extends AbstractEntityTest {
+ private EmbIdNaming ed_id1;
+ private EmbIdNaming ed_id2;
+ private EmbIdNaming ing_id1;
+
+ public void configure(Ejb3Configuration cfg) {
+ cfg.addAnnotatedClass(JoinEmbIdNamingRefEdEntity.class);
+ cfg.addAnnotatedClass(JoinEmbIdNamingRefIngEntity.class);
+ }
+
+ @BeforeClass(dependsOnMethods = "init")
+ public void initData() {
+ ed_id1 = new EmbIdNaming(10, 20);
+ ed_id2 = new EmbIdNaming(11, 21);
+ ing_id1 = new EmbIdNaming(12, 22);
+
+ JoinEmbIdNamingRefEdEntity ed1 = new JoinEmbIdNamingRefEdEntity(ed_id1, "data1");
+ JoinEmbIdNamingRefEdEntity ed2 = new JoinEmbIdNamingRefEdEntity(ed_id2, "data2");
+
+ JoinEmbIdNamingRefIngEntity ing1 = new JoinEmbIdNamingRefIngEntity(ing_id1, "x", ed1);
+
+ // Revision 1
+ EntityManager em = getEntityManager();
+ em.getTransaction().begin();
+
+ em.persist(ed1);
+ em.persist(ed2);
+ em.persist(ing1);
+
+ em.getTransaction().commit();
+
+ // Revision 2
+ em.getTransaction().begin();
+
+ ed2 = em.find(JoinEmbIdNamingRefEdEntity.class, ed2.getId());
+
+ ing1 = em.find(JoinEmbIdNamingRefIngEntity.class, ing1.getId());
+ ing1.setData("y");
+ ing1.setReference(ed2);
+
+ em.getTransaction().commit();
+ }
+
+ @Test
+ public void testRevisionsCounts() {
+ assert Arrays.asList(1, 2).equals(getVersionsReader().getRevisions(JoinEmbIdNamingRefEdEntity.class, ed_id1));
+ assert Arrays.asList(1, 2).equals(getVersionsReader().getRevisions(JoinEmbIdNamingRefEdEntity.class, ed_id2));
+ assert Arrays.asList(1, 2).equals(getVersionsReader().getRevisions(JoinEmbIdNamingRefIngEntity.class, ing_id1));
+ }
+
+ @Test
+ public void testHistoryOfEdId1() {
+ JoinEmbIdNamingRefEdEntity ver1 = new JoinEmbIdNamingRefEdEntity(ed_id1, "data1");
+
+ assert getVersionsReader().find(JoinEmbIdNamingRefEdEntity.class, ed_id1, 1).equals(ver1);
+ assert getVersionsReader().find(JoinEmbIdNamingRefEdEntity.class, ed_id1, 2).equals(ver1);
+ }
+
+ @Test
+ public void testHistoryOfEdId2() {
+ JoinEmbIdNamingRefEdEntity ver1 = new JoinEmbIdNamingRefEdEntity(ed_id2, "data2");
+
+ assert getVersionsReader().find(JoinEmbIdNamingRefEdEntity.class, ed_id2, 1).equals(ver1);
+ assert getVersionsReader().find(JoinEmbIdNamingRefEdEntity.class, ed_id2, 2).equals(ver1);
+ }
+
+ @Test
+ public void testHistoryOfIngId1() {
+ JoinEmbIdNamingRefIngEntity ver1 = new JoinEmbIdNamingRefIngEntity(ing_id1, "x", null);
+ JoinEmbIdNamingRefIngEntity ver2 = new JoinEmbIdNamingRefIngEntity(ing_id1, "y", null);
+
+ assert getVersionsReader().find(JoinEmbIdNamingRefIngEntity.class, ing_id1, 1).equals(ver1);
+ assert getVersionsReader().find(JoinEmbIdNamingRefIngEntity.class, ing_id1, 2).equals(ver2);
+
+ assert getVersionsReader().find(JoinEmbIdNamingRefIngEntity.class, ing_id1, 1).getReference().equals(
+ new JoinEmbIdNamingRefEdEntity(ed_id1, "data1"));
+ assert getVersionsReader().find(JoinEmbIdNamingRefIngEntity.class, ing_id1, 2).getReference().equals(
+ new JoinEmbIdNamingRefEdEntity(ed_id2, "data2"));
+ }
+
+ @SuppressWarnings({"unchecked"})
+ @Test
+ public void testJoinColumnNames() {
+ Iterator<Column> columns =
+ getCfg().getClassMapping("org.jboss.envers.test.integration.naming.ids.JoinEmbIdNamingRefIngEntity_versions")
+ .getProperty("reference").getColumnIterator();
+
+ boolean xxFound = false;
+ boolean yyFound = false;
+ while (columns.hasNext()) {
+ if ("XX_reference".equals(columns.next().getName())) {
+ xxFound = true;
+ }
+
+ if ("YY_reference".equals(columns.next().getName())) {
+ yyFound = true;
+ }
+ }
+
+ assert xxFound && yyFound;
+ }
+}
\ No newline at end of file
Added: core/trunk/envers/src/test/java/org/jboss/envers/test/integration/naming/ids/JoinEmbIdNamingRefEdEntity.java
===================================================================
--- core/trunk/envers/src/test/java/org/jboss/envers/test/integration/naming/ids/JoinEmbIdNamingRefEdEntity.java (rev 0)
+++ core/trunk/envers/src/test/java/org/jboss/envers/test/integration/naming/ids/JoinEmbIdNamingRefEdEntity.java 2008-10-27 18:56:31 UTC (rev 15406)
@@ -0,0 +1,83 @@
+package org.jboss.envers.test.integration.naming.ids;
+
+import org.jboss.envers.Versioned;
+
+import javax.persistence.*;
+import java.util.List;
+
+/**
+ * ReferencEd entity
+ * @author Adam Warski (adam at warski dot org)
+ */
+ at Entity
+public class JoinEmbIdNamingRefEdEntity {
+ @Id
+ @GeneratedValue
+ private EmbIdNaming id;
+
+ @Versioned
+ private String data;
+
+ @Versioned
+ @OneToMany(mappedBy="reference")
+ private List<JoinEmbIdNamingRefIngEntity> reffering;
+
+ public JoinEmbIdNamingRefEdEntity() {
+ }
+
+ public JoinEmbIdNamingRefEdEntity(EmbIdNaming id, String data) {
+ this.id = id;
+ this.data = data;
+ }
+
+ public JoinEmbIdNamingRefEdEntity(String data) {
+ this.data = data;
+ }
+
+ public EmbIdNaming getId() {
+ return id;
+ }
+
+ public void setId(EmbIdNaming id) {
+ this.id = id;
+ }
+
+ public String getData() {
+ return data;
+ }
+
+ public void setData(String data) {
+ this.data = data;
+ }
+
+ public List<JoinEmbIdNamingRefIngEntity> getReffering() {
+ return reffering;
+ }
+
+ public void setReffering(List<JoinEmbIdNamingRefIngEntity> reffering) {
+ this.reffering = reffering;
+ }
+
+ public boolean equals(Object o) {
+ if (this == o) return true;
+ if (!(o instanceof JoinEmbIdNamingRefEdEntity)) return false;
+
+ JoinEmbIdNamingRefEdEntity that = (JoinEmbIdNamingRefEdEntity) o;
+
+ if (data != null ? !data.equals(that.data) : that.data != null) return false;
+ if (id != null ? !id.equals(that.id) : that.id != null) return false;
+
+ return true;
+ }
+
+ public int hashCode() {
+ int result;
+ result = (id != null ? id.hashCode() : 0);
+ result = 31 * result + (data != null ? data.hashCode() : 0);
+ return result;
+ }
+
+ public String toString() {
+ return "JoinEmbIdNamingRefEdEntity(id = " + id + ", data = " + data + ")";
+ }
+}
\ No newline at end of file
Added: core/trunk/envers/src/test/java/org/jboss/envers/test/integration/naming/ids/JoinEmbIdNamingRefIngEntity.java
===================================================================
--- core/trunk/envers/src/test/java/org/jboss/envers/test/integration/naming/ids/JoinEmbIdNamingRefIngEntity.java (rev 0)
+++ core/trunk/envers/src/test/java/org/jboss/envers/test/integration/naming/ids/JoinEmbIdNamingRefIngEntity.java 2008-10-27 18:56:31 UTC (rev 15406)
@@ -0,0 +1,85 @@
+package org.jboss.envers.test.integration.naming.ids;
+
+import org.jboss.envers.Versioned;
+
+import javax.persistence.*;
+
+/**
+ * ReferencIng entity
+ * @author Adam Warski (adam at warski dot org)
+ */
+ at Entity
+public class JoinEmbIdNamingRefIngEntity {
+ @Id
+ @GeneratedValue
+ private EmbIdNaming id;
+
+ @Versioned
+ private String data;
+
+ @Versioned
+ @ManyToOne
+ @JoinColumns({@JoinColumn(name = "XX_reference", referencedColumnName = "XX"),
+ @JoinColumn(name = "YY_reference", referencedColumnName = "YY")})
+ private JoinEmbIdNamingRefEdEntity reference;
+
+ public JoinEmbIdNamingRefIngEntity() { }
+
+ public JoinEmbIdNamingRefIngEntity(EmbIdNaming id, String data, JoinEmbIdNamingRefEdEntity reference) {
+ this.id = id;
+ this.data = data;
+ this.reference = reference;
+ }
+
+ public JoinEmbIdNamingRefIngEntity(String data, JoinEmbIdNamingRefEdEntity reference) {
+ this.data = data;
+ this.reference = reference;
+ }
+
+ public EmbIdNaming getId() {
+ return id;
+ }
+
+ public void setId(EmbIdNaming id) {
+ this.id = id;
+ }
+
+ public String getData() {
+ return data;
+ }
+
+ public void setData(String data) {
+ this.data = data;
+ }
+
+ public JoinEmbIdNamingRefEdEntity getReference() {
+ return reference;
+ }
+
+ public void setReference(JoinEmbIdNamingRefEdEntity reference) {
+ this.reference = reference;
+ }
+
+ public boolean equals(Object o) {
+ if (this == o) return true;
+ if (!(o instanceof JoinEmbIdNamingRefIngEntity)) return false;
+
+ JoinEmbIdNamingRefIngEntity that = (JoinEmbIdNamingRefIngEntity) o;
+
+ if (data != null ? !data.equals(that.data) : that.data != null) return false;
+ if (id != null ? !id.equals(that.id) : that.id != null) return false;
+
+ return true;
+ }
+
+ public int hashCode() {
+ int result;
+ result = (id != null ? id.hashCode() : 0);
+ result = 31 * result + (data != null ? data.hashCode() : 0);
+ return result;
+ }
+
+ public String toString() {
+ return "JoinEmbIdNamingRefIngEntity(id = " + id + ", data = " + data + ")";
+ }
+}
\ No newline at end of file
Added: core/trunk/envers/src/test/java/org/jboss/envers/test/integration/naming/ids/JoinMulIdNaming.java
===================================================================
--- core/trunk/envers/src/test/java/org/jboss/envers/test/integration/naming/ids/JoinMulIdNaming.java (rev 0)
+++ core/trunk/envers/src/test/java/org/jboss/envers/test/integration/naming/ids/JoinMulIdNaming.java 2008-10-27 18:56:31 UTC (rev 15406)
@@ -0,0 +1,117 @@
+package org.jboss.envers.test.integration.naming.ids;
+
+import org.jboss.envers.test.AbstractEntityTest;
+import org.hibernate.ejb.Ejb3Configuration;
+import org.hibernate.mapping.Column;
+import org.testng.annotations.BeforeClass;
+import org.testng.annotations.Test;
+
+import javax.persistence.EntityManager;
+import java.util.Arrays;
+import java.util.Iterator;
+
+/**
+ * @author Adam Warski (adam at warski dot org)
+ */
+public class JoinMulIdNaming extends AbstractEntityTest {
+ private MulIdNaming ed_id1;
+ private MulIdNaming ed_id2;
+ private MulIdNaming ing_id1;
+
+ public void configure(Ejb3Configuration cfg) {
+ cfg.addAnnotatedClass(JoinMulIdNamingRefEdEntity.class);
+ cfg.addAnnotatedClass(JoinMulIdNamingRefIngEntity.class);
+ }
+
+ @BeforeClass(dependsOnMethods = "init")
+ public void initData() {
+ ed_id1 = new MulIdNaming(10, 20);
+ ed_id2 = new MulIdNaming(11, 21);
+ ing_id1 = new MulIdNaming(12, 22);
+
+ JoinMulIdNamingRefEdEntity ed1 = new JoinMulIdNamingRefEdEntity(ed_id1, "data1");
+ JoinMulIdNamingRefEdEntity ed2 = new JoinMulIdNamingRefEdEntity(ed_id2, "data2");
+
+ JoinMulIdNamingRefIngEntity ing1 = new JoinMulIdNamingRefIngEntity(ing_id1, "x", ed1);
+
+ // Revision 1
+ EntityManager em = getEntityManager();
+ em.getTransaction().begin();
+
+ em.persist(ed1);
+ em.persist(ed2);
+ em.persist(ing1);
+
+ em.getTransaction().commit();
+
+ // Revision 2
+ em.getTransaction().begin();
+
+ ed2 = em.find(JoinMulIdNamingRefEdEntity.class, ed_id2);
+
+ ing1 = em.find(JoinMulIdNamingRefIngEntity.class, ing_id1);
+ ing1.setData("y");
+ ing1.setReference(ed2);
+
+ em.getTransaction().commit();
+ }
+
+ @Test
+ public void testRevisionsCounts() {
+ assert Arrays.asList(1, 2).equals(getVersionsReader().getRevisions(JoinMulIdNamingRefEdEntity.class, ed_id1));
+ assert Arrays.asList(1, 2).equals(getVersionsReader().getRevisions(JoinMulIdNamingRefEdEntity.class, ed_id2));
+ assert Arrays.asList(1, 2).equals(getVersionsReader().getRevisions(JoinMulIdNamingRefIngEntity.class, ing_id1));
+ }
+
+ @Test
+ public void testHistoryOfEdId1() {
+ JoinMulIdNamingRefEdEntity ver1 = new JoinMulIdNamingRefEdEntity(ed_id1, "data1");
+
+ assert getVersionsReader().find(JoinMulIdNamingRefEdEntity.class, ed_id1, 1).equals(ver1);
+ assert getVersionsReader().find(JoinMulIdNamingRefEdEntity.class, ed_id1, 2).equals(ver1);
+ }
+
+ @Test
+ public void testHistoryOfEdId2() {
+ JoinMulIdNamingRefEdEntity ver1 = new JoinMulIdNamingRefEdEntity(ed_id2, "data2");
+
+ assert getVersionsReader().find(JoinMulIdNamingRefEdEntity.class, ed_id2, 1).equals(ver1);
+ assert getVersionsReader().find(JoinMulIdNamingRefEdEntity.class, ed_id2, 2).equals(ver1);
+ }
+
+ @Test
+ public void testHistoryOfIngId1() {
+ JoinMulIdNamingRefIngEntity ver1 = new JoinMulIdNamingRefIngEntity(ing_id1, "x", null);
+ JoinMulIdNamingRefIngEntity ver2 = new JoinMulIdNamingRefIngEntity(ing_id1, "y", null);
+
+ assert getVersionsReader().find(JoinMulIdNamingRefIngEntity.class, ing_id1, 1).equals(ver1);
+ assert getVersionsReader().find(JoinMulIdNamingRefIngEntity.class, ing_id1, 2).equals(ver2);
+
+ assert getVersionsReader().find(JoinMulIdNamingRefIngEntity.class, ing_id1, 1).getReference().equals(
+ new JoinMulIdNamingRefEdEntity(ed_id1, "data1"));
+ assert getVersionsReader().find(JoinMulIdNamingRefIngEntity.class, ing_id1, 2).getReference().equals(
+ new JoinMulIdNamingRefEdEntity(ed_id2, "data2"));
+ }
+
+ @SuppressWarnings({"unchecked"})
+ @Test
+ public void testJoinColumnNames() {
+ Iterator<Column> columns =
+ getCfg().getClassMapping("org.jboss.envers.test.integration.naming.ids.JoinMulIdNamingRefIngEntity_versions")
+ .getProperty("reference").getColumnIterator();
+
+ boolean id1Found = false;
+ boolean id2Found = false;
+ while (columns.hasNext()) {
+ if ("ID1_reference".equals(columns.next().getName())) {
+ id1Found = true;
+ }
+
+ if ("ID2_reference".equals(columns.next().getName())) {
+ id2Found = true;
+ }
+ }
+
+ assert id1Found && id2Found;
+ }
+}
\ No newline at end of file
Added: core/trunk/envers/src/test/java/org/jboss/envers/test/integration/naming/ids/JoinMulIdNamingRefEdEntity.java
===================================================================
--- core/trunk/envers/src/test/java/org/jboss/envers/test/integration/naming/ids/JoinMulIdNamingRefEdEntity.java (rev 0)
+++ core/trunk/envers/src/test/java/org/jboss/envers/test/integration/naming/ids/JoinMulIdNamingRefEdEntity.java 2008-10-27 18:56:31 UTC (rev 15406)
@@ -0,0 +1,97 @@
+package org.jboss.envers.test.integration.naming.ids;
+
+import org.jboss.envers.Versioned;
+
+import javax.persistence.*;
+import java.util.List;
+
+/**
+ * ReferencEd entity
+ * @author Adam Warski (adam at warski dot org)
+ */
+ at Entity
+ at IdClass(MulIdNaming.class)
+public class JoinMulIdNamingRefEdEntity {
+ @Id
+ private Integer id1;
+
+ @Id
+ private Integer id2;
+
+ @Versioned
+ private String data;
+
+ @Versioned
+ @OneToMany(mappedBy="reference")
+ private List<JoinMulIdNamingRefIngEntity> reffering;
+
+ public JoinMulIdNamingRefEdEntity() {
+ }
+
+ public JoinMulIdNamingRefEdEntity(MulIdNaming id, String data) {
+ this.id1 = id.getId1();
+ this.id2 = id.getId2();
+ this.data = data;
+ }
+
+ public JoinMulIdNamingRefEdEntity(String data) {
+ this.data = data;
+ }
+
+ public Integer getId1() {
+ return id1;
+ }
+
+ public void setId1(Integer id1) {
+ this.id1 = id1;
+ }
+
+ public Integer getId2() {
+ return id2;
+ }
+
+ public void setId2(Integer id2) {
+ this.id2 = id2;
+ }
+
+ public String getData() {
+ return data;
+ }
+
+ public void setData(String data) {
+ this.data = data;
+ }
+
+ public List<JoinMulIdNamingRefIngEntity> getReffering() {
+ return reffering;
+ }
+
+ public void setReffering(List<JoinMulIdNamingRefIngEntity> reffering) {
+ this.reffering = reffering;
+ }
+
+ public boolean equals(Object o) {
+ if (this == o) return true;
+ if (!(o instanceof JoinMulIdNamingRefEdEntity)) return false;
+
+ JoinMulIdNamingRefEdEntity that = (JoinMulIdNamingRefEdEntity) o;
+
+ if (data != null ? !data.equals(that.data) : that.data != null) return false;
+ if (id1 != null ? !id1.equals(that.id1) : that.id1 != null) return false;
+ if (id2 != null ? !id2.equals(that.id2) : that.id2 != null) return false;
+
+ return true;
+ }
+
+ public int hashCode() {
+ int result;
+ result = (id1 != null ? id1.hashCode() : 0);
+ result = 31 * result + (id2 != null ? id2.hashCode() : 0);
+ result = 31 * result + (data != null ? data.hashCode() : 0);
+ return result;
+ }
+
+ public String toString() {
+ return "JoinMulIdNamingRefEdEntity(id1 = " + id1 + ", id2 = " + id2 + ", data = " + data + ")";
+ }
+}
\ No newline at end of file
Added: core/trunk/envers/src/test/java/org/jboss/envers/test/integration/naming/ids/JoinMulIdNamingRefIngEntity.java
===================================================================
--- core/trunk/envers/src/test/java/org/jboss/envers/test/integration/naming/ids/JoinMulIdNamingRefIngEntity.java (rev 0)
+++ core/trunk/envers/src/test/java/org/jboss/envers/test/integration/naming/ids/JoinMulIdNamingRefIngEntity.java 2008-10-27 18:56:31 UTC (rev 15406)
@@ -0,0 +1,91 @@
+package org.jboss.envers.test.integration.naming.ids;
+
+import org.jboss.envers.Versioned;
+
+import javax.persistence.*;
+
+/**
+ * ReferencIng entity
+ * @author Adam Warski (adam at warski dot org)
+ */
+ at Entity
+ at IdClass(MulIdNaming.class)
+public class JoinMulIdNamingRefIngEntity {
+ @Id
+ private Integer id1;
+
+ @Id
+ private Integer id2;
+
+ @Versioned
+ private String data;
+
+ @Versioned
+ @ManyToOne
+ @JoinColumns({@JoinColumn(name = "ID2_reference", referencedColumnName = "ID_2"),
+ @JoinColumn(name = "ID1_reference", referencedColumnName = "ID_1")})
+ private JoinMulIdNamingRefEdEntity reference;
+
+ public JoinMulIdNamingRefIngEntity() { }
+
+ public JoinMulIdNamingRefIngEntity(MulIdNaming id, String data, JoinMulIdNamingRefEdEntity reference) {
+ this.id1 = id.getId1();
+ this.id2 = id.getId2();
+ this.data = data;
+ this.reference = reference;
+ }
+
+ public JoinMulIdNamingRefIngEntity(String data, JoinMulIdNamingRefEdEntity reference) {
+ this.data = data;
+ this.reference = reference;
+ }
+
+ public void setId1(Integer id1) {
+ this.id1 = id1;
+ }
+
+ public void setId2(Integer id2) {
+ this.id2 = id2;
+ }
+
+ public String getData() {
+ return data;
+ }
+
+ public void setData(String data) {
+ this.data = data;
+ }
+
+ public JoinMulIdNamingRefEdEntity getReference() {
+ return reference;
+ }
+
+ public void setReference(JoinMulIdNamingRefEdEntity reference) {
+ this.reference = reference;
+ }
+
+ public boolean equals(Object o) {
+ if (this == o) return true;
+ if (!(o instanceof JoinMulIdNamingRefIngEntity)) return false;
+
+ JoinMulIdNamingRefIngEntity that = (JoinMulIdNamingRefIngEntity) o;
+
+ if (data != null ? !data.equals(that.data) : that.data != null) return false;
+ if (id1 != null ? !id1.equals(that.id1) : that.id1 != null) return false;
+ if (id2 != null ? !id2.equals(that.id2) : that.id2 != null) return false;
+
+ return true;
+ }
+
+ public int hashCode() {
+ int result;
+ result = (id1 != null ? id1.hashCode() : 0);
+ result = 31 * result + (id2 != null ? id2.hashCode() : 0);
+ result = 31 * result + (data != null ? data.hashCode() : 0);
+ return result;
+ }
+
+ public String toString() {
+ return "JoinMulIdNamingRefIngEntity(id1 = " + id1 + ", id2 = " + id2 + ", data = " + data + ")";
+ }
+}
\ No newline at end of file
Added: core/trunk/envers/src/test/java/org/jboss/envers/test/integration/naming/ids/MulIdNaming.java
===================================================================
--- core/trunk/envers/src/test/java/org/jboss/envers/test/integration/naming/ids/MulIdNaming.java (rev 0)
+++ core/trunk/envers/src/test/java/org/jboss/envers/test/integration/naming/ids/MulIdNaming.java 2008-10-27 18:56:31 UTC (rev 15406)
@@ -0,0 +1,62 @@
+package org.jboss.envers.test.integration.naming.ids;
+
+import javax.persistence.Column;
+import java.io.Serializable;
+
+/**
+ * @author Adam Warski (adam at warski dot org)
+ */
+public class MulIdNaming implements Serializable {
+ @Column(name = "ID_1")
+ private Integer id1;
+
+ @Column(name = "ID_2")
+ private Integer id2;
+
+ public MulIdNaming() {
+ }
+
+ public MulIdNaming(Integer id1, Integer id2) {
+ this.id1 = id1;
+ this.id2 = id2;
+ }
+
+ public Integer getId1() {
+ return id1;
+ }
+
+ public void setId1(Integer id1) {
+ this.id1 = id1;
+ }
+
+ public Integer getId2() {
+ return id2;
+ }
+
+ public void setId2(Integer id2) {
+ this.id2 = id2;
+ }
+
+ public boolean equals(Object o) {
+ if (this == o) return true;
+ if (!(o instanceof MulIdNaming)) return false;
+
+ MulIdNaming mulId = (MulIdNaming) o;
+
+ if (id1 != null ? !id1.equals(mulId.id1) : mulId.id1 != null) return false;
+ if (id2 != null ? !id2.equals(mulId.id2) : mulId.id2 != null) return false;
+
+ return true;
+ }
+
+ public int hashCode() {
+ int result;
+ result = (id1 != null ? id1.hashCode() : 0);
+ result = 31 * result + (id2 != null ? id2.hashCode() : 0);
+ return result;
+ }
+
+ public String toString() {
+ return "MulIdNaming(" + id1 + ", " + id2 + ")";
+ }
+}
\ No newline at end of file
Added: core/trunk/envers/src/test/java/org/jboss/envers/test/integration/notinsertable/NotInsertable.java
===================================================================
--- core/trunk/envers/src/test/java/org/jboss/envers/test/integration/notinsertable/NotInsertable.java (rev 0)
+++ core/trunk/envers/src/test/java/org/jboss/envers/test/integration/notinsertable/NotInsertable.java 2008-10-27 18:56:31 UTC (rev 15406)
@@ -0,0 +1,49 @@
+package org.jboss.envers.test.integration.notinsertable;
+
+import org.jboss.envers.test.AbstractEntityTest;
+import org.hibernate.ejb.Ejb3Configuration;
+import org.testng.annotations.Test;
+import org.testng.annotations.BeforeClass;
+
+import javax.persistence.EntityManager;
+import java.util.Arrays;
+
+/**
+ * @author Adam Warski (adam at warski dot org)
+ */
+public class NotInsertable extends AbstractEntityTest {
+ private Integer id1;
+
+ public void configure(Ejb3Configuration cfg) {
+ cfg.addAnnotatedClass(NotInsertableTestEntity.class);
+ }
+
+ @BeforeClass(dependsOnMethods = "init")
+ public void initData() {
+ EntityManager em = getEntityManager();
+ em.getTransaction().begin();
+ NotInsertableTestEntity dte = new NotInsertableTestEntity("data1");
+ em.persist(dte);
+ id1 = dte.getId();
+ em.getTransaction().commit();
+
+ em.getTransaction().begin();
+ dte = em.find(NotInsertableTestEntity.class, id1);
+ dte.setData("data2");
+ em.getTransaction().commit();
+ }
+
+ @Test
+ public void testRevisionsCounts() {
+ assert Arrays.asList(1, 2).equals(getVersionsReader().getRevisions(NotInsertableTestEntity.class, id1));
+ }
+
+ @Test
+ public void testHistoryOfId1() {
+ NotInsertableTestEntity ver1 = new NotInsertableTestEntity(id1, "data1", "data1");
+ NotInsertableTestEntity ver2 = new NotInsertableTestEntity(id1, "data2", "data2");
+
+ assert getVersionsReader().find(NotInsertableTestEntity.class, id1, 1).equals(ver1);
+ assert getVersionsReader().find(NotInsertableTestEntity.class, id1, 2).equals(ver2);
+ }
+}
\ No newline at end of file
Added: core/trunk/envers/src/test/java/org/jboss/envers/test/integration/notinsertable/NotInsertableTestEntity.java
===================================================================
--- core/trunk/envers/src/test/java/org/jboss/envers/test/integration/notinsertable/NotInsertableTestEntity.java (rev 0)
+++ core/trunk/envers/src/test/java/org/jboss/envers/test/integration/notinsertable/NotInsertableTestEntity.java 2008-10-27 18:56:31 UTC (rev 15406)
@@ -0,0 +1,83 @@
+package org.jboss.envers.test.integration.notinsertable;
+
+import org.jboss.envers.Versioned;
+
+import javax.persistence.Entity;
+import javax.persistence.Id;
+import javax.persistence.GeneratedValue;
+import javax.persistence.Column;
+
+/**
+ * @author Adam Warski (adam at warski dot org)
+ */
+ at Entity
+ at Versioned
+public class NotInsertableTestEntity {
+ @Id
+ @GeneratedValue
+ private Integer id;
+
+ @Column(name = "data")
+ private String data;
+
+ @Column(name = "data", insertable = false, updatable = false)
+ private String dataCopy;
+
+ public NotInsertableTestEntity() {
+ }
+
+ public NotInsertableTestEntity(Integer id, String data, String dataCopy) {
+ this.id = id;
+ this.data = data;
+ this.dataCopy = dataCopy;
+ }
+
+ public NotInsertableTestEntity(String data) {
+ this.data = data;
+ }
+
+ public Integer getId() {
+ return id;
+ }
+
+ public void setId(Integer id) {
+ this.id = id;
+ }
+
+ public String getData() {
+ return data;
+ }
+
+ public void setData(String data) {
+ this.data = data;
+ }
+
+ public String getDataCopy() {
+ return dataCopy;
+ }
+
+ public void setDataCopy(String dataCopy) {
+ this.dataCopy = dataCopy;
+ }
+
+ public boolean equals(Object o) {
+ if (this == o) return true;
+ if (!(o instanceof NotInsertableTestEntity)) return false;
+
+ NotInsertableTestEntity that = (NotInsertableTestEntity) o;
+
+ if (data != null ? !data.equals(that.data) : that.data != null) return false;
+ if (dataCopy != null ? !dataCopy.equals(that.dataCopy) : that.dataCopy != null) return false;
+ if (id != null ? !id.equals(that.id) : that.id != null) return false;
+
+ return true;
+ }
+
+ public int hashCode() {
+ int result;
+ result = (id != null ? id.hashCode() : 0);
+ result = 31 * result + (data != null ? data.hashCode() : 0);
+ result = 31 * result + (dataCopy != null ? dataCopy.hashCode() : 0);
+ return result;
+ }
+}
\ No newline at end of file
Added: core/trunk/envers/src/test/java/org/jboss/envers/test/integration/onetomany/BasicCollection.java
===================================================================
--- core/trunk/envers/src/test/java/org/jboss/envers/test/integration/onetomany/BasicCollection.java (rev 0)
+++ core/trunk/envers/src/test/java/org/jboss/envers/test/integration/onetomany/BasicCollection.java 2008-10-27 18:56:31 UTC (rev 15406)
@@ -0,0 +1,163 @@
+package org.jboss.envers.test.integration.onetomany;
+
+import org.jboss.envers.test.AbstractEntityTest;
+import org.jboss.envers.test.entities.onetomany.CollectionRefEdEntity;
+import org.jboss.envers.test.entities.onetomany.CollectionRefIngEntity;
+import org.testng.annotations.BeforeClass;
+import org.testng.annotations.Test;
+import org.hibernate.ejb.Ejb3Configuration;
+
+import javax.persistence.EntityManager;
+import java.util.Arrays;
+import java.util.Set;
+import java.util.HashSet;
+import java.util.Collections;
+
+/**
+ * @author Adam Warski (adam at warski dot org)
+ */
+public class BasicCollection extends AbstractEntityTest {
+ private Integer ed1_id;
+ private Integer ed2_id;
+
+ private Integer ing1_id;
+ private Integer ing2_id;
+
+ public void configure(Ejb3Configuration cfg) {
+ cfg.addAnnotatedClass(CollectionRefEdEntity.class);
+ cfg.addAnnotatedClass(CollectionRefIngEntity.class);
+ }
+
+ @BeforeClass(dependsOnMethods = "init")
+ public void initData() {
+ EntityManager em = getEntityManager();
+
+ CollectionRefEdEntity ed1 = new CollectionRefEdEntity(1, "data_ed_1");
+ CollectionRefEdEntity ed2 = new CollectionRefEdEntity(2, "data_ed_2");
+
+ CollectionRefIngEntity ing1 = new CollectionRefIngEntity(3, "data_ing_1", ed1);
+ CollectionRefIngEntity ing2 = new CollectionRefIngEntity(4, "data_ing_2", ed1);
+
+ // Revision 1
+ em.getTransaction().begin();
+
+ em.persist(ed1);
+ em.persist(ed2);
+
+ em.persist(ing1);
+ em.persist(ing2);
+
+ em.getTransaction().commit();
+
+ // Revision 2
+ em.getTransaction().begin();
+
+ ing1 = em.find(CollectionRefIngEntity.class, ing1.getId());
+ ed2 = em.find(CollectionRefEdEntity.class, ed2.getId());
+
+ ing1.setReference(ed2);
+
+ em.getTransaction().commit();
+
+ // Revision 3
+ em.getTransaction().begin();
+
+ ing2 = em.find(CollectionRefIngEntity.class, ing2.getId());
+ ed2 = em.find(CollectionRefEdEntity.class, ed2.getId());
+
+ ing2.setReference(ed2);
+
+ em.getTransaction().commit();
+
+ //
+
+ ed1_id = ed1.getId();
+ ed2_id = ed2.getId();
+
+ ing1_id = ing1.getId();
+ ing2_id = ing2.getId();
+ }
+
+ @Test
+ public void testRevisionsCounts() {
+ assert Arrays.asList(1, 2, 3).equals(getVersionsReader().getRevisions(CollectionRefEdEntity.class, ed1_id));
+ assert Arrays.asList(1, 2, 3).equals(getVersionsReader().getRevisions(CollectionRefEdEntity.class, ed2_id));
+
+ assert Arrays.asList(1, 2).equals(getVersionsReader().getRevisions(CollectionRefIngEntity.class, ing1_id));
+ assert Arrays.asList(1, 3).equals(getVersionsReader().getRevisions(CollectionRefIngEntity.class, ing2_id));
+ }
+
+ private <T> Set<T> makeSet(T... objects) {
+ Set<T> ret = new HashSet<T>();
+ //noinspection ManualArrayToCollectionCopy
+ for (T obj : objects) { ret.add(obj); }
+ return ret;
+ }
+
+ @Test
+ public void testHistoryOfEdId1() {
+ CollectionRefIngEntity ing1 = getEntityManager().find(CollectionRefIngEntity.class, ing1_id);
+ CollectionRefIngEntity ing2 = getEntityManager().find(CollectionRefIngEntity.class, ing2_id);
+
+ CollectionRefEdEntity rev1 = getVersionsReader().find(CollectionRefEdEntity.class, ed1_id, 1);
+ CollectionRefEdEntity rev2 = getVersionsReader().find(CollectionRefEdEntity.class, ed1_id, 2);
+ CollectionRefEdEntity rev3 = getVersionsReader().find(CollectionRefEdEntity.class, ed1_id, 3);
+
+ assert rev1.getReffering().containsAll(makeSet(ing1, ing2));
+ assert rev1.getReffering().size() == 2;
+
+ assert rev2.getReffering().containsAll(makeSet(ing2));
+ assert rev2.getReffering().size() == 1;
+
+ assert rev3.getReffering().containsAll(Collections.EMPTY_SET);
+ assert rev3.getReffering().size() == 0;
+ }
+
+ @Test
+ public void testHistoryOfEdId2() {
+ CollectionRefIngEntity ing1 = getEntityManager().find(CollectionRefIngEntity.class, ing1_id);
+ CollectionRefIngEntity ing2 = getEntityManager().find(CollectionRefIngEntity.class, ing2_id);
+
+ CollectionRefEdEntity rev1 = getVersionsReader().find(CollectionRefEdEntity.class, ed2_id, 1);
+ CollectionRefEdEntity rev2 = getVersionsReader().find(CollectionRefEdEntity.class, ed2_id, 2);
+ CollectionRefEdEntity rev3 = getVersionsReader().find(CollectionRefEdEntity.class, ed2_id, 3);
+
+ assert rev1.getReffering().containsAll(Collections.EMPTY_SET);
+ assert rev1.getReffering().size() == 0;
+
+ assert rev2.getReffering().containsAll(makeSet(ing1));
+ assert rev2.getReffering().size() == 1;
+
+ assert rev3.getReffering().containsAll(makeSet(ing1, ing2));
+ assert rev3.getReffering().size() == 2;
+
+ }
+
+ @Test
+ public void testHistoryOfEdIng1() {
+ CollectionRefEdEntity ed1 = getEntityManager().find(CollectionRefEdEntity.class, ed1_id);
+ CollectionRefEdEntity ed2 = getEntityManager().find(CollectionRefEdEntity.class, ed2_id);
+
+ CollectionRefIngEntity rev1 = getVersionsReader().find(CollectionRefIngEntity.class, ing1_id, 1);
+ CollectionRefIngEntity rev2 = getVersionsReader().find(CollectionRefIngEntity.class, ing1_id, 2);
+ CollectionRefIngEntity rev3 = getVersionsReader().find(CollectionRefIngEntity.class, ing1_id, 3);
+
+ assert rev1.getReference().equals(ed1);
+ assert rev2.getReference().equals(ed2);
+ assert rev3.getReference().equals(ed2);
+ }
+
+ @Test
+ public void testHistoryOfEdIng2() {
+ CollectionRefEdEntity ed1 = getEntityManager().find(CollectionRefEdEntity.class, ed1_id);
+ CollectionRefEdEntity ed2 = getEntityManager().find(CollectionRefEdEntity.class, ed2_id);
+
+ CollectionRefIngEntity rev1 = getVersionsReader().find(CollectionRefIngEntity.class, ing2_id, 1);
+ CollectionRefIngEntity rev2 = getVersionsReader().find(CollectionRefIngEntity.class, ing2_id, 2);
+ CollectionRefIngEntity rev3 = getVersionsReader().find(CollectionRefIngEntity.class, ing2_id, 3);
+
+ assert rev1.getReference().equals(ed1);
+ assert rev2.getReference().equals(ed1);
+ assert rev3.getReference().equals(ed2);
+ }
+}
\ No newline at end of file
Added: core/trunk/envers/src/test/java/org/jboss/envers/test/integration/onetomany/BasicList.java
===================================================================
--- core/trunk/envers/src/test/java/org/jboss/envers/test/integration/onetomany/BasicList.java (rev 0)
+++ core/trunk/envers/src/test/java/org/jboss/envers/test/integration/onetomany/BasicList.java 2008-10-27 18:56:31 UTC (rev 15406)
@@ -0,0 +1,142 @@
+package org.jboss.envers.test.integration.onetomany;
+
+import org.jboss.envers.test.AbstractEntityTest;
+import org.jboss.envers.test.entities.onetomany.ListRefEdEntity;
+import org.jboss.envers.test.entities.onetomany.ListRefIngEntity;
+import org.jboss.envers.test.tools.TestTools;
+import org.testng.annotations.BeforeClass;
+import org.testng.annotations.Test;
+import org.hibernate.ejb.Ejb3Configuration;
+
+import javax.persistence.EntityManager;
+import java.util.*;
+
+/**
+ * @author Adam Warski (adam at warski dot org)
+ */
+public class BasicList extends AbstractEntityTest {
+ private Integer ed1_id;
+ private Integer ed2_id;
+
+ private Integer ing1_id;
+ private Integer ing2_id;
+
+ public void configure(Ejb3Configuration cfg) {
+ cfg.addAnnotatedClass(ListRefEdEntity.class);
+ cfg.addAnnotatedClass(ListRefIngEntity.class);
+ }
+
+ @BeforeClass(dependsOnMethods = "init")
+ public void initData() {
+ EntityManager em = getEntityManager();
+
+ ListRefEdEntity ed1 = new ListRefEdEntity(1, "data_ed_1");
+ ListRefEdEntity ed2 = new ListRefEdEntity(2, "data_ed_2");
+
+ ListRefIngEntity ing1 = new ListRefIngEntity(3, "data_ing_1", ed1);
+ ListRefIngEntity ing2 = new ListRefIngEntity(4, "data_ing_2", ed1);
+
+ // Revision 1
+ em.getTransaction().begin();
+
+ em.persist(ed1);
+ em.persist(ed2);
+
+ em.persist(ing1);
+ em.persist(ing2);
+
+ em.getTransaction().commit();
+
+ // Revision 2
+ em.getTransaction().begin();
+
+ ing1 = em.find(ListRefIngEntity.class, ing1.getId());
+ ed2 = em.find(ListRefEdEntity.class, ed2.getId());
+
+ ing1.setReference(ed2);
+
+ em.getTransaction().commit();
+
+ // Revision 3
+ em.getTransaction().begin();
+
+ ing2 = em.find(ListRefIngEntity.class, ing2.getId());
+ ed2 = em.find(ListRefEdEntity.class, ed2.getId());
+
+ ing2.setReference(ed2);
+
+ em.getTransaction().commit();
+
+ //
+
+ ed1_id = ed1.getId();
+ ed2_id = ed2.getId();
+
+ ing1_id = ing1.getId();
+ ing2_id = ing2.getId();
+ }
+
+ @Test
+ public void testRevisionsCounts() {
+ assert Arrays.asList(1, 2, 3).equals(getVersionsReader().getRevisions(ListRefEdEntity.class, ed1_id));
+ assert Arrays.asList(1, 2, 3).equals(getVersionsReader().getRevisions(ListRefEdEntity.class, ed2_id));
+
+ assert Arrays.asList(1, 2).equals(getVersionsReader().getRevisions(ListRefIngEntity.class, ing1_id));
+ assert Arrays.asList(1, 3).equals(getVersionsReader().getRevisions(ListRefIngEntity.class, ing2_id));
+ }
+ @Test
+ public void testHistoryOfEdId1() {
+ ListRefIngEntity ing1 = getEntityManager().find(ListRefIngEntity.class, ing1_id);
+ ListRefIngEntity ing2 = getEntityManager().find(ListRefIngEntity.class, ing2_id);
+
+ ListRefEdEntity rev1 = getVersionsReader().find(ListRefEdEntity.class, ed1_id, 1);
+ ListRefEdEntity rev2 = getVersionsReader().find(ListRefEdEntity.class, ed1_id, 2);
+ ListRefEdEntity rev3 = getVersionsReader().find(ListRefEdEntity.class, ed1_id, 3);
+
+ assert TestTools.checkList(rev1.getReffering(), ing1, ing2);
+ assert TestTools.checkList(rev2.getReffering(), ing2);
+ assert TestTools.checkList(rev3.getReffering());
+ }
+
+ @Test
+ public void testHistoryOfEdId2() {
+ ListRefIngEntity ing1 = getEntityManager().find(ListRefIngEntity.class, ing1_id);
+ ListRefIngEntity ing2 = getEntityManager().find(ListRefIngEntity.class, ing2_id);
+
+ ListRefEdEntity rev1 = getVersionsReader().find(ListRefEdEntity.class, ed2_id, 1);
+ ListRefEdEntity rev2 = getVersionsReader().find(ListRefEdEntity.class, ed2_id, 2);
+ ListRefEdEntity rev3 = getVersionsReader().find(ListRefEdEntity.class, ed2_id, 3);
+
+ assert TestTools.checkList(rev1.getReffering());
+ assert TestTools.checkList(rev2.getReffering(), ing1);
+ assert TestTools.checkList(rev3.getReffering(), ing1, ing2);
+ }
+
+ @Test
+ public void testHistoryOfEdIng1() {
+ ListRefEdEntity ed1 = getEntityManager().find(ListRefEdEntity.class, ed1_id);
+ ListRefEdEntity ed2 = getEntityManager().find(ListRefEdEntity.class, ed2_id);
+
+ ListRefIngEntity rev1 = getVersionsReader().find(ListRefIngEntity.class, ing1_id, 1);
+ ListRefIngEntity rev2 = getVersionsReader().find(ListRefIngEntity.class, ing1_id, 2);
+ ListRefIngEntity rev3 = getVersionsReader().find(ListRefIngEntity.class, ing1_id, 3);
+
+ assert rev1.getReference().equals(ed1);
+ assert rev2.getReference().equals(ed2);
+ assert rev3.getReference().equals(ed2);
+ }
+
+ @Test
+ public void testHistoryOfEdIng2() {
+ ListRefEdEntity ed1 = getEntityManager().find(ListRefEdEntity.class, ed1_id);
+ ListRefEdEntity ed2 = getEntityManager().find(ListRefEdEntity.class, ed2_id);
+
+ ListRefIngEntity rev1 = getVersionsReader().find(ListRefIngEntity.class, ing2_id, 1);
+ ListRefIngEntity rev2 = getVersionsReader().find(ListRefIngEntity.class, ing2_id, 2);
+ ListRefIngEntity rev3 = getVersionsReader().find(ListRefIngEntity.class, ing2_id, 3);
+
+ assert rev1.getReference().equals(ed1);
+ assert rev2.getReference().equals(ed1);
+ assert rev3.getReference().equals(ed2);
+ }
+}
\ No newline at end of file
Added: core/trunk/envers/src/test/java/org/jboss/envers/test/integration/onetomany/BasicSet.java
===================================================================
--- core/trunk/envers/src/test/java/org/jboss/envers/test/integration/onetomany/BasicSet.java (rev 0)
+++ core/trunk/envers/src/test/java/org/jboss/envers/test/integration/onetomany/BasicSet.java 2008-10-27 18:56:31 UTC (rev 15406)
@@ -0,0 +1,163 @@
+package org.jboss.envers.test.integration.onetomany;
+
+import org.jboss.envers.test.AbstractEntityTest;
+import org.jboss.envers.test.entities.onetomany.SetRefEdEntity;
+import org.jboss.envers.test.entities.onetomany.SetRefIngEntity;
+import org.jboss.envers.test.tools.TestTools;
+import org.testng.annotations.BeforeClass;
+import org.testng.annotations.Test;
+import org.hibernate.ejb.Ejb3Configuration;
+
+import javax.persistence.EntityManager;
+import java.util.Arrays;
+import java.util.Collections;
+
+/**
+ * @author Adam Warski (adam at warski dot org)
+ */
+public class BasicSet extends AbstractEntityTest {
+ private Integer ed1_id;
+ private Integer ed2_id;
+
+ private Integer ing1_id;
+ private Integer ing2_id;
+
+ public void configure(Ejb3Configuration cfg) {
+ cfg.addAnnotatedClass(SetRefEdEntity.class);
+ cfg.addAnnotatedClass(SetRefIngEntity.class);
+ }
+
+ @BeforeClass(dependsOnMethods = "init")
+ public void initData() {
+ EntityManager em = getEntityManager();
+
+ SetRefEdEntity ed1 = new SetRefEdEntity(1, "data_ed_1");
+ SetRefEdEntity ed2 = new SetRefEdEntity(2, "data_ed_2");
+
+ SetRefIngEntity ing1 = new SetRefIngEntity(3, "data_ing_1");
+ SetRefIngEntity ing2 = new SetRefIngEntity(4, "data_ing_2");
+
+ // Revision 1
+ em.getTransaction().begin();
+
+ em.persist(ed1);
+ em.persist(ed2);
+
+ em.getTransaction().commit();
+
+ // Revision 2
+
+ em.getTransaction().begin();
+
+ ed1 = em.find(SetRefEdEntity.class, ed1.getId());
+
+ ing1.setReference(ed1);
+ ing2.setReference(ed1);
+
+ em.persist(ing1);
+ em.persist(ing2);
+
+ em.getTransaction().commit();
+
+ // Revision 3
+ em.getTransaction().begin();
+
+ ing1 = em.find(SetRefIngEntity.class, ing1.getId());
+ ed2 = em.find(SetRefEdEntity.class, ed2.getId());
+
+ ing1.setReference(ed2);
+
+ em.getTransaction().commit();
+
+ // Revision 4
+ em.getTransaction().begin();
+
+ ing2 = em.find(SetRefIngEntity.class, ing2.getId());
+ ed2 = em.find(SetRefEdEntity.class, ed2.getId());
+
+ ing2.setReference(ed2);
+
+ em.getTransaction().commit();
+
+ //
+
+ ed1_id = ed1.getId();
+ ed2_id = ed2.getId();
+
+ ing1_id = ing1.getId();
+ ing2_id = ing2.getId();
+ }
+
+ @Test
+ public void testRevisionsCounts() {
+ assert Arrays.asList(1, 2, 3, 4).equals(getVersionsReader().getRevisions(SetRefEdEntity.class, ed1_id));
+ assert Arrays.asList(1, 3, 4).equals(getVersionsReader().getRevisions(SetRefEdEntity.class, ed2_id));
+
+ assert Arrays.asList(2, 3).equals(getVersionsReader().getRevisions(SetRefIngEntity.class, ing1_id));
+ assert Arrays.asList(2, 4).equals(getVersionsReader().getRevisions(SetRefIngEntity.class, ing2_id));
+ }
+
+ @Test
+ public void testHistoryOfEdId1() {
+ SetRefIngEntity ing1 = getEntityManager().find(SetRefIngEntity.class, ing1_id);
+ SetRefIngEntity ing2 = getEntityManager().find(SetRefIngEntity.class, ing2_id);
+
+ SetRefEdEntity rev1 = getVersionsReader().find(SetRefEdEntity.class, ed1_id, 1);
+ SetRefEdEntity rev2 = getVersionsReader().find(SetRefEdEntity.class, ed1_id, 2);
+ SetRefEdEntity rev3 = getVersionsReader().find(SetRefEdEntity.class, ed1_id, 3);
+ SetRefEdEntity rev4 = getVersionsReader().find(SetRefEdEntity.class, ed1_id, 4);
+
+ assert rev1.getReffering().equals(Collections.EMPTY_SET);
+ assert rev2.getReffering().equals(TestTools.makeSet(ing1, ing2));
+ assert rev3.getReffering().equals(TestTools.makeSet(ing2));
+ assert rev4.getReffering().equals(Collections.EMPTY_SET);
+ }
+
+ @Test
+ public void testHistoryOfEdId2() {
+ SetRefIngEntity ing1 = getEntityManager().find(SetRefIngEntity.class, ing1_id);
+ SetRefIngEntity ing2 = getEntityManager().find(SetRefIngEntity.class, ing2_id);
+
+ SetRefEdEntity rev1 = getVersionsReader().find(SetRefEdEntity.class, ed2_id, 1);
+ SetRefEdEntity rev2 = getVersionsReader().find(SetRefEdEntity.class, ed2_id, 2);
+ SetRefEdEntity rev3 = getVersionsReader().find(SetRefEdEntity.class, ed2_id, 3);
+ SetRefEdEntity rev4 = getVersionsReader().find(SetRefEdEntity.class, ed2_id, 4);
+
+ assert rev1.getReffering().equals(Collections.EMPTY_SET);
+ assert rev2.getReffering().equals(Collections.EMPTY_SET);
+ assert rev3.getReffering().equals(TestTools.makeSet(ing1));
+ assert rev4.getReffering().equals(TestTools.makeSet(ing1, ing2));
+ }
+
+ @Test
+ public void testHistoryOfEdIng1() {
+ SetRefEdEntity ed1 = getEntityManager().find(SetRefEdEntity.class, ed1_id);
+ SetRefEdEntity ed2 = getEntityManager().find(SetRefEdEntity.class, ed2_id);
+
+ SetRefIngEntity rev1 = getVersionsReader().find(SetRefIngEntity.class, ing1_id, 1);
+ SetRefIngEntity rev2 = getVersionsReader().find(SetRefIngEntity.class, ing1_id, 2);
+ SetRefIngEntity rev3 = getVersionsReader().find(SetRefIngEntity.class, ing1_id, 3);
+ SetRefIngEntity rev4 = getVersionsReader().find(SetRefIngEntity.class, ing1_id, 4);
+
+ assert rev1 == null;
+ assert rev2.getReference().equals(ed1);
+ assert rev3.getReference().equals(ed2);
+ assert rev4.getReference().equals(ed2);
+ }
+
+ @Test
+ public void testHistoryOfEdIng2() {
+ SetRefEdEntity ed1 = getEntityManager().find(SetRefEdEntity.class, ed1_id);
+ SetRefEdEntity ed2 = getEntityManager().find(SetRefEdEntity.class, ed2_id);
+
+ SetRefIngEntity rev1 = getVersionsReader().find(SetRefIngEntity.class, ing2_id, 1);
+ SetRefIngEntity rev2 = getVersionsReader().find(SetRefIngEntity.class, ing2_id, 2);
+ SetRefIngEntity rev3 = getVersionsReader().find(SetRefIngEntity.class, ing2_id, 3);
+ SetRefIngEntity rev4 = getVersionsReader().find(SetRefIngEntity.class, ing2_id, 4);
+
+ assert rev1 == null;
+ assert rev2.getReference().equals(ed1);
+ assert rev3.getReference().equals(ed1);
+ assert rev4.getReference().equals(ed2);
+ }
+}
Added: core/trunk/envers/src/test/java/org/jboss/envers/test/integration/onetomany/BasicSetWithEmbId.java
===================================================================
--- core/trunk/envers/src/test/java/org/jboss/envers/test/integration/onetomany/BasicSetWithEmbId.java (rev 0)
+++ core/trunk/envers/src/test/java/org/jboss/envers/test/integration/onetomany/BasicSetWithEmbId.java 2008-10-27 18:56:31 UTC (rev 15406)
@@ -0,0 +1,151 @@
+package org.jboss.envers.test.integration.onetomany;
+
+import org.jboss.envers.test.AbstractEntityTest;
+import org.jboss.envers.test.entities.ids.EmbId;
+import org.jboss.envers.test.entities.onetomany.ids.SetRefEdEmbIdEntity;
+import org.jboss.envers.test.entities.onetomany.ids.SetRefIngEmbIdEntity;
+import org.testng.annotations.BeforeClass;
+import org.testng.annotations.Test;
+import org.hibernate.ejb.Ejb3Configuration;
+
+import javax.persistence.EntityManager;
+import java.util.Arrays;
+import java.util.Set;
+import java.util.HashSet;
+import java.util.Collections;
+
+/**
+ * @author Adam Warski (adam at warski dot org)
+ */
+public class BasicSetWithEmbId extends AbstractEntityTest {
+ private EmbId ed1_id;
+ private EmbId ed2_id;
+
+ private EmbId ing1_id;
+ private EmbId ing2_id;
+
+ public void configure(Ejb3Configuration cfg) {
+ cfg.addAnnotatedClass(SetRefEdEmbIdEntity.class);
+ cfg.addAnnotatedClass(SetRefIngEmbIdEntity.class);
+ }
+
+ @BeforeClass(dependsOnMethods = "init")
+ public void initData() {
+ ed1_id = new EmbId(0, 1);
+ ed2_id = new EmbId(2, 3);
+
+ ing2_id = new EmbId(4, 5);
+ ing1_id = new EmbId(6, 7);
+
+ EntityManager em = getEntityManager();
+
+ SetRefEdEmbIdEntity ed1 = new SetRefEdEmbIdEntity(ed1_id, "data_ed_1");
+ SetRefEdEmbIdEntity ed2 = new SetRefEdEmbIdEntity(ed2_id, "data_ed_2");
+
+ SetRefIngEmbIdEntity ing1 = new SetRefIngEmbIdEntity(ing1_id, "data_ing_1", ed1);
+ SetRefIngEmbIdEntity ing2 = new SetRefIngEmbIdEntity(ing2_id, "data_ing_2", ed1);
+
+ // Revision 1
+ em.getTransaction().begin();
+
+ em.persist(ed1);
+ em.persist(ed2);
+
+ em.persist(ing1);
+ em.persist(ing2);
+
+ em.getTransaction().commit();
+
+ // Revision 2
+ em.getTransaction().begin();
+
+ ing1 = em.find(SetRefIngEmbIdEntity.class, ing1.getId());
+ ed2 = em.find(SetRefEdEmbIdEntity.class, ed2.getId());
+
+ ing1.setReference(ed2);
+
+ em.getTransaction().commit();
+
+ // Revision 3
+ em.getTransaction().begin();
+
+ ing2 = em.find(SetRefIngEmbIdEntity.class, ing2.getId());
+ ed2 = em.find(SetRefEdEmbIdEntity.class, ed2.getId());
+
+ ing2.setReference(ed2);
+
+ em.getTransaction().commit();
+ }
+
+ @Test
+ public void testRevisionsCounts() {
+ assert Arrays.asList(1, 2, 3).equals(getVersionsReader().getRevisions(SetRefEdEmbIdEntity.class, ed1_id));
+ assert Arrays.asList(1, 2, 3).equals(getVersionsReader().getRevisions(SetRefEdEmbIdEntity.class, ed2_id));
+
+ assert Arrays.asList(1, 2).equals(getVersionsReader().getRevisions(SetRefIngEmbIdEntity.class, ing1_id));
+ assert Arrays.asList(1, 3).equals(getVersionsReader().getRevisions(SetRefIngEmbIdEntity.class, ing2_id));
+ }
+
+ private <T> Set<T> makeSet(T... objects) {
+ Set<T> ret = new HashSet<T>();
+ //noinspection ManualArrayToCollectionCopy
+ for (T obj : objects) { ret.add(obj); }
+ return ret;
+ }
+
+ @Test
+ public void testHistoryOfEdId1() {
+ SetRefIngEmbIdEntity ing1 = getEntityManager().find(SetRefIngEmbIdEntity.class, ing1_id);
+ SetRefIngEmbIdEntity ing2 = getEntityManager().find(SetRefIngEmbIdEntity.class, ing2_id);
+
+ SetRefEdEmbIdEntity rev1 = getVersionsReader().find(SetRefEdEmbIdEntity.class, ed1_id, 1);
+ SetRefEdEmbIdEntity rev2 = getVersionsReader().find(SetRefEdEmbIdEntity.class, ed1_id, 2);
+ SetRefEdEmbIdEntity rev3 = getVersionsReader().find(SetRefEdEmbIdEntity.class, ed1_id, 3);
+
+ assert rev1.getReffering().equals(makeSet(ing1, ing2));
+ assert rev2.getReffering().equals(makeSet(ing2));
+ assert rev3.getReffering().equals(Collections.EMPTY_SET);
+ }
+
+ @Test
+ public void testHistoryOfEdId2() {
+ SetRefIngEmbIdEntity ing1 = getEntityManager().find(SetRefIngEmbIdEntity.class, ing1_id);
+ SetRefIngEmbIdEntity ing2 = getEntityManager().find(SetRefIngEmbIdEntity.class, ing2_id);
+
+ SetRefEdEmbIdEntity rev1 = getVersionsReader().find(SetRefEdEmbIdEntity.class, ed2_id, 1);
+ SetRefEdEmbIdEntity rev2 = getVersionsReader().find(SetRefEdEmbIdEntity.class, ed2_id, 2);
+ SetRefEdEmbIdEntity rev3 = getVersionsReader().find(SetRefEdEmbIdEntity.class, ed2_id, 3);
+
+ assert rev1.getReffering().equals(Collections.EMPTY_SET);
+ assert rev2.getReffering().equals(makeSet(ing1));
+ assert rev3.getReffering().equals(makeSet(ing1, ing2));
+ }
+
+ @Test
+ public void testHistoryOfEdIng1() {
+ SetRefEdEmbIdEntity ed1 = getEntityManager().find(SetRefEdEmbIdEntity.class, ed1_id);
+ SetRefEdEmbIdEntity ed2 = getEntityManager().find(SetRefEdEmbIdEntity.class, ed2_id);
+
+ SetRefIngEmbIdEntity rev1 = getVersionsReader().find(SetRefIngEmbIdEntity.class, ing1_id, 1);
+ SetRefIngEmbIdEntity rev2 = getVersionsReader().find(SetRefIngEmbIdEntity.class, ing1_id, 2);
+ SetRefIngEmbIdEntity rev3 = getVersionsReader().find(SetRefIngEmbIdEntity.class, ing1_id, 3);
+
+ assert rev1.getReference().equals(ed1);
+ assert rev2.getReference().equals(ed2);
+ assert rev3.getReference().equals(ed2);
+ }
+
+ @Test
+ public void testHistoryOfEdIng2() {
+ SetRefEdEmbIdEntity ed1 = getEntityManager().find(SetRefEdEmbIdEntity.class, ed1_id);
+ SetRefEdEmbIdEntity ed2 = getEntityManager().find(SetRefEdEmbIdEntity.class, ed2_id);
+
+ SetRefIngEmbIdEntity rev1 = getVersionsReader().find(SetRefIngEmbIdEntity.class, ing2_id, 1);
+ SetRefIngEmbIdEntity rev2 = getVersionsReader().find(SetRefIngEmbIdEntity.class, ing2_id, 2);
+ SetRefIngEmbIdEntity rev3 = getVersionsReader().find(SetRefIngEmbIdEntity.class, ing2_id, 3);
+
+ assert rev1.getReference().equals(ed1);
+ assert rev2.getReference().equals(ed1);
+ assert rev3.getReference().equals(ed2);
+ }
+}
\ No newline at end of file
Added: core/trunk/envers/src/test/java/org/jboss/envers/test/integration/onetomany/BasicSetWithMulId.java
===================================================================
--- core/trunk/envers/src/test/java/org/jboss/envers/test/integration/onetomany/BasicSetWithMulId.java (rev 0)
+++ core/trunk/envers/src/test/java/org/jboss/envers/test/integration/onetomany/BasicSetWithMulId.java 2008-10-27 18:56:31 UTC (rev 15406)
@@ -0,0 +1,151 @@
+package org.jboss.envers.test.integration.onetomany;
+
+import org.jboss.envers.test.AbstractEntityTest;
+import org.jboss.envers.test.entities.ids.MulId;
+import org.jboss.envers.test.entities.onetomany.ids.SetRefEdMulIdEntity;
+import org.jboss.envers.test.entities.onetomany.ids.SetRefIngMulIdEntity;
+import org.testng.annotations.BeforeClass;
+import org.testng.annotations.Test;
+import org.hibernate.ejb.Ejb3Configuration;
+
+import javax.persistence.EntityManager;
+import java.util.Arrays;
+import java.util.Set;
+import java.util.HashSet;
+import java.util.Collections;
+
+/**
+ * @author Adam Warski (adam at warski dot org)
+ */
+public class BasicSetWithMulId extends AbstractEntityTest {
+ private MulId ed1_id;
+ private MulId ed2_id;
+
+ private MulId ing1_id;
+ private MulId ing2_id;
+
+ public void configure(Ejb3Configuration cfg) {
+ cfg.addAnnotatedClass(SetRefEdMulIdEntity.class);
+ cfg.addAnnotatedClass(SetRefIngMulIdEntity.class);
+ }
+
+ @BeforeClass(dependsOnMethods = "init")
+ public void initData() {
+ ed1_id = new MulId(0, 1);
+ ed2_id = new MulId(2, 3);
+
+ ing2_id = new MulId(4, 5);
+ ing1_id = new MulId(6, 7);
+
+ EntityManager em = getEntityManager();
+
+ SetRefEdMulIdEntity ed1 = new SetRefEdMulIdEntity(ed1_id.getId1(), ed1_id.getId2(), "data_ed_1");
+ SetRefEdMulIdEntity ed2 = new SetRefEdMulIdEntity(ed2_id.getId1(), ed2_id.getId2(), "data_ed_2");
+
+ SetRefIngMulIdEntity ing1 = new SetRefIngMulIdEntity(ing1_id.getId1(), ing1_id.getId2(), "data_ing_1", ed1);
+ SetRefIngMulIdEntity ing2 = new SetRefIngMulIdEntity(ing2_id.getId1(), ing2_id.getId2(), "data_ing_2", ed1);
+
+ // Revision 1
+ em.getTransaction().begin();
+
+ em.persist(ed1);
+ em.persist(ed2);
+
+ em.persist(ing1);
+ em.persist(ing2);
+
+ em.getTransaction().commit();
+
+ // Revision 2
+ em.getTransaction().begin();
+
+ ing1 = em.find(SetRefIngMulIdEntity.class, ing1_id);
+ ed2 = em.find(SetRefEdMulIdEntity.class, ed2_id);
+
+ ing1.setReference(ed2);
+
+ em.getTransaction().commit();
+
+ // Revision 3
+ em.getTransaction().begin();
+
+ ing2 = em.find(SetRefIngMulIdEntity.class, ing2_id);
+ ed2 = em.find(SetRefEdMulIdEntity.class, ed2_id);
+
+ ing2.setReference(ed2);
+
+ em.getTransaction().commit();
+ }
+
+ @Test
+ public void testRevisionsCounts() {
+ assert Arrays.asList(1, 2, 3).equals(getVersionsReader().getRevisions(SetRefEdMulIdEntity.class, ed1_id));
+ assert Arrays.asList(1, 2, 3).equals(getVersionsReader().getRevisions(SetRefEdMulIdEntity.class, ed2_id));
+
+ assert Arrays.asList(1, 2).equals(getVersionsReader().getRevisions(SetRefIngMulIdEntity.class, ing1_id));
+ assert Arrays.asList(1, 3).equals(getVersionsReader().getRevisions(SetRefIngMulIdEntity.class, ing2_id));
+ }
+
+ private <T> Set<T> makeSet(T... objects) {
+ Set<T> ret = new HashSet<T>();
+ //noinspection ManualArrayToCollectionCopy
+ for (T obj : objects) { ret.add(obj); }
+ return ret;
+ }
+
+ @Test
+ public void testHistoryOfEdId1() {
+ SetRefIngMulIdEntity ing1 = getEntityManager().find(SetRefIngMulIdEntity.class, ing1_id);
+ SetRefIngMulIdEntity ing2 = getEntityManager().find(SetRefIngMulIdEntity.class, ing2_id);
+
+ SetRefEdMulIdEntity rev1 = getVersionsReader().find(SetRefEdMulIdEntity.class, ed1_id, 1);
+ SetRefEdMulIdEntity rev2 = getVersionsReader().find(SetRefEdMulIdEntity.class, ed1_id, 2);
+ SetRefEdMulIdEntity rev3 = getVersionsReader().find(SetRefEdMulIdEntity.class, ed1_id, 3);
+
+ assert rev1.getReffering().equals(makeSet(ing1, ing2));
+ assert rev2.getReffering().equals(makeSet(ing2));
+ assert rev3.getReffering().equals(Collections.EMPTY_SET);
+ }
+
+ @Test
+ public void testHistoryOfEdId2() {
+ SetRefIngMulIdEntity ing1 = getEntityManager().find(SetRefIngMulIdEntity.class, ing1_id);
+ SetRefIngMulIdEntity ing2 = getEntityManager().find(SetRefIngMulIdEntity.class, ing2_id);
+
+ SetRefEdMulIdEntity rev1 = getVersionsReader().find(SetRefEdMulIdEntity.class, ed2_id, 1);
+ SetRefEdMulIdEntity rev2 = getVersionsReader().find(SetRefEdMulIdEntity.class, ed2_id, 2);
+ SetRefEdMulIdEntity rev3 = getVersionsReader().find(SetRefEdMulIdEntity.class, ed2_id, 3);
+
+ assert rev1.getReffering().equals(Collections.EMPTY_SET);
+ assert rev2.getReffering().equals(makeSet(ing1));
+ assert rev3.getReffering().equals(makeSet(ing1, ing2));
+ }
+
+ @Test
+ public void testHistoryOfEdIng1() {
+ SetRefEdMulIdEntity ed1 = getEntityManager().find(SetRefEdMulIdEntity.class, ed1_id);
+ SetRefEdMulIdEntity ed2 = getEntityManager().find(SetRefEdMulIdEntity.class, ed2_id);
+
+ SetRefIngMulIdEntity rev1 = getVersionsReader().find(SetRefIngMulIdEntity.class, ing1_id, 1);
+ SetRefIngMulIdEntity rev2 = getVersionsReader().find(SetRefIngMulIdEntity.class, ing1_id, 2);
+ SetRefIngMulIdEntity rev3 = getVersionsReader().find(SetRefIngMulIdEntity.class, ing1_id, 3);
+
+ assert rev1.getReference().equals(ed1);
+ assert rev2.getReference().equals(ed2);
+ assert rev3.getReference().equals(ed2);
+ }
+
+ @Test
+ public void testHistoryOfEdIng2() {
+ SetRefEdMulIdEntity ed1 = getEntityManager().find(SetRefEdMulIdEntity.class, ed1_id);
+ SetRefEdMulIdEntity ed2 = getEntityManager().find(SetRefEdMulIdEntity.class, ed2_id);
+
+ SetRefIngMulIdEntity rev1 = getVersionsReader().find(SetRefIngMulIdEntity.class, ing2_id, 1);
+ SetRefIngMulIdEntity rev2 = getVersionsReader().find(SetRefIngMulIdEntity.class, ing2_id, 2);
+ SetRefIngMulIdEntity rev3 = getVersionsReader().find(SetRefIngMulIdEntity.class, ing2_id, 3);
+
+ assert rev1.getReference().equals(ed1);
+ assert rev2.getReference().equals(ed1);
+ assert rev3.getReference().equals(ed2);
+ }
+}
\ No newline at end of file
Added: core/trunk/envers/src/test/java/org/jboss/envers/test/integration/onetomany/BasicSetWithNullsDelete.java
===================================================================
--- core/trunk/envers/src/test/java/org/jboss/envers/test/integration/onetomany/BasicSetWithNullsDelete.java (rev 0)
+++ core/trunk/envers/src/test/java/org/jboss/envers/test/integration/onetomany/BasicSetWithNullsDelete.java 2008-10-27 18:56:31 UTC (rev 15406)
@@ -0,0 +1,227 @@
+package org.jboss.envers.test.integration.onetomany;
+
+import org.jboss.envers.test.AbstractEntityTest;
+import org.jboss.envers.test.entities.onetomany.SetRefEdEntity;
+import org.jboss.envers.test.entities.onetomany.SetRefIngEntity;
+import org.testng.annotations.BeforeClass;
+import org.testng.annotations.Test;
+import org.hibernate.ejb.Ejb3Configuration;
+
+import javax.persistence.EntityManager;
+import java.util.Arrays;
+import java.util.Set;
+import java.util.HashSet;
+import java.util.Collections;
+
+/**
+ * @author Adam Warski (adam at warski dot org)
+ */
+public class BasicSetWithNullsDelete extends AbstractEntityTest {
+ private Integer ed1_id;
+ private Integer ed2_id;
+
+ private Integer ing1_id;
+ private Integer ing2_id;
+ private Integer ing3_id;
+ private Integer ing4_id;
+
+ public void configure(Ejb3Configuration cfg) {
+ cfg.addAnnotatedClass(SetRefEdEntity.class);
+ cfg.addAnnotatedClass(SetRefIngEntity.class);
+ }
+
+ @BeforeClass(dependsOnMethods = "init")
+ public void initData() {
+ EntityManager em = getEntityManager();
+
+ SetRefEdEntity ed1 = new SetRefEdEntity(1, "data_ed_1");
+ SetRefEdEntity ed2 = new SetRefEdEntity(2, "data_ed_2");
+
+ SetRefIngEntity ing1 = new SetRefIngEntity(3, "data_ing_1", ed1);
+ SetRefIngEntity ing2 = new SetRefIngEntity(4, "data_ing_2", ed1);
+ SetRefIngEntity ing3 = new SetRefIngEntity(5, "data_ing_3", ed1);
+ SetRefIngEntity ing4 = new SetRefIngEntity(6, "data_ing_4", ed1);
+
+ // Revision 1
+ em.getTransaction().begin();
+
+ em.persist(ed1);
+ em.persist(ed2);
+
+ em.persist(ing1);
+ em.persist(ing2);
+ em.persist(ing3);
+ em.persist(ing4);
+
+ em.getTransaction().commit();
+
+ // Revision 2
+ em.getTransaction().begin();
+
+ ing1 = em.find(SetRefIngEntity.class, ing1.getId());
+
+ ing1.setReference(null);
+
+ em.getTransaction().commit();
+
+ // Revision 3
+ em.getTransaction().begin();
+
+ ing2 = em.find(SetRefIngEntity.class, ing2.getId());
+ em.remove(ing2);
+
+ em.getTransaction().commit();
+
+ // Revision 4
+ em.getTransaction().begin();
+
+ ing3 = em.find(SetRefIngEntity.class, ing3.getId());
+ ed2 = em.find(SetRefEdEntity.class, ed2.getId());
+ ing3.setReference(ed2);
+
+ em.getTransaction().commit();
+ // Revision 5
+ em.getTransaction().begin();
+
+ ing4 = em.find(SetRefIngEntity.class, ing4.getId());
+ ed1 = em.find(SetRefEdEntity.class, ed1.getId());
+ em.remove(ed1);
+ ing4.setReference(null);
+
+ em.getTransaction().commit();
+
+ //
+
+ ed1_id = ed1.getId();
+ ed2_id = ed2.getId();
+
+ ing1_id = ing1.getId();
+ ing2_id = ing2.getId();
+ ing3_id = ing3.getId();
+ ing4_id = ing4.getId();
+ }
+
+ @Test
+ public void testRevisionsCounts() {
+ assert Arrays.asList(1, 2, 3, 4, 5).equals(getVersionsReader().getRevisions(SetRefEdEntity.class, ed1_id));
+ assert Arrays.asList(1, 4).equals(getVersionsReader().getRevisions(SetRefEdEntity.class, ed2_id));
+
+ assert Arrays.asList(1, 2).equals(getVersionsReader().getRevisions(SetRefIngEntity.class, ing1_id));
+ assert Arrays.asList(1, 3).equals(getVersionsReader().getRevisions(SetRefIngEntity.class, ing2_id));
+ assert Arrays.asList(1, 4).equals(getVersionsReader().getRevisions(SetRefIngEntity.class, ing3_id));
+ assert Arrays.asList(1, 5).equals(getVersionsReader().getRevisions(SetRefIngEntity.class, ing4_id));
+ }
+
+ private <T> Set<T> makeSet(T... objects) {
+ Set<T> ret = new HashSet<T>();
+ //noinspection ManualArrayToCollectionCopy
+ for (T obj : objects) { ret.add(obj); }
+ return ret;
+ }
+
+ @Test
+ public void testHistoryOfEdId1() {
+ SetRefIngEntity ing1 = getEntityManager().find(SetRefIngEntity.class, ing1_id);
+ SetRefIngEntity ing2 = new SetRefIngEntity(4, "data_ing_2", new SetRefEdEntity(1, "data_ed_1"));
+ SetRefIngEntity ing3 = getEntityManager().find(SetRefIngEntity.class, ing3_id);
+ SetRefIngEntity ing4 = getEntityManager().find(SetRefIngEntity.class, ing4_id);
+
+ SetRefEdEntity rev1 = getVersionsReader().find(SetRefEdEntity.class, ed1_id, 1);
+ SetRefEdEntity rev2 = getVersionsReader().find(SetRefEdEntity.class, ed1_id, 2);
+ SetRefEdEntity rev3 = getVersionsReader().find(SetRefEdEntity.class, ed1_id, 3);
+ SetRefEdEntity rev4 = getVersionsReader().find(SetRefEdEntity.class, ed1_id, 4);
+ SetRefEdEntity rev5 = getVersionsReader().find(SetRefEdEntity.class, ed1_id, 5);
+
+ assert rev1.getReffering().equals(makeSet(ing1, ing2, ing3, ing4));
+ assert rev2.getReffering().equals(makeSet(ing2, ing3, ing4));
+ assert rev3.getReffering().equals(makeSet(ing3, ing4));
+ assert rev4.getReffering().equals(makeSet(ing4));
+ assert rev5 == null;
+ }
+
+ @Test
+ public void testHistoryOfEdId2() {
+ SetRefIngEntity ing3 = getEntityManager().find(SetRefIngEntity.class, ing3_id);
+
+ SetRefEdEntity rev1 = getVersionsReader().find(SetRefEdEntity.class, ed2_id, 1);
+ SetRefEdEntity rev2 = getVersionsReader().find(SetRefEdEntity.class, ed2_id, 2);
+ SetRefEdEntity rev3 = getVersionsReader().find(SetRefEdEntity.class, ed2_id, 3);
+ SetRefEdEntity rev4 = getVersionsReader().find(SetRefEdEntity.class, ed2_id, 4);
+ SetRefEdEntity rev5 = getVersionsReader().find(SetRefEdEntity.class, ed2_id, 5);
+
+ assert rev1.getReffering().equals(Collections.EMPTY_SET);
+ assert rev2.getReffering().equals(Collections.EMPTY_SET);
+ assert rev3.getReffering().equals(Collections.EMPTY_SET);
+ assert rev4.getReffering().equals(makeSet(ing3));
+ assert rev5.getReffering().equals(makeSet(ing3));
+ }
+
+ @Test
+ public void testHistoryOfEdIng1() {
+ SetRefEdEntity ed1 = new SetRefEdEntity(1, "data_ed_1");
+
+ SetRefIngEntity rev1 = getVersionsReader().find(SetRefIngEntity.class, ing1_id, 1);
+ SetRefIngEntity rev2 = getVersionsReader().find(SetRefIngEntity.class, ing1_id, 2);
+ SetRefIngEntity rev3 = getVersionsReader().find(SetRefIngEntity.class, ing1_id, 3);
+ SetRefIngEntity rev4 = getVersionsReader().find(SetRefIngEntity.class, ing1_id, 4);
+ SetRefIngEntity rev5 = getVersionsReader().find(SetRefIngEntity.class, ing1_id, 5);
+
+ assert rev1.getReference().equals(ed1);
+ assert rev2.getReference() == null;
+ assert rev3.getReference() == null;
+ assert rev4.getReference() == null;
+ assert rev5.getReference() == null;
+ }
+
+ @Test
+ public void testHistoryOfEdIng2() {
+ SetRefEdEntity ed1 = new SetRefEdEntity(1, "data_ed_1");
+
+ SetRefIngEntity rev1 = getVersionsReader().find(SetRefIngEntity.class, ing2_id, 1);
+ SetRefIngEntity rev2 = getVersionsReader().find(SetRefIngEntity.class, ing2_id, 2);
+ SetRefIngEntity rev3 = getVersionsReader().find(SetRefIngEntity.class, ing2_id, 3);
+ SetRefIngEntity rev4 = getVersionsReader().find(SetRefIngEntity.class, ing2_id, 4);
+ SetRefIngEntity rev5 = getVersionsReader().find(SetRefIngEntity.class, ing2_id, 5);
+
+ assert rev1.getReference().equals(ed1);
+ assert rev2.getReference().equals(ed1);
+ assert rev3 == null;
+ assert rev4 == null;
+ assert rev5 == null;
+ }
+
+ @Test
+ public void testHistoryOfEdIng3() {
+ SetRefEdEntity ed1 = new SetRefEdEntity(1, "data_ed_1");
+ SetRefEdEntity ed2 = new SetRefEdEntity(2, "data_ed_2");
+
+ SetRefIngEntity rev1 = getVersionsReader().find(SetRefIngEntity.class, ing3_id, 1);
+ SetRefIngEntity rev2 = getVersionsReader().find(SetRefIngEntity.class, ing3_id, 2);
+ SetRefIngEntity rev3 = getVersionsReader().find(SetRefIngEntity.class, ing3_id, 3);
+ SetRefIngEntity rev4 = getVersionsReader().find(SetRefIngEntity.class, ing3_id, 4);
+ SetRefIngEntity rev5 = getVersionsReader().find(SetRefIngEntity.class, ing3_id, 5);
+
+ assert rev1.getReference().equals(ed1);
+ assert rev2.getReference().equals(ed1);
+ assert rev3.getReference().equals(ed1);
+ assert rev4.getReference().equals(ed2);
+ assert rev5.getReference().equals(ed2);
+ }
+
+ @Test
+ public void testHistoryOfEdIng4() {
+ SetRefEdEntity ed1 = new SetRefEdEntity(1, "data_ed_1");
+
+ SetRefIngEntity rev1 = getVersionsReader().find(SetRefIngEntity.class, ing4_id, 1);
+ SetRefIngEntity rev2 = getVersionsReader().find(SetRefIngEntity.class, ing4_id, 2);
+ SetRefIngEntity rev3 = getVersionsReader().find(SetRefIngEntity.class, ing4_id, 3);
+ SetRefIngEntity rev4 = getVersionsReader().find(SetRefIngEntity.class, ing4_id, 4);
+ SetRefIngEntity rev5 = getVersionsReader().find(SetRefIngEntity.class, ing4_id, 5);
+
+ assert rev1.getReference().equals(ed1);
+ assert rev2.getReference().equals(ed1);
+ assert rev3.getReference().equals(ed1);
+ assert rev4.getReference().equals(ed1);
+ assert rev5.getReference() == null;
+ }
+}
Added: core/trunk/envers/src/test/java/org/jboss/envers/test/integration/onetomany/BidirectionalMapKey.java
===================================================================
--- core/trunk/envers/src/test/java/org/jboss/envers/test/integration/onetomany/BidirectionalMapKey.java (rev 0)
+++ core/trunk/envers/src/test/java/org/jboss/envers/test/integration/onetomany/BidirectionalMapKey.java 2008-10-27 18:56:31 UTC (rev 15406)
@@ -0,0 +1,86 @@
+package org.jboss.envers.test.integration.onetomany;
+
+import org.jboss.envers.test.AbstractEntityTest;
+import org.jboss.envers.test.tools.TestTools;
+import org.testng.annotations.BeforeClass;
+import org.testng.annotations.Test;
+import org.hibernate.ejb.Ejb3Configuration;
+
+import javax.persistence.EntityManager;
+import java.util.Arrays;
+
+/**
+ * @author Adam Warski (adam at warski dot org)
+ */
+public class BidirectionalMapKey extends AbstractEntityTest {
+ private Integer ed_id;
+
+ private Integer ing1_id;
+ private Integer ing2_id;
+
+ public void configure(Ejb3Configuration cfg) {
+ cfg.addAnnotatedClass(RefIngMapKeyEntity.class);
+ cfg.addAnnotatedClass(RefEdMapKeyEntity.class);
+ }
+
+ @BeforeClass(dependsOnMethods = "init")
+ public void initData() {
+ EntityManager em = getEntityManager();
+
+ // Revision 1 (intialy 1 relation: ing1 -> ed)
+ em.getTransaction().begin();
+
+ RefEdMapKeyEntity ed = new RefEdMapKeyEntity();
+
+ em.persist(ed);
+
+ RefIngMapKeyEntity ing1 = new RefIngMapKeyEntity();
+ ing1.setData("a");
+ ing1.setReference(ed);
+
+ RefIngMapKeyEntity ing2 = new RefIngMapKeyEntity();
+ ing2.setData("b");
+
+ em.persist(ing1);
+ em.persist(ing2);
+
+ em.getTransaction().commit();
+
+ // Revision 2 (adding second relation: ing2 -> ed)
+ em.getTransaction().begin();
+
+ ed = em.find(RefEdMapKeyEntity.class, ed.getId());
+ ing2 = em.find(RefIngMapKeyEntity.class, ing2.getId());
+
+ ing2.setReference(ed);
+
+ em.getTransaction().commit();
+
+ //
+
+ ed_id = ed.getId();
+
+ ing1_id = ing1.getId();
+ ing2_id = ing2.getId();
+ }
+
+ @Test
+ public void testRevisionsCounts() {
+ assert Arrays.asList(1, 2).equals(getVersionsReader().getRevisions(RefEdMapKeyEntity.class, ed_id));
+
+ assert Arrays.asList(1).equals(getVersionsReader().getRevisions(RefIngMapKeyEntity.class, ing1_id));
+ assert Arrays.asList(1, 2).equals(getVersionsReader().getRevisions(RefIngMapKeyEntity.class, ing2_id));
+ }
+
+ @Test
+ public void testHistoryOfEd() {
+ RefIngMapKeyEntity ing1 = getEntityManager().find(RefIngMapKeyEntity.class, ing1_id);
+ RefIngMapKeyEntity ing2 = getEntityManager().find(RefIngMapKeyEntity.class, ing2_id);
+
+ RefEdMapKeyEntity rev1 = getVersionsReader().find(RefEdMapKeyEntity.class, ed_id, 1);
+ RefEdMapKeyEntity rev2 = getVersionsReader().find(RefEdMapKeyEntity.class, ed_id, 2);
+
+ assert rev1.getIdmap().equals(TestTools.makeMap("a", ing1));
+ assert rev2.getIdmap().equals(TestTools.makeMap("a", ing1, "b", ing2));
+ }
+}
\ No newline at end of file
Added: core/trunk/envers/src/test/java/org/jboss/envers/test/integration/onetomany/RefEdMapKeyEntity.java
===================================================================
--- core/trunk/envers/src/test/java/org/jboss/envers/test/integration/onetomany/RefEdMapKeyEntity.java (rev 0)
+++ core/trunk/envers/src/test/java/org/jboss/envers/test/integration/onetomany/RefEdMapKeyEntity.java 2008-10-27 18:56:31 UTC (rev 15406)
@@ -0,0 +1,61 @@
+package org.jboss.envers.test.integration.onetomany;
+
+import org.jboss.envers.Versioned;
+
+import javax.persistence.*;
+import java.util.Map;
+import java.util.HashMap;
+
+/**
+ * @author Adam Warski (adam at warski dot org)
+ */
+ at Entity
+public class RefEdMapKeyEntity {
+ @Id
+ @GeneratedValue
+ private Integer id;
+
+ @Versioned
+ @OneToMany(mappedBy="reference")
+ @MapKey(name = "data")
+ private Map<String, RefIngMapKeyEntity> idmap;
+
+ public RefEdMapKeyEntity() {
+ idmap = new HashMap<String, RefIngMapKeyEntity>();
+ }
+
+ public Integer getId() {
+ return id;
+ }
+
+ public void setId(Integer id) {
+ this.id = id;
+ }
+
+ public Map<String, RefIngMapKeyEntity> getIdmap() {
+ return idmap;
+ }
+
+ public void setIdmap(Map<String, RefIngMapKeyEntity> idmap) {
+ this.idmap = idmap;
+ }
+
+ public boolean equals(Object o) {
+ if (this == o) return true;
+ if (!(o instanceof RefEdMapKeyEntity)) return false;
+
+ RefEdMapKeyEntity that = (RefEdMapKeyEntity) o;
+
+ if (id != null ? !id.equals(that.id) : that.id != null) return false;
+
+ return true;
+ }
+
+ public int hashCode() {
+ return (id != null ? id.hashCode() : 0);
+ }
+
+ public String toString() {
+ return "RedMKE(id = " + id + ", idmap = " + idmap + ")";
+ }
+}
\ No newline at end of file
Added: core/trunk/envers/src/test/java/org/jboss/envers/test/integration/onetomany/RefIngMapKeyEntity.java
===================================================================
--- core/trunk/envers/src/test/java/org/jboss/envers/test/integration/onetomany/RefIngMapKeyEntity.java (rev 0)
+++ core/trunk/envers/src/test/java/org/jboss/envers/test/integration/onetomany/RefIngMapKeyEntity.java 2008-10-27 18:56:31 UTC (rev 15406)
@@ -0,0 +1,65 @@
+package org.jboss.envers.test.integration.onetomany;
+
+import org.jboss.envers.Versioned;
+
+import javax.persistence.*;
+
+/**
+ * @author Adam Warski (adam at warski dot org)
+ */
+ at Entity
+public class RefIngMapKeyEntity {
+ @Id
+ @GeneratedValue
+ private Integer id;
+
+ @Versioned
+ @ManyToOne
+ private RefEdMapKeyEntity reference;
+
+ @Versioned
+ private String data;
+
+ public Integer getId() {
+ return id;
+ }
+
+ public void setId(Integer id) {
+ this.id = id;
+ }
+
+ public RefEdMapKeyEntity getReference() {
+ return reference;
+ }
+
+ public void setReference(RefEdMapKeyEntity reference) {
+ this.reference = reference;
+ }
+
+ public String getData() {
+ return data;
+ }
+
+ public void setData(String data) {
+ this.data = data;
+ }
+
+ public boolean equals(Object o) {
+ if (this == o) return true;
+ if (!(o instanceof RefIngMapKeyEntity)) return false;
+
+ RefIngMapKeyEntity that = (RefIngMapKeyEntity) o;
+
+ if (id != null ? !id.equals(that.id) : that.id != null) return false;
+
+ return true;
+ }
+
+ public int hashCode() {
+ return (id != null ? id.hashCode() : 0);
+ }
+
+ public String toString() {
+ return "RingMKE(id = " + id + ", data = " + data + ", reference = " + reference + ")";
+ }
+}
\ No newline at end of file
Added: core/trunk/envers/src/test/java/org/jboss/envers/test/integration/onetomany/detached/BasicDetachedList.java
===================================================================
--- core/trunk/envers/src/test/java/org/jboss/envers/test/integration/onetomany/detached/BasicDetachedList.java (rev 0)
+++ core/trunk/envers/src/test/java/org/jboss/envers/test/integration/onetomany/detached/BasicDetachedList.java 2008-10-27 18:56:31 UTC (rev 15406)
@@ -0,0 +1,115 @@
+package org.jboss.envers.test.integration.onetomany.detached;
+
+import org.jboss.envers.test.AbstractEntityTest;
+import org.jboss.envers.test.entities.onetomany.detached.ListRefCollEntity;
+import org.jboss.envers.test.entities.StrTestEntity;
+import org.jboss.envers.test.tools.TestTools;
+import org.hibernate.ejb.Ejb3Configuration;
+import org.testng.annotations.BeforeClass;
+import org.testng.annotations.Test;
+
+import javax.persistence.EntityManager;
+import java.util.Arrays;
+import java.util.ArrayList;
+
+/**
+ * @author Adam Warski (adam at warski dot org)
+ */
+public class BasicDetachedList extends AbstractEntityTest {
+ private Integer str1_id;
+ private Integer str2_id;
+
+ private Integer coll1_id;
+
+ public void configure(Ejb3Configuration cfg) {
+ cfg.addAnnotatedClass(StrTestEntity.class);
+ cfg.addAnnotatedClass(ListRefCollEntity.class);
+ }
+
+ @BeforeClass(dependsOnMethods = "init")
+ public void initData() {
+ EntityManager em = getEntityManager();
+
+ StrTestEntity str1 = new StrTestEntity("str1");
+ StrTestEntity str2 = new StrTestEntity("str2");
+
+ ListRefCollEntity coll1 = new ListRefCollEntity(3, "coll1");
+
+ // Revision 1
+ em.getTransaction().begin();
+
+ em.persist(str1);
+ em.persist(str2);
+
+ coll1.setCollection(new ArrayList<StrTestEntity>());
+ coll1.getCollection().add(str1);
+ em.persist(coll1);
+
+ em.getTransaction().commit();
+
+ // Revision 2
+ em.getTransaction().begin();
+
+ str2 = em.find(StrTestEntity.class, str2.getId());
+ coll1 = em.find(ListRefCollEntity.class, coll1.getId());
+
+ coll1.getCollection().add(str2);
+
+ em.getTransaction().commit();
+
+ // Revision 3
+ em.getTransaction().begin();
+
+ str1 = em.find(StrTestEntity.class, str1.getId());
+ coll1 = em.find(ListRefCollEntity.class, coll1.getId());
+
+ coll1.getCollection().remove(str1);
+
+ em.getTransaction().commit();
+
+ // Revision 4
+ em.getTransaction().begin();
+
+ coll1 = em.find(ListRefCollEntity.class, coll1.getId());
+
+ coll1.getCollection().clear();
+
+ em.getTransaction().commit();
+
+ //
+
+ str1_id = str1.getId();
+ str2_id = str2.getId();
+
+ coll1_id = coll1.getId();
+ }
+
+ @Test
+ public void testRevisionsCounts() {
+ assert Arrays.asList(1, 2, 3, 4).equals(getVersionsReader().getRevisions(ListRefCollEntity.class, coll1_id));
+
+ assert Arrays.asList(1).equals(getVersionsReader().getRevisions(StrTestEntity.class, str1_id));
+ assert Arrays.asList(1).equals(getVersionsReader().getRevisions(StrTestEntity.class, str2_id));
+ }
+
+ @Test
+ public void testHistoryOfColl1() {
+ StrTestEntity str1 = getEntityManager().find(StrTestEntity.class, str1_id);
+ StrTestEntity str2 = getEntityManager().find(StrTestEntity.class, str2_id);
+
+ ListRefCollEntity rev1 = getVersionsReader().find(ListRefCollEntity.class, coll1_id, 1);
+ ListRefCollEntity rev2 = getVersionsReader().find(ListRefCollEntity.class, coll1_id, 2);
+ ListRefCollEntity rev3 = getVersionsReader().find(ListRefCollEntity.class, coll1_id, 3);
+ ListRefCollEntity rev4 = getVersionsReader().find(ListRefCollEntity.class, coll1_id, 4);
+
+ assert TestTools.checkList(rev1.getCollection(), str1);
+ assert TestTools.checkList(rev2.getCollection(), str1, str2);
+ assert TestTools.checkList(rev3.getCollection(), str2);
+ assert TestTools.checkList(rev4.getCollection());
+
+ assert "coll1".equals(rev1.getData());
+ assert "coll1".equals(rev2.getData());
+ assert "coll1".equals(rev3.getData());
+ assert "coll1".equals(rev4.getData());
+ }
+}
\ No newline at end of file
Added: core/trunk/envers/src/test/java/org/jboss/envers/test/integration/onetomany/detached/BasicDetachedSet.java
===================================================================
--- core/trunk/envers/src/test/java/org/jboss/envers/test/integration/onetomany/detached/BasicDetachedSet.java (rev 0)
+++ core/trunk/envers/src/test/java/org/jboss/envers/test/integration/onetomany/detached/BasicDetachedSet.java 2008-10-27 18:56:31 UTC (rev 15406)
@@ -0,0 +1,115 @@
+package org.jboss.envers.test.integration.onetomany.detached;
+
+import org.jboss.envers.test.AbstractEntityTest;
+import org.jboss.envers.test.entities.onetomany.detached.SetRefCollEntity;
+import org.jboss.envers.test.entities.StrTestEntity;
+import org.jboss.envers.test.tools.TestTools;
+import org.hibernate.ejb.Ejb3Configuration;
+import org.testng.annotations.BeforeClass;
+import org.testng.annotations.Test;
+
+import javax.persistence.EntityManager;
+import java.util.Arrays;
+import java.util.HashSet;
+
+/**
+ * @author Adam Warski (adam at warski dot org)
+ */
+public class BasicDetachedSet extends AbstractEntityTest {
+ private Integer str1_id;
+ private Integer str2_id;
+
+ private Integer coll1_id;
+
+ public void configure(Ejb3Configuration cfg) {
+ cfg.addAnnotatedClass(StrTestEntity.class);
+ cfg.addAnnotatedClass(SetRefCollEntity.class);
+ }
+
+ @BeforeClass(dependsOnMethods = "init")
+ public void initData() {
+ EntityManager em = getEntityManager();
+
+ StrTestEntity str1 = new StrTestEntity("str1");
+ StrTestEntity str2 = new StrTestEntity("str2");
+
+ SetRefCollEntity coll1 = new SetRefCollEntity(3, "coll1");
+
+ // Revision 1
+ em.getTransaction().begin();
+
+ em.persist(str1);
+ em.persist(str2);
+
+ coll1.setCollection(new HashSet<StrTestEntity>());
+ coll1.getCollection().add(str1);
+ em.persist(coll1);
+
+ em.getTransaction().commit();
+
+ // Revision 2
+ em.getTransaction().begin();
+
+ str2 = em.find(StrTestEntity.class, str2.getId());
+ coll1 = em.find(SetRefCollEntity.class, coll1.getId());
+
+ coll1.getCollection().add(str2);
+
+ em.getTransaction().commit();
+
+ // Revision 3
+ em.getTransaction().begin();
+
+ str1 = em.find(StrTestEntity.class, str1.getId());
+ coll1 = em.find(SetRefCollEntity.class, coll1.getId());
+
+ coll1.getCollection().remove(str1);
+
+ em.getTransaction().commit();
+
+ // Revision 4
+ em.getTransaction().begin();
+
+ coll1 = em.find(SetRefCollEntity.class, coll1.getId());
+
+ coll1.getCollection().clear();
+
+ em.getTransaction().commit();
+
+ //
+
+ str1_id = str1.getId();
+ str2_id = str2.getId();
+
+ coll1_id = coll1.getId();
+ }
+
+ @Test
+ public void testRevisionsCounts() {
+ assert Arrays.asList(1, 2, 3, 4).equals(getVersionsReader().getRevisions(SetRefCollEntity.class, coll1_id));
+
+ assert Arrays.asList(1).equals(getVersionsReader().getRevisions(StrTestEntity.class, str1_id));
+ assert Arrays.asList(1).equals(getVersionsReader().getRevisions(StrTestEntity.class, str2_id));
+ }
+
+ @Test
+ public void testHistoryOfColl1() {
+ StrTestEntity str1 = getEntityManager().find(StrTestEntity.class, str1_id);
+ StrTestEntity str2 = getEntityManager().find(StrTestEntity.class, str2_id);
+
+ SetRefCollEntity rev1 = getVersionsReader().find(SetRefCollEntity.class, coll1_id, 1);
+ SetRefCollEntity rev2 = getVersionsReader().find(SetRefCollEntity.class, coll1_id, 2);
+ SetRefCollEntity rev3 = getVersionsReader().find(SetRefCollEntity.class, coll1_id, 3);
+ SetRefCollEntity rev4 = getVersionsReader().find(SetRefCollEntity.class, coll1_id, 4);
+
+ assert rev1.getCollection().equals(TestTools.makeSet(str1));
+ assert rev2.getCollection().equals(TestTools.makeSet(str1, str2));
+ assert rev3.getCollection().equals(TestTools.makeSet(str2));
+ assert rev4.getCollection().equals(TestTools.makeSet());
+
+ assert "coll1".equals(rev1.getData());
+ assert "coll1".equals(rev2.getData());
+ assert "coll1".equals(rev3.getData());
+ assert "coll1".equals(rev4.getData());
+ }
+}
Added: core/trunk/envers/src/test/java/org/jboss/envers/test/integration/onetomany/detached/BasicDetachedSetWithEmbId.java
===================================================================
--- core/trunk/envers/src/test/java/org/jboss/envers/test/integration/onetomany/detached/BasicDetachedSetWithEmbId.java (rev 0)
+++ core/trunk/envers/src/test/java/org/jboss/envers/test/integration/onetomany/detached/BasicDetachedSetWithEmbId.java 2008-10-27 18:56:31 UTC (rev 15406)
@@ -0,0 +1,114 @@
+package org.jboss.envers.test.integration.onetomany.detached;
+
+import org.jboss.envers.test.AbstractEntityTest;
+import org.jboss.envers.test.entities.onetomany.detached.ids.SetRefCollEntityEmbId;
+import org.jboss.envers.test.entities.ids.EmbIdTestEntity;
+import org.jboss.envers.test.entities.ids.EmbId;
+import org.jboss.envers.test.tools.TestTools;
+import org.hibernate.ejb.Ejb3Configuration;
+import org.testng.annotations.BeforeClass;
+import org.testng.annotations.Test;
+
+import javax.persistence.EntityManager;
+import java.util.Arrays;
+import java.util.HashSet;
+
+/**
+ * @author Adam Warski (adam at warski dot org)
+ */
+public class BasicDetachedSetWithEmbId extends AbstractEntityTest {
+ private EmbId str1_id;
+ private EmbId str2_id;
+
+ private EmbId coll1_id;
+
+ public void configure(Ejb3Configuration cfg) {
+ cfg.addAnnotatedClass(EmbIdTestEntity.class);
+ cfg.addAnnotatedClass(SetRefCollEntityEmbId.class);
+ }
+
+ @BeforeClass(dependsOnMethods = "init")
+ public void initData() {
+ EntityManager em = getEntityManager();
+
+ str1_id = new EmbId(1, 2);
+ str2_id = new EmbId(3, 4);
+
+ coll1_id = new EmbId(5, 6);
+
+ EmbIdTestEntity str1 = new EmbIdTestEntity(str1_id, "str1");
+ EmbIdTestEntity str2 = new EmbIdTestEntity(str2_id, "str2");
+
+ SetRefCollEntityEmbId coll1 = new SetRefCollEntityEmbId(coll1_id, "coll1");
+
+ // Revision 1
+ em.getTransaction().begin();
+
+ em.persist(str1);
+ em.persist(str2);
+
+ coll1.setCollection(new HashSet<EmbIdTestEntity>());
+ coll1.getCollection().add(str1);
+ em.persist(coll1);
+
+ em.getTransaction().commit();
+
+ // Revision 2
+ em.getTransaction().begin();
+
+ str2 = em.find(EmbIdTestEntity.class, str2.getId());
+ coll1 = em.find(SetRefCollEntityEmbId.class, coll1.getId());
+
+ coll1.getCollection().add(str2);
+
+ em.getTransaction().commit();
+
+ // Revision 3
+ em.getTransaction().begin();
+
+ str1 = em.find(EmbIdTestEntity.class, str1.getId());
+ coll1 = em.find(SetRefCollEntityEmbId.class, coll1.getId());
+
+ coll1.getCollection().remove(str1);
+
+ em.getTransaction().commit();
+
+ // Revision 4
+ em.getTransaction().begin();
+
+ coll1 = em.find(SetRefCollEntityEmbId.class, coll1.getId());
+
+ coll1.getCollection().clear();
+
+ em.getTransaction().commit();
+ }
+
+ @Test
+ public void testRevisionsCounts() {
+ assert Arrays.asList(1, 2, 3, 4).equals(getVersionsReader().getRevisions(SetRefCollEntityEmbId.class, coll1_id));
+
+ assert Arrays.asList(1).equals(getVersionsReader().getRevisions(EmbIdTestEntity.class, str1_id));
+ assert Arrays.asList(1).equals(getVersionsReader().getRevisions(EmbIdTestEntity.class, str2_id));
+ }
+
+ @Test
+ public void testHistoryOfColl1() {
+ EmbIdTestEntity str1 = getEntityManager().find(EmbIdTestEntity.class, str1_id);
+ EmbIdTestEntity str2 = getEntityManager().find(EmbIdTestEntity.class, str2_id);
+
+ SetRefCollEntityEmbId rev1 = getVersionsReader().find(SetRefCollEntityEmbId.class, coll1_id, 1);
+ SetRefCollEntityEmbId rev2 = getVersionsReader().find(SetRefCollEntityEmbId.class, coll1_id, 2);
+ SetRefCollEntityEmbId rev3 = getVersionsReader().find(SetRefCollEntityEmbId.class, coll1_id, 3);
+ SetRefCollEntityEmbId rev4 = getVersionsReader().find(SetRefCollEntityEmbId.class, coll1_id, 4);
+
+ assert rev1.getCollection().equals(TestTools.makeSet(str1));
+ assert rev2.getCollection().equals(TestTools.makeSet(str1, str2));
+ assert rev3.getCollection().equals(TestTools.makeSet(str2));
+ assert rev4.getCollection().equals(TestTools.makeSet());
+
+ assert "coll1".equals(rev1.getData());
+ assert "coll1".equals(rev2.getData());
+ assert "coll1".equals(rev3.getData());
+ assert "coll1".equals(rev4.getData());
+ }
+}
\ No newline at end of file
Added: core/trunk/envers/src/test/java/org/jboss/envers/test/integration/onetomany/detached/BasicDetachedSetWithMulId.java
===================================================================
--- core/trunk/envers/src/test/java/org/jboss/envers/test/integration/onetomany/detached/BasicDetachedSetWithMulId.java (rev 0)
+++ core/trunk/envers/src/test/java/org/jboss/envers/test/integration/onetomany/detached/BasicDetachedSetWithMulId.java 2008-10-27 18:56:31 UTC (rev 15406)
@@ -0,0 +1,114 @@
+package org.jboss.envers.test.integration.onetomany.detached;
+
+import org.jboss.envers.test.AbstractEntityTest;
+import org.jboss.envers.test.entities.onetomany.detached.ids.SetRefCollEntityMulId;
+import org.jboss.envers.test.entities.ids.MulIdTestEntity;
+import org.jboss.envers.test.entities.ids.MulId;
+import org.jboss.envers.test.tools.TestTools;
+import org.hibernate.ejb.Ejb3Configuration;
+import org.testng.annotations.BeforeClass;
+import org.testng.annotations.Test;
+
+import javax.persistence.EntityManager;
+import java.util.Arrays;
+import java.util.HashSet;
+
+/**
+ * @author Adam Warski (adam at warski dot org)
+ */
+public class BasicDetachedSetWithMulId extends AbstractEntityTest {
+ private MulId str1_id;
+ private MulId str2_id;
+
+ private MulId coll1_id;
+
+ public void configure(Ejb3Configuration cfg) {
+ cfg.addAnnotatedClass(MulIdTestEntity.class);
+ cfg.addAnnotatedClass(SetRefCollEntityMulId.class);
+ }
+
+ @BeforeClass(dependsOnMethods = "init")
+ public void initData() {
+ EntityManager em = getEntityManager();
+
+ str1_id = new MulId(1, 2);
+ str2_id = new MulId(3, 4);
+
+ coll1_id = new MulId(5, 6);
+
+ MulIdTestEntity str1 = new MulIdTestEntity(str1_id.getId1(), str1_id.getId2(), "str1");
+ MulIdTestEntity str2 = new MulIdTestEntity(str2_id.getId1(), str2_id.getId2(), "str2");
+
+ SetRefCollEntityMulId coll1 = new SetRefCollEntityMulId(coll1_id.getId1(), coll1_id.getId2(), "coll1");
+
+ // Revision 1
+ em.getTransaction().begin();
+
+ em.persist(str1);
+ em.persist(str2);
+
+ coll1.setCollection(new HashSet<MulIdTestEntity>());
+ coll1.getCollection().add(str1);
+ em.persist(coll1);
+
+ em.getTransaction().commit();
+
+ // Revision 2
+ em.getTransaction().begin();
+
+ str2 = em.find(MulIdTestEntity.class, str2_id);
+ coll1 = em.find(SetRefCollEntityMulId.class, coll1_id);
+
+ coll1.getCollection().add(str2);
+
+ em.getTransaction().commit();
+
+ // Revision 3
+ em.getTransaction().begin();
+
+ str1 = em.find(MulIdTestEntity.class, str1_id);
+ coll1 = em.find(SetRefCollEntityMulId.class, coll1_id);
+
+ coll1.getCollection().remove(str1);
+
+ em.getTransaction().commit();
+
+ // Revision 4
+ em.getTransaction().begin();
+
+ coll1 = em.find(SetRefCollEntityMulId.class, coll1_id);
+
+ coll1.getCollection().clear();
+
+ em.getTransaction().commit();
+ }
+
+ @Test
+ public void testRevisionsCounts() {
+ assert Arrays.asList(1, 2, 3, 4).equals(getVersionsReader().getRevisions(SetRefCollEntityMulId.class, coll1_id));
+
+ assert Arrays.asList(1).equals(getVersionsReader().getRevisions(MulIdTestEntity.class, str1_id));
+ assert Arrays.asList(1).equals(getVersionsReader().getRevisions(MulIdTestEntity.class, str2_id));
+ }
+
+ @Test
+ public void testHistoryOfColl1() {
+ MulIdTestEntity str1 = getEntityManager().find(MulIdTestEntity.class, str1_id);
+ MulIdTestEntity str2 = getEntityManager().find(MulIdTestEntity.class, str2_id);
+
+ SetRefCollEntityMulId rev1 = getVersionsReader().find(SetRefCollEntityMulId.class, coll1_id, 1);
+ SetRefCollEntityMulId rev2 = getVersionsReader().find(SetRefCollEntityMulId.class, coll1_id, 2);
+ SetRefCollEntityMulId rev3 = getVersionsReader().find(SetRefCollEntityMulId.class, coll1_id, 3);
+ SetRefCollEntityMulId rev4 = getVersionsReader().find(SetRefCollEntityMulId.class, coll1_id, 4);
+
+ assert rev1.getCollection().equals(TestTools.makeSet(str1));
+ assert rev2.getCollection().equals(TestTools.makeSet(str1, str2));
+ assert rev3.getCollection().equals(TestTools.makeSet(str2));
+ assert rev4.getCollection().equals(TestTools.makeSet());
+
+ assert "coll1".equals(rev1.getData());
+ assert "coll1".equals(rev2.getData());
+ assert "coll1".equals(rev3.getData());
+ assert "coll1".equals(rev4.getData());
+ }
+}
\ No newline at end of file
Added: core/trunk/envers/src/test/java/org/jboss/envers/test/integration/onetomany/detached/BasicJoinColumnSet.java
===================================================================
--- core/trunk/envers/src/test/java/org/jboss/envers/test/integration/onetomany/detached/BasicJoinColumnSet.java (rev 0)
+++ core/trunk/envers/src/test/java/org/jboss/envers/test/integration/onetomany/detached/BasicJoinColumnSet.java 2008-10-27 18:56:31 UTC (rev 15406)
@@ -0,0 +1,115 @@
+package org.jboss.envers.test.integration.onetomany.detached;
+
+import org.jboss.envers.test.AbstractEntityTest;
+import org.jboss.envers.test.entities.StrTestEntity;
+import org.jboss.envers.test.entities.onetomany.detached.SetJoinColumnRefCollEntity;
+import org.jboss.envers.test.tools.TestTools;
+import org.hibernate.ejb.Ejb3Configuration;
+import org.testng.annotations.BeforeClass;
+import org.testng.annotations.Test;
+
+import javax.persistence.EntityManager;
+import java.util.Arrays;
+import java.util.HashSet;
+
+/**
+ * @author Adam Warski (adam at warski dot org)
+ */
+public class BasicJoinColumnSet extends AbstractEntityTest {
+ private Integer str1_id;
+ private Integer str2_id;
+
+ private Integer coll1_id;
+
+ public void configure(Ejb3Configuration cfg) {
+ cfg.addAnnotatedClass(StrTestEntity.class);
+ cfg.addAnnotatedClass(SetJoinColumnRefCollEntity.class);
+ }
+
+ @BeforeClass(dependsOnMethods = "init")
+ public void initData() {
+ EntityManager em = getEntityManager();
+
+ StrTestEntity str1 = new StrTestEntity("str1");
+ StrTestEntity str2 = new StrTestEntity("str2");
+
+ SetJoinColumnRefCollEntity coll1 = new SetJoinColumnRefCollEntity(3, "coll1");
+
+ // Revision 1
+ em.getTransaction().begin();
+
+ em.persist(str1);
+ em.persist(str2);
+
+ coll1.setCollection(new HashSet<StrTestEntity>());
+ coll1.getCollection().add(str1);
+ em.persist(coll1);
+
+ em.getTransaction().commit();
+
+ // Revision 2
+ em.getTransaction().begin();
+
+ str2 = em.find(StrTestEntity.class, str2.getId());
+ coll1 = em.find(SetJoinColumnRefCollEntity.class, coll1.getId());
+
+ coll1.getCollection().add(str2);
+
+ em.getTransaction().commit();
+
+ // Revision 3
+ em.getTransaction().begin();
+
+ str1 = em.find(StrTestEntity.class, str1.getId());
+ coll1 = em.find(SetJoinColumnRefCollEntity.class, coll1.getId());
+
+ coll1.getCollection().remove(str1);
+
+ em.getTransaction().commit();
+
+ // Revision 4
+ em.getTransaction().begin();
+
+ coll1 = em.find(SetJoinColumnRefCollEntity.class, coll1.getId());
+
+ coll1.getCollection().clear();
+
+ em.getTransaction().commit();
+
+ //
+
+ str1_id = str1.getId();
+ str2_id = str2.getId();
+
+ coll1_id = coll1.getId();
+ }
+
+ @Test
+ public void testRevisionsCounts() {
+ assert Arrays.asList(1, 2, 3, 4).equals(getVersionsReader().getRevisions(SetJoinColumnRefCollEntity.class, coll1_id));
+
+ assert Arrays.asList(1).equals(getVersionsReader().getRevisions(StrTestEntity.class, str1_id));
+ assert Arrays.asList(1).equals(getVersionsReader().getRevisions(StrTestEntity.class, str2_id));
+ }
+
+ @Test
+ public void testHistoryOfColl1() {
+ StrTestEntity str1 = getEntityManager().find(StrTestEntity.class, str1_id);
+ StrTestEntity str2 = getEntityManager().find(StrTestEntity.class, str2_id);
+
+ SetJoinColumnRefCollEntity rev1 = getVersionsReader().find(SetJoinColumnRefCollEntity.class, coll1_id, 1);
+ SetJoinColumnRefCollEntity rev2 = getVersionsReader().find(SetJoinColumnRefCollEntity.class, coll1_id, 2);
+ SetJoinColumnRefCollEntity rev3 = getVersionsReader().find(SetJoinColumnRefCollEntity.class, coll1_id, 3);
+ SetJoinColumnRefCollEntity rev4 = getVersionsReader().find(SetJoinColumnRefCollEntity.class, coll1_id, 4);
+
+ assert rev1.getCollection().equals(TestTools.makeSet(str1));
+ assert rev2.getCollection().equals(TestTools.makeSet(str1, str2));
+ assert rev3.getCollection().equals(TestTools.makeSet(str2));
+ assert rev4.getCollection().equals(TestTools.makeSet());
+
+ assert "coll1".equals(rev1.getData());
+ assert "coll1".equals(rev2.getData());
+ assert "coll1".equals(rev3.getData());
+ assert "coll1".equals(rev4.getData());
+ }
+}
\ No newline at end of file
Added: core/trunk/envers/src/test/java/org/jboss/envers/test/integration/onetomany/detached/DataChangesDetachedSet.java
===================================================================
--- core/trunk/envers/src/test/java/org/jboss/envers/test/integration/onetomany/detached/DataChangesDetachedSet.java (rev 0)
+++ core/trunk/envers/src/test/java/org/jboss/envers/test/integration/onetomany/detached/DataChangesDetachedSet.java 2008-10-27 18:56:31 UTC (rev 15406)
@@ -0,0 +1,84 @@
+package org.jboss.envers.test.integration.onetomany.detached;
+
+import org.jboss.envers.test.AbstractEntityTest;
+import org.jboss.envers.test.entities.onetomany.detached.SetRefCollEntity;
+import org.jboss.envers.test.entities.StrTestEntity;
+import org.jboss.envers.test.tools.TestTools;
+import org.hibernate.ejb.Ejb3Configuration;
+import org.testng.annotations.BeforeClass;
+import org.testng.annotations.Test;
+
+import javax.persistence.EntityManager;
+import java.util.Arrays;
+import java.util.HashSet;
+
+/**
+ * @author Adam Warski (adam at warski dot org)
+ */
+public class DataChangesDetachedSet extends AbstractEntityTest {
+ private Integer str1_id;
+
+ private Integer coll1_id;
+
+ public void configure(Ejb3Configuration cfg) {
+ cfg.addAnnotatedClass(StrTestEntity.class);
+ cfg.addAnnotatedClass(SetRefCollEntity.class);
+ }
+
+ @BeforeClass(dependsOnMethods = "init")
+ public void initData() {
+ EntityManager em = getEntityManager();
+
+ StrTestEntity str1 = new StrTestEntity("str1");
+
+ SetRefCollEntity coll1 = new SetRefCollEntity(3, "coll1");
+
+ // Revision 1
+ em.getTransaction().begin();
+
+ em.persist(str1);
+
+ coll1.setCollection(new HashSet<StrTestEntity>());
+ em.persist(coll1);
+
+ em.getTransaction().commit();
+
+ // Revision 2
+ em.getTransaction().begin();
+
+ str1 = em.find(StrTestEntity.class, str1.getId());
+ coll1 = em.find(SetRefCollEntity.class, coll1.getId());
+
+ coll1.getCollection().add(str1);
+ coll1.setData("coll2");
+
+ em.getTransaction().commit();
+
+ //
+
+ str1_id = str1.getId();
+
+ coll1_id = coll1.getId();
+ }
+
+ @Test
+ public void testRevisionsCounts() {
+ assert Arrays.asList(1, 2).equals(getVersionsReader().getRevisions(SetRefCollEntity.class, coll1_id));
+
+ assert Arrays.asList(1).equals(getVersionsReader().getRevisions(StrTestEntity.class, str1_id));
+ }
+
+ @Test
+ public void testHistoryOfColl1() {
+ StrTestEntity str1 = getEntityManager().find(StrTestEntity.class, str1_id);
+
+ SetRefCollEntity rev1 = getVersionsReader().find(SetRefCollEntity.class, coll1_id, 1);
+ SetRefCollEntity rev2 = getVersionsReader().find(SetRefCollEntity.class, coll1_id, 2);
+
+ assert rev1.getCollection().equals(TestTools.makeSet());
+ assert rev2.getCollection().equals(TestTools.makeSet(str1));
+
+ assert "coll1".equals(rev1.getData());
+ assert "coll2".equals(rev2.getData());
+ }
+}
\ No newline at end of file
Added: core/trunk/envers/src/test/java/org/jboss/envers/test/integration/onetomany/detached/DoubleDetachedSet.java
===================================================================
--- core/trunk/envers/src/test/java/org/jboss/envers/test/integration/onetomany/detached/DoubleDetachedSet.java (rev 0)
+++ core/trunk/envers/src/test/java/org/jboss/envers/test/integration/onetomany/detached/DoubleDetachedSet.java 2008-10-27 18:56:31 UTC (rev 15406)
@@ -0,0 +1,108 @@
+package org.jboss.envers.test.integration.onetomany.detached;
+
+import org.jboss.envers.test.AbstractEntityTest;
+import org.jboss.envers.test.entities.onetomany.detached.DoubleSetRefCollEntity;
+import org.jboss.envers.test.entities.StrTestEntity;
+import org.jboss.envers.test.tools.TestTools;
+import org.hibernate.ejb.Ejb3Configuration;
+import org.testng.annotations.BeforeClass;
+import org.testng.annotations.Test;
+
+import javax.persistence.EntityManager;
+import java.util.Arrays;
+import java.util.HashSet;
+
+/**
+ * @author Adam Warski (adam at warski dot org)
+ */
+public class DoubleDetachedSet extends AbstractEntityTest {
+ private Integer str1_id;
+ private Integer str2_id;
+
+ private Integer coll1_id;
+
+ public void configure(Ejb3Configuration cfg) {
+ cfg.addAnnotatedClass(StrTestEntity.class);
+ cfg.addAnnotatedClass(DoubleSetRefCollEntity.class);
+ }
+
+ @BeforeClass(dependsOnMethods = "init")
+ public void initData() {
+ EntityManager em = getEntityManager();
+
+ StrTestEntity str1 = new StrTestEntity("str1");
+ StrTestEntity str2 = new StrTestEntity("str2");
+
+ DoubleSetRefCollEntity coll1 = new DoubleSetRefCollEntity(3, "coll1");
+
+ // Revision 1
+ em.getTransaction().begin();
+
+ em.persist(str1);
+ em.persist(str2);
+
+ coll1.setCollection(new HashSet<StrTestEntity>());
+ coll1.getCollection().add(str1);
+ em.persist(coll1);
+
+ coll1.setCollection2(new HashSet<StrTestEntity>());
+ coll1.getCollection2().add(str2);
+ em.persist(coll1);
+
+ em.getTransaction().commit();
+
+ // Revision 2
+ em.getTransaction().begin();
+
+ str2 = em.find(StrTestEntity.class, str2.getId());
+ coll1 = em.find(DoubleSetRefCollEntity.class, coll1.getId());
+
+ coll1.getCollection().add(str2);
+
+ em.getTransaction().commit();
+
+ // Revision 3
+ em.getTransaction().begin();
+
+ str1 = em.find(StrTestEntity.class, str1.getId());
+ coll1 = em.find(DoubleSetRefCollEntity.class, coll1.getId());
+
+ coll1.getCollection().remove(str1);
+ coll1.getCollection2().add(str1);
+
+ em.getTransaction().commit();
+
+ //
+
+ str1_id = str1.getId();
+ str2_id = str2.getId();
+
+ coll1_id = coll1.getId();
+ }
+
+ @Test
+ public void testRevisionsCounts() {
+ assert Arrays.asList(1, 2, 3).equals(getVersionsReader().getRevisions(DoubleSetRefCollEntity.class, coll1_id));
+
+ assert Arrays.asList(1).equals(getVersionsReader().getRevisions(StrTestEntity.class, str1_id));
+ assert Arrays.asList(1).equals(getVersionsReader().getRevisions(StrTestEntity.class, str2_id));
+ }
+
+ @Test
+ public void testHistoryOfColl1() {
+ StrTestEntity str1 = getEntityManager().find(StrTestEntity.class, str1_id);
+ StrTestEntity str2 = getEntityManager().find(StrTestEntity.class, str2_id);
+
+ DoubleSetRefCollEntity rev1 = getVersionsReader().find(DoubleSetRefCollEntity.class, coll1_id, 1);
+ DoubleSetRefCollEntity rev2 = getVersionsReader().find(DoubleSetRefCollEntity.class, coll1_id, 2);
+ DoubleSetRefCollEntity rev3 = getVersionsReader().find(DoubleSetRefCollEntity.class, coll1_id, 3);
+
+ assert rev1.getCollection().equals(TestTools.makeSet(str1));
+ assert rev2.getCollection().equals(TestTools.makeSet(str1, str2));
+ assert rev3.getCollection().equals(TestTools.makeSet(str2));
+
+ assert rev1.getCollection2().equals(TestTools.makeSet(str2));
+ assert rev2.getCollection2().equals(TestTools.makeSet(str2));
+ assert rev3.getCollection2().equals(TestTools.makeSet(str1, str2));
+ }
+}
\ No newline at end of file
Added: core/trunk/envers/src/test/java/org/jboss/envers/test/integration/onetoone/bidirectional/BiRefEdEntity.java
===================================================================
--- core/trunk/envers/src/test/java/org/jboss/envers/test/integration/onetoone/bidirectional/BiRefEdEntity.java (rev 0)
+++ core/trunk/envers/src/test/java/org/jboss/envers/test/integration/onetoone/bidirectional/BiRefEdEntity.java 2008-10-27 18:56:31 UTC (rev 15406)
@@ -0,0 +1,80 @@
+package org.jboss.envers.test.integration.onetoone.bidirectional;
+
+import org.jboss.envers.Versioned;
+
+import javax.persistence.Entity;
+import javax.persistence.OneToOne;
+import javax.persistence.Id;
+
+/**
+ * @author Adam Warski (adam at warski dot org)
+ */
+ at Entity
+public class BiRefEdEntity {
+ @Id
+ private Integer id;
+
+ @Versioned
+ private String data;
+
+ @Versioned
+ @OneToOne(mappedBy="reference")
+ private BiRefIngEntity referencing;
+
+ public BiRefEdEntity() {
+ }
+
+ public BiRefEdEntity(Integer id, String data) {
+ this.id = id;
+ this.data = data;
+ }
+
+ public BiRefEdEntity(Integer id, String data, BiRefIngEntity referencing) {
+ this.id = id;
+ this.data = data;
+ this.referencing = referencing;
+ }
+
+ public Integer getId() {
+ return id;
+ }
+
+ public void setId(Integer id) {
+ this.id = id;
+ }
+
+ public String getData() {
+ return data;
+ }
+
+ public void setData(String data) {
+ this.data = data;
+ }
+
+ public BiRefIngEntity getReferencing() {
+ return referencing;
+ }
+
+ public void setReferencing(BiRefIngEntity referencing) {
+ this.referencing = referencing;
+ }
+
+ public boolean equals(Object o) {
+ if (this == o) return true;
+ if (!(o instanceof BiRefEdEntity)) return false;
+
+ BiRefEdEntity that = (BiRefEdEntity) o;
+
+ if (data != null ? !data.equals(that.data) : that.data != null) return false;
+ if (id != null ? !id.equals(that.id) : that.id != null) return false;
+
+ return true;
+ }
+
+ public int hashCode() {
+ int result;
+ result = (id != null ? id.hashCode() : 0);
+ result = 31 * result + (data != null ? data.hashCode() : 0);
+ return result;
+ }
+}
Added: core/trunk/envers/src/test/java/org/jboss/envers/test/integration/onetoone/bidirectional/BiRefIngEntity.java
===================================================================
--- core/trunk/envers/src/test/java/org/jboss/envers/test/integration/onetoone/bidirectional/BiRefIngEntity.java (rev 0)
+++ core/trunk/envers/src/test/java/org/jboss/envers/test/integration/onetoone/bidirectional/BiRefIngEntity.java 2008-10-27 18:56:31 UTC (rev 15406)
@@ -0,0 +1,80 @@
+package org.jboss.envers.test.integration.onetoone.bidirectional;
+
+import org.jboss.envers.Versioned;
+
+import javax.persistence.Entity;
+import javax.persistence.Id;
+import javax.persistence.OneToOne;
+
+/**
+ * @author Adam Warski (adam at warski dot org)
+ */
+ at Entity
+public class BiRefIngEntity {
+ @Id
+ private Integer id;
+
+ @Versioned
+ private String data;
+
+ @Versioned
+ @OneToOne
+ private BiRefEdEntity reference;
+
+ public BiRefIngEntity() {
+ }
+
+ public BiRefIngEntity(Integer id, String data) {
+ this.id = id;
+ this.data = data;
+ }
+
+ public BiRefIngEntity(Integer id, String data, BiRefEdEntity reference) {
+ this.id = id;
+ this.data = data;
+ this.reference = reference;
+ }
+
+ public Integer getId() {
+ return id;
+ }
+
+ public void setId(Integer id) {
+ this.id = id;
+ }
+
+ public String getData() {
+ return data;
+ }
+
+ public void setData(String data) {
+ this.data = data;
+ }
+
+ public BiRefEdEntity getReference() {
+ return reference;
+ }
+
+ public void setReference(BiRefEdEntity reference) {
+ this.reference = reference;
+ }
+
+ public boolean equals(Object o) {
+ if (this == o) return true;
+ if (!(o instanceof BiRefIngEntity)) return false;
+
+ BiRefIngEntity that = (BiRefIngEntity) o;
+
+ if (data != null ? !data.equals(that.data) : that.data != null) return false;
+ if (id != null ? !id.equals(that.id) : that.id != null) return false;
+
+ return true;
+ }
+
+ public int hashCode() {
+ int result;
+ result = (id != null ? id.hashCode() : 0);
+ result = 31 * result + (data != null ? data.hashCode() : 0);
+ return result;
+ }
+}
Added: core/trunk/envers/src/test/java/org/jboss/envers/test/integration/onetoone/bidirectional/Bidirectional.java
===================================================================
--- core/trunk/envers/src/test/java/org/jboss/envers/test/integration/onetoone/bidirectional/Bidirectional.java (rev 0)
+++ core/trunk/envers/src/test/java/org/jboss/envers/test/integration/onetoone/bidirectional/Bidirectional.java 2008-10-27 18:56:31 UTC (rev 15406)
@@ -0,0 +1,92 @@
+package org.jboss.envers.test.integration.onetoone.bidirectional;
+
+import org.jboss.envers.test.AbstractEntityTest;
+import org.hibernate.ejb.Ejb3Configuration;
+import org.testng.annotations.BeforeClass;
+import org.testng.annotations.Test;
+
+import javax.persistence.EntityManager;
+import java.util.Arrays;
+
+/**
+ * @author Adam Warski (adam at warski dot org)
+ */
+public class Bidirectional extends AbstractEntityTest {
+ private Integer ed1_id;
+ private Integer ed2_id;
+
+ private Integer ing1_id;
+
+ public void configure(Ejb3Configuration cfg) {
+ cfg.addAnnotatedClass(BiRefEdEntity.class);
+ cfg.addAnnotatedClass(BiRefIngEntity.class);
+ }
+
+ @BeforeClass(dependsOnMethods = "init")
+ public void initData() {
+ BiRefEdEntity ed1 = new BiRefEdEntity(1, "data_ed_1");
+ BiRefEdEntity ed2 = new BiRefEdEntity(2, "data_ed_2");
+
+ BiRefIngEntity ing1 = new BiRefIngEntity(3, "data_ing_1");
+
+ // Revision 1
+ EntityManager em = getEntityManager();
+ em.getTransaction().begin();
+
+ ing1.setReference(ed1);
+
+ em.persist(ed1);
+ em.persist(ed2);
+
+ em.persist(ing1);
+
+ em.getTransaction().commit();
+
+ // Revision 2
+ em.getTransaction().begin();
+
+ ing1 = em.find(BiRefIngEntity.class, ing1.getId());
+ ed2 = em.find(BiRefEdEntity.class, ed2.getId());
+
+ ing1.setReference(ed2);
+
+ em.getTransaction().commit();
+
+ //
+
+ ed1_id = ed1.getId();
+ ed2_id = ed2.getId();
+
+ ing1_id = ing1.getId();
+ }
+
+ @Test
+ public void testRevisionsCounts() {
+ assert Arrays.asList(1, 2).equals(getVersionsReader().getRevisions(BiRefEdEntity.class, ed1_id));
+ assert Arrays.asList(1, 2).equals(getVersionsReader().getRevisions(BiRefEdEntity.class, ed2_id));
+
+ assert Arrays.asList(1, 2).equals(getVersionsReader().getRevisions(BiRefIngEntity.class, ing1_id));
+ }
+
+ @Test
+ public void testHistoryOfEdId1() {
+ BiRefIngEntity ing1 = getEntityManager().find(BiRefIngEntity.class, ing1_id);
+
+ BiRefEdEntity rev1 = getVersionsReader().find(BiRefEdEntity.class, ed1_id, 1);
+ BiRefEdEntity rev2 = getVersionsReader().find(BiRefEdEntity.class, ed1_id, 2);
+
+ assert rev1.getReferencing().equals(ing1);
+ assert rev2.getReferencing() == null;
+ }
+
+ @Test
+ public void testHistoryOfEdId2() {
+ BiRefIngEntity ing1 = getEntityManager().find(BiRefIngEntity.class, ing1_id);
+
+ BiRefEdEntity rev1 = getVersionsReader().find(BiRefEdEntity.class, ed2_id, 1);
+ BiRefEdEntity rev2 = getVersionsReader().find(BiRefEdEntity.class, ed2_id, 2);
+
+ assert rev1.getReferencing() == null;
+ assert rev2.getReferencing().equals(ing1);
+ }
+}
\ No newline at end of file
Added: core/trunk/envers/src/test/java/org/jboss/envers/test/integration/onetoone/bidirectional/Bidirectional2.java
===================================================================
--- core/trunk/envers/src/test/java/org/jboss/envers/test/integration/onetoone/bidirectional/Bidirectional2.java (rev 0)
+++ core/trunk/envers/src/test/java/org/jboss/envers/test/integration/onetoone/bidirectional/Bidirectional2.java 2008-10-27 18:56:31 UTC (rev 15406)
@@ -0,0 +1,127 @@
+package org.jboss.envers.test.integration.onetoone.bidirectional;
+
+import org.jboss.envers.test.AbstractEntityTest;
+import org.hibernate.ejb.Ejb3Configuration;
+import org.testng.annotations.BeforeClass;
+import org.testng.annotations.Test;
+
+import javax.persistence.EntityManager;
+import java.util.Arrays;
+
+/**
+ * @author Adam Warski (adam at warski dot org)
+ */
+public class Bidirectional2 extends AbstractEntityTest {
+ private Integer ed1_id;
+ private Integer ed2_id;
+
+ private Integer ing1_id;
+ private Integer ing2_id;
+
+ public void configure(Ejb3Configuration cfg) {
+ cfg.addAnnotatedClass(BiRefEdEntity.class);
+ cfg.addAnnotatedClass(BiRefIngEntity.class);
+ }
+
+ @BeforeClass(dependsOnMethods = "init")
+ public void initData() {
+ BiRefEdEntity ed1 = new BiRefEdEntity(1, "data_ed_1");
+ BiRefEdEntity ed2 = new BiRefEdEntity(2, "data_ed_2");
+
+ BiRefIngEntity ing1 = new BiRefIngEntity(3, "data_ing_1");
+ BiRefIngEntity ing2 = new BiRefIngEntity(4, "data_ing_2");
+
+ // Revision 1
+ EntityManager em = getEntityManager();
+ em.getTransaction().begin();
+
+ em.persist(ed1);
+ em.persist(ed2);
+
+ em.getTransaction().commit();
+
+ // Revision 2
+ em.getTransaction().begin();
+
+ ed1 = em.find(BiRefEdEntity.class, ed1.getId());
+
+ ing1.setReference(ed1);
+
+ em.persist(ing1);
+ em.persist(ing2);
+
+ em.getTransaction().commit();
+
+ // Revision 3
+ em.getTransaction().begin();
+
+ ed1 = em.find(BiRefEdEntity.class, ed1.getId());
+ ing1 = em.find(BiRefIngEntity.class, ing1.getId());
+ ing2 = em.find(BiRefIngEntity.class, ing2.getId());
+
+ ing1.setReference(null);
+ ing2.setReference(ed1);
+
+ em.getTransaction().commit();
+
+ // Revision 4
+ em.getTransaction().begin();
+
+ ed2 = em.find(BiRefEdEntity.class, ed2.getId());
+ ing1 = em.find(BiRefIngEntity.class, ing1.getId());
+ ing2 = em.find(BiRefIngEntity.class, ing2.getId());
+
+ ing1.setReference(ed2);
+ ing2.setReference(null);
+
+ em.getTransaction().commit();
+
+ //
+
+ ed1_id = ed1.getId();
+ ed2_id = ed2.getId();
+
+ ing1_id = ing1.getId();
+ ing2_id = ing2.getId();
+ }
+
+ @Test
+ public void testRevisionsCounts() {
+ assert Arrays.asList(1, 2, 3, 4).equals(getVersionsReader().getRevisions(BiRefEdEntity.class, ed1_id));
+ assert Arrays.asList(1, 4).equals(getVersionsReader().getRevisions(BiRefEdEntity.class, ed2_id));
+
+ assert Arrays.asList(2, 3, 4).equals(getVersionsReader().getRevisions(BiRefIngEntity.class, ing1_id));
+ assert Arrays.asList(2, 3, 4).equals(getVersionsReader().getRevisions(BiRefIngEntity.class, ing2_id));
+ }
+
+ @Test
+ public void testHistoryOfEdId1() {
+ BiRefIngEntity ing1 = getEntityManager().find(BiRefIngEntity.class, ing1_id);
+ BiRefIngEntity ing2 = getEntityManager().find(BiRefIngEntity.class, ing2_id);
+
+ BiRefEdEntity rev1 = getVersionsReader().find(BiRefEdEntity.class, ed1_id, 1);
+ BiRefEdEntity rev2 = getVersionsReader().find(BiRefEdEntity.class, ed1_id, 2);
+ BiRefEdEntity rev3 = getVersionsReader().find(BiRefEdEntity.class, ed1_id, 3);
+ BiRefEdEntity rev4 = getVersionsReader().find(BiRefEdEntity.class, ed1_id, 4);
+
+ assert rev1.getReferencing() == null;
+ assert rev2.getReferencing().equals(ing1);
+ assert rev3.getReferencing().equals(ing2);
+ assert rev4.getReferencing() == null;
+ }
+
+ @Test
+ public void testHistoryOfEdId2() {
+ BiRefIngEntity ing1 = getEntityManager().find(BiRefIngEntity.class, ing1_id);
+
+ BiRefEdEntity rev1 = getVersionsReader().find(BiRefEdEntity.class, ed2_id, 1);
+ BiRefEdEntity rev2 = getVersionsReader().find(BiRefEdEntity.class, ed2_id, 2);
+ BiRefEdEntity rev3 = getVersionsReader().find(BiRefEdEntity.class, ed2_id, 3);
+ BiRefEdEntity rev4 = getVersionsReader().find(BiRefEdEntity.class, ed2_id, 4);
+
+ assert rev1.getReferencing() == null;
+ assert rev2.getReferencing() == null;
+ assert rev3.getReferencing() == null;
+ assert rev4.getReferencing().equals(ing1);
+ }
+}
\ No newline at end of file
Added: core/trunk/envers/src/test/java/org/jboss/envers/test/integration/onetoone/bidirectional/BidirectionalNoNulls.java
===================================================================
--- core/trunk/envers/src/test/java/org/jboss/envers/test/integration/onetoone/bidirectional/BidirectionalNoNulls.java (rev 0)
+++ core/trunk/envers/src/test/java/org/jboss/envers/test/integration/onetoone/bidirectional/BidirectionalNoNulls.java 2008-10-27 18:56:31 UTC (rev 15406)
@@ -0,0 +1,105 @@
+package org.jboss.envers.test.integration.onetoone.bidirectional;
+
+import org.jboss.envers.test.AbstractEntityTest;
+import org.hibernate.ejb.Ejb3Configuration;
+import org.testng.annotations.BeforeClass;
+import org.testng.annotations.Test;
+
+import javax.persistence.EntityManager;
+import java.util.Arrays;
+
+/**
+ * @author Adam Warski (adam at warski dot org)
+ */
+public class BidirectionalNoNulls extends AbstractEntityTest {
+ private Integer ed1_id;
+ private Integer ed2_id;
+
+ private Integer ing1_id;
+ private Integer ing2_id;
+
+ public void configure(Ejb3Configuration cfg) {
+ cfg.addAnnotatedClass(BiRefEdEntity.class);
+ cfg.addAnnotatedClass(BiRefIngEntity.class);
+ }
+
+ @BeforeClass(dependsOnMethods = "init")
+ public void initData() {
+ BiRefEdEntity ed1 = new BiRefEdEntity(1, "data_ed_1");
+ BiRefEdEntity ed2 = new BiRefEdEntity(2, "data_ed_2");
+
+ BiRefIngEntity ing1 = new BiRefIngEntity(3, "data_ing_1");
+ BiRefIngEntity ing2 = new BiRefIngEntity(4, "data_ing_2");
+
+ // Revision 1
+ EntityManager em = getEntityManager();
+ em.getTransaction().begin();
+
+ ing1.setReference(ed1);
+ ing2.setReference(ed2);
+
+ em.persist(ed1);
+ em.persist(ed2);
+
+ em.persist(ing1);
+ em.persist(ing2);
+
+ em.getTransaction().commit();
+
+ // Revision 2
+ em = getEntityManager();
+ em.getTransaction().begin();
+
+ ing1 = em.find(BiRefIngEntity.class, ing1.getId());
+ ing2 = em.find(BiRefIngEntity.class, ing2.getId());
+
+ ed1 = em.find(BiRefEdEntity.class, ed1.getId());
+ ed2 = em.find(BiRefEdEntity.class, ed2.getId());
+
+ ing1.setReference(ed2);
+ ing2.setReference(ed1);
+
+ em.getTransaction().commit();
+
+ //
+
+ ed1_id = ed1.getId();
+ ed2_id = ed2.getId();
+
+ ing1_id = ing1.getId();
+ ing2_id = ing2.getId();
+ }
+
+ @Test
+ public void testRevisionsCounts() {
+ assert Arrays.asList(1, 2).equals(getVersionsReader().getRevisions(BiRefEdEntity.class, ed1_id));
+ assert Arrays.asList(1, 2).equals(getVersionsReader().getRevisions(BiRefEdEntity.class, ed2_id));
+
+ assert Arrays.asList(1, 2).equals(getVersionsReader().getRevisions(BiRefIngEntity.class, ing1_id));
+ assert Arrays.asList(1, 2).equals(getVersionsReader().getRevisions(BiRefIngEntity.class, ing2_id));
+ }
+
+ @Test
+ public void testHistoryOfEdId1() {
+ BiRefIngEntity ing1 = getEntityManager().find(BiRefIngEntity.class, ing1_id);
+ BiRefIngEntity ing2 = getEntityManager().find(BiRefIngEntity.class, ing2_id);
+
+ BiRefEdEntity rev1 = getVersionsReader().find(BiRefEdEntity.class, ed1_id, 1);
+ BiRefEdEntity rev2 = getVersionsReader().find(BiRefEdEntity.class, ed1_id, 2);
+
+ assert rev1.getReferencing().equals(ing1);
+ assert rev2.getReferencing().equals(ing2);
+ }
+
+ @Test
+ public void testHistoryOfEdId2() {
+ BiRefIngEntity ing1 = getEntityManager().find(BiRefIngEntity.class, ing1_id);
+ BiRefIngEntity ing2 = getEntityManager().find(BiRefIngEntity.class, ing2_id);
+
+ BiRefEdEntity rev1 = getVersionsReader().find(BiRefEdEntity.class, ed2_id, 1);
+ BiRefEdEntity rev2 = getVersionsReader().find(BiRefEdEntity.class, ed2_id, 2);
+
+ assert rev1.getReferencing().equals(ing2);
+ assert rev2.getReferencing().equals(ing1);
+ }
+}
Added: core/trunk/envers/src/test/java/org/jboss/envers/test/integration/onetoone/bidirectional/ids/BiEmbIdRefEdEntity.java
===================================================================
--- core/trunk/envers/src/test/java/org/jboss/envers/test/integration/onetoone/bidirectional/ids/BiEmbIdRefEdEntity.java (rev 0)
+++ core/trunk/envers/src/test/java/org/jboss/envers/test/integration/onetoone/bidirectional/ids/BiEmbIdRefEdEntity.java 2008-10-27 18:56:31 UTC (rev 15406)
@@ -0,0 +1,81 @@
+package org.jboss.envers.test.integration.onetoone.bidirectional.ids;
+
+import org.jboss.envers.Versioned;
+import org.jboss.envers.test.entities.ids.EmbId;
+
+import javax.persistence.Entity;
+import javax.persistence.OneToOne;
+import javax.persistence.EmbeddedId;
+
+/**
+ * @author Adam Warski (adam at warski dot org)
+ */
+ at Entity
+public class BiEmbIdRefEdEntity {
+ @EmbeddedId
+ private EmbId id;
+
+ @Versioned
+ private String data;
+
+ @Versioned
+ @OneToOne(mappedBy="reference")
+ private BiEmbIdRefIngEntity referencing;
+
+ public BiEmbIdRefEdEntity() {
+ }
+
+ public BiEmbIdRefEdEntity(EmbId id, String data) {
+ this.id = id;
+ this.data = data;
+ }
+
+ public BiEmbIdRefEdEntity(EmbId id, String data, BiEmbIdRefIngEntity referencing) {
+ this.id = id;
+ this.data = data;
+ this.referencing = referencing;
+ }
+
+ public EmbId getId() {
+ return id;
+ }
+
+ public void setId(EmbId id) {
+ this.id = id;
+ }
+
+ public String getData() {
+ return data;
+ }
+
+ public void setData(String data) {
+ this.data = data;
+ }
+
+ public BiEmbIdRefIngEntity getReferencing() {
+ return referencing;
+ }
+
+ public void setReferencing(BiEmbIdRefIngEntity referencing) {
+ this.referencing = referencing;
+ }
+
+ public boolean equals(Object o) {
+ if (this == o) return true;
+ if (!(o instanceof BiEmbIdRefEdEntity)) return false;
+
+ BiEmbIdRefEdEntity that = (BiEmbIdRefEdEntity) o;
+
+ if (data != null ? !data.equals(that.data) : that.data != null) return false;
+ if (id != null ? !id.equals(that.id) : that.id != null) return false;
+
+ return true;
+ }
+
+ public int hashCode() {
+ int result;
+ result = (id != null ? id.hashCode() : 0);
+ result = 31 * result + (data != null ? data.hashCode() : 0);
+ return result;
+ }
+}
\ No newline at end of file
Added: core/trunk/envers/src/test/java/org/jboss/envers/test/integration/onetoone/bidirectional/ids/BiEmbIdRefIngEntity.java
===================================================================
--- core/trunk/envers/src/test/java/org/jboss/envers/test/integration/onetoone/bidirectional/ids/BiEmbIdRefIngEntity.java (rev 0)
+++ core/trunk/envers/src/test/java/org/jboss/envers/test/integration/onetoone/bidirectional/ids/BiEmbIdRefIngEntity.java 2008-10-27 18:56:31 UTC (rev 15406)
@@ -0,0 +1,81 @@
+package org.jboss.envers.test.integration.onetoone.bidirectional.ids;
+
+import org.jboss.envers.Versioned;
+import org.jboss.envers.test.entities.ids.EmbId;
+
+import javax.persistence.Entity;
+import javax.persistence.OneToOne;
+import javax.persistence.EmbeddedId;
+
+/**
+ * @author Adam Warski (adam at warski dot org)
+ */
+ at Entity
+public class BiEmbIdRefIngEntity {
+ @EmbeddedId
+ private EmbId id;
+
+ @Versioned
+ private String data;
+
+ @Versioned
+ @OneToOne
+ private BiEmbIdRefEdEntity reference;
+
+ public BiEmbIdRefIngEntity() {
+ }
+
+ public BiEmbIdRefIngEntity(EmbId id, String data) {
+ this.id = id;
+ this.data = data;
+ }
+
+ public BiEmbIdRefIngEntity(EmbId id, String data, BiEmbIdRefEdEntity reference) {
+ this.id = id;
+ this.data = data;
+ this.reference = reference;
+ }
+
+ public EmbId getId() {
+ return id;
+ }
+
+ public void setId(EmbId id) {
+ this.id = id;
+ }
+
+ public String getData() {
+ return data;
+ }
+
+ public void setData(String data) {
+ this.data = data;
+ }
+
+ public BiEmbIdRefEdEntity getReference() {
+ return reference;
+ }
+
+ public void setReference(BiEmbIdRefEdEntity reference) {
+ this.reference = reference;
+ }
+
+ public boolean equals(Object o) {
+ if (this == o) return true;
+ if (!(o instanceof BiEmbIdRefIngEntity)) return false;
+
+ BiEmbIdRefIngEntity that = (BiEmbIdRefIngEntity) o;
+
+ if (data != null ? !data.equals(that.data) : that.data != null) return false;
+ if (id != null ? !id.equals(that.id) : that.id != null) return false;
+
+ return true;
+ }
+
+ public int hashCode() {
+ int result;
+ result = (id != null ? id.hashCode() : 0);
+ result = 31 * result + (data != null ? data.hashCode() : 0);
+ return result;
+ }
+}
\ No newline at end of file
Added: core/trunk/envers/src/test/java/org/jboss/envers/test/integration/onetoone/bidirectional/ids/BiMulIdRefEdEntity.java
===================================================================
--- core/trunk/envers/src/test/java/org/jboss/envers/test/integration/onetoone/bidirectional/ids/BiMulIdRefEdEntity.java (rev 0)
+++ core/trunk/envers/src/test/java/org/jboss/envers/test/integration/onetoone/bidirectional/ids/BiMulIdRefEdEntity.java 2008-10-27 18:56:31 UTC (rev 15406)
@@ -0,0 +1,88 @@
+package org.jboss.envers.test.integration.onetoone.bidirectional.ids;
+
+import org.jboss.envers.Versioned;
+import org.jboss.envers.test.entities.ids.MulId;
+
+import javax.persistence.*;
+
+/**
+ * @author Adam Warski (adam at warski dot org)
+ */
+ at Entity
+ at IdClass(MulId.class)
+public class BiMulIdRefEdEntity {
+ @Id
+ private Integer id1;
+
+ @Id
+ private Integer id2;
+
+ @Versioned
+ private String data;
+
+ @Versioned
+ @OneToOne(mappedBy="reference")
+ private BiMulIdRefIngEntity referencing;
+
+ public BiMulIdRefEdEntity() {
+ }
+
+ public BiMulIdRefEdEntity(Integer id1, Integer id2, String data) {
+ this.id1 = id1;
+ this.id2 = id2;
+ this.data = data;
+ }
+
+ public Integer getId1() {
+ return id1;
+ }
+
+ public void setId1(Integer id1) {
+ this.id1 = id1;
+ }
+
+ public Integer getId2() {
+ return id2;
+ }
+
+ public void setId2(Integer id2) {
+ this.id2 = id2;
+ }
+
+ public String getData() {
+ return data;
+ }
+
+ public void setData(String data) {
+ this.data = data;
+ }
+
+ public BiMulIdRefIngEntity getReferencing() {
+ return referencing;
+ }
+
+ public void setReferencing(BiMulIdRefIngEntity referencing) {
+ this.referencing = referencing;
+ }
+
+ public boolean equals(Object o) {
+ if (this == o) return true;
+ if (!(o instanceof BiMulIdRefEdEntity)) return false;
+
+ BiMulIdRefEdEntity that = (BiMulIdRefEdEntity) o;
+
+ if (data != null ? !data.equals(that.data) : that.data != null) return false;
+ if (id1 != null ? !id1.equals(that.id1) : that.id1 != null) return false;
+ if (id2 != null ? !id2.equals(that.id2) : that.id2 != null) return false;
+
+ return true;
+ }
+
+ public int hashCode() {
+ int result;
+ result = (id1 != null ? id1.hashCode() : 0);
+ result = 31 * result + (id2 != null ? id2.hashCode() : 0);
+ result = 31 * result + (data != null ? data.hashCode() : 0);
+ return result;
+ }
+}
\ No newline at end of file
Added: core/trunk/envers/src/test/java/org/jboss/envers/test/integration/onetoone/bidirectional/ids/BiMulIdRefIngEntity.java
===================================================================
--- core/trunk/envers/src/test/java/org/jboss/envers/test/integration/onetoone/bidirectional/ids/BiMulIdRefIngEntity.java (rev 0)
+++ core/trunk/envers/src/test/java/org/jboss/envers/test/integration/onetoone/bidirectional/ids/BiMulIdRefIngEntity.java 2008-10-27 18:56:31 UTC (rev 15406)
@@ -0,0 +1,88 @@
+package org.jboss.envers.test.integration.onetoone.bidirectional.ids;
+
+import org.jboss.envers.Versioned;
+import org.jboss.envers.test.entities.ids.MulId;
+
+import javax.persistence.*;
+
+/**
+ * @author Adam Warski (adam at warski dot org)
+ */
+ at Entity
+ at IdClass(MulId.class)
+public class BiMulIdRefIngEntity {
+ @Id
+ private Integer id1;
+
+ @Id
+ private Integer id2;
+
+ @Versioned
+ private String data;
+
+ @Versioned
+ @OneToOne
+ private BiMulIdRefEdEntity reference;
+
+ public BiMulIdRefIngEntity() {
+ }
+
+ public BiMulIdRefIngEntity(Integer id1, Integer id2, String data) {
+ this.id1 = id1;
+ this.id2 = id2;
+ this.data = data;
+ }
+
+ public Integer getId1() {
+ return id1;
+ }
+
+ public void setId1(Integer id1) {
+ this.id1 = id1;
+ }
+
+ public Integer getId2() {
+ return id2;
+ }
+
+ public void setId2(Integer id2) {
+ this.id2 = id2;
+ }
+
+ public String getData() {
+ return data;
+ }
+
+ public void setData(String data) {
+ this.data = data;
+ }
+
+ public BiMulIdRefEdEntity getReference() {
+ return reference;
+ }
+
+ public void setReference(BiMulIdRefEdEntity reference) {
+ this.reference = reference;
+ }
+
+ public boolean equals(Object o) {
+ if (this == o) return true;
+ if (!(o instanceof BiMulIdRefIngEntity)) return false;
+
+ BiMulIdRefIngEntity that = (BiMulIdRefIngEntity) o;
+
+ if (data != null ? !data.equals(that.data) : that.data != null) return false;
+ if (id1 != null ? !id1.equals(that.id1) : that.id1 != null) return false;
+ if (id2 != null ? !id2.equals(that.id2) : that.id2 != null) return false;
+
+ return true;
+ }
+
+ public int hashCode() {
+ int result;
+ result = (id1 != null ? id1.hashCode() : 0);
+ result = 31 * result + (id2 != null ? id2.hashCode() : 0);
+ result = 31 * result + (data != null ? data.hashCode() : 0);
+ return result;
+ }
+}
\ No newline at end of file
Added: core/trunk/envers/src/test/java/org/jboss/envers/test/integration/onetoone/bidirectional/ids/EmbIdBidirectional.java
===================================================================
--- core/trunk/envers/src/test/java/org/jboss/envers/test/integration/onetoone/bidirectional/ids/EmbIdBidirectional.java (rev 0)
+++ core/trunk/envers/src/test/java/org/jboss/envers/test/integration/onetoone/bidirectional/ids/EmbIdBidirectional.java 2008-10-27 18:56:31 UTC (rev 15406)
@@ -0,0 +1,103 @@
+package org.jboss.envers.test.integration.onetoone.bidirectional.ids;
+
+import org.jboss.envers.test.AbstractEntityTest;
+import org.jboss.envers.test.entities.ids.EmbId;
+import org.hibernate.ejb.Ejb3Configuration;
+import org.testng.annotations.BeforeClass;
+import org.testng.annotations.Test;
+
+import javax.persistence.EntityManager;
+import java.util.Arrays;
+
+/**
+ * @author Adam Warski (adam at warski dot org)
+ */
+public class EmbIdBidirectional extends AbstractEntityTest {
+ private EmbId ed1_id;
+ private EmbId ed2_id;
+
+ private EmbId ing1_id;
+
+ public void configure(Ejb3Configuration cfg) {
+ cfg.addAnnotatedClass(BiEmbIdRefEdEntity.class);
+ cfg.addAnnotatedClass(BiEmbIdRefIngEntity.class);
+ }
+
+ @BeforeClass(dependsOnMethods = "init")
+ public void initData() {
+ ed1_id = new EmbId(1, 2);
+ ed2_id = new EmbId(3, 4);
+
+ ing1_id = new EmbId(5, 6);
+
+ BiEmbIdRefEdEntity ed1 = new BiEmbIdRefEdEntity(ed1_id, "data_ed_1");
+ BiEmbIdRefEdEntity ed2 = new BiEmbIdRefEdEntity(ed2_id, "data_ed_2");
+
+ BiEmbIdRefIngEntity ing1 = new BiEmbIdRefIngEntity(ing1_id, "data_ing_1");
+
+ // Revision 1
+ EntityManager em = getEntityManager();
+ em.getTransaction().begin();
+
+ ing1.setReference(ed1);
+
+ em.persist(ed1);
+ em.persist(ed2);
+
+ em.persist(ing1);
+
+ em.getTransaction().commit();
+
+ // Revision 2
+ em.getTransaction().begin();
+
+ ing1 = em.find(BiEmbIdRefIngEntity.class, ing1.getId());
+ ed2 = em.find(BiEmbIdRefEdEntity.class, ed2.getId());
+
+ ing1.setReference(ed2);
+
+ em.getTransaction().commit();
+ }
+
+ @Test
+ public void testRevisionsCounts() {
+ assert Arrays.asList(1, 2).equals(getVersionsReader().getRevisions(BiEmbIdRefEdEntity.class, ed1_id));
+ assert Arrays.asList(1, 2).equals(getVersionsReader().getRevisions(BiEmbIdRefEdEntity.class, ed2_id));
+
+ assert Arrays.asList(1, 2).equals(getVersionsReader().getRevisions(BiEmbIdRefIngEntity.class, ing1_id));
+ }
+
+ @Test
+ public void testHistoryOfEdId1() {
+ BiEmbIdRefIngEntity ing1 = getEntityManager().find(BiEmbIdRefIngEntity.class, ing1_id);
+
+ BiEmbIdRefEdEntity rev1 = getVersionsReader().find(BiEmbIdRefEdEntity.class, ed1_id, 1);
+ BiEmbIdRefEdEntity rev2 = getVersionsReader().find(BiEmbIdRefEdEntity.class, ed1_id, 2);
+
+ assert rev1.getReferencing().equals(ing1);
+ assert rev2.getReferencing() == null;
+ }
+
+ @Test
+ public void testHistoryOfEdId2() {
+ BiEmbIdRefIngEntity ing1 = getEntityManager().find(BiEmbIdRefIngEntity.class, ing1_id);
+
+ BiEmbIdRefEdEntity rev1 = getVersionsReader().find(BiEmbIdRefEdEntity.class, ed2_id, 1);
+ BiEmbIdRefEdEntity rev2 = getVersionsReader().find(BiEmbIdRefEdEntity.class, ed2_id, 2);
+
+ assert rev1.getReferencing() == null;
+ assert rev2.getReferencing().equals(ing1);
+ }
+
+ @Test
+ public void testHistoryOfIngId1() {
+ BiEmbIdRefEdEntity ed1 = getEntityManager().find(BiEmbIdRefEdEntity.class, ed1_id);
+ BiEmbIdRefEdEntity ed2 = getEntityManager().find(BiEmbIdRefEdEntity.class, ed2_id);
+
+ BiEmbIdRefIngEntity rev1 = getVersionsReader().find(BiEmbIdRefIngEntity.class, ing1_id, 1);
+ BiEmbIdRefIngEntity rev2 = getVersionsReader().find(BiEmbIdRefIngEntity.class, ing1_id, 2);
+
+ assert rev1.getReference().equals(ed1);
+ assert rev2.getReference().equals(ed2);
+ }
+}
\ No newline at end of file
Added: core/trunk/envers/src/test/java/org/jboss/envers/test/integration/onetoone/bidirectional/ids/MulIdBidirectional.java
===================================================================
--- core/trunk/envers/src/test/java/org/jboss/envers/test/integration/onetoone/bidirectional/ids/MulIdBidirectional.java (rev 0)
+++ core/trunk/envers/src/test/java/org/jboss/envers/test/integration/onetoone/bidirectional/ids/MulIdBidirectional.java 2008-10-27 18:56:31 UTC (rev 15406)
@@ -0,0 +1,103 @@
+package org.jboss.envers.test.integration.onetoone.bidirectional.ids;
+
+import org.jboss.envers.test.AbstractEntityTest;
+import org.jboss.envers.test.entities.ids.MulId;
+import org.hibernate.ejb.Ejb3Configuration;
+import org.testng.annotations.BeforeClass;
+import org.testng.annotations.Test;
+
+import javax.persistence.EntityManager;
+import java.util.Arrays;
+
+/**
+ * @author Adam Warski (adam at warski dot org)
+ */
+public class MulIdBidirectional extends AbstractEntityTest {
+ private MulId ed1_id;
+ private MulId ed2_id;
+
+ private MulId ing1_id;
+
+ public void configure(Ejb3Configuration cfg) {
+ cfg.addAnnotatedClass(BiMulIdRefEdEntity.class);
+ cfg.addAnnotatedClass(BiMulIdRefIngEntity.class);
+ }
+
+ @BeforeClass(dependsOnMethods = "init")
+ public void initData() {
+ ed1_id = new MulId(1, 2);
+ ed2_id = new MulId(3, 4);
+
+ ing1_id = new MulId(5, 6);
+
+ BiMulIdRefEdEntity ed1 = new BiMulIdRefEdEntity(ed1_id.getId1(), ed1_id.getId2(), "data_ed_1");
+ BiMulIdRefEdEntity ed2 = new BiMulIdRefEdEntity(ed2_id.getId1(), ed2_id.getId2(), "data_ed_2");
+
+ BiMulIdRefIngEntity ing1 = new BiMulIdRefIngEntity(ing1_id.getId1(), ing1_id.getId2(), "data_ing_1");
+
+ // Revision 1
+ EntityManager em = getEntityManager();
+ em.getTransaction().begin();
+
+ ing1.setReference(ed1);
+
+ em.persist(ed1);
+ em.persist(ed2);
+
+ em.persist(ing1);
+
+ em.getTransaction().commit();
+
+ // Revision 2
+ em.getTransaction().begin();
+
+ ing1 = em.find(BiMulIdRefIngEntity.class, ing1_id);
+ ed2 = em.find(BiMulIdRefEdEntity.class, ed2_id);
+
+ ing1.setReference(ed2);
+
+ em.getTransaction().commit();
+ }
+
+ @Test
+ public void testRevisionsCounts() {
+ assert Arrays.asList(1, 2).equals(getVersionsReader().getRevisions(BiMulIdRefEdEntity.class, ed1_id));
+ assert Arrays.asList(1, 2).equals(getVersionsReader().getRevisions(BiMulIdRefEdEntity.class, ed2_id));
+
+ assert Arrays.asList(1, 2).equals(getVersionsReader().getRevisions(BiMulIdRefIngEntity.class, ing1_id));
+ }
+
+ @Test
+ public void testHistoryOfEdId1() {
+ BiMulIdRefIngEntity ing1 = getEntityManager().find(BiMulIdRefIngEntity.class, ing1_id);
+
+ BiMulIdRefEdEntity rev1 = getVersionsReader().find(BiMulIdRefEdEntity.class, ed1_id, 1);
+ BiMulIdRefEdEntity rev2 = getVersionsReader().find(BiMulIdRefEdEntity.class, ed1_id, 2);
+
+ assert rev1.getReferencing().equals(ing1);
+ assert rev2.getReferencing() == null;
+ }
+
+ @Test
+ public void testHistoryOfEdId2() {
+ BiMulIdRefIngEntity ing1 = getEntityManager().find(BiMulIdRefIngEntity.class, ing1_id);
+
+ BiMulIdRefEdEntity rev1 = getVersionsReader().find(BiMulIdRefEdEntity.class, ed2_id, 1);
+ BiMulIdRefEdEntity rev2 = getVersionsReader().find(BiMulIdRefEdEntity.class, ed2_id, 2);
+
+ assert rev1.getReferencing() == null;
+ assert rev2.getReferencing().equals(ing1);
+ }
+
+ @Test
+ public void testHistoryOfIngId1() {
+ BiMulIdRefEdEntity ed1 = getEntityManager().find(BiMulIdRefEdEntity.class, ed1_id);
+ BiMulIdRefEdEntity ed2 = getEntityManager().find(BiMulIdRefEdEntity.class, ed2_id);
+
+ BiMulIdRefIngEntity rev1 = getVersionsReader().find(BiMulIdRefIngEntity.class, ing1_id, 1);
+ BiMulIdRefIngEntity rev2 = getVersionsReader().find(BiMulIdRefIngEntity.class, ing1_id, 2);
+
+ assert rev1.getReference().equals(ed1);
+ assert rev2.getReference().equals(ed2);
+ }
+}
\ No newline at end of file
Added: core/trunk/envers/src/test/java/org/jboss/envers/test/integration/onetoone/unidirectional/UniRefEdEntity.java
===================================================================
--- core/trunk/envers/src/test/java/org/jboss/envers/test/integration/onetoone/unidirectional/UniRefEdEntity.java (rev 0)
+++ core/trunk/envers/src/test/java/org/jboss/envers/test/integration/onetoone/unidirectional/UniRefEdEntity.java 2008-10-27 18:56:31 UTC (rev 15406)
@@ -0,0 +1,62 @@
+package org.jboss.envers.test.integration.onetoone.unidirectional;
+
+import org.jboss.envers.Versioned;
+
+import javax.persistence.Id;
+import javax.persistence.Entity;
+
+/**
+ * Unidirectional ReferencEd Entity
+ * @author Adam Warski (adam at warski dot org)
+ */
+ at Entity
+public class UniRefEdEntity {
+ @Id
+ private Integer id;
+
+ @Versioned
+ private String data;
+
+ public UniRefEdEntity() {
+ }
+
+ public UniRefEdEntity(Integer id, String data) {
+ this.id = id;
+ this.data = data;
+ }
+
+ public String getData() {
+ return data;
+ }
+
+ public void setData(String data) {
+ this.data = data;
+ }
+
+ public Integer getId() {
+ return id;
+ }
+
+ public void setId(Integer id) {
+ this.id = id;
+ }
+
+ public boolean equals(Object o) {
+ if (this == o) return true;
+ if (!(o instanceof UniRefEdEntity)) return false;
+
+ UniRefEdEntity that = (UniRefEdEntity) o;
+
+ if (data != null ? !data.equals(that.data) : that.data != null) return false;
+ if (id != null ? !id.equals(that.id) : that.id != null) return false;
+
+ return true;
+ }
+
+ public int hashCode() {
+ int result;
+ result = (id != null ? id.hashCode() : 0);
+ result = 31 * result + (data != null ? data.hashCode() : 0);
+ return result;
+ }
+}
Added: core/trunk/envers/src/test/java/org/jboss/envers/test/integration/onetoone/unidirectional/UniRefIngEntity.java
===================================================================
--- core/trunk/envers/src/test/java/org/jboss/envers/test/integration/onetoone/unidirectional/UniRefIngEntity.java (rev 0)
+++ core/trunk/envers/src/test/java/org/jboss/envers/test/integration/onetoone/unidirectional/UniRefIngEntity.java 2008-10-27 18:56:31 UTC (rev 15406)
@@ -0,0 +1,76 @@
+package org.jboss.envers.test.integration.onetoone.unidirectional;
+
+import org.jboss.envers.Versioned;
+
+import javax.persistence.Entity;
+import javax.persistence.Id;
+import javax.persistence.OneToOne;
+
+/**
+ * Unidirectional ReferencIng Entity
+ * @author Adam Warski (adam at warski dot org)
+ */
+ at Entity
+public class UniRefIngEntity {
+ @Id
+ private Integer id;
+
+ @Versioned
+ private String data;
+
+ @Versioned
+ @OneToOne
+ private UniRefEdEntity reference;
+
+ public UniRefIngEntity() {
+ }
+
+ public UniRefIngEntity(Integer id, String data, UniRefEdEntity reference) {
+ this.id = id;
+ this.data = data;
+ this.reference = reference;
+ }
+
+ public Integer getId() {
+ return id;
+ }
+
+ public void setId(Integer id) {
+ this.id = id;
+ }
+
+ public String getData() {
+ return data;
+ }
+
+ public void setData(String data) {
+ this.data = data;
+ }
+
+ public UniRefEdEntity getReference() {
+ return reference;
+ }
+
+ public void setReference(UniRefEdEntity reference) {
+ this.reference = reference;
+ }
+
+ public boolean equals(Object o) {
+ if (this == o) return true;
+ if (!(o instanceof UniRefIngEntity)) return false;
+
+ UniRefIngEntity that = (UniRefIngEntity) o;
+
+ if (data != null ? !data.equals(that.data) : that.data != null) return false;
+ if (id != null ? !id.equals(that.id) : that.id != null) return false;
+
+ return true;
+ }
+
+ public int hashCode() {
+ int result;
+ result = (id != null ? id.hashCode() : 0);
+ result = 31 * result + (data != null ? data.hashCode() : 0);
+ return result;
+ }
+}
Added: core/trunk/envers/src/test/java/org/jboss/envers/test/integration/onetoone/unidirectional/Unidirectional.java
===================================================================
--- core/trunk/envers/src/test/java/org/jboss/envers/test/integration/onetoone/unidirectional/Unidirectional.java (rev 0)
+++ core/trunk/envers/src/test/java/org/jboss/envers/test/integration/onetoone/unidirectional/Unidirectional.java 2008-10-27 18:56:31 UTC (rev 15406)
@@ -0,0 +1,125 @@
+package org.jboss.envers.test.integration.onetoone.unidirectional;
+
+import org.jboss.envers.test.AbstractEntityTest;
+import org.hibernate.ejb.Ejb3Configuration;
+import org.testng.annotations.BeforeClass;
+import org.testng.annotations.Test;
+
+import javax.persistence.EntityManager;
+import java.util.Arrays;
+
+/**
+ * @author Adam Warski (adam at warski dot org)
+ */
+public class Unidirectional extends AbstractEntityTest {
+ private Integer ed1_id;
+ private Integer ed2_id;
+ private Integer ed3_id;
+ private Integer ed4_id;
+
+ private Integer ing1_id;
+ private Integer ing2_id;
+
+ public void configure(Ejb3Configuration cfg) {
+ cfg.addAnnotatedClass(UniRefEdEntity.class);
+ cfg.addAnnotatedClass(UniRefIngEntity.class);
+ }
+
+ @BeforeClass(dependsOnMethods = "init")
+ public void initData() {
+ UniRefEdEntity ed1 = new UniRefEdEntity(1, "data_ed_1");
+ UniRefEdEntity ed2 = new UniRefEdEntity(2, "data_ed_2");
+ UniRefEdEntity ed3 = new UniRefEdEntity(3, "data_ed_2");
+ UniRefEdEntity ed4 = new UniRefEdEntity(4, "data_ed_2");
+
+ UniRefIngEntity ing1 = new UniRefIngEntity(5, "data_ing_1", ed1);
+ UniRefIngEntity ing2 = new UniRefIngEntity(6, "data_ing_2", ed3);
+
+ // Revision 1
+ EntityManager em = getEntityManager();
+ em.getTransaction().begin();
+
+ em.persist(ed1);
+ em.persist(ed2);
+ em.persist(ed3);
+ em.persist(ed4);
+
+ em.persist(ing1);
+ em.persist(ing2);
+
+ em.getTransaction().commit();
+
+ // Revision 2
+
+ em = getEntityManager();
+ em.getTransaction().begin();
+
+ ing1 = em.find(UniRefIngEntity.class, ing1.getId());
+ ed2 = em.find(UniRefEdEntity.class, ed2.getId());
+
+ ing1.setReference(ed2);
+
+ em.getTransaction().commit();
+
+ // Revision 3
+
+ em = getEntityManager();
+ em.getTransaction().begin();
+
+ ing2 = em.find(UniRefIngEntity.class, ing2.getId());
+ ed3 = em.find(UniRefEdEntity.class, ed3.getId());
+
+ ing2.setReference(ed4);
+
+ em.getTransaction().commit();
+
+ //
+
+ ed1_id = ed1.getId();
+ ed2_id = ed2.getId();
+ ed3_id = ed3.getId();
+ ed4_id = ed4.getId();
+
+ ing1_id = ing1.getId();
+ ing2_id = ing2.getId();
+ }
+
+ @Test
+ public void testRevisionsCounts() {
+ assert Arrays.asList(1).equals(getVersionsReader().getRevisions(UniRefEdEntity.class, ed1_id));
+ assert Arrays.asList(1).equals(getVersionsReader().getRevisions(UniRefEdEntity.class, ed2_id));
+ assert Arrays.asList(1).equals(getVersionsReader().getRevisions(UniRefEdEntity.class, ed3_id));
+ assert Arrays.asList(1).equals(getVersionsReader().getRevisions(UniRefEdEntity.class, ed4_id));
+
+ assert Arrays.asList(1, 2).equals(getVersionsReader().getRevisions(UniRefIngEntity.class, ing1_id));
+ assert Arrays.asList(1, 3).equals(getVersionsReader().getRevisions(UniRefIngEntity.class, ing2_id));
+ }
+
+ @Test
+ public void testHistoryOfIngId1() {
+ UniRefEdEntity ed1 = getEntityManager().find(UniRefEdEntity.class, ed1_id);
+ UniRefEdEntity ed2 = getEntityManager().find(UniRefEdEntity.class, ed2_id);
+
+ UniRefIngEntity rev1 = getVersionsReader().find(UniRefIngEntity.class, ing1_id, 1);
+ UniRefIngEntity rev2 = getVersionsReader().find(UniRefIngEntity.class, ing1_id, 2);
+ UniRefIngEntity rev3 = getVersionsReader().find(UniRefIngEntity.class, ing1_id, 3);
+
+ assert rev1.getReference().equals(ed1);
+ assert rev2.getReference().equals(ed2);
+ assert rev3.getReference().equals(ed2);
+ }
+
+ @Test
+ public void testHistoryOfIngId2() {
+ UniRefEdEntity ed3 = getEntityManager().find(UniRefEdEntity.class, ed3_id);
+ UniRefEdEntity ed4 = getEntityManager().find(UniRefEdEntity.class, ed4_id);
+
+ UniRefIngEntity rev1 = getVersionsReader().find(UniRefIngEntity.class, ing2_id, 1);
+ UniRefIngEntity rev2 = getVersionsReader().find(UniRefIngEntity.class, ing2_id, 2);
+ UniRefIngEntity rev3 = getVersionsReader().find(UniRefIngEntity.class, ing2_id, 3);
+
+ assert rev1.getReference().equals(ed3);
+ assert rev2.getReference().equals(ed3);
+ assert rev3.getReference().equals(ed4);
+ }
+}
Added: core/trunk/envers/src/test/java/org/jboss/envers/test/integration/onetoone/unidirectional/UnidirectionalWithNulls.java
===================================================================
--- core/trunk/envers/src/test/java/org/jboss/envers/test/integration/onetoone/unidirectional/UnidirectionalWithNulls.java (rev 0)
+++ core/trunk/envers/src/test/java/org/jboss/envers/test/integration/onetoone/unidirectional/UnidirectionalWithNulls.java 2008-10-27 18:56:31 UTC (rev 15406)
@@ -0,0 +1,112 @@
+package org.jboss.envers.test.integration.onetoone.unidirectional;
+
+import org.jboss.envers.test.AbstractEntityTest;
+import org.hibernate.ejb.Ejb3Configuration;
+import org.testng.annotations.BeforeClass;
+import org.testng.annotations.Test;
+
+import javax.persistence.EntityManager;
+import java.util.Arrays;
+
+/**
+ * @author Adam Warski (adam at warski dot org)
+ */
+public class UnidirectionalWithNulls extends AbstractEntityTest {
+ private Integer ed1_id;
+ private Integer ed2_id;
+
+ private Integer ing1_id;
+ private Integer ing2_id;
+
+ public void configure(Ejb3Configuration cfg) {
+ cfg.addAnnotatedClass(UniRefEdEntity.class);
+ cfg.addAnnotatedClass(UniRefIngEntity.class);
+ }
+
+ @BeforeClass(dependsOnMethods = "init")
+ public void initData() {
+ UniRefEdEntity ed1 = new UniRefEdEntity(1, "data_ed_1");
+ UniRefEdEntity ed2 = new UniRefEdEntity(2, "data_ed_2");
+
+ UniRefIngEntity ing1 = new UniRefIngEntity(3, "data_ing_1", ed1);
+ UniRefIngEntity ing2 = new UniRefIngEntity(4, "data_ing_2", null);
+
+ // Revision 1
+ EntityManager em = getEntityManager();
+ em.getTransaction().begin();
+
+ em.persist(ed1);
+ em.persist(ed2);
+
+ em.persist(ing1);
+ em.persist(ing2);
+
+ em.getTransaction().commit();
+
+ // Revision 2
+
+ em = getEntityManager();
+ em.getTransaction().begin();
+
+ ing1 = em.find(UniRefIngEntity.class, ing1.getId());
+
+ ing1.setReference(null);
+
+ em.getTransaction().commit();
+
+ // Revision 3
+
+ em = getEntityManager();
+ em.getTransaction().begin();
+
+ ing2 = em.find(UniRefIngEntity.class, ing2.getId());
+ ed2 = em.find(UniRefEdEntity.class, ed2.getId());
+
+ ing2.setReference(ed2);
+
+ em.getTransaction().commit();
+
+ //
+
+ ed1_id = ed1.getId();
+ ed2_id = ed2.getId();
+
+ ing1_id = ing1.getId();
+ ing2_id = ing2.getId();
+ }
+
+ @Test
+ public void testRevisionsCounts() {
+ assert Arrays.asList(1).equals(getVersionsReader().getRevisions(UniRefEdEntity.class, ed1_id));
+ assert Arrays.asList(1).equals(getVersionsReader().getRevisions(UniRefEdEntity.class, ed2_id));
+
+ assert Arrays.asList(1, 2).equals(getVersionsReader().getRevisions(UniRefIngEntity.class, ing1_id));
+ assert Arrays.asList(1, 3).equals(getVersionsReader().getRevisions(UniRefIngEntity.class, ing2_id));
+ }
+
+ @Test
+ public void testHistoryOfIngId1() {
+ UniRefEdEntity ed1 = getEntityManager().find(UniRefEdEntity.class, ed1_id);
+
+ UniRefIngEntity rev1 = getVersionsReader().find(UniRefIngEntity.class, ing1_id, 1);
+ UniRefIngEntity rev2 = getVersionsReader().find(UniRefIngEntity.class, ing1_id, 2);
+ UniRefIngEntity rev3 = getVersionsReader().find(UniRefIngEntity.class, ing1_id, 3);
+
+ assert rev1.getReference().equals(ed1);
+ assert rev2.getReference() == null;
+ assert rev3.getReference() == null;
+ }
+
+ @Test
+ public void testHistoryOfIngId2() {
+ UniRefEdEntity ed2 = getEntityManager().find(UniRefEdEntity.class, ed2_id);
+
+ UniRefIngEntity rev1 = getVersionsReader().find(UniRefIngEntity.class, ing2_id, 1);
+ UniRefIngEntity rev2 = getVersionsReader().find(UniRefIngEntity.class, ing2_id, 2);
+ UniRefIngEntity rev3 = getVersionsReader().find(UniRefIngEntity.class, ing2_id, 3);
+
+ assert rev1.getReference() == null;
+ assert rev2.getReference() == null;
+ assert rev3.getReference().equals(ed2);
+ }
+}
\ No newline at end of file
Added: core/trunk/envers/src/test/java/org/jboss/envers/test/integration/properties/PropertiesTestEntity.java
===================================================================
--- core/trunk/envers/src/test/java/org/jboss/envers/test/integration/properties/PropertiesTestEntity.java (rev 0)
+++ core/trunk/envers/src/test/java/org/jboss/envers/test/integration/properties/PropertiesTestEntity.java 2008-10-27 18:56:31 UTC (rev 15406)
@@ -0,0 +1,67 @@
+package org.jboss.envers.test.integration.properties;
+
+import org.jboss.envers.Versioned;
+
+import javax.persistence.Entity;
+import javax.persistence.Id;
+import javax.persistence.GeneratedValue;
+
+/**
+ * @author Adam Warski (adam at warski dot org)
+ */
+ at Entity
+public class PropertiesTestEntity {
+ @Id
+ @GeneratedValue
+ private Integer id;
+
+ @Versioned
+ private String str;
+
+ public PropertiesTestEntity() {
+ }
+
+ public PropertiesTestEntity(String str) {
+ this.str = str;
+ }
+
+ public PropertiesTestEntity(Integer id, String str) {
+ this.id = id;
+ this.str = str;
+ }
+
+ public Integer getId() {
+ return id;
+ }
+
+ public void setId(Integer id) {
+ this.id = id;
+ }
+
+ public String getStr() {
+ return str;
+}
+
+ public void setStr(String str) {
+ this.str = str;
+ }
+
+ public boolean equals(Object o) {
+ if (this == o) return true;
+ if (!(o instanceof PropertiesTestEntity)) return false;
+
+ PropertiesTestEntity that = (PropertiesTestEntity) o;
+
+ if (id != null ? !id.equals(that.id) : that.id != null) return false;
+ if (str != null ? !str.equals(that.str) : that.str != null) return false;
+
+ return true;
+ }
+
+ public int hashCode() {
+ int result;
+ result = (id != null ? id.hashCode() : 0);
+ result = 31 * result + (str != null ? str.hashCode() : 0);
+ return result;
+ }
+}
\ No newline at end of file
Added: core/trunk/envers/src/test/java/org/jboss/envers/test/integration/properties/UnversionedOptimisticLockingField.java
===================================================================
--- core/trunk/envers/src/test/java/org/jboss/envers/test/integration/properties/UnversionedOptimisticLockingField.java (rev 0)
+++ core/trunk/envers/src/test/java/org/jboss/envers/test/integration/properties/UnversionedOptimisticLockingField.java 2008-10-27 18:56:31 UTC (rev 15406)
@@ -0,0 +1,69 @@
+package org.jboss.envers.test.integration.properties;
+
+import java.util.Arrays;
+import java.util.Iterator;
+
+import javax.persistence.EntityManager;
+
+import org.hibernate.ejb.Ejb3Configuration;
+import org.hibernate.mapping.PersistentClass;
+import org.hibernate.mapping.Property;
+import org.jboss.envers.test.AbstractEntityTest;
+import org.testng.annotations.BeforeClass;
+import org.testng.annotations.Test;
+
+/**
+ * @author Nicolas Doroskevich
+ */
+public class UnversionedOptimisticLockingField extends AbstractEntityTest {
+ private Integer id1;
+
+ public void configure(Ejb3Configuration cfg) {
+ cfg.addAnnotatedClass(UnversionedOptimisticLockingFieldEntity.class);
+
+ cfg.setProperty("org.jboss.envers.unversionedOptimisticLockingField", "true");
+ }
+
+ @BeforeClass(dependsOnMethods = "init")
+ public void initData() {
+ EntityManager em = getEntityManager();
+ em.getTransaction().begin();
+ UnversionedOptimisticLockingFieldEntity olfe = new UnversionedOptimisticLockingFieldEntity("x");
+ em.persist(olfe);
+ id1 = olfe.getId();
+ em.getTransaction().commit();
+
+ em.getTransaction().begin();
+ olfe = em.find(UnversionedOptimisticLockingFieldEntity.class, id1);
+ olfe.setStr("y");
+ em.getTransaction().commit();
+ }
+
+ @Test
+ public void testRevisionCounts() {
+ assert Arrays.asList(1, 2).equals(
+ getVersionsReader().getRevisions(UnversionedOptimisticLockingFieldEntity.class,
+ id1));
+ }
+
+ @Test
+ public void testHistoryOfId1() {
+ UnversionedOptimisticLockingFieldEntity ver1 = new UnversionedOptimisticLockingFieldEntity(id1, "x");
+ UnversionedOptimisticLockingFieldEntity ver2 = new UnversionedOptimisticLockingFieldEntity(id1, "y");
+
+ assert getVersionsReader().find(UnversionedOptimisticLockingFieldEntity.class, id1, 1)
+ .equals(ver1);
+ assert getVersionsReader().find(UnversionedOptimisticLockingFieldEntity.class, id1, 2)
+ .equals(ver2);
+ }
+
+ @Test
+ public void testMapping() {
+ PersistentClass pc = getCfg().getClassMapping(UnversionedOptimisticLockingFieldEntity.class.getName() + "_versions");
+ Iterator pi = pc.getPropertyIterator();
+ while(pi.hasNext()) {
+ Property p = (Property) pi.next();
+ assert !"optLocking".equals(p.getName());
+ }
+ }
+}
Added: core/trunk/envers/src/test/java/org/jboss/envers/test/integration/properties/UnversionedOptimisticLockingFieldEntity.java
===================================================================
--- core/trunk/envers/src/test/java/org/jboss/envers/test/integration/properties/UnversionedOptimisticLockingFieldEntity.java (rev 0)
+++ core/trunk/envers/src/test/java/org/jboss/envers/test/integration/properties/UnversionedOptimisticLockingFieldEntity.java 2008-10-27 18:56:31 UTC (rev 15406)
@@ -0,0 +1,81 @@
+package org.jboss.envers.test.integration.properties;
+
+import javax.persistence.Entity;
+import javax.persistence.GeneratedValue;
+import javax.persistence.Id;
+import javax.persistence.Version;
+
+import org.jboss.envers.Versioned;
+
+/**
+ * @author Nicolas Doroskevich
+ */
+ at Versioned
+ at Entity
+public class UnversionedOptimisticLockingFieldEntity {
+
+ @Id
+ @GeneratedValue
+ private Integer id;
+
+ private String str;
+
+ @Version
+ private int optLocking;
+
+ public UnversionedOptimisticLockingFieldEntity() {
+ }
+
+ public UnversionedOptimisticLockingFieldEntity(String str) {
+ this.str = str;
+ }
+
+ public UnversionedOptimisticLockingFieldEntity(Integer id, String str) {
+ this.id = id;
+ this.str = str;
+ }
+
+ public Integer getId() {
+ return id;
+ }
+
+ public void setId(Integer id) {
+ this.id = id;
+ }
+
+ public String getStr() {
+ return str;
+ }
+
+ public void setStr(String str) {
+ this.str = str;
+ }
+
+ public int getOptLocking() {
+ return optLocking;
+ }
+
+ public void setOptLocking(int optLocking) {
+ this.optLocking = optLocking;
+ }
+
+ public boolean equals(Object o) {
+ if (this == o) return true;
+ if (!(o instanceof UnversionedOptimisticLockingFieldEntity)) return false;
+
+ UnversionedOptimisticLockingFieldEntity that = (UnversionedOptimisticLockingFieldEntity) o;
+
+ if (id != null ? !id.equals(that.id) : that.id != null) return false;
+ if (str != null ? !str.equals(that.str) : that.str != null) return false;
+
+ return true;
+ }
+
+ public int hashCode() {
+ int result;
+ result = (id != null ? id.hashCode() : 0);
+ result = 31 * result + (str != null ? str.hashCode() : 0);
+ return result;
+ }
+
+}
Added: core/trunk/envers/src/test/java/org/jboss/envers/test/integration/properties/VersionsProperties.java
===================================================================
--- core/trunk/envers/src/test/java/org/jboss/envers/test/integration/properties/VersionsProperties.java (rev 0)
+++ core/trunk/envers/src/test/java/org/jboss/envers/test/integration/properties/VersionsProperties.java 2008-10-27 18:56:31 UTC (rev 15406)
@@ -0,0 +1,55 @@
+package org.jboss.envers.test.integration.properties;
+
+import org.jboss.envers.test.AbstractEntityTest;
+import org.hibernate.ejb.Ejb3Configuration;
+import org.testng.annotations.Test;
+import org.testng.annotations.BeforeClass;
+
+import javax.persistence.EntityManager;
+import java.util.Arrays;
+
+/**
+ * @author Adam Warski (adam at warski dot org)
+ */
+public class VersionsProperties extends AbstractEntityTest {
+ private Integer id1;
+
+ public void configure(Ejb3Configuration cfg) {
+ cfg.addAnnotatedClass(PropertiesTestEntity.class);
+
+ cfg.setProperty("org.jboss.envers.versionsTablePrefix", "VP_");
+ cfg.setProperty("org.jboss.envers.versionsTableSuffix", "_VS");
+ cfg.setProperty("org.jboss.envers.idFieldName", "ver_id");
+ cfg.setProperty("org.jboss.envers.revisionFieldName", "ver_rev");
+ cfg.setProperty("org.jboss.envers.revisionTypeFieldName", "ver_rev_type");
+ }
+
+ @BeforeClass(dependsOnMethods = "init")
+ public void initData() {
+ EntityManager em = getEntityManager();
+ em.getTransaction().begin();
+ PropertiesTestEntity pte = new PropertiesTestEntity("x");
+ em.persist(pte);
+ id1 = pte.getId();
+ em.getTransaction().commit();
+
+ em.getTransaction().begin();
+ pte = em.find(PropertiesTestEntity.class, id1);
+ pte.setStr("y");
+ em.getTransaction().commit();
+ }
+
+ @Test
+ public void testRevisionsCounts() {
+ assert Arrays.asList(1, 2).equals(getVersionsReader().getRevisions(PropertiesTestEntity.class, id1));
+ }
+
+ @Test
+ public void testHistoryOfId1() {
+ PropertiesTestEntity ver1 = new PropertiesTestEntity(id1, "x");
+ PropertiesTestEntity ver2 = new PropertiesTestEntity(id1, "y");
+
+ assert getVersionsReader().find(PropertiesTestEntity.class, id1, 1).equals(ver1);
+ assert getVersionsReader().find(PropertiesTestEntity.class, id1, 2).equals(ver2);
+ }
+}
\ No newline at end of file
Added: core/trunk/envers/src/test/java/org/jboss/envers/test/integration/query/AggregateQuery.java
===================================================================
--- core/trunk/envers/src/test/java/org/jboss/envers/test/integration/query/AggregateQuery.java (rev 0)
+++ core/trunk/envers/src/test/java/org/jboss/envers/test/integration/query/AggregateQuery.java 2008-10-27 18:56:31 UTC (rev 15406)
@@ -0,0 +1,87 @@
+package org.jboss.envers.test.integration.query;
+
+import org.jboss.envers.test.AbstractEntityTest;
+import org.jboss.envers.test.entities.IntTestEntity;
+import org.hibernate.ejb.Ejb3Configuration;
+import org.testng.annotations.BeforeClass;
+import org.testng.annotations.Test;
+
+import javax.persistence.EntityManager;
+/**
+ * @author Adam Warski (adam at warski dot org)
+ */
+ at SuppressWarnings({"unchecked"})
+public class AggregateQuery extends AbstractEntityTest {
+ public void configure(Ejb3Configuration cfg) {
+ cfg.addAnnotatedClass(IntTestEntity.class);
+ }
+
+ @BeforeClass(dependsOnMethods = "init")
+ public void initData() {
+ // Revision 1
+ EntityManager em = getEntityManager();
+ em.getTransaction().begin();
+
+ IntTestEntity ite1 = new IntTestEntity(2);
+ IntTestEntity ite2 = new IntTestEntity(10);
+
+ em.persist(ite1);
+ em.persist(ite2);
+
+ Integer id1 = ite1.getId();
+ Integer id2 = ite2.getId();
+
+ em.getTransaction().commit();
+
+ // Revision 2
+ em.getTransaction().begin();
+
+ IntTestEntity ite3 = new IntTestEntity(8);
+ em.persist(ite3);
+
+ ite1 = em.find(IntTestEntity.class, id1);
+
+ ite1.setNumber(0);
+
+ em.getTransaction().commit();
+
+ // Revision 3
+ em.getTransaction().begin();
+
+ ite2 = em.find(IntTestEntity.class, id2);
+
+ ite2.setNumber(52);
+
+ em.getTransaction().commit();
+ }
+
+ @Test
+ public void testEntitiesAvgMaxQuery() {
+ Object[] ver1 = (Object[]) getVersionsReader().createQuery()
+ .forEntitiesAtRevision(IntTestEntity.class, 1)
+ .addProjection("max", "number")
+ .addProjection("avg", "number")
+ .getSingleResult();
+
+ Object[] ver2 = (Object[]) getVersionsReader().createQuery()
+ .forEntitiesAtRevision(IntTestEntity.class, 2)
+ .addProjection("max", "number")
+ .addProjection("avg", "number")
+ .getSingleResult();
+
+ Object[] ver3 = (Object[]) getVersionsReader().createQuery()
+ .forEntitiesAtRevision(IntTestEntity.class, 3)
+ .addProjection("max", "number")
+ .addProjection("avg", "number")
+ .getSingleResult();
+
+ assert (Integer) ver1[0] == 10;
+ assert (Double) ver1[1] == 6.0;
+
+ assert (Integer) ver2[0] == 10;
+ assert (Double) ver2[1] == 6.0;
+
+ assert (Integer) ver3[0] == 52;
+ assert (Double) ver3[1] == 20.0;
+ }
+}
\ No newline at end of file
Added: core/trunk/envers/src/test/java/org/jboss/envers/test/integration/query/CustomRevEntityQuery.java
===================================================================
--- core/trunk/envers/src/test/java/org/jboss/envers/test/integration/query/CustomRevEntityQuery.java (rev 0)
+++ core/trunk/envers/src/test/java/org/jboss/envers/test/integration/query/CustomRevEntityQuery.java 2008-10-27 18:56:31 UTC (rev 15406)
@@ -0,0 +1,81 @@
+package org.jboss.envers.test.integration.query;
+
+import org.jboss.envers.test.AbstractEntityTest;
+import org.jboss.envers.test.entities.StrIntTestEntity;
+import org.jboss.envers.test.entities.reventity.CustomRevEntity;
+import org.jboss.envers.query.VersionsRestrictions;
+import org.hibernate.ejb.Ejb3Configuration;
+import org.testng.annotations.BeforeClass;
+import org.testng.annotations.Test;
+
+import javax.persistence.EntityManager;
+import java.util.List;
+
+/**
+ * @author Adam Warski (adam at warski dot org)
+ */
+ at SuppressWarnings({"unchecked"})
+public class CustomRevEntityQuery extends AbstractEntityTest {
+ private Integer id1;
+ private Integer id2;
+
+ public void configure(Ejb3Configuration cfg) {
+ cfg.addAnnotatedClass(CustomRevEntity.class);
+ cfg.addAnnotatedClass(StrIntTestEntity.class);
+ }
+
+ @BeforeClass(dependsOnMethods = "init")
+ public void initData() {
+ // Revision 1
+ EntityManager em = getEntityManager();
+ em.getTransaction().begin();
+
+ StrIntTestEntity site1 = new StrIntTestEntity("a", 10);
+ StrIntTestEntity site2 = new StrIntTestEntity("b", 15);
+
+ em.persist(site1);
+ em.persist(site2);
+
+ id1 = site1.getId();
+ id2 = site2.getId();
+
+ em.getTransaction().commit();
+
+ // Revision 2
+ em.getTransaction().begin();
+
+ site1 = em.find(StrIntTestEntity.class, id1);
+
+ site1.setStr1("c");
+
+ em.getTransaction().commit();
+ }
+
+ @Test
+ public void testRevisionsOfId1Query() {
+ List<Object[]> result = getVersionsReader().createQuery()
+ .forRevisionsOfEntity(StrIntTestEntity.class, false, true)
+ .add(VersionsRestrictions.idEq(id1))
+ .getResultList();
+
+ assert result.get(0)[0].equals(new StrIntTestEntity("a", 10, id1));
+ assert result.get(0)[1] instanceof CustomRevEntity;
+ assert ((CustomRevEntity) result.get(0)[1]).getCustomId() == 1;
+
+ assert result.get(1)[0].equals(new StrIntTestEntity("c", 10, id1));
+ assert result.get(1)[1] instanceof CustomRevEntity;
+ assert ((CustomRevEntity) result.get(1)[1]).getCustomId() == 2;
+ }
+
+ @Test
+ public void testRevisionsOfId2Query() {
+ List<Object[]> result = getVersionsReader().createQuery()
+ .forRevisionsOfEntity(StrIntTestEntity.class, false, true)
+ .add(VersionsRestrictions.idEq(id2))
+ .getResultList();
+
+ assert result.get(0)[0].equals(new StrIntTestEntity("b", 15, id2));
+ assert result.get(0)[1] instanceof CustomRevEntity;
+ assert ((CustomRevEntity) result.get(0)[1]).getCustomId() == 1;
+ }
+}
\ No newline at end of file
Added: core/trunk/envers/src/test/java/org/jboss/envers/test/integration/query/DeletedEntities.java
===================================================================
--- core/trunk/envers/src/test/java/org/jboss/envers/test/integration/query/DeletedEntities.java (rev 0)
+++ core/trunk/envers/src/test/java/org/jboss/envers/test/integration/query/DeletedEntities.java 2008-10-27 18:56:31 UTC (rev 15406)
@@ -0,0 +1,76 @@
+package org.jboss.envers.test.integration.query;
+
+import org.jboss.envers.test.AbstractEntityTest;
+import org.jboss.envers.test.entities.StrIntTestEntity;
+import org.jboss.envers.query.VersionsRestrictions;
+import org.jboss.envers.RevisionType;
+import org.jboss.envers.DefaultRevisionEntity;
+import org.hibernate.ejb.Ejb3Configuration;
+import org.testng.annotations.BeforeClass;
+import org.testng.annotations.Test;
+
+import javax.persistence.EntityManager;
+import java.util.List;
+
+/**
+ * @author Adam Warski (adam at warski dot org)
+ */
+public class DeletedEntities extends AbstractEntityTest {
+ private Integer id2;
+
+ public void configure(Ejb3Configuration cfg) {
+ cfg.addAnnotatedClass(StrIntTestEntity.class);
+ }
+
+ @BeforeClass(dependsOnMethods = "init")
+ public void initData() {
+ // Revision 1
+ EntityManager em = getEntityManager();
+ em.getTransaction().begin();
+
+ StrIntTestEntity site1 = new StrIntTestEntity("a", 10);
+ StrIntTestEntity site2 = new StrIntTestEntity("b", 11);
+
+ em.persist(site1);
+ em.persist(site2);
+
+ id2 = site2.getId();
+
+ em.getTransaction().commit();
+
+ // Revision 2
+ em.getTransaction().begin();
+
+ site2 = em.find(StrIntTestEntity.class, id2);
+ em.remove(site2);
+
+ em.getTransaction().commit();
+ }
+
+ @Test
+ public void testProjectionsInEntitiesAtRevision() {
+ assert getVersionsReader().createQuery().forEntitiesAtRevision(StrIntTestEntity.class, 1)
+ .getResultList().size() == 2;
+ assert getVersionsReader().createQuery().forEntitiesAtRevision(StrIntTestEntity.class, 2)
+ .getResultList().size() == 1;
+
+ assert (Long) getVersionsReader().createQuery().forEntitiesAtRevision(StrIntTestEntity.class, 1)
+ .addProjection("count", "originalId.id").getResultList().get(0) == 2;
+ assert (Long) getVersionsReader().createQuery().forEntitiesAtRevision(StrIntTestEntity.class, 2)
+ .addProjection("count", "originalId.id").getResultList().get(0) == 1;
+ }
+
+ @Test
+ public void testRevisionsOfEntityWithoutDelete() {
+ List result = getVersionsReader().createQuery()
+ .forRevisionsOfEntity(StrIntTestEntity.class, false, false)
+ .add(VersionsRestrictions.idEq(id2))
+ .getResultList();
+
+ assert result.size() == 1;
+
+ assert ((Object []) result.get(0))[0].equals(new StrIntTestEntity("b", 11, id2));
+ assert ((DefaultRevisionEntity) ((Object []) result.get(0))[1]).getId() == 1;
+ assert ((Object []) result.get(0))[2].equals(RevisionType.ADD);
+ }
+}
Added: core/trunk/envers/src/test/java/org/jboss/envers/test/integration/query/MaximalizePropertyQuery.java
===================================================================
--- core/trunk/envers/src/test/java/org/jboss/envers/test/integration/query/MaximalizePropertyQuery.java (rev 0)
+++ core/trunk/envers/src/test/java/org/jboss/envers/test/integration/query/MaximalizePropertyQuery.java 2008-10-27 18:56:31 UTC (rev 15406)
@@ -0,0 +1,101 @@
+package org.jboss.envers.test.integration.query;
+
+import org.jboss.envers.test.AbstractEntityTest;
+import org.jboss.envers.test.entities.StrIntTestEntity;
+import org.jboss.envers.query.VersionsRestrictions;
+import org.jboss.envers.query.RevisionProperty;
+import org.hibernate.ejb.Ejb3Configuration;
+import org.testng.annotations.BeforeClass;
+import org.testng.annotations.Test;
+
+import javax.persistence.EntityManager;
+import java.util.List;
+import java.util.Arrays;
+
+/**
+ * @author Adam Warski (adam at warski dot org)
+ */
+ at SuppressWarnings({"unchecked"})
+public class MaximalizePropertyQuery extends AbstractEntityTest {
+ Integer id1;
+ Integer id2;
+
+ public void configure(Ejb3Configuration cfg) {
+ cfg.addAnnotatedClass(StrIntTestEntity.class);
+ }
+
+ @BeforeClass(dependsOnMethods = "init")
+ public void initData() {
+ // Revision 1
+ EntityManager em = getEntityManager();
+ em.getTransaction().begin();
+
+ StrIntTestEntity site1 = new StrIntTestEntity("a", 10);
+ StrIntTestEntity site2 = new StrIntTestEntity("b", 15);
+
+ em.persist(site1);
+ em.persist(site2);
+
+ id1 = site1.getId();
+ id2 = site2.getId();
+
+ em.getTransaction().commit();
+
+ // Revision 2
+ em.getTransaction().begin();
+
+ site1 = em.find(StrIntTestEntity.class, id1);
+ site2 = em.find(StrIntTestEntity.class, id2);
+
+ site1.setStr1("d");
+ site2.setNumber(20);
+
+ em.getTransaction().commit();
+
+ // Revision 3
+ em.getTransaction().begin();
+
+ site1 = em.find(StrIntTestEntity.class, id1);
+ site2 = em.find(StrIntTestEntity.class, id2);
+
+ site1.setNumber(30);
+ site2.setStr1("z");
+
+ em.getTransaction().commit();
+
+ // Revision 4
+ em.getTransaction().begin();
+
+ site1 = em.find(StrIntTestEntity.class, id1);
+ site2 = em.find(StrIntTestEntity.class, id2);
+
+ site1.setNumber(5);
+ site2.setStr1("a");
+
+ em.getTransaction().commit();
+ }
+
+ @Test
+ public void testMaximizeWithIdEq() {
+ List revs_id1 = getVersionsReader().createQuery()
+ .forRevisionsOfEntity(StrIntTestEntity.class, false, true)
+ .addProjection(RevisionProperty.revisionNumber())
+ .add(VersionsRestrictions.maximizeProperty("number")
+ .add(VersionsRestrictions.idEq(id2)))
+ .getResultList();
+
+ assert Arrays.asList(2, 3, 4).equals(revs_id1);
+ }
+
+ @Test
+ public void testMinimizeWithPropertyEq() {
+ List result = getVersionsReader().createQuery()
+ .forRevisionsOfEntity(StrIntTestEntity.class, false, true)
+ .addProjection(RevisionProperty.revisionNumber())
+ .add(VersionsRestrictions.minimizeProperty("number")
+ .add(VersionsRestrictions.eq("str1", "a")))
+ .getResultList();
+
+ assert Arrays.asList(1).equals(result);
+ }
+}
\ No newline at end of file
Added: core/trunk/envers/src/test/java/org/jboss/envers/test/integration/query/OrderByLimitQuery.java
===================================================================
--- core/trunk/envers/src/test/java/org/jboss/envers/test/integration/query/OrderByLimitQuery.java (rev 0)
+++ core/trunk/envers/src/test/java/org/jboss/envers/test/integration/query/OrderByLimitQuery.java 2008-10-27 18:56:31 UTC (rev 15406)
@@ -0,0 +1,122 @@
+package org.jboss.envers.test.integration.query;
+
+import org.jboss.envers.test.AbstractEntityTest;
+import org.jboss.envers.test.entities.IntTestEntity;
+import org.hibernate.ejb.Ejb3Configuration;
+import org.testng.annotations.BeforeClass;
+import org.testng.annotations.Test;
+
+import javax.persistence.EntityManager;
+import java.util.List;
+import java.util.Arrays;
+
+/**
+ * @author Adam Warski (adam at warski dot org)
+ */
+ at SuppressWarnings({"unchecked"})
+public class OrderByLimitQuery extends AbstractEntityTest {
+ private Integer id1;
+ private Integer id2;
+ private Integer id3;
+ private Integer id4;
+ private Integer id5;
+
+ public void configure(Ejb3Configuration cfg) {
+ cfg.addAnnotatedClass(IntTestEntity.class);
+ }
+
+ @BeforeClass(dependsOnMethods = "init")
+ public void initData() {
+ // Revision 1
+ EntityManager em = getEntityManager();
+ em.getTransaction().begin();
+
+ IntTestEntity ite1 = new IntTestEntity(12);
+ IntTestEntity ite2 = new IntTestEntity(5);
+ IntTestEntity ite3 = new IntTestEntity(8);
+ IntTestEntity ite4 = new IntTestEntity(1);
+
+ em.persist(ite1);
+ em.persist(ite2);
+ em.persist(ite3);
+ em.persist(ite4);
+
+ id1 = ite1.getId();
+ id2 = ite2.getId();
+ id3 = ite3.getId();
+ id4 = ite4.getId();
+
+ em.getTransaction().commit();
+
+ // Revision 2
+ em.getTransaction().begin();
+
+ IntTestEntity ite5 = new IntTestEntity(3);
+ em.persist(ite5);
+ id5 = ite5.getId();
+
+ ite1 = em.find(IntTestEntity.class, id1);
+ ite1.setNumber(0);
+
+ ite4 = em.find(IntTestEntity.class, id4);
+ ite4.setNumber(15);
+
+ em.getTransaction().commit();
+ }
+
+ @Test
+ public void testEntitiesOrderLimitByQueryRev1() {
+ List res_0_to_1 = getVersionsReader().createQuery()
+ .forEntitiesAtRevision(IntTestEntity.class, 1)
+ .addOrder("number", false)
+ .setFirstResult(0)
+ .setMaxResults(2)
+ .getResultList();
+
+ List res_2_to_3 = getVersionsReader().createQuery()
+ .forEntitiesAtRevision(IntTestEntity.class, 1)
+ .addOrder("number", false)
+ .setFirstResult(2)
+ .setMaxResults(2)
+ .getResultList();
+
+ List res_empty = getVersionsReader().createQuery()
+ .forEntitiesAtRevision(IntTestEntity.class, 1)
+ .addOrder("number", false)
+ .setFirstResult(4)
+ .setMaxResults(2)
+ .getResultList();
+
+ assert Arrays.asList(new IntTestEntity(12, id1), new IntTestEntity(8, id3)).equals(res_0_to_1);
+ assert Arrays.asList(new IntTestEntity(5, id2), new IntTestEntity(1, id4)).equals(res_2_to_3);
+ assert Arrays.asList().equals(res_empty);
+ }
+
+ @Test
+ public void testEntitiesOrderLimitByQueryRev2() {
+ List res_0_to_1 = getVersionsReader().createQuery()
+ .forEntitiesAtRevision(IntTestEntity.class, 2)
+ .addOrder("number", false)
+ .setFirstResult(0)
+ .setMaxResults(2)
+ .getResultList();
+
+ List res_2_to_3 = getVersionsReader().createQuery()
+ .forEntitiesAtRevision(IntTestEntity.class, 2)
+ .addOrder("number", false)
+ .setFirstResult(2)
+ .setMaxResults(2)
+ .getResultList();
+
+ List res_4 = getVersionsReader().createQuery()
+ .forEntitiesAtRevision(IntTestEntity.class, 2)
+ .addOrder("number", false)
+ .setFirstResult(4)
+ .setMaxResults(2)
+ .getResultList();
+
+ assert Arrays.asList(new IntTestEntity(15, id4), new IntTestEntity(8, id3)).equals(res_0_to_1);
+ assert Arrays.asList(new IntTestEntity(5, id2), new IntTestEntity(3, id5)).equals(res_2_to_3);
+ assert Arrays.asList(new IntTestEntity(0, id1)).equals(res_4);
+ }
+}
\ No newline at end of file
Added: core/trunk/envers/src/test/java/org/jboss/envers/test/integration/query/RevisionConstraintQuery.java
===================================================================
--- core/trunk/envers/src/test/java/org/jboss/envers/test/integration/query/RevisionConstraintQuery.java (rev 0)
+++ core/trunk/envers/src/test/java/org/jboss/envers/test/integration/query/RevisionConstraintQuery.java 2008-10-27 18:56:31 UTC (rev 15406)
@@ -0,0 +1,163 @@
+package org.jboss.envers.test.integration.query;
+
+import org.jboss.envers.test.AbstractEntityTest;
+import org.jboss.envers.test.entities.StrIntTestEntity;
+import org.jboss.envers.query.VersionsRestrictions;
+import org.jboss.envers.query.RevisionProperty;
+import org.hibernate.ejb.Ejb3Configuration;
+import org.testng.annotations.BeforeClass;
+import org.testng.annotations.Test;
+
+import javax.persistence.EntityManager;
+import java.util.List;
+import java.util.Arrays;
+
+/**
+ * @author Adam Warski (adam at warski dot org)
+ */
+ at SuppressWarnings({"unchecked"})
+public class RevisionConstraintQuery extends AbstractEntityTest {
+ private Integer id1;
+
+ public void configure(Ejb3Configuration cfg) {
+ cfg.addAnnotatedClass(StrIntTestEntity.class);
+ }
+
+ @BeforeClass(dependsOnMethods = "init")
+ public void initData() {
+ // Revision 1
+ EntityManager em = getEntityManager();
+ em.getTransaction().begin();
+
+ StrIntTestEntity site1 = new StrIntTestEntity("a", 10);
+ StrIntTestEntity site2 = new StrIntTestEntity("b", 15);
+
+ em.persist(site1);
+ em.persist(site2);
+
+ id1 = site1.getId();
+ Integer id2 = site2.getId();
+
+ em.getTransaction().commit();
+
+ // Revision 2
+ em.getTransaction().begin();
+
+ site1 = em.find(StrIntTestEntity.class, id1);
+ site2 = em.find(StrIntTestEntity.class, id2);
+
+ site1.setStr1("d");
+ site2.setNumber(20);
+
+ em.getTransaction().commit();
+
+ // Revision 3
+ em.getTransaction().begin();
+
+ site1 = em.find(StrIntTestEntity.class, id1);
+ site2 = em.find(StrIntTestEntity.class, id2);
+
+ site1.setNumber(1);
+ site2.setStr1("z");
+
+ em.getTransaction().commit();
+
+ // Revision 4
+ em.getTransaction().begin();
+
+ site1 = em.find(StrIntTestEntity.class, id1);
+ site2 = em.find(StrIntTestEntity.class, id2);
+
+ site1.setNumber(5);
+ site2.setStr1("a");
+
+ em.getTransaction().commit();
+ }
+
+ @Test
+ public void testRevisionsLtQuery() {
+ List result = getVersionsReader().createQuery()
+ .forRevisionsOfEntity(StrIntTestEntity.class, false, true)
+ .addProjection(RevisionProperty.distinct())
+ .add(RevisionProperty.lt(3))
+ .getResultList();
+
+ assert Arrays.asList(1, 2).equals(result);
+ }
+
+ @Test
+ public void testRevisionsGeQuery() {
+ List result = getVersionsReader().createQuery()
+ .forRevisionsOfEntity(StrIntTestEntity.class, false, true)
+ .addProjection(RevisionProperty.distinct())
+ .add(RevisionProperty.ge(2))
+ .getResultList();
+
+ assert Arrays.asList(2, 3, 4).equals(result);
+ }
+
+ @Test
+ public void testRevisionsLeWithPropertyQuery() {
+ List result = getVersionsReader().createQuery()
+ .forRevisionsOfEntity(StrIntTestEntity.class, false, true)
+ .addProjection(RevisionProperty.revisionNumber())
+ .add(RevisionProperty.le(3))
+ .add(VersionsRestrictions.eq("str1", "a"))
+ .getResultList();
+
+ assert Arrays.asList(1).equals(result);
+ }
+
+ @Test
+ public void testRevisionsGtWithPropertyQuery() {
+ List result = getVersionsReader().createQuery()
+ .forRevisionsOfEntity(StrIntTestEntity.class, false, true)
+ .addProjection(RevisionProperty.revisionNumber())
+ .add(RevisionProperty.gt(1))
+ .add(VersionsRestrictions.lt("number", 10))
+ .getResultList();
+
+ assert Arrays.asList(3, 4).equals(result);
+ }
+
+ @Test
+ public void testRevisionProjectionQuery() {
+ Object[] result = (Object[]) getVersionsReader().createQuery()
+ .forRevisionsOfEntity(StrIntTestEntity.class, false, true)
+ .addProjection(RevisionProperty.max())
+ .addProjection(RevisionProperty.count())
+ .addProjection(RevisionProperty.countDistinct())
+ .addProjection(RevisionProperty.min())
+ .add(VersionsRestrictions.idEq(id1))
+ .getSingleResult();
+
+ assert (Integer) result[0] == 4;
+ assert (Long) result[1] == 4;
+ assert (Long) result[2] == 4;
+ assert (Integer) result[3] == 1;
+ }
+
+ @Test
+ public void testRevisionOrderQuery() {
+ List result = getVersionsReader().createQuery()
+ .forRevisionsOfEntity(StrIntTestEntity.class, false, true)
+ .addProjection(RevisionProperty.revisionNumber())
+ .add(VersionsRestrictions.idEq(id1))
+ .addOrder(RevisionProperty.desc())
+ .getResultList();
+
+ assert Arrays.asList(4, 3, 2, 1).equals(result);
+ }
+
+ @Test
+ public void testRevisionCountQuery() {
+ // The query shouldn't be ordered as always, otherwise - we get an exception.
+ Object result = getVersionsReader().createQuery()
+ .forRevisionsOfEntity(StrIntTestEntity.class, false, true)
+ .addProjection(RevisionProperty.count())
+ .add(VersionsRestrictions.idEq(id1))
+ .getSingleResult();
+
+ assert (Long) result == 4;
+ }
+}
\ No newline at end of file
Added: core/trunk/envers/src/test/java/org/jboss/envers/test/integration/query/SimpleQuery.java
===================================================================
--- core/trunk/envers/src/test/java/org/jboss/envers/test/integration/query/SimpleQuery.java (rev 0)
+++ core/trunk/envers/src/test/java/org/jboss/envers/test/integration/query/SimpleQuery.java 2008-10-27 18:56:31 UTC (rev 15406)
@@ -0,0 +1,219 @@
+package org.jboss.envers.test.integration.query;
+
+import org.jboss.envers.test.AbstractEntityTest;
+import org.jboss.envers.test.entities.StrIntTestEntity;
+import org.jboss.envers.test.tools.TestTools;
+import org.jboss.envers.query.VersionsRestrictions;
+import org.jboss.envers.query.RevisionProperty;
+import org.jboss.envers.query.RevisionTypeProperty;
+import org.jboss.envers.RevisionType;
+import org.jboss.envers.DefaultRevisionEntity;
+import org.hibernate.ejb.Ejb3Configuration;
+import org.testng.annotations.BeforeClass;
+import org.testng.annotations.Test;
+
+import javax.persistence.EntityManager;
+import java.util.List;
+import java.util.HashSet;
+import java.util.Arrays;
+
+/**
+ * @author Adam Warski (adam at warski dot org)
+ */
+ at SuppressWarnings({"unchecked"})
+public class SimpleQuery extends AbstractEntityTest {
+ private Integer id1;
+ private Integer id2;
+ private Integer id3;
+
+ public void configure(Ejb3Configuration cfg) {
+ cfg.addAnnotatedClass(StrIntTestEntity.class);
+ }
+
+ @BeforeClass(dependsOnMethods = "init")
+ public void initData() {
+ // Revision 1
+ EntityManager em = getEntityManager();
+ em.getTransaction().begin();
+
+ StrIntTestEntity site1 = new StrIntTestEntity("a", 10);
+ StrIntTestEntity site2 = new StrIntTestEntity("a", 10);
+ StrIntTestEntity site3 = new StrIntTestEntity("b", 5);
+
+ em.persist(site1);
+ em.persist(site2);
+ em.persist(site3);
+
+ id1 = site1.getId();
+ id2 = site2.getId();
+ id3 = site3.getId();
+
+ em.getTransaction().commit();
+
+ // Revision 2
+ em.getTransaction().begin();
+
+ site1 = em.find(StrIntTestEntity.class, id1);
+ site2 = em.find(StrIntTestEntity.class, id2);
+
+ site1.setStr1("c");
+ site2.setNumber(20);
+
+ em.getTransaction().commit();
+
+ // Revision 3
+ em.getTransaction().begin();
+
+ site3 = em.find(StrIntTestEntity.class, id3);
+
+ site3.setStr1("a");
+
+ em.getTransaction().commit();
+
+ // Revision 4
+ em.getTransaction().begin();
+
+ site1 = em.find(StrIntTestEntity.class, id1);
+
+ em.remove(site1);
+
+ em.getTransaction().commit();
+ }
+
+ @Test
+ public void testEntitiesIdQuery() {
+ StrIntTestEntity ver2 = (StrIntTestEntity) getVersionsReader().createQuery()
+ .forEntitiesAtRevision(StrIntTestEntity.class, 2)
+ .add(VersionsRestrictions.idEq(id2))
+ .getSingleResult();
+
+ assert ver2.equals(new StrIntTestEntity("a", 20, id2));
+ }
+
+ @Test
+ public void testEntitiesPropertyEqualsQuery() {
+ List ver1 = getVersionsReader().createQuery()
+ .forEntitiesAtRevision(StrIntTestEntity.class, 1)
+ .add(VersionsRestrictions.eq("str1", "a"))
+ .getResultList();
+
+ List ver2 = getVersionsReader().createQuery()
+ .forEntitiesAtRevision(StrIntTestEntity.class, 2)
+ .add(VersionsRestrictions.eq("str1", "a"))
+ .getResultList();
+
+ List ver3 = getVersionsReader().createQuery()
+ .forEntitiesAtRevision(StrIntTestEntity.class, 3)
+ .add(VersionsRestrictions.eq("str1", "a"))
+ .getResultList();
+
+ assert new HashSet(ver1).equals(TestTools.makeSet(new StrIntTestEntity("a", 10, id1),
+ new StrIntTestEntity("a", 10, id2)));
+ assert new HashSet(ver2).equals(TestTools.makeSet(new StrIntTestEntity("a", 20, id2)));
+ assert new HashSet(ver3).equals(TestTools.makeSet(new StrIntTestEntity("a", 20, id2),
+ new StrIntTestEntity("a", 5, id3)));
+ }
+
+ @Test
+ public void testEntitiesPropertyLeQuery() {
+ List ver1 = getVersionsReader().createQuery()
+ .forEntitiesAtRevision(StrIntTestEntity.class, 1)
+ .add(VersionsRestrictions.le("number", 10))
+ .getResultList();
+
+ List ver2 = getVersionsReader().createQuery()
+ .forEntitiesAtRevision(StrIntTestEntity.class, 2)
+ .add(VersionsRestrictions.le("number", 10))
+ .getResultList();
+
+ List ver3 = getVersionsReader().createQuery()
+ .forEntitiesAtRevision(StrIntTestEntity.class, 3)
+ .add(VersionsRestrictions.le("number", 10))
+ .getResultList();
+
+ assert new HashSet(ver1).equals(TestTools.makeSet(new StrIntTestEntity("a", 10, id1),
+ new StrIntTestEntity("a", 10, id2), new StrIntTestEntity("b", 5, id3)));
+ assert new HashSet(ver2).equals(TestTools.makeSet(new StrIntTestEntity("c", 10, id1),
+ new StrIntTestEntity("b", 5, id3)));
+ assert new HashSet(ver3).equals(TestTools.makeSet(new StrIntTestEntity("c", 10, id1),
+ new StrIntTestEntity("a", 5, id3)));
+ }
+
+ @Test
+ public void testRevisionsPropertyEqQuery() {
+ List revs_id1 = getVersionsReader().createQuery()
+ .forRevisionsOfEntity(StrIntTestEntity.class, false, true)
+ .addProjection(RevisionProperty.revisionNumber())
+ .add(VersionsRestrictions.le("str1", "a"))
+ .add(VersionsRestrictions.idEq(id1))
+ .getResultList();
+
+ List revs_id2 = getVersionsReader().createQuery()
+ .forRevisionsOfEntity(StrIntTestEntity.class, false, true)
+ .addProjection(RevisionProperty.revisionNumber())
+ .add(VersionsRestrictions.le("str1", "a"))
+ .add(VersionsRestrictions.idEq(id2))
+ .getResultList();
+
+ List revs_id3 = getVersionsReader().createQuery()
+ .forRevisionsOfEntity(StrIntTestEntity.class, false, true)
+ .addProjection(RevisionProperty.revisionNumber())
+ .add(VersionsRestrictions.le("str1", "a"))
+ .add(VersionsRestrictions.idEq(id3))
+ .getResultList();
+
+ assert Arrays.asList(1).equals(revs_id1);
+ assert Arrays.asList(1, 2).equals(revs_id2);
+ assert Arrays.asList(3).equals(revs_id3);
+ }
+
+ @Test
+ public void testSelectEntitiesQuery() {
+ List result = getVersionsReader().createQuery()
+ .forRevisionsOfEntity(StrIntTestEntity.class, true, false)
+ .add(VersionsRestrictions.idEq(id1))
+ .getResultList();
+
+ assert result.size() == 2;
+
+ assert result.get(0).equals(new StrIntTestEntity("a", 10, id1));
+ assert result.get(1).equals(new StrIntTestEntity("c", 10, id1));
+ }
+
+ @Test
+ public void testSelectEntitiesAndRevisionsQuery() {
+ List result = getVersionsReader().createQuery()
+ .forRevisionsOfEntity(StrIntTestEntity.class, false, true)
+ .add(VersionsRestrictions.idEq(id1))
+ .getResultList();
+
+ assert result.size() == 3;
+
+ assert ((Object []) result.get(0))[0].equals(new StrIntTestEntity("a", 10, id1));
+ assert ((Object []) result.get(1))[0].equals(new StrIntTestEntity("c", 10, id1));
+ assert ((Object []) result.get(2))[0].equals(new StrIntTestEntity(null, null, id1));
+
+ assert ((DefaultRevisionEntity) ((Object []) result.get(0))[1]).getId() == 1;
+ assert ((DefaultRevisionEntity) ((Object []) result.get(1))[1]).getId() == 2;
+ assert ((DefaultRevisionEntity) ((Object []) result.get(2))[1]).getId() == 4;
+
+ assert ((Object []) result.get(0))[2].equals(RevisionType.ADD);
+ assert ((Object []) result.get(1))[2].equals(RevisionType.MOD);
+ assert ((Object []) result.get(2))[2].equals(RevisionType.DEL);
+ }
+
+ @Test
+ public void testSelectRevisionTypeQuery() {
+ List result = getVersionsReader().createQuery()
+ .forRevisionsOfEntity(StrIntTestEntity.class, false, true)
+ .addProjection(RevisionTypeProperty.revisionType())
+ .add(VersionsRestrictions.idEq(id1))
+ .getResultList();
+
+ assert result.size() == 3;
+
+ assert result.get(0).equals(RevisionType.ADD);
+ assert result.get(1).equals(RevisionType.MOD);
+ assert result.get(2).equals(RevisionType.DEL);
+ }
+}
Added: core/trunk/envers/src/test/java/org/jboss/envers/test/integration/query/ids/EmbIdOneToManyQuery.java
===================================================================
--- core/trunk/envers/src/test/java/org/jboss/envers/test/integration/query/ids/EmbIdOneToManyQuery.java (rev 0)
+++ core/trunk/envers/src/test/java/org/jboss/envers/test/integration/query/ids/EmbIdOneToManyQuery.java 2008-10-27 18:56:31 UTC (rev 15406)
@@ -0,0 +1,193 @@
+package org.jboss.envers.test.integration.query.ids;
+
+import org.hibernate.ejb.Ejb3Configuration;
+import org.jboss.envers.test.AbstractEntityTest;
+import org.jboss.envers.test.entities.onetomany.ids.SetRefEdEmbIdEntity;
+import org.jboss.envers.test.entities.onetomany.ids.SetRefIngEmbIdEntity;
+import org.jboss.envers.test.entities.ids.EmbId;
+import org.jboss.envers.test.tools.TestTools;
+import org.jboss.envers.query.VersionsRestrictions;
+import org.testng.annotations.BeforeClass;
+import org.testng.annotations.Test;
+
+import javax.persistence.EntityManager;
+import java.util.List;
+import java.util.Set;
+import java.util.HashSet;
+
+/**
+ * @author Adam Warski (adam at warski dot org)
+ */
+ at SuppressWarnings({"unchecked"})
+public class EmbIdOneToManyQuery extends AbstractEntityTest {
+ private EmbId id1;
+ private EmbId id2;
+
+ private EmbId id3;
+ private EmbId id4;
+
+ public void configure(Ejb3Configuration cfg) {
+ cfg.addAnnotatedClass(SetRefEdEmbIdEntity.class);
+ cfg.addAnnotatedClass(SetRefIngEmbIdEntity.class);
+ }
+
+ @BeforeClass(dependsOnMethods = "init")
+ public void initData() {
+ id1 = new EmbId(0, 1);
+ id2 = new EmbId(10, 11);
+ id3 = new EmbId(20, 21);
+ id4 = new EmbId(30, 31);
+
+ // Revision 1
+ EntityManager em = getEntityManager();
+ em.getTransaction().begin();
+
+ SetRefIngEmbIdEntity refIng1 = new SetRefIngEmbIdEntity(id1, "x", null);
+ SetRefIngEmbIdEntity refIng2 = new SetRefIngEmbIdEntity(id2, "y", null);
+
+ em.persist(refIng1);
+ em.persist(refIng2);
+
+ em.getTransaction().commit();
+
+ // Revision 2
+ em.getTransaction().begin();
+
+ SetRefEdEmbIdEntity refEd3 = new SetRefEdEmbIdEntity(id3, "a");
+ SetRefEdEmbIdEntity refEd4 = new SetRefEdEmbIdEntity(id4, "a");
+
+ em.persist(refEd3);
+ em.persist(refEd4);
+
+ refIng1 = em.find(SetRefIngEmbIdEntity.class, id1);
+ refIng2 = em.find(SetRefIngEmbIdEntity.class, id2);
+
+ refIng1.setReference(refEd3);
+ refIng2.setReference(refEd4);
+
+ em.getTransaction().commit();
+
+ // Revision 3
+ em.getTransaction().begin();
+
+ refEd3 = em.find(SetRefEdEmbIdEntity.class, id3);
+ refIng2 = em.find(SetRefIngEmbIdEntity.class, id2);
+ refIng2.setReference(refEd3);
+
+ em.getTransaction().commit();
+ }
+
+ @Test
+ public void testEntitiesReferencedToId3() {
+ Set rev1_related = new HashSet(getVersionsReader().createQuery()
+ .forEntitiesAtRevision(SetRefIngEmbIdEntity.class, 1)
+ .add(VersionsRestrictions.relatedIdEq("reference", id3))
+ .getResultList());
+
+ Set rev1 = new HashSet(getVersionsReader().createQuery()
+ .forEntitiesAtRevision(SetRefIngEmbIdEntity.class, 1)
+ .add(VersionsRestrictions.eq("reference", new SetRefEdEmbIdEntity(id3, null)))
+ .getResultList());
+
+ Set rev2_related = new HashSet(getVersionsReader().createQuery()
+ .forEntitiesAtRevision(SetRefIngEmbIdEntity.class, 2)
+ .add(VersionsRestrictions.relatedIdEq("reference", id3))
+ .getResultList());
+
+ Set rev2 = new HashSet(getVersionsReader().createQuery()
+ .forEntitiesAtRevision(SetRefIngEmbIdEntity.class, 2)
+ .add(VersionsRestrictions.eq("reference", new SetRefEdEmbIdEntity(id3, null)))
+ .getResultList());
+
+ Set rev3_related = new HashSet(getVersionsReader().createQuery()
+ .forEntitiesAtRevision(SetRefIngEmbIdEntity.class, 3)
+ .add(VersionsRestrictions.relatedIdEq("reference", id3))
+ .getResultList());
+
+ Set rev3 = new HashSet(getVersionsReader().createQuery()
+ .forEntitiesAtRevision(SetRefIngEmbIdEntity.class, 3)
+ .add(VersionsRestrictions.eq("reference", new SetRefEdEmbIdEntity(id3, null)))
+ .getResultList());
+
+ assert rev1.equals(rev1_related);
+ assert rev2.equals(rev2_related);
+ assert rev3.equals(rev3_related);
+
+ assert rev1.equals(TestTools.makeSet());
+ assert rev2.equals(TestTools.makeSet(new SetRefIngEmbIdEntity(id1, "x", null)));
+ assert rev3.equals(TestTools.makeSet(new SetRefIngEmbIdEntity(id1, "x", null),
+ new SetRefIngEmbIdEntity(id2, "y", null)));
+ }
+
+ @Test
+ public void testEntitiesReferencedToId4() {
+ Set rev1_related = new HashSet(getVersionsReader().createQuery()
+ .forEntitiesAtRevision(SetRefIngEmbIdEntity.class, 1)
+ .add(VersionsRestrictions.relatedIdEq("reference", id4))
+ .getResultList());
+
+ Set rev2_related = new HashSet(getVersionsReader().createQuery()
+ .forEntitiesAtRevision(SetRefIngEmbIdEntity.class, 2)
+ .add(VersionsRestrictions.relatedIdEq("reference", id4))
+ .getResultList());
+
+ Set rev3_related = new HashSet(getVersionsReader().createQuery()
+ .forEntitiesAtRevision(SetRefIngEmbIdEntity.class, 3)
+ .add(VersionsRestrictions.relatedIdEq("reference", id4))
+ .getResultList());
+
+ assert rev1_related.equals(TestTools.makeSet());
+ assert rev2_related.equals(TestTools.makeSet(new SetRefIngEmbIdEntity(id2, "y", null)));
+ assert rev3_related.equals(TestTools.makeSet());
+ }
+
+ @Test
+ public void testEntitiesReferencedByIng1ToId3() {
+ List rev1_related = getVersionsReader().createQuery()
+ .forEntitiesAtRevision(SetRefIngEmbIdEntity.class, 1)
+ .add(VersionsRestrictions.relatedIdEq("reference", id3))
+ .add(VersionsRestrictions.idEq(id1))
+ .getResultList();
+
+ Object rev2_related = getVersionsReader().createQuery()
+ .forEntitiesAtRevision(SetRefIngEmbIdEntity.class, 2)
+ .add(VersionsRestrictions.relatedIdEq("reference", id3))
+ .add(VersionsRestrictions.idEq(id1))
+ .getSingleResult();
+
+ Object rev3_related = getVersionsReader().createQuery()
+ .forEntitiesAtRevision(SetRefIngEmbIdEntity.class, 3)
+ .add(VersionsRestrictions.relatedIdEq("reference", id3))
+ .add(VersionsRestrictions.idEq(id1))
+ .getSingleResult();
+
+ assert rev1_related.size() == 0;
+ assert rev2_related.equals(new SetRefIngEmbIdEntity(id1, "x", null));
+ assert rev3_related.equals(new SetRefIngEmbIdEntity(id1, "x", null));
+ }
+
+ @Test
+ public void testEntitiesReferencedByIng2ToId3() {
+ List rev1_related = getVersionsReader().createQuery()
+ .forEntitiesAtRevision(SetRefIngEmbIdEntity.class, 1)
+ .add(VersionsRestrictions.relatedIdEq("reference", id3))
+ .add(VersionsRestrictions.idEq(id2))
+ .getResultList();
+
+ List rev2_related = getVersionsReader().createQuery()
+ .forEntitiesAtRevision(SetRefIngEmbIdEntity.class, 2)
+ .add(VersionsRestrictions.relatedIdEq("reference", id3))
+ .add(VersionsRestrictions.idEq(id2))
+ .getResultList();
+
+ Object rev3_related = getVersionsReader().createQuery()
+ .forEntitiesAtRevision(SetRefIngEmbIdEntity.class, 3)
+ .add(VersionsRestrictions.relatedIdEq("reference", id3))
+ .add(VersionsRestrictions.idEq(id2))
+ .getSingleResult();
+
+ assert rev1_related.size() == 0;
+ assert rev2_related.size() == 0;
+ assert rev3_related.equals(new SetRefIngEmbIdEntity(id2, "y", null));
+ }
+}
Added: core/trunk/envers/src/test/java/org/jboss/envers/test/integration/query/ids/MulIdOneToManyQuery.java
===================================================================
--- core/trunk/envers/src/test/java/org/jboss/envers/test/integration/query/ids/MulIdOneToManyQuery.java (rev 0)
+++ core/trunk/envers/src/test/java/org/jboss/envers/test/integration/query/ids/MulIdOneToManyQuery.java 2008-10-27 18:56:31 UTC (rev 15406)
@@ -0,0 +1,193 @@
+package org.jboss.envers.test.integration.query.ids;
+
+import org.hibernate.ejb.Ejb3Configuration;
+import org.jboss.envers.test.AbstractEntityTest;
+import org.jboss.envers.test.tools.TestTools;
+import org.jboss.envers.test.entities.ids.MulId;
+import org.jboss.envers.test.entities.onetomany.ids.SetRefEdMulIdEntity;
+import org.jboss.envers.test.entities.onetomany.ids.SetRefIngMulIdEntity;
+import org.jboss.envers.query.VersionsRestrictions;
+import org.testng.annotations.BeforeClass;
+import org.testng.annotations.Test;
+
+import javax.persistence.EntityManager;
+import java.util.List;
+import java.util.Set;
+import java.util.HashSet;
+
+/**
+ * @author Adam Warski (adam at warski dot org)
+ */
+ at SuppressWarnings({"unchecked"})
+public class MulIdOneToManyQuery extends AbstractEntityTest {
+ private MulId id1;
+ private MulId id2;
+
+ private MulId id3;
+ private MulId id4;
+
+ public void configure(Ejb3Configuration cfg) {
+ cfg.addAnnotatedClass(SetRefEdMulIdEntity.class);
+ cfg.addAnnotatedClass(SetRefIngMulIdEntity.class);
+ }
+
+ @BeforeClass(dependsOnMethods = "init")
+ public void initData() {
+ id1 = new MulId(0, 1);
+ id2 = new MulId(10, 11);
+ id3 = new MulId(20, 21);
+ id4 = new MulId(30, 31);
+
+ // Revision 1
+ EntityManager em = getEntityManager();
+ em.getTransaction().begin();
+
+ SetRefIngMulIdEntity refIng1 = new SetRefIngMulIdEntity(id1, "x", null);
+ SetRefIngMulIdEntity refIng2 = new SetRefIngMulIdEntity(id2, "y", null);
+
+ em.persist(refIng1);
+ em.persist(refIng2);
+
+ em.getTransaction().commit();
+
+ // Revision 2
+ em.getTransaction().begin();
+
+ SetRefEdMulIdEntity refEd3 = new SetRefEdMulIdEntity(id3, "a");
+ SetRefEdMulIdEntity refEd4 = new SetRefEdMulIdEntity(id4, "a");
+
+ em.persist(refEd3);
+ em.persist(refEd4);
+
+ refIng1 = em.find(SetRefIngMulIdEntity.class, id1);
+ refIng2 = em.find(SetRefIngMulIdEntity.class, id2);
+
+ refIng1.setReference(refEd3);
+ refIng2.setReference(refEd4);
+
+ em.getTransaction().commit();
+
+ // Revision 3
+ em.getTransaction().begin();
+
+ refEd3 = em.find(SetRefEdMulIdEntity.class, id3);
+ refIng2 = em.find(SetRefIngMulIdEntity.class, id2);
+ refIng2.setReference(refEd3);
+
+ em.getTransaction().commit();
+ }
+
+ @Test
+ public void testEntitiesReferencedToId3() {
+ Set rev1_related = new HashSet(getVersionsReader().createQuery()
+ .forEntitiesAtRevision(SetRefIngMulIdEntity.class, 1)
+ .add(VersionsRestrictions.relatedIdEq("reference", id3))
+ .getResultList());
+
+ Set rev1 = new HashSet(getVersionsReader().createQuery()
+ .forEntitiesAtRevision(SetRefIngMulIdEntity.class, 1)
+ .add(VersionsRestrictions.eq("reference", new SetRefEdMulIdEntity(id3, null)))
+ .getResultList());
+
+ Set rev2_related = new HashSet(getVersionsReader().createQuery()
+ .forEntitiesAtRevision(SetRefIngMulIdEntity.class, 2)
+ .add(VersionsRestrictions.relatedIdEq("reference", id3))
+ .getResultList());
+
+ Set rev2 = new HashSet(getVersionsReader().createQuery()
+ .forEntitiesAtRevision(SetRefIngMulIdEntity.class, 2)
+ .add(VersionsRestrictions.eq("reference", new SetRefEdMulIdEntity(id3, null)))
+ .getResultList());
+
+ Set rev3_related = new HashSet(getVersionsReader().createQuery()
+ .forEntitiesAtRevision(SetRefIngMulIdEntity.class, 3)
+ .add(VersionsRestrictions.relatedIdEq("reference", id3))
+ .getResultList());
+
+ Set rev3 = new HashSet(getVersionsReader().createQuery()
+ .forEntitiesAtRevision(SetRefIngMulIdEntity.class, 3)
+ .add(VersionsRestrictions.eq("reference", new SetRefEdMulIdEntity(id3, null)))
+ .getResultList());
+
+ assert rev1.equals(rev1_related);
+ assert rev2.equals(rev2_related);
+ assert rev3.equals(rev3_related);
+
+ assert rev1.equals(TestTools.makeSet());
+ assert rev2.equals(TestTools.makeSet(new SetRefIngMulIdEntity(id1, "x", null)));
+ assert rev3.equals(TestTools.makeSet(new SetRefIngMulIdEntity(id1, "x", null),
+ new SetRefIngMulIdEntity(id2, "y", null)));
+ }
+
+ @Test
+ public void testEntitiesReferencedToId4() {
+ Set rev1_related = new HashSet(getVersionsReader().createQuery()
+ .forEntitiesAtRevision(SetRefIngMulIdEntity.class, 1)
+ .add(VersionsRestrictions.relatedIdEq("reference", id4))
+ .getResultList());
+
+ Set rev2_related = new HashSet(getVersionsReader().createQuery()
+ .forEntitiesAtRevision(SetRefIngMulIdEntity.class, 2)
+ .add(VersionsRestrictions.relatedIdEq("reference", id4))
+ .getResultList());
+
+ Set rev3_related = new HashSet(getVersionsReader().createQuery()
+ .forEntitiesAtRevision(SetRefIngMulIdEntity.class, 3)
+ .add(VersionsRestrictions.relatedIdEq("reference", id4))
+ .getResultList());
+
+ assert rev1_related.equals(TestTools.makeSet());
+ assert rev2_related.equals(TestTools.makeSet(new SetRefIngMulIdEntity(id2, "y", null)));
+ assert rev3_related.equals(TestTools.makeSet());
+ }
+
+ @Test
+ public void testEntitiesReferencedByIng1ToId3() {
+ List rev1_related = getVersionsReader().createQuery()
+ .forEntitiesAtRevision(SetRefIngMulIdEntity.class, 1)
+ .add(VersionsRestrictions.relatedIdEq("reference", id3))
+ .add(VersionsRestrictions.idEq(id1))
+ .getResultList();
+
+ Object rev2_related = getVersionsReader().createQuery()
+ .forEntitiesAtRevision(SetRefIngMulIdEntity.class, 2)
+ .add(VersionsRestrictions.relatedIdEq("reference", id3))
+ .add(VersionsRestrictions.idEq(id1))
+ .getSingleResult();
+
+ Object rev3_related = getVersionsReader().createQuery()
+ .forEntitiesAtRevision(SetRefIngMulIdEntity.class, 3)
+ .add(VersionsRestrictions.relatedIdEq("reference", id3))
+ .add(VersionsRestrictions.idEq(id1))
+ .getSingleResult();
+
+ assert rev1_related.size() == 0;
+ assert rev2_related.equals(new SetRefIngMulIdEntity(id1, "x", null));
+ assert rev3_related.equals(new SetRefIngMulIdEntity(id1, "x", null));
+ }
+
+ @Test
+ public void testEntitiesReferencedByIng2ToId3() {
+ List rev1_related = getVersionsReader().createQuery()
+ .forEntitiesAtRevision(SetRefIngMulIdEntity.class, 1)
+ .add(VersionsRestrictions.relatedIdEq("reference", id3))
+ .add(VersionsRestrictions.idEq(id2))
+ .getResultList();
+
+ List rev2_related = getVersionsReader().createQuery()
+ .forEntitiesAtRevision(SetRefIngMulIdEntity.class, 2)
+ .add(VersionsRestrictions.relatedIdEq("reference", id3))
+ .add(VersionsRestrictions.idEq(id2))
+ .getResultList();
+
+ Object rev3_related = getVersionsReader().createQuery()
+ .forEntitiesAtRevision(SetRefIngMulIdEntity.class, 3)
+ .add(VersionsRestrictions.relatedIdEq("reference", id3))
+ .add(VersionsRestrictions.idEq(id2))
+ .getSingleResult();
+
+ assert rev1_related.size() == 0;
+ assert rev2_related.size() == 0;
+ assert rev3_related.equals(new SetRefIngMulIdEntity(id2, "y", null));
+ }
+}
\ No newline at end of file
Added: core/trunk/envers/src/test/java/org/jboss/envers/test/integration/reventity/Custom.java
===================================================================
--- core/trunk/envers/src/test/java/org/jboss/envers/test/integration/reventity/Custom.java (rev 0)
+++ core/trunk/envers/src/test/java/org/jboss/envers/test/integration/reventity/Custom.java 2008-10-27 18:56:31 UTC (rev 15406)
@@ -0,0 +1,111 @@
+package org.jboss.envers.test.integration.reventity;
+
+import org.jboss.envers.test.AbstractEntityTest;
+import org.jboss.envers.test.entities.StrTestEntity;
+import org.jboss.envers.test.entities.reventity.CustomRevEntity;
+import org.jboss.envers.exception.RevisionDoesNotExistException;
+import org.jboss.envers.VersionsReader;
+import org.hibernate.ejb.Ejb3Configuration;
+import org.testng.annotations.BeforeClass;
+import org.testng.annotations.Test;
+
+import javax.persistence.EntityManager;
+import java.util.Date;
+import java.util.Arrays;
+
+/**
+ * @author Adam Warski (adam at warski dot org)
+ */
+public class Custom extends AbstractEntityTest {
+ private Integer id;
+ private long timestamp1;
+ private long timestamp2;
+ private long timestamp3;
+
+ public void configure(Ejb3Configuration cfg) {
+ cfg.addAnnotatedClass(StrTestEntity.class);
+ cfg.addAnnotatedClass(CustomRevEntity.class);
+ }
+
+ @BeforeClass(dependsOnMethods = "init")
+ public void initData() throws InterruptedException {
+ timestamp1 = System.currentTimeMillis();
+
+ Thread.sleep(100);
+
+ // Revision 1
+ EntityManager em = getEntityManager();
+ em.getTransaction().begin();
+ StrTestEntity te = new StrTestEntity("x");
+ em.persist(te);
+ id = te.getId();
+ em.getTransaction().commit();
+
+ timestamp2 = System.currentTimeMillis();
+
+ Thread.sleep(100);
+
+ // Revision 2
+ em.getTransaction().begin();
+ te = em.find(StrTestEntity.class, id);
+ te.setStr("y");
+ em.getTransaction().commit();
+
+ timestamp3 = System.currentTimeMillis();
+ }
+
+ @Test(expectedExceptions = RevisionDoesNotExistException.class)
+ public void testTimestamps1() {
+ getVersionsReader().getRevisionNumberForDate(new Date(timestamp1));
+ }
+
+ @Test
+ public void testTimestamps() {
+ assert getVersionsReader().getRevisionNumberForDate(new Date(timestamp2)).intValue() == 1;
+ assert getVersionsReader().getRevisionNumberForDate(new Date(timestamp3)).intValue() == 2;
+ }
+
+ @Test
+ public void testDatesForRevisions() {
+ VersionsReader vr = getVersionsReader();
+ assert vr.getRevisionNumberForDate(vr.getRevisionDate(1)).intValue() == 1;
+ assert vr.getRevisionNumberForDate(vr.getRevisionDate(2)).intValue() == 2;
+ }
+
+ @Test
+ public void testRevisionsForDates() {
+ VersionsReader vr = getVersionsReader();
+
+ assert vr.getRevisionDate(vr.getRevisionNumberForDate(new Date(timestamp2))).getTime() <= timestamp2;
+ assert vr.getRevisionDate(vr.getRevisionNumberForDate(new Date(timestamp2)).intValue()+1).getTime() > timestamp2;
+
+ assert vr.getRevisionDate(vr.getRevisionNumberForDate(new Date(timestamp3))).getTime() <= timestamp3;
+ }
+
+ @Test
+ public void testFindRevision() {
+ VersionsReader vr = getVersionsReader();
+
+ long rev1Timestamp = vr.findRevision(CustomRevEntity.class, 1).getCustomTimestamp();
+ assert rev1Timestamp > timestamp1;
+ assert rev1Timestamp <= timestamp2;
+
+ long rev2Timestamp = vr.findRevision(CustomRevEntity.class, 2).getCustomTimestamp();
+ assert rev2Timestamp > timestamp2;
+ assert rev2Timestamp <= timestamp3;
+ }
+
+ @Test
+ public void testRevisionsCounts() {
+ assert Arrays.asList(1, 2).equals(getVersionsReader().getRevisions(StrTestEntity.class, id));
+ }
+
+ @Test
+ public void testHistoryOfId1() {
+ StrTestEntity ver1 = new StrTestEntity("x", id);
+ StrTestEntity ver2 = new StrTestEntity("y", id);
+
+ assert getVersionsReader().find(StrTestEntity.class, id, 1).equals(ver1);
+ assert getVersionsReader().find(StrTestEntity.class, id, 2).equals(ver2);
+ }
+}
Added: core/trunk/envers/src/test/java/org/jboss/envers/test/integration/reventity/CustomBoxed.java
===================================================================
--- core/trunk/envers/src/test/java/org/jboss/envers/test/integration/reventity/CustomBoxed.java (rev 0)
+++ core/trunk/envers/src/test/java/org/jboss/envers/test/integration/reventity/CustomBoxed.java 2008-10-27 18:56:31 UTC (rev 15406)
@@ -0,0 +1,110 @@
+package org.jboss.envers.test.integration.reventity;
+
+import org.jboss.envers.test.AbstractEntityTest;
+import org.jboss.envers.test.entities.StrTestEntity;
+import org.jboss.envers.exception.RevisionDoesNotExistException;
+import org.jboss.envers.VersionsReader;
+import org.hibernate.ejb.Ejb3Configuration;
+import org.testng.annotations.BeforeClass;
+import org.testng.annotations.Test;
+
+import javax.persistence.EntityManager;
+import java.util.Date;
+import java.util.Arrays;
+
+/**
+ * @author Adam Warski (adam at warski dot org)
+ */
+public class CustomBoxed extends AbstractEntityTest {
+ private Integer id;
+ private long timestamp1;
+ private long timestamp2;
+ private long timestamp3;
+
+ public void configure(Ejb3Configuration cfg) {
+ cfg.addAnnotatedClass(StrTestEntity.class);
+ cfg.addAnnotatedClass(CustomBoxedRevEntity.class);
+ }
+
+ @BeforeClass(dependsOnMethods = "init")
+ public void initData() throws InterruptedException {
+ timestamp1 = System.currentTimeMillis();
+
+ Thread.sleep(100);
+
+ // Revision 1
+ EntityManager em = getEntityManager();
+ em.getTransaction().begin();
+ StrTestEntity te = new StrTestEntity("x");
+ em.persist(te);
+ id = te.getId();
+ em.getTransaction().commit();
+
+ timestamp2 = System.currentTimeMillis();
+
+ Thread.sleep(100);
+
+ // Revision 2
+ em.getTransaction().begin();
+ te = em.find(StrTestEntity.class, id);
+ te.setStr("y");
+ em.getTransaction().commit();
+
+ timestamp3 = System.currentTimeMillis();
+ }
+
+ @Test(expectedExceptions = RevisionDoesNotExistException.class)
+ public void testTimestamps1() {
+ getVersionsReader().getRevisionNumberForDate(new Date(timestamp1));
+ }
+
+ @Test
+ public void testTimestamps() {
+ assert getVersionsReader().getRevisionNumberForDate(new Date(timestamp2)).intValue() == 1;
+ assert getVersionsReader().getRevisionNumberForDate(new Date(timestamp3)).intValue() == 2;
+ }
+
+ @Test
+ public void testDatesForRevisions() {
+ VersionsReader vr = getVersionsReader();
+ assert vr.getRevisionNumberForDate(vr.getRevisionDate(1)).intValue() == 1;
+ assert vr.getRevisionNumberForDate(vr.getRevisionDate(2)).intValue() == 2;
+ }
+
+ @Test
+ public void testRevisionsForDates() {
+ VersionsReader vr = getVersionsReader();
+
+ assert vr.getRevisionDate(vr.getRevisionNumberForDate(new Date(timestamp2))).getTime() <= timestamp2;
+ assert vr.getRevisionDate(vr.getRevisionNumberForDate(new Date(timestamp2)).intValue()+1).getTime() > timestamp2;
+
+ assert vr.getRevisionDate(vr.getRevisionNumberForDate(new Date(timestamp3))).getTime() <= timestamp3;
+ }
+
+ @Test
+ public void testFindRevision() {
+ VersionsReader vr = getVersionsReader();
+
+ long rev1Timestamp = vr.findRevision(CustomBoxedRevEntity.class, 1).getCustomTimestamp();
+ assert rev1Timestamp > timestamp1;
+ assert rev1Timestamp <= timestamp2;
+
+ long rev2Timestamp = vr.findRevision(CustomBoxedRevEntity.class, 2).getCustomTimestamp();
+ assert rev2Timestamp > timestamp2;
+ assert rev2Timestamp <= timestamp3;
+ }
+
+ @Test
+ public void testRevisionsCounts() {
+ assert Arrays.asList(1, 2).equals(getVersionsReader().getRevisions(StrTestEntity.class, id));
+ }
+
+ @Test
+ public void testHistoryOfId1() {
+ StrTestEntity ver1 = new StrTestEntity("x", id);
+ StrTestEntity ver2 = new StrTestEntity("y", id);
+
+ assert getVersionsReader().find(StrTestEntity.class, id, 1).equals(ver1);
+ assert getVersionsReader().find(StrTestEntity.class, id, 2).equals(ver2);
+ }
+}
\ No newline at end of file
Added: core/trunk/envers/src/test/java/org/jboss/envers/test/integration/reventity/CustomBoxedRevEntity.java
===================================================================
--- core/trunk/envers/src/test/java/org/jboss/envers/test/integration/reventity/CustomBoxedRevEntity.java (rev 0)
+++ core/trunk/envers/src/test/java/org/jboss/envers/test/integration/reventity/CustomBoxedRevEntity.java 2008-10-27 18:56:31 UTC (rev 15406)
@@ -0,0 +1,60 @@
+package org.jboss.envers.test.integration.reventity;
+
+import org.jboss.envers.RevisionNumber;
+import org.jboss.envers.RevisionTimestamp;
+import org.jboss.envers.RevisionEntity;
+
+import javax.persistence.Id;
+import javax.persistence.GeneratedValue;
+import javax.persistence.Entity;
+
+/**
+ * @author Adam Warski (adam at warski dot org)
+ */
+ at Entity
+ at RevisionEntity
+public class CustomBoxedRevEntity {
+ @Id
+ @GeneratedValue
+ @RevisionNumber
+ private Integer customId;
+
+ @RevisionTimestamp
+ private Long customTimestamp;
+
+ public Integer getCustomId() {
+ return customId;
+ }
+
+ public void setCustomId(Integer customId) {
+ this.customId = customId;
+ }
+
+ public Long getCustomTimestamp() {
+ return customTimestamp;
+ }
+
+ public void setCustomTimestamp(Long customTimestamp) {
+ this.customTimestamp = customTimestamp;
+ }
+
+ public boolean equals(Object o) {
+ if (this == o) return true;
+ if (!(o instanceof CustomBoxedRevEntity)) return false;
+
+ CustomBoxedRevEntity that = (CustomBoxedRevEntity) o;
+
+ if (customId != null ? !customId.equals(that.customId) : that.customId != null) return false;
+ if (customTimestamp != null ? !customTimestamp.equals(that.customTimestamp) : that.customTimestamp != null)
+ return false;
+
+ return true;
+ }
+
+ public int hashCode() {
+ int result;
+ result = (customId != null ? customId.hashCode() : 0);
+ result = 31 * result + (customTimestamp != null ? customTimestamp.hashCode() : 0);
+ return result;
+ }
+}
\ No newline at end of file
Added: core/trunk/envers/src/test/java/org/jboss/envers/test/integration/reventity/CustomPropertyAccess.java
===================================================================
--- core/trunk/envers/src/test/java/org/jboss/envers/test/integration/reventity/CustomPropertyAccess.java (rev 0)
+++ core/trunk/envers/src/test/java/org/jboss/envers/test/integration/reventity/CustomPropertyAccess.java 2008-10-27 18:56:31 UTC (rev 15406)
@@ -0,0 +1,111 @@
+package org.jboss.envers.test.integration.reventity;
+
+import org.jboss.envers.test.AbstractEntityTest;
+import org.jboss.envers.test.entities.StrTestEntity;
+import org.jboss.envers.test.entities.reventity.CustomPropertyAccessRevEntity;
+import org.jboss.envers.exception.RevisionDoesNotExistException;
+import org.jboss.envers.VersionsReader;
+import org.hibernate.ejb.Ejb3Configuration;
+import org.testng.annotations.BeforeClass;
+import org.testng.annotations.Test;
+
+import javax.persistence.EntityManager;
+import java.util.Date;
+import java.util.Arrays;
+
+/**
+ * @author Adam Warski (adam at warski dot org)
+ */
+public class CustomPropertyAccess extends AbstractEntityTest {
+ private Integer id;
+ private long timestamp1;
+ private long timestamp2;
+ private long timestamp3;
+
+ public void configure(Ejb3Configuration cfg) {
+ cfg.addAnnotatedClass(StrTestEntity.class);
+ cfg.addAnnotatedClass(CustomPropertyAccessRevEntity.class);
+ }
+
+ @BeforeClass(dependsOnMethods = "init")
+ public void initData() throws InterruptedException {
+ timestamp1 = System.currentTimeMillis();
+
+ Thread.sleep(100);
+
+ // Revision 1
+ EntityManager em = getEntityManager();
+ em.getTransaction().begin();
+ StrTestEntity te = new StrTestEntity("x");
+ em.persist(te);
+ id = te.getId();
+ em.getTransaction().commit();
+
+ timestamp2 = System.currentTimeMillis();
+
+ Thread.sleep(100);
+
+ // Revision 2
+ em.getTransaction().begin();
+ te = em.find(StrTestEntity.class, id);
+ te.setStr("y");
+ em.getTransaction().commit();
+
+ timestamp3 = System.currentTimeMillis();
+ }
+
+ @Test(expectedExceptions = RevisionDoesNotExistException.class)
+ public void testTimestamps1() {
+ getVersionsReader().getRevisionNumberForDate(new Date(timestamp1));
+ }
+
+ @Test
+ public void testTimestamps() {
+ assert getVersionsReader().getRevisionNumberForDate(new Date(timestamp2)).intValue() == 1;
+ assert getVersionsReader().getRevisionNumberForDate(new Date(timestamp3)).intValue() == 2;
+ }
+
+ @Test
+ public void testDatesForRevisions() {
+ VersionsReader vr = getVersionsReader();
+ assert vr.getRevisionNumberForDate(vr.getRevisionDate(1)).intValue() == 1;
+ assert vr.getRevisionNumberForDate(vr.getRevisionDate(2)).intValue() == 2;
+ }
+
+ @Test
+ public void testRevisionsForDates() {
+ VersionsReader vr = getVersionsReader();
+
+ assert vr.getRevisionDate(vr.getRevisionNumberForDate(new Date(timestamp2))).getTime() <= timestamp2;
+ assert vr.getRevisionDate(vr.getRevisionNumberForDate(new Date(timestamp2)).intValue()+1).getTime() > timestamp2;
+
+ assert vr.getRevisionDate(vr.getRevisionNumberForDate(new Date(timestamp3))).getTime() <= timestamp3;
+ }
+
+ @Test
+ public void testFindRevision() {
+ VersionsReader vr = getVersionsReader();
+
+ long rev1Timestamp = vr.findRevision(CustomPropertyAccessRevEntity.class, 1).getCustomTimestamp();
+ assert rev1Timestamp > timestamp1;
+ assert rev1Timestamp <= timestamp2;
+
+ long rev2Timestamp = vr.findRevision(CustomPropertyAccessRevEntity.class, 2).getCustomTimestamp();
+ assert rev2Timestamp > timestamp2;
+ assert rev2Timestamp <= timestamp3;
+ }
+
+ @Test
+ public void testRevisionsCounts() {
+ assert Arrays.asList(1, 2).equals(getVersionsReader().getRevisions(StrTestEntity.class, id));
+ }
+
+ @Test
+ public void testHistoryOfId1() {
+ StrTestEntity ver1 = new StrTestEntity("x", id);
+ StrTestEntity ver2 = new StrTestEntity("y", id);
+
+ assert getVersionsReader().find(StrTestEntity.class, id, 1).equals(ver1);
+ assert getVersionsReader().find(StrTestEntity.class, id, 2).equals(ver2);
+ }
+}
\ No newline at end of file
Added: core/trunk/envers/src/test/java/org/jboss/envers/test/integration/reventity/Inherited.java
===================================================================
--- core/trunk/envers/src/test/java/org/jboss/envers/test/integration/reventity/Inherited.java (rev 0)
+++ core/trunk/envers/src/test/java/org/jboss/envers/test/integration/reventity/Inherited.java 2008-10-27 18:56:31 UTC (rev 15406)
@@ -0,0 +1,110 @@
+package org.jboss.envers.test.integration.reventity;
+
+import org.jboss.envers.test.AbstractEntityTest;
+import org.jboss.envers.test.entities.StrTestEntity;
+import org.jboss.envers.exception.RevisionDoesNotExistException;
+import org.jboss.envers.VersionsReader;
+import org.hibernate.ejb.Ejb3Configuration;
+import org.testng.annotations.BeforeClass;
+import org.testng.annotations.Test;
+
+import javax.persistence.EntityManager;
+import java.util.Date;
+import java.util.Arrays;
+
+/**
+ * @author Adam Warski (adam at warski dot org)
+ */
+public class Inherited extends AbstractEntityTest {
+ private Integer id;
+ private long timestamp1;
+ private long timestamp2;
+ private long timestamp3;
+
+ public void configure(Ejb3Configuration cfg) {
+ cfg.addAnnotatedClass(StrTestEntity.class);
+ cfg.addAnnotatedClass(InheritedRevEntity.class);
+ }
+
+ @BeforeClass(dependsOnMethods = "init")
+ public void initData() throws InterruptedException {
+ timestamp1 = System.currentTimeMillis();
+
+ Thread.sleep(100);
+
+ // Revision 1
+ EntityManager em = getEntityManager();
+ em.getTransaction().begin();
+ StrTestEntity te = new StrTestEntity("x");
+ em.persist(te);
+ id = te.getId();
+ em.getTransaction().commit();
+
+ timestamp2 = System.currentTimeMillis();
+
+ Thread.sleep(100);
+
+ // Revision 2
+ em.getTransaction().begin();
+ te = em.find(StrTestEntity.class, id);
+ te.setStr("y");
+ em.getTransaction().commit();
+
+ timestamp3 = System.currentTimeMillis();
+ }
+
+ @Test(expectedExceptions = RevisionDoesNotExistException.class)
+ public void testTimestamps1() {
+ getVersionsReader().getRevisionNumberForDate(new Date(timestamp1));
+ }
+
+ @Test
+ public void testTimestamps() {
+ assert getVersionsReader().getRevisionNumberForDate(new Date(timestamp2)).intValue() == 1;
+ assert getVersionsReader().getRevisionNumberForDate(new Date(timestamp3)).intValue() == 2;
+ }
+
+ @Test
+ public void testDatesForRevisions() {
+ VersionsReader vr = getVersionsReader();
+ assert vr.getRevisionNumberForDate(vr.getRevisionDate(1)).intValue() == 1;
+ assert vr.getRevisionNumberForDate(vr.getRevisionDate(2)).intValue() == 2;
+ }
+
+ @Test
+ public void testRevisionsForDates() {
+ VersionsReader vr = getVersionsReader();
+
+ assert vr.getRevisionDate(vr.getRevisionNumberForDate(new Date(timestamp2))).getTime() <= timestamp2;
+ assert vr.getRevisionDate(vr.getRevisionNumberForDate(new Date(timestamp2)).intValue()+1).getTime() > timestamp2;
+
+ assert vr.getRevisionDate(vr.getRevisionNumberForDate(new Date(timestamp3))).getTime() <= timestamp3;
+ }
+
+ @Test
+ public void testFindRevision() {
+ VersionsReader vr = getVersionsReader();
+
+ long rev1Timestamp = vr.findRevision(InheritedRevEntity.class, 1).getTimestamp();
+ assert rev1Timestamp > timestamp1;
+ assert rev1Timestamp <= timestamp2;
+
+ long rev2Timestamp = vr.findRevision(InheritedRevEntity.class, 2).getTimestamp();
+ assert rev2Timestamp > timestamp2;
+ assert rev2Timestamp <= timestamp3;
+ }
+
+ @Test
+ public void testRevisionsCounts() {
+ assert Arrays.asList(1, 2).equals(getVersionsReader().getRevisions(StrTestEntity.class, id));
+ }
+
+ @Test
+ public void testHistoryOfId1() {
+ StrTestEntity ver1 = new StrTestEntity("x", id);
+ StrTestEntity ver2 = new StrTestEntity("y", id);
+
+ assert getVersionsReader().find(StrTestEntity.class, id, 1).equals(ver1);
+ assert getVersionsReader().find(StrTestEntity.class, id, 2).equals(ver2);
+ }
+}
Added: core/trunk/envers/src/test/java/org/jboss/envers/test/integration/reventity/InheritedRevEntity.java
===================================================================
--- core/trunk/envers/src/test/java/org/jboss/envers/test/integration/reventity/InheritedRevEntity.java (rev 0)
+++ core/trunk/envers/src/test/java/org/jboss/envers/test/integration/reventity/InheritedRevEntity.java 2008-10-27 18:56:31 UTC (rev 15406)
@@ -0,0 +1,15 @@
+package org.jboss.envers.test.integration.reventity;
+
+import org.jboss.envers.RevisionEntity;
+import org.jboss.envers.DefaultRevisionEntity;
+
+import javax.persistence.Entity;
+
+/**
+ * @author Adam Warski (adam at warski dot org)
+ */
+ at Entity
+ at RevisionEntity
+public class InheritedRevEntity extends DefaultRevisionEntity {
+
+}
Added: core/trunk/envers/src/test/java/org/jboss/envers/test/integration/reventity/Listener.java
===================================================================
--- core/trunk/envers/src/test/java/org/jboss/envers/test/integration/reventity/Listener.java (rev 0)
+++ core/trunk/envers/src/test/java/org/jboss/envers/test/integration/reventity/Listener.java 2008-10-27 18:56:31 UTC (rev 15406)
@@ -0,0 +1,123 @@
+package org.jboss.envers.test.integration.reventity;
+
+import org.jboss.envers.test.AbstractEntityTest;
+import org.jboss.envers.test.entities.StrTestEntity;
+import org.jboss.envers.exception.RevisionDoesNotExistException;
+import org.jboss.envers.VersionsReader;
+import org.hibernate.ejb.Ejb3Configuration;
+import org.testng.annotations.BeforeClass;
+import org.testng.annotations.Test;
+
+import javax.persistence.EntityManager;
+import java.util.Date;
+import java.util.Arrays;
+
+/**
+ * @author Adam Warski (adam at warski dot org)
+ */
+public class Listener extends AbstractEntityTest {
+ private Integer id;
+ private long timestamp1;
+ private long timestamp2;
+ private long timestamp3;
+
+ public void configure(Ejb3Configuration cfg) {
+ cfg.addAnnotatedClass(StrTestEntity.class);
+ cfg.addAnnotatedClass(ListenerRevEntity.class);
+ }
+
+ @BeforeClass(dependsOnMethods = "init")
+ public void initData() throws InterruptedException {
+ timestamp1 = System.currentTimeMillis();
+
+ Thread.sleep(100);
+
+ // Revision 1
+ EntityManager em = getEntityManager();
+ em.getTransaction().begin();
+
+ TestRevisionListener.data = "data1";
+
+ StrTestEntity te = new StrTestEntity("x");
+ em.persist(te);
+ id = te.getId();
+ em.getTransaction().commit();
+
+ timestamp2 = System.currentTimeMillis();
+
+ Thread.sleep(100);
+
+ // Revision 2
+ em.getTransaction().begin();
+ te = em.find(StrTestEntity.class, id);
+
+ TestRevisionListener.data = "data2";
+
+ te.setStr("y");
+ em.getTransaction().commit();
+
+ timestamp3 = System.currentTimeMillis();
+ }
+
+ @Test(expectedExceptions = RevisionDoesNotExistException.class)
+ public void testTimestamps1() {
+ getVersionsReader().getRevisionNumberForDate(new Date(timestamp1));
+ }
+
+ @Test
+ public void testTimestamps() {
+ assert getVersionsReader().getRevisionNumberForDate(new Date(timestamp2)).intValue() == 1;
+ assert getVersionsReader().getRevisionNumberForDate(new Date(timestamp3)).intValue() == 2;
+ }
+
+ @Test
+ public void testDatesForRevisions() {
+ VersionsReader vr = getVersionsReader();
+ assert vr.getRevisionNumberForDate(vr.getRevisionDate(1)).intValue() == 1;
+ assert vr.getRevisionNumberForDate(vr.getRevisionDate(2)).intValue() == 2;
+ }
+
+ @Test
+ public void testRevisionsForDates() {
+ VersionsReader vr = getVersionsReader();
+
+ assert vr.getRevisionDate(vr.getRevisionNumberForDate(new Date(timestamp2))).getTime() <= timestamp2;
+ assert vr.getRevisionDate(vr.getRevisionNumberForDate(new Date(timestamp2)).intValue()+1).getTime() > timestamp2;
+
+ assert vr.getRevisionDate(vr.getRevisionNumberForDate(new Date(timestamp3))).getTime() <= timestamp3;
+ }
+
+ @Test
+ public void testFindRevision() {
+ VersionsReader vr = getVersionsReader();
+
+ ListenerRevEntity rev1Data = vr.findRevision(ListenerRevEntity.class, 1);
+ ListenerRevEntity rev2Data = vr.findRevision(ListenerRevEntity.class, 2);
+
+ long rev1Timestamp = rev1Data.getTimestamp();
+ assert rev1Timestamp > timestamp1;
+ assert rev1Timestamp <= timestamp2;
+
+ assert "data1".equals(rev1Data.getData());
+
+ long rev2Timestamp = rev2Data.getTimestamp();
+ assert rev2Timestamp > timestamp2;
+ assert rev2Timestamp <= timestamp3;
+
+ assert "data2".equals(rev2Data.getData());
+ }
+
+ @Test
+ public void testRevisionsCounts() {
+ assert Arrays.asList(1, 2).equals(getVersionsReader().getRevisions(StrTestEntity.class, id));
+ }
+
+ @Test
+ public void testHistoryOfId1() {
+ StrTestEntity ver1 = new StrTestEntity("x", id);
+ StrTestEntity ver2 = new StrTestEntity("y", id);
+
+ assert getVersionsReader().find(StrTestEntity.class, id, 1).equals(ver1);
+ assert getVersionsReader().find(StrTestEntity.class, id, 2).equals(ver2);
+ }
+}
Added: core/trunk/envers/src/test/java/org/jboss/envers/test/integration/reventity/ListenerRevEntity.java
===================================================================
--- core/trunk/envers/src/test/java/org/jboss/envers/test/integration/reventity/ListenerRevEntity.java (rev 0)
+++ core/trunk/envers/src/test/java/org/jboss/envers/test/integration/reventity/ListenerRevEntity.java 2008-10-27 18:56:31 UTC (rev 15406)
@@ -0,0 +1,69 @@
+package org.jboss.envers.test.integration.reventity;
+
+import org.jboss.envers.RevisionNumber;
+import org.jboss.envers.RevisionTimestamp;
+import org.jboss.envers.RevisionEntity;
+
+import javax.persistence.Id;
+import javax.persistence.GeneratedValue;
+import javax.persistence.Entity;
+
+/**
+ * @author Adam Warski (adam at warski dot org)
+ */
+ at Entity
+ at RevisionEntity(TestRevisionListener.class)
+public class ListenerRevEntity {
+ @Id
+ @GeneratedValue
+ @RevisionNumber
+ private int id;
+
+ @RevisionTimestamp
+ private long timestamp;
+
+ private String data;
+
+ public int getId() {
+ return id;
+ }
+
+ public void setId(int id) {
+ this.id = id;
+ }
+
+ public long getTimestamp() {
+ return timestamp;
+ }
+
+ public void setTimestamp(long timestamp) {
+ this.timestamp = timestamp;
+ }
+
+ public String getData() {
+ return data;
+ }
+
+ public void setData(String data) {
+ this.data = data;
+ }
+
+ public boolean equals(Object o) {
+ if (this == o) return true;
+ if (!(o instanceof ListenerRevEntity)) return false;
+
+ ListenerRevEntity revEntity = (ListenerRevEntity) o;
+
+ if (id != revEntity.id) return false;
+ if (timestamp != revEntity.timestamp) return false;
+
+ return true;
+ }
+
+ public int hashCode() {
+ int result;
+ result = id;
+ result = 31 * result + (int) (timestamp ^ (timestamp >>> 32));
+ return result;
+ }
+}
Added: core/trunk/envers/src/test/java/org/jboss/envers/test/integration/reventity/LongRevNumber.java
===================================================================
--- core/trunk/envers/src/test/java/org/jboss/envers/test/integration/reventity/LongRevNumber.java (rev 0)
+++ core/trunk/envers/src/test/java/org/jboss/envers/test/integration/reventity/LongRevNumber.java 2008-10-27 18:56:31 UTC (rev 15406)
@@ -0,0 +1,62 @@
+package org.jboss.envers.test.integration.reventity;
+
+import org.jboss.envers.test.AbstractEntityTest;
+import org.jboss.envers.test.entities.StrTestEntity;
+import org.jboss.envers.VersionsReader;
+import org.hibernate.ejb.Ejb3Configuration;
+import org.testng.annotations.BeforeClass;
+import org.testng.annotations.Test;
+
+import javax.persistence.EntityManager;
+import java.util.Arrays;
+
+/**
+ * @author Adam Warski (adam at warski dot org)
+ */
+public class LongRevNumber extends AbstractEntityTest {
+ private Integer id;
+
+ public void configure(Ejb3Configuration cfg) {
+ cfg.addAnnotatedClass(StrTestEntity.class);
+ cfg.addAnnotatedClass(LongRevNumberRevEntity.class);
+ }
+
+ @BeforeClass(dependsOnMethods = "init")
+ public void initData() throws InterruptedException {
+ // Revision 1
+ EntityManager em = getEntityManager();
+ em.getTransaction().begin();
+ StrTestEntity te = new StrTestEntity("x");
+ em.persist(te);
+ id = te.getId();
+ em.getTransaction().commit();
+
+ // Revision 2
+ em.getTransaction().begin();
+ te = em.find(StrTestEntity.class, id);
+ te.setStr("y");
+ em.getTransaction().commit();
+ }
+
+ @Test
+ public void testFindRevision() {
+ VersionsReader vr = getVersionsReader();
+
+ assert vr.findRevision(LongRevNumberRevEntity.class, 1l).getCustomId() == 1l;
+ assert vr.findRevision(LongRevNumberRevEntity.class, 2l).getCustomId() == 2l;
+ }
+
+ @Test
+ public void testRevisionsCounts() {
+ assert Arrays.asList(1l, 2l).equals(getVersionsReader().getRevisions(StrTestEntity.class, id));
+ }
+
+ @Test
+ public void testHistoryOfId1() {
+ StrTestEntity ver1 = new StrTestEntity("x", id);
+ StrTestEntity ver2 = new StrTestEntity("y", id);
+
+ assert getVersionsReader().find(StrTestEntity.class, id, 1l).equals(ver1);
+ assert getVersionsReader().find(StrTestEntity.class, id, 2l).equals(ver2);
+ }
+}
\ No newline at end of file
Added: core/trunk/envers/src/test/java/org/jboss/envers/test/integration/reventity/LongRevNumberRevEntity.java
===================================================================
--- core/trunk/envers/src/test/java/org/jboss/envers/test/integration/reventity/LongRevNumberRevEntity.java (rev 0)
+++ core/trunk/envers/src/test/java/org/jboss/envers/test/integration/reventity/LongRevNumberRevEntity.java 2008-10-27 18:56:31 UTC (rev 15406)
@@ -0,0 +1,59 @@
+package org.jboss.envers.test.integration.reventity;
+
+import org.jboss.envers.RevisionNumber;
+import org.jboss.envers.RevisionTimestamp;
+import org.jboss.envers.RevisionEntity;
+
+import javax.persistence.Id;
+import javax.persistence.GeneratedValue;
+import javax.persistence.Entity;
+
+/**
+ * @author Adam Warski (adam at warski dot org)
+ */
+ at Entity
+ at RevisionEntity
+public class LongRevNumberRevEntity {
+ @Id
+ @GeneratedValue
+ @RevisionNumber
+ private long customId;
+
+ @RevisionTimestamp
+ private long customTimestamp;
+
+ public long getCustomId() {
+ return customId;
+ }
+
+ public void setCustomId(long customId) {
+ this.customId = customId;
+ }
+
+ public long getCustomTimestamp() {
+ return customTimestamp;
+ }
+
+ public void setCustomTimestamp(long customTimestamp) {
+ this.customTimestamp = customTimestamp;
+ }
+
+ public boolean equals(Object o) {
+ if (this == o) return true;
+ if (!(o instanceof LongRevNumberRevEntity)) return false;
+
+ LongRevNumberRevEntity that = (LongRevNumberRevEntity) o;
+
+ if (customId != that.customId) return false;
+ if (customTimestamp != that.customTimestamp) return false;
+
+ return true;
+ }
+
+ public int hashCode() {
+ int result;
+ result = (int) (customId ^ (customId >>> 32));
+ result = 31 * result + (int) (customTimestamp ^ (customTimestamp >>> 32));
+ return result;
+ }
+}
\ No newline at end of file
Added: core/trunk/envers/src/test/java/org/jboss/envers/test/integration/reventity/TestRevisionListener.java
===================================================================
--- core/trunk/envers/src/test/java/org/jboss/envers/test/integration/reventity/TestRevisionListener.java (rev 0)
+++ core/trunk/envers/src/test/java/org/jboss/envers/test/integration/reventity/TestRevisionListener.java 2008-10-27 18:56:31 UTC (rev 15406)
@@ -0,0 +1,14 @@
+package org.jboss.envers.test.integration.reventity;
+
+import org.jboss.envers.RevisionListener;
+
+/**
+ * @author Adam Warski (adam at warski dot org)
+ */
+public class TestRevisionListener implements RevisionListener {
+ public static String data = "data0";
+
+ public void newRevision(Object revisionEntity) {
+ ((ListenerRevEntity) revisionEntity).setData(data);
+ }
+}
Added: core/trunk/envers/src/test/java/org/jboss/envers/test/integration/revfordate/RevisionForDate.java
===================================================================
--- core/trunk/envers/src/test/java/org/jboss/envers/test/integration/revfordate/RevisionForDate.java (rev 0)
+++ core/trunk/envers/src/test/java/org/jboss/envers/test/integration/revfordate/RevisionForDate.java 2008-10-27 18:56:31 UTC (rev 15406)
@@ -0,0 +1,96 @@
+package org.jboss.envers.test.integration.revfordate;
+
+import org.jboss.envers.test.AbstractEntityTest;
+import org.jboss.envers.test.entities.StrTestEntity;
+import org.jboss.envers.exception.RevisionDoesNotExistException;
+import org.jboss.envers.VersionsReader;
+import org.hibernate.ejb.Ejb3Configuration;
+import org.testng.annotations.BeforeClass;
+import org.testng.annotations.Test;
+
+import javax.persistence.EntityManager;
+import java.util.Date;
+
+/**
+ * @author Adam Warski (adam at warski dot org)
+ */
+public class RevisionForDate extends AbstractEntityTest {
+ private long timestamp1;
+ private long timestamp2;
+ private long timestamp3;
+ private long timestamp4;
+
+ public void configure(Ejb3Configuration cfg) {
+ cfg.addAnnotatedClass(StrTestEntity.class);
+ }
+
+ @BeforeClass(dependsOnMethods = "init")
+ public void initData() throws InterruptedException {
+ timestamp1 = System.currentTimeMillis();
+
+ Thread.sleep(100);
+
+ // Revision 1
+ EntityManager em = getEntityManager();
+ em.getTransaction().begin();
+ StrTestEntity rfd = new StrTestEntity("x");
+ em.persist(rfd);
+ Integer id = rfd.getId();
+ em.getTransaction().commit();
+
+ timestamp2 = System.currentTimeMillis();
+
+ Thread.sleep(100);
+
+ // Revision 2
+ em.getTransaction().begin();
+ rfd = em.find(StrTestEntity.class, id);
+ rfd.setStr("y");
+ em.getTransaction().commit();
+
+ timestamp3 = System.currentTimeMillis();
+
+ Thread.sleep(100);
+
+ // Revision 3
+ em.getTransaction().begin();
+ rfd = em.find(StrTestEntity.class, id);
+ rfd.setStr("z");
+ em.getTransaction().commit();
+
+ timestamp4 = System.currentTimeMillis();
+ }
+
+ @Test(expectedExceptions = RevisionDoesNotExistException.class)
+ public void testTimestamps1() {
+ getVersionsReader().getRevisionNumberForDate(new Date(timestamp1));
+ }
+
+ @Test
+ public void testTimestamps() {
+ assert getVersionsReader().getRevisionNumberForDate(new Date(timestamp2)).intValue() == 1;
+ assert getVersionsReader().getRevisionNumberForDate(new Date(timestamp3)).intValue() == 2;
+ assert getVersionsReader().getRevisionNumberForDate(new Date(timestamp4)).intValue() == 3;
+ }
+
+ @Test
+ public void testDatesForRevisions() {
+ VersionsReader vr = getVersionsReader();
+ assert vr.getRevisionNumberForDate(vr.getRevisionDate(1)).intValue() == 1;
+ assert vr.getRevisionNumberForDate(vr.getRevisionDate(2)).intValue() == 2;
+ assert vr.getRevisionNumberForDate(vr.getRevisionDate(3)).intValue() == 3;
+ }
+
+ @Test
+ public void testRevisionsForDates() {
+ VersionsReader vr = getVersionsReader();
+
+ assert vr.getRevisionDate(vr.getRevisionNumberForDate(new Date(timestamp2))).getTime() <= timestamp2;
+ assert vr.getRevisionDate(vr.getRevisionNumberForDate(new Date(timestamp2)).intValue()+1).getTime() > timestamp2;
+
+ assert vr.getRevisionDate(vr.getRevisionNumberForDate(new Date(timestamp3))).getTime() <= timestamp3;
+ assert vr.getRevisionDate(vr.getRevisionNumberForDate(new Date(timestamp3)).intValue()+1).getTime() > timestamp3;
+
+ assert vr.getRevisionDate(vr.getRevisionNumberForDate(new Date(timestamp4))).getTime() <= timestamp4;
+ }
+}
Added: core/trunk/envers/src/test/java/org/jboss/envers/test/integration/sameids/SameIdTestEntity1.java
===================================================================
--- core/trunk/envers/src/test/java/org/jboss/envers/test/integration/sameids/SameIdTestEntity1.java (rev 0)
+++ core/trunk/envers/src/test/java/org/jboss/envers/test/integration/sameids/SameIdTestEntity1.java 2008-10-27 18:56:31 UTC (rev 15406)
@@ -0,0 +1,65 @@
+package org.jboss.envers.test.integration.sameids;
+
+import org.jboss.envers.Versioned;
+
+import javax.persistence.Entity;
+import javax.persistence.Id;
+
+/**
+ * @author Adam Warski (adam at warski dot org)
+ */
+ at Entity
+public class SameIdTestEntity1 {
+ @Id
+ private Integer id;
+
+ @Versioned
+ private String str1;
+
+ public SameIdTestEntity1() {
+ }
+
+ public SameIdTestEntity1(String str1) {
+ this.str1 = str1;
+ }
+
+ public SameIdTestEntity1(Integer id, String str1) {
+ this.id = id;
+ this.str1 = str1;
+ }
+
+ public Integer getId() {
+ return id;
+ }
+
+ public void setId(Integer id) {
+ this.id = id;
+ }
+
+ public String getStr1() {
+ return str1;
+ }
+
+ public void setStr1(String str1) {
+ this.str1 = str1;
+ }
+
+ public boolean equals(Object o) {
+ if (this == o) return true;
+ if (!(o instanceof SameIdTestEntity1)) return false;
+
+ SameIdTestEntity1 that = (SameIdTestEntity1) o;
+
+ if (id != null ? !id.equals(that.id) : that.id != null) return false;
+ if (str1 != null ? !str1.equals(that.str1) : that.str1 != null) return false;
+
+ return true;
+ }
+
+ public int hashCode() {
+ int result;
+ result = (id != null ? id.hashCode() : 0);
+ result = 31 * result + (str1 != null ? str1.hashCode() : 0);
+ return result;
+ }
+}
\ No newline at end of file
Added: core/trunk/envers/src/test/java/org/jboss/envers/test/integration/sameids/SameIdTestEntity2.java
===================================================================
--- core/trunk/envers/src/test/java/org/jboss/envers/test/integration/sameids/SameIdTestEntity2.java (rev 0)
+++ core/trunk/envers/src/test/java/org/jboss/envers/test/integration/sameids/SameIdTestEntity2.java 2008-10-27 18:56:31 UTC (rev 15406)
@@ -0,0 +1,65 @@
+package org.jboss.envers.test.integration.sameids;
+
+import org.jboss.envers.Versioned;
+
+import javax.persistence.Entity;
+import javax.persistence.Id;
+
+/**
+ * @author Adam Warski (adam at warski dot org)
+ */
+ at Entity
+public class SameIdTestEntity2 {
+ @Id
+ private Integer id;
+
+ @Versioned
+ private String str1;
+
+ public SameIdTestEntity2() {
+ }
+
+ public SameIdTestEntity2(String str1) {
+ this.str1 = str1;
+ }
+
+ public SameIdTestEntity2(Integer id, String str1) {
+ this.id = id;
+ this.str1 = str1;
+ }
+
+ public Integer getId() {
+ return id;
+ }
+
+ public void setId(Integer id) {
+ this.id = id;
+ }
+
+ public String getStr1() {
+ return str1;
+ }
+
+ public void setStr1(String str1) {
+ this.str1 = str1;
+ }
+
+ public boolean equals(Object o) {
+ if (this == o) return true;
+ if (!(o instanceof SameIdTestEntity2)) return false;
+
+ SameIdTestEntity2 that = (SameIdTestEntity2) o;
+
+ if (id != null ? !id.equals(that.id) : that.id != null) return false;
+ if (str1 != null ? !str1.equals(that.str1) : that.str1 != null) return false;
+
+ return true;
+ }
+
+ public int hashCode() {
+ int result;
+ result = (id != null ? id.hashCode() : 0);
+ result = 31 * result + (str1 != null ? str1.hashCode() : 0);
+ return result;
+ }
+}
\ No newline at end of file
Added: core/trunk/envers/src/test/java/org/jboss/envers/test/integration/sameids/SameIds.java
===================================================================
--- core/trunk/envers/src/test/java/org/jboss/envers/test/integration/sameids/SameIds.java (rev 0)
+++ core/trunk/envers/src/test/java/org/jboss/envers/test/integration/sameids/SameIds.java 2008-10-27 18:56:31 UTC (rev 15406)
@@ -0,0 +1,64 @@
+package org.jboss.envers.test.integration.sameids;
+
+import org.jboss.envers.test.AbstractEntityTest;
+import org.hibernate.ejb.Ejb3Configuration;
+import org.testng.annotations.Test;
+import org.testng.annotations.BeforeClass;
+
+import javax.persistence.EntityManager;
+import java.util.Arrays;
+
+/**
+ * A test which checks that if we add two different entities with the same ids in one revision, they
+ * will both be stored.
+ * @author Adam Warski (adam at warski dot org)
+ */
+public class SameIds extends AbstractEntityTest {
+ public void configure(Ejb3Configuration cfg) {
+ cfg.addAnnotatedClass(SameIdTestEntity1.class);
+ cfg.addAnnotatedClass(SameIdTestEntity2.class);
+ }
+
+ @BeforeClass(dependsOnMethods = "init")
+ public void initData() {
+ EntityManager em = getEntityManager();
+ em.getTransaction().begin();
+ SameIdTestEntity1 site1 = new SameIdTestEntity1(1, "str1");
+ SameIdTestEntity2 site2 = new SameIdTestEntity2(1, "str1");
+
+ em.persist(site1);
+ em.persist(site2);
+ em.getTransaction().commit();
+
+ em.getTransaction().begin();
+ site1 = em.find(SameIdTestEntity1.class, 1);
+ site2 = em.find(SameIdTestEntity2.class, 1);
+ site1.setStr1("str2");
+ site2.setStr1("str2");
+ em.getTransaction().commit();
+ }
+
+ @Test
+ public void testRevisionsCounts() {
+ assert Arrays.asList(1, 2).equals(getVersionsReader().getRevisions(SameIdTestEntity1.class, 1));
+ assert Arrays.asList(1, 2).equals(getVersionsReader().getRevisions(SameIdTestEntity2.class, 1));
+ }
+
+ @Test
+ public void testHistoryOfSite1() {
+ SameIdTestEntity1 ver1 = new SameIdTestEntity1(1, "str1");
+ SameIdTestEntity1 ver2 = new SameIdTestEntity1(1, "str2");
+
+ assert getVersionsReader().find(SameIdTestEntity1.class, 1, 1).equals(ver1);
+ assert getVersionsReader().find(SameIdTestEntity1.class, 1, 2).equals(ver2);
+ }
+
+ @Test
+ public void testHistoryOfSite2() {
+ SameIdTestEntity2 ver1 = new SameIdTestEntity2(1, "str1");
+ SameIdTestEntity2 ver2 = new SameIdTestEntity2(1, "str2");
+
+ assert getVersionsReader().find(SameIdTestEntity2.class, 1, 1).equals(ver1);
+ assert getVersionsReader().find(SameIdTestEntity2.class, 1, 2).equals(ver2);
+ }
+}
Added: core/trunk/envers/src/test/java/org/jboss/envers/test/integration/secondary/BasicSecondary.java
===================================================================
--- core/trunk/envers/src/test/java/org/jboss/envers/test/integration/secondary/BasicSecondary.java (rev 0)
+++ core/trunk/envers/src/test/java/org/jboss/envers/test/integration/secondary/BasicSecondary.java 2008-10-27 18:56:31 UTC (rev 15406)
@@ -0,0 +1,71 @@
+package org.jboss.envers.test.integration.secondary;
+
+import org.jboss.envers.test.AbstractEntityTest;
+import org.hibernate.ejb.Ejb3Configuration;
+import org.hibernate.mapping.Join;
+import org.testng.annotations.BeforeClass;
+import org.testng.annotations.Test;
+
+import javax.persistence.EntityManager;
+import java.util.Arrays;
+import java.util.Iterator;
+
+/**
+ * @author Adam Warski (adam at warski dot org)
+ */
+public class BasicSecondary extends AbstractEntityTest {
+ private Integer id;
+
+ public void configure(Ejb3Configuration cfg) {
+ cfg.addAnnotatedClass(SecondaryTestEntity.class);
+ }
+
+ @BeforeClass(dependsOnMethods = "init")
+ public void initData() {
+ SecondaryTestEntity ste = new SecondaryTestEntity("a", "1");
+
+ // Revision 1
+ EntityManager em = getEntityManager();
+ em.getTransaction().begin();
+
+ em.persist(ste);
+
+ em.getTransaction().commit();
+
+ // Revision 2
+ em.getTransaction().begin();
+
+ ste = em.find(SecondaryTestEntity.class, ste.getId());
+ ste.setS1("b");
+ ste.setS2("2");
+
+ em.getTransaction().commit();
+
+ //
+
+ id = ste.getId();
+ }
+
+ @Test
+ public void testRevisionsCounts() {
+ assert Arrays.asList(1, 2).equals(getVersionsReader().getRevisions(SecondaryTestEntity.class, id));
+ }
+
+ @Test
+ public void testHistoryOfId() {
+ SecondaryTestEntity ver1 = new SecondaryTestEntity(id, "a", "1");
+ SecondaryTestEntity ver2 = new SecondaryTestEntity(id, "b", "2");
+
+ assert getVersionsReader().find(SecondaryTestEntity.class, id, 1).equals(ver1);
+ assert getVersionsReader().find(SecondaryTestEntity.class, id, 2).equals(ver2);
+ }
+
+ @SuppressWarnings({"unchecked"})
+ @Test
+ public void testTableNames() {
+ assert "secondary_versions".equals(((Iterator<Join>)
+ getCfg().getClassMapping("org.jboss.envers.test.integration.secondary.SecondaryTestEntity_versions")
+ .getJoinIterator())
+ .next().getTable().getName());
+ }
+}
\ No newline at end of file
Added: core/trunk/envers/src/test/java/org/jboss/envers/test/integration/secondary/NamingSecondary.java
===================================================================
--- core/trunk/envers/src/test/java/org/jboss/envers/test/integration/secondary/NamingSecondary.java (rev 0)
+++ core/trunk/envers/src/test/java/org/jboss/envers/test/integration/secondary/NamingSecondary.java 2008-10-27 18:56:31 UTC (rev 15406)
@@ -0,0 +1,71 @@
+package org.jboss.envers.test.integration.secondary;
+
+import org.jboss.envers.test.AbstractEntityTest;
+import org.hibernate.ejb.Ejb3Configuration;
+import org.hibernate.mapping.Join;
+import org.testng.annotations.BeforeClass;
+import org.testng.annotations.Test;
+
+import javax.persistence.EntityManager;
+import java.util.Arrays;
+import java.util.Iterator;
+
+/**
+ * @author Adam Warski (adam at warski dot org)
+ */
+public class NamingSecondary extends AbstractEntityTest {
+ private Integer id;
+
+ public void configure(Ejb3Configuration cfg) {
+ cfg.addAnnotatedClass(SecondaryNamingTestEntity.class);
+ }
+
+ @BeforeClass(dependsOnMethods = "init")
+ public void initData() {
+ SecondaryNamingTestEntity ste = new SecondaryNamingTestEntity("a", "1");
+
+ // Revision 1
+ EntityManager em = getEntityManager();
+ em.getTransaction().begin();
+
+ em.persist(ste);
+
+ em.getTransaction().commit();
+
+ // Revision 2
+ em.getTransaction().begin();
+
+ ste = em.find(SecondaryNamingTestEntity.class, ste.getId());
+ ste.setS1("b");
+ ste.setS2("2");
+
+ em.getTransaction().commit();
+
+ //
+
+ id = ste.getId();
+ }
+
+ @Test
+ public void testRevisionsCounts() {
+ assert Arrays.asList(1, 2).equals(getVersionsReader().getRevisions(SecondaryNamingTestEntity.class, id));
+ }
+
+ @Test
+ public void testHistoryOfId() {
+ SecondaryNamingTestEntity ver1 = new SecondaryNamingTestEntity(id, "a", "1");
+ SecondaryNamingTestEntity ver2 = new SecondaryNamingTestEntity(id, "b", "2");
+
+ assert getVersionsReader().find(SecondaryNamingTestEntity.class, id, 1).equals(ver1);
+ assert getVersionsReader().find(SecondaryNamingTestEntity.class, id, 2).equals(ver2);
+ }
+
+ @SuppressWarnings({"unchecked"})
+ @Test
+ public void testTableNames() {
+ assert "sec_versions".equals(((Iterator<Join>)
+ getCfg().getClassMapping("org.jboss.envers.test.integration.secondary.SecondaryNamingTestEntity_versions")
+ .getJoinIterator())
+ .next().getTable().getName());
+ }
+}
Added: core/trunk/envers/src/test/java/org/jboss/envers/test/integration/secondary/SecondaryNamingTestEntity.java
===================================================================
--- core/trunk/envers/src/test/java/org/jboss/envers/test/integration/secondary/SecondaryNamingTestEntity.java (rev 0)
+++ core/trunk/envers/src/test/java/org/jboss/envers/test/integration/secondary/SecondaryNamingTestEntity.java 2008-10-27 18:56:31 UTC (rev 15406)
@@ -0,0 +1,83 @@
+package org.jboss.envers.test.integration.secondary;
+
+import org.jboss.envers.SecondaryVersionsTable;
+import org.jboss.envers.Versioned;
+
+import javax.persistence.*;
+
+/**
+ * @author Adam Warski (adam at warski dot org)
+ */
+ at Entity
+ at SecondaryTable(name = "secondary")
+ at SecondaryVersionsTable(secondaryTableName = "secondary", secondaryVersionsTableName = "sec_versions")
+ at Versioned
+public class SecondaryNamingTestEntity {
+ @Id
+ @GeneratedValue
+ private Integer id;
+
+ private String s1;
+
+ @Column(table = "secondary")
+ private String s2;
+
+ public SecondaryNamingTestEntity(Integer id, String s1, String s2) {
+ this.id = id;
+ this.s1 = s1;
+ this.s2 = s2;
+ }
+
+ public SecondaryNamingTestEntity(String s1, String s2) {
+ this.s1 = s1;
+ this.s2 = s2;
+ }
+
+ public SecondaryNamingTestEntity() {
+ }
+
+ public Integer getId() {
+ return id;
+ }
+
+ public void setId(Integer id) {
+ this.id = id;
+ }
+
+ public String getS1() {
+ return s1;
+ }
+
+ public void setS1(String s1) {
+ this.s1 = s1;
+ }
+
+ public String getS2() {
+ return s2;
+ }
+
+ public void setS2(String s2) {
+ this.s2 = s2;
+ }
+
+ public boolean equals(Object o) {
+ if (this == o) return true;
+ if (!(o instanceof SecondaryNamingTestEntity)) return false;
+
+ SecondaryNamingTestEntity that = (SecondaryNamingTestEntity) o;
+
+ if (id != null ? !id.equals(that.id) : that.id != null) return false;
+ if (s1 != null ? !s1.equals(that.s1) : that.s1 != null) return false;
+ if (s2 != null ? !s2.equals(that.s2) : that.s2 != null) return false;
+
+ return true;
+ }
+
+ public int hashCode() {
+ int result;
+ result = (id != null ? id.hashCode() : 0);
+ result = 31 * result + (s1 != null ? s1.hashCode() : 0);
+ result = 31 * result + (s2 != null ? s2.hashCode() : 0);
+ return result;
+ }
+}
Added: core/trunk/envers/src/test/java/org/jboss/envers/test/integration/secondary/SecondaryTestEntity.java
===================================================================
--- core/trunk/envers/src/test/java/org/jboss/envers/test/integration/secondary/SecondaryTestEntity.java (rev 0)
+++ core/trunk/envers/src/test/java/org/jboss/envers/test/integration/secondary/SecondaryTestEntity.java 2008-10-27 18:56:31 UTC (rev 15406)
@@ -0,0 +1,81 @@
+package org.jboss.envers.test.integration.secondary;
+
+import org.jboss.envers.Versioned;
+
+import javax.persistence.*;
+
+/**
+ * @author Adam Warski (adam at warski dot org)
+ */
+ at Entity
+ at SecondaryTable(name = "secondary")
+ at Versioned
+public class SecondaryTestEntity {
+ @Id
+ @GeneratedValue
+ private Integer id;
+
+ private String s1;
+
+ @Column(table = "secondary")
+ private String s2;
+
+ public SecondaryTestEntity(Integer id, String s1, String s2) {
+ this.id = id;
+ this.s1 = s1;
+ this.s2 = s2;
+ }
+
+ public SecondaryTestEntity(String s1, String s2) {
+ this.s1 = s1;
+ this.s2 = s2;
+ }
+
+ public SecondaryTestEntity() {
+ }
+
+ public Integer getId() {
+ return id;
+ }
+
+ public void setId(Integer id) {
+ this.id = id;
+ }
+
+ public String getS1() {
+ return s1;
+ }
+
+ public void setS1(String s1) {
+ this.s1 = s1;
+ }
+
+ public String getS2() {
+ return s2;
+ }
+
+ public void setS2(String s2) {
+ this.s2 = s2;
+ }
+
+ public boolean equals(Object o) {
+ if (this == o) return true;
+ if (!(o instanceof SecondaryTestEntity)) return false;
+
+ SecondaryTestEntity that = (SecondaryTestEntity) o;
+
+ if (id != null ? !id.equals(that.id) : that.id != null) return false;
+ if (s1 != null ? !s1.equals(that.s1) : that.s1 != null) return false;
+ if (s2 != null ? !s2.equals(that.s2) : that.s2 != null) return false;
+
+ return true;
+ }
+
+ public int hashCode() {
+ int result;
+ result = (id != null ? id.hashCode() : 0);
+ result = 31 * result + (s1 != null ? s1.hashCode() : 0);
+ result = 31 * result + (s2 != null ? s2.hashCode() : 0);
+ return result;
+ }
+}
\ No newline at end of file
Added: core/trunk/envers/src/test/java/org/jboss/envers/test/integration/secondary/ids/EmbIdSecondary.java
===================================================================
--- core/trunk/envers/src/test/java/org/jboss/envers/test/integration/secondary/ids/EmbIdSecondary.java (rev 0)
+++ core/trunk/envers/src/test/java/org/jboss/envers/test/integration/secondary/ids/EmbIdSecondary.java 2008-10-27 18:56:31 UTC (rev 15406)
@@ -0,0 +1,70 @@
+package org.jboss.envers.test.integration.secondary.ids;
+
+import org.jboss.envers.test.AbstractEntityTest;
+import org.jboss.envers.test.entities.ids.EmbId;
+import org.hibernate.ejb.Ejb3Configuration;
+import org.hibernate.mapping.Join;
+import org.testng.annotations.BeforeClass;
+import org.testng.annotations.Test;
+
+import javax.persistence.EntityManager;
+import java.util.Arrays;
+import java.util.Iterator;
+
+/**
+ * @author Adam Warski (adam at warski dot org)
+ */
+public class EmbIdSecondary extends AbstractEntityTest {
+ private EmbId id;
+
+ public void configure(Ejb3Configuration cfg) {
+ cfg.addAnnotatedClass(SecondaryEmbIdTestEntity.class);
+ }
+
+ @BeforeClass(dependsOnMethods = "init")
+ public void initData() {
+ id = new EmbId(1, 2);
+
+ SecondaryEmbIdTestEntity ste = new SecondaryEmbIdTestEntity(id, "a", "1");
+
+ // Revision 1
+ EntityManager em = getEntityManager();
+ em.getTransaction().begin();
+
+ em.persist(ste);
+
+ em.getTransaction().commit();
+
+ // Revision 2
+ em.getTransaction().begin();
+
+ ste = em.find(SecondaryEmbIdTestEntity.class, ste.getId());
+ ste.setS1("b");
+ ste.setS2("2");
+
+ em.getTransaction().commit();
+ }
+
+ @Test
+ public void testRevisionsCounts() {
+ assert Arrays.asList(1, 2).equals(getVersionsReader().getRevisions(SecondaryEmbIdTestEntity.class, id));
+ }
+
+ @Test
+ public void testHistoryOfId() {
+ SecondaryEmbIdTestEntity ver1 = new SecondaryEmbIdTestEntity(id, "a", "1");
+ SecondaryEmbIdTestEntity ver2 = new SecondaryEmbIdTestEntity(id, "b", "2");
+
+ assert getVersionsReader().find(SecondaryEmbIdTestEntity.class, id, 1).equals(ver1);
+ assert getVersionsReader().find(SecondaryEmbIdTestEntity.class, id, 2).equals(ver2);
+ }
+
+ @SuppressWarnings({"unchecked"})
+ @Test
+ public void testTableNames() {
+ assert "sec_embid_versions".equals(((Iterator<Join>)
+ getCfg().getClassMapping("org.jboss.envers.test.integration.secondary.ids.SecondaryEmbIdTestEntity_versions")
+ .getJoinIterator())
+ .next().getTable().getName());
+ }
+}
\ No newline at end of file
Added: core/trunk/envers/src/test/java/org/jboss/envers/test/integration/secondary/ids/MulIdSecondary.java
===================================================================
--- core/trunk/envers/src/test/java/org/jboss/envers/test/integration/secondary/ids/MulIdSecondary.java (rev 0)
+++ core/trunk/envers/src/test/java/org/jboss/envers/test/integration/secondary/ids/MulIdSecondary.java 2008-10-27 18:56:31 UTC (rev 15406)
@@ -0,0 +1,70 @@
+package org.jboss.envers.test.integration.secondary.ids;
+
+import org.jboss.envers.test.AbstractEntityTest;
+import org.jboss.envers.test.entities.ids.MulId;
+import org.hibernate.ejb.Ejb3Configuration;
+import org.hibernate.mapping.Join;
+import org.testng.annotations.BeforeClass;
+import org.testng.annotations.Test;
+
+import javax.persistence.EntityManager;
+import java.util.Arrays;
+import java.util.Iterator;
+
+/**
+ * @author Adam Warski (adam at warski dot org)
+ */
+public class MulIdSecondary extends AbstractEntityTest {
+ private MulId id;
+
+ public void configure(Ejb3Configuration cfg) {
+ cfg.addAnnotatedClass(SecondaryMulIdTestEntity.class);
+ }
+
+ @BeforeClass(dependsOnMethods = "init")
+ public void initData() {
+ id = new MulId(1, 2);
+
+ SecondaryMulIdTestEntity ste = new SecondaryMulIdTestEntity(id, "a", "1");
+
+ // Revision 1
+ EntityManager em = getEntityManager();
+ em.getTransaction().begin();
+
+ em.persist(ste);
+
+ em.getTransaction().commit();
+
+ // Revision 2
+ em.getTransaction().begin();
+
+ ste = em.find(SecondaryMulIdTestEntity.class, id);
+ ste.setS1("b");
+ ste.setS2("2");
+
+ em.getTransaction().commit();
+ }
+
+ @Test
+ public void testRevisionsCounts() {
+ assert Arrays.asList(1, 2).equals(getVersionsReader().getRevisions(SecondaryMulIdTestEntity.class, id));
+ }
+
+ @Test
+ public void testHistoryOfId() {
+ SecondaryMulIdTestEntity ver1 = new SecondaryMulIdTestEntity(id, "a", "1");
+ SecondaryMulIdTestEntity ver2 = new SecondaryMulIdTestEntity(id, "b", "2");
+
+ assert getVersionsReader().find(SecondaryMulIdTestEntity.class, id, 1).equals(ver1);
+ assert getVersionsReader().find(SecondaryMulIdTestEntity.class, id, 2).equals(ver2);
+ }
+
+ @SuppressWarnings({"unchecked"})
+ @Test
+ public void testTableNames() {
+ assert "sec_mulid_versions".equals(((Iterator<Join>)
+ getCfg().getClassMapping("org.jboss.envers.test.integration.secondary.ids.SecondaryMulIdTestEntity_versions")
+ .getJoinIterator())
+ .next().getTable().getName());
+ }
+}
\ No newline at end of file
Added: core/trunk/envers/src/test/java/org/jboss/envers/test/integration/secondary/ids/SecondaryEmbIdTestEntity.java
===================================================================
--- core/trunk/envers/src/test/java/org/jboss/envers/test/integration/secondary/ids/SecondaryEmbIdTestEntity.java (rev 0)
+++ core/trunk/envers/src/test/java/org/jboss/envers/test/integration/secondary/ids/SecondaryEmbIdTestEntity.java 2008-10-27 18:56:31 UTC (rev 15406)
@@ -0,0 +1,83 @@
+package org.jboss.envers.test.integration.secondary.ids;
+
+import org.jboss.envers.SecondaryVersionsTable;
+import org.jboss.envers.Versioned;
+import org.jboss.envers.test.entities.ids.EmbId;
+
+import javax.persistence.*;
+
+/**
+ * @author Adam Warski (adam at warski dot org)
+ */
+ at Entity
+ at SecondaryTable(name = "secondary")
+ at SecondaryVersionsTable(secondaryTableName = "secondary", secondaryVersionsTableName = "sec_embid_versions")
+ at Versioned
+public class SecondaryEmbIdTestEntity {
+ @Id
+ private EmbId id;
+
+ private String s1;
+
+ @Column(table = "secondary")
+ private String s2;
+
+ public SecondaryEmbIdTestEntity(EmbId id, String s1, String s2) {
+ this.id = id;
+ this.s1 = s1;
+ this.s2 = s2;
+ }
+
+ public SecondaryEmbIdTestEntity(String s1, String s2) {
+ this.s1 = s1;
+ this.s2 = s2;
+ }
+
+ public SecondaryEmbIdTestEntity() {
+ }
+
+ public EmbId getId() {
+ return id;
+ }
+
+ public void setId(EmbId id) {
+ this.id = id;
+ }
+
+ public String getS1() {
+ return s1;
+ }
+
+ public void setS1(String s1) {
+ this.s1 = s1;
+ }
+
+ public String getS2() {
+ return s2;
+ }
+
+ public void setS2(String s2) {
+ this.s2 = s2;
+ }
+
+ public boolean equals(Object o) {
+ if (this == o) return true;
+ if (!(o instanceof SecondaryEmbIdTestEntity)) return false;
+
+ SecondaryEmbIdTestEntity that = (SecondaryEmbIdTestEntity) o;
+
+ if (id != null ? !id.equals(that.id) : that.id != null) return false;
+ if (s1 != null ? !s1.equals(that.s1) : that.s1 != null) return false;
+ if (s2 != null ? !s2.equals(that.s2) : that.s2 != null) return false;
+
+ return true;
+ }
+
+ public int hashCode() {
+ int result;
+ result = (id != null ? id.hashCode() : 0);
+ result = 31 * result + (s1 != null ? s1.hashCode() : 0);
+ result = 31 * result + (s2 != null ? s2.hashCode() : 0);
+ return result;
+ }
+}
\ No newline at end of file
Added: core/trunk/envers/src/test/java/org/jboss/envers/test/integration/secondary/ids/SecondaryMulIdTestEntity.java
===================================================================
--- core/trunk/envers/src/test/java/org/jboss/envers/test/integration/secondary/ids/SecondaryMulIdTestEntity.java (rev 0)
+++ core/trunk/envers/src/test/java/org/jboss/envers/test/integration/secondary/ids/SecondaryMulIdTestEntity.java 2008-10-27 18:56:31 UTC (rev 15406)
@@ -0,0 +1,98 @@
+package org.jboss.envers.test.integration.secondary.ids;
+
+import org.jboss.envers.SecondaryVersionsTable;
+import org.jboss.envers.Versioned;
+import org.jboss.envers.test.entities.ids.MulId;
+
+import javax.persistence.*;
+
+/**
+ * @author Adam Warski (adam at warski dot org)
+ */
+ at Entity
+ at SecondaryTable(name = "secondary")
+ at SecondaryVersionsTable(secondaryTableName = "secondary", secondaryVersionsTableName = "sec_mulid_versions")
+ at Versioned
+ at IdClass(MulId.class)
+public class SecondaryMulIdTestEntity {
+ @Id
+ private Integer id1;
+
+ @Id
+ private Integer id2;
+
+ private String s1;
+
+ @Column(table = "secondary")
+ private String s2;
+
+ public SecondaryMulIdTestEntity(MulId id, String s1, String s2) {
+ this.id1 = id.getId1();
+ this.id2 = id.getId2();
+ this.s1 = s1;
+ this.s2 = s2;
+ }
+
+ public SecondaryMulIdTestEntity(String s1, String s2) {
+ this.s1 = s1;
+ this.s2 = s2;
+ }
+
+ public SecondaryMulIdTestEntity() {
+ }
+
+ public Integer getId1() {
+ return id1;
+ }
+
+ public void setId1(Integer id1) {
+ this.id1 = id1;
+ }
+
+ public Integer getId2() {
+ return id2;
+ }
+
+ public void setId2(Integer id2) {
+ this.id2 = id2;
+ }
+
+ public String getS1() {
+ return s1;
+ }
+
+ public void setS1(String s1) {
+ this.s1 = s1;
+ }
+
+ public String getS2() {
+ return s2;
+ }
+
+ public void setS2(String s2) {
+ this.s2 = s2;
+ }
+
+ public boolean equals(Object o) {
+ if (this == o) return true;
+ if (!(o instanceof SecondaryMulIdTestEntity)) return false;
+
+ SecondaryMulIdTestEntity that = (SecondaryMulIdTestEntity) o;
+
+ if (id1 != null ? !id1.equals(that.id1) : that.id1 != null) return false;
+ if (id2 != null ? !id2.equals(that.id2) : that.id2 != null) return false;
+ if (s1 != null ? !s1.equals(that.s1) : that.s1 != null) return false;
+ if (s2 != null ? !s2.equals(that.s2) : that.s2 != null) return false;
+
+ return true;
+ }
+
+ public int hashCode() {
+ int result;
+ result = (id1 != null ? id1.hashCode() : 0);
+ result = 31 * result + (id2 != null ? id2.hashCode() : 0);
+ result = 31 * result + (s1 != null ? s1.hashCode() : 0);
+ result = 31 * result + (s2 != null ? s2.hashCode() : 0);
+ return result;
+ }
+}
\ No newline at end of file
Added: core/trunk/envers/src/test/java/org/jboss/envers/test/integration/superclass/MappedSubclassing.java
===================================================================
--- core/trunk/envers/src/test/java/org/jboss/envers/test/integration/superclass/MappedSubclassing.java (rev 0)
+++ core/trunk/envers/src/test/java/org/jboss/envers/test/integration/superclass/MappedSubclassing.java 2008-10-27 18:56:31 UTC (rev 15406)
@@ -0,0 +1,51 @@
+package org.jboss.envers.test.integration.superclass;
+
+import org.jboss.envers.test.AbstractEntityTest;
+import org.hibernate.ejb.Ejb3Configuration;
+import org.testng.annotations.BeforeClass;
+import org.testng.annotations.Test;
+
+import javax.persistence.EntityManager;
+import java.util.Arrays;
+
+/**
+ * @author Adam Warski (adam at warski dot org)
+ */
+public class MappedSubclassing extends AbstractEntityTest {
+ private Integer id1;
+
+ public void configure(Ejb3Configuration cfg) {
+ cfg.addAnnotatedClass(SubclassEntity.class);
+ }
+
+ @BeforeClass(dependsOnMethods = "init")
+ public void initData() {
+ // Revision 1
+ EntityManager em = getEntityManager();
+ em.getTransaction().begin();
+ SubclassEntity se1 = new SubclassEntity("x");
+ em.persist(se1);
+ id1 = se1.getId();
+ em.getTransaction().commit();
+
+ // Revision 2
+ em.getTransaction().begin();
+ se1 = em.find(SubclassEntity.class, id1);
+ se1.setStr("y");
+ em.getTransaction().commit();
+ }
+
+ @Test
+ public void testRevisionsCounts() {
+ assert Arrays.asList(1, 2).equals(getVersionsReader().getRevisions(SubclassEntity.class, id1));
+ }
+
+ @Test
+ public void testHistoryOfId1() {
+ SubclassEntity ver1 = new SubclassEntity(id1, "x");
+ SubclassEntity ver2 = new SubclassEntity(id1, "y");
+
+ assert getVersionsReader().find(SubclassEntity.class, id1, 1).equals(ver1);
+ assert getVersionsReader().find(SubclassEntity.class, id1, 2).equals(ver2);
+ }
+}
Added: core/trunk/envers/src/test/java/org/jboss/envers/test/integration/superclass/SubclassEntity.java
===================================================================
--- core/trunk/envers/src/test/java/org/jboss/envers/test/integration/superclass/SubclassEntity.java (rev 0)
+++ core/trunk/envers/src/test/java/org/jboss/envers/test/integration/superclass/SubclassEntity.java 2008-10-27 18:56:31 UTC (rev 15406)
@@ -0,0 +1,53 @@
+package org.jboss.envers.test.integration.superclass;
+
+import javax.persistence.Entity;
+import javax.persistence.Id;
+import javax.persistence.GeneratedValue;
+
+/**
+ * @author Adam Warski (adam at warski dot org)
+ */
+ at Entity
+public class SubclassEntity extends SuperclassOfEntity {
+ @Id
+ @GeneratedValue
+ private Integer id;
+
+ public SubclassEntity() {
+ }
+
+ public SubclassEntity(Integer id, String str) {
+ super(str);
+ this.id = id;
+ }
+
+ public SubclassEntity(String str) {
+ super(str);
+ }
+
+ public Integer getId() {
+ return id;
+ }
+
+ public void setId(Integer id) {
+ this.id = id;
+ }
+
+ public boolean equals(Object o) {
+ if (this == o) return true;
+ if (!(o instanceof SubclassEntity)) return false;
+ if (!super.equals(o)) return false;
+
+ SubclassEntity that = (SubclassEntity) o;
+
+ if (id != null ? !id.equals(that.id) : that.id != null) return false;
+
+ return true;
+ }
+
+ public int hashCode() {
+ int result = super.hashCode();
+ result = 31 * result + (id != null ? id.hashCode() : 0);
+ return result;
+ }
+}
Added: core/trunk/envers/src/test/java/org/jboss/envers/test/integration/superclass/SuperclassOfEntity.java
===================================================================
--- core/trunk/envers/src/test/java/org/jboss/envers/test/integration/superclass/SuperclassOfEntity.java (rev 0)
+++ core/trunk/envers/src/test/java/org/jboss/envers/test/integration/superclass/SuperclassOfEntity.java 2008-10-27 18:56:31 UTC (rev 15406)
@@ -0,0 +1,44 @@
+package org.jboss.envers.test.integration.superclass;
+
+import org.jboss.envers.Versioned;
+
+import javax.persistence.MappedSuperclass;
+
+/**
+ * @author Adam Warski (adam at warski dot org)
+ */
+ at MappedSuperclass
+public class SuperclassOfEntity {
+ @Versioned
+ private String str;
+
+ public SuperclassOfEntity() {
+ }
+
+ public SuperclassOfEntity(String str) {
+ this.str = str;
+ }
+
+ public String getStr() {
+ return str;
+ }
+
+ public void setStr(String str) {
+ this.str = str;
+ }
+
+ public boolean equals(Object o) {
+ if (this == o) return true;
+ if (!(o instanceof SuperclassOfEntity)) return false;
+
+ SuperclassOfEntity that = (SuperclassOfEntity) o;
+
+ if (str != null ? !str.equals(that.str) : that.str != null) return false;
+
+ return true;
+ }
+
+ public int hashCode() {
+ return (str != null ? str.hashCode() : 0);
+ }
+}
Added: core/trunk/envers/src/test/java/org/jboss/envers/test/performance/AbstractPerformanceTest.java
===================================================================
--- core/trunk/envers/src/test/java/org/jboss/envers/test/performance/AbstractPerformanceTest.java (rev 0)
+++ core/trunk/envers/src/test/java/org/jboss/envers/test/performance/AbstractPerformanceTest.java 2008-10-27 18:56:31 UTC (rev 15406)
@@ -0,0 +1,59 @@
+package org.jboss.envers.test.performance;
+
+import org.jboss.envers.test.AbstractEntityTest;
+import org.jboss.envers.tools.Pair;
+
+/**
+ * @author Adam Warski (adam at warski dot org)
+ */
+public abstract class AbstractPerformanceTest extends AbstractEntityTest {
+ protected String getSecondsString(long milliseconds) {
+ return (milliseconds/1000) + "." + (milliseconds%1000);
+ }
+
+ protected long measureTime(Runnable r) {
+ long start = System.currentTimeMillis();
+ r.run();
+ return System.currentTimeMillis() - start;
+ }
+
+ protected abstract Pair<Long, Long> doTest();
+
+ protected abstract String getName();
+
+ private long totalUnversioned;
+ private long totalVersioned;
+
+ private void printResults(long unversioned, long versioned) {
+ System.out.println("Unversioned: " + getSecondsString(unversioned));
+ System.out.println(" Versioned: " + getSecondsString(versioned));
+ System.out.println(" Delta: " + getSecondsString(versioned-unversioned));
+ System.out.println(" Factor: " + (double)versioned/unversioned);
+ }
+
+ private void test(boolean count) {
+ Pair<Long, Long> result = doTest();
+ long unversioned = result.getFirst();
+ long versioned = result.getSecond();
+
+ totalUnversioned += unversioned;
+ totalVersioned += versioned;
+
+ printResults(unversioned, versioned);
+ }
+
+ public void run(int numberOfRuns) {
+ for (int i=0; i<=numberOfRuns; i++) {
+ System.out.println("");
+ System.out.println(getName() + " TEST, RUN " + i);
+ test(i != 0);
+ }
+
+ totalUnversioned /= numberOfRuns;
+ totalVersioned /= numberOfRuns;
+
+ System.out.println("");
+ System.out.println(getName() + " TEST, AVERAGE");
+ printResults(totalUnversioned, totalVersioned);
+ }
+}
Added: core/trunk/envers/src/test/java/org/jboss/envers/test/performance/InsertsPerformance.java
===================================================================
--- core/trunk/envers/src/test/java/org/jboss/envers/test/performance/InsertsPerformance.java (rev 0)
+++ core/trunk/envers/src/test/java/org/jboss/envers/test/performance/InsertsPerformance.java 2008-10-27 18:56:31 UTC (rev 15406)
@@ -0,0 +1,56 @@
+package org.jboss.envers.test.performance;
+
+import org.jboss.envers.test.entities.StrTestEntity;
+import org.jboss.envers.test.entities.UnversionedStrTestEntity;
+import org.jboss.envers.tools.Pair;
+import org.hibernate.ejb.Ejb3Configuration;
+
+import javax.persistence.EntityManager;
+import java.io.IOException;
+
+/**
+ * @author Adam Warski (adam at warski dot org)
+ */
+public class InsertsPerformance extends AbstractPerformanceTest {
+ public void configure(Ejb3Configuration cfg) {
+ cfg.addAnnotatedClass(StrTestEntity.class);
+ cfg.addAnnotatedClass(UnversionedStrTestEntity.class);
+ }
+
+ private final static int NUMBER_INSERTS = 1000;
+
+ private void insertUnversioned() {
+ EntityManager entityManager = getEntityManager();
+ for (int i=0; i<NUMBER_INSERTS; i++) {
+ entityManager.getTransaction().begin();
+ entityManager.persist(new UnversionedStrTestEntity("x" + i));
+ entityManager.getTransaction().commit();
+ }
+ }
+
+ private void insertVersioned() {
+ EntityManager entityManager = getEntityManager();
+ for (int i=0; i<NUMBER_INSERTS; i++) {
+ entityManager.getTransaction().begin();
+ entityManager.persist(new StrTestEntity("x" + i));
+ entityManager.getTransaction().commit();
+ }
+ }
+
+ protected Pair<Long, Long> doTest() {
+ long unversioned = measureTime(new Runnable() { public void run() { insertUnversioned(); } });
+ long versioned = measureTime(new Runnable() { public void run() { insertVersioned(); } });
+
+ return Pair.make(unversioned, versioned);
+ }
+
+ protected String getName() {
+ return "INSERTS";
+ }
+
+ public static void main(String[] args) throws IOException {
+ InsertsPerformance insertsPerformance = new InsertsPerformance();
+ insertsPerformance.init();
+ insertsPerformance.run(10);
+ }
+}
Added: core/trunk/envers/src/test/java/org/jboss/envers/test/performance/UpdatesPerformance.java
===================================================================
--- core/trunk/envers/src/test/java/org/jboss/envers/test/performance/UpdatesPerformance.java (rev 0)
+++ core/trunk/envers/src/test/java/org/jboss/envers/test/performance/UpdatesPerformance.java 2008-10-27 18:56:31 UTC (rev 15406)
@@ -0,0 +1,87 @@
+package org.jboss.envers.test.performance;
+
+import org.jboss.envers.test.entities.StrTestEntity;
+import org.jboss.envers.test.entities.UnversionedStrTestEntity;
+import org.jboss.envers.tools.Pair;
+import org.hibernate.ejb.Ejb3Configuration;
+
+import javax.persistence.EntityManager;
+import java.io.IOException;
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Random;
+
+/**
+ * @author Adam Warski (adam at warski dot org)
+ */
+public class UpdatesPerformance extends AbstractPerformanceTest {
+ public void configure(Ejb3Configuration cfg) {
+ cfg.addAnnotatedClass(StrTestEntity.class);
+ cfg.addAnnotatedClass(UnversionedStrTestEntity.class);
+ }
+
+ private final static int NUMBER_UPDATES = 1000;
+ private final static int NUMBER_ENTITIES = 10;
+
+ private Random random = new Random();
+
+ private List<Integer> unversioned_ids = new ArrayList<Integer>();
+ private List<Integer> versioned_ids = new ArrayList<Integer>();
+
+ public void setup() {
+ EntityManager entityManager = getEntityManager();
+ entityManager.getTransaction().begin();
+ for (int i=0; i<NUMBER_ENTITIES; i++) {
+ UnversionedStrTestEntity testEntity = new UnversionedStrTestEntity("x" + i);
+ entityManager.persist(testEntity);
+ unversioned_ids.add(testEntity.getId());
+ }
+
+ for (int i=0; i<NUMBER_ENTITIES; i++) {
+ StrTestEntity testEntity = new StrTestEntity("x" + i);
+ entityManager.persist(testEntity);
+ versioned_ids.add(testEntity.getId());
+ }
+ entityManager.getTransaction().commit();
+ }
+
+ private void updateUnversioned() {
+ EntityManager entityManager = getEntityManager();
+ for (int i=0; i<NUMBER_UPDATES; i++) {
+ entityManager.getTransaction().begin();
+ Integer id = unversioned_ids.get(random.nextInt(NUMBER_ENTITIES));
+ UnversionedStrTestEntity testEntity = entityManager.find(UnversionedStrTestEntity.class, id);
+ testEntity.setStr("z" + i);
+ entityManager.getTransaction().commit();
+ }
+ }
+
+ private void updateVersioned() {
+ EntityManager entityManager = getEntityManager();
+ for (int i=0; i<NUMBER_UPDATES; i++) {
+ entityManager.getTransaction().begin();
+ Integer id = versioned_ids.get(random.nextInt(NUMBER_ENTITIES));
+ StrTestEntity testEntity = entityManager.find(StrTestEntity.class, id);
+ testEntity.setStr("z" + i);
+ entityManager.getTransaction().commit();
+ }
+ }
+
+ protected Pair<Long, Long> doTest() {
+ long unversioned = measureTime(new Runnable() { public void run() { updateUnversioned(); } });
+ long versioned = measureTime(new Runnable() { public void run() { updateVersioned(); } });
+
+ return Pair.make(unversioned, versioned);
+ }
+
+ protected String getName() {
+ return "UPDATES";
+ }
+
+ public static void main(String[] args) throws IOException {
+ UpdatesPerformance updatesPerformance = new UpdatesPerformance();
+ updatesPerformance.init();
+ updatesPerformance.setup();
+ updatesPerformance.run(10);
+ }
+}
\ No newline at end of file
Added: core/trunk/envers/src/test/java/org/jboss/envers/test/tools/TestTools.java
===================================================================
--- core/trunk/envers/src/test/java/org/jboss/envers/test/tools/TestTools.java (rev 0)
+++ core/trunk/envers/src/test/java/org/jboss/envers/test/tools/TestTools.java 2008-10-27 18:56:31 UTC (rev 15406)
@@ -0,0 +1,47 @@
+package org.jboss.envers.test.tools;
+
+import java.util.*;
+
+/**
+ * @author Adam Warski (adam at warski dot org)
+ */
+public class TestTools {
+ public static <T> Set<T> makeSet(T... objects) {
+ Set<T> ret = new HashSet<T>();
+ //noinspection ManualArrayToCollectionCopy
+ for (T o : objects) {
+ ret.add(o);
+ }
+
+ return ret;
+ }
+
+ public static <T> List<T> makeList(T... objects) {
+ return Arrays.asList(objects);
+ }
+
+ public static Map<Object, Object> makeMap(Object... objects) {
+ Map<Object, Object> ret = new HashMap<Object, Object>();
+ // The number of objects must be divisable by 2.
+ //noinspection ManualArrayToCollectionCopy
+ for (int i=0; i<objects.length; i+=2) {
+ ret.put(objects[i], objects[i+1]);
+ }
+
+ return ret;
+ }
+
+ public static <T> boolean checkList(List<T> list, T... objects) {
+ if (list.size() != objects.length) {
+ return false;
+ }
+
+ for (T obj : objects) {
+ if (!list.contains(obj)) {
+ return false;
+ }
+ }
+
+ return true;
+ }
+}
Added: core/trunk/envers/src/test/java/org/jboss/envers/test/various/Address.java
===================================================================
--- core/trunk/envers/src/test/java/org/jboss/envers/test/various/Address.java (rev 0)
+++ core/trunk/envers/src/test/java/org/jboss/envers/test/various/Address.java 2008-10-27 18:56:31 UTC (rev 15406)
@@ -0,0 +1,113 @@
+/*
+ * Envers. http://www.jboss.org/envers
+ *
+ * Copyright 2008 Red Hat Middleware, LLC. All rights reserved.
+ *
+ * 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, v. 2.1.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT A 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, v.2.1 along with this distribution; if not, write to the Free
+ * Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+ * 02110-1301, USA.
+ *
+ * Red Hat Author(s): Adam Warski
+ */
+package org.jboss.envers.test.various;
+
+import org.jboss.envers.Versioned;
+
+import javax.persistence.*;
+import java.util.Set;
+
+/**
+ * @author Adam Warski (adam at warski dot org)
+ */
+ at Entity
+public class Address {
+ @Id
+ @GeneratedValue
+ private int id;
+
+ @Versioned
+ private String streetName;
+
+ @Versioned
+ private Integer houseNumber;
+
+ @Versioned
+ private Integer flatNumber;
+
+ @Versioned
+ @OneToMany(mappedBy = "address")
+ private Set<Person> persons;
+
+ public int getId() {
+ return id;
+ }
+
+ public void setId(int id) {
+ this.id = id;
+ }
+
+ public String getStreetName() {
+ return streetName;
+ }
+
+ public void setStreetName(String streetName) {
+ this.streetName = streetName;
+ }
+
+ public Integer getHouseNumber() {
+ return houseNumber;
+ }
+
+ public void setHouseNumber(Integer houseNumber) {
+ this.houseNumber = houseNumber;
+ }
+
+ public Integer getFlatNumber() {
+ return flatNumber;
+ }
+
+ public void setFlatNumber(Integer flatNumber) {
+ this.flatNumber = flatNumber;
+ }
+
+ public Set<Person> getPersons() {
+ return persons;
+ }
+
+ public void setPersons(Set<Person> persons) {
+ this.persons = persons;
+ }
+
+ public boolean equals(Object o) {
+ if (this == o) return true;
+ if (!(o instanceof Address)) return false;
+
+ Address address = (Address) o;
+
+ if (id != address.id) return false;
+ if (flatNumber != null ? !flatNumber.equals(address.flatNumber) : address.flatNumber != null) return false;
+ if (houseNumber != null ? !houseNumber.equals(address.houseNumber) : address.houseNumber != null) return false;
+ if (streetName != null ? !streetName.equals(address.streetName) : address.streetName != null) return false;
+
+ return true;
+ }
+
+ public int hashCode() {
+ int result;
+ result = id;
+ result = 31 * result + (streetName != null ? streetName.hashCode() : 0);
+ result = 31 * result + (houseNumber != null ? houseNumber.hashCode() : 0);
+ result = 31 * result + (flatNumber != null ? flatNumber.hashCode() : 0);
+ return result;
+ }
+}
\ No newline at end of file
Added: core/trunk/envers/src/test/java/org/jboss/envers/test/various/HsqlTest.java
===================================================================
--- core/trunk/envers/src/test/java/org/jboss/envers/test/various/HsqlTest.java (rev 0)
+++ core/trunk/envers/src/test/java/org/jboss/envers/test/various/HsqlTest.java 2008-10-27 18:56:31 UTC (rev 15406)
@@ -0,0 +1,129 @@
+package org.jboss.envers.test.various;
+
+import org.hibernate.Session;
+
+import javax.persistence.EntityManagerFactory;
+import javax.persistence.Persistence;
+import javax.persistence.EntityManager;
+import java.util.Map;
+import java.util.HashMap;
+import java.util.HashSet;
+
+/**
+ * @author Adam Warski (adam at warski dot org)
+ */
+public class HsqlTest {
+ /*
+ Query generated by Hibernate from an old demo, when criteria was used: (works)
+
+ select
+ this_.id as id2_0_,
+ this_._revision as column2_2_0_,
+ this_._revision_type as column3_2_0_,
+ this_.name as name2_0_,
+ this_.surname as surname2_0_,
+ this_.address_id as address6_2_0_
+ from
+ Person_versions this_
+ where
+ this_._revision = (
+ select
+ max(e2_._revision) as y0_
+ from
+ Person_versions e2_
+ where
+ e2_._revision<=1
+ and this_.id=e2_.id
+ )
+ and this_.id=1
+
+ Query generated by Hibernate from a new demo, when query generator is used:
+ (throws Column not found: ID in statement because of "person_ver0_.id=person_ver1_.id")
+
+ select
+ person_ver0_.id as id3_,
+ person_ver0_._revision as column2_3_,
+ person_ver0_._revision_type as column3_3_,
+ person_ver0_.name as name3_,
+ person_ver0_.surname as surname3_,
+ person_ver0_.address_id as address6_3_
+ from
+ Person_versions person_ver0_
+ where
+ person_ver0_._revision_type<>2
+ and person_ver0_._revision=(
+ select
+ max(person_ver1_._revision)
+ from
+ Person_versions person_ver1_
+ where
+ person_ver1_._revision<=1
+ and person_ver0_.id=person_ver1_.id
+ )
+ and person_ver0_.id=1
+
+ Both queries work from HSQL console
+ (to run: java -cp hsqldb.jar org.hsqldb.util.DatabaseManager -user sa -url jdbc:hsqldb:file:/tmp/_versions_demo.db)
+
+ TODO: post hibernate bug
+ */
+
+ public static void main(String[] argv) {
+ Map<String, String> configurationOverrides = new HashMap<String, String>();
+ EntityManagerFactory emf = Persistence.createEntityManagerFactory("ConsolePU", configurationOverrides);
+ EntityManager entityManager = emf.createEntityManager();
+
+ populateTestData(entityManager);
+
+ entityManager.getTransaction().begin();
+
+ Session sesion = (Session) entityManager.getDelegate();
+ System.out.println(sesion.createQuery(
+ "select e from org.jboss.envers.demo.Person_versions e " +
+ "where " +
+ "e.originalId._revision.id =" +
+ "(select max(e2.originalId._revision.id) " +
+ "from org.jboss.envers.demo.Person_versions e2 " +
+ "where e.originalId.id = :p0) ")
+ .setParameter("p0", 1)
+ .list());
+
+ entityManager.getTransaction().commit();
+
+ entityManager.close();
+ emf.close();
+ }
+
+ private static void populateTestData(EntityManager entityManager) {
+ entityManager.getTransaction().begin();
+
+ if (!hasData(entityManager)) {
+ Person p1 = new Person();
+
+ Address a1 = new Address();
+
+ p1.setName("James");
+ p1.setSurname("Bond");
+ p1.setAddress(a1);
+
+ a1.setStreetName("MI6");
+ a1.setHouseNumber(18);
+ a1.setFlatNumber(25);
+ a1.setPersons(new HashSet<Person>());
+ a1.getPersons().add(p1);
+
+ entityManager.persist(a1);
+
+ entityManager.persist(p1);
+
+ System.out.println("The DB was populated with example data.");
+ }
+
+ entityManager.getTransaction().commit();
+ }
+
+ private static boolean hasData(EntityManager entityManager) {
+ return (((Long) entityManager.createQuery("select count(a) from Address a").getSingleResult()) +
+ ((Long) entityManager.createQuery("select count(p) from Person p").getSingleResult())) > 0;
+ }
+}
Added: core/trunk/envers/src/test/java/org/jboss/envers/test/various/Person.java
===================================================================
--- core/trunk/envers/src/test/java/org/jboss/envers/test/various/Person.java (rev 0)
+++ core/trunk/envers/src/test/java/org/jboss/envers/test/various/Person.java 2008-10-27 18:56:31 UTC (rev 15406)
@@ -0,0 +1,99 @@
+/*
+ * Envers. http://www.jboss.org/envers
+ *
+ * Copyright 2008 Red Hat Middleware, LLC. All rights reserved.
+ *
+ * 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, v. 2.1.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT A 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, v.2.1 along with this distribution; if not, write to the Free
+ * Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+ * 02110-1301, USA.
+ *
+ * Red Hat Author(s): Adam Warski
+ */
+package org.jboss.envers.test.various;
+
+import org.jboss.envers.Versioned;
+
+import javax.persistence.*;
+
+/**
+ * @author Adam Warski (adam at warski dot org)
+ */
+ at Entity
+public class Person {
+ @Id
+ @GeneratedValue
+ private int id;
+
+ @Versioned
+ private String name;
+
+ @Versioned
+ private String surname;
+
+ @Versioned
+ @ManyToOne
+ private Address address;
+
+ public int getId() {
+ return id;
+ }
+
+ public void setId(int id) {
+ this.id = id;
+ }
+
+ public String getName() {
+ return name;
+ }
+
+ public void setName(String name) {
+ this.name = name;
+ }
+
+ public String getSurname() {
+ return surname;
+ }
+
+ public void setSurname(String surname) {
+ this.surname = surname;
+ }
+
+ public Address getAddress() {
+ return address;
+ }
+
+ public void setAddress(Address address) {
+ this.address = address;
+ }
+
+ public boolean equals(Object o) {
+ if (this == o) return true;
+ if (!(o instanceof Person)) return false;
+
+ Person person = (Person) o;
+
+ if (id != person.id) return false;
+ if (name != null ? !name.equals(person.name) : person.name != null) return false;
+ if (surname != null ? !surname.equals(person.surname) : person.surname != null) return false;
+
+ return true;
+ }
+
+ public int hashCode() {
+ int result;
+ result = id;
+ result = 31 * result + (name != null ? name.hashCode() : 0);
+ result = 31 * result + (surname != null ? surname.hashCode() : 0);
+ return result;
+ }
+}
\ No newline at end of file
Added: core/trunk/envers/src/test/resources/hibernate.test.cfg.xml
===================================================================
--- core/trunk/envers/src/test/resources/hibernate.test.cfg.xml (rev 0)
+++ core/trunk/envers/src/test/resources/hibernate.test.cfg.xml 2008-10-27 18:56:31 UTC (rev 15406)
@@ -0,0 +1,45 @@
+<?xml version='1.0' encoding='utf-8'?>
+<!DOCTYPE hibernate-configuration PUBLIC
+ "-//Hibernate/Hibernate Configuration DTD//EN"
+ "http://hibernate.sourceforge.net/hibernate-configuration-3.0.dtd">
+
+<!--suppress HibernateConfigDomInspection -->
+<hibernate-configuration>
+ <session-factory>
+ <property name="hbm2ddl.auto">create-drop</property>
+
+ <property name="dialect">org.hibernate.dialect.MySQLDialect</property>
+ <property name="connection.url">jdbc:mysql:///hibernate_tests?useUnicode=true&characterEncoding=UTF-8</property>
+ <property name="connection.driver_class">com.mysql.jdbc.Driver</property>
+ <property name="connection.username">root</property>
+ <property name="connection.password"></property>
+
+ <!--<property name="dialect">org.hibernate.dialect.PostgreSQLDialect</property>
+ <property name="connection.url">jdbc:postgresql://localhost/hibernate_tests</property>
+ <property name="connection.driver_class">org.postgresql.Driver</property>
+ <property name="connection.username">postgres</property>
+ <property name="connection.password"></property>-->
+
+ <property name="show_sql">false</property>
+ <property name="format_sql">true</property>
+
+ <event type="post-insert">
+ <listener class="org.jboss.envers.event.VersionsEventListener" />
+ </event>
+ <event type="post-update">
+ <listener class="org.jboss.envers.event.VersionsEventListener" />
+ </event>
+ <event type="post-delete">
+ <listener class="org.jboss.envers.event.VersionsEventListener" />
+ </event>
+ <event type="pre-collection-update">
+ <listener class="org.jboss.envers.event.VersionsEventListener" />
+ </event>
+ <event type="pre-collection-remove">
+ <listener class="org.jboss.envers.event.VersionsEventListener" />
+ </event>
+ <event type="post-collection-recreate">
+ <listener class="org.jboss.envers.event.VersionsEventListener" />
+ </event>
+ </session-factory>
+</hibernate-configuration>
\ No newline at end of file
Added: core/trunk/envers/src/test/resources/testng.xml
===================================================================
--- core/trunk/envers/src/test/resources/testng.xml (rev 0)
+++ core/trunk/envers/src/test/resources/testng.xml 2008-10-27 18:56:31 UTC (rev 15406)
@@ -0,0 +1,40 @@
+<!DOCTYPE suite SYSTEM "http://testng.org/testng-1.0.dtd" >
+
+<suite name="Envers">
+ <test name="All">
+ <packages>
+ <package name="org.jboss.envers.test.integration.basic" />
+ <package name="org.jboss.envers.test.integration.cache" />
+ <package name="org.jboss.envers.test.integration.collection" />
+ <package name="org.jboss.envers.test.integration.collection.mapkey" />
+ <package name="org.jboss.envers.test.integration.components" />
+ <package name="org.jboss.envers.test.integration.customtype" />
+ <package name="org.jboss.envers.test.integration.data" />
+ <package name="org.jboss.envers.test.integration.flush" />
+ <package name="org.jboss.envers.test.integration.ids" />
+ <package name="org.jboss.envers.test.integration.inheritance.single" />
+ <package name="org.jboss.envers.test.integration.inheritance.single.childrelation" />
+ <package name="org.jboss.envers.test.integration.inheritance.single.relation" />
+ <package name="org.jboss.envers.test.integration.manytomany" />
+ <package name="org.jboss.envers.test.integration.manytomany.ternary" />
+ <package name="org.jboss.envers.test.integration.manytomany.unidirectional" />
+ <package name="org.jboss.envers.test.integration.naming" />
+ <package name="org.jboss.envers.test.integration.naming.ids" />
+ <package name="org.jboss.envers.test.integration.notinsertable" />
+ <package name="org.jboss.envers.test.integration.onetomany" />
+ <package name="org.jboss.envers.test.integration.onetomany.detached" />
+ <package name="org.jboss.envers.test.integration.onetoone.bidirectional" />
+ <package name="org.jboss.envers.test.integration.onetoone.bidirectional.ids" />
+ <package name="org.jboss.envers.test.integration.onetoone.unidirectional" />
+ <package name="org.jboss.envers.test.integration.properties" />
+ <package name="org.jboss.envers.test.integration.query" />
+ <package name="org.jboss.envers.test.integration.query.ids" />
+ <package name="org.jboss.envers.test.integration.reventity" />
+ <package name="org.jboss.envers.test.integration.revfordate" />
+ <package name="org.jboss.envers.test.integration.sameids" />
+ <package name="org.jboss.envers.test.integration.secondary" />
+ <package name="org.jboss.envers.test.integration.secondary.ids" />
+ <package name="org.jboss.envers.test.integration.superclass" />
+ </packages>
+ </test>
+</suite>
\ No newline at end of file
Modified: core/trunk/pom.xml
===================================================================
--- core/trunk/pom.xml 2008-10-27 14:49:08 UTC (rev 15405)
+++ core/trunk/pom.xml 2008-10-27 18:56:31 UTC (rev 15406)
@@ -53,6 +53,7 @@
<module>cache-swarmcache</module>
<module>connection-c3p0</module>
<module>connection-proxool</module>
+ <module>envers</module>
<module>jmx</module>
<module>testing</module>
<module>testsuite</module>
@@ -93,4 +94,4 @@
</profile>
</profiles>
-</project>
\ No newline at end of file
+</project>
More information about the hibernate-commits
mailing list