001: // /////////////////////////////
002: // Makumba, Makumba tag library
003: // Copyright (C) 2000-2003 http://www.makumba.org
004: //
005: // This library is free software; you can redistribute it and/or
006: // modify it under the terms of the GNU Lesser General Public
007: // License as published by the Free Software Foundation; either
008: // version 2.1 of the License, or (at your option) any later version.
009: //
010: // This library is distributed in the hope that it will be useful,
011: // but WITHOUT ANY WARRANTY; without even the implied warranty of
012: // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
013: // Lesser General Public License for more details.
014: //
015: // You should have received a copy of the GNU Lesser General Public
016: // License along with this library; if not, write to the Free Software
017: // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
018: //
019: // -------------
020: // $Id: dateEditor.java 1749 2007-10-03 15:56:11Z manuel_gay $
021: // $Name$
022: /////////////////////////////////////
023:
024: package org.makumba.forms.html;
025:
026: import java.text.SimpleDateFormat;
027: import java.util.Calendar;
028: import java.util.Date;
029: import java.util.Dictionary;
030: import java.util.GregorianCalendar;
031: import java.util.Vector;
032:
033: import org.makumba.MakumbaSystem;
034: import org.makumba.commons.attributes.HttpParameters;
035: import org.makumba.commons.formatters.FieldFormatter;
036: import org.makumba.commons.formatters.InvalidValueException;
037: import org.makumba.commons.formatters.RecordFormatter;
038: import org.makumba.commons.formatters.dateFormatter;
039:
040: public class dateEditor extends FieldEditor {
041:
042: private static final class SingletonHolder {
043: static final FieldEditor singleton = new dateEditor();
044: }
045:
046: private dateEditor() {
047: }
048:
049: public static FieldFormatter getInstance() {
050: return SingletonHolder.singleton;
051: }
052:
053: static String[] _params = { "format", "calendarEditor",
054: "calendarEditorLink" };
055:
056: static String[][] _paramValues = { null,
057: new String[] { "true", "false" }, null };
058:
059: public String[] getAcceptedParams() {
060: return _params;
061: }
062:
063: public String[][] getAcceptedValue() {
064: return _paramValues;
065: }
066:
067: static final String recognized = "dMyHms";
068:
069: static int[] lowLimits = { 1, 0, -1, 0, 0, 0 };
070:
071: static int[] hiLimits = { 31, 11, -1, 23, 59, 59 };
072:
073: public static int[] components = { Calendar.DAY_OF_MONTH,
074: Calendar.MONTH, Calendar.YEAR, Calendar.HOUR_OF_DAY,
075: Calendar.MINUTE, Calendar.SECOND };
076:
077: static String[] componentNames = { "day", "month", "year", "hour",
078: "minute", "second" };
079:
080: String getNullName(RecordFormatter rf, int fieldIndex,
081: Dictionary formatParams) {
082: return getNullName(rf, fieldIndex, getSuffix(rf, fieldIndex,
083: formatParams));
084: }
085:
086: String getNullName(RecordFormatter rf, int fieldIndex, String suffix) {
087: return getInputName(rf, fieldIndex, suffix) + "_null";
088: }
089:
090: String getComponentName(RecordFormatter rf, int fieldIndex, int i,
091: String suffix) {
092: return getInputName(rf, fieldIndex, suffix) + "_" + i;
093: }
094:
095: String getComponentName(RecordFormatter rf, int fieldIndex, int i,
096: Dictionary formatParams) {
097: return getComponentName(rf, fieldIndex, i, getSuffix(rf,
098: fieldIndex, formatParams));
099: }
100:
101: public String format(RecordFormatter rf, int fieldIndex, Object o,
102: Dictionary formatParams) {
103: String format = (String) formatParams.get("format");
104: if (format == null)
105: format = "dd MMMMM yyyy";
106: if (o == org.makumba.Pointer.NullDate)
107: o = null;
108: Date d = (Date) o;
109: StringBuffer sb = new StringBuffer();
110: boolean hidden = "hidden".equals(formatParams.get("type"));
111: if (d == null) {
112: d = (Date) rf.dd.getFieldDefinition(fieldIndex)
113: .getDefaultValue();
114: sb.append("<input type=\"hidden\" name=\"").append(
115: getNullName(rf, fieldIndex, formatParams)).append(
116: "\">");
117: }
118: int n = 0;
119: while (true) {
120: n = findNextFormatter(rf, fieldIndex, sb, format, n, hidden);
121: if (n == -1)
122: break;
123: n = formatFrom(rf, fieldIndex, sb, d, format, n, hidden,
124: formatParams);
125: }
126:
127: String inputName = getInputName(rf, fieldIndex, getSuffix(rf,
128: fieldIndex, formatParams));
129: String calendarEditor = (String) formatParams
130: .get("calendarEditor");
131: if (!calendarEditor.equals("false")) {
132: sb.append(MakumbaSystem.getCalendarProvider()
133: .formatEditorCode(
134: inputName,
135: (String) formatParams
136: .get("calendarEditorLink")));
137: }
138:
139: return sb.toString();
140: }
141:
142: void formatComponent(RecordFormatter rf, int fieldIndex,
143: StringBuffer sb, Date d, String fmt, int component,
144: boolean hidden, Dictionary formatParams) {
145: SimpleDateFormat df = new SimpleDateFormat(fmt,
146: org.makumba.MakumbaSystem.getLocale());
147: df.setCalendar(dateFormatter.calendar);
148:
149: String name = getComponentName(rf, fieldIndex, component,
150: formatParams);
151:
152: if (hidden) {
153: Calendar c = new GregorianCalendar(
154: org.makumba.MakumbaSystem.getTimeZone());
155: c.setTime(d);
156: sb.append("<input type=\"hidden\" name=\"").append(name)
157: .append("\" id=\"").append(name).append(
158: "\" value=\"").append(
159: c.get(components[component])).append("\">");
160: } else {
161: String val = df.format(d);
162:
163: if (lowLimits[component] == -1) {// year
164: sb.append("<input type=\"text\" name=\"").append(name)
165: .append("\" id=\"").append(name).append(
166: "\" value=\"").append(val).append(
167: "\" maxlength=\"").append(fmt.length())
168: .append("\" size=\"").append(fmt.length())
169: .append("\"").append(
170: getExtraFormatting(rf, fieldIndex,
171: formatParams)).append(">");
172: } else {
173: sb.append("<select name=\"").append(name).append(
174: "\" id=\"").append(name).append("\"")
175: .append(
176: getExtraFormatting(rf, fieldIndex,
177: formatParams)).append(">");
178: Calendar c = new GregorianCalendar(
179: org.makumba.MakumbaSystem.getTimeZone());
180: c.clear();
181: c.set(1900, 0, 1); // set 1900,Jan,1st as the date to start
182: // building interface from
183: for (int i = lowLimits[component]; i <= hiLimits[component]; i++) {
184: c.set(components[component], i);
185: String opt = df.format(c.getTime());
186: sb.append("<option value=\"").append(i)
187: .append("\"");
188: if (opt.equals(val))
189: sb.append(" selected");
190: sb.append(">").append(opt).append("</option>");
191: }
192: sb.append("</select>");
193: }
194: }
195: }
196:
197: public Object readFrom(RecordFormatter rf, int fieldIndex,
198: org.makumba.commons.attributes.HttpParameters pr,
199: String suffix) {
200: Calendar c = new GregorianCalendar(org.makumba.MakumbaSystem
201: .getTimeZone());
202: c.clear();
203: for (int i = 0; i < components.length; i++) {
204: String name = getComponentName(rf, fieldIndex, i, suffix);
205: Object o = pr.getParameter(name);
206: if (o == null)
207: continue;
208: if (o instanceof Vector)
209: throw new InvalidValueException(rf.expr[fieldIndex],
210: "Multiple value not allowed for '"
211: + componentNames[i] + "' component");
212: int n = -1;
213: try {
214: n = Integer.parseInt((String) o);
215: } catch (NumberFormatException e) {
216: throw new InvalidValueException(rf.expr[fieldIndex],
217: "Non-integer value not allowed for '"
218: + componentNames[i] + "' component: "
219: + o);
220: }
221: c.set(components[i], n);
222: }
223: Date d = c.getTime();
224: if (d.equals(rf.dd.getFieldDefinition(fieldIndex)
225: .getDefaultValue())
226: && pr.getParameter(getNullName(rf, fieldIndex, suffix)) != null)
227: return null;
228: return d;
229: }
230:
231: /**
232: * This method is used to get the date field in case of a form reload due to validation errors, and is used from
233: * {@link BasicValueTag#doMakumbaEndTag(org.makumba.commons.formatters.jsptaglib.PageCache)}. It is basically
234: * i simplified version of {@link #readFrom(RecordFormatter, int, HttpParameters, String)}.
235: */
236: public static Object readFrom(String name, HttpParameters pr) {
237: Calendar c = new GregorianCalendar(org.makumba.MakumbaSystem
238: .getTimeZone());
239: c.clear();
240: for (int i = 0; i < components.length; i++) {
241: Object o = pr.getParameter(name + "_" + i);
242: if (o == null)
243: continue;
244: int n = -1;
245: try {
246: n = Integer.parseInt((String) o);
247: } catch (NumberFormatException e) {
248: }
249: c.set(components[i], n);
250: }
251: return c.getTime();
252: }
253:
254: int formatFrom(RecordFormatter rf, int fieldIndex, StringBuffer sb,
255: Date d, String format, int n, boolean hidden,
256: Dictionary formatParams) {
257: int m = n;
258: char c = format.charAt(n);
259: while (++n < format.length() && format.charAt(n) == c)
260: ;
261: formatComponent(rf, fieldIndex, sb, d, format.substring(m, n),
262: recognized.indexOf(c), hidden, formatParams);
263: return n;
264: }
265:
266: int findNextFormatter(RecordFormatter rf, int fieldIndex,
267: StringBuffer sb, String format, int n, boolean hidden) {
268: StringBuffer quoted = null;
269: for (; n < format.length(); n++) {
270: char c = format.charAt(n);
271: if (c == '\'')
272: if (quoted != null) // existing quote
273: if (quoted.length() == 0) // double quote
274: {
275: if (!hidden)
276: sb.append('\'');
277: quoted = null;
278: } else // closed quote
279: {
280: if (!hidden)
281: sb.append(quoted.toString());
282: quoted = null;
283: }
284: else
285: // new quote
286: quoted = new StringBuffer();
287: else if (quoted != null) {
288: quoted.append(c);
289: } else // we're outside quotes
290: if (!Character.isLetter(c)) // non-letters don't need quotes
291: {
292: if (!hidden)
293: sb.append(c);
294: } else if (recognized.indexOf(c) == -1)
295: throw new InvalidValueException(rf.expr[fieldIndex],
296: "unrecognized formatting letter \'" + c
297: + "\' in date format string <" + format
298: + ">");
299: else
300: return n;
301: }
302: if (quoted != null)
303: throw new InvalidValueException(rf.expr[fieldIndex],
304: "unterminated single quote in date format string <"
305: + format + ">");
306: return -1;
307: }
308: }
|