/**
* ***************************************************************************
* Copyright (c) 2010 Qcadoo Limited
* Project: Qcadoo Framework
* Version: 1.4
*
* This file is part of Qcadoo.
*
* Qcadoo is free software; you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as published
* by the Free Software Foundation; either version 3 of the License,
* or (at your option) any later version.
*
* This program 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 Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
* ***************************************************************************
*/
package com.qcadoo.model.internal.types;
import java.math.BigDecimal;
import java.text.DecimalFormat;
import java.text.NumberFormat;
import java.text.ParsePosition;
import java.util.Collection;
import java.util.Locale;
import java.util.Set;
import com.google.common.collect.Sets;
import com.qcadoo.model.api.FieldDefinition;
import com.qcadoo.model.api.NumberService;
import com.qcadoo.model.internal.NumberServiceImpl;
import com.qcadoo.model.internal.api.DefaultValidatorsProvider;
import com.qcadoo.model.internal.api.FieldHookDefinition;
import com.qcadoo.model.internal.api.ValueAndError;
import com.qcadoo.model.internal.validators.ScaleValidator;
import com.qcadoo.model.internal.validators.UnscaledValueValidator;
public final class DecimalType extends AbstractFieldType implements DefaultValidatorsProvider {
public DecimalType() {
this(true);
}
public DecimalType(final boolean copyable) {
super(copyable);
}
@Override
public Class<?> getType() {
return BigDecimal.class;
}
@Override
public ValueAndError toObject(final FieldDefinition fieldDefinition, final Object value) {
BigDecimal decimal = null;
if (value instanceof BigDecimal) {
decimal = ((BigDecimal) value).stripTrailingZeros();
} else {
try {
decimal = new BigDecimal(String.valueOf(value)).stripTrailingZeros();
} catch (NumberFormatException e) {
return ValueAndError.withError("qcadooView.validate.field.error.invalidNumericFormat");
}
}
return ValueAndError.withoutError(decimal);
}
@Override
public String toString(final Object value, final Locale locale) {
if (value == null) {
return "";
}
if(value instanceof String){
return (String) value;
}
NumberFormat format = null;
if (locale == null) {
format = NumberFormat.getNumberInstance();
} else {
format = NumberFormat.getNumberInstance(locale);
}
format.setMaximumFractionDigits(getMaxFractionDigits(value));
return format.format(value);
}
private int getMaxFractionDigits(final Object value) {
if (value instanceof BigDecimal) {
return ((BigDecimal) value).stripTrailingZeros().scale();
}
return NumberServiceImpl.MAX_PRECISION;
}
@Override
public Object fromString(final String value, final Locale locale) {
ParsePosition parsePosition = new ParsePosition(0);
String trimedValue = value.replaceAll(" ", "");
DecimalFormat formatter = (DecimalFormat) NumberFormat.getNumberInstance(locale);
formatter.setParseBigDecimal(true);
Object parsedValue = formatter.parseObject(trimedValue, parsePosition);
if (parsePosition.getIndex() == trimedValue.length()) {
return parsedValue;
}
return value;
}
@Override
public Collection<FieldHookDefinition> getMissingValidators(final Iterable<FieldHookDefinition> validators) {
FieldHookDefinition defaultScaleValidator = new ScaleValidator(null, null,
NumberService.DEFAULT_MAX_FRACTION_DIGITS_IN_DECIMAL);
FieldHookDefinition defaultUnscaledValueValidator = new UnscaledValueValidator(null, null,
NumberService.DEFAULT_MAX_INTEGER_DIGITS_IN_DECIMAL);
Set<FieldHookDefinition> missingValidators = Sets.<FieldHookDefinition> newHashSet(defaultScaleValidator,
defaultUnscaledValueValidator);
for (FieldHookDefinition validator : validators) {
if (validator instanceof UnscaledValueValidator && ((UnscaledValueValidator) validator).hasUppuerBoundDefined()) {
missingValidators.remove(defaultUnscaledValueValidator);
}
if (validator instanceof ScaleValidator && ((ScaleValidator) validator).hasUppuerBoundDefined()) {
missingValidators.remove(defaultScaleValidator);
}
}
return missingValidators;
}
}