/* * Copyright (c) 2005-2016 Vincent Vandenschrick. All rights reserved. * * This file is part of the Jspresso framework. * * Jspresso 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, either version 3 of the License, or * (at your option) any later version. * * Jspresso 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 Jspresso. If not, see <http://www.gnu.org/licenses/>. */ package org.jspresso.framework.model.descriptor.basic; import java.math.BigDecimal; import java.util.Locale; import org.jspresso.framework.model.descriptor.INumberPropertyDescriptor; import org.jspresso.framework.util.bean.integrity.IntegrityException; import org.jspresso.framework.util.i18n.ITranslationProvider; /** * This is the abstract base descriptor of all numeric based properties. * * @author Vincent Vandenschrick */ public abstract class BasicNumberPropertyDescriptor extends BasicScalarPropertyDescriptor implements INumberPropertyDescriptor { private BigDecimal maxValue; private BigDecimal minValue; private boolean thousandsGroupingUsed; private String formatPattern; /** * Constructs a new {@code BasicPropertyDescriptor} instance. */ public BasicNumberPropertyDescriptor() { thousandsGroupingUsed = true; } /** * {@inheritDoc} */ @Override public BasicNumberPropertyDescriptor clone() { BasicNumberPropertyDescriptor clonedDescriptor = (BasicNumberPropertyDescriptor) super .clone(); return clonedDescriptor; } /** * {@inheritDoc} */ @Override public BasicPropertyDescriptor createQueryDescriptor() { BasicNumberPropertyDescriptor queryDescriptor = (BasicNumberPropertyDescriptor) super .createQueryDescriptor(); queryDescriptor.setMinValue(null); queryDescriptor.setMaxValue(null); return queryDescriptor; } /** * {@inheritDoc} */ @Override public BigDecimal getMaxValue() { return maxValue; } /** * {@inheritDoc} */ @Override public BigDecimal getMinValue() { return minValue; } /** * Handles value bounds. * <p> * {@inheritDoc} */ @Override public void preprocessSetter(final Object component, final Object newValue) { super.preprocessSetter(component, newValue); if (newValue != null) { if ((getMinValue() != null && compare(((Number) newValue), getMinValue()) < 0) || (getMaxValue() != null && compare(((Number) newValue), getMaxValue()) > 0)) { IntegrityException ie = new IntegrityException("[" + getName() + "] value is out of bounds on [" + component + "].") { private static final long serialVersionUID = 7459823123892198831L; @Override public String getI18nMessage( ITranslationProvider translationProvider, Locale locale) { StringBuilder boundsSpec = new StringBuilder(); if (getMinValue() != null && !isDefault(getMinValue())) { boundsSpec.append(getMinValue()).append(" <= "); } boundsSpec.append("x"); if (getMaxValue() != null && !isDefault(getMaxValue())) { boundsSpec.append(" <= ").append(getMaxValue()); } String messageKey; if (getMinValue() != null && compare(((Number) newValue), getMinValue()) < 0) { messageKey = "integrity.property.toosmall"; } else { messageKey = "integrity.property.toobig"; } return translationProvider.getTranslation(messageKey, new Object[] { getI18nName(translationProvider, locale), boundsSpec, component }, locale); } }; throw ie; } } } /** * is default value a default one. * * @param boundValue * the boundValue to test. * @return true is the boundValue us a default one. */ protected boolean isDefault(BigDecimal boundValue) { return false; } /** * Configures the upper bound of the allowed values. Default value is * {@code null}, meaning unbound. * * @param maxValue * the maxValue to set. */ public void setMaxValue(BigDecimal maxValue) { this.maxValue = maxValue; } /** * Configures the lower bound of the allowed values. Default value is * {@code null}, meaning unbound. * * @param minValue * the minValue to set. */ public void setMinValue(BigDecimal minValue) { this.minValue = minValue; } private int compare(Number value, BigDecimal bound) { if (value instanceof BigDecimal) { return ((BigDecimal) value).compareTo(bound); } return new BigDecimal(value.doubleValue()).compareTo(bound); } /** * {@inheritDoc} */ @Override public boolean isThousandsGroupingUsed() { return thousandsGroupingUsed; } /** * Sets thousands grouping used. * * @param thousandsGroupingUsed the thousands grouping used */ public void setThousandsGroupingUsed(boolean thousandsGroupingUsed) { this.thousandsGroupingUsed = thousandsGroupingUsed; } /** * {@inheritDoc} */ @Override public String getFormatPattern() { return formatPattern; } /** * Sets format pattern. Allows to override the default one. * * @param formatPattern * the format pattern */ public void setFormatPattern(String formatPattern) { this.formatPattern = formatPattern; } /** * Is default filter comparable. * * @return {@code true} */ @Override protected boolean isDefaultFilterComparable() { return true; } }