/* * ==================== * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER. * * Copyright 2008-2009 Sun Microsystems, Inc. All rights reserved. * * The contents of this file are subject to the terms of the Common Development * and Distribution License("CDDL") (the "License"). You may not use this file * except in compliance with the License. * * You can obtain a copy of the License at * http://opensource.org/licenses/cddl1.php * See the License for the specific language governing permissions and limitations * under the License. * * When distributing the Covered Code, include this CDDL Header Notice in each file * and include the License file at http://opensource.org/licenses/cddl1.php. * If applicable, add the following below this CDDL Header, with the fields * enclosed by brackets [] replaced by your own identifying information: * "Portions Copyrighted [year] [name of copyright owner]" * ==================== */ package org.identityconnectors.dbcommon; import org.identityconnectors.framework.common.objects.Attribute; import org.identityconnectors.framework.common.objects.AttributeUtil; import org.identityconnectors.framework.common.objects.ObjectClass; import org.identityconnectors.framework.common.objects.OperationOptions; import org.identityconnectors.framework.common.objects.filter.AbstractFilterTranslator; import org.identityconnectors.framework.common.objects.filter.ContainsFilter; import org.identityconnectors.framework.common.objects.filter.EndsWithFilter; import org.identityconnectors.framework.common.objects.filter.EqualsFilter; import org.identityconnectors.framework.common.objects.filter.GreaterThanFilter; import org.identityconnectors.framework.common.objects.filter.GreaterThanOrEqualFilter; import org.identityconnectors.framework.common.objects.filter.LessThanFilter; import org.identityconnectors.framework.common.objects.filter.LessThanOrEqualFilter; import org.identityconnectors.framework.common.objects.filter.StartsWithFilter; /** * DatabaseFilterTranslator abstract class translate filters to database WHERE * clause The resource specific getAttributeName must be provided in real * translator. * * @since 1.0 */ public abstract class DatabaseFilterTranslator extends AbstractFilterTranslator<FilterWhereBuilder> { protected final ObjectClass oclass; protected final OperationOptions options; /** * DatabaseFilterTranslator translate filters to database WHERE clause. * * @param oclass * the object class * @param options * the filter options */ public DatabaseFilterTranslator(final ObjectClass oclass, final OperationOptions options) { this.oclass = oclass; this.options = options; } /** * @return */ protected FilterWhereBuilder createBuilder() { return new FilterWhereBuilder(); } @Override protected FilterWhereBuilder createAndExpression(FilterWhereBuilder leftExpression, FilterWhereBuilder rightExpression) { FilterWhereBuilder build = createBuilder(); build.join("AND", leftExpression, rightExpression); return build; } @Override protected FilterWhereBuilder createOrExpression(FilterWhereBuilder leftExpression, FilterWhereBuilder rightExpression) { FilterWhereBuilder build = createBuilder(); build.join("OR", leftExpression, rightExpression); return build; } @Override protected FilterWhereBuilder createEqualsExpression(EqualsFilter filter, boolean not) { final Attribute attribute = filter.getAttribute(); if (!validateSearchAttribute(attribute)) { return null; } SQLParam param = getSQLParam(attribute, oclass, options); if (param == null) { return null; } final FilterWhereBuilder ret = createBuilder(); if (not) { ret.getWhere().append("NOT "); } // Normalize NULLs if (param.getValue() == null) { ret.addNull(param.getName()); return ret; } ret.addBind(param, "="); return ret; } @Override protected FilterWhereBuilder createContainsExpression(ContainsFilter filter, boolean not) { final Attribute attribute = filter.getAttribute(); if (!validateSearchAttribute(attribute)) { return null; } SQLParam param = getSQLParam(attribute, oclass, options); if (param == null || param.getValue() == null || !(param.getValue() instanceof String)) { // Null value filter is not supported return null; } String value = (String) param.getValue(); final FilterWhereBuilder ret = createBuilder(); if (not) { ret.getWhere().append("NOT "); } // To be sure, this is not already quoted if (!value.startsWith("%")) { value = "%" + value; } if (!value.endsWith("%")) { value = value + "%"; } ret.addBind(new SQLParam(param.getName(), value, param.getSqlType()), "LIKE"); return ret; } @Override protected FilterWhereBuilder createEndsWithExpression(EndsWithFilter filter, boolean not) { final Attribute attribute = filter.getAttribute(); if (!validateSearchAttribute(attribute)) { return null; } SQLParam param = getSQLParam(attribute, oclass, options); if (param == null || param.getValue() == null || !(param.getValue() instanceof String)) { // Null value filter is not supported return null; } String value = (String) param.getValue(); final FilterWhereBuilder ret = createBuilder(); if (not) { ret.getWhere().append("NOT "); } // To be sure, this is not already quoted if (!value.startsWith("%")) { value = "%" + value; } ret.addBind(new SQLParam(param.getName(), value, param.getSqlType()), "LIKE"); return ret; } @Override protected FilterWhereBuilder createStartsWithExpression(StartsWithFilter filter, boolean not) { final Attribute attribute = filter.getAttribute(); if (!validateSearchAttribute(attribute)) { return null; } SQLParam param = getSQLParam(attribute, oclass, options); if (param == null || param.getValue() == null || !(param.getValue() instanceof String)) { // Null value filter is not supported return null; } String value = (String) param.getValue(); final FilterWhereBuilder ret = createBuilder(); if (not) { ret.getWhere().append("NOT "); } // To be sure, this is not already quoted if (!value.endsWith("%")) { value = value + "%"; } ret.addBind(new SQLParam(param.getName(), value, param.getSqlType()), "LIKE"); return ret; } @Override protected FilterWhereBuilder createGreaterThanExpression(GreaterThanFilter filter, boolean not) { final Attribute attribute = filter.getAttribute(); if (!validateSearchAttribute(attribute)) { return null; } SQLParam param = getSQLParam(attribute, oclass, options); if (param == null || param.getValue() == null) { return null; } final FilterWhereBuilder ret = createBuilder(); final String op = not ? "<=" : ">"; ret.addBind(param, op); return ret; } @Override protected FilterWhereBuilder createGreaterThanOrEqualExpression( GreaterThanOrEqualFilter filter, boolean not) { final Attribute attribute = filter.getAttribute(); if (!validateSearchAttribute(attribute)) { return null; } SQLParam param = getSQLParam(attribute, oclass, options); if (param == null || param.getValue() == null) { return null; } final FilterWhereBuilder ret = createBuilder(); final String op = not ? "<" : ">="; ret.addBind(param, op); return ret; } @Override protected FilterWhereBuilder createLessThanExpression(LessThanFilter filter, boolean not) { final Attribute attribute = filter.getAttribute(); if (!validateSearchAttribute(attribute)) { return null; } SQLParam param = getSQLParam(attribute, oclass, options); if (param == null || param.getValue() == null) { return null; } final FilterWhereBuilder ret = createBuilder(); final String op = not ? ">=" : "<"; ret.addBind(param, op); return ret; } @Override protected FilterWhereBuilder createLessThanOrEqualExpression(LessThanOrEqualFilter filter, boolean not) { final Attribute attribute = filter.getAttribute(); if (!validateSearchAttribute(attribute)) { return null; } SQLParam param = getSQLParam(attribute, oclass, options); if (param == null || param.getValue() == null) { return null; } final FilterWhereBuilder ret = createBuilder(); final String op = not ? ">" : "<="; ret.addBind(param, op); return ret; } /** * Get the SQLParam for given attribute. * * @param attribute * to translate * @return the expected SQLParam, or null if filter not supported * {@link java.sql.Types} */ protected abstract SQLParam getSQLParam(Attribute attribute, ObjectClass objectClass, OperationOptions options); /** * Validate the attribute to supported search types. * * @param attribute */ protected boolean validateSearchAttribute(final Attribute attribute) { // Ignore streamed ( byte[] objects ) from query if (byte[].class.equals(AttributeUtil.getSingleValue(attribute).getClass())) { return false; } // Otherwise let the database process return true; } }