/*
This file is part of Cyclos (www.cyclos.org).
A project of the Social Trade Organisation (www.socialtrade.org).
Cyclos is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
Cyclos 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 General Public License for more details.
You should have received a copy of the GNU General Public License
along with Cyclos; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
package nl.strohalm.cyclos.utils.hibernate;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Map;
import nl.strohalm.cyclos.dao.FetchDAO;
import nl.strohalm.cyclos.dao.customizations.CustomFieldPossibleValueDAO;
import nl.strohalm.cyclos.entities.customization.fields.CustomField;
import nl.strohalm.cyclos.entities.customization.fields.CustomFieldPossibleValue;
import nl.strohalm.cyclos.entities.customization.fields.CustomFieldValue;
import nl.strohalm.cyclos.utils.StringHelper;
import nl.strohalm.cyclos.utils.access.LoggedUser;
import nl.strohalm.cyclos.utils.conversion.IdConverter;
import org.apache.commons.lang.StringUtils;
/**
* Helper class used to handle custom fields
* @author luis
*/
public class HibernateCustomFieldHandler {
private FetchDAO fetchDao;
private CustomFieldPossibleValueDAO customFieldPossibleValueDao;
/**
* Appends the custom field values on a query. Should be invoked when building the where part of the query
* @param hql The current HQL buffer
* @param values The custom field values used to filter
*/
public void appendConditions(final StringBuilder hql, final Map<String, Object> namedParameters, final Collection<? extends CustomFieldValue> values) {
if (values == null || values.isEmpty()) {
return;
}
for (final CustomFieldValue fieldValue : values) {
CustomField field = fieldValue.getField();
if (field == null) {
continue;
}
field = fetchDao.fetch(field);
String value = fieldValue.getValue();
// Remove any manually entered '%'
value = StringUtils.trimToNull(StringUtils.replace(value, "%", ""));
if (value == null) {
continue;
}
final String alias = alias(field);
final String fieldParam = "field_" + alias;
final String valueParam = "value_" + alias;
hql.append(" and ").append(alias).append(".field = :").append(fieldParam);
namedParameters.put(fieldParam, field);
if (LoggedUser.hasUser() && !LoggedUser.isAdministrator()) {
if (field.getNature() == CustomField.Nature.MEMBER) {
// Exclude hidden fields
hql.append(" and ").append(alias).append(".hidden <> true");
}
}
// Check the field type
switch (field.getType()) {
case STRING:
if (StringUtils.isNotEmpty(field.getPattern())) {
// Remove the mask and consider the value as matching exactly
value = StringHelper.removeMask(field.getPattern(), value, false);
hql.append(" and ").append(alias).append(".stringValue like :").append(valueParam);
namedParameters.put(valueParam, value);
} else {
// Use a like expression
hql.append(" and ").append(alias).append(".stringValue like :").append(valueParam);
namedParameters.put(valueParam, StringUtils.trimToEmpty(value) + "%");
}
break;
case BOOLEAN:
if (Boolean.parseBoolean(value)) {
hql.append(" and ").append(alias).append(".stringValue = :" + valueParam);
} else {
hql.append(" and ").append(alias).append(".stringValue <> :" + valueParam);
}
namedParameters.put(valueParam, "true");
break;
case ENUMERATED:
boolean byName = true;
if (StringUtils.containsOnly(value, "0123456789,")) {
// Try by id
try {
final Collection<CustomFieldPossibleValue> possibleValues = new ArrayList<CustomFieldPossibleValue>();
final String[] possibleValueIds = StringUtils.split(value, ',');
for (final String idAsString : possibleValueIds) {
final CustomFieldPossibleValue possibleValue = customFieldPossibleValueDao.load(Long.valueOf(idAsString));
if (!possibleValue.getField().equals(field)) {
throw new Exception();
}
possibleValues.add(possibleValue);
}
byName = false;
hql.append(" and ").append(alias).append(".possibleValue in (:").append(valueParam).append(')');
namedParameters.put(valueParam, possibleValues);
} catch (final Exception e) {
// Possible value not found by id - next try by name
}
}
if (byName) {
hql.append(" and ").append(alias).append(".possibleValue.value = :").append(valueParam);
namedParameters.put(valueParam, value);
}
break;
case MEMBER:
Long memberId = null;
if (fieldValue.getMemberValue() != null) {
memberId = fieldValue.getMemberValue().getId();
} else {
memberId = IdConverter.instance().valueOf(value);
}
if (memberId != null) {
hql.append(" and ").append(alias).append(".memberValue.id = :").append(valueParam);
namedParameters.put(valueParam, memberId);
}
break;
default:
hql.append(" and ").append(alias).append(".stringValue = :").append(valueParam);
namedParameters.put(valueParam, value);
break;
}
}
}
/**
* Appends the inner joins for each custom field. Should be invoked when building the from part of the query.
* @param hql The current HQL buffer
* @param fieldValuesPath The path on the query for the custom fields value collection
* @param values The custom field values used to filter
*/
public void appendJoins(final StringBuilder hql, final String fieldValuesPath, final Collection<? extends CustomFieldValue> values) {
if (values == null || values.isEmpty()) {
return;
}
for (final CustomFieldValue fieldValue : values) {
CustomField field = fieldValue.getField();
if (field == null) {
continue;
}
String value = fieldValue.getValue();
// Remove any manually entered '%'
value = StringUtils.trimToNull(StringUtils.replace(value, "%", ""));
if (value == null) {
continue;
}
field = fetchDao.fetch(field);
hql.append(" inner join ").append(fieldValuesPath).append(' ').append(alias(field));
}
}
public void setCustomFieldPossibleValueDao(final CustomFieldPossibleValueDAO customFieldPossibleValueDao) {
this.customFieldPossibleValueDao = customFieldPossibleValueDao;
}
public void setFetchDao(final FetchDAO fetchDao) {
this.fetchDao = fetchDao;
}
private String alias(final CustomField field) {
return "fv_" + field.getId();
}
}