[jboss-envers-commits] JBoss Envers SVN: r115 - in trunk: src/main/org/jboss/envers/configuration and 7 other directories.

jboss-envers-commits at lists.jboss.org jboss-envers-commits at lists.jboss.org
Wed Aug 20 07:44:45 EDT 2008


Author: adamw
Date: 2008-08-20 07:44:45 -0400 (Wed, 20 Aug 2008)
New Revision: 115

Added:
   trunk/src/main/org/jboss/envers/entities/mapper/PersistentCollectionChangeData.java
   trunk/src/main/org/jboss/envers/entities/mapper/relation/OneToManyUnidirectionalMapper.java
   trunk/src/main/org/jboss/envers/synchronization/work/BidirectionalCollectionChangeWorkUnit.java
   trunk/src/main/org/jboss/envers/synchronization/work/PersistentCollectionChangeWorkUnit.java
Modified:
   trunk/resources/test/hibernate.test.cfg.xml
   trunk/src/main/org/jboss/envers/configuration/EntitiesConfigurator.java
   trunk/src/main/org/jboss/envers/configuration/metadata/MetadataTools.java
   trunk/src/main/org/jboss/envers/configuration/metadata/VersionsMetadataGenerator.java
   trunk/src/main/org/jboss/envers/entities/mapper/MapPropertyMapper.java
   trunk/src/main/org/jboss/envers/entities/mapper/MultiPropertyMapper.java
   trunk/src/main/org/jboss/envers/entities/mapper/PropertyMapper.java
   trunk/src/main/org/jboss/envers/entities/mapper/SinglePropertyMapper.java
   trunk/src/main/org/jboss/envers/entities/mapper/SubclassPropertyMapper.java
   trunk/src/main/org/jboss/envers/entities/mapper/relation/OneToManyIdMapper.java
   trunk/src/main/org/jboss/envers/entities/mapper/relation/OneToOneIdMapper.java
   trunk/src/main/org/jboss/envers/entities/mapper/relation/ToOneIdMapper.java
   trunk/src/main/org/jboss/envers/event/VersionsEventListener.java
   trunk/src/main/org/jboss/envers/synchronization/VersionsSync.java
   trunk/src/main/org/jboss/envers/synchronization/work/AddWorkUnit.java
   trunk/src/main/org/jboss/envers/synchronization/work/DelWorkUnit.java
   trunk/src/main/org/jboss/envers/synchronization/work/KeepCheckVisitor.java
   trunk/src/main/org/jboss/envers/synchronization/work/ModWorkUnit.java
   trunk/src/test/org/jboss/envers/test/working/WorkingEntity1.java
   trunk/src/test/org/jboss/envers/test/working/WorkingEntity2.java
   trunk/src/test/org/jboss/envers/test/working/WorkingMain.java
Log:
ENVERS-26: storing changes in unidirectional one-to-many associations, set valued

Modified: trunk/resources/test/hibernate.test.cfg.xml
===================================================================
--- trunk/resources/test/hibernate.test.cfg.xml	2008-08-18 07:44:39 UTC (rev 114)
+++ trunk/resources/test/hibernate.test.cfg.xml	2008-08-20 11:44:45 UTC (rev 115)
@@ -24,5 +24,14 @@
         <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

Modified: trunk/src/main/org/jboss/envers/configuration/EntitiesConfigurator.java
===================================================================
--- trunk/src/main/org/jboss/envers/configuration/EntitiesConfigurator.java	2008-08-18 07:44:39 UTC (rev 114)
+++ trunk/src/main/org/jboss/envers/configuration/EntitiesConfigurator.java	2008-08-20 11:44:45 UTC (rev 115)
@@ -68,14 +68,14 @@
 
             versionsMetaGen.generateSecondPass(pc, pcDatas.get(pc), mappingData);
 
-            //TODO
-            //writeDocument(document);
 
             try {
                 cfg.addDocument(writer.write(mappingData.getMainMapping()));
+                writeDocument(mappingData.getMainMapping());
 
                 for (Document additionalMapping : mappingData.getAdditionalMappings()) {
-                    cfg.addDocument(writer.write(additionalMapping));    
+                    cfg.addDocument(writer.write(additionalMapping));
+                    writeDocument(additionalMapping);
                 }
             } catch (DocumentException e) {
                 throw new MappingException(e);

Modified: trunk/src/main/org/jboss/envers/configuration/metadata/MetadataTools.java
===================================================================
--- trunk/src/main/org/jboss/envers/configuration/metadata/MetadataTools.java	2008-08-18 07:44:39 UTC (rev 114)
+++ trunk/src/main/org/jboss/envers/configuration/metadata/MetadataTools.java	2008-08-20 11:44:45 UTC (rev 115)
@@ -67,6 +67,7 @@
                                               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);
         class_mapping.addAttribute("entity-name", entityName);

Modified: trunk/src/main/org/jboss/envers/configuration/metadata/VersionsMetadataGenerator.java
===================================================================
--- trunk/src/main/org/jboss/envers/configuration/metadata/VersionsMetadataGenerator.java	2008-08-18 07:44:39 UTC (rev 114)
+++ trunk/src/main/org/jboss/envers/configuration/metadata/VersionsMetadataGenerator.java	2008-08-20 11:44:45 UTC (rev 115)
@@ -21,10 +21,11 @@
  */
 package org.jboss.envers.configuration.metadata;
 
-import org.hibernate.mapping.*;
 import org.hibernate.type.*;
 import org.hibernate.util.StringHelper;
 import org.hibernate.MappingException;
+import org.hibernate.mapping.*;
+import org.hibernate.mapping.Collection;
 import org.dom4j.Element;
 import org.dom4j.Attribute;
 import org.dom4j.tree.DefaultElement;
@@ -37,6 +38,7 @@
 import org.jboss.envers.entities.mapper.relation.ToOneIdMapper;
 import org.jboss.envers.entities.mapper.relation.OneToOneIdMapper;
 import org.jboss.envers.entities.mapper.relation.OneToManyIdMapper;
+import org.jboss.envers.entities.mapper.relation.OneToManyUnidirectionalMapper;
 import org.jboss.envers.tools.StringTools;
 import org.jboss.envers.tools.Tools;
 import org.jboss.envers.tools.HibernateVersion;
@@ -45,10 +47,9 @@
 import org.jboss.envers.tools.log.YLogManager;
 import org.jboss.envers.exception.VersionsException;
 
-import java.util.Iterator;
+import java.util.*;
+import java.util.List;
 import java.util.Map;
-import java.util.Collections;
-import java.util.HashMap;
 
 /**
  * @author Adam Warski (adam at warski dot org)
@@ -87,6 +88,18 @@
         }
     }
 
+    private void addRevisionNumber(Element any_mapping) {
+        Element rev_mapping = MetadataTools.addProperty(any_mapping, verEntCfg.getRevisionPropName(),
+                verEntCfg.getRevisionPropType(), true);
+        MetadataTools.addColumn(rev_mapping, verEntCfg.getRevisionPropName(), null);
+    }
+
+    private void addRevisionType(Element any_mapping) {
+        Element revTypeProperty = MetadataTools.addProperty(any_mapping, verEntCfg.getRevisionTypePropName(),
+                verEntCfg.getRevisionTypePropType(), false);
+        revTypeProperty.addAttribute("type", "org.jboss.envers.entities.RevisionTypeType");
+    }
+
     @SuppressWarnings({"unchecked"})
     private void addSimpleProperty(Element parent, Property property, SimpleMapperBuilder mapper,
                                    ModificationStore store, boolean key) {
@@ -126,7 +139,7 @@
 
     @SuppressWarnings({"unchecked"})
     private void addComponent(Element parent, Property property, CompositeMapperBuilder mapper, ModificationStore store,
-                              String entityName, boolean firstPass) {
+                              String entityName, EntityMappingData mappingData, boolean firstPass) {
         Element component_mapping = null;
         Component prop_component = (Component) property.getValue();
 
@@ -153,7 +166,7 @@
 
         addProperties(component_mapping, (Iterator<Property>) prop_component.getPropertyIterator(),
                 mapper.addComposite(property.getName()), new PropertyStoreInfo(store, EMPTY_STORE), entityName,
-                firstPass);
+                mappingData, firstPass);
     }
 
     @SuppressWarnings({"unchecked"})
@@ -172,7 +185,8 @@
     }
 
     @SuppressWarnings({"unchecked"})
-    private void prefixNamesInPropertyElement(Element element, String prefix, Iterator<Column> columnIterator) {
+    private void prefixNamesInPropertyElement(Element element, String prefix, Iterator<Column> columnIterator,
+                                              boolean changeToKey) {
         Iterator<Element> properties = element.elementIterator();
         while (properties.hasNext()) {
             Element property = properties.next();
@@ -184,6 +198,10 @@
                 }
 
                 changeNamesInColumnElement(property, columnIterator);
+
+                if (changeToKey) {
+                    property.setName("key-property");
+                }
             }
         }
     }
@@ -212,7 +230,7 @@
         Element properties = (Element) idMapping.getXmlRelationMapping().clone();
         properties.addAttribute("name", propertyName);
 
-        prefixNamesInPropertyElement(properties, lastPropertyPrefix, property.getValue().getColumnIterator());
+        prefixNamesInPropertyElement(properties, lastPropertyPrefix, property.getValue().getColumnIterator(), false);
         parent.add(properties);
 
         // Adding mapper for the id
@@ -302,7 +320,8 @@
     }
 
     @SuppressWarnings({"unchecked"})
-    private void addOneToManyUnidirectional(Property property, CompositeMapperBuilder mapper, String entityName) {
+    private void addOneToManyUnidirectional(Property property, CompositeMapperBuilder mapper, String entityName,
+                                            EntityMappingData mappingData) {
         Collection propertyValue = (Collection) property.getValue();
         ManyToOne mto = (ManyToOne) propertyValue.getElement();
 
@@ -321,12 +340,45 @@
         IdMappingData referencingIdMapping = configuration.getIdMappingData();
         IdMappingData referencedIdMapping = referencedConfiguration.getIdMappingData();
 
+        String referencingPrefix = entityName + "_";
+        String referencedPrefix = property.getName() + "_";
+
         // Name of the entity that will be used to store the relation between the two entities.
-        String middleEntityName = entityName + "_" + referencedEntityName;
+        String middleEntityName = referencingPrefix + referencedEntityName;
+        String versionsMiddleEntityName = verEntCfg.getVersionsEntityName(middleEntityName);
+        String versionsMiddleTableName = verEntCfg.getVersionsTableName(middleEntityName, mto.getTable().getName());
 
-        MetadataTools.createEntity(null, middleEntityName, mto.getTable().getName(), mto.getTable().getSchema(),
-                mto.getTable().getCatalog(), null);
+        Element middleEntity = MetadataTools.createEntity(mappingData.newAdditionalMapping(), versionsMiddleEntityName,
+                versionsMiddleTableName, mto.getTable().getSchema(), mto.getTable().getCatalog(), null);
 
+        Element middleEntityId = middleEntity.addElement("composite-id");
+        middleEntityId.addAttribute("name", verEntCfg.getOriginalIdPropName());
+
+        Iterator columnIterator = mto.getTable().getColumnIterator();
+        
+        // Adding elements to the mapping corresponding to the referencing entity id's
+        Element properties = (Element) referencingIdMapping.getXmlRelationMapping().clone();
+        prefixNamesInPropertyElement(properties, referencingPrefix, columnIterator, true);
+        for (Element idProperty : (List<Element>) properties.elements()) {
+            middleEntityId.add((Element) idProperty.clone());
+        }
+
+        // Adding elements to the mapping corresponding to the referenced entity id's
+        properties = (Element) referencedIdMapping.getXmlRelationMapping().clone();
+        prefixNamesInPropertyElement(properties, referencedPrefix, columnIterator, true);
+        for (Element idProperty : (List<Element>) properties.elements()) {
+            middleEntityId.add((Element) idProperty.clone());
+        }
+
+        addRevisionNumber(middleEntityId);
+        addRevisionType(middleEntity);
+
+        // Adding the property mapper
+        mapper.addComposite(property.getName(), new OneToManyUnidirectionalMapper(verEntCfg, property.getName(),
+                referencedEntityName, versionsMiddleEntityName,
+                referencingIdMapping.getIdMapper().prefixMappedProperties(referencingPrefix),
+                referencedIdMapping.getIdMapper().prefixMappedProperties(referencedPrefix)));
+
         // TODO: ???
     }
 
@@ -363,7 +415,8 @@
 
     @SuppressWarnings({"unchecked"})
     private void addProperties(Element parent, Iterator<Property> properties, CompositeMapperBuilder currentMapper,
-                               PropertyStoreInfo propertyStoreInfo, String entityName, boolean firstPass) {
+                               PropertyStoreInfo propertyStoreInfo, String entityName, EntityMappingData mappingData,
+                               boolean firstPass) {
         while (properties.hasNext()) {
             Property property = properties.next();
             Type propertyType = property.getType();
@@ -374,7 +427,7 @@
                     if (propertyType instanceof ComponentType) {
                         // only first pass
                         if (firstPass) {
-                            addComponent(parent, property, currentMapper, store, entityName, firstPass);
+                            addComponent(parent, property, currentMapper, store, entityName, mappingData, firstPass);
                         }
                     } else if (propertyType instanceof ImmutableType || propertyType instanceof MutableType) {
                         // only first pass
@@ -420,7 +473,7 @@
                             ((((Collection) property.getValue()).getElement() instanceof ManyToOne))) {
                         // only second pass
                         if (!firstPass) {
-                            addOneToManyUnidirectional(property, currentMapper, entityName);
+                            addOneToManyUnidirectional(property, currentMapper, entityName, mappingData);
                         }
                     } else {
                         String message = "Type not supported for versioning: " + propertyType.getClass().getName() +
@@ -475,7 +528,7 @@
 
     @SuppressWarnings({"unchecked"})
     private void addJoins(PersistentClass pc, CompositeMapperBuilder currentMapper, PropertyStoreInfo propertyStoreInfo,
-                          String entityName, boolean firstPass) {
+                          String entityName, EntityMappingData mappingData, boolean firstPass) {
         Iterator<Join> joins = pc.getJoinIterator();
 
         while (joins.hasNext()) {
@@ -483,7 +536,7 @@
             Element joinElement = entitiesJoins.get(entityName).get(join);
 
             addProperties(joinElement, join.getPropertyIterator(), currentMapper, propertyStoreInfo, entityName,
-                    firstPass);
+                    mappingData, firstPass);
         }
     }
 
@@ -524,9 +577,7 @@
         orig_id_mapping.addAttribute("name", verEntCfg.getOriginalIdPropName());
 
         // Adding the "revision number" property
-        Element rev_mapping = MetadataTools.addProperty(orig_id_mapping, verEntCfg.getRevisionPropName(),
-                verEntCfg.getRevisionPropType(), true);
-        MetadataTools.addColumn(rev_mapping, verEntCfg.getRevisionPropName(), null);
+        addRevisionNumber(orig_id_mapping);
 
         return new IdMappingData(mapper, orig_id_mapping, rel_id_mapping);
     }
@@ -544,7 +595,7 @@
 
     @SuppressWarnings({"unchecked"})
     public void generateFirstPass(PersistentClass pc, PersistentClassVersioningData versioningData,
-                                      EntityMappingData mappingData) {
+                                  EntityMappingData mappingData) {
         String schema = versioningData.schema;
         if (StringTools.isEmpty(schema)) {
             schema = pc.getTable().getSchema();
@@ -588,9 +639,7 @@
                 class_mapping.add((Element) idMapper.getXmlMapping().clone());
 
                 // Adding the "revision type" property
-                Element revTypeProperty = MetadataTools.addProperty(class_mapping, verEntCfg.getRevisionTypePropName(),
-                    verEntCfg.getRevisionTypePropType(), false);
-                revTypeProperty.addAttribute("type", "org.jboss.envers.entities.RevisionTypeType");
+                addRevisionType(class_mapping);
 
                 break;
             case SINGLE:
@@ -618,14 +667,14 @@
 
         // Mapping unjoined properties
         addProperties(class_mapping, (Iterator<Property>) pc.getUnjoinedPropertyIterator(), propertyMapper,
-                versioningData.propertyStoreInfo, pc.getEntityName(), true);
+                versioningData.propertyStoreInfo, pc.getEntityName(), mappingData, true);
 
         // Creating and mapping joins (first pass)
         createJoins(pc, class_mapping, versioningData);
-        addJoins(pc, propertyMapper, versioningData.propertyStoreInfo, pc.getEntityName(), true);
+        addJoins(pc, propertyMapper, versioningData.propertyStoreInfo, pc.getEntityName(), mappingData, true);
 
         // Storing the generated configuration
-        EntityConfiguration entityCfg = new EntityConfiguration(entityName, versionsEntityName, idMapper, 
+        EntityConfiguration entityCfg = new EntityConfiguration(entityName, versionsEntityName, idMapper,
                 propertyMapper, parentEntityName);
         entitiesConfigurations.put(pc.getEntityName(), entityCfg);
     }
@@ -642,12 +691,12 @@
         if (parent == null) {
             parent = mappingData.getMainMapping().getRootElement().element("subclass");
         }
-        
+
         addProperties(parent, (Iterator<Property>) pc.getUnjoinedPropertyIterator(),
-                propertyMapper, versioningData.propertyStoreInfo, entityName, false);
+                propertyMapper, versioningData.propertyStoreInfo, entityName, mappingData, false);
 
         // Mapping joins (second pass)
-        addJoins(pc, propertyMapper, versioningData.propertyStoreInfo, entityName, false);
+        addJoins(pc, propertyMapper, versioningData.propertyStoreInfo, entityName, mappingData, false);
     }
 
     public Map<String, EntityConfiguration> getEntitiesConfigurations() {

Modified: trunk/src/main/org/jboss/envers/entities/mapper/MapPropertyMapper.java
===================================================================
--- trunk/src/main/org/jboss/envers/entities/mapper/MapPropertyMapper.java	2008-08-18 07:44:39 UTC (rev 114)
+++ trunk/src/main/org/jboss/envers/entities/mapper/MapPropertyMapper.java	2008-08-20 11:44:45 UTC (rev 115)
@@ -28,9 +28,12 @@
 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)
@@ -80,4 +83,11 @@
         }
     }
 
+    public List<PersistentCollectionChangeData> mapCollectionChangesFromCollections(String referencingPropertyName,
+                                                                                    PersistentCollection newColl,
+                                                                                    Serializable oldColl,
+                                                                                    Serializable id) {
+        return delegate.mapCollectionChangesFromCollections(referencingPropertyName, newColl, oldColl, id);
+    }
+
 }

Modified: trunk/src/main/org/jboss/envers/entities/mapper/MultiPropertyMapper.java
===================================================================
--- trunk/src/main/org/jboss/envers/entities/mapper/MultiPropertyMapper.java	2008-08-18 07:44:39 UTC (rev 114)
+++ trunk/src/main/org/jboss/envers/entities/mapper/MultiPropertyMapper.java	2008-08-20 11:44:45 UTC (rev 115)
@@ -23,12 +23,15 @@
 
 import org.hibernate.property.Getter;
 import org.hibernate.MappingException;
+import org.hibernate.collection.PersistentCollection;
 import org.jboss.envers.ModificationStore;
 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)
@@ -104,4 +107,15 @@
         }
     }
 
+    public List<PersistentCollectionChangeData> mapCollectionChangesFromCollections(String referencingPropertyName,
+                                                                                    PersistentCollection newColl,
+                                                                                    Serializable oldColl,
+                                                                                    Serializable id) {
+        PropertyMapper mapper = properties.get(referencingPropertyName);
+        if (mapper != null) {
+            return mapper.mapCollectionChangesFromCollections(referencingPropertyName, newColl, oldColl, id);
+        } else {
+            return null;
+        }
+    }
 }

Added: trunk/src/main/org/jboss/envers/entities/mapper/PersistentCollectionChangeData.java
===================================================================
--- trunk/src/main/org/jboss/envers/entities/mapper/PersistentCollectionChangeData.java	                        (rev 0)
+++ trunk/src/main/org/jboss/envers/entities/mapper/PersistentCollectionChangeData.java	2008-08-20 11:44:45 UTC (rev 115)
@@ -0,0 +1,24 @@
+package org.jboss.envers.entities.mapper;
+
+import java.util.Map;
+
+/**
+ * @author Adam Warski (adam at warski dot org)
+ */
+public class PersistentCollectionChangeData {
+    private String entityName;
+    private Map<String, Object> data;
+
+    public PersistentCollectionChangeData(String entityName, Map<String, Object> data) {
+        this.entityName = entityName;
+        this.data = data;
+    }
+
+    public String getEntityName() {
+        return entityName;
+    }
+
+    public Map<String, Object> getData() {
+        return data;
+    }
+}

Modified: trunk/src/main/org/jboss/envers/entities/mapper/PropertyMapper.java
===================================================================
--- trunk/src/main/org/jboss/envers/entities/mapper/PropertyMapper.java	2008-08-18 07:44:39 UTC (rev 114)
+++ trunk/src/main/org/jboss/envers/entities/mapper/PropertyMapper.java	2008-08-20 11:44:45 UTC (rev 115)
@@ -22,8 +22,11 @@
 package org.jboss.envers.entities.mapper;
 
 import org.jboss.envers.reader.VersionsReaderImplementor;
+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)
@@ -49,4 +52,17 @@
      */
     public void mapToEntityFromMap(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.
+     */
+    public List<PersistentCollectionChangeData> mapCollectionChangesFromCollections(String referencingPropertyName,
+                                                                                    PersistentCollection newColl,
+                                                                                    Serializable oldColl,
+                                                                                    Serializable id);
 }

Modified: trunk/src/main/org/jboss/envers/entities/mapper/SinglePropertyMapper.java
===================================================================
--- trunk/src/main/org/jboss/envers/entities/mapper/SinglePropertyMapper.java	2008-08-18 07:44:39 UTC (rev 114)
+++ trunk/src/main/org/jboss/envers/entities/mapper/SinglePropertyMapper.java	2008-08-20 11:44:45 UTC (rev 115)
@@ -27,8 +27,11 @@
 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
@@ -66,4 +69,11 @@
         setter.set(obj, data.get(propertyName), null);
     }
 
+    public List<PersistentCollectionChangeData> mapCollectionChangesFromCollections(String referencingPropertyName,
+                                                                                    PersistentCollection newColl,
+                                                                                    Serializable oldColl,
+                                                                                    Serializable id) {
+        return null;
+    }
+
 }

Modified: trunk/src/main/org/jboss/envers/entities/mapper/SubclassPropertyMapper.java
===================================================================
--- trunk/src/main/org/jboss/envers/entities/mapper/SubclassPropertyMapper.java	2008-08-18 07:44:39 UTC (rev 114)
+++ trunk/src/main/org/jboss/envers/entities/mapper/SubclassPropertyMapper.java	2008-08-20 11:44:45 UTC (rev 115)
@@ -23,8 +23,11 @@
 
 import org.jboss.envers.reader.VersionsReaderImplementor;
 import org.jboss.envers.ModificationStore;
+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
@@ -59,6 +62,20 @@
         main.mapToEntityFromMap(obj, data, primaryKey, versionsReader, revision);
     }
 
+    public List<PersistentCollectionChangeData> mapCollectionChangesFromCollections(String referencingPropertyName,
+                                                                                    PersistentCollection newColl, 
+                                                                                    Serializable oldColl,
+                                                                                    Serializable id) {
+        List<PersistentCollectionChangeData> collectionChanges = parentMapper.mapCollectionChangesFromCollections(
+                referencingPropertyName, newColl, oldColl, id);
+
+        if (collectionChanges == null) {
+            return main.mapCollectionChangesFromCollections(referencingPropertyName, newColl, oldColl, id);
+        } else {
+            return collectionChanges;
+        }
+    }
+
     public CompositeMapperBuilder addComposite(String propertyName) {
         return main.addComposite(propertyName);
     }

Modified: trunk/src/main/org/jboss/envers/entities/mapper/relation/OneToManyIdMapper.java
===================================================================
--- trunk/src/main/org/jboss/envers/entities/mapper/relation/OneToManyIdMapper.java	2008-08-18 07:44:39 UTC (rev 114)
+++ trunk/src/main/org/jboss/envers/entities/mapper/relation/OneToManyIdMapper.java	2008-08-20 11:44:45 UTC (rev 115)
@@ -22,6 +22,7 @@
 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.entities.mapper.relation.lazy.OneToManyInitializor;
 import org.jboss.envers.entities.mapper.relation.lazy.proxy.ListProxy;
@@ -30,8 +31,10 @@
 import org.jboss.envers.tools.reflection.ReflectionTools;
 import org.hibernate.property.Setter;
 import org.hibernate.property.Getter;
+import org.hibernate.collection.PersistentCollection;
 
 import java.util.*;
+import java.io.Serializable;
 
 /**
  * @author Adam Warski (adam at warski dot org)
@@ -77,4 +80,11 @@
         Setter setter = ReflectionTools.getSetter(obj.getClass(), propertyName);
         setter.set(obj, value, null);
     }
+
+    public List<PersistentCollectionChangeData> mapCollectionChangesFromCollections(String referencingPropertyName,
+                                                                                    PersistentCollection newColl,
+                                                                                    Serializable oldColl,
+                                                                                    Serializable id) {
+        return null;
+    }
 }
\ No newline at end of file

Added: trunk/src/main/org/jboss/envers/entities/mapper/relation/OneToManyUnidirectionalMapper.java
===================================================================
--- trunk/src/main/org/jboss/envers/entities/mapper/relation/OneToManyUnidirectionalMapper.java	                        (rev 0)
+++ trunk/src/main/org/jboss/envers/entities/mapper/relation/OneToManyUnidirectionalMapper.java	2008-08-20 11:44:45 UTC (rev 115)
@@ -0,0 +1,99 @@
+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.reader.VersionsReaderImplementor;
+import org.jboss.envers.configuration.VersionsEntitiesConfiguration;
+import org.jboss.envers.RevisionType;
+import org.hibernate.collection.PersistentCollection;
+
+import java.util.*;
+import java.io.Serializable;
+
+/**
+ * @author Adam Warski (adam at warski dot org)
+ */
+public class OneToManyUnidirectionalMapper implements PropertyMapper {
+    private final VersionsEntitiesConfiguration verEntCfg;
+    private final String collectionReferencingPropertyName;
+    private final String referencedEntityName;
+    private final String versionsMiddleEntityName;
+    private final IdMapper referencingMiddleIdMapper;
+    private final IdMapper referencedMiddleIdMapper;
+
+    public OneToManyUnidirectionalMapper(VersionsEntitiesConfiguration verEntCfg,
+                                         String collectionReferencingPropertyName,
+                                         String referencedEntityName, String versionsMiddleEntityName,
+                                         IdMapper referencingMiddleIdMapper, IdMapper referencedMiddleIdMapper) {
+        this.verEntCfg = verEntCfg;
+        this.collectionReferencingPropertyName = collectionReferencingPropertyName;
+        this.referencedEntityName = referencedEntityName;
+        this.versionsMiddleEntityName = versionsMiddleEntityName;
+        this.referencingMiddleIdMapper = referencingMiddleIdMapper;
+        this.referencedMiddleIdMapper = referencedMiddleIdMapper;
+    }
+
+    private Collection getOldCollection(Serializable oldColl) {
+        if (oldColl instanceof Map) {
+            return ((Map) oldColl).keySet();
+        } else {
+            return (Collection) oldColl;
+        }
+    }
+
+    private void addCollectionChanges(List<PersistentCollectionChangeData> collectionChanges, Set<Object> changed,
+                                      RevisionType revisionType, Serializable id) {
+        for (Object changedEntity : changed) {
+            Map<String, Object> entityData = new HashMap<String, Object>();
+            Map<String, Object> originalId = new HashMap<String, Object>();
+            entityData.put(verEntCfg.getOriginalIdPropName(), originalId);
+
+            collectionChanges.add(new PersistentCollectionChangeData(versionsMiddleEntityName, entityData));
+            referencingMiddleIdMapper.mapToMapFromId(originalId, id);
+            referencedMiddleIdMapper.mapToMapFromEntity(originalId, changedEntity);
+
+            entityData.put(verEntCfg.getRevisionTypePropName(), revisionType);
+
+            System.out.println("entityData = " + entityData);
+        }
+    }
+
+    @SuppressWarnings({"unchecked"})
+    public List<PersistentCollectionChangeData> mapCollectionChangesFromCollections(String referencingPropertyName,
+                                                                                    PersistentCollection newColl,
+                                                                                    Serializable oldColl,
+                                                                                    Serializable id) {
+        if (!collectionReferencingPropertyName.equals(referencingPropertyName)) {
+            return null;
+        }
+
+        List<PersistentCollectionChangeData> collectionChanges = new ArrayList<PersistentCollectionChangeData>();
+
+        Collection newCollection = (Collection) newColl;
+        Collection oldCollection = getOldCollection(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;
+    }
+
+    @SuppressWarnings({"unchecked"})
+    public boolean mapToMapFromEntity(Map<String, Object> data, Object newObj, Object oldObj) {
+        return false;
+    }
+
+    public void mapToEntityFromMap(Object obj, Map data, Object primaryKey, VersionsReaderImplementor versionsReader, Number revision) {
+        System.out.println("XXX");
+    }
+}

Modified: trunk/src/main/org/jboss/envers/entities/mapper/relation/OneToOneIdMapper.java
===================================================================
--- trunk/src/main/org/jboss/envers/entities/mapper/relation/OneToOneIdMapper.java	2008-08-18 07:44:39 UTC (rev 114)
+++ trunk/src/main/org/jboss/envers/entities/mapper/relation/OneToOneIdMapper.java	2008-08-20 11:44:45 UTC (rev 115)
@@ -22,15 +22,19 @@
 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.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)
@@ -72,4 +76,11 @@
         Setter setter = ReflectionTools.getSetter(obj.getClass(), propertyName);
         setter.set(obj, value, null);
     }
+
+    public List<PersistentCollectionChangeData> mapCollectionChangesFromCollections(String referencingPropertyName,
+                                                                                    PersistentCollection newColl,
+                                                                                    Serializable oldColl,
+                                                                                    Serializable id) {
+        return null;
+    }
 }

Modified: trunk/src/main/org/jboss/envers/entities/mapper/relation/ToOneIdMapper.java
===================================================================
--- trunk/src/main/org/jboss/envers/entities/mapper/relation/ToOneIdMapper.java	2008-08-18 07:44:39 UTC (rev 114)
+++ trunk/src/main/org/jboss/envers/entities/mapper/relation/ToOneIdMapper.java	2008-08-20 11:44:45 UTC (rev 115)
@@ -22,15 +22,19 @@
 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.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)
@@ -62,10 +66,6 @@
         }
 
         Object entityId = delegate.mapToIdFromMap((Map) data.get(propertyName));
-        doMap(obj, versionsReader, revision, entityId);
-    }
-
-    private void doMap(Object obj, VersionsReaderImplementor versionsReader, Number revision, Object entityId) {
         Object value;
         if (entityId == null) {
             value = null;
@@ -79,4 +79,11 @@
         Setter setter = ReflectionTools.getSetter(obj.getClass(), propertyName);
         setter.set(obj, value, null);
     }
+
+    public List<PersistentCollectionChangeData> mapCollectionChangesFromCollections(String referencingPropertyName,
+                                                                                    PersistentCollection newColl,
+                                                                                    Serializable oldColl,
+                                                                                    Serializable id) {
+        return null;
+    }
 }

Modified: trunk/src/main/org/jboss/envers/event/VersionsEventListener.java
===================================================================
--- trunk/src/main/org/jboss/envers/event/VersionsEventListener.java	2008-08-18 07:44:39 UTC (rev 114)
+++ trunk/src/main/org/jboss/envers/event/VersionsEventListener.java	2008-08-20 11:44:45 UTC (rev 115)
@@ -24,14 +24,13 @@
 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.AddWorkUnit;
-import org.jboss.envers.synchronization.work.ModWorkUnit;
-import org.jboss.envers.synchronization.work.DelWorkUnit;
-import org.jboss.envers.synchronization.work.CollectionChangeWorkUnit;
+import org.jboss.envers.synchronization.work.*;
 import org.jboss.envers.tools.Tools;
 import org.jboss.envers.entities.mapper.id.IdMapper;
 
@@ -41,7 +40,8 @@
  * @author Adam Warski (adam at warski dot org)
  */
 public class VersionsEventListener implements PostInsertEventListener, PostUpdateEventListener,
-        PostDeleteEventListener, Initializable {
+        PostDeleteEventListener, PreCollectionUpdateEventListener, PreCollectionRemoveEventListener,
+        PostCollectionRecreateEventListener, Initializable {
     private VersionsConfiguration verCfg;
 
     private void generateCollectionChangeWorkUnits(VersionsSync verSync, EntityPersister entityPersister,
@@ -71,12 +71,12 @@
                     // (size increases).
                     if (newValue != null) {
                         Serializable id = (Serializable) idMapper.mapToIdFromEntity(newValue);
-                        verSync.addWorkUnit(new CollectionChangeWorkUnit(relDesc.getToEntityName(), verCfg, id, newValue));
+                        verSync.addWorkUnit(new BidirectionalCollectionChangeWorkUnit(relDesc.getToEntityName(), verCfg, id, newValue));
                     }
                     
                     if (oldValue != null) {
                         Serializable id = (Serializable) idMapper.mapToIdFromEntity(oldValue);
-                        verSync.addWorkUnit(new CollectionChangeWorkUnit(relDesc.getToEntityName(), verCfg, id, oldValue));
+                        verSync.addWorkUnit(new BidirectionalCollectionChangeWorkUnit(relDesc.getToEntityName(), verCfg, id, oldValue));
                     }
                 }
             }
@@ -121,6 +121,36 @@
         }
     }
 
+    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());
+
+            verSync.addWorkUnit(new PersistentCollectionChangeWorkUnit(entityName, verCfg, newColl,
+                    collectionEntry.getRole(), oldColl, event.getAffectedOwnerIdOrNull()));
+        }
+    }
+
+    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);

Modified: trunk/src/main/org/jboss/envers/synchronization/VersionsSync.java
===================================================================
--- trunk/src/main/org/jboss/envers/synchronization/VersionsSync.java	2008-08-18 07:44:39 UTC (rev 114)
+++ trunk/src/main/org/jboss/envers/synchronization/VersionsSync.java	2008-08-20 11:44:45 UTC (rev 115)
@@ -38,7 +38,7 @@
     private final RevisionNumberGenerator revisionNumberGenerator;
     private final VersionsSyncManager manager;
     private final Session session;
-    
+
     private final Transaction transaction;
     private final LinkedList<VersionsWorkUnit> workUnits;
     private final Queue<VersionsWorkUnit> undoQueue;
@@ -56,7 +56,7 @@
         undoQueue = new LinkedList<VersionsWorkUnit>();
         usedIds = new HashMap<Pair<String, Object>, VersionsWorkUnit>();
     }
-    
+
     private void removeWorkUnit(VersionsWorkUnit vwu) {
         workUnits.remove(vwu);
         if (vwu.isPerformed()) {
@@ -68,30 +68,37 @@
     public void addWorkUnit(VersionsWorkUnit vwu) {
         if (vwu.containsWork()) {
             Object entityId = vwu.getEntityId();
-            String entityName = vwu.getEntityName();
-            Pair<String, Object> usedIdsKey = Pair.make(entityName, entityId);
 
-            if (usedIds.containsKey(usedIdsKey)) {
-                VersionsWorkUnit other = usedIds.get(usedIdsKey);
+            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);
 
-                // 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;
+                if (usedIds.containsKey(usedIdsKey)) {
+                    VersionsWorkUnit other = usedIds.get(usedIdsKey);
 
-                    case SECOND:
-                        removeWorkUnit(other);
-                        usedIds.put(usedIdsKey, vwu);
-                        workUnits.offer(vwu);
-                        break;
+                    // 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 NONE:
-                        removeWorkUnit(other);
+                        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);
                 }
-            } else {
-                usedIds.put(usedIdsKey, vwu);
-                workUnits.offer(vwu);
             }
         }
     }

Modified: trunk/src/main/org/jboss/envers/synchronization/work/AddWorkUnit.java
===================================================================
--- trunk/src/main/org/jboss/envers/synchronization/work/AddWorkUnit.java	2008-08-18 07:44:39 UTC (rev 114)
+++ trunk/src/main/org/jboss/envers/synchronization/work/AddWorkUnit.java	2008-08-20 11:44:45 UTC (rev 115)
@@ -72,7 +72,7 @@
         return KeepCheckResult.NONE;
     }
 
-    public KeepCheckResult check(CollectionChangeWorkUnit second) {
+    public KeepCheckResult check(BidirectionalCollectionChangeWorkUnit second) {
         return KeepCheckResult.FIRST;
     }
 

Copied: trunk/src/main/org/jboss/envers/synchronization/work/BidirectionalCollectionChangeWorkUnit.java (from rev 114, trunk/src/main/org/jboss/envers/synchronization/work/CollectionChangeWorkUnit.java)
===================================================================
--- trunk/src/main/org/jboss/envers/synchronization/work/BidirectionalCollectionChangeWorkUnit.java	                        (rev 0)
+++ trunk/src/main/org/jboss/envers/synchronization/work/BidirectionalCollectionChangeWorkUnit.java	2008-08-20 11:44:45 UTC (rev 115)
@@ -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 BidirectionalCollectionChangeWorkUnit extends AbstractVersionsWorkUnit implements VersionsWorkUnit {
+    private final Object entity;
+
+    public BidirectionalCollectionChangeWorkUnit(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, Number revision) {
+        Map<String, Object> data = new HashMap<String, Object>();
+        fillDataWithId(data, revision, 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(BidirectionalCollectionChangeWorkUnit second) {
+        return KeepCheckResult.FIRST;
+    }
+
+    public KeepCheckResult dispatch(KeepCheckVisitor first) {
+        return first.check(this);
+    }
+}

Modified: trunk/src/main/org/jboss/envers/synchronization/work/DelWorkUnit.java
===================================================================
--- trunk/src/main/org/jboss/envers/synchronization/work/DelWorkUnit.java	2008-08-18 07:44:39 UTC (rev 114)
+++ trunk/src/main/org/jboss/envers/synchronization/work/DelWorkUnit.java	2008-08-20 11:44:45 UTC (rev 115)
@@ -62,7 +62,7 @@
         return KeepCheckResult.FIRST;
     }
 
-    public KeepCheckResult check(CollectionChangeWorkUnit second) {
+    public KeepCheckResult check(BidirectionalCollectionChangeWorkUnit second) {
         return KeepCheckResult.FIRST;
     }
 

Modified: trunk/src/main/org/jboss/envers/synchronization/work/KeepCheckVisitor.java
===================================================================
--- trunk/src/main/org/jboss/envers/synchronization/work/KeepCheckVisitor.java	2008-08-18 07:44:39 UTC (rev 114)
+++ trunk/src/main/org/jboss/envers/synchronization/work/KeepCheckVisitor.java	2008-08-20 11:44:45 UTC (rev 115)
@@ -29,5 +29,5 @@
     KeepCheckResult check(AddWorkUnit second);
     KeepCheckResult check(ModWorkUnit second);
     KeepCheckResult check(DelWorkUnit second);
-    KeepCheckResult check(CollectionChangeWorkUnit second);
+    KeepCheckResult check(BidirectionalCollectionChangeWorkUnit second);
 }

Modified: trunk/src/main/org/jboss/envers/synchronization/work/ModWorkUnit.java
===================================================================
--- trunk/src/main/org/jboss/envers/synchronization/work/ModWorkUnit.java	2008-08-18 07:44:39 UTC (rev 114)
+++ trunk/src/main/org/jboss/envers/synchronization/work/ModWorkUnit.java	2008-08-20 11:44:45 UTC (rev 115)
@@ -70,7 +70,7 @@
         return KeepCheckResult.SECOND;
     }
 
-    public KeepCheckResult check(CollectionChangeWorkUnit second) {
+    public KeepCheckResult check(BidirectionalCollectionChangeWorkUnit second) {
         return KeepCheckResult.FIRST;
     }
 

Added: trunk/src/main/org/jboss/envers/synchronization/work/PersistentCollectionChangeWorkUnit.java
===================================================================
--- trunk/src/main/org/jboss/envers/synchronization/work/PersistentCollectionChangeWorkUnit.java	                        (rev 0)
+++ trunk/src/main/org/jboss/envers/synchronization/work/PersistentCollectionChangeWorkUnit.java	2008-08-20 11:44:45 UTC (rev 115)
@@ -0,0 +1,66 @@
+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;
+
+    public PersistentCollectionChangeWorkUnit(String entityName, VersionsConfiguration verCfg,
+                                              PersistentCollection collection, String role,
+                                              Serializable snapshot, Serializable id) {
+        super(entityName, verCfg, null);
+
+        String referencingPropertyName = role.substring(entityName.length() + 1);
+
+        collectionChanges = verCfg.getEntCfg().get(getEntityName()).getPropertyMapper()
+                .mapCollectionChangesFromCollections(referencingPropertyName, collection, snapshot, id);
+    }
+
+    public boolean containsWork() {
+        return collectionChanges == null || collectionChanges.size() != 0;
+    }
+
+    @SuppressWarnings({"unchecked"})
+    public void perform(Session session, Number revision) {
+        VersionsEntitiesConfiguration entitiesCfg = verCfg.getVerEntCfg();
+
+        for (PersistentCollectionChangeData persistentCollectionChangeData : collectionChanges) {
+            // Setting the revision number
+            ((Map<String, Object>) persistentCollectionChangeData.getData().get(entitiesCfg.getOriginalIdPropName()))
+                    .put(entitiesCfg.getRevisionPropName(), revision);
+
+            session.save(persistentCollectionChangeData.getEntityName(), persistentCollectionChangeData.getData());
+        }
+    }
+
+    public KeepCheckResult check(AddWorkUnit second) {
+        return null;
+    }
+
+    public KeepCheckResult check(ModWorkUnit second) {
+        return null;
+    }
+
+    public KeepCheckResult check(DelWorkUnit second) {
+        return null;
+    }
+
+    public KeepCheckResult check(BidirectionalCollectionChangeWorkUnit second) {
+        return null;
+    }
+
+    public KeepCheckResult dispatch(KeepCheckVisitor first) {
+        return null;
+    }
+}

Modified: trunk/src/test/org/jboss/envers/test/working/WorkingEntity1.java
===================================================================
--- trunk/src/test/org/jboss/envers/test/working/WorkingEntity1.java	2008-08-18 07:44:39 UTC (rev 114)
+++ trunk/src/test/org/jboss/envers/test/working/WorkingEntity1.java	2008-08-20 11:44:45 UTC (rev 115)
@@ -25,10 +25,10 @@
     //@Column(table = "second_table", name = "cc_second")
     private String cc;
 
-    @Versioned
+    //@Versioned
     //@OneToOne
-    @ManyToOne
-    //@Transient
+    //@ManyToOne
+    @Transient
     private WorkingEntity2 we2;
 
     public WorkingEntity1() {

Modified: trunk/src/test/org/jboss/envers/test/working/WorkingEntity2.java
===================================================================
--- trunk/src/test/org/jboss/envers/test/working/WorkingEntity2.java	2008-08-18 07:44:39 UTC (rev 114)
+++ trunk/src/test/org/jboss/envers/test/working/WorkingEntity2.java	2008-08-20 11:44:45 UTC (rev 115)
@@ -22,7 +22,7 @@
     private String str2;
 
     @Versioned
-    @OneToMany(mappedBy="we2")
+    @OneToMany //(mappedBy="we2")
     //@ManyToMany
     //@Transient
     private Set<WorkingEntity1> we1s;

Modified: trunk/src/test/org/jboss/envers/test/working/WorkingMain.java
===================================================================
--- trunk/src/test/org/jboss/envers/test/working/WorkingMain.java	2008-08-18 07:44:39 UTC (rev 114)
+++ trunk/src/test/org/jboss/envers/test/working/WorkingMain.java	2008-08-20 11:44:45 UTC (rev 115)
@@ -60,43 +60,64 @@
         // Rev 1
         entityManager.getTransaction().begin();
 
-        WorkingEntity2 we2 = new WorkingEntity2("s");
-        entityManager.persist(we2);
-
         WorkingEntity1 we1 = new WorkingEntity1("b", "c");
-        we1.setWe2(we2);
         entityManager.persist(we1);
 
         WorkingEntity1 we1_2 = new WorkingEntity1("b2", "c2");
-        we1_2.setWe2(we2);
         entityManager.persist(we1_2);
 
+        WorkingEntity1 we1_3 = new WorkingEntity1("b3", "c3");
+        entityManager.persist(we1_3);
+
+        WorkingEntity2 we2 = new WorkingEntity2("s");
+        Set<WorkingEntity1> we1s = new HashSet<WorkingEntity1>();
+        we1s.add(we1_3);
+        we2.setWe1s(we1s);
+        entityManager.persist(we2);
+
         entityManager.getTransaction().commit();
 
         // Rev 2
         entityManager.getTransaction().begin();
 
         we1 = entityManager.find(WorkingEntity1.class, we1.getId1());
-        entityManager.remove(we1);
+        we2 = entityManager.find(WorkingEntity2.class, we2.getId2());
+        we2.getWe1s().add(we1);
 
         entityManager.getTransaction().commit();
 
         // Rev 3
         entityManager.getTransaction().begin();
 
-        VersionsReader vr = VersionsReaderFactory.get(entityManager);
+        we1_2 = entityManager.find(WorkingEntity1.class, we1_2.getId1());
+        we2 = entityManager.find(WorkingEntity2.class, we2.getId2());
+        we2.getWe1s().add(we1_2);
 
-        System.out.println(vr.createQuery().forEntitiesAtRevision(WorkingEntity1.class, 1)
-            .getResultList());
-        System.out.println(vr.createQuery().forEntitiesAtRevision(WorkingEntity1.class, 1)
-            .setProjection(Projections.count("originalId.id1")).getResultList());
+        entityManager.getTransaction().commit();
 
-        System.out.println(vr.createQuery().forEntitiesAtRevision(WorkingEntity1.class, 2)
-            .getResultList());
-        System.out.println(vr.createQuery().forEntitiesAtRevision(WorkingEntity1.class, 2)
-            .setProjection(Projections.count("originalId.id1")).getResultList());
+        // Rev 4
+        entityManager.getTransaction().begin();
 
+        we1_2 = entityManager.find(WorkingEntity1.class, we1_2.getId1());
+        we2 = entityManager.find(WorkingEntity2.class, we2.getId2());
+        we2.getWe1s().remove(we1_2);
+
         entityManager.getTransaction().commit();
+
+        // Rev 5
+        entityManager.getTransaction().begin();
+
+        we2 = entityManager.find(WorkingEntity2.class, we2.getId2());
+        we2.setWe1s(null);
+
+        entityManager.getTransaction().commit();
+
+        // Rev 6
+        entityManager.getTransaction().begin();
+
+        VersionsReader vr = VersionsReaderFactory.get(entityManager);
+
+        entityManager.getTransaction().commit();
     }
 }
 




More information about the jboss-envers-commits mailing list