/* * Copyright 2013 Eric F. Savage, code@efsavage.com * * Licensed 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 com.ajah.spring.jdbc.criteria; import java.util.ArrayList; import java.util.List; import com.ajah.util.AjahUtils; import com.ajah.util.CollectionUtils; import com.ajah.util.lang.NameValuePair; /** * A subclause of a {@link Criteria}. Supports ORs. Only supports WHERE * expressions. * * @author <a href="http://efsavage.com">Eric F. Savage</a>, <a * href="mailto:code@efsavage.com">code@efsavage.com</a>. */ public class SubCriteria extends AbstractCriteria<SubCriteria> { private List<NameValuePair<String>> orLikes = null; private List<NameValuePair<Number>> gts = null; private List<SubCriteria> ands = null; private List<SubCriteria> ors = null; /** * A subclause, included as an AND, but may contain ORs. * * @param subCriteria * The subCriteria to include * @return Criteria instance the method was invoked on (for chaining). */ public SubCriteria and(final SubCriteria subCriteria) { AjahUtils.requireParam(subCriteria, "field"); if (this.ands == null) { this.ands = new ArrayList<>(); } this.ands.add(subCriteria); return this; } /** * @see com.ajah.spring.jdbc.criteria.AbstractCriteria#getThis() */ @Override protected SubCriteria getThis() { return this; } /** * Constructs a {@link Where} object from this instance, suitable for * creating a prepared SQL statement. Note that this does not include the * WHERE token. * * @return A where clause that is equivalent to this criteria. */ public Where getWhere() { final List<String> values = new ArrayList<>(); final StringBuilder where = new StringBuilder().append("("); boolean first = true; if (!CollectionUtils.isEmpty(this.eqs)) { for (final NameValuePair<String> eq : this.eqs) { if (first) { first = false; } else { where.append(" AND "); } where.append("`"); where.append(eq.getName()); where.append("`"); if (eq.getValue() == null) { where.append(" IS NULL"); } else { where.append("=?"); values.add(eq.getValue()); } } } if (!CollectionUtils.isEmpty(this.orLikes)) { where.append("("); for (final NameValuePair<String> orLike : this.orLikes) { if (first) { first = false; } else { where.append(" OR "); } where.append("`"); where.append(orLike.getName()); where.append("`"); where.append(" LIKE '"); where.append(orLike.getValue()); where.append("'"); } where.append(")"); } if (!CollectionUtils.isEmpty(this.ands)) { for (final SubCriteria and : this.ands) { if (first) { first = false; } else { where.append(" AND "); } where.append(and.getWhere().getSql(false)); values.addAll(and.getWhere().getValues()); } } if (!CollectionUtils.isEmpty(this.ors)) { for (final SubCriteria or : this.ors) { if (first) { first = false; } else { where.append(" OR "); } where.append(or.getWhere().getSql(false)); values.addAll(or.getWhere().getValues()); } } if (!CollectionUtils.isEmpty(this.gts)) { for (final NameValuePair<Number> gt : this.gts) { if (first) { first = false; } else { where.append(" AND "); } where.append("`"); where.append(gt.getName()); where.append("`"); where.append(" > "); where.append(gt.getValue()); } } return new Where(where.toString() + ")", values); } /** * Adds a "greater than" clause to the criteria. * * @param field * The field to query on. * @param value * The value to be greater than. * @return SubCriteria instance the method was invoked on (for chaining). */ public SubCriteria gt(final String field, final Number value) { AjahUtils.requireParam(field, "field"); AjahUtils.requireParam(value, "value"); if (this.gts == null) { this.gts = new ArrayList<>(); } this.gts.add(new NameValuePair<>(field, value)); return this; } /** * A subclause, included as an OR * * @param subCriteria * The subCriteria to include * @return Criteria instance the method was invoked on (for chaining). */ public SubCriteria or(final SubCriteria subCriteria) { AjahUtils.requireParam(subCriteria, "field"); if (this.ors == null) { this.ors = new ArrayList<>(); } this.ors.add(subCriteria); return this; } /** * A LIKE field match included as an OR. Uses the query as-is (i.e. add your * own wildcards). * * @param field * The field to match * @param pattern * The pattern the field must match. * @return SubCriteria instance the method was invoked on (for chaining). */ public SubCriteria orLike(final String field, final String pattern) { AjahUtils.requireParam(field, "field"); AjahUtils.requireParam(pattern, "pattern"); if (this.orLikes == null) { this.orLikes = new ArrayList<>(); } this.orLikes.add(new NameValuePair<>(field, pattern)); return this; } }