View Javadoc
1   /*
2    * Licensed to the Apache Software Foundation (ASF) under one
3    * or more contributor license agreements.  See the NOTICE file
4    * distributed with this work for additional information
5    * regarding copyright ownership.  The ASF licenses this file
6    * to you under the Apache License, Version 2.0 (the
7    * "License"); you may not use this file except in compliance
8    * with the License.  You may obtain a copy of the License at
9    *
10   *   http://www.apache.org/licenses/LICENSE-2.0
11   *
12   * Unless required by applicable law or agreed to in writing,
13   * software distributed under the License is distributed on an
14   * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
15   * KIND, either express or implied.  See the License for the
16   * specific language governing permissions and limitations
17   * under the License.
18   */
19  package org.apache.syncope.core.persistence.api.dao.search;
20  
21  import java.util.List;
22  import java.util.Optional;
23  import org.apache.commons.lang3.builder.EqualsBuilder;
24  import org.apache.commons.lang3.builder.HashCodeBuilder;
25  import org.apache.commons.lang3.builder.ToStringBuilder;
26  
27  public class SearchCond extends AbstractSearchCond {
28  
29      private static final long serialVersionUID = 661560782247499526L;
30  
31      public enum Type {
32  
33          LEAF,
34          NOT_LEAF,
35          AND,
36          OR
37  
38      }
39  
40      private Type type;
41  
42      private AbstractSearchCond leaf;
43  
44      private SearchCond left;
45  
46      private SearchCond right;
47  
48      public static SearchCond getLeaf(final AbstractSearchCond leaf) {
49          SearchCond cond;
50          if (leaf instanceof SearchCond) {
51              cond = (SearchCond) leaf;
52          } else {
53              cond = new SearchCond();
54              cond.leaf = leaf;
55          }
56  
57          cond.type = Type.LEAF;
58  
59          return cond;
60      }
61  
62      public static SearchCond getNotLeaf(final AbstractSearchCond leaf) {
63          SearchCond cond = getLeaf(leaf);
64  
65          cond.type = Type.NOT_LEAF;
66  
67          return cond;
68      }
69  
70      public static SearchCond getAnd(final SearchCond left, final SearchCond right) {
71          SearchCond cond = new SearchCond();
72  
73          cond.type = Type.AND;
74          cond.left = left;
75          cond.right = right;
76  
77          return cond;
78      }
79  
80      public static SearchCond getAnd(final List<SearchCond> conditions) {
81          if (conditions.size() == 1) {
82              return conditions.get(0);
83          } else if (conditions.size() > 2) {
84              return getAnd(conditions.get(0), getAnd(conditions.subList(1, conditions.size())));
85          } else {
86              return getAnd(conditions.get(0), conditions.get(1));
87          }
88      }
89  
90      public static SearchCond getOr(final SearchCond left, final SearchCond right) {
91          SearchCond cond = new SearchCond();
92  
93          cond.type = Type.OR;
94          cond.left = left;
95          cond.right = right;
96  
97          return cond;
98      }
99  
100     public static SearchCond getOr(final List<SearchCond> conditions) {
101         if (conditions.size() == 1) {
102             return conditions.get(0);
103         } else if (conditions.size() > 2) {
104             return getOr(conditions.get(0), getOr(conditions.subList(1, conditions.size())));
105         } else {
106             return getOr(conditions.get(0), conditions.get(1));
107         }
108     }
109 
110     public Optional<AnyTypeCond> getAnyTypeCond() {
111         return Optional.ofNullable(leaf instanceof AnyTypeCond ? (AnyTypeCond) leaf : null);
112     }
113 
114     /**
115      * Not a simple getter: recursively scans the search condition tree.
116      *
117      * @return the AnyType key or {@code NULL} if no type condition was found
118      */
119     public String hasAnyTypeCond() {
120         String anyTypeName = null;
121 
122         if (type == null) {
123             return null;
124         }
125 
126         switch (type) {
127             case LEAF:
128             case NOT_LEAF:
129                 if (leaf instanceof AnyTypeCond) {
130                     anyTypeName = ((AnyTypeCond) leaf).getAnyTypeKey();
131                 }
132                 break;
133 
134             case AND:
135             case OR:
136                 if (left != null) {
137                     anyTypeName = left.hasAnyTypeCond();
138                 }
139                 if (anyTypeName == null && right != null) {
140                     anyTypeName = right.hasAnyTypeCond();
141                 }
142                 break;
143 
144             default:
145         }
146 
147         return anyTypeName;
148     }
149 
150     @SuppressWarnings("unchecked")
151     public <T extends AbstractSearchCond> Optional<T> getLeaf(final Class<T> clazz) {
152         return Optional.ofNullable((T) (clazz.isInstance(leaf) ? leaf : null));
153     }
154 
155     public SearchCond getLeft() {
156         return left;
157     }
158 
159     public SearchCond getRight() {
160         return right;
161     }
162 
163     public Type getType() {
164         return type;
165     }
166 
167     @Override
168     public boolean isValid() {
169         boolean isValid = false;
170 
171         if (type == null) {
172             return false;
173         }
174 
175         switch (type) {
176             case LEAF:
177             case NOT_LEAF:
178                 isValid = leaf != null && leaf.isValid();
179                 break;
180 
181             case AND:
182             case OR:
183                 isValid = left != null && right != null
184                         && left.isValid() && right.isValid();
185                 break;
186 
187             default:
188         }
189 
190         return isValid;
191     }
192 
193     @Override
194     public int hashCode() {
195         return new HashCodeBuilder().
196                 append(type).
197                 append(leaf).
198                 append(left).
199                 append(right).
200                 build();
201     }
202 
203     @Override
204     public boolean equals(final Object obj) {
205         if (this == obj) {
206             return true;
207         }
208         if (obj == null) {
209             return false;
210         }
211         if (getClass() != obj.getClass()) {
212             return false;
213         }
214         final SearchCond other = (SearchCond) obj;
215         return new EqualsBuilder().
216                 append(type, other.type).
217                 append(leaf, other.leaf).
218                 append(left, other.left).
219                 append(right, other.right).
220                 build();
221     }
222 
223     @Override
224     public String toString() {
225         return new ToStringBuilder(this).
226                 append(type).
227                 append(leaf).
228                 append(left).
229                 append(right).
230                 build();
231     }
232 }