001    // Copyright 2005 The Apache Software Foundation
002    //
003    // Licensed under the Apache License, Version 2.0 (the "License");
004    // you may not use this file except in compliance with the License.
005    // You may obtain a copy of the License at
006    //
007    //     http://www.apache.org/licenses/LICENSE-2.0
008    //
009    // Unless required by applicable law or agreed to in writing, software
010    // distributed under the License is distributed on an "AS IS" BASIS,
011    // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
012    // See the License for the specific language governing permissions and
013    // limitations under the License.
014    
015    package org.apache.tapestry.form.translator;
016    
017    import java.text.DecimalFormat;
018    import java.text.DecimalFormatSymbols;
019    import java.text.Format;
020    import java.util.Locale;
021    
022    import org.apache.hivemind.util.PropertyUtils;
023    import org.apache.tapestry.IMarkupWriter;
024    import org.apache.tapestry.IRequestCycle;
025    import org.apache.tapestry.form.FormComponentContributorContext;
026    import org.apache.tapestry.form.IFormComponent;
027    import org.apache.tapestry.json.JSONLiteral;
028    import org.apache.tapestry.json.JSONObject;
029    import org.apache.tapestry.valid.ValidationConstants;
030    import org.apache.tapestry.valid.ValidationConstraint;
031    import org.apache.tapestry.valid.ValidationStrings;
032    
033    /**
034     * A {@link java.text.DecimalFormat}-based {@link Translator} implementation.
035     * 
036     * @author Paul Ferraro
037     * @since 4.0
038     */
039    public class NumberTranslator extends FormatTranslator
040    {
041        private boolean _omitZero = true;
042    
043        public NumberTranslator()
044        {
045        }
046    
047        //TODO: Needed until HIVEMIND-134 fix is available
048        public NumberTranslator(String initializer)
049        {
050            PropertyUtils.configureProperties(this, initializer);
051        }
052        
053        protected String formatObject(IFormComponent field, Locale locale, Object object)
054        {
055            Number number = (Number) object;
056    
057            if (_omitZero)
058            {
059                if (number.doubleValue() == 0)
060    
061                    return "";
062            }
063    
064            return super.formatObject(field, locale, object);
065        }
066    
067        /**
068         * @see org.apache.tapestry.form.translator.FormatTranslator#defaultPattern()
069         */
070        protected String defaultPattern()
071        {
072            return "#";
073        }
074    
075        /**
076         * @see org.apache.tapestry.form.translator.FormatTranslator#getFormat(java.util.Locale)
077         */
078        protected Format getFormat(Locale locale)
079        {
080            return getDecimalFormat(locale);
081        }
082    
083        public DecimalFormat getDecimalFormat(Locale locale)
084        {
085            return new DecimalFormat(getPattern(), new DecimalFormatSymbols(locale));
086        }
087    
088        /**
089         * @see org.apache.tapestry.form.translator.FormatTranslator#getMessageKey()
090         */
091        protected String getMessageKey()
092        {
093            return ValidationStrings.INVALID_NUMBER;
094        }
095    
096        /**
097         * @see org.apache.tapestry.form.translator.AbstractTranslator#getMessageParameters(java.util.Locale,
098         *      java.lang.String)
099         */
100        protected Object[] getMessageParameters(Locale locale, String label)
101        {
102            String pattern = getDecimalFormat(locale).toLocalizedPattern();
103            
104            return new Object[] { label, pattern };
105        }
106    
107        /**
108         * @see org.apache.tapestry.form.FormComponentContributor#renderContribution(org.apache.tapestry.IMarkupWriter,
109         *      org.apache.tapestry.IRequestCycle, FormComponentContributorContext,
110         *      org.apache.tapestry.form.IFormComponent)
111         */
112        public void renderContribution(IMarkupWriter writer, IRequestCycle cycle,
113                FormComponentContributorContext context, IFormComponent field)
114        {
115            super.renderContribution(writer, cycle, context, field);
116            
117            String message = buildMessage(context, field, getMessageKey());
118            
119            JSONObject profile = context.getProfile();
120            if (!profile.has(ValidationConstants.CONSTRAINTS)) {
121                profile.put(ValidationConstants.CONSTRAINTS, new JSONObject());
122            }
123            
124            JSONObject cons = profile.getJSONObject(ValidationConstants.CONSTRAINTS);
125            
126            DecimalFormat format = getDecimalFormat(context.getLocale());
127            
128            cons.accumulate(field.getClientId(),
129                    new JSONLiteral("[dojo.validate.isRealNumber,{"
130                            + ((format.getMaximumFractionDigits() > 0) 
131                                    ? "" : "places:" + format.getMaximumFractionDigits() + ",")
132                                    + "decimal:" 
133                                    + JSONObject.quote(format.getDecimalFormatSymbols().getDecimalSeparator()) 
134                                    + (format.isGroupingUsed()
135                                            ? ",separator:" + JSONObject.quote(format.getDecimalFormatSymbols().getGroupingSeparator())
136                                                    : "")
137                                                    + "}]"));
138            
139            accumulateProfileProperty(field, profile, ValidationConstants.CONSTRAINTS, message);
140        }
141    
142        /**
143         * @see org.apache.tapestry.form.translator.FormatTranslator#getConstraint()
144         */
145        protected ValidationConstraint getConstraint()
146        {
147            return ValidationConstraint.NUMBER_FORMAT;
148        }
149    
150        /**
151         * If true (which is the default for the property), then values that are 0 are rendered to an
152         * empty string, not "0" or "0.00". This is useful in most cases where the field is optional; it
153         * allows the field to render blank when no value is present.
154         */
155    
156        public void setOmitZero(boolean omitZero)
157        {
158            _omitZero = omitZero;
159        }
160    
161    }