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 }