001 /** 002 * Copyright 2005-2012 The Kuali Foundation 003 * 004 * Licensed under the Educational Community 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.opensource.org/licenses/ecl2.php 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 */ 016 package org.kuali.rice.krad.datadictionary.validation.constraint; 017 018 import java.util.ArrayList; 019 import java.util.Arrays; 020 import java.util.Collections; 021 import java.util.List; 022 023 import org.apache.commons.lang.StringUtils; 024 import org.kuali.rice.core.api.CoreConstants; 025 import org.kuali.rice.core.api.config.property.ConfigContext; 026 import org.kuali.rice.core.api.config.property.ConfigurationService; 027 import org.kuali.rice.krad.service.KRADServiceLocator; 028 import org.kuali.rice.krad.uif.UifConstants; 029 030 /** 031 * DatePatternConstraint constrains a field to only allow dates which are part of the formats 032 * defined in the system. Constraining a field all these formats is often not appropriate for 033 * fields, and you may want to constrain the input to a subset of the allowed formats in the system. 034 * This can be done by setting the allowed formats to this subset (see BasicDatePatternConstraint 035 * bean for example) 036 * 037 * @author Kuali Rice Team (rice.collab@kuali.org) 038 */ 039 public class DatePatternConstraint extends ValidDataPatternConstraint { 040 041 private List<String> allowedFormats; 042 043 /** 044 * Returns a regex representing all the allowed formats in the system. If allowedFormats is 045 * supplied, returns a regex representing only those formats. 046 * 047 * @see org.kuali.rice.krad.datadictionary.validation.constraint.ValidDataPatternConstraint#getRegexString() 048 */ 049 @Override 050 protected String getRegexString() { 051 List<String> dateFormatParams = 052 parseConfigValues(ConfigContext.getCurrentContextConfig().getProperty( 053 CoreConstants.STRING_TO_DATE_FORMATS)); 054 if (allowedFormats != null && !allowedFormats.isEmpty()) { 055 if (dateFormatParams.containsAll(allowedFormats)) { 056 dateFormatParams = allowedFormats; 057 } else { 058 //throw new Exception("Some of these formats do not exist in configured allowed date formats: " + allowedFormats.toString()); 059 } 060 } 061 062 if (dateFormatParams.isEmpty()) { 063 //exception 064 } 065 String regex = ""; 066 int i = 0; 067 for (String format : dateFormatParams) { 068 if (i == 0) { 069 regex = "(^" + convertDateFormatToRegex(format.trim()) + "$)"; 070 } else { 071 regex = regex + "|(^" + convertDateFormatToRegex(format.trim()) + "$)"; 072 } 073 i++; 074 } 075 return regex; 076 } 077 078 /** 079 * Converts a date format supplied to the appropriate date format regex equivalent 080 * 081 * @param format 082 * @return 083 */ 084 private String convertDateFormatToRegex(String format) { 085 format = format.replace("\\", "\\\\") 086 .replace(".", "\\.") 087 .replace("-", "\\-") 088 .replace("+", "\\+") 089 .replace("(", "\\(") 090 .replace(")", "\\)") 091 .replace("[", "\\[") 092 .replace("]", "\\]") 093 .replace("|", "\\|") 094 .replace("yyyy", "((19|2[0-9])[0-9]{2})") 095 .replace("yy", "([0-9]{2})") 096 .replaceAll("M{4,}", "([@]+)") //"(January|February|March|April|May|June|July|August|September|October|November|December)") 097 .replace("MMM", "([@]{3})") //"(Jan|Feb|Mar|Apr|May|Jun|Jul|Aug|Sep|Oct|Nov|Dec)") 098 .replace("MM", "(0[1-9]|1[012])") 099 .replace("M", "(0?[1-9]|1[012])") 100 .replace("dd", "(0[1-9]|[12][0-9]|3[01])") 101 .replace("d", "(0?[1-9]|[12][0-9]|3[01])") 102 .replace("hh", "(1[0-2]|0[1-9])") 103 .replace("h", "(1[0-2]|0?[1-9])") 104 .replace("HH", "(2[0-3]|1[0-9]|0[0-9])") 105 .replace("H", "(2[0-3]|1[0-9]|0?[0-9])") 106 .replace("kk", "(2[0-4]|1[0-9]|0[1-9])") 107 .replace("k", "(2[0-4]|1[0-9]|0?[1-9])") 108 .replace("KK", "(1[01]|0[0-9])") 109 .replace("K", "(1[01]|0?[0-9])") 110 .replace("mm", "([0-5][0-9])") 111 .replace("m", "([1-5][0-9]|0?[0-9])") 112 .replace("ss", "([0-5][0-9])") 113 .replace("s", "([1-5][0-9]|0?[0-9])") 114 .replace("SSS", "([0-9][0-9][0-9])") 115 .replace("SS", "([0-9][0-9][0-9]?)") 116 .replace("S", "([0-9][0-9]?[0-9]?)") 117 .replaceAll("E{4,}", "([@]+)")//"(Monday|Tuesday|Wednesday|Thursday|Friday|Saturday|Sunday)") 118 .replaceAll("E{1,3}", "([@]{3})")//"(Mon|Tue|Wed|Thu|Fri|Sat|Sun)") 119 .replace("DDD", "(3[0-6][0-5]|[1-2][0-9][0-9]|0[0-9][1-9])") 120 .replace("DD", "(3[0-6][0-5]|[1-2][0-9][0-9]|0?[0-9][1-9])") 121 .replace("D", "(3[0-6][0-5]|[1-2][0-9][0-9]|0?[0-9]?[1-9])") 122 .replace("F", "([1-5])") 123 .replace("ww", "(5[0-3]|[1-4][0-9]|0[1-9])") 124 .replace("w", "(5[0-3]|[1-4][0-9]|[1-9])") 125 .replace("W", "([1-5])") 126 .replaceAll("z{4,}", "([@]+)") 127 .replaceAll("z{1,3}", "([@]{1,4})") 128 .replaceAll("a{1,}", "([aApP][mM])") 129 .replaceAll("G{1,}", "([aA][dD]|[bB][cC])") 130 .replace(" ", "\\s") 131 .replace("@", "a-zA-Z"); 132 133 return format; 134 135 } 136 137 /** 138 * 139 * The dateTime config vars are ';' seperated. 140 * 141 * @param configValue 142 * @return 143 */ 144 private List<String> parseConfigValues(String configValue) { 145 if (configValue == null || "".equals(configValue)) { 146 return Collections.emptyList(); 147 } 148 return Arrays.asList(configValue.split(";")); 149 } 150 151 /** 152 * @return the allowedFormats 153 */ 154 public List<String> getAllowedFormats() { 155 return this.allowedFormats; 156 } 157 158 /** 159 * Sets the alloweFormats for this constraint, this must be a subset of the system configured 160 * formats for a date - this list should be used for most fields where you are expecting a user 161 * to enter a date in a specific format 162 * @param allowedFormats the allowedFormats to set 163 */ 164 public void setAllowedFormats(List<String> allowedFormats) { 165 this.allowedFormats = allowedFormats; 166 } 167 168 /** 169 * This overridden method ... 170 * 171 * @see org.kuali.rice.krad.datadictionary.validation.constraint.ValidDataPatternConstraint#getValidationMessageParams() 172 */ 173 @Override 174 public List<String> getValidationMessageParams() { 175 if (validationMessageParams == null) { 176 validationMessageParams = new ArrayList<String>(); 177 if (allowedFormats != null && !allowedFormats.isEmpty()) { 178 validationMessageParams.add(StringUtils.join(allowedFormats, ", ")); 179 } else { 180 List<String> dateFormatParams = 181 parseConfigValues(ConfigContext.getCurrentContextConfig().getProperty( 182 CoreConstants.STRING_TO_DATE_FORMATS)); 183 validationMessageParams.add(StringUtils.join(dateFormatParams, ", ")); 184 } 185 } 186 return validationMessageParams; 187 } 188 189 }