[hibernate-commits] Hibernate SVN: r16952 - beanvalidation/trunk/validation-tck/src/main/java/org/hibernate/jsr303/tck/tests/constraints/groups/defaultgroupsequence and 4 other directories.

hibernate-commits at lists.jboss.org hibernate-commits at lists.jboss.org
Thu Jun 25 11:43:43 EDT 2009


Author: hardy.ferentschik
Date: 2009-06-25 11:43:42 -0400 (Thu, 25 Jun 2009)
New Revision: 16952

Added:
   beanvalidation/trunk/validation-tck/src/main/java/org/hibernate/jsr303/tck/tests/constraints/groups/defaultgroupsequence/
   beanvalidation/trunk/validation-tck/src/main/java/org/hibernate/jsr303/tck/tests/constraints/groups/defaultgroupsequence/SequenceResolutionTest.java
   beanvalidation/trunk/validation-tck/src/main/java/org/hibernate/jsr303/tck/tests/constraints/groups/defaultgroupsequence/TestEntity.java
   validator/trunk/hibernate-validator/src/test/java/org/hibernate/validation/engine/groups/GroupChainTest.java
Modified:
   validator/trunk/hibernate-validator/src/main/java/org/hibernate/validation/engine/ValidatorImpl.java
   validator/trunk/hibernate-validator/src/main/java/org/hibernate/validation/engine/groups/Group.java
   validator/trunk/hibernate-validator/src/main/java/org/hibernate/validation/engine/groups/GroupChain.java
   validator/trunk/hibernate-validator/src/main/java/org/hibernate/validation/engine/groups/GroupChainGenerator.java
   validator/trunk/hibernate-validator/src/main/java/org/hibernate/validation/metadata/BeanMetaData.java
   validator/trunk/hibernate-validator/src/main/java/org/hibernate/validation/metadata/BeanMetaDataImpl.java
Log:
HV-170 - Refactor the group sequence expansion and take the default sequence expansion of the validated entity into considertation


Added: beanvalidation/trunk/validation-tck/src/main/java/org/hibernate/jsr303/tck/tests/constraints/groups/defaultgroupsequence/SequenceResolutionTest.java
===================================================================
--- beanvalidation/trunk/validation-tck/src/main/java/org/hibernate/jsr303/tck/tests/constraints/groups/defaultgroupsequence/SequenceResolutionTest.java	                        (rev 0)
+++ beanvalidation/trunk/validation-tck/src/main/java/org/hibernate/jsr303/tck/tests/constraints/groups/defaultgroupsequence/SequenceResolutionTest.java	2009-06-25 15:43:42 UTC (rev 16952)
@@ -0,0 +1,44 @@
+// $Id:$
+/*
+* JBoss, Home of Professional Open Source
+* Copyright 2008, Red Hat Middleware LLC, and individual contributors
+* by the @authors tag. See the copyright.txt in the distribution for a
+* full listing of individual contributors.
+*
+* Licensed 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.hibernate.jsr303.tck.tests.constraints.groups.defaultgroupsequence;
+
+import javax.validation.GroupDefinitionException;
+import javax.validation.Validator;
+
+import org.jboss.testharness.AbstractTest;
+import org.jboss.testharness.impl.packaging.Artifact;
+import org.jboss.testharness.impl.packaging.ArtifactType;
+import org.jboss.testharness.impl.packaging.Classes;
+import org.testng.annotations.Test;
+
+import org.hibernate.jsr303.tck.util.TestUtil;
+
+/**
+ * @author Hardy Ferentschik
+ */
+ at Artifact(artifactType = ArtifactType.JSR303)
+ at Classes({ TestUtil.class, TestUtil.PathImpl.class, TestUtil.NodeImpl.class })
+public class SequenceResolutionTest extends AbstractTest {
+
+	@Test(expectedExceptions = GroupDefinitionException.class)
+	public void testInvalidDefinitionOfDefaultSequenceInEntity() {
+		Validator validator = TestUtil.getDefaultValidator();
+		TestEntity entity = new TestEntity();
+		validator.validate( entity, Complete.class );
+	}
+}

Added: beanvalidation/trunk/validation-tck/src/main/java/org/hibernate/jsr303/tck/tests/constraints/groups/defaultgroupsequence/TestEntity.java
===================================================================
--- beanvalidation/trunk/validation-tck/src/main/java/org/hibernate/jsr303/tck/tests/constraints/groups/defaultgroupsequence/TestEntity.java	                        (rev 0)
+++ beanvalidation/trunk/validation-tck/src/main/java/org/hibernate/jsr303/tck/tests/constraints/groups/defaultgroupsequence/TestEntity.java	2009-06-25 15:43:42 UTC (rev 16952)
@@ -0,0 +1,38 @@
+// $Id:$
+/*
+* JBoss, Home of Professional Open Source
+* Copyright 2008, Red Hat Middleware LLC, and individual contributors
+* by the @authors tag. See the copyright.txt in the distribution for a
+* full listing of individual contributors.
+*
+* Licensed 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.hibernate.jsr303.tck.tests.constraints.groups.defaultgroupsequence;
+
+import javax.validation.GroupSequence;
+import javax.validation.constraints.NotNull;
+import javax.validation.groups.Default;
+
+/**
+ * @author Hardy Ferentschik
+ */
+ at GroupSequence({ TimeConsumingChecks.class, TestEntity.class })
+public class TestEntity {
+	@NotNull
+	public String foo;
+}
+
+interface TimeConsumingChecks {
+}
+
+ at GroupSequence({ Default.class, TimeConsumingChecks.class })
+interface Complete {
+}

Modified: validator/trunk/hibernate-validator/src/main/java/org/hibernate/validation/engine/ValidatorImpl.java
===================================================================
--- validator/trunk/hibernate-validator/src/main/java/org/hibernate/validation/engine/ValidatorImpl.java	2009-06-25 11:12:54 UTC (rev 16951)
+++ validator/trunk/hibernate-validator/src/main/java/org/hibernate/validation/engine/ValidatorImpl.java	2009-06-25 15:43:42 UTC (rev 16952)
@@ -75,13 +75,29 @@
 	private final transient GroupChainGenerator groupChainGenerator;
 
 	private final ConstraintValidatorFactory constraintValidatorFactory;
+
+	/**
+	 * {@link MessageInterpolator} as passed to the constructor of this instance.
+	 */
 	private final MessageInterpolator messageInterpolator;
-	//never use it directly, always use getCachingTraversableResolver() to retrieved the single threaded caching wrapper.
+
+	/**
+	 * {@link TraversableResolver} as passed to the constructor of this instance.
+	 * Never use it directly, always use {@link #getCachingTraversableResolver()} to retrieved the single threaded caching wrapper.
+	 */
 	private final TraversableResolver traversableResolver;
+
+	/**
+	 * Passed at creation time of this validator instance.
+	 */
 	private final ConstraintHelper constraintHelper;
+
+	/**
+	 * Used to get access to the bean meta data. Used to avoid to parsing the constraint configuration for each call
+	 * of a given entity.
+	 */
 	private final BeanMetaDataCache beanMetaDataCache;
 
-
 	public ValidatorImpl(ConstraintValidatorFactory constraintValidatorFactory, MessageInterpolator messageInterpolator, TraversableResolver traversableResolver, ConstraintHelper constraintHelper, BeanMetaDataCache beanMetaDataCache) {
 		this.constraintValidatorFactory = constraintValidatorFactory;
 		this.messageInterpolator = messageInterpolator;
@@ -96,6 +112,7 @@
 		if ( object == null ) {
 			throw new IllegalArgumentException( "Validation of a null object" );
 		}
+
 		GroupChain groupChain = determineGroupExecutionOrder( groups );
 
 		GlobalExecutionContext<T> context = GlobalExecutionContext.getContextForValidate(
@@ -185,9 +202,13 @@
 		}
 
 		path = PathImpl.createShallowCopy( path );
-
 		LocalExecutionContext<U, V> localExecutionContext = LocalExecutionContext.getLocalExecutionContext( value );
 
+		BeanMetaData<U> beanMetaData = getBeanMetaData( localExecutionContext.getCurrentBeanType() );
+		if ( beanMetaData.defaultGroupSequenceIsRedefined() ) {
+		  	groupChain.assertDefaulGroupSequenceIsExpandable(beanMetaData.getDefaultGroupSequence());
+		}
+
 		// process first single groups. For these we can skip some object traversal, by first running all validations on the current bean
 		// before traversing the object.
 		Iterator<Group> groupIterator = groupChain.getGroupIterator();
@@ -231,9 +252,7 @@
 	 * @param <T> The type of the root bean
 	 */
 	private <T, U, V> void validateConstraints(GlobalExecutionContext<T> executionContext, LocalExecutionContext<U, V> localExecutionContext, PathImpl path) {
-		//casting rely on the fact that root object is at the top of the stack
-		@SuppressWarnings("unchecked")
-		BeanMetaData<T> beanMetaData = getBeanMetaData( ( Class<T> ) localExecutionContext.getCurrentBeanType() );
+		BeanMetaData<U> beanMetaData = getBeanMetaData( localExecutionContext.getCurrentBeanType() );
 		if ( localExecutionContext.getCurrentGroup().getName().equals( Default.class.getName() ) ) {
 			List<Class<?>> defaultGroupSequence = beanMetaData.getDefaultGroupSequence();
 			if ( log.isTraceEnabled() && defaultGroupSequence.size() > 0 && defaultGroupSequence.get( 0 ) != Default.class ) {
@@ -258,9 +277,9 @@
 		}
 	}
 
-	private <T, U, V> boolean validateConstraintsForCurrentGroup(GlobalExecutionContext<T> globalExecutionContext, LocalExecutionContext<U, V> localExecutionContext, BeanMetaData<T> beanMetaData, PathImpl path) {
+	private <T, U, V> boolean validateConstraintsForCurrentGroup(GlobalExecutionContext<T> globalExecutionContext, LocalExecutionContext<U, V> localExecutionContext, BeanMetaData<U> beanMetaData, PathImpl path) {
 		boolean validationSuccessful = true;
-		for ( MetaConstraint<T, ?> metaConstraint : beanMetaData.geMetaConstraintList() ) {
+		for ( MetaConstraint<U, ?> metaConstraint : beanMetaData.geMetaConstraintList() ) {
 			PathImpl newPath = PathImpl.createShallowCopy( path );
 			if ( !"".equals( metaConstraint.getPropertyName() ) ) {
 				newPath.addNode( new NodeImpl( metaConstraint.getPropertyName() ) );

Modified: validator/trunk/hibernate-validator/src/main/java/org/hibernate/validation/engine/groups/Group.java
===================================================================
--- validator/trunk/hibernate-validator/src/main/java/org/hibernate/validation/engine/groups/Group.java	2009-06-25 11:12:54 UTC (rev 16951)
+++ validator/trunk/hibernate-validator/src/main/java/org/hibernate/validation/engine/groups/Group.java	2009-06-25 15:43:42 UTC (rev 16952)
@@ -25,7 +25,14 @@
  * @author Hardy Ferentschik
  */
 public class Group {
+	/**
+	 * The actual group.
+	 */
 	private Class<?> group;
+
+	/**
+	 * The sequence the group is part of ({@code null}, if this group is not part of a sequence).
+	 */
 	private Class<?> sequence;
 
 	public Group(Class<?> group) {

Modified: validator/trunk/hibernate-validator/src/main/java/org/hibernate/validation/engine/groups/GroupChain.java
===================================================================
--- validator/trunk/hibernate-validator/src/main/java/org/hibernate/validation/engine/groups/GroupChain.java	2009-06-25 11:12:54 UTC (rev 16951)
+++ validator/trunk/hibernate-validator/src/main/java/org/hibernate/validation/engine/groups/GroupChain.java	2009-06-25 15:43:42 UTC (rev 16952)
@@ -18,43 +18,41 @@
 package org.hibernate.validation.engine.groups;
 
 import java.util.ArrayList;
+import java.util.HashMap;
 import java.util.Iterator;
 import java.util.List;
+import java.util.Map;
+import javax.validation.GroupDefinitionException;
+import javax.validation.groups.Default;
 
 /**
- * An instance of <code>GroupExecutionChain</code> defines the order in to validate groups during the validation process.
+ * An instance of {@code GroupChain} defines the group order during one full validation call.
  *
  * @author Hardy Ferentschik
  */
 public class GroupChain {
 
 	/**
-	 * The list of single groups.
+	 * The list of single groups to be used this validation.
 	 */
 	private List<Group> groupList = new ArrayList<Group>();
 
 	/**
-	 * The list of sequences.
+	 * The different sequences for this validation. The map contains the list of groups mapped to their sequence
+	 * name.
 	 */
-	private List<List<Group>> sequenceList = new ArrayList<List<Group>>();
+	private Map<Class<?>, List<Group>> sequenceMap = new HashMap<Class<?>, List<Group>>();
 
 	public Iterator<Group> getGroupIterator() {
 		return groupList.iterator();
 	}
 
 	public Iterator<List<Group>> getSequenceIterator() {
-		return sequenceList.iterator();
+		return sequenceMap.values().iterator();
 	}
 
 	public boolean containsSequence(Class<?> groupSequence) {
-		boolean result = false;
-		for ( List<Group> sequence : sequenceList ) {
-			if ( sequence.get( 0 ).getSequence().getName().equals( groupSequence.getName() ) ) {
-				result = true;
-				break;
-			}
-		}
-		return result;
+		return sequenceMap.containsKey( groupSequence );
 	}
 
 	void insertGroup(Group group) {
@@ -68,8 +66,62 @@
 			return;
 		}
 
-		if ( !sequenceList.contains( groups ) ) {
-			sequenceList.add( groups );
+		if ( !sequenceMap.containsValue( groups ) ) {
+			sequenceMap.put( groups.get( 0 ).getSequence(), groups );
 		}
 	}
+
+	@Override
+	public String toString() {
+		return "GroupChain{" +
+				"groupList=" + groupList +
+				", sequenceMap=" + sequenceMap +
+				'}';
+	}
+
+	public void assertDefaulGroupSequenceIsExpandable(List<Class<?>> defaultGroupSequence) {
+		for ( Map.Entry<Class<?>, List<Group>> entry : sequenceMap.entrySet() ) {
+			Class<?> sequence = entry.getKey();
+			List<Group> groupList = entry.getValue();
+			List<Group> defaultGroupList = buildTempGroupList( defaultGroupSequence, sequence );
+			int defaultGroupIndex = containsDefaultGroupAtIndex( sequence, groupList );
+			if ( defaultGroupIndex != -1 ) {
+				ensureDefaultGroupSequenceIsExpandable( groupList, defaultGroupList, defaultGroupIndex );
+			}
+		}
+	}
+
+	private void ensureDefaultGroupSequenceIsExpandable(List<Group> groupList, List<Group> defaultGroupList, int defaultGroupIndex) {
+		for ( int i = 0; i < defaultGroupList.size(); i++ ) {
+			Group group = defaultGroupList.get( i );
+			if(group.getGroup().equals( Default.class )) {
+				continue; // we don't have to consider the default group since it is the one we want to replace
+			}
+			int index = groupList.indexOf( group ); // check whether the sequence contains group of the default group sequence
+			if ( index == -1 ) {
+				continue; // if the group is not in the sequence we can continue
+			}
+
+			if ( ( i == 0 && index == defaultGroupIndex - 1 ) || ( i == defaultGroupList.size() - 1 && index == defaultGroupIndex + 1 ) ) {
+				// if we are at the beginning or end of he defaultGroupSequence and the matches are either directly before resp after we can continue as well,
+				// since we basically have two groups
+				continue;
+			}
+			throw new GroupDefinitionException( "Unable to expand default group list" + defaultGroupList + " into sequence " + groupList );
+		}
+	}
+
+	private int containsDefaultGroupAtIndex(Class<?> sequence, List<Group> groupList) {
+		Group defaultGroup = new Group( Default.class, sequence );
+		return groupList.indexOf( defaultGroup );
+	}
+
+	private List<Group> buildTempGroupList(List<Class<?>> defaultGroupSequence, Class<?> sequence) {
+		List<Group> groupList = new ArrayList<Group>();
+		for ( Class<?> clazz : defaultGroupSequence ) {
+			Group g = new Group( clazz, sequence );
+			groupList.add( g );
+		}
+		return groupList;
+	}
 }
\ No newline at end of file

Modified: validator/trunk/hibernate-validator/src/main/java/org/hibernate/validation/engine/groups/GroupChainGenerator.java
===================================================================
--- validator/trunk/hibernate-validator/src/main/java/org/hibernate/validation/engine/groups/GroupChainGenerator.java	2009-06-25 11:12:54 UTC (rev 16951)
+++ validator/trunk/hibernate-validator/src/main/java/org/hibernate/validation/engine/groups/GroupChainGenerator.java	2009-06-25 15:43:42 UTC (rev 16952)
@@ -90,7 +90,7 @@
 		List<Group> resolvedGroupSequence = new ArrayList<Group>();
 		GroupSequence sequenceAnnotation = group.getAnnotation( GroupSequence.class );
 		Class<?>[] sequenceArray = sequenceAnnotation.value();
-		for ( Class clazz : sequenceArray ) {
+		for ( Class<?> clazz : sequenceArray ) {
 			if ( clazz.getAnnotation( GroupSequence.class ) == null ) {
 				resolvedGroupSequence.add( new Group( clazz, group ) );
 			}

Modified: validator/trunk/hibernate-validator/src/main/java/org/hibernate/validation/metadata/BeanMetaData.java
===================================================================
--- validator/trunk/hibernate-validator/src/main/java/org/hibernate/validation/metadata/BeanMetaData.java	2009-06-25 11:12:54 UTC (rev 16951)
+++ validator/trunk/hibernate-validator/src/main/java/org/hibernate/validation/metadata/BeanMetaData.java	2009-06-25 15:43:42 UTC (rev 16952)
@@ -24,8 +24,6 @@
 import javax.validation.metadata.BeanDescriptor;
 import javax.validation.metadata.PropertyDescriptor;
 
-import org.hibernate.validation.metadata.MetaConstraint;
-
 /**
  * Interface defining the meta data about the constraints defined in a given bean.
  *
@@ -39,7 +37,7 @@
 	Class<T> getBeanClass();
 
 	/**
-	 * @return an instance of <code>ElementDescriptor</code> describing the bean this meta data applies for.
+	 * @return an instance of {@code ElementDescriptor} describing the bean this meta data applies for.
 	 */
 	BeanDescriptor getBeanDescriptor();
 
@@ -54,17 +52,22 @@
 	List<Class<?>> getDefaultGroupSequence();
 
 	/**
-	 * @return A list of <code>MetaConstraint</code> instances encapsulating the information of all the constraints
+	 * @return {@code true} if the entity redefines the default group sequence, {@code false} otherwise.
+	 */
+	boolean defaultGroupSequenceIsRedefined();
+
+	/**
+	 * @return A list of {@code MetaConstraint} instances encapsulating the information of all the constraints
 	 *         defined on the bean.
 	 */
 	List<MetaConstraint<T, ? extends Annotation>> geMetaConstraintList();
 
 	/**
-	 * Return <code>PropertyDescriptor</code> for the given property.
+	 * Return {@code PropertyDescriptor} for the given property.
 	 *
 	 * @param property the property for which to retrieve the descriptor.
 	 *
-	 * @return Returns the <code>PropertyDescriptor</code> for the given property or <code>null</code> in case the
+	 * @return Returns the {@code PropertyDescriptor} for the given property or {@code null} in case the
 	 *         property does not have a descriptor.
 	 */
 	PropertyDescriptor getPropertyDescriptor(String property);

Modified: validator/trunk/hibernate-validator/src/main/java/org/hibernate/validation/metadata/BeanMetaDataImpl.java
===================================================================
--- validator/trunk/hibernate-validator/src/main/java/org/hibernate/validation/metadata/BeanMetaDataImpl.java	2009-06-25 11:12:54 UTC (rev 16951)
+++ validator/trunk/hibernate-validator/src/main/java/org/hibernate/validation/metadata/BeanMetaDataImpl.java	2009-06-25 15:43:42 UTC (rev 16952)
@@ -137,6 +137,10 @@
 		return Collections.unmodifiableList( defaultGroupSequence );
 	}
 
+	public boolean defaultGroupSequenceIsRedefined() {
+		return defaultGroupSequence.size() > 1;
+	}
+
 	public void setDefaultGroupSequence(List<Class<?>> groupSequence) {
 		defaultGroupSequence = new ArrayList<Class<?>>();
 		boolean groupSequenceContainsDefault = false;
@@ -331,7 +335,7 @@
 	@SuppressWarnings("unchecked")
 	private <A extends Annotation> ConstraintDescriptorImpl buildConstraintDescriptor(Class<?> clazz, A annotation) {
 		ConstraintDescriptorImpl constraintDescriptor;
-		if ( clazz.isInterface() && !clazz.equals( beanClass)) {
+		if ( clazz.isInterface() && !clazz.equals( beanClass ) ) {
 			constraintDescriptor = new ConstraintDescriptorImpl( annotation, constraintHelper, clazz );
 		}
 		else {

Added: validator/trunk/hibernate-validator/src/test/java/org/hibernate/validation/engine/groups/GroupChainTest.java
===================================================================
--- validator/trunk/hibernate-validator/src/test/java/org/hibernate/validation/engine/groups/GroupChainTest.java	                        (rev 0)
+++ validator/trunk/hibernate-validator/src/test/java/org/hibernate/validation/engine/groups/GroupChainTest.java	2009-06-25 15:43:42 UTC (rev 16952)
@@ -0,0 +1,162 @@
+// $Id:$
+/*
+* JBoss, Home of Professional Open Source
+* Copyright 2008, Red Hat Middleware LLC, and individual contributors
+* by the @authors tag. See the copyright.txt in the distribution for a
+* full listing of individual contributors.
+*
+* Licensed 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.hibernate.validation.engine.groups;
+
+import java.util.ArrayList;
+import java.util.List;
+import javax.validation.GroupDefinitionException;
+import javax.validation.groups.Default;
+
+import static org.testng.FileAssert.fail;
+import org.testng.annotations.Test;
+
+
+/**
+ * @author Hardy Ferentschik
+ */
+public class GroupChainTest {
+	@Test
+	public void testAssertDefaulGroupSequenceIsExpandableWithDefaultAtEndOfSequence() {
+		// create a dummy sequence
+		Group a = new Group( GroupA.class, TestSequence.class );
+		Group b = new Group( GroupB.class, TestSequence.class );
+		Group c = new Group( GroupC.class, TestSequence.class );
+		Group defaultGroup = new Group(
+				Default.class, TestSequence.class
+		);
+		List<Group> sequence = new ArrayList<Group>();
+		sequence.add( a );
+		sequence.add( b );
+		sequence.add( c );
+		sequence.add( defaultGroup );
+
+		GroupChain chain = new GroupChain();
+		chain.insertSequence( sequence );
+
+		// create test default sequence
+		List<Class<?>> defaultSequence = new ArrayList<Class<?>>();
+		defaultSequence.add( Default.class );
+		defaultSequence.add( GroupA.class );
+		try {
+			chain.assertDefaulGroupSequenceIsExpandable( defaultSequence );
+			fail();
+		}
+		catch ( GroupDefinitionException e ) {
+			// success
+		}
+
+		defaultSequence.clear();
+		defaultSequence.add( GroupA.class );
+		defaultSequence.add( Default.class );
+		try {
+			chain.assertDefaulGroupSequenceIsExpandable( defaultSequence );
+			fail();
+		}
+		catch ( GroupDefinitionException e ) {
+			// success
+		}
+
+		defaultSequence.clear();
+		defaultSequence.add( Default.class );
+		defaultSequence.add( GroupC.class );
+		try {
+			chain.assertDefaulGroupSequenceIsExpandable( defaultSequence );
+			fail();
+		}
+		catch ( GroupDefinitionException e ) {
+			// success
+		}
+
+		defaultSequence.clear();
+		defaultSequence.add( GroupC.class );
+		defaultSequence.add( Default.class );
+		chain.assertDefaulGroupSequenceIsExpandable( defaultSequence );
+	}
+
+
+	@Test
+	public void testAssertDefaulGroupSequenceIsExpandableWithDefaultAtBeginningOfSequence() {
+		// create a dummy sequence
+		Group a = new Group( GroupA.class, TestSequence.class );
+		Group b = new Group( GroupB.class, TestSequence.class );
+		Group c = new Group( GroupC.class, TestSequence.class );
+		Group defaultGroup = new Group(
+				Default.class, TestSequence.class
+		);
+		List<Group> sequence = new ArrayList<Group>();
+		sequence.add( defaultGroup );
+		sequence.add( a );
+		sequence.add( b );
+		sequence.add( c );
+
+		GroupChain chain = new GroupChain();
+		chain.insertSequence( sequence );
+
+		// create test default sequence
+		List<Class<?>> defaultSequence = new ArrayList<Class<?>>();
+		defaultSequence.add( Default.class );
+		defaultSequence.add( GroupA.class );
+		chain.assertDefaulGroupSequenceIsExpandable( defaultSequence );
+
+
+		defaultSequence.clear();
+		defaultSequence.add( GroupA.class );
+		defaultSequence.add( Default.class );
+		try {
+			chain.assertDefaulGroupSequenceIsExpandable( defaultSequence );
+			fail();
+		}
+		catch ( GroupDefinitionException e ) {
+			// success
+		}
+
+		defaultSequence.clear();
+		defaultSequence.add( Default.class );
+		defaultSequence.add( GroupC.class );
+		try {
+			chain.assertDefaulGroupSequenceIsExpandable( defaultSequence );
+			fail();
+		}
+		catch ( GroupDefinitionException e ) {
+			// success
+		}
+
+		defaultSequence.clear();
+		defaultSequence.add( GroupC.class );
+		defaultSequence.add( Default.class );
+		try {
+			chain.assertDefaulGroupSequenceIsExpandable( defaultSequence );
+			fail();
+		}
+		catch ( GroupDefinitionException e ) {
+			// success
+		}
+	}
+}
+
+interface TestSequence {
+}
+
+interface GroupA {
+}
+
+interface GroupB {
+}
+
+interface GroupC {
+}




More information about the hibernate-commits mailing list