Java tutorial
/* * 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.client.console.panels.search; import java.io.Serializable; import java.util.ArrayList; import java.util.Collections; import java.util.HashMap; import java.util.List; import java.util.Map; import java.util.regex.Pattern; import org.apache.commons.lang3.StringUtils; import org.apache.commons.lang3.math.NumberUtils; 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.client.CompleteCondition; import org.apache.syncope.common.lib.search.AbstractFiqlSearchConditionBuilder; import org.apache.syncope.common.lib.search.AnyObjectFiqlSearchConditionBuilder; import org.apache.syncope.common.lib.search.GroupFiqlSearchConditionBuilder; 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.common.lib.search.SyncopeProperty; import org.apache.syncope.common.lib.search.UserFiqlSearchConditionBuilder; import org.apache.syncope.common.lib.to.PlainSchemaTO; import org.apache.syncope.common.lib.types.AttrSchemaType; import org.slf4j.Logger; import org.slf4j.LoggerFactory; public final class SearchUtils implements Serializable { private static final long serialVersionUID = 398381905376547084L; private static final Logger LOG = LoggerFactory.getLogger(SearchUtils.class); private static Pattern getTypeConditionPattern(final String type) { return Pattern.compile(String.format(";\\$type==%s|\\$type==%s;", type, type)); } public static Map<String, List<SearchClause>> getSearchClauses(final Map<String, String> fiql) { Map<String, List<SearchClause>> clauses = new HashMap<>(); for (Map.Entry<String, String> entry : fiql.entrySet()) { clauses.put(entry.getKey(), getSearchClauses( entry.getValue().replaceAll(getTypeConditionPattern(entry.getKey()).pattern(), ""))); } return clauses; } public static List<SearchClause> getSearchClauses(final String fiql) { List<SearchClause> clauses = new ArrayList<>(); if (StringUtils.isNotBlank(fiql)) { try { SyncopeFiqlParser<SearchBean> fiqlParser = new SyncopeFiqlParser<>(SearchBean.class, AbstractFiqlSearchConditionBuilder.CONTEXTUAL_PROPERTIES); clauses.addAll(getSearchClauses(fiqlParser.parse(fiql))); } catch (Exception e) { LOG.error("Unparseable FIQL expression '{}'", fiql, e); } } return clauses; } private static List<SearchClause> getSearchClauses(final SearchCondition<SearchBean> sc) { List<SearchClause> clauses = new ArrayList<>(); if (sc.getStatement() == null) { clauses.addAll(getCompoundSearchClauses(sc)); } else { clauses.add(getPrimitiveSearchClause(sc)); } return clauses; } private static List<SearchClause> getCompoundSearchClauses(final SearchCondition<SearchBean> sc) { List<SearchClause> clauses = new ArrayList<>(); for (SearchCondition<SearchBean> searchCondition : sc.getSearchConditions()) { if (searchCondition.getStatement() == null) { clauses.addAll(getCompoundSearchClauses(searchCondition)); } else { SearchClause clause = getPrimitiveSearchClause(searchCondition); if (sc.getConditionType() == ConditionType.AND) { clause.setOperator(SearchClause.Operator.AND); } if (sc.getConditionType() == ConditionType.OR) { clause.setOperator(SearchClause.Operator.OR); } clauses.add(clause); } } return clauses; } private static SearchClause getPrimitiveSearchClause(final SearchCondition<SearchBean> sc) { SearchClause clause = new SearchClause(); String property = sc.getCondition().getKeySet().iterator().next(); clause.setProperty(property); String value = sc.getCondition().get(property).replace("%252C", ",").replace("%253B", ";"); clause.setValue(value); LOG.debug("Condition: " + sc.getCondition()); if (SpecialAttr.ROLES.toString().equals(property)) { clause.setType(SearchClause.Type.ROLE_MEMBERSHIP); clause.setProperty(value); } else if (SpecialAttr.RELATIONSHIPS.toString().equals(property)) { clause.setType(SearchClause.Type.RELATIONSHIP); clause.setProperty(value); } else if (SpecialAttr.RELATIONSHIP_TYPES.toString().equals(property)) { clause.setType(SearchClause.Type.RELATIONSHIP); clause.setProperty(value); } else if (SpecialAttr.GROUPS.toString().equals(property)) { clause.setType(SearchClause.Type.GROUP_MEMBERSHIP); clause.setProperty(value); } else if (SpecialAttr.RESOURCES.toString().equals(property)) { clause.setType(SearchClause.Type.RESOURCE); clause.setProperty(value); } else if (SpecialAttr.MEMBER.toString().equals(property)) { clause.setType(SearchClause.Type.GROUP_MEMBER); clause.setProperty(value); } else { clause.setType(SearchClause.Type.ATTRIBUTE); } 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; } } switch (ct) { case EQUALS: if (SpecialAttr.RELATIONSHIP_TYPES.toString().equals(property)) { clause.setComparator(SpecialAttr.NULL.toString().equals(value) ? SearchClause.Comparator.EQUALS : SearchClause.Comparator.IS_NULL); } else { clause.setComparator(SpecialAttr.NULL.toString().equals(value) ? SearchClause.Comparator.IS_NULL : SearchClause.Comparator.EQUALS); } break; case NOT_EQUALS: if (SpecialAttr.RELATIONSHIP_TYPES.toString().equals(property)) { clause.setComparator(SpecialAttr.NULL.toString().equals(value) ? SearchClause.Comparator.NOT_EQUALS : SearchClause.Comparator.IS_NOT_NULL); } else { clause.setComparator(SpecialAttr.NULL.toString().equals(value) ? SearchClause.Comparator.IS_NOT_NULL : SearchClause.Comparator.NOT_EQUALS); } break; case GREATER_OR_EQUALS: clause.setComparator(SearchClause.Comparator.GREATER_OR_EQUALS); break; case GREATER_THAN: clause.setComparator(SearchClause.Comparator.GREATER_THAN); break; case LESS_OR_EQUALS: clause.setComparator(SearchClause.Comparator.LESS_OR_EQUALS); break; case LESS_THAN: clause.setComparator(SearchClause.Comparator.LESS_THAN); break; default: break; } return clause; } public static String buildFIQL(final List<SearchClause> clauses, final AbstractFiqlSearchConditionBuilder builder) { return buildFIQL(clauses, builder, Collections.<String, PlainSchemaTO>emptyMap()); } public static String buildFIQL(final List<SearchClause> clauses, final AbstractFiqlSearchConditionBuilder builder, final Map<String, PlainSchemaTO> availableSchemaTypes) { LOG.debug("Generating FIQL from List<SearchClause>: {}", clauses); CompleteCondition prevCondition; CompleteCondition condition = null; boolean notTheFirst = false; for (SearchClause clause : clauses) { prevCondition = condition; if (clause.getType() != null) { String value = clause.getValue() == null ? null : clause.getValue().replace(",", "%252C").replace(";", "%253B"); switch (clause.getType()) { case GROUP_MEMBER: switch (clause.getComparator()) { case EQUALS: condition = ((GroupFiqlSearchConditionBuilder) builder).withMembers(value); break; case NOT_EQUALS: condition = ((GroupFiqlSearchConditionBuilder) builder).withoutMembers(value); break; default: } break; case GROUP_MEMBERSHIP: if (StringUtils.isNotBlank(clause.getProperty())) { String groupKey = clause.getProperty(); if (builder instanceof UserFiqlSearchConditionBuilder) { condition = clause.getComparator() == SearchClause.Comparator.EQUALS ? ((UserFiqlSearchConditionBuilder) builder).inGroups(groupKey) : ((UserFiqlSearchConditionBuilder) builder).notInGroups(groupKey); } else { condition = clause.getComparator() == SearchClause.Comparator.EQUALS ? ((AnyObjectFiqlSearchConditionBuilder) builder).inGroups(groupKey) : ((AnyObjectFiqlSearchConditionBuilder) builder).notInGroups(groupKey); } } break; case RESOURCE: if (StringUtils.isNotBlank(clause.getProperty())) { condition = clause.getComparator() == SearchClause.Comparator.EQUALS ? builder.hasResources(clause.getProperty()) : builder.hasNotResources(clause.getProperty()); } break; case ATTRIBUTE: if (StringUtils.isNotBlank(clause.getProperty())) { boolean isLong = false; boolean isDouble = false; if (availableSchemaTypes.get(clause.getProperty()) != null) { isLong = availableSchemaTypes.get(clause.getProperty()) .getType() == AttrSchemaType.Long; isDouble = availableSchemaTypes.get(clause.getProperty()) .getType() == AttrSchemaType.Double; } SyncopeProperty property = builder.is(clause.getProperty()); switch (clause.getComparator()) { case IS_NULL: condition = builder.isNull(clause.getProperty()); break; case IS_NOT_NULL: condition = builder.isNotNull(clause.getProperty()); break; case LESS_THAN: condition = isLong ? property.lessThan(NumberUtils.toLong(value)) : isDouble ? property.lessThan(NumberUtils.toDouble(value)) : property.lexicalBefore(value); break; case LESS_OR_EQUALS: condition = isLong ? property.lessOrEqualTo(NumberUtils.toLong(value)) : isDouble ? property.lessOrEqualTo(NumberUtils.toDouble(value)) : property.lexicalNotAfter(value); break; case GREATER_THAN: condition = isLong ? property.greaterThan(NumberUtils.toLong(value)) : isDouble ? property.greaterThan(NumberUtils.toDouble(value)) : property.lexicalAfter(value); break; case GREATER_OR_EQUALS: condition = isLong ? property.greaterOrEqualTo(NumberUtils.toLong(value)) : isDouble ? property.greaterOrEqualTo(NumberUtils.toDouble(value)) : property.lexicalNotBefore(value); break; case NOT_EQUALS: condition = property.notEqualTolIgnoreCase(value); break; case EQUALS: condition = isLong ? property.equalTo(NumberUtils.toLong(value)) : isDouble ? property.equalTo(NumberUtils.toDouble(value)) : property.equalToIgnoreCase(value); break; default: condition = property.equalToIgnoreCase(value); break; } } break; case ROLE_MEMBERSHIP: if (StringUtils.isNotBlank(clause.getProperty())) { switch (clause.getComparator()) { case EQUALS: condition = ((UserFiqlSearchConditionBuilder) builder).inRoles(clause.getProperty()); break; case NOT_EQUALS: condition = ((UserFiqlSearchConditionBuilder) builder).notInRoles(clause.getProperty()); break; default: break; } } break; case RELATIONSHIP: if (StringUtils.isNotBlank(clause.getProperty())) { if (builder instanceof UserFiqlSearchConditionBuilder) { switch (clause.getComparator()) { case IS_NOT_NULL: condition = ((UserFiqlSearchConditionBuilder) builder) .inRelationshipTypes(clause.getProperty()); break; case IS_NULL: condition = ((UserFiqlSearchConditionBuilder) builder) .notInRelationshipTypes(clause.getProperty()); break; case EQUALS: condition = ((UserFiqlSearchConditionBuilder) builder).inRelationships(value); break; case NOT_EQUALS: condition = ((UserFiqlSearchConditionBuilder) builder).notInRelationships(value); break; default: break; } } else { switch (clause.getComparator()) { case IS_NOT_NULL: condition = ((AnyObjectFiqlSearchConditionBuilder) builder) .inRelationshipTypes(clause.getProperty()); break; case IS_NULL: condition = ((AnyObjectFiqlSearchConditionBuilder) builder) .notInRelationshipTypes(clause.getProperty()); break; case EQUALS: condition = ((AnyObjectFiqlSearchConditionBuilder) builder).inRelationships(value); break; case NOT_EQUALS: condition = ((AnyObjectFiqlSearchConditionBuilder) builder) .notInRelationships(value); break; default: break; } } } break; default: break; } } if (notTheFirst) { if (clause.getOperator() == SearchClause.Operator.AND) { condition = builder.and(prevCondition, condition); } if (clause.getOperator() == SearchClause.Operator.OR) { condition = builder.or(prevCondition, condition); } } notTheFirst = true; } String fiql = condition == null ? null : condition.query(); LOG.debug("Generated FIQL: {}", fiql); return fiql; } private SearchUtils() { // private constructor for static utility class } }