001: /*
002: Mdarad-Toolobox is a collection of tools for Architected RAD
003: (Rapid Application Development) based on an MDA approach.
004: The toolbox contains frameworks and generators for many environments
005: (JAVA, J2EE, Hibernate, .NET, C++, etc.) which allow to generate
006: applications from a design Model
007: Copyright (C) 2004-2005 Elapse Technologies Inc.
008:
009: This library is free software; you can redistribute it and/or
010: modify it under the terms of the GNU General Public
011: License as published by the Free Software Foundation; either
012: version 2.1 of the License, or (at your option) any later version.
013:
014: This library is distributed in the hope that it will be useful,
015: but WITHOUT ANY WARRANTY; without even the implied warranty of
016: MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
017: General Public License for more details.
018:
019: You should have received a copy of the GNU General Public
020: License along with this library; if not, write to the Free Software
021: Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
022: */
023: package org.mdarad.framework.expr;
024:
025: import java.util.Collection;
026: import java.util.Iterator;
027:
028: import org.hibernate.criterion.DetachedCriteria;
029: import org.hibernate.criterion.Property;
030: import org.apache.commons.lang.StringUtils;
031:
032: /**
033: * This class is used to translate criteria objects from the MDARAD framework
034: * to criteria objects from the Hibernate persistence framework
035: * (http://www.hibernate.org). To use this translator, instanciated from
036: * the class {@link CriteriaTranslator}
037: *
038: * @author Philippe Brouillette
039: * @version 1.0
040: */
041: public class HibernateCriteriaTranslator extends CriteriaTranslator {
042:
043: /**
044: * Method that returns the expression statement as a string. Usually, it will
045: * returns a SQL statement as a string.
046: *
047: * @param entity persistence type
048: * @param criteria collection of the criteria
049: * @return The string expression representing the statement (SQL, XML, etc)
050: */
051: public String getExpressionStatement(Class entity,
052: Collection criteria) {
053:
054: String className = entity.getName().substring(
055: entity.getName().lastIndexOf('.') + 1,
056: entity.getName().length());
057: String lcClassName = StringUtils.uncapitalise(className);
058:
059: //FROM CLAUSE
060: StringBuffer hqlStatement = new StringBuffer("from ").append(
061: className).append(" as ").append(lcClassName).append(
062: "_alias");
063:
064: //If one criterion is of a different entity, there is a need for a localized class join
065: Criterion localizedCriterion = getFirstLocalizedCriterion(
066: criteria, entity);
067: if (localizedCriterion != null) {
068: String criterionClassName = localizedCriterion.getEntity()
069: .getName().substring(
070: localizedCriterion.getEntity().getName()
071: .lastIndexOf('.') + 1,
072: localizedCriterion.getEntity().getName()
073: .length());
074: String criterionLCClassName = StringUtils
075: .uncapitalise(criterionClassName);
076: hqlStatement.append(" join ").append(lcClassName).append(
077: "_alias").append(".");
078: hqlStatement.append(lcClassName)
079: .append("Localizations as ").append(
080: criterionLCClassName);
081: }
082:
083: //WHERE CLAUSE
084: Iterator i = criteria.iterator();
085: if (i.hasNext()) {
086: hqlStatement.append(" where ");
087: }
088: while (i.hasNext()) {
089: Criterion criterion = (Criterion) i.next();
090: String criterionClassName = className;
091: String criterionLCClassName = lcClassName + "_alias";
092:
093: //Only use a different class name if the entity is not derived from the criterion's entity class
094: try {
095: if (!criterion.getEntity().isInstance(
096: entity.newInstance())) {
097: criterionClassName = criterion.getEntity()
098: .getName().substring(
099: criterion.getEntity().getName()
100: .lastIndexOf('.') + 1,
101: criterion.getEntity().getName()
102: .length());
103: criterionLCClassName = StringUtils
104: .uncapitalise(criterionClassName);
105: }
106: } catch (InstantiationException e) {
107: throw new IllegalArgumentException();
108: } catch (IllegalAccessException e) {
109: throw new IllegalArgumentException();
110: }
111:
112: if (criterion != null && criterion.getValue() != null
113: && criterion.getValue().toString() != "") {
114: }
115: OperatorType operator = criterion.getOperator();
116: String property = criterion.getProperty();
117:
118: // add the operator for each type
119: // equal
120: if (operator.equals(OperatorTypes.EQUAL)) {
121: hqlStatement.append(criterionLCClassName).append(".")
122: .append(property).append(" = ").append(
123: criterion.getValue());
124: // greater than
125: } else if (operator.equals(OperatorTypes.GREATER_THAN)) {
126: hqlStatement.append(criterionLCClassName).append(".")
127: .append(property).append(" > ").append(
128: criterion.getValue());
129: // greater than or equal
130: } else if (operator
131: .equals(OperatorTypes.GREATER_THAN_OR_EQUAL)) {
132: hqlStatement.append(criterionLCClassName).append(".")
133: .append(property).append(" >= ").append(
134: criterion.getValue());
135: // lower than
136: } else if (operator.equals(OperatorTypes.LOWER_THAN)) {
137: hqlStatement.append(criterionLCClassName).append(".")
138: .append(property).append(" < ").append(
139: criterion.getValue());
140: // lower thn or equal
141: } else if (operator
142: .equals(OperatorTypes.LOWER_THAN_OR_EQUAL)) {
143: hqlStatement.append(criterionLCClassName).append(".")
144: .append(property).append(" <= ").append(
145: criterion.getValue());
146: // in operator
147: } else if (operator.equals(OperatorTypes.IN)) {
148: hqlStatement.append(criterionLCClassName).append(".")
149: .append(property).append(" in '").append(
150: criterion.getValue()).append("'");
151: // like operator
152: } else if (operator.equals(OperatorTypes.LIKE)) {
153: hqlStatement.append(criterionLCClassName).append(".")
154: .append(property).append(" like '").append(
155: criterion.getValue()).append("'");
156: // start with (like) operator
157: } else if (operator.equals(OperatorTypes.START_WITH)) {
158: hqlStatement.append(criterionLCClassName).append(".")
159: .append(property).append(" like '").append(
160: criterion.getValue()).append("%'");
161: // end with (like)operator
162: } else if (operator.equals(OperatorTypes.END_WITH)) {
163: hqlStatement.append(criterionLCClassName).append(".")
164: .append(property).append(" like '%").append(
165: criterion.getValue()).append("'");
166: }
167:
168: //Check if it is the last of the list
169: if (i.hasNext()) {
170: hqlStatement.append(" and ");
171: }
172: }
173:
174: //If one criterion is of a different entity, we need to set the index of the locale of the localized entity
175: if (localizedCriterion != null) {
176: String criterionClassName = localizedCriterion.getEntity()
177: .getName().substring(
178: localizedCriterion.getEntity().getName()
179: .lastIndexOf('.') + 1,
180: localizedCriterion.getEntity().getName()
181: .length());
182: String criterionLCClassName = StringUtils
183: .uncapitalise(criterionClassName);
184: hqlStatement.append(" and index(").append(
185: criterionLCClassName).append(") ='").append(
186: localizedCriterion.getLocale()).append("' ");
187: }
188:
189: return hqlStatement.toString();
190: }
191:
192: private Criterion getFirstLocalizedCriterion(Collection criteria,
193: Class entity) {
194: Iterator i = criteria.iterator();
195: while (i.hasNext()) {
196: Criterion criterion = (Criterion) i.next();
197:
198: //Check if this criterion is on an associated class (if so it is for localization)
199: try {
200: if (!criterion.getEntity().isInstance(
201: entity.newInstance())) {
202: return criterion;
203: }
204: } catch (InstantiationException e) {
205: throw new IllegalArgumentException();
206: } catch (IllegalAccessException e) {
207: throw new IllegalArgumentException();
208: }
209: }
210: return null;
211: }
212:
213: /**
214: * @deprecated Do not use for now. The criterion of hibernate are not yet ready for this
215: *
216: * Method that returns the expression statement as an object. Usually, it will
217: * returns a SQL statement as a object from the persistence framework. This method returns
218: * DetachedCriteria object from the Hibernate Framework.
219: *
220: * @param entity persistence type
221: * @param criteria collection of the criteria
222: * @return Return the expression statement as an object.
223: */
224: public Object getCriterionObject(Class entity, Collection criteria) {
225:
226: DetachedCriteria query = DetachedCriteria.forClass(entity);
227:
228: // loop for all the criteria in the collection
229: for (Iterator i = criteria.iterator(); i.hasNext();) {
230: Criterion criterion = (Criterion) i.next();
231:
232: if (criterion != null && criterion.getValue() != null
233: && criterion.getValue().toString() != "") {
234: OperatorType operator = criterion.getOperator();
235: Property property = Property.forName(criterion
236: .getProperty());
237: Object value = criterion.getValue();
238: // add the operator for each type
239: // equal
240: if (operator.equals(OperatorTypes.EQUAL)) {
241: query.add(property.eq(value));
242: // greater than
243: } else if (operator.equals(OperatorTypes.GREATER_THAN)) {
244: query.add(property.gt(value));
245: // greater than or equal
246: } else if (operator
247: .equals(OperatorTypes.GREATER_THAN_OR_EQUAL)) {
248: query.add(property.ge(value));
249: // lower than
250: } else if (operator.equals(OperatorTypes.LOWER_THAN)) {
251: query.add(property.lt(value));
252: // lower thn or equal
253: } else if (operator
254: .equals(OperatorTypes.LOWER_THAN_OR_EQUAL)) {
255: query.add(property.le(value));
256: // in operator
257: } else if (operator.equals(OperatorTypes.IN)) {
258: query.add(property.in((Object[]) value));
259: // like operator
260: } else if (operator.equals(OperatorTypes.LIKE)) {
261: query.add(property.like(value));
262: // start with (like) operator
263: } else if (operator.equals(OperatorTypes.START_WITH)) {
264: query.add(property.like(value + "%"));
265: // end with (like)operator
266: } else if (operator.equals(OperatorTypes.END_WITH)) {
267: query.add(property.like("%" + value));
268: }
269: }
270: }
271:
272: return query;
273: }
274: }
|