View Javadoc
1   /**
2    * Copyright 2005-2015 The Kuali Foundation
3    *
4    * Licensed under the Educational Community License, Version 2.0 (the "License");
5    * you may not use this file except in compliance with the License.
6    * You may obtain a copy of the License at
7    *
8    * http://www.opensource.org/licenses/ecl2.php
9    *
10   * Unless required by applicable law or agreed to in writing, software
11   * distributed under the License is distributed on an "AS IS" BASIS,
12   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13   * See the License for the specific language governing permissions and
14   * limitations under the License.
15   */
16  package org.kuali.rice.kim.impl.common.attribute;
17  
18  import com.google.common.collect.Iterables;
19  import org.kuali.rice.core.api.criteria.AndPredicate;
20  import org.kuali.rice.core.api.criteria.CompositePredicate;
21  import org.kuali.rice.core.api.criteria.CriteriaValue;
22  import org.kuali.rice.core.api.criteria.MultiValuedPredicate;
23  import org.kuali.rice.core.api.criteria.OrPredicate;
24  import org.kuali.rice.core.api.criteria.Predicate;
25  import org.kuali.rice.core.api.criteria.PropertyPathPredicate;
26  import org.kuali.rice.core.api.criteria.QueryByCriteria;
27  import org.kuali.rice.core.api.criteria.SingleValuedPredicate;
28  import org.kuali.rice.core.api.criteria.Transform;
29  
30  import java.util.ArrayList;
31  import java.util.HashSet;
32  import java.util.List;
33  import java.util.Set;
34  import java.util.regex.Matcher;
35  import java.util.regex.Pattern;
36  
37  import static org.kuali.rice.core.api.criteria.PredicateFactory.*;
38  
39  /**
40   * this is an internal class used by kim service implementations that have generic lookup methods for classes
41   * with "attributes".
42   */
43  public final class AttributeTransform implements Transform<QueryByCriteria, QueryByCriteria> {
44  
45      private static final Transform<QueryByCriteria, QueryByCriteria> INSTANCE = new AttributeTransform();
46      private static final String ATTRIBUTE_DETAILS_ATTRIBUTE_VALUE = "attributeDetails.attributeValue";
47      private static final String ATTRIBUTE_DETAILS_ATTRIBUTE_NAME = "attributeDetails.kimAttribute.attributeName";
48      private static final String ATTRIBUTES_REGEX = "^attributes\\[\\w*\\]$";
49      private static final Pattern ATTRIBUTES_PATTERN = Pattern.compile(ATTRIBUTES_REGEX);
50  
51      private AttributeTransform() {
52  
53      }
54  
55      @Override
56      public QueryByCriteria apply(final QueryByCriteria input) {
57          QueryByCriteria.Builder builder = QueryByCriteria.Builder.create(input);
58          builder.setPredicates(applyPredicate(input.getPredicate()));
59          return builder.build();
60      }
61  
62      private Predicate applyPredicate(final Predicate input) {
63          if (input instanceof PropertyPathPredicate) {
64              String pp = ((PropertyPathPredicate) input).getPropertyPath();
65              if (isAttributesPredicate(pp)) {
66                  final String attributeName = pp.substring(pp.indexOf('[') + 1, pp.indexOf(']'));
67  
68                  final Predicate attrValue;
69                  if (input instanceof SingleValuedPredicate) {
70                      final CriteriaValue<?> value = ((SingleValuedPredicate) input).getValue();
71                      attrValue = dynConstruct(input.getClass().getSimpleName(), ATTRIBUTE_DETAILS_ATTRIBUTE_VALUE, value.getValue());
72                  } else if (input instanceof MultiValuedPredicate) {
73                      final Set<? extends CriteriaValue<?>> values = ((MultiValuedPredicate) input).getValues();
74                      List<Object> l = new ArrayList<Object>();
75                      for (CriteriaValue<?> v : values) {
76                          l.add(v.getValue());
77                      }
78  
79                      attrValue = dynConstruct(input.getClass().getSimpleName(), ATTRIBUTE_DETAILS_ATTRIBUTE_VALUE, l.toArray());
80                  } else {
81                      attrValue = dynConstruct(input.getClass().getSimpleName(), ATTRIBUTE_DETAILS_ATTRIBUTE_VALUE);
82                  }
83                  return and(equal(ATTRIBUTE_DETAILS_ATTRIBUTE_NAME, attributeName), attrValue);
84              }
85          } else if (input instanceof CompositePredicate) {
86              return applyCompositePredicate((CompositePredicate) input);
87          }
88  
89          return input;
90      }
91  
92      private Predicate applyCompositePredicate(final CompositePredicate input) {
93          Set<Predicate> appliedPredicates = new HashSet<Predicate>();
94  
95          for (Predicate predicate : input.getPredicates()) {
96              appliedPredicates.add(applyPredicate(predicate));
97          }
98  
99          Predicate[] appliedPredicatesArray = Iterables.toArray(appliedPredicates, Predicate.class);
100 
101         if (input instanceof AndPredicate) {
102             return and(appliedPredicatesArray);
103         } else if (input instanceof OrPredicate) {
104             return or(appliedPredicatesArray);
105         }
106 
107         return input;
108     }
109 
110     private boolean isAttributesPredicate(String pp) {
111         Matcher matcher = ATTRIBUTES_PATTERN.matcher(pp);
112         return matcher.matches();
113     }
114 
115     public static Transform<QueryByCriteria, QueryByCriteria> getInstance() {
116         return INSTANCE;
117     }
118 }