1 /*
2  * Hibernate Validator, declare and validate application constraints
3  *
4  * License: Apache License, Version 2.0
5  * See the license.txt file in the root directory or <http://www.apache.org/licenses/LICENSE-2.0>.
6  */

7 package org.hibernate.validator.internal.engine.groups;
8
9 import java.lang.invoke.MethodHandles;
10 import java.util.ArrayList;
11 import java.util.Collections;
12 import java.util.HashSet;
13 import java.util.Iterator;
14 import java.util.List;
15 import java.util.Set;
16
17 import javax.validation.GroupSequence;
18 import javax.validation.groups.Default;
19
20 import org.hibernate.validator.internal.util.logging.Log;
21 import org.hibernate.validator.internal.util.logging.LoggerFactory;
22
23 /**
24  * Models a group sequence.
25  *
26  * @author Hardy Ferentschik
27  */

28 public class Sequence implements Iterable<GroupWithInheritance> {
29
30     /**
31      * An "anonymous" sequence with just a single contained element, {@code Default.class}.
32      */

33     public static Sequence DEFAULT = new Sequence();
34
35     private static final Log LOG = LoggerFactory.make( MethodHandles.lookup() );
36
37     private final Class<?> sequence;
38     private List<Group> groups;
39     private List<GroupWithInheritance> expandedGroups;
40
41     private Sequence() {
42         this.sequence = Default.class;
43         this.groups = Collections.singletonList( Group.DEFAULT_GROUP );
44         this.expandedGroups = Collections.singletonList(
45                 new GroupWithInheritance( Collections.singleton( Group.DEFAULT_GROUP ) )
46         );
47     }
48
49     public Sequence(Class<?> sequence, List<Group> groups) {
50         this.groups = groups;
51         this.sequence = sequence;
52     }
53
54     public List<Group> getComposingGroups() {
55         return groups;
56     }
57
58     public Class<?> getDefiningClass() {
59         return sequence;
60     }
61
62     public void expandInheritedGroups() {
63         if ( expandedGroups != null ) {
64             return;
65         }
66
67         expandedGroups = new ArrayList<GroupWithInheritance>();
68         ArrayList<Group> tmpGroups = new ArrayList<Group>();
69
70         for ( Group group : groups ) {
71             HashSet<Group> groupsOfGroup = new HashSet<Group>();
72
73             groupsOfGroup.add( group );
74             addInheritedGroups( group, groupsOfGroup );
75
76             expandedGroups.add( new GroupWithInheritance( groupsOfGroup ) );
77             tmpGroups.addAll( groupsOfGroup );
78         }
79
80         groups = tmpGroups;
81     }
82
83     @Override
84     public Iterator<GroupWithInheritance> iterator() {
85         return expandedGroups.iterator();
86     }
87
88     @Override
89     public boolean equals(Object o) {
90         if ( this == o ) {
91             return true;
92         }
93         if ( o == null || getClass() != o.getClass() ) {
94             return false;
95         }
96
97         Sequence sequence1 = (Sequence) o;
98
99         if ( groups != null ? !groups.equals( sequence1.groups ) : sequence1.groups != null ) {
100             return false;
101         }
102         if ( sequence != null ? !sequence.equals( sequence1.sequence ) : sequence1.sequence != null ) {
103             return false;
104         }
105
106         return true;
107     }
108
109     @Override
110     public int hashCode() {
111         int result = sequence != null ? sequence.hashCode() : 0;
112         result = 31 * result + ( groups != null ? groups.hashCode() : 0 );
113         return result;
114     }
115
116     @Override
117     public String toString() {
118         final StringBuilder sb = new StringBuilder();
119         sb.append( "Sequence" );
120         sb.append( "{sequence=" ).append( sequence );
121         sb.append( ", groups=" ).append( groups );
122         sb.append( '}' );
123         return sb.toString();
124     }
125
126     /**
127      * Recursively add inherited (groups defined on superclasses).
128      *
129      * @param group the group for which the inherited groups need to be added to {@code expandedGroups}
130      * @param expandedGroups The list into which to add all groups
131      */

132     private void addInheritedGroups(Group group, Set<Group> expandedGroups) {
133         for ( Class<?> inheritedGroup : group.getDefiningClass().getInterfaces() ) {
134             if ( isGroupSequence( inheritedGroup ) ) {
135                 throw LOG.getSequenceDefinitionsNotAllowedException();
136             }
137             Group g = new Group( inheritedGroup );
138             expandedGroups.add( g );
139             addInheritedGroups( g, expandedGroups );
140         }
141     }
142
143     private boolean isGroupSequence(Class<?> clazz) {
144         return clazz.getAnnotation( GroupSequence.class ) != null;
145     }
146 }
147