001/**
002 * Copyright 2005-2016 The Kuali Foundation
003 *
004 * Licensed under the Educational Community License, Version 2.0 (the "License");
005 * you may not use this file except in compliance with the License.
006 * You may obtain a copy of the License at
007 *
008 * http://www.opensource.org/licenses/ecl2.php
009 *
010 * Unless required by applicable law or agreed to in writing, software
011 * distributed under the License is distributed on an "AS IS" BASIS,
012 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
013 * See the License for the specific language governing permissions and
014 * limitations under the License.
015 */
016package org.kuali.rice.kim.impl.common.attribute;
017
018import org.kuali.rice.core.api.criteria.CriteriaValue;
019import org.kuali.rice.core.api.criteria.LookupCustomizer;
020import org.kuali.rice.core.api.criteria.MultiValuedPredicate;
021import org.kuali.rice.core.api.criteria.Predicate;
022import org.kuali.rice.core.api.criteria.PropertyPathPredicate;
023import org.kuali.rice.core.api.criteria.SingleValuedPredicate;
024
025import java.util.ArrayList;
026import java.util.List;
027import java.util.Set;
028import java.util.regex.Matcher;
029import java.util.regex.Pattern;
030
031import static org.kuali.rice.core.api.criteria.PredicateFactory.*;
032
033/**
034 * this is an internal class used by kim service implementations that have generic lookup methods for classes
035 * with "attributes".
036 */
037public final class AttributeTransform implements LookupCustomizer.Transform<Predicate, Predicate> {
038
039    private static final LookupCustomizer.Transform<Predicate, Predicate> INSTANCE = new AttributeTransform();
040    private static final String ATTRIBUTE_DETAILS_ATTRIBUTE_VALUE = "attributeDetails.attributeValue";
041    private static final String ATTRIBUTE_DETAILS_ATTRIBUTE_NAME = "attributeDetails.kimAttribute.attributeName";
042    private static final String ATTRIBUTES_REGEX = "^attributes\\[\\w*\\]$";
043    private static final Pattern ATTRIBUTES_PATTERN = Pattern.compile(ATTRIBUTES_REGEX);
044
045    private AttributeTransform() {
046
047    }
048
049    @Override
050    public Predicate apply(final Predicate input) {
051        if (input instanceof PropertyPathPredicate) {
052            String pp = ((PropertyPathPredicate) input).getPropertyPath();
053            if (isAttributesPredicate(pp)) {
054                final String attributeName = pp.substring(pp.indexOf('[') + 1, pp.indexOf(']'));
055
056                final Predicate attrValue;
057                if (input instanceof SingleValuedPredicate) {
058                    final CriteriaValue<?> value = ((SingleValuedPredicate) input).getValue();
059                    attrValue = dynConstruct(input.getClass().getSimpleName(), ATTRIBUTE_DETAILS_ATTRIBUTE_VALUE, value.getValue());
060                } else if (input instanceof MultiValuedPredicate) {
061                    final Set<? extends CriteriaValue<?>> values = ((MultiValuedPredicate) input).getValues();
062                    List<Object> l = new ArrayList<Object>();
063                    for (CriteriaValue<?> v : values) {
064                        l.add(v.getValue());
065                    }
066
067                    attrValue = dynConstruct(input.getClass().getSimpleName(), ATTRIBUTE_DETAILS_ATTRIBUTE_VALUE, l.toArray());
068                } else {
069                    attrValue = dynConstruct(input.getClass().getSimpleName(), ATTRIBUTE_DETAILS_ATTRIBUTE_VALUE);
070                }
071                return and(equal(ATTRIBUTE_DETAILS_ATTRIBUTE_NAME, attributeName), attrValue);
072            }
073        }
074
075        return input;
076    }
077
078    private boolean isAttributesPredicate(String pp) {
079        Matcher matcher = ATTRIBUTES_PATTERN.matcher(pp);
080        return matcher.matches();
081    }
082
083    public static LookupCustomizer.Transform<Predicate, Predicate> getInstance() {
084        return INSTANCE;
085    }
086}