/*
* #%L
* BroadleafCommerce Open Admin Platform
* %%
* Copyright (C) 2009 - 2013 Broadleaf Commerce
* %%
* 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.
* #L%
*/
package org.broadleafcommerce.openadmin.server.service.persistence.module.provider;
import org.apache.commons.collections.CollectionUtils;
import org.apache.commons.lang.StringUtils;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.broadleafcommerce.common.admin.domain.AdminMainEntity;
import org.broadleafcommerce.common.extension.ExtensionResultHolder;
import org.broadleafcommerce.common.extension.ExtensionResultStatusType;
import org.broadleafcommerce.common.money.Money;
import org.broadleafcommerce.common.presentation.client.ForeignKeyRestrictionType;
import org.broadleafcommerce.common.presentation.client.PersistencePerspectiveItemType;
import org.broadleafcommerce.common.presentation.client.SupportedFieldType;
import org.broadleafcommerce.openadmin.dto.BasicFieldMetadata;
import org.broadleafcommerce.openadmin.dto.FieldMetadata;
import org.broadleafcommerce.openadmin.dto.FilterAndSortCriteria;
import org.broadleafcommerce.openadmin.dto.ForeignKey;
import org.broadleafcommerce.openadmin.dto.Property;
import org.broadleafcommerce.openadmin.server.service.persistence.PersistenceException;
import org.broadleafcommerce.openadmin.server.service.persistence.module.EmptyFilterValues;
import org.broadleafcommerce.openadmin.server.service.persistence.module.FieldManager;
import org.broadleafcommerce.openadmin.server.service.persistence.module.FieldNotAvailableException;
import org.broadleafcommerce.openadmin.server.service.persistence.module.criteria.FieldPath;
import org.broadleafcommerce.openadmin.server.service.persistence.module.criteria.FilterMapping;
import org.broadleafcommerce.openadmin.server.service.persistence.module.criteria.Restriction;
import org.broadleafcommerce.openadmin.server.service.persistence.module.criteria.RestrictionType;
import org.broadleafcommerce.openadmin.server.service.persistence.module.criteria.predicate.IsNotNullPredicateProvider;
import org.broadleafcommerce.openadmin.server.service.persistence.module.criteria.predicate.IsNullPredicateProvider;
import org.broadleafcommerce.openadmin.server.service.persistence.module.provider.extension.BasicFieldPersistenceProviderExtensionManager;
import org.broadleafcommerce.openadmin.server.service.persistence.module.provider.request.AddSearchMappingRequest;
import org.broadleafcommerce.openadmin.server.service.persistence.module.provider.request.ExtractValueRequest;
import org.broadleafcommerce.openadmin.server.service.persistence.module.provider.request.PopulateValueRequest;
import org.broadleafcommerce.openadmin.server.service.type.FieldProviderResponse;
import org.hibernate.Session;
import org.springframework.context.annotation.Scope;
import org.springframework.stereotype.Component;
import java.io.Serializable;
import java.lang.reflect.Field;
import java.math.BigDecimal;
import java.sql.Timestamp;
import java.text.DecimalFormat;
import java.util.Arrays;
import java.util.Calendar;
import java.util.Collection;
import java.util.Comparator;
import java.util.Date;
import java.util.List;
import java.util.Map;
import javax.annotation.Resource;
/**
* @author Jeff Fischer
*/
@Component("blBasicFieldPersistenceProvider")
@Scope("prototype")
public class BasicFieldPersistenceProvider extends FieldPersistenceProviderAdapter {
@Resource(name = "blBasicFieldPersistenceProviderExtensionManager")
protected BasicFieldPersistenceProviderExtensionManager extensionManager;
protected static final Log LOG = LogFactory.getLog(BasicFieldPersistenceProvider.class);
protected boolean canHandlePersistence(PopulateValueRequest populateValueRequest, Serializable instance) {
BasicFieldMetadata metadata = populateValueRequest.getMetadata();
Property property = populateValueRequest.getProperty();
//don't handle map fields here - we'll get them in a separate provider
boolean response = detectBasicType(metadata, property);
if (!response) {
//we'll allow this provider to handle money filter mapping for persistence
response = metadata.getFieldType() == SupportedFieldType.MONEY;
}
return response;
}
protected boolean detectBasicType(FieldMetadata md, Property property) {
if (!(md instanceof BasicFieldMetadata)) {
return false;
}
BasicFieldMetadata metadata = (BasicFieldMetadata) md;
return (metadata.getFieldType() == SupportedFieldType.BOOLEAN ||
metadata.getFieldType() == SupportedFieldType.DATE ||
metadata.getFieldType() == SupportedFieldType.INTEGER ||
metadata.getFieldType() == SupportedFieldType.DECIMAL ||
metadata.getFieldType() == SupportedFieldType.EMAIL ||
metadata.getFieldType() == SupportedFieldType.FOREIGN_KEY ||
metadata.getFieldType() == SupportedFieldType.ADDITIONAL_FOREIGN_KEY ||
metadata.getFieldType() == SupportedFieldType.STRING ||
metadata.getFieldType() == SupportedFieldType.CODE ||
metadata.getFieldType() == SupportedFieldType.HTML ||
metadata.getFieldType() == SupportedFieldType.HTML_BASIC ||
metadata.getFieldType() == SupportedFieldType.MONEY ||
metadata.getFieldType() == SupportedFieldType.ASSET_URL ||
metadata.getFieldType() == SupportedFieldType.ID) &&
(property == null ||
!property.getName().contains(FieldManager.MAPFIELDSEPARATOR));
}
protected boolean detectAdditionalSearchTypes(FieldMetadata md, Property property) {
if (!(md instanceof BasicFieldMetadata)) {
return false;
}
BasicFieldMetadata metadata = (BasicFieldMetadata) md;
return (metadata.getFieldType() == SupportedFieldType.BROADLEAF_ENUMERATION ||
metadata.getFieldType() == SupportedFieldType.EXPLICIT_ENUMERATION ||
metadata.getFieldType() == SupportedFieldType.DATA_DRIVEN_ENUMERATION) &&
(property == null || !property.getName().contains(FieldManager.MAPFIELDSEPARATOR));
}
protected boolean canHandleExtraction(ExtractValueRequest extractValueRequest, Property property) {
BasicFieldMetadata metadata = extractValueRequest.getMetadata();
//don't handle map fields here - we'll get them in a separate provider
return detectBasicType(metadata, property);
}
protected boolean canHandleSearchMapping(AddSearchMappingRequest addSearchMappingRequest,
List<FilterMapping> filterMappings) {
FieldMetadata metadata = addSearchMappingRequest.getMergedProperties().get
(addSearchMappingRequest.getPropertyName());
Property property = null;
//don't handle map fields here - we'll get them in a separate provider
boolean response = detectBasicType(metadata, property) || detectAdditionalSearchTypes(metadata, property);
return response;
}
@Override
public FieldProviderResponse populateValue(PopulateValueRequest populateValueRequest, Serializable instance) {
if (!canHandlePersistence(populateValueRequest, instance)) {
return FieldProviderResponse.NOT_HANDLED;
}
boolean dirty = false;
try {
Property prop = populateValueRequest.getProperty();
Object origValue = populateValueRequest.getFieldManager().getFieldValue(instance, prop.getName());
switch (populateValueRequest.getMetadata().getFieldType()) {
case BOOLEAN:
boolean v = Boolean.valueOf(populateValueRequest.getRequestedValue());
prop.setOriginalValue(String.valueOf(origValue));
prop.setOriginalDisplayValue(prop.getOriginalValue());
try {
dirty = checkDirtyState(populateValueRequest, instance, v);
populateValueRequest.getFieldManager().setFieldValue(instance,
populateValueRequest.getProperty().getName(), v);
} catch (IllegalArgumentException e) {
char c = v ? 'Y' : 'N';
dirty = checkDirtyState(populateValueRequest, instance, c);
populateValueRequest.getFieldManager().setFieldValue(instance,
populateValueRequest.getProperty().getName(), c);
}
break;
case DATE:
Date date = (Date) populateValueRequest.getFieldManager().getFieldValue(instance, populateValueRequest.getProperty().getName());
String oldValue = null;
if (date != null) {
oldValue = populateValueRequest.getDataFormatProvider().getSimpleDateFormatter().format(date);
}
prop.setOriginalValue(oldValue);
prop.setOriginalDisplayValue(prop.getOriginalValue());
dirty = !StringUtils.equals(oldValue, populateValueRequest.getRequestedValue());
populateValueRequest.getFieldManager().setFieldValue(instance,
populateValueRequest.getProperty().getName(), populateValueRequest.getDataFormatProvider().
getSimpleDateFormatter().parse(populateValueRequest.getRequestedValue()));
break;
case DECIMAL:
if (origValue != null) {
prop.setOriginalValue(String.valueOf(origValue));
prop.setOriginalDisplayValue(prop.getOriginalValue());
}
if (BigDecimal.class.isAssignableFrom(populateValueRequest.getReturnType())) {
DecimalFormat format = populateValueRequest.getDataFormatProvider().getDecimalFormatter();
format.setParseBigDecimal(true);
BigDecimal val = (BigDecimal) format.parse(populateValueRequest.getRequestedValue());
dirty = checkDirtyState(populateValueRequest, instance, val);
populateValueRequest.getFieldManager().setFieldValue(instance,
populateValueRequest.getProperty().getName(), val);
format.setParseBigDecimal(false);
} else {
Double val = populateValueRequest.getDataFormatProvider().getDecimalFormatter().parse(populateValueRequest.getRequestedValue()).doubleValue();
dirty = checkDirtyState(populateValueRequest, instance, val);
populateValueRequest.getFieldManager().setFieldValue(instance, populateValueRequest.getProperty().getName(), val);
}
break;
case MONEY:
if (origValue != null) {
prop.setOriginalValue(String.valueOf(origValue));
prop.setOriginalDisplayValue(prop.getOriginalValue());
}
if (BigDecimal.class.isAssignableFrom(populateValueRequest.getReturnType())) {
DecimalFormat format = populateValueRequest.getDataFormatProvider().getDecimalFormatter();
format.setParseBigDecimal(true);
BigDecimal val = (BigDecimal) format.parse(populateValueRequest.getRequestedValue());
dirty = checkDirtyState(populateValueRequest, instance, val);
populateValueRequest.getFieldManager()
.setFieldValue(instance, populateValueRequest.getProperty().getName(), val);
format.setParseBigDecimal(true);
} else if (Double.class.isAssignableFrom(populateValueRequest.getReturnType())) {
Double val = populateValueRequest.getDataFormatProvider().getDecimalFormatter().parse(populateValueRequest.getRequestedValue()).doubleValue();
dirty = checkDirtyState(populateValueRequest, instance, val);
LOG.warn("The requested Money field is of type double and could result in a loss of precision." +
" Broadleaf recommends that the type of all Money fields be 'BigDecimal' in order to avoid" +
" this loss of precision that could occur.");
populateValueRequest.getFieldManager().setFieldValue(instance, populateValueRequest.getProperty().getName(), val);
} else {
DecimalFormat format = populateValueRequest.getDataFormatProvider().getDecimalFormatter();
format.setParseBigDecimal(true);
BigDecimal val = (BigDecimal) format.parse(populateValueRequest.getRequestedValue());
dirty = checkDirtyState(populateValueRequest, instance, val);
populateValueRequest.getFieldManager().setFieldValue(instance, populateValueRequest.getProperty().getName(), new Money(val));
format.setParseBigDecimal(false);
}
break;
case INTEGER:
if (origValue != null) {
prop.setOriginalValue(String.valueOf(origValue));
prop.setOriginalDisplayValue(prop.getOriginalValue());
}
if (int.class.isAssignableFrom(populateValueRequest.getReturnType()) || Integer.class
.isAssignableFrom(populateValueRequest.getReturnType())) {
dirty = checkDirtyState(populateValueRequest, instance, Integer.valueOf(populateValueRequest.getRequestedValue()));
populateValueRequest.getFieldManager().setFieldValue(instance,
populateValueRequest.getProperty().getName(), Integer.valueOf(populateValueRequest
.getRequestedValue()));
} else if (byte.class.isAssignableFrom(populateValueRequest.getReturnType()) || Byte.class
.isAssignableFrom(populateValueRequest.getReturnType())) {
dirty = checkDirtyState(populateValueRequest, instance, Byte.valueOf(populateValueRequest.getRequestedValue()));
populateValueRequest.getFieldManager().setFieldValue(instance,
populateValueRequest.getProperty().getName(), Byte.valueOf(populateValueRequest
.getRequestedValue()));
} else if (short.class.isAssignableFrom(populateValueRequest.getReturnType()) || Short.class
.isAssignableFrom(populateValueRequest.getReturnType())) {
dirty = checkDirtyState(populateValueRequest, instance, Short.valueOf(populateValueRequest.getRequestedValue()));
populateValueRequest.getFieldManager().setFieldValue(instance,
populateValueRequest.getProperty().getName(), Short.valueOf(populateValueRequest
.getRequestedValue()));
} else if (long.class.isAssignableFrom(populateValueRequest.getReturnType()) || Long.class
.isAssignableFrom(populateValueRequest.getReturnType())) {
dirty = checkDirtyState(populateValueRequest, instance, Long.valueOf(populateValueRequest.getRequestedValue()));
populateValueRequest.getFieldManager().setFieldValue(instance,
populateValueRequest.getProperty().getName(), Long.valueOf(populateValueRequest
.getRequestedValue()));
}
break;
case CODE:
// **NOTE** We want to fall through in this case, do not break.
setNonDisplayableValues(populateValueRequest);
case STRING:
case HTML_BASIC:
case HTML:
case EMAIL:
if (origValue != null) {
prop.setOriginalValue(String.valueOf(origValue));
prop.setOriginalDisplayValue(prop.getOriginalValue());
}
dirty = checkDirtyState(populateValueRequest, instance, populateValueRequest.getRequestedValue());
populateValueRequest.getFieldManager().setFieldValue(instance, populateValueRequest.getProperty()
.getName(), populateValueRequest.getRequestedValue());
break;
case FOREIGN_KEY: {
if (origValue != null) {
prop.setOriginalValue(String.valueOf(origValue));
}
Serializable foreignInstance;
if (StringUtils.isEmpty(populateValueRequest.getRequestedValue())) {
foreignInstance = null;
} else {
if (SupportedFieldType.INTEGER.toString().equals(populateValueRequest.getMetadata()
.getSecondaryType().toString())) {
foreignInstance = populateValueRequest.getPersistenceManager().getDynamicEntityDao()
.retrieve(Class.forName(populateValueRequest.getMetadata().getForeignKeyClass()),
Long.valueOf(populateValueRequest.getRequestedValue()));
} else {
foreignInstance = populateValueRequest.getPersistenceManager().getDynamicEntityDao()
.retrieve(Class.forName(populateValueRequest.getMetadata().getForeignKeyClass()),
populateValueRequest.getRequestedValue());
}
}
if (Collection.class.isAssignableFrom(populateValueRequest.getReturnType())) {
Collection collection;
try {
collection = (Collection) populateValueRequest.getFieldManager().getFieldValue(instance,
populateValueRequest.getProperty().getName());
} catch (FieldNotAvailableException e) {
throw new IllegalArgumentException(e);
}
if (!collection.contains(foreignInstance)) {
collection.add(foreignInstance);
dirty = true;
}
} else if (Map.class.isAssignableFrom(populateValueRequest.getReturnType())) {
throw new IllegalArgumentException("Map structures are not supported for foreign key fields.");
} else {
dirty = checkDirtyState(populateValueRequest, instance, foreignInstance);
populateValueRequest.getFieldManager().setFieldValue(instance,
populateValueRequest.getProperty().getName(), foreignInstance);
}
break;
}
case ADDITIONAL_FOREIGN_KEY: {
Serializable foreignInstance;
if (StringUtils.isEmpty(populateValueRequest.getRequestedValue())) {
foreignInstance = null;
} else {
if (SupportedFieldType.INTEGER.toString().equals(populateValueRequest.getMetadata()
.getSecondaryType().toString())) {
foreignInstance = populateValueRequest.getPersistenceManager().getDynamicEntityDao()
.retrieve(Class.forName(populateValueRequest.getMetadata().getForeignKeyClass()),
Long.valueOf(populateValueRequest.getRequestedValue()));
} else {
foreignInstance = populateValueRequest.getPersistenceManager().getDynamicEntityDao()
.retrieve(Class.forName(populateValueRequest.getMetadata().getForeignKeyClass()),
populateValueRequest.getRequestedValue());
}
}
// Best guess at grabbing the original display value
String fkProp = populateValueRequest.getMetadata().getForeignKeyDisplayValueProperty();
Object origDispVal = null;
if (origValue != null) {
if (AdminMainEntity.MAIN_ENTITY_NAME_PROPERTY.equals(fkProp)) {
if (origValue instanceof AdminMainEntity) {
origDispVal = ((AdminMainEntity) origValue).getMainEntityName();
}
} else {
origDispVal = populateValueRequest.getFieldManager().getFieldValue(origValue, fkProp);
}
}
if (origDispVal != null) {
prop.setOriginalDisplayValue(String.valueOf(origDispVal));
Session session = populateValueRequest.getPersistenceManager().getDynamicEntityDao().getStandardEntityManager().unwrap(Session.class);
prop.setOriginalValue(String.valueOf(session.getIdentifier(foreignInstance)));
}
if (Collection.class.isAssignableFrom(populateValueRequest.getReturnType())) {
Collection collection;
try {
collection = (Collection) populateValueRequest.getFieldManager().getFieldValue(instance,
populateValueRequest.getProperty().getName());
} catch (FieldNotAvailableException e) {
throw new IllegalArgumentException(e);
}
if (!collection.contains(foreignInstance)) {
collection.add(foreignInstance);
dirty = true;
}
} else if (Map.class.isAssignableFrom(populateValueRequest.getReturnType())) {
throw new IllegalArgumentException("Map structures are not supported for foreign key fields.");
} else {
dirty = checkDirtyState(populateValueRequest, instance, foreignInstance);
populateValueRequest.getFieldManager().setFieldValue(instance,
populateValueRequest.getProperty().getName(), foreignInstance);
}
break;
}
case ID:
if (populateValueRequest.getSetId()) {
switch (populateValueRequest.getMetadata().getSecondaryType()) {
case INTEGER:
dirty = checkDirtyState(populateValueRequest, instance, Long.valueOf(populateValueRequest.getRequestedValue()));
populateValueRequest.getFieldManager().setFieldValue(instance,
populateValueRequest.getProperty().getName(),
Long.valueOf(populateValueRequest.getRequestedValue()));
break;
case STRING:
dirty = checkDirtyState(populateValueRequest, instance, populateValueRequest.getRequestedValue());
populateValueRequest.getFieldManager().setFieldValue(instance,
populateValueRequest.getProperty().getName(),
populateValueRequest.getRequestedValue());
break;
}
}
break;
}
} catch (Exception e) {
throw new PersistenceException(e);
}
populateValueRequest.getProperty().setIsDirty(dirty);
return FieldProviderResponse.HANDLED;
}
@Override
public FieldProviderResponse extractValue(ExtractValueRequest extractValueRequest,
Property property) throws PersistenceException {
if (!canHandleExtraction(extractValueRequest, property)) {
return FieldProviderResponse.NOT_HANDLED;
}
try {
if (extractValueRequest.getRequestedValue() != null) {
String val = null;
if (extractValueRequest.getMetadata().getForeignKeyCollection()) {
((BasicFieldMetadata) property.getMetadata()).setFieldType(extractValueRequest.getMetadata()
.getFieldType());
} else if (extractValueRequest.getMetadata().getFieldType().equals(SupportedFieldType.BOOLEAN) &&
extractValueRequest.getRequestedValue() instanceof Character) {
val = (extractValueRequest.getRequestedValue().equals('Y')) ? "true" : "false";
} else if (Date.class.isAssignableFrom(extractValueRequest.getRequestedValue().getClass())) {
val = extractValueRequest.getDataFormatProvider().getSimpleDateFormatter
().format((Date) extractValueRequest.getRequestedValue());
} else if (Timestamp.class.isAssignableFrom(extractValueRequest.getRequestedValue().getClass())) {
val = extractValueRequest.getDataFormatProvider().getSimpleDateFormatter
().format(new Date(((Timestamp) extractValueRequest.getRequestedValue()).getTime()));
} else if (Calendar.class.isAssignableFrom(extractValueRequest.getRequestedValue().getClass())) {
val = extractValueRequest.getDataFormatProvider().getSimpleDateFormatter
().format(((Calendar) extractValueRequest.getRequestedValue()).getTime());
} else if (Double.class.isAssignableFrom(extractValueRequest.getRequestedValue().getClass())) {
val = extractValueRequest.getDataFormatProvider().getDecimalFormatter().format
(extractValueRequest.getRequestedValue());
} else if (BigDecimal.class.isAssignableFrom(extractValueRequest.getRequestedValue().getClass())) {
BigDecimal decimal = (BigDecimal) extractValueRequest.getRequestedValue();
DecimalFormat format = extractValueRequest.getDataFormatProvider().getDecimalFormatter();
//track all the decimal places in the scale of the BigDecimal - even if they're all zeros
StringBuilder sb = new StringBuilder();
sb.append("0");
if (decimal.scale() > 0) {
sb.append(".");
for (int j = 0; j < decimal.scale(); j++) {
sb.append("0");
}
}
format.applyPattern(sb.toString());
val = format.format(extractValueRequest.getRequestedValue());
} else if (extractValueRequest.getMetadata().getForeignKeyClass() != null) {
try {
val = extractValueRequest.getFieldManager().getFieldValue
(extractValueRequest.getRequestedValue(), extractValueRequest.getMetadata()
.getForeignKeyProperty()).toString();
if (extensionManager != null) {
ExtensionResultHolder<Serializable> resultHolder = new
ExtensionResultHolder<Serializable>();
ExtensionResultStatusType result = extensionManager.getProxy().transformForeignKey
(extractValueRequest, property, resultHolder);
if (ExtensionResultStatusType.NOT_HANDLED != result && resultHolder.getResult() != null) {
val = String.valueOf(resultHolder.getResult());
}
}
//see if there's a name property and use it for the display value
String entityName = null;
if (extractValueRequest.getRequestedValue() instanceof AdminMainEntity) {
entityName = ((AdminMainEntity) extractValueRequest.getRequestedValue())
.getMainEntityName();
}
Object temp = null;
if (!StringUtils.isEmpty(extractValueRequest.getMetadata().getForeignKeyDisplayValueProperty
())) {
String nameProperty = extractValueRequest.getMetadata().getForeignKeyDisplayValueProperty();
try {
temp = extractValueRequest.getFieldManager().getFieldValue(extractValueRequest
.getRequestedValue(), nameProperty);
} catch (FieldNotAvailableException e) {
//do nothing
}
}
if (temp == null && StringUtils.isEmpty(entityName)) {
try {
temp = extractValueRequest.getFieldManager().getFieldValue(extractValueRequest
.getRequestedValue(), "name");
} catch (FieldNotAvailableException e) {
//do nothing
}
}
if (temp != null) {
extractValueRequest.setDisplayVal(temp.toString());
} else if (!StringUtils.isEmpty(entityName)) {
extractValueRequest.setDisplayVal(entityName);
}
} catch (FieldNotAvailableException e) {
throw new IllegalArgumentException(e);
}
} else if (SupportedFieldType.ID == extractValueRequest.getMetadata().getFieldType()) {
val = extractValueRequest.getRequestedValue().toString();
if (extensionManager != null) {
ExtensionResultHolder<Serializable> resultHolder = new
ExtensionResultHolder<Serializable>();
ExtensionResultStatusType result = extensionManager.getProxy().transformId
(extractValueRequest, property, resultHolder);
if (ExtensionResultStatusType.NOT_HANDLED != result && resultHolder.getResult() != null) {
val = String.valueOf(resultHolder.getResult());
}
}
} else {
val = extractValueRequest.getRequestedValue().toString();
}
property.setValue(val);
property.setDisplayValue(extractValueRequest.getDisplayVal());
}
} catch (IllegalAccessException e) {
throw new PersistenceException(e);
}
return FieldProviderResponse.HANDLED;
}
@Override
public FieldProviderResponse addSearchMapping(AddSearchMappingRequest addSearchMappingRequest,
List<FilterMapping> filterMappings) {
if (!canHandleSearchMapping(addSearchMappingRequest, filterMappings)) {
return FieldProviderResponse.NOT_HANDLED;
}
Class clazz;
try {
clazz = Class.forName(addSearchMappingRequest.getMergedProperties().get(addSearchMappingRequest
.getPropertyName()).getInheritedFromType());
} catch (ClassNotFoundException e) {
throw new PersistenceException(e);
}
Field field = addSearchMappingRequest.getFieldManager().getField(clazz,
addSearchMappingRequest.getPropertyName());
Class<?> targetType = null;
if (field != null) {
targetType = field.getType();
}
BasicFieldMetadata metadata = (BasicFieldMetadata) addSearchMappingRequest.getMergedProperties().get
(addSearchMappingRequest.getPropertyName());
FilterAndSortCriteria fasc = addSearchMappingRequest.getRequestedCto().get(addSearchMappingRequest.getPropertyName());
FilterMapping filterMapping = new FilterMapping()
.withInheritedFromClass(clazz)
.withFullPropertyName(addSearchMappingRequest.getPropertyName())
.withFilterValues(fasc.getFilterValues())
.withSortDirection(fasc.getSortDirection())
.withOrder(fasc.getOrder())
.withNullsLast(fasc.isNullsLast());
filterMappings.add(filterMapping);
if (fasc.hasSpecialFilterValue()) {
filterMapping.setDirectFilterValues(new EmptyFilterValues());
// Handle special values on a case by case basis
List<String> specialValues = fasc.getSpecialFilterValues();
if (specialValues.contains(FilterAndSortCriteria.IS_NULL_FILTER_VALUE)) {
filterMapping.setRestriction(new Restriction().withPredicateProvider(new IsNullPredicateProvider()));
}
if (specialValues.contains(FilterAndSortCriteria.IS_NOT_NULL_FILTER_VALUE)) {
filterMapping.setRestriction(new Restriction().withPredicateProvider(new IsNotNullPredicateProvider()));
}
} else {
if (fasc.getRestrictionType() != null) {
filterMapping.setRestriction(addSearchMappingRequest.getRestrictionFactory().
getRestriction(fasc.getRestrictionType().getType(),
addSearchMappingRequest.getPropertyName()));
} else {
switch (metadata.getFieldType()) {
case BOOLEAN:
if (targetType == null || targetType.equals(Boolean.class) || targetType.equals(boolean.class)) {
filterMapping.setRestriction(addSearchMappingRequest.getRestrictionFactory().getRestriction
(RestrictionType.BOOLEAN.getType(), addSearchMappingRequest.getPropertyName()));
} else {
filterMapping.setRestriction(addSearchMappingRequest.getRestrictionFactory().getRestriction
(RestrictionType.CHARACTER.getType(), addSearchMappingRequest.getPropertyName()));
}
break;
case DATE:
filterMapping.setRestriction(addSearchMappingRequest.getRestrictionFactory().getRestriction
(RestrictionType.DATE.getType(), addSearchMappingRequest.getPropertyName()));
break;
case DECIMAL:
case MONEY:
filterMapping.setRestriction(addSearchMappingRequest.getRestrictionFactory().getRestriction
(RestrictionType.DECIMAL.getType(), addSearchMappingRequest.getPropertyName()));
break;
case INTEGER:
filterMapping.setRestriction(addSearchMappingRequest.getRestrictionFactory().getRestriction
(RestrictionType.LONG.getType(), addSearchMappingRequest.getPropertyName()));
break;
case BROADLEAF_ENUMERATION:
filterMapping.setRestriction(addSearchMappingRequest.getRestrictionFactory().getRestriction(RestrictionType.STRING_EQUAL.getType(), addSearchMappingRequest.getPropertyName()));
break;
default:
filterMapping.setRestriction(addSearchMappingRequest.getRestrictionFactory().getRestriction
(RestrictionType.STRING_LIKE.getType(), addSearchMappingRequest.getPropertyName()));
break;
case FOREIGN_KEY:
if (!addSearchMappingRequest.getRequestedCto().get(addSearchMappingRequest.getPropertyName())
.getFilterValues().isEmpty()) {
ForeignKey foreignKey = (ForeignKey) addSearchMappingRequest.getPersistencePerspective()
.getPersistencePerspectiveItems().get
(PersistencePerspectiveItemType.FOREIGNKEY);
if (metadata.getForeignKeyCollection()) {
if (ForeignKeyRestrictionType.COLLECTION_SIZE_EQ.toString().equals(foreignKey
.getRestrictionType().toString())) {
filterMapping.setRestriction(addSearchMappingRequest.getRestrictionFactory()
.getRestriction(RestrictionType.COLLECTION_SIZE_EQUAL.getType(),
addSearchMappingRequest.getPropertyName()));
filterMapping.setFieldPath(new FieldPath());
} else {
filterMapping.setRestriction(addSearchMappingRequest.getRestrictionFactory()
.getRestriction(RestrictionType.LONG.getType(),
addSearchMappingRequest.getPropertyName()));
filterMapping.setFieldPath(new FieldPath().withTargetProperty
(addSearchMappingRequest
.getPropertyName() + "." + metadata.getForeignKeyProperty()));
}
} else if (addSearchMappingRequest.getRequestedCto().get(addSearchMappingRequest.getPropertyName())
.getFilterValues().get(0) == null || "null".equals(addSearchMappingRequest
.getRequestedCto().get
(addSearchMappingRequest.getPropertyName()).getFilterValues().get(0))) {
filterMapping.setRestriction(addSearchMappingRequest.getRestrictionFactory().getRestriction
(RestrictionType.IS_NULL_LONG.getType(), addSearchMappingRequest.getPropertyName()));
} else if (metadata.getSecondaryType() == SupportedFieldType.STRING) {
filterMapping.setRestriction(addSearchMappingRequest.getRestrictionFactory().getRestriction
(RestrictionType.STRING_EQUAL.getType(), addSearchMappingRequest.getPropertyName()));
filterMapping.setFieldPath(new FieldPath().withTargetProperty(addSearchMappingRequest
.getPropertyName() + "." + metadata.getForeignKeyProperty()));
} else {
filterMapping.setRestriction(addSearchMappingRequest.getRestrictionFactory().getRestriction
(RestrictionType.LONG_EQUAL.getType(), addSearchMappingRequest.getPropertyName()));
filterMapping.setFieldPath(new FieldPath().withTargetProperty(addSearchMappingRequest
.getPropertyName() + "." + metadata.getForeignKeyProperty()));
}
}
break;
case ADDITIONAL_FOREIGN_KEY:
int additionalForeignKeyIndexPosition = Arrays.binarySearch(addSearchMappingRequest
.getPersistencePerspective()
.getAdditionalForeignKeys(), new ForeignKey(addSearchMappingRequest
.getPropertyName(),
null, null),
new Comparator<ForeignKey>() {
@Override
public int compare(ForeignKey o1, ForeignKey o2) {
return o1.getManyToField().compareTo(o2.getManyToField());
}
});
ForeignKey foreignKey = null;
if (additionalForeignKeyIndexPosition >= 0) {
foreignKey = addSearchMappingRequest.getPersistencePerspective().getAdditionalForeignKeys()[additionalForeignKeyIndexPosition];
}
// in the case of a to-one lookup, an explicit ForeignKey is not passed in. The system should then
// default to just using a ForeignKeyRestrictionType.ID_EQ
if (metadata.getForeignKeyCollection()) {
if (ForeignKeyRestrictionType.COLLECTION_SIZE_EQ.toString().equals(foreignKey
.getRestrictionType().toString())) {
filterMapping.setRestriction(addSearchMappingRequest.getRestrictionFactory()
.getRestriction(RestrictionType.COLLECTION_SIZE_EQUAL.getType(),
addSearchMappingRequest.getPropertyName()));
filterMapping.setFieldPath(new FieldPath());
} else {
filterMapping.setRestriction(addSearchMappingRequest.getRestrictionFactory().getRestriction(RestrictionType.LONG.getType(), addSearchMappingRequest.getPropertyName()));
filterMapping.setFieldPath(new FieldPath().withTargetProperty(addSearchMappingRequest.getPropertyName() + "." + metadata.getForeignKeyProperty()));
}
} else if (CollectionUtils.isEmpty(addSearchMappingRequest.getRequestedCto().get(addSearchMappingRequest.getPropertyName()).getFilterValues()) ||
addSearchMappingRequest.getRequestedCto().get(addSearchMappingRequest.getPropertyName
()).getFilterValues().get(0) == null || "null".equals(addSearchMappingRequest.getRequestedCto().get
(addSearchMappingRequest.getPropertyName()).getFilterValues().get(0))) {
filterMapping.setRestriction(addSearchMappingRequest.getRestrictionFactory().getRestriction(RestrictionType.IS_NULL_LONG.getType(), addSearchMappingRequest.getPropertyName()));
} else if (metadata.getSecondaryType() == SupportedFieldType.STRING) {
filterMapping.setRestriction(addSearchMappingRequest.getRestrictionFactory().getRestriction(RestrictionType.STRING_EQUAL.getType(), addSearchMappingRequest.getPropertyName()));
filterMapping.setFieldPath(new FieldPath().withTargetProperty(addSearchMappingRequest.getPropertyName() + "." + metadata.getForeignKeyProperty()));
} else {
filterMapping.setRestriction(addSearchMappingRequest.getRestrictionFactory().getRestriction(RestrictionType.LONG_EQUAL.getType(), addSearchMappingRequest.getPropertyName()));
filterMapping.setFieldPath(new FieldPath().withTargetProperty(addSearchMappingRequest
.getPropertyName() + "." + metadata.getForeignKeyProperty()));
}
break;
case ID:
switch (metadata.getSecondaryType()) {
case INTEGER:
filterMapping.setRestriction(addSearchMappingRequest.getRestrictionFactory()
.getRestriction
(RestrictionType.LONG_EQUAL.getType(), addSearchMappingRequest.getPropertyName()));
break;
case STRING:
filterMapping.setRestriction(addSearchMappingRequest.getRestrictionFactory().
getRestriction(RestrictionType.STRING_EQUAL.getType(),
addSearchMappingRequest.getPropertyName()));
break;
}
break;
}
}
}
return FieldProviderResponse.HANDLED;
}
@Override
public int getOrder() {
return FieldPersistenceProvider.BASIC;
}
}