Java tutorial
/** * Copyright 2008 Autentia Real Business Solutions S.L. This file is part of Autentia WUIJA. Autentia WUIJA is free * software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as * published by the Free Software Foundation, version 3 of the License. Autentia WUIJA is distributed in the hope that * it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A * PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of * the GNU Lesser General Public License along with Autentia WUIJA. If not, see <http://www.gnu.org/licenses/>. */ package com.autentia.wuija.persistence.criteria; import java.util.ArrayList; import java.util.List; import org.hibernate.criterion.Restrictions; /** * Esta clase representa simplemente una agrupacin de varios {@link Criterion}. Todos los {@link Criterion} dentro de * esta clase se relacionan con el mismo operador lgico: AND, OR (AND es el operador por defecto). * <p> * Se definir una clase hija {@link Junction} que implementa la interfaz {@link Criterion}, de manera que gracias a * esta clase {@link Junction} se pueden componer consultas combinando varios operadores AND y OR (cada {@link Junction} * tiene su propio operador logico, pero como un {@link Junction} se puede meter dentro de otro, se pueden ir * combinando). * * @see Criterion */ public abstract class Criteria implements Cloneable { protected static final MatchMode DEFAULT_MATCH_MODE = MatchMode.ALL; /** Lista de {@link Criterion} que forman parte de este junction. */ protected List<Criterion> criterions = new ArrayList<Criterion>(); /** Indica si hay que hacer un AND o un OR cont todos los {@link Criterion} de este junction. */ protected MatchMode matchMode; /** * Crea una nueva instancia de esta clase. Donde el operador a usar entre los criterion sern un AND. * * @param matchMode el {@link MatchMode} para los criterios. */ protected Criteria() { this(DEFAULT_MATCH_MODE); } /** * Crea una nueva instancia de esta clase. * * @param matchMode el {@link MatchMode} para los criterios. */ protected Criteria(MatchMode matchMode) { this.matchMode = matchMode; } /** * Aade un nuevo {@link Criterion}. * * @param criterionToAdd {@link Criterion} que hay que aadir. */ public void add(Criterion criterionToAdd) { criterions.add(criterionToAdd); } /** * Aade todos los {@link Criterion} que se pasan como parmetro. * * @param criterionsToAdd lista de {@link Criterion} que hay que aadir. */ public void add(List<Criterion> criterionsToAdd) { criterions.addAll(criterionsToAdd); } void addHqlRestrictions(String alias, StringBuilder restrictionsHql, List<Object> paramValues) { if (!criterions.isEmpty()) { boolean atLeastOneOperand = false; restrictionsHql.append("("); for (Criterion criterion : criterions) { final int restrictionsHqlLength = restrictionsHql.length(); criterion.toHql(alias, restrictionsHql, paramValues); if (restrictionsHqlLength != restrictionsHql.length()) { // Slo aadimos el operador si el criterion a aportado algo a la consulta. // Por ejemplo, si la property de un SimpleExpressin es null, no aporta nada a la conulta. // En este caso no aadimos el operador porque ya tenemos el operador del ciclo anterior. restrictionsHql.append(matchMode.toHql()); atLeastOneOperand = true; } } if (atLeastOneOperand) { removeLastOperand(restrictionsHql); restrictionsHql.append(")"); } else { // Como no se ha aadido nada, quitamos el parentesis de apertura restrictionsHql.setLength(restrictionsHql.length() - 1); } } } /** * Elimina todos los {@link Criterion} de este junction. */ public void clearCriterions() { criterions.clear(); } /** * Clona este objeto en profundidad, es decir, tambin clona todos los {@link Criterion} de esta clase. * * @return una nueva instancia, clon en profundidad de este objeto. */ @Override public Object clone() throws CloneNotSupportedException { final Criteria clonedCriteria = (Criteria) super.clone(); clonedCriteria.criterions = cloneCriterions(this.criterions); return clonedCriteria; } private List<Criterion> cloneCriterions(List<Criterion> criterionsToClone) { final List<Criterion> clonedCriterions = new ArrayList<Criterion>(criterionsToClone.size()); for (Criterion criterion : criterionsToClone) { try { clonedCriterions.add((Criterion) criterion.clone()); } catch (CloneNotSupportedException e) { throw new IllegalArgumentException("Cannot clone " + criterion + ". The class " + criterion.getClass().getName() + " have to be clonable", e); } } return clonedCriterions; } protected org.hibernate.criterion.Junction createHibernateJunction() { switch (matchMode) { case ALL: return Restrictions.conjunction(); case ANY: return Restrictions.disjunction(); default: throw new UnsupportedOperationException("Match mode " + matchMode + " is not supported."); } } /** * Devuelve los {@link Criterion} de este junction. * * @return los {@link Criterion} de este junction. */ public List<Criterion> getCriterions() { return criterions; } /** * Devuelve el {@link MatchMode} de este junction. * * @return el {@link MatchMode} de este junction. */ public MatchMode getMatchMode() { return matchMode; } /** * Quita el ltimo {@link Criterion} que se aadi. */ public void removeCriterion() { criterions.remove(criterions.size() - 1); } private void removeLastOperand(StringBuilder restrictionsHql) { restrictionsHql.setLength(restrictionsHql.length() - matchMode.toHql().length()); } public void setCriteria(Criteria criteria) { this.matchMode = criteria.matchMode; this.criterions = cloneCriterions(criteria.criterions); } /** * Fija el {@link MatchMode} de este junction. * * @param matchMode el {@link MatchMode} de este junction. */ public void setMatchMode(MatchMode matchMode) { this.matchMode = matchMode; } }