You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@openjpa.apache.org by jr...@apache.org on 2009/07/07 04:35:09 UTC

svn commit: r791678 - in /openjpa/trunk: openjpa-integration/validation/src/test/java/org/apache/openjpa/integration/validation/ openjpa-integration/validation/src/test/resources/org/apache/openjpa/integration/validation/ openjpa-kernel/src/main/java/o...

Author: jrbauer
Date: Tue Jul  7 02:35:08 2009
New Revision: 791678

URL: http://svn.apache.org/viewvc?rev=791678&view=rev
Log:
OPENJPA-1082 Added support for configurable bean validation groups

Added:
    openjpa/trunk/openjpa-integration/validation/src/test/java/org/apache/openjpa/integration/validation/DefGrpEntity.java   (with props)
    openjpa/trunk/openjpa-integration/validation/src/test/java/org/apache/openjpa/integration/validation/MixedGrpEntity.java   (with props)
    openjpa/trunk/openjpa-integration/validation/src/test/java/org/apache/openjpa/integration/validation/NonDefGrpEntity.java   (with props)
    openjpa/trunk/openjpa-integration/validation/src/test/java/org/apache/openjpa/integration/validation/TestValidationGroups.java   (with props)
    openjpa/trunk/openjpa-integration/validation/src/test/java/org/apache/openjpa/integration/validation/ValGroup1.java   (with props)
    openjpa/trunk/openjpa-integration/validation/src/test/java/org/apache/openjpa/integration/validation/ValGroup2.java   (with props)
Modified:
    openjpa/trunk/openjpa-integration/validation/src/test/resources/org/apache/openjpa/integration/validation/persistence.xml
    openjpa/trunk/openjpa-kernel/src/main/java/org/apache/openjpa/conf/OpenJPAConfiguration.java
    openjpa/trunk/openjpa-kernel/src/main/java/org/apache/openjpa/conf/OpenJPAConfigurationImpl.java
    openjpa/trunk/openjpa-persistence/src/main/java/org/apache/openjpa/persistence/validation/ValidationUtils.java
    openjpa/trunk/openjpa-persistence/src/main/java/org/apache/openjpa/persistence/validation/ValidatorImpl.java
    openjpa/trunk/openjpa-persistence/src/main/resources/org/apache/openjpa/persistence/validation/localizer.properties

Added: openjpa/trunk/openjpa-integration/validation/src/test/java/org/apache/openjpa/integration/validation/DefGrpEntity.java
URL: http://svn.apache.org/viewvc/openjpa/trunk/openjpa-integration/validation/src/test/java/org/apache/openjpa/integration/validation/DefGrpEntity.java?rev=791678&view=auto
==============================================================================
--- openjpa/trunk/openjpa-integration/validation/src/test/java/org/apache/openjpa/integration/validation/DefGrpEntity.java (added)
+++ openjpa/trunk/openjpa-integration/validation/src/test/java/org/apache/openjpa/integration/validation/DefGrpEntity.java Tue Jul  7 02:35:08 2009
@@ -0,0 +1,52 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.    
+ */
+package org.apache.openjpa.integration.validation;
+
+import javax.persistence.Entity;
+import javax.persistence.GeneratedValue;
+import javax.persistence.Id;
+import javax.validation.constraints.NotNull;
+
+@Entity
+public class DefGrpEntity {
+
+    @Id
+    @GeneratedValue
+    private int id;
+    
+    // NotNull constraint with default validation group
+    @NotNull
+    private String dgName;
+
+    public void setId(int id) {
+        this.id = id;
+    }
+
+    public int getId() {
+        return id;
+    }
+
+    public void setDgName(String dgName) {
+        this.dgName = dgName;
+    }
+
+    public String getDgName() {
+        return dgName;
+    }    
+}

Propchange: openjpa/trunk/openjpa-integration/validation/src/test/java/org/apache/openjpa/integration/validation/DefGrpEntity.java
------------------------------------------------------------------------------
    svn:eol-style = native

Added: openjpa/trunk/openjpa-integration/validation/src/test/java/org/apache/openjpa/integration/validation/MixedGrpEntity.java
URL: http://svn.apache.org/viewvc/openjpa/trunk/openjpa-integration/validation/src/test/java/org/apache/openjpa/integration/validation/MixedGrpEntity.java?rev=791678&view=auto
==============================================================================
--- openjpa/trunk/openjpa-integration/validation/src/test/java/org/apache/openjpa/integration/validation/MixedGrpEntity.java (added)
+++ openjpa/trunk/openjpa-integration/validation/src/test/java/org/apache/openjpa/integration/validation/MixedGrpEntity.java Tue Jul  7 02:35:08 2009
@@ -0,0 +1,76 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.    
+ */
+package org.apache.openjpa.integration.validation;
+
+import javax.persistence.Entity;
+import javax.persistence.GeneratedValue;
+import javax.persistence.Id;
+import javax.validation.constraints.NotNull;
+
+@Entity
+public class MixedGrpEntity {
+
+    @Id
+    @GeneratedValue
+    private int id;
+
+    @NotNull
+    private String defNotNull;
+    
+    @NotNull(groups=ValGroup1.class)
+    private String vg1NotNull;
+    
+    @NotNull(groups=ValGroup2.class)
+    private String vg2NotNull;
+    
+    @NotNull(groups={ValGroup1.class, ValGroup2.class})
+    private String vg12NotNull;
+
+    public void setDefNotNull(String defNotNull) {
+        this.defNotNull = defNotNull;
+    }
+
+    public String getDefNotNull() {
+        return defNotNull;
+    }
+
+    public void setVg1NotNull(String vg1NotNull) {
+        this.vg1NotNull = vg1NotNull;
+    }
+
+    public String getVg1NotNull() {
+        return vg1NotNull;
+    }
+
+    public void setVg2NotNull(String vg2NotNull) {
+        this.vg2NotNull = vg2NotNull;
+    }
+
+    public String getVg2NotNull() {
+        return vg2NotNull;
+    }
+
+    public void setVg12NotNull(String vg12NotNull) {
+        this.vg12NotNull = vg12NotNull;
+    }
+
+    public String getVg12NotNull() {
+        return vg12NotNull;
+    }
+}

Propchange: openjpa/trunk/openjpa-integration/validation/src/test/java/org/apache/openjpa/integration/validation/MixedGrpEntity.java
------------------------------------------------------------------------------
    svn:eol-style = native

Added: openjpa/trunk/openjpa-integration/validation/src/test/java/org/apache/openjpa/integration/validation/NonDefGrpEntity.java
URL: http://svn.apache.org/viewvc/openjpa/trunk/openjpa-integration/validation/src/test/java/org/apache/openjpa/integration/validation/NonDefGrpEntity.java?rev=791678&view=auto
==============================================================================
--- openjpa/trunk/openjpa-integration/validation/src/test/java/org/apache/openjpa/integration/validation/NonDefGrpEntity.java (added)
+++ openjpa/trunk/openjpa-integration/validation/src/test/java/org/apache/openjpa/integration/validation/NonDefGrpEntity.java Tue Jul  7 02:35:08 2009
@@ -0,0 +1,65 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.    
+ */
+package org.apache.openjpa.integration.validation;
+
+import javax.persistence.Entity;
+import javax.persistence.GeneratedValue;
+import javax.persistence.Id;
+import javax.validation.constraints.NotNull;
+import org.apache.openjpa.integration.validation.ValGroup1;
+
+@Entity
+public class NonDefGrpEntity {
+
+    @Id
+    @GeneratedValue
+    private int id;
+    
+    // NotNull constraint with default validation group
+    @NotNull
+    private String dgName;
+    
+    // NotNull constraint with specified validation group
+    @NotNull(groups=ValGroup1.class)
+    private String ndgName;
+
+    public void setId(int id) {
+        this.id = id;
+    }
+
+    public int getId() {
+        return id;
+    }
+
+    public void setDgName(String dgName) {
+        this.dgName = dgName;
+    }
+
+    public String getDgName() {
+        return dgName;
+    }    
+
+    public void setNdgName(String dgName) {
+        this.ndgName = dgName;
+    }
+
+    public String getNdgName() {
+        return ndgName;
+    }    
+}

Propchange: openjpa/trunk/openjpa-integration/validation/src/test/java/org/apache/openjpa/integration/validation/NonDefGrpEntity.java
------------------------------------------------------------------------------
    svn:eol-style = native

Added: openjpa/trunk/openjpa-integration/validation/src/test/java/org/apache/openjpa/integration/validation/TestValidationGroups.java
URL: http://svn.apache.org/viewvc/openjpa/trunk/openjpa-integration/validation/src/test/java/org/apache/openjpa/integration/validation/TestValidationGroups.java?rev=791678&view=auto
==============================================================================
--- openjpa/trunk/openjpa-integration/validation/src/test/java/org/apache/openjpa/integration/validation/TestValidationGroups.java (added)
+++ openjpa/trunk/openjpa-integration/validation/src/test/java/org/apache/openjpa/integration/validation/TestValidationGroups.java Tue Jul  7 02:35:08 2009
@@ -0,0 +1,639 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.    
+ */
+package org.apache.openjpa.integration.validation;
+
+import java.util.HashMap;
+import java.util.Iterator;
+import java.util.Map;
+import java.util.Set;
+
+import javax.validation.ConstraintViolation;
+import javax.validation.ConstraintViolationException;
+
+import org.apache.openjpa.lib.log.Log;
+import org.apache.openjpa.persistence.OpenJPAEntityManager;
+import org.apache.openjpa.persistence.OpenJPAEntityManagerFactorySPI;
+import org.apache.openjpa.persistence.OpenJPAPersistence;
+import org.apache.openjpa.persistence.test.PersistenceTestCase;
+
+/**
+ * Tests the Bean Validation groups support as defined in the JPA 2.0 spec
+ * via the following scenarios:
+ *      
+ * Verify default validation group on lifecycle events:
+ * 1a) PrePersist and PreUpdate validate with default validation group
+ * 1b) PreRemove does not validate with default validation group
+ * 1c) Specify the default group for PreRemove and verify that it validates with
+ *     the default group.
+ * 1d) Verify validation for constraints using non-default validation groups 
+ *     does not occur.
+ *    
+ * Verify validation occurs when specific validation groups are specified:
+ * 2a) Specify a non-default group for all lifecycle events.
+ * 2b) Specify multiple/mixed non-default groups for lifecycle events.
+ * 
+ * Verify validation does not occur when no validation groups are specified:
+ * 3a) Specify an empty validation group for PrePersist and PreUpdate and
+ *     verify validation does not occur on these events.
+ *
+ * @version $Rev$ $Date$
+ */
+public class TestValidationGroups extends PersistenceTestCase {
+
+    /**
+     * 1a) verify validation occurs using the default validation groups
+     * on pre-persist and pre-update on commit
+     */
+    public void testDefaultValidationGroup() {
+        verifyDefaultValidationGroup(false);
+    }
+
+    /**
+     * 1af) verify validation occurs using the default validation groups
+     * on pre-persist and pre-update on flush
+     */
+    public void testDefaultValidationGroupFlush() {
+        verifyDefaultValidationGroup(true);
+    }
+    
+
+    /**
+     * 1b) verify validation does not occur using the default validation group
+     * on the PreRemove lifecycle event on commit.  
+     */
+    public void testDefaultPreRemove() {
+        verifyDefaultPreRemove(false);
+    }
+
+    /**
+     * 1bf) verify validation does not occur using the default validation group
+     * on the PreRemove lifecycle event on flush.  
+     */
+    public void testDefaultPreRemoveFlush() {
+        verifyDefaultPreRemove(true);
+    }
+    
+    /**
+	 * 1c) verify validation occurs on the default group when default is 
+	 *  specified for pre-remove on commit
+	 */
+	public void testSpecifiedDefaultPreRemove() {
+	    verifySpecifiedDefaultPreRemove(true);
+	}
+
+    /**
+     * 1cf) verify validation occurs on the default group when default is 
+     *  specified for pre-remove on flush
+     */
+    public void testSpecifiedDefaultPreRemoveFlush() {
+        verifySpecifiedDefaultPreRemove(false);
+    }
+    
+    /**
+     * 2a) verify non-default validation group for all lifecycle events on
+     * commit.  default validation group constraints should not validate
+     */
+    public void testNonDefaultValidationGroup() {
+        verifyNonDefaultValidationGroup(false);
+    }
+
+    /**
+     * 2af) verify non-default validation group for all lifecycle events on
+     * flush.  default validation group constraints should not validate
+     */
+    public void testNonDefaultValidationGroupFlush() {
+        verifyNonDefaultValidationGroup(true);
+    }
+    
+    /**
+     * 2b) verify multiple/mixed validation groups
+     * @param flush
+     */
+    public void testMultipleValidationGroups() {
+
+        // Configure persistence properties via map
+        Map<String, Object> propMap = new HashMap<String, Object>();
+        propMap.put("javax.persistence.validation.group.pre-persist",
+            "org.apache.openjpa.integration.validation.ValGroup1," +
+            "org.apache.openjpa.integration.validation.ValGroup2");
+
+        propMap.put("javax.persistence.validation.group.pre-update",
+            "");
+
+        propMap.put("javax.persistence.validation.group.pre-remove",
+            "org.apache.openjpa.integration.validation.ValGroup2");
+
+        OpenJPAEntityManagerFactorySPI emf = (OpenJPAEntityManagerFactorySPI) 
+        OpenJPAPersistence.createEntityManagerFactory(
+                "multi-validation-group",
+                "org/apache/openjpa/integration/validation/persistence.xml",
+                propMap);
+        assertNotNull(emf);
+        // create EM
+        OpenJPAEntityManager em = emf.createEntityManager();
+        assertNotNull(em);
+
+        try {
+            MixedGrpEntity mge = new MixedGrpEntity();
+            
+            // Assert vg1 and vg2 fire on pre-persist
+            try
+            {
+                em.getTransaction().begin();
+                em.persist(mge);
+                em.getTransaction().commit();
+            } catch (ConstraintViolationException e) {
+                checkCVE(e, 
+                    "vg1NotNull",
+                    "vg2NotNull",
+                    "vg12NotNull");
+            }
+            catch (Exception e) {
+                fail("Should have caught a ConstraintViolationException");
+            }
+            finally {
+                if (em.getTransaction().isActive()) {
+                    em.getTransaction().rollback();
+                }
+            }            
+            // Assert no validation occurs on pre-update
+            // Persist an entity.  Default should not validate on pre-persist
+            em.getTransaction().begin();
+            mge.setVg1NotNull("Vg1");
+            mge.setVg2NotNull("Vg2");
+            mge.setVg12NotNull("Vg1&2");
+            em.persist(mge);
+            em.getTransaction().commit();
+
+            
+            try {
+                em.getTransaction().begin();
+                mge.setDefNotNull(null);
+                mge.setVg12NotNull(null);
+                mge.setVg1NotNull(null);
+                mge.setVg2NotNull(null);
+                em.getTransaction().commit(); 
+            } catch (ConstraintViolationException e) {
+                fail("Update should have been successful." +
+                     " Caught unexpected ConstraintViolationException.");
+            }
+            catch (Exception e) {
+                fail("Update should have been successful." +
+                     " Caught unexpected exception.");
+            }
+            
+            // Update the entity again so that it can be cleaned up by the
+            // emf cleanup facility.  The update should not validate
+            em.getTransaction().begin();
+            mge.setVg2NotNull("Vg2NotNull");
+            mge.setVg12NotNull("Vg12NotNull");
+            em.getTransaction().commit();   
+
+            // Assert vg2 and default groups validate on pre-remove
+            try {
+                em.getTransaction().begin();
+                mge.setDefNotNull(null);
+                mge.setVg1NotNull(null);
+                mge.setVg2NotNull(null);
+                mge.setVg12NotNull(null);
+                em.remove(mge);
+                em.getTransaction().commit();                
+            } catch (ConstraintViolationException e) {
+                checkCVE(e, 
+                    "vg2NotNull",
+                    "vg12NotNull");
+            }
+            catch (Exception e) {
+                fail("Should have caught a ConstraintViolationException");
+            }
+            finally {
+                if (em.getTransaction().isActive()) {
+                    em.getTransaction().rollback();
+                }
+            }
+            
+        }
+        finally {
+            cleanup(emf);
+        }        
+    }
+
+    /**
+     * 3a) No validation groups for pre-persist and pre-update and none for
+     * pre-remove by default.  No validation should occur.
+     */
+    public void testNoValidationGroups() {
+
+        // Configure persistence properties via map
+        Map<String, Object> propMap = new HashMap<String, Object>();
+        propMap.put("javax.persistence.validation.group.pre-persist","");
+
+        propMap.put("javax.persistence.validation.group.pre-update","");
+
+        OpenJPAEntityManagerFactorySPI emf = (OpenJPAEntityManagerFactorySPI) 
+        OpenJPAPersistence.createEntityManagerFactory(
+                "multi-validation-group",
+                "org/apache/openjpa/integration/validation/persistence.xml",
+                propMap);
+        assertNotNull(emf);
+        // create EM
+        OpenJPAEntityManager em = emf.createEntityManager();
+        assertNotNull(em);
+
+        try {
+            MixedGrpEntity mge = new MixedGrpEntity();
+            
+            try
+            {
+                // No validation on pre-persist
+                em.getTransaction().begin();
+                em.persist(mge);
+                em.getTransaction().commit();                
+                
+                // No validation on pre-update
+                em.getTransaction().begin();
+                mge.setVg12NotNull(null);
+                em.getTransaction().commit();
+
+                // No validation on pre-remove
+                em.getTransaction().begin();
+                em.remove(mge);
+                em.getTransaction().commit();
+            } catch (ConstraintViolationException e) {
+                fail("Operations should have been successful." +
+                     " Caught unexpected ConstraintViolationException.");
+            }
+            catch (Exception e) {
+                fail("Operations should have been successful." +
+                     " Caught unexpected exception.");
+            }            
+        }
+        finally {
+            cleanup(emf);
+        }        
+    }
+
+    private void verifyDefaultValidationGroup(boolean flush) {
+        OpenJPAEntityManagerFactorySPI emf = (OpenJPAEntityManagerFactorySPI) 
+        OpenJPAPersistence.createEntityManagerFactory(
+                "default-validation-group",
+                "org/apache/openjpa/integration/validation/persistence.xml");
+        assertNotNull(emf);
+        // create EM
+        OpenJPAEntityManager em = emf.createEntityManager();
+        assertNotNull(em);
+        try {
+            DefGrpEntity dge = new DefGrpEntity();
+            // Test pre-persist with default group with flush after persist
+            // 1a) pre-persist
+            try {
+                em.getTransaction().begin();
+                em.persist(dge);
+                if (flush)
+                    em.flush();
+                else
+                    em.getTransaction().commit();
+                fail("A ConstraintViolationException should have been thrown " +
+                    "on pre-persist");
+            } catch (ConstraintViolationException e) {
+                checkCVE(e, "dgName");
+                // If flushing, tx should be marked for rollback
+                if (flush) {
+                    assertTrue(em.getTransaction().isActive());
+                    assertTrue(em.getTransaction().getRollbackOnly());
+                }
+            }
+            catch (Exception e) {
+                fail("Should have caught a ConstraintViolationException");
+            }
+            finally {
+                if (em.getTransaction().isActive()) {
+                    em.getTransaction().rollback();
+                }
+            }
+
+            // 1a) test pre-update with default group
+            // Add an entity with valid data (validation passes)
+            dge.setDgName("NonNullName");
+            em.getTransaction().begin();
+            em.persist(dge);
+            em.getTransaction().commit();
+            try {
+                // Update the entity with null value.  pre-update 
+                // validation should fail on flush or commit
+                em.getTransaction().begin();
+                dge.setDgName(null);
+                if (flush)
+                    em.flush();
+                else
+                    em.getTransaction().commit();
+                fail("A ConstraintViolationException should have been thrown " +
+                    "on pre-update");
+            } catch (ConstraintViolationException e) {
+                checkCVE(e, "dgName");
+                // If flushing, tx should be marked for rollback
+                if (flush) {
+                    assertTrue(em.getTransaction().isActive());
+                    assertTrue(em.getTransaction().getRollbackOnly());
+                }
+            }
+            catch (Exception e) {
+                fail("Should have caught a ConstraintViolationException");
+            }
+            finally {
+                if (em.getTransaction().isActive()) {
+                    em.getTransaction().rollback();
+                }
+            }
+        }
+        finally {
+            cleanup(emf);
+        }
+    }
+
+    private void verifyNonDefaultValidationGroup(boolean flush) {
+        OpenJPAEntityManagerFactorySPI emf = (OpenJPAEntityManagerFactorySPI) 
+        OpenJPAPersistence.createEntityManagerFactory(
+                "non-default-validation-group",
+                "org/apache/openjpa/integration/validation/persistence.xml");
+        assertNotNull(emf);
+        // create EM
+        OpenJPAEntityManager em = emf.createEntityManager();
+        assertNotNull(em);
+        try {
+            NonDefGrpEntity ndge = new NonDefGrpEntity();
+            // Test pre-persist with non-default group with flush after persist
+            try {
+                em.getTransaction().begin();
+                em.persist(ndge);
+                if (flush)
+                    em.flush();
+                else
+                    em.getTransaction().commit();
+                fail("A ConstraintViolationException should have been thrown " +
+                    "on pre-persist");
+            } catch (ConstraintViolationException e) {
+                checkCVE(e, "ndgName");
+                getLog(emf).trace("Caught expected exception");
+                // If flushing, tx should be marked for rollback
+                if (flush) {
+                    assertTrue(em.getTransaction().isActive());
+                    assertTrue(em.getTransaction().getRollbackOnly());
+                }
+            }
+            catch (Exception e) {
+                fail("Should have caught a ConstraintViolationException");
+            }
+            finally {
+                if (em.getTransaction().isActive()) {
+                    em.getTransaction().rollback();
+                }
+            }
+
+            // pre-update with non-default group.  default group
+            // validation should not occur
+            // Add an entity with valid data (validation passes)
+            try {
+                ndge.setNdgName("NonNullName");
+                ndge.setDgName(null);
+                em.getTransaction().begin();
+                em.persist(ndge);
+                em.getTransaction().commit();
+                getLog(emf).trace("Entity was persisted. As expected, no " +
+                "validation took place on pre-persist with default group.");
+            }
+            catch (ConstraintViolationException e) {
+                fail("Caught unexpected exception");
+                if (em.getTransaction().isActive())
+                    em.getTransaction().rollback();
+            }                
+            try {
+                // Update the entity with null value.  pre-update 
+                // validation should fail on flush or commit
+                
+                em.getTransaction().begin();
+                ndge.setNdgName(null);
+                if (flush)
+                    em.flush();
+                else
+                    em.getTransaction().commit();
+                fail("A ConstraintViolationException should have been thrown " +
+                    "on pre-update");
+            } catch (ConstraintViolationException e) {
+                checkCVE(e, "ndgName");
+                // If flushing, tx should be marked for rollback
+                if (flush) {
+                    assertTrue(em.getTransaction().isActive());
+                    assertTrue(em.getTransaction().getRollbackOnly());
+                }
+            }
+            catch (Exception e) {
+                fail("Should have caught a ConstraintViolationException");
+            }
+            finally {
+                if (em.getTransaction().isActive()) {
+                    em.getTransaction().rollback();
+                }
+            }
+
+            // Merge the entity so that it can be removed.
+            em.getTransaction().begin();
+            ndge.setDgName(null);
+            ndge.setNdgName("Some name");
+            ndge = em.merge(ndge);
+            em.getTransaction().commit();
+            
+            try {
+                // Update the entity with null value and remove the entity.  
+                // validation should not fail on pre-remove
+                em.getTransaction().begin();
+                ndge.setNdgName(null);
+                em.remove(ndge);
+                if (flush)
+                    em.flush();
+                else
+                    em.getTransaction().commit();
+                fail("A ConstraintViolationException should have been thrown " +
+                    "on pre-remove");
+            } catch (ConstraintViolationException e) {
+                checkCVE(e, "ndgName");
+                // If flushing, tx should be marked for rollback
+                if (flush) {
+                    assertTrue(em.getTransaction().isActive());
+                    assertTrue(em.getTransaction().getRollbackOnly());
+                }
+            }
+            catch (Exception e) {
+                fail("Should have caught a ConstraintViolationException");
+            }
+
+        }
+        finally {
+            cleanup(emf);
+        }
+    }
+
+    /**
+     * verify validation does not occur using the default validation group
+     * on the PreRemove lifecycle event.  
+     */
+    public void verifyDefaultPreRemove(boolean flush) {
+        OpenJPAEntityManagerFactorySPI emf = (OpenJPAEntityManagerFactorySPI) 
+        OpenJPAPersistence.createEntityManagerFactory(
+                "default-validation-group",
+                "org/apache/openjpa/integration/validation/persistence.xml");
+        assertNotNull(emf);
+        // create EM
+        OpenJPAEntityManager em = emf.createEntityManager();
+        assertNotNull(em);
+
+        try {
+            // Add an entity 
+            DefGrpEntity dge = new DefGrpEntity();
+            dge.setDgName("NonNullName");
+            em.getTransaction().begin();
+            em.persist(dge);
+            em.getTransaction().commit();
+            try {
+                // Update the entity with null value and remove the entity.  
+                // validation should not fail on pre-remove
+                em.getTransaction().begin();
+                dge.setDgName(null);
+                em.remove(dge);
+                if (flush)
+                    em.flush();
+                else
+                    em.getTransaction().commit();
+                getLog(emf).trace("Entity was removed. As expected, no " +
+                    "validation took place on pre-remove.");
+            } catch (ConstraintViolationException e) {
+                fail("Should not have caught a ConstraintViolationException");
+                getLog(emf).trace("Caught expected exception");
+            }
+            catch (Exception e) {
+                fail("Should not have caught an Exception");
+            }
+            finally {
+                if (em.getTransaction().isActive()) {
+                    em.getTransaction().rollback();
+                }
+            }
+        }
+        finally {
+            cleanup(emf);
+        }
+    }
+
+    /**
+     * verify validation occurs when the default validation group
+     * is specified for the PreRemove lifecycle event via the 
+     * "javax.persistence.validation.group.pre-remove" property.
+     */
+    public void verifySpecifiedDefaultPreRemove(boolean flush) {
+        OpenJPAEntityManagerFactorySPI emf = (OpenJPAEntityManagerFactorySPI) 
+        OpenJPAPersistence.createEntityManagerFactory(
+                "pre-remove-default-validation-group",
+                "org/apache/openjpa/integration/validation/persistence.xml");
+        assertNotNull(emf);
+        // create EM
+        OpenJPAEntityManager em = emf.createEntityManager();
+        assertNotNull(em);
+
+        try {
+            // Add an entity 
+            DefGrpEntity dge = new DefGrpEntity();
+            dge.setDgName("NonNullName");
+            em.getTransaction().begin();
+            em.persist(dge);
+            em.getTransaction().commit();
+            try {
+                // Update the entity with null value and remove the entity.  
+                // validation should not fail on pre-remove
+                em.getTransaction().begin();
+                dge.setDgName(null);
+                em.remove(dge);
+                if (flush)
+                    em.flush();
+                else
+                    em.getTransaction().commit();
+                fail("A ConstraintViolationException should have been thrown " +
+                    "on pre-remove");
+            } catch (ConstraintViolationException e) {
+                checkCVE(e, "dgName");
+                // If flushing, tx should be marked for rollback
+                if (flush) {
+                    assertTrue(em.getTransaction().isActive());
+                    assertTrue(em.getTransaction().getRollbackOnly());
+                }
+            }
+            catch (Exception e) {
+                fail("Should have caught a ConstraintViolationException");
+            }
+            finally {
+                if (em.getTransaction().isActive()) {
+                    em.getTransaction().rollback();
+                }
+            }
+        }
+        finally {
+            cleanup(emf);
+        }
+    }
+
+    private void checkCVE(ConstraintViolationException e,
+        String... vioProperties) {
+        Set<?>cvs = e.getConstraintViolations();
+        if (vioProperties.length == 0 && cvs == null)
+            return;
+        assertEquals(vioProperties.length, cvs.size());
+        Iterator<ConstraintViolation<?>> i = 
+            (Iterator<ConstraintViolation<?>>) cvs.iterator();
+        while (i.hasNext()) {
+            ConstraintViolation<?> v = (ConstraintViolation<?>)i.next();
+            boolean found = false;
+            for (String vio : vioProperties) {
+                if (v.getPropertyPath().equals(vio)) {
+                    found = true;
+                    break;
+                }
+            }
+            if (!found)
+                fail("Unexpected ConstraintViolation for: " + 
+                    v.getPropertyPath());
+        }
+    }
+
+    /**
+     * Remove entities and close the emf an any open em's.
+     * @param emf
+     */
+    private void cleanup(OpenJPAEntityManagerFactorySPI emf) {
+        clear(emf);
+        closeEMF(emf);
+    }
+    
+    /**
+     * Internal convenience method for getting the OpenJPA logger
+     * 
+     * @return
+     */
+    private Log getLog(OpenJPAEntityManagerFactorySPI emf) {
+        return emf.getConfiguration().getLog("Tests");
+    }
+}

Propchange: openjpa/trunk/openjpa-integration/validation/src/test/java/org/apache/openjpa/integration/validation/TestValidationGroups.java
------------------------------------------------------------------------------
    svn:eol-style = native

Added: openjpa/trunk/openjpa-integration/validation/src/test/java/org/apache/openjpa/integration/validation/ValGroup1.java
URL: http://svn.apache.org/viewvc/openjpa/trunk/openjpa-integration/validation/src/test/java/org/apache/openjpa/integration/validation/ValGroup1.java?rev=791678&view=auto
==============================================================================
--- openjpa/trunk/openjpa-integration/validation/src/test/java/org/apache/openjpa/integration/validation/ValGroup1.java (added)
+++ openjpa/trunk/openjpa-integration/validation/src/test/java/org/apache/openjpa/integration/validation/ValGroup1.java Tue Jul  7 02:35:08 2009
@@ -0,0 +1,22 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.    
+ */
+package org.apache.openjpa.integration.validation;
+
+public interface ValGroup1 {
+}

Propchange: openjpa/trunk/openjpa-integration/validation/src/test/java/org/apache/openjpa/integration/validation/ValGroup1.java
------------------------------------------------------------------------------
    svn:eol-style = native

Added: openjpa/trunk/openjpa-integration/validation/src/test/java/org/apache/openjpa/integration/validation/ValGroup2.java
URL: http://svn.apache.org/viewvc/openjpa/trunk/openjpa-integration/validation/src/test/java/org/apache/openjpa/integration/validation/ValGroup2.java?rev=791678&view=auto
==============================================================================
--- openjpa/trunk/openjpa-integration/validation/src/test/java/org/apache/openjpa/integration/validation/ValGroup2.java (added)
+++ openjpa/trunk/openjpa-integration/validation/src/test/java/org/apache/openjpa/integration/validation/ValGroup2.java Tue Jul  7 02:35:08 2009
@@ -0,0 +1,22 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.    
+ */
+package org.apache.openjpa.integration.validation;
+
+public interface ValGroup2 {
+}

Propchange: openjpa/trunk/openjpa-integration/validation/src/test/java/org/apache/openjpa/integration/validation/ValGroup2.java
------------------------------------------------------------------------------
    svn:eol-style = native

Modified: openjpa/trunk/openjpa-integration/validation/src/test/resources/org/apache/openjpa/integration/validation/persistence.xml
URL: http://svn.apache.org/viewvc/openjpa/trunk/openjpa-integration/validation/src/test/resources/org/apache/openjpa/integration/validation/persistence.xml?rev=791678&r1=791677&r2=791678&view=diff
==============================================================================
--- openjpa/trunk/openjpa-integration/validation/src/test/resources/org/apache/openjpa/integration/validation/persistence.xml (original)
+++ openjpa/trunk/openjpa-integration/validation/src/test/resources/org/apache/openjpa/integration/validation/persistence.xml Tue Jul  7 02:35:08 2009
@@ -69,5 +69,50 @@
     	<class>org.apache.openjpa.integration.validation.ConstraintNull</class>
         <validation-mode>CALLBACK</validation-mode>
     </persistence-unit>
+
+    <persistence-unit name="default-validation-group">
+        <class>org.apache.openjpa.integration.validation.DefGrpEntity</class>
+        <validation-mode>CALLBACK</validation-mode>
+        <properties>
+            <property name="openjpa.jdbc.SynchronizeMappings" 
+                value="buildSchema"/>
+        </properties>        
+    </persistence-unit>
+    
+    <persistence-unit name="pre-remove-default-validation-group">
+        <class>org.apache.openjpa.integration.validation.DefGrpEntity</class>
+        <validation-mode>CALLBACK</validation-mode>
+        <properties>
+            <property name="openjpa.jdbc.SynchronizeMappings" 
+                value="buildSchema"/>
+            <property name="javax.persistence.validation.group.pre-remove"
+                value="javax.validation.groups.Default"/>
+        </properties>        
+    </persistence-unit>
+
+    <persistence-unit name="non-default-validation-group">
+        <class>org.apache.openjpa.integration.validation.NonDefGrpEntity</class>
+        <validation-mode>CALLBACK</validation-mode>
+        <properties>
+            <property name="openjpa.jdbc.SynchronizeMappings" 
+                value="buildSchema"/>
+            <property name="javax.persistence.validation.group.pre-persist"
+                value="org.apache.openjpa.integration.validation.ValGroup1"/>
+            <property name="javax.persistence.validation.group.pre-update"
+                value="org.apache.openjpa.integration.validation.ValGroup1"/>
+            <property name="javax.persistence.validation.group.pre-remove"
+                value="org.apache.openjpa.integration.validation.ValGroup1"/>
+        </properties>
+    </persistence-unit>
+
+    <persistence-unit name="multi-validation-group">
+        <class>org.apache.openjpa.integration.validation.MixedGrpEntity</class>
+        <validation-mode>CALLBACK</validation-mode>
+        <properties>
+            <property name="openjpa.jdbc.SynchronizeMappings" 
+                value="buildSchema"/>
+            <!-- Properties passed in via createEMF -->
+        </properties>
+    </persistence-unit>
     
 </persistence>

Modified: openjpa/trunk/openjpa-kernel/src/main/java/org/apache/openjpa/conf/OpenJPAConfiguration.java
URL: http://svn.apache.org/viewvc/openjpa/trunk/openjpa-kernel/src/main/java/org/apache/openjpa/conf/OpenJPAConfiguration.java?rev=791678&r1=791677&r2=791678&view=diff
==============================================================================
--- openjpa/trunk/openjpa-kernel/src/main/java/org/apache/openjpa/conf/OpenJPAConfiguration.java (original)
+++ openjpa/trunk/openjpa-kernel/src/main/java/org/apache/openjpa/conf/OpenJPAConfiguration.java Tue Jul  7 02:35:08 2009
@@ -1773,4 +1773,46 @@
      * @since 2.0.0
      */
     public void setWriteBehindCallback(String wbcallback);
+
+    /**
+     * Gets the validation groups for pre-persist
+     * 
+     * @Since 2.0.0
+     */
+    public String getValidationGroupPrePersist();
+
+    /**
+     * Sets the validation groups for pre-persist
+     * 
+     * @Since 2.0.0
+     */
+    public void setValidationGroupPrePersist(String vgPrePersist);
+
+    /**
+     * Gets the validation groups for pre-update
+     * 
+     * @Since 2.0.0
+     */
+    public String getValidationGroupPreUpdate();
+
+    /**
+     * Sets the validation groups for pre-update
+     * 
+     * @Since 2.0.0
+     */
+    public void setValidationGroupPreUpdate(String vgPreUpdate);
+
+    /**
+     * Gets the validation groups for pre-remove
+     * 
+     * @Since 2.0.0
+     */
+    public String getValidationGroupPreRemove();
+
+    /**
+     * Sets the validation groups for pre-remove
+     * 
+     * @Since 2.0.0
+     */
+    public void setValidationGroupPreRemove(String vgPreRemove);
 }

Modified: openjpa/trunk/openjpa-kernel/src/main/java/org/apache/openjpa/conf/OpenJPAConfigurationImpl.java
URL: http://svn.apache.org/viewvc/openjpa/trunk/openjpa-kernel/src/main/java/org/apache/openjpa/conf/OpenJPAConfigurationImpl.java?rev=791678&r1=791677&r2=791678&view=diff
==============================================================================
--- openjpa/trunk/openjpa-kernel/src/main/java/org/apache/openjpa/conf/OpenJPAConfigurationImpl.java (original)
+++ openjpa/trunk/openjpa-kernel/src/main/java/org/apache/openjpa/conf/OpenJPAConfigurationImpl.java Tue Jul  7 02:35:08 2009
@@ -164,7 +164,9 @@
     public ObjectValue validationFactory;
     public ObjectValue validator;
     public ObjectValue lifecycleEventManager;
-
+    public StringValue validationGroupPrePersist;
+    public StringValue validationGroupPreUpdate;
+    public StringValue validationGroupPreRemove;
     public ObjectValue writeBehindCachePlugin;
     public ObjectValue writeBehindCacheManagerPlugin;
     public ObjectValue writeBehindCallbackPlugin;
@@ -574,6 +576,24 @@
         validationMode = addString("javax.persistence.validation.mode");
         validationMode.setDynamic(true);
 
+        String defValidationGroup = "javax.validation.groups.Default";
+        validationGroupPrePersist = 
+            addString("javax.persistence.validation.group.pre-persist");
+        validationGroupPrePersist.setString(defValidationGroup);
+        validationGroupPrePersist.setDefault("");
+        validationGroupPrePersist.setDynamic(true);
+
+        validationGroupPreUpdate = 
+            addString("javax.persistence.validation.group.pre-update");
+        validationGroupPreUpdate.setString(defValidationGroup);
+        validationGroupPreUpdate.setDefault("");
+        validationGroupPreUpdate.setDynamic(true);
+
+        validationGroupPreRemove = 
+            addString("javax.persistence.validation.group.pre-remove");
+        validationGroupPreRemove.setDefault("");
+        validationGroupPreRemove.setDynamic(true);
+
         validationFactory = addObject("javax.persistence.validation.factory");
         validationFactory.setInstantiatingGetter(
             "getValidationFactoryInstance");
@@ -1592,6 +1612,39 @@
         return mode;
     }
 
+    public void setValidationGroupPrePersist(String vgPrePersist) {
+        validationGroupPrePersist.setString(vgPrePersist);
+    }
+
+    public String getValidationGroupPrePersist() {
+        String vgPrePersist = validationGroupPrePersist.getString();
+        if (vgPrePersist == null)
+            vgPrePersist = validationGroupPrePersist.getDefault();
+        return vgPrePersist;
+    }
+
+    public void setValidationGroupPreUpdate(String vgPreUpdate) {
+        validationGroupPreUpdate.setString(vgPreUpdate);
+    }
+
+    public String getValidationGroupPreUpdate() {
+        String vgPreUpdate = validationGroupPreUpdate.getString();
+        if (vgPreUpdate == null)
+            vgPreUpdate = validationGroupPreUpdate.getDefault();
+        return vgPreUpdate;
+    }
+
+    public void setValidationGroupPreRemove(String vgPreRemove) {
+        validationGroupPreRemove.setString(vgPreRemove);
+    }
+
+    public String getValidationGroupPreRemove() {
+        String vgPreRemove = validationGroupPreRemove.getString();
+        if (vgPreRemove == null)
+            vgPreRemove = validationGroupPreRemove.getDefault();
+        return vgPreRemove;
+    }
+
     public void instantiateAll() {
         super.instantiateAll();
         getMetaDataRepositoryInstance();

Modified: openjpa/trunk/openjpa-persistence/src/main/java/org/apache/openjpa/persistence/validation/ValidationUtils.java
URL: http://svn.apache.org/viewvc/openjpa/trunk/openjpa-persistence/src/main/java/org/apache/openjpa/persistence/validation/ValidationUtils.java?rev=791678&r1=791677&r2=791678&view=diff
==============================================================================
--- openjpa/trunk/openjpa-persistence/src/main/java/org/apache/openjpa/persistence/validation/ValidationUtils.java (original)
+++ openjpa/trunk/openjpa-persistence/src/main/java/org/apache/openjpa/persistence/validation/ValidationUtils.java Tue Jul  7 02:35:08 2009
@@ -97,9 +97,7 @@
             // we have the javax.validation APIs
             try {
                 // try loading a validation provider
-                ValidatorImpl validator = new ValidatorImpl(
-                    conf.getValidationFactoryInstance(),
-                    conf.getValidationMode());
+                ValidatorImpl validator = new ValidatorImpl(conf);
                 // set the Validator into the config
                 conf.setValidatorInstance(validator);
                 // update the LifecycleEventManager plugin to use it

Modified: openjpa/trunk/openjpa-persistence/src/main/java/org/apache/openjpa/persistence/validation/ValidatorImpl.java
URL: http://svn.apache.org/viewvc/openjpa/trunk/openjpa-persistence/src/main/java/org/apache/openjpa/persistence/validation/ValidatorImpl.java?rev=791678&r1=791677&r2=791678&view=diff
==============================================================================
--- openjpa/trunk/openjpa-persistence/src/main/java/org/apache/openjpa/persistence/validation/ValidatorImpl.java (original)
+++ openjpa/trunk/openjpa-persistence/src/main/java/org/apache/openjpa/persistence/validation/ValidatorImpl.java Tue Jul  7 02:35:08 2009
@@ -30,7 +30,9 @@
 import javax.validation.Validator;
 import javax.validation.ValidatorFactory;
 
+import org.apache.openjpa.conf.OpenJPAConfiguration;
 import org.apache.openjpa.event.LifecycleEvent;
+import org.apache.openjpa.lib.conf.Configuration;
 import org.apache.openjpa.lib.util.Localizer;
 import org.apache.openjpa.validation.AbstractValidator;
 import org.apache.openjpa.validation.ValidationException;
@@ -43,6 +45,8 @@
     private ValidatorFactory _validatorFactory = null;
     private Validator _validator = null;
     private ValidationMode _mode = ValidationMode.AUTO;
+    private OpenJPAConfiguration _conf = null;
+
     
     // A map storing the validation groups to use for a particular event type
     private Map<Integer, Class<?>[]> _validationGroups = 
@@ -61,7 +65,7 @@
     
     static {
         _vgMapping.put(VG_PRE_PERSIST,
-            LifecycleEvent.BEFORE_STORE);
+            LifecycleEvent.BEFORE_PERSIST);
         _vgMapping.put(VG_PRE_REMOVE,
             LifecycleEvent.BEFORE_DELETE);
         _vgMapping.put(VG_PRE_UPDATE,
@@ -77,6 +81,25 @@
         initialize();
     }
     
+    public ValidatorImpl(Configuration conf) {
+        if (conf instanceof OpenJPAConfiguration) {
+            _conf = (OpenJPAConfiguration)conf;
+            Object validatorFactory = _conf.getValidationFactoryInstance();
+            String mode = _conf.getValidationMode();
+            _mode = Enum.valueOf(ValidationMode.class, mode);
+            if (validatorFactory != null) {
+                if (validatorFactory instanceof ValidatorFactory) {
+                    _validatorFactory = (ValidatorFactory)validatorFactory;
+                } else {
+                    // Supplied object was not an instance of a ValidatorFactory
+                    throw new IllegalArgumentException(
+                        _loc.get("invalid-factory").getMessage());                
+                }
+            }
+        }
+        initialize();
+    }
+    
     /**
      * Type-specific constructor
      * Returns an Exception if a Validator could not be created.
@@ -96,27 +119,6 @@
     }
 
     /**
-     * Generic-type constructor 
-     * Returns an Exception if a Validator could not be created.
-     * @param validatorFactory an instance to the validatorFactory
-     * @param mode validation mode enum as string value
-     */    
-    public ValidatorImpl(Object validatorFactory,
-        String mode) {        
-        _mode = Enum.valueOf(ValidationMode.class, mode);
-        if (validatorFactory != null) {
-            if (validatorFactory instanceof ValidatorFactory) {
-                _validatorFactory = (ValidatorFactory)validatorFactory;
-            } else {
-                // Supplied object was not an instance of a ValidatorFactory.
-                throw new IllegalArgumentException(
-                    _loc.get("invalid-factory").getMessage());                
-            }
-        }
-        initialize();
-    }
-
-    /**
      * Common setup code factored out of the constructors
      */
     private void initialize() {
@@ -140,8 +142,19 @@
                     _loc.get("no-validator").getMessage());
             }
 
-            // add in default validation groups, which can be over-ridden later
-            addDefaultValidationGroups();
+            if (_conf != null) {
+                addValidationGroup(VG_PRE_PERSIST,
+                    _conf.getValidationGroupPrePersist());
+                addValidationGroup(VG_PRE_UPDATE,
+                    _conf.getValidationGroupPreUpdate());
+                addValidationGroup(VG_PRE_REMOVE,
+                    _conf.getValidationGroupPreRemove());        
+
+            }
+            else {
+                // add in default validation groups, which can be over-ridden later
+                addDefaultValidationGroups();
+            }
         } else {
             // A Validator should not be created based on the supplied ValidationMode.
             throw new RuntimeException(
@@ -182,6 +195,54 @@
     }
     
     /**
+     * Add the validation group(s) for the specified event.  Event definitions
+     * are defined in LifecycleEvent
+     * @param event
+     * @param group
+     */
+    public void addValidationGroup(String validationGroupName, String group) {
+        Integer event = findEvent(validationGroupName);
+        if (event != null) {
+            Class<?>[] vgs = getValidationGroup(validationGroupName, group);
+            if (vgs != null) {
+                addValidationGroup(event, vgs);
+            }
+        }
+        else {
+            // There were no events found for group "{0}".
+            throw new IllegalArgumentException(
+                _loc.get("no-group-events", validationGroupName).getMessage());
+        }
+    }
+
+    /**
+     * Converts a comma separated list of validation groups into an array
+     * of classes.
+     * @param group
+     * @return
+     */
+    private Class<?>[] getValidationGroup(String vgName, String group) {
+        Class<?>[] vgGrp = null;
+        if (group == null || group.trim().length() == 0) {
+            return null;
+        }
+        String[] strClasses = group.split(",");
+        if (strClasses.length > 0) {
+            vgGrp = new Class<?>[strClasses.length];
+            for (int i = 0; i < strClasses.length; i++) {
+                try {
+                    vgGrp[i] =  Class.forName(strClasses[i]);
+                } catch (Throwable t) {
+                    throw new IllegalArgumentException(
+                        _loc.get("invalid-validation-group", strClasses[i], 
+                            vgName).getMessage(), t);
+                }
+            }            
+        }
+        return vgGrp;
+    }
+
+    /**
      * Return the validation groups to be validated for a specified event
      * @param event Lifecycle event id
      * @return An array of validation groups

Modified: openjpa/trunk/openjpa-persistence/src/main/resources/org/apache/openjpa/persistence/validation/localizer.properties
URL: http://svn.apache.org/viewvc/openjpa/trunk/openjpa-persistence/src/main/resources/org/apache/openjpa/persistence/validation/localizer.properties?rev=791678&r1=791677&r2=791678&view=diff
==============================================================================
--- openjpa/trunk/openjpa-persistence/src/main/resources/org/apache/openjpa/persistence/validation/localizer.properties (original)
+++ openjpa/trunk/openjpa-persistence/src/main/resources/org/apache/openjpa/persistence/validation/localizer.properties Tue Jul  7 02:35:08 2009
@@ -34,4 +34,5 @@
     property "{1}" in class "{0}".
 validate-value-failed: A validation constraint failure occurred for \
     value "{2}" of property "{1}" in class "{0}".
-
+invalid-validation-group: The class "{0}" specified in the validation group \
+	property "{1}" is not valid or could not be loaded.