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 }