/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you 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.apache.syncope.core.persistence.api.search; import java.util.ArrayList; import java.util.List; import org.apache.cxf.jaxrs.ext.search.ConditionType; import org.apache.cxf.jaxrs.ext.search.SearchBean; import org.apache.cxf.jaxrs.ext.search.SearchCondition; import org.apache.cxf.jaxrs.ext.search.SearchUtils; import org.apache.cxf.jaxrs.ext.search.visitor.AbstractSearchConditionVisitor; import org.apache.syncope.common.lib.search.SearchableFields; import org.apache.syncope.common.lib.search.SpecialAttr; import org.apache.syncope.common.lib.search.SyncopeFiqlParser; import org.apache.syncope.common.lib.search.SyncopeFiqlSearchCondition; import org.apache.syncope.core.persistence.api.dao.search.AttributeCond; import org.apache.syncope.core.persistence.api.dao.search.MembershipCond; import org.apache.syncope.core.persistence.api.dao.search.ResourceCond; import org.apache.syncope.core.persistence.api.dao.search.RoleCond; import org.apache.syncope.core.persistence.api.dao.search.SearchCond; import org.apache.syncope.core.persistence.api.dao.search.AnyCond; import org.apache.syncope.core.persistence.api.dao.search.AnyTypeCond; import org.apache.syncope.core.persistence.api.dao.search.AssignableCond; import org.apache.syncope.core.persistence.api.dao.search.MemberCond; import org.apache.syncope.core.persistence.api.dao.search.RelationshipCond; import org.apache.syncope.core.persistence.api.dao.search.RelationshipTypeCond; /** * Converts CXF's <tt>SearchCondition</tt> into internal <tt>SearchCond</tt>. */ public class SearchCondVisitor extends AbstractSearchConditionVisitor<SearchBean, SearchCond> { private String realm; private SearchCond searchCond; public SearchCondVisitor() { super(null); } public void setRealm(final String realm) { this.realm = realm; } private AttributeCond createAttributeCond(final String schema) { AttributeCond attributeCond = SearchableFields.contains(schema) ? new AnyCond() : new AttributeCond(); attributeCond.setSchema(schema); return attributeCond; } private SearchCond visitPrimitive(final SearchCondition<SearchBean> sc) { String name = getRealPropertyName(sc.getStatement().getProperty()); SpecialAttr specialAttrName = SpecialAttr.fromString(name); String value = SearchUtils.toSqlWildcardString(sc.getStatement().getValue().toString(), false). replaceAll("\\\\_", "_"); SpecialAttr specialAttrValue = SpecialAttr.fromString(value); AttributeCond attributeCond = createAttributeCond(name); attributeCond.setExpression(value); ConditionType ct = sc.getConditionType(); if (sc instanceof SyncopeFiqlSearchCondition && sc.getConditionType() == ConditionType.CUSTOM) { SyncopeFiqlSearchCondition<SearchBean> sfsc = (SyncopeFiqlSearchCondition<SearchBean>) sc; if (SyncopeFiqlParser.IEQ.equals(sfsc.getOperator())) { ct = ConditionType.EQUALS; } else if (SyncopeFiqlParser.NIEQ.equals(sfsc.getOperator())) { ct = ConditionType.NOT_EQUALS; } else { throw new IllegalArgumentException( String.format("Condition type %s is not supported", sfsc.getOperator())); } } SearchCond leaf; switch (ct) { case EQUALS: case NOT_EQUALS: if (specialAttrName == null) { if (specialAttrValue != null && specialAttrValue == SpecialAttr.NULL) { attributeCond.setType(AttributeCond.Type.ISNULL); attributeCond.setExpression(null); } else if (value.indexOf('%') == -1) { attributeCond.setType(sc.getConditionType() == ConditionType.CUSTOM ? AttributeCond.Type.IEQ : AttributeCond.Type.EQ); } else { attributeCond.setType(sc.getConditionType() == ConditionType.CUSTOM ? AttributeCond.Type.ILIKE : AttributeCond.Type.LIKE); } leaf = SearchCond.getLeafCond(attributeCond); } else { switch (specialAttrName) { case TYPE: AnyTypeCond typeCond = new AnyTypeCond(); typeCond.setAnyTypeKey(value); leaf = SearchCond.getLeafCond(typeCond); break; case RESOURCES: ResourceCond resourceCond = new ResourceCond(); resourceCond.setResourceKey(value); leaf = SearchCond.getLeafCond(resourceCond); break; case GROUPS: MembershipCond groupCond = new MembershipCond(); groupCond.setGroup(value); leaf = SearchCond.getLeafCond(groupCond); break; case RELATIONSHIPS: RelationshipCond relationshipCond = new RelationshipCond(); relationshipCond.setAnyObject(value); leaf = SearchCond.getLeafCond(relationshipCond); break; case RELATIONSHIP_TYPES: RelationshipTypeCond relationshipTypeCond = new RelationshipTypeCond(); relationshipTypeCond.setRelationshipTypeKey(value); leaf = SearchCond.getLeafCond(relationshipTypeCond); break; case ROLES: RoleCond roleCond = new RoleCond(); roleCond.setRoleKey(value); leaf = SearchCond.getLeafCond(roleCond); break; case ASSIGNABLE: AssignableCond assignableCond = new AssignableCond(); assignableCond.setRealmFullPath(realm); leaf = SearchCond.getLeafCond(assignableCond); break; case MEMBER: MemberCond memberCond = new MemberCond(); memberCond.setMember(value); leaf = SearchCond.getLeafCond(memberCond); break; default: throw new IllegalArgumentException( String.format("Special attr name %s is not supported", specialAttrName)); } } if (ct == ConditionType.NOT_EQUALS) { if (leaf.getAttributeCond() != null && leaf.getAttributeCond().getType() == AttributeCond.Type.ISNULL) { leaf.getAttributeCond().setType(AttributeCond.Type.ISNOTNULL); } else if (leaf.getAnyCond() != null && leaf.getAnyCond().getType() == AnyCond.Type.ISNULL) { leaf.getAnyCond().setType(AttributeCond.Type.ISNOTNULL); } else { leaf = SearchCond.getNotLeafCond(leaf); } } break; case GREATER_OR_EQUALS: attributeCond.setType(AttributeCond.Type.GE); leaf = SearchCond.getLeafCond(attributeCond); break; case GREATER_THAN: attributeCond.setType(AttributeCond.Type.GT); leaf = SearchCond.getLeafCond(attributeCond); break; case LESS_OR_EQUALS: attributeCond.setType(AttributeCond.Type.LE); leaf = SearchCond.getLeafCond(attributeCond); break; case LESS_THAN: attributeCond.setType(AttributeCond.Type.LT); leaf = SearchCond.getLeafCond(attributeCond); break; default: throw new IllegalArgumentException(String.format("Condition type %s is not supported", ct.name())); } return leaf; } private SearchCond visitCompount(final SearchCondition<SearchBean> sc) { List<SearchCond> searchConds = new ArrayList<>(); for (SearchCondition<SearchBean> searchCondition : sc.getSearchConditions()) { searchConds.add(searchCondition.getStatement() == null ? visitCompount(searchCondition) : visitPrimitive(searchCondition)); } SearchCond compound; switch (sc.getConditionType()) { case AND: compound = SearchCond.getAndCond(searchConds); break; case OR: compound = SearchCond.getOrCond(searchConds); break; default: throw new IllegalArgumentException( String.format("Condition type %s is not supported", sc.getConditionType().name())); } return compound; } @Override public void visit(final SearchCondition<SearchBean> sc) { searchCond = sc.getStatement() == null ? visitCompount(sc) : visitPrimitive(sc); } @Override public SearchCond getQuery() { return searchCond; } }