blob: 67aec02bdee22e2705a2be968d8dd6569bef4c3f [file] [log] [blame]
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.apache.taglibs.rdc;
import java.util.regex.Pattern;
import org.apache.taglibs.rdc.core.BaseModel;
/**
* Datamodel for the duration RDC. The duration RDC will be associated
* with the duration input, the maximum and minimum
* duration within which the input's duration must lie, and a pattern to
* which the input must conform.
*
* @author Sindhu Unnikrishnan
* @author Rahul Akolkar
*/
public class Duration extends BaseModel {
//The duration RDC will be associated
//with the duration input, the maximum and minimum
//duration within which the input's duration must lie, and a pattern to
//which the input must conform.
// Serial Version UID
private static final long serialVersionUID = 1L;
// value returned cannot be more than this value
private String maxDuration;
// value returned cannot be less than this value
private String minDuration;
// The duration input must conform to this pattern
private String pattern;
//Error codes defined in the configuration file
/**A constant for Error Code stating Invalid duration */
public static final int ERR_INVALID_DURATION = 1;
/**A constant for Error Code stating the duration entered is
* larger than allowed */
public static final int ERR_NEED_LOWER_VALUE = 2;
/**A constant for Error Code stating the duration entered is
* smaller than allowed */
public static final int ERR_NEED_HIGHER_VALUE = 3;
//this constant that checks whether one value is less than the other
private static final int LESS = -1;
//this constant constant checks whether two values are equal
private static final int EQUAL = 0;
//this constant checks whether one value is more than the other
private static final int MORE = 1;
/**
* Sets default values for all data members
*/
public Duration() {
super();
maxDuration = null;
minDuration = null;
this.pattern = "P([0-9]{2}Y)?([0-9]{2}M)?([0-9]{2}D)?";
}
/**
* Gets the maximum Duration that a user has specified in the attirbute
* @return the user specified maximum duration
*/
public String getMaxDuration() {
return maxDuration;
}
/**
* Sets the maximum Duration value.
* @param maxDuration The maximum duration value.
*/
public void setMaxDuration(String maxDuration) {
if (maxDuration != null) {
this.maxDuration = (String)canonicalize(maxDuration, true);
}
}
/**
* Gets what minimum duration that a user has specified in the attirbute
* @return the user specified minimum duration
*/
public String getMinDuration() {
return minDuration;
}
/**
* Sets the minimum duration value.
* @param minDuration The minimum duration value.
*/
public void setMinDuration(String minDuration) {
if (minDuration != null) {
this.minDuration = (String)canonicalize(minDuration, true);
}
}
/**
* Validates the received input against the validation constraints
* @return true if valid, false if invalid
*/
protected Boolean validate(Object newValue, boolean setErrorCode) {
if (pattern != null && !(Pattern.matches(pattern, (String)newValue))) {
if (setErrorCode) setErrorCode(ERR_INVALID_DURATION);
return Boolean.FALSE;
}
if (cmpDuration((String) newValue, minDuration) == LESS) {
if (setErrorCode) setErrorCode(ERR_NEED_HIGHER_VALUE);
return Boolean.FALSE;
} else if (cmpDuration((String) newValue, maxDuration) == MORE) {
if (setErrorCode) setErrorCode(ERR_NEED_LOWER_VALUE);
return Boolean.FALSE;
}
return Boolean.TRUE;
}
/**
* This method returns the full duration format if either partial
* duration is spoken or retuns full duration if input is
* full duration
*
* @param input The duration value(either partial or full)
* @return The full duration format
*/
protected Object canonicalize(Object input, boolean isAttribute) {
if (input == null) {
return null;
}
String inputStr = (String) input;
int INDEX_YEAR_END = inputStr.indexOf('Y');
int INDEX_MONTH_END = inputStr.indexOf('M');
int INDEX_DAY_END = inputStr.indexOf('D');
if (!(Pattern.matches(pattern, inputStr))) {
if (isAttribute) {
throw new IllegalArgumentException("The required value \"" +
inputStr + "\" does not match the expected pattern for " +
"duration RDC with ID " + getId());
} else {
setErrorCode(ERR_INVALID_DURATION);
return null;
}
} else {
if (INDEX_YEAR_END == -1) {
inputStr = "P00Y" + (inputStr.length() > 1 ?
inputStr.substring(1) : "");
}
if (INDEX_DAY_END == -1) {
inputStr += "00D";
}
if (INDEX_MONTH_END == -1) {
inputStr = inputStr.substring(0,inputStr.indexOf('Y')) + "Y00M"
+ inputStr.substring(inputStr.indexOf('Y')+1);
}
}
return inputStr;
}
/**
* This method compares the minimum and maximu durations
* against the input and returns LESS,MORE or EQUAL accordingly
*
* @param s1 the duration value
* @param s2 could be minimum and maximum durations
*
* @return could be LESS,MORE or EQUAL
*/
private int cmpDuration(String s1, String s2) {
int INDEX_YEAR_END = s1.indexOf('Y');
int INDEX_MONTH_END = s1.indexOf('M');
int INDEX_DAY_END = s1.indexOf('D');
int INDEX_YEAR_BEGIN = s1.indexOf('P') + 1;
int INDEX_MONTH_BEGIN = INDEX_MONTH_END - 2;
int INDEX_DAY_BEGIN = INDEX_DAY_END - 2;
switch (cmp(Integer.parseInt(s1.substring(INDEX_YEAR_BEGIN,
INDEX_YEAR_END)), Integer.parseInt(s2.substring(INDEX_YEAR_BEGIN,
INDEX_YEAR_END)))) {
case LESS :
return LESS;
case MORE :
return MORE;
case EQUAL :
switch (cmp(Integer.parseInt(s1.substring(INDEX_MONTH_BEGIN,
INDEX_MONTH_END)), Integer.parseInt(s2.
substring(INDEX_MONTH_BEGIN, INDEX_MONTH_END)))) {
case LESS :
return LESS;
case MORE :
return MORE;
case EQUAL :
switch (cmp(Integer.parseInt(s1.
substring(INDEX_DAY_BEGIN, INDEX_DAY_END)),
Integer.parseInt(s2.substring(INDEX_DAY_BEGIN,
INDEX_DAY_END)))) {
case LESS :
return LESS;
case MORE :
return MORE;
}
}
}
return EQUAL;
}
/**
* Compares the minimum and maximum durations
* against the duration input and returns LESS,MORE or
* EQUAL accordingly
*
* @param a the duration value
* @param b could be minimum and maximum durations
* @return could be LESS,MORE or EQUAL
*/
private int cmp(int a, int b) {
return a < b ? LESS : a > b ? MORE : EQUAL;
}
}