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 org.apache.hivemind.util.PropertyUtils;
018    import org.apache.tapestry.IMarkupWriter;
019    import org.apache.tapestry.IRequestCycle;
020    import org.apache.tapestry.form.FormComponentContributorContext;
021    import org.apache.tapestry.form.IFormComponent;
022    import org.apache.tapestry.json.JSONLiteral;
023    import org.apache.tapestry.json.JSONObject;
024    import org.apache.tapestry.valid.ValidationConstants;
025    import org.apache.tapestry.valid.ValidationConstraint;
026    import org.apache.tapestry.valid.ValidationStrings;
027    
028    import java.text.DecimalFormat;
029    import java.text.DecimalFormatSymbols;
030    import java.text.Format;
031    import java.util.Locale;
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 = false;
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                    return "";
061            }
062    
063            return super.formatObject(field, locale, object);
064        }
065    
066        protected Object getValueForEmptyInput()
067        {
068            return _omitZero ? null : new Double(0);
069        }
070    
071        /**
072         * @see org.apache.tapestry.form.translator.FormatTranslator#defaultPattern()
073         */
074        protected String defaultPattern()
075        {
076            return "#";
077        }
078    
079        /**
080         * @see org.apache.tapestry.form.translator.FormatTranslator#getFormat(java.util.Locale)
081         */
082        protected Format getFormat(Locale locale)
083        {
084            return getDecimalFormat(locale);
085        }
086    
087        public DecimalFormat getDecimalFormat(Locale locale)
088        {
089            return new DecimalFormat(getPattern(), new DecimalFormatSymbols(locale));
090        }
091    
092        /**
093         * @see org.apache.tapestry.form.translator.FormatTranslator#getMessageKey()
094         */
095        protected String getMessageKey()
096        {
097            return ValidationStrings.INVALID_NUMBER;
098        }
099    
100        /**
101         * @see org.apache.tapestry.form.translator.AbstractTranslator#getMessageParameters(java.util.Locale,
102         *      java.lang.String)
103         */
104        protected Object[] getMessageParameters(Locale locale, String label)
105        {
106            String pattern = getDecimalFormat(locale).toLocalizedPattern();
107    
108            return new Object[] { label, pattern };
109        }
110    
111        /**
112         * @see org.apache.tapestry.form.FormComponentContributor#renderContribution(org.apache.tapestry.IMarkupWriter,
113         *      org.apache.tapestry.IRequestCycle, FormComponentContributorContext,
114         *      org.apache.tapestry.form.IFormComponent)
115         */
116        public void renderContribution(IMarkupWriter writer, IRequestCycle cycle,
117                                       FormComponentContributorContext context, IFormComponent field)
118        {
119            super.renderContribution(writer, cycle, context, field);
120    
121            String message = buildMessage(context, field, getMessageKey());
122    
123            JSONObject profile = context.getProfile();
124            if (!profile.has(ValidationConstants.CONSTRAINTS)) {
125                profile.put(ValidationConstants.CONSTRAINTS, new JSONObject());
126            }
127            JSONObject cons = profile.getJSONObject(ValidationConstants.CONSTRAINTS);
128    
129            DecimalFormat format = getDecimalFormat(context.getLocale());
130    
131            String grouping = "";
132            if (format.isGroupingUsed()) {
133    
134                grouping += ",separator:" + JSONObject.quote(format.getDecimalFormatSymbols().getGroupingSeparator());
135                grouping += ",groupSize:" + format.getGroupingSize();
136            } else {
137    
138                grouping += ",separator:\"\"";
139            }
140    
141            cons.accumulate(field.getClientId(),
142                            new JSONLiteral("[tapestry.form.validation.isReal,null,{"
143                                            + "places:" + format.getMaximumFractionDigits() + ","
144                                            + "decimal:"
145                                            + JSONObject.quote(format.getDecimalFormatSymbols().getDecimalSeparator())
146                                            + grouping
147                                            + "}]"));
148    
149            accumulateProfileProperty(field, profile, ValidationConstants.CONSTRAINTS, message);
150        }
151    
152        /**
153         * @see org.apache.tapestry.form.translator.FormatTranslator#getConstraint()
154         */
155        protected ValidationConstraint getConstraint()
156        {
157            return ValidationConstraint.NUMBER_FORMAT;
158        }
159    
160        /**
161         * If true (which is the default for the property), then values that are 0 are rendered to an
162         * empty string, not "0" or "0.00". This is useful in most cases where the field is optional; it
163         * allows the field to render blank when no value is present.
164         *
165         * @param omitZero
166         *          Whether or not to omit zero.
167         */
168    
169        public void setOmitZero(boolean omitZero)
170        {
171            _omitZero = omitZero;
172        }
173    
174        public boolean isOmitZero()
175        {
176            return _omitZero;
177        }
178    }