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.form.constraint;
016:
017: import java.text.Collator;
018: import org.araneaframework.Environment;
019: import org.araneaframework.core.AraneaRuntimeException;
020: import org.araneaframework.framework.LocalizationContext;
021: import org.araneaframework.uilib.form.FormElement;
022: import org.araneaframework.uilib.support.UiLibMessages;
023: import org.araneaframework.uilib.util.MessageUtil;
024:
025: /**
026: * Given two form elements checks that their values are one after another.
027: * It assumes that the values of both form elements are of the same type and comparable.
028: *
029: * TODO: Add locale support for string ranges.
030: *
031: * @author <a href="mailto:kt@webmedia.ee">Konstantin Tretyakov</a>
032: * XXX: this is one messy constraint.
033: */
034: public final class RangeConstraint extends BaseConstraint {
035:
036: protected boolean allowEquals;
037: protected FormElement fieldLo, fieldHi;
038:
039: /**
040: * @param fieldLo The value of this field is checked to be less than the value of fieldHi (or null)
041: * @param fieldHi The value of this field is checked to be greater than the value of fieldLo (or null)
042: * @param allowEquals If this is true, the constraint will be considered satisfied when values of fieldLo and fieldHi are
043: * equal. Otherwise the constraint won't be satisfied in this case.
044: */
045: public RangeConstraint(FormElement fieldLo, FormElement fieldHi,
046: boolean allowEquals) {
047: this .allowEquals = allowEquals;
048: this .fieldHi = fieldHi;
049: this .fieldLo = fieldLo;
050: }
051:
052: protected void validateConstraint() {
053: Object valueLo = fieldLo.getData().getValue();
054: Object valueHi = fieldHi.getData().getValue();
055:
056: // If any of the values is null, we stay quiet no matter what.
057: if (valueLo == null || valueHi == null)
058: return;
059:
060: boolean loExtendsHi;
061:
062: if (valueHi.getClass().isAssignableFrom(valueLo.getClass()))
063: loExtendsHi = true;
064: else if (valueLo.getClass()
065: .isAssignableFrom(valueHi.getClass()))
066: loExtendsHi = false;
067: else
068: throw new AraneaRuntimeException(
069: "RangeConstraint can be used only with fields of compatible types.");
070:
071: int comparison = 0; // Will be -1, 0 or 1 depending on whether sLo is <, = or > than sHi
072:
073: // Strings are handled separately because we have to compare them in given locale.
074: if (valueLo instanceof String && valueHi instanceof String) {
075: Collator collator = Collator.getInstance(); // TODO: Must be locale-specific
076: comparison = collator.compare((String) valueLo,
077: (String) valueHi);
078: } else if (valueLo instanceof Comparable
079: && valueHi instanceof Comparable) {
080: if (loExtendsHi)
081: comparison = ((Comparable) valueLo).compareTo(valueHi);
082: else
083: comparison = -1
084: * ((Comparable) valueHi).compareTo(valueLo);
085: } else { // Objects are not comparable
086: throw new AraneaRuntimeException(
087: "RangeConstraint expects fields of Comparable type");
088: }
089:
090: if (comparison > 0 || (!allowEquals && comparison == 0)) {
091: addError(MessageUtil.localizeAndFormat(
092: UiLibMessages.RANGE_CHECK_FAILED, t(fieldLo
093: .getLabel(), fieldLo.getEnvironment()), t(
094: fieldHi.getLabel(), fieldHi
095: .getEnvironment()),
096: getEnvironment()));
097: }
098: }
099:
100: private String t(String key, Environment env) {
101: LocalizationContext locCtx = (LocalizationContext) env
102: .getEntry(LocalizationContext.class);
103: return locCtx.localize(key);
104: }
105:
106: }
|