001: /**
002: * Copyright 2006 Webmedia Group Ltd.
003: *
004: * Licensed under the Apache License, Version 2.0 (the "License");
005: * you may not use this file except in compliance with the License.
006: * You may obtain a copy of the License at
007: *
008: * http://www.apache.org/licenses/LICENSE-2.0
009: *
010: * Unless required by applicable law or agreed to in writing, software
011: * distributed under the License is distributed on an "AS IS" BASIS,
012: * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
013: * See the License for the specific language governing permissions and
014: * limitations under the License.
015: **/package org.araneaframework.uilib.list.structure.filter;
016:
017: import java.io.Serializable;
018: import java.util.Comparator;
019: import java.util.HashMap;
020: import java.util.Locale;
021: import java.util.Map;
022: import org.apache.commons.lang.StringUtils;
023: import org.apache.commons.lang.Validate;
024: import org.araneaframework.Environment;
025: import org.araneaframework.framework.LocalizationContext;
026: import org.araneaframework.uilib.ConfigurationContext;
027: import org.araneaframework.uilib.form.FormWidget;
028: import org.araneaframework.uilib.list.ListWidget;
029: import org.araneaframework.uilib.list.TypeHelper;
030: import org.araneaframework.uilib.list.util.FilterFormUtil;
031: import org.araneaframework.uilib.util.Event;
032:
033: /**
034: * Base implementation of list filter helper. Filter helper is used to add
035: * filters and their form elements to the {@link ListWidget}.
036: * <p>
037: * This class handles configuration for new filter such as strictness (e.g equal
038: * is not allowed for greater than filter) as well as allow to predefine custom
039: * labels for fields that are not added to the standard list of list fields but
040: * are used in filter form elements instead.
041: * </p>
042: * <p>
043: * The handling of field types and their comparator is proxied to
044: * {@link TypeHelper} of the list widget.
045: *
046: * @author <a href="mailto:rein@araneaframework.org">Rein Raudjärv</a>
047: *
048: * @see ListWidget
049: * @see FilterHelper
050: * @see TypeHelper
051: */
052: public abstract class BaseFilterHelper implements FilterContext,
053: Serializable {
054:
055: /** Field id suffix for range filter's low/start/min value */
056: public static final String LOW_SUFFIX = "_start";
057: /** Field id suffix for range filter's high/end/max value */
058: public static final String HIGH_SUFFIX = "_end";
059:
060: /** The associated list */
061: protected final ListWidget list;
062:
063: private boolean strict = false;
064:
065: // Map<String,String> - custom labels for fields
066: private Map labels = new HashMap();
067:
068: private boolean changed = true;
069:
070: /**
071: * Constructs a {@link BaseFilterHelper}.
072: *
073: * @param list list.
074: */
075: public BaseFilterHelper(ListWidget list) {
076: this (list, true);
077: }
078:
079: private BaseFilterHelper(ListWidget list, boolean createCopy) {
080: Validate.notNull(list);
081: this .list = list;
082: }
083:
084: public void init(Environment env) throws Exception {
085: }
086:
087: public void destroy() throws Exception {
088: }
089:
090: public void addInitEvent(Event event) {
091: this .list.addInitEvent(event);
092: }
093:
094: /**
095: * Returns the current case sensitivity behaivor.
096: *
097: * @return the current case sensitivity behaivor.
098: */
099: public boolean isIgnoreCase() {
100: return getTypeHelper().isIgnoreCase();
101: }
102:
103: /**
104: * Sets the current case sensitivity behaivor.
105: *
106: * @param ignoreCase whether to ignore case.
107: */
108: protected void _setIgnoreCase(boolean ignoreCase) {
109: TypeHelper helper = getTypeHelper();
110: if (helper.isIgnoreCase() != ignoreCase) {
111: getTypeHelper().setIgnoreCase(ignoreCase);
112: fireChange();
113: }
114: }
115:
116: /**
117: * Returns the current locale.
118: *
119: * @return the current locale.
120: */
121: public Locale getLocale() {
122: return getTypeHelper().getLocale();
123: }
124:
125: // /**
126: // * Sets the current locale.
127: // *
128: // * @param locale new locale.
129: // */
130: // protected void _setLocale(Locale locale) {
131: // getTypeHelper().setLocale(locale);
132: // }
133:
134: /**
135: * Returns whether new filters should be strict.
136: * <p>
137: * E.g. when adding e GreaterThan filter, strict does not allow two values
138: * to be equal.
139: *
140: * @return whether new filters should be strict.
141: */
142: public boolean isStrict() {
143: return strict;
144: }
145:
146: /**
147: * Sets the current strickness behaivor.
148: *
149: * @param strict whether new filters should be strict.
150: */
151: protected void _setStrict(boolean strict) {
152: if (strict != this .strict) {
153: this .strict = strict;
154: fireChange();
155: }
156: }
157:
158: // General
159:
160: /**
161: * Returns the associated {@link TypeHelper}.
162: *
163: * @return TypeHelper.
164: */
165: protected TypeHelper getTypeHelper() {
166: return this .list.getTypeHelper();
167: }
168:
169: /**
170: * Retrieves the global configuration context.
171: *
172: * @return the global configuration context.
173: */
174: public ConfigurationContext getConfiguration() {
175: return (ConfigurationContext) this .list.getEnvironment()
176: .getEntry(ConfigurationContext.class);
177: }
178:
179: /**
180: * Returns the localization context.
181: *
182: * @return the localization context.
183: */
184: protected LocalizationContext getL10nCtx() {
185: return (LocalizationContext) this .list.getEnvironment()
186: .requireEntry(LocalizationContext.class);
187: }
188:
189: /**
190: * Returns the filter form.
191: *
192: * @return the filter form.
193: */
194: public FormWidget getForm() {
195: return list.getForm();
196: }
197:
198: // List fields
199:
200: /**
201: * Adds custom label for specified field. This can override already defined
202: * label of list field. Those labels are used by new filter form elements
203: * that are automatically created for list filters.
204: *
205: * @param fieldId field id.
206: * @param labelId label id (not yet resolved).
207: */
208: protected void _addCustomLabel(String fieldId, String labelId) {
209: this .labels.put(fieldId, labelId);
210: fireChange();
211: }
212:
213: /**
214: * Retrieves label for the specified field. If there are now custom label
215: * defined, one is retrieved from list fields defined in {@link ListWidget}.
216: * <p>
217: * Range filter's low and high labels are automatically generated based on
218: * the original field itself.
219: */
220: public String getFieldLabel(String fieldId) {
221: String result = (String) this .labels.get(fieldId);
222: if (result == null) {
223: result = list.getFieldLabel(fieldId);
224: }
225:
226: if (result == null) {
227: if (fieldId.endsWith(LOW_SUFFIX)) {
228: String listFieldId = getFieldIdFromLowValueId(fieldId);
229: String fieldLabel = (String) this .labels
230: .get(listFieldId);
231: if (fieldLabel == null)
232: fieldLabel = list.getFieldLabel(listFieldId);
233:
234: result = FilterFormUtil.getLabelForLowField(
235: getL10nCtx(), fieldLabel);
236: } else if (fieldId.endsWith(HIGH_SUFFIX)) {
237: String listFieldId = getFieldIdFromHighValueId(fieldId);
238: String fieldLabel = (String) this .labels
239: .get(listFieldId);
240: if (fieldLabel == null)
241: fieldLabel = list.getFieldLabel(listFieldId);
242:
243: result = FilterFormUtil.getLabelForHighField(
244: getL10nCtx(), fieldLabel);
245: }
246: }
247: return result;
248: }
249:
250: /**
251: * Defines type for specified field.
252: *
253: * @param fieldId field id.
254: * @param type field type.
255: *
256: * @see TypeHelper#addFieldType(String, Class)
257: */
258: protected void _addFieldType(String fieldId, Class type) {
259: getTypeHelper().addFieldType(fieldId, type);
260: fireChange();
261: }
262:
263: /**
264: * Retrieves type for the specified field.
265: * <p>
266: * If type is not defined for range filter's low/high value, the
267: * range filter field type is returned.
268: * </p>
269: * <p>
270: * Otherwise {@link TypeHelper#getFieldType(String)} is just called.
271: * </p>
272: *
273: * @see TypeHelper#getFieldType(String)
274: */
275: public Class getFieldType(String fieldId) {
276: Class result = getTypeHelper().getFieldType(fieldId);
277: if (result == null) {
278: if (fieldId.endsWith(LOW_SUFFIX)) {
279: result = getFieldType(getFieldIdFromLowValueId(fieldId));
280: } else if (fieldId.endsWith(HIGH_SUFFIX)) {
281: result = getFieldType(getFieldIdFromHighValueId(fieldId));
282: }
283: }
284: return result;
285: }
286:
287: /**
288: * Adds custom comparator for the specified field. This just proxies the
289: * call to TypeHelper#addCustomComparator(String, Comparator).
290: *
291: * @param fieldId field id.
292: * @param comp custom comparator.
293: *
294: * @see TypeHelper#addCustomComparator(String, Comparator)
295: */
296: public void addCustomComparator(String fieldId, Comparator comp) {
297: getTypeHelper().addCustomComparator(fieldId, comp);
298: fireChange();
299: }
300:
301: /**
302: * Retrieves comparator for the specified field. This just proxies the call
303: * to {@link TypeHelper#getFieldComparator(String)}.
304: *
305: * @see TypeHelper#getFieldComparator(String)
306: */
307: public Comparator getFieldComparator(String fieldId) {
308: Comparator result = getTypeHelper().getFieldComparator(fieldId);
309: if (result == null) {
310: if (fieldId.endsWith(LOW_SUFFIX)) {
311: result = getFieldComparator(getFieldIdFromLowValueId(fieldId));
312: } else if (fieldId.endsWith(HIGH_SUFFIX)) {
313: result = getFieldComparator(getFieldIdFromHighValueId(fieldId));
314: }
315: }
316: return result;
317: }
318:
319: // Value ids
320:
321: /**
322: * Transforms the field id into value id.
323: * <p>
324: * The same string is returned.
325: *
326: * @param fieldId field id.
327: * @return value id.
328: */
329: public String getValueId(String fieldId) {
330: return fieldId;
331: }
332:
333: /**
334: * Transform the field id into range filter's low value id.
335: * <p>
336: * The {@link #LOW_SUFFIX} is appended to the field id.
337: *
338: * @param fieldId field id.
339: * @return low value id.
340: */
341: public String getLowValueId(String fieldId) {
342: return fieldId + LOW_SUFFIX;
343: }
344:
345: /**
346: * Transform the field id into range filter's high value id.
347: * <p>
348: * The {@link #HIGH_SUFFIX} is appended to the field id.
349: *
350: * @param fieldId field id.
351: * @return high value id.
352: */
353: public String getHighValueId(String fieldId) {
354: return fieldId + HIGH_SUFFIX;
355: }
356:
357: /**
358: * Transforms the value id into field id.
359: * <p>
360: * The same string is returned.
361: *
362: * @param valueId value id.
363: * @return field id.
364: */
365: public String getFieldId(String valueId) {
366: return valueId;
367: }
368:
369: /**
370: * Transforms the range filter's low value id into field id.
371: * <p>
372: * The {@link #LOW_SUFFIX} is removed from the end.
373: *
374: * @param lowValueId low value id.
375: * @return field id.
376: */
377: public String getFieldIdFromLowValueId(String lowValueId) {
378: return StringUtils.substringBeforeLast(lowValueId, LOW_SUFFIX);
379: }
380:
381: /**
382: * Transforms the range filter's high value id into field id.
383: * <p>
384: * The {@link #HIGH_SUFFIX} is removed from the end.
385: *
386: * @param highValueId high value id.
387: * @return field id.
388: */
389: public String getFieldIdFromHighValueId(String highValueId) {
390: return StringUtils
391: .substringBeforeLast(highValueId, HIGH_SUFFIX);
392: }
393:
394: /**
395: * @since 1.1
396: */
397: protected void fireChange() {
398: changed = true;
399: }
400:
401: /**
402: * Returns whether the basic configuration that specifies which items are
403: * shown has changed since last call to this {@link BaseFilterHelper}'s {@link BaseFilterHelper#checkChanged()}
404: * method.
405: *
406: * @since 1.1
407: */
408: public boolean checkChanged() {
409: boolean result = changed;
410: changed = false;
411: return result;
412: }
413: }
|