/* * Copyright (C) NetStruxr, Inc. All rights reserved. * * This software is published under the terms of the NetStruxr * Public Software License version 0.5, a copy of which has been * included with this distribution in the LICENSE.NPL file. */ package er.directtoweb.components.numbers; import java.math.BigDecimal; import java.text.ParseException; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import com.webobjects.appserver.WOContext; import com.webobjects.directtoweb.D2WEditNumber; import com.webobjects.eoaccess.EOAttribute; import com.webobjects.foundation.NSNumberFormatter; import com.webobjects.foundation.NSValidation; import er.extensions.eof.ERXConstant; import er.extensions.formatters.ERXNumberFormatter; import er.extensions.validation.ERXValidationFactory; /** * Common superclass of all ER's edit number components. * * @d2wKey name * @d2wKey smartAttribute */ public class ERD2WEditNumber extends D2WEditNumber { /** * Do I need to update serialVersionUID? * See section 5.6 <cite>Type Changes Affecting Serialization</cite> on page 51 of the * <a href="http://java.sun.com/j2se/1.4/pdf/serial-spec.pdf">Java Object Serialization Spec</a> */ private static final long serialVersionUID = 1L; public ERD2WEditNumber(WOContext context) { super(context); } private static final Logger log = LoggerFactory.getLogger(ERD2WEditNumber.class); @Override public void reset() { super.reset(); _numberFormatter = null; } @Override public EOAttribute attribute() { return super.attribute() != null ? super.attribute() : (EOAttribute)d2wContext().valueForKey("smartAttribute"); } private NSNumberFormatter _numberFormatter; protected java.text.Format numberFormatter() { if (_numberFormatter == null) { _numberFormatter = ERXNumberFormatter.numberFormatterForPattern(formatter()); } return _numberFormatter; } @Override public Object validateTakeValueForKeyPath (Object anObject, String aPath) throws NSValidation.ValidationException { Number number = null; try { if (anObject instanceof String) { number = (Number)numberFormatValueForString((String)anObject); } else if (anObject!=null && !(anObject instanceof Number)) { log.warn("Unable to read number: {}", anObject); throw ERXValidationFactory.defaultFactory().createException(object(), propertyKey(), anObject, "NotANumberException"); } } catch(NSValidation.ValidationException ex) { validationFailedWithException(ex, anObject, propertyKey()); throw ex; } return super.validateTakeValueForKeyPath(convertNumber(number), propertyKey()); } @Override public void validationFailedWithException(Throwable theException,Object theValue, String theKeyPath) { // This is for number formatting exceptions String keyPath = theKeyPath.equals("stringValue") ? propertyKey() : theKeyPath; // the following is needed because we might Number formatValue = null; try { if (theValue != null) formatValue = (Number) numberFormatter().parseObject((String) theValue); } catch(Exception ex) { formatValue = (Number)objectPropertyValue(); } parent().validationFailedWithException(theException, formatValue, keyPath); } /* following needed because we do not want to leave control over our (light) numberFormatter to WebObjects, which needs a full fledged NSNumberFormatter */ public String stringValue() { return value() != null ? numberFormatter().format(value()) : null; } public void setStringValue(String newStringValue) { if (newStringValue != null) setValue(numberFormatValueForString(newStringValue)); else setValue(null); } protected Object numberFormatValueForString(String value) { Object formatValue = null; try { if (value != null) formatValue = numberFormatter().parseObject(value); } catch (ParseException e) { log.debug("Unable to parse number: {} in {}", value, propertyKey()); throw ERXValidationFactory.defaultFactory().createException(object(), propertyKey(), value, "IllegalCharacterInNumberException"); } return formatValue; } protected Object convertNumber(Object anObject) { Number newValue=null; if (anObject!=null && anObject instanceof Number) { newValue=(Number)anObject; if (newValue instanceof BigDecimal && !isDecimalNumber() && attribute().valueType() != null && attribute().valueType().equals("i")) { // we are getting a BigDecimal from WOTextField even though we asked for an Integer! newValue=ERXConstant.integerForInt(newValue.intValue()); } } return newValue; } }