001/** 002 * Copyright 2005-2016 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 */ 016package org.kuali.rice.krad.datadictionary.validation.constraint; 017 018import org.kuali.rice.krad.datadictionary.parse.BeanTag; 019import org.kuali.rice.krad.datadictionary.parse.BeanTagAttribute; 020import org.kuali.rice.krad.datadictionary.validator.ValidationTrace; 021import org.kuali.rice.krad.messages.MessageService; 022import org.kuali.rice.krad.service.KRADServiceLocatorWeb; 023import org.kuali.rice.krad.uif.UifConstants; 024 025import java.util.ArrayList; 026import java.util.List; 027 028/** 029 * Validation pattern for matching fixed point numbers, optionally matching negative numbers 030 * 031 * <p> 032 * Only allows a numeric value where the precision property represents the maximum number of 033 * total numbers allowed, and scale represents the minimum numbers after the decimal point. 034 * The decimal places are implied to be 0 if not included and still count towards total 035 * numbers allowed. 036 * </p> 037 * 038 * @author Kuali Rice Team (rice.collab@kuali.org) 039 */ 040@BeanTag(name = "fixedPointPatternConstraint", parent = "FixedPointPatternConstraint") 041public class FixedPointPatternConstraint extends ValidDataPatternConstraint { 042 043 protected boolean allowNegative; 044 protected int precision; 045 protected int scale; 046 047 /** 048 * Overriding retrieval of 049 * 050 * @see org.kuali.rice.krad.datadictionary.validation.constraint.ValidCharactersPatternConstraint#getRegexString() 051 */ 052 @Override 053 protected String getRegexString() { 054 StringBuilder regex = new StringBuilder(); 055 056 if (getPrecision() < 0 || getScale() < 0 || getPrecision() - getScale() < 0){ 057 throw new RuntimeException("Precision and scale cannot be negative AND scale cannot be greater than " 058 + "precision for FixedPointPatternConstraints!"); 059 } 060 061 if (isAllowNegative()) { 062 regex.append("-?"); 063 } 064 // final pattern will be: -?([0-9]{0,p-s}\.[0-9]{1,s}|[0-9]{1,p-s}) where p = precision, s=scale 065 066 regex.append("("); 067 if(getPrecision() - getScale() > 0){ 068 regex.append("[0-9]{0," + (getPrecision() - getScale()) + "}"); 069 } 070 regex.append("\\."); 071 regex.append("[0-9]{1," + getScale() + "}"); 072 if(getPrecision() - getScale() > 0){ 073 regex.append("|[0-9]{1," + (getPrecision() - getScale()) + "}"); 074 } 075 regex.append(")"); 076 return regex.toString(); 077 } 078 079 /** 080 * @return the allowNegative 081 */ 082 @BeanTagAttribute(name = "allowNegative") 083 public boolean isAllowNegative() { 084 return this.allowNegative; 085 } 086 087 /** 088 * @param allowNegative the allowNegative to set 089 */ 090 public void setAllowNegative(boolean allowNegative) { 091 this.allowNegative = allowNegative; 092 } 093 094 /** 095 * @return the precision 096 */ 097 @BeanTagAttribute(name = "precision") 098 public int getPrecision() { 099 return this.precision; 100 } 101 102 /** 103 * @param precision the precision to set 104 */ 105 public void setPrecision(int precision) { 106 this.precision = precision; 107 } 108 109 /** 110 * @return the scale 111 */ 112 @BeanTagAttribute(name = "scale") 113 public int getScale() { 114 return this.scale; 115 } 116 117 /** 118 * @param scale the scale to set 119 */ 120 public void setScale(int scale) { 121 this.scale = scale; 122 } 123 124 /** 125 * This overridden method ... 126 * 127 * @see org.kuali.rice.krad.datadictionary.validation.constraint.ValidDataPatternConstraint#getValidationMessageParams() 128 */ 129 @Override 130 public List<String> getValidationMessageParams() { 131 if (validationMessageParams == null) { 132 validationMessageParams = new ArrayList<String>(); 133 MessageService messageService = KRADServiceLocatorWeb.getMessageService(); 134 if (allowNegative) { 135 validationMessageParams.add(messageService.getMessageText( 136 UifConstants.Messages.VALIDATION_MSG_KEY_PREFIX + "positiveOrNegative")); 137 } else { 138 validationMessageParams.add(messageService.getMessageText( 139 UifConstants.Messages.VALIDATION_MSG_KEY_PREFIX + "positiveOrZero")); 140 } 141 142 validationMessageParams.add(Integer.toString(precision)); 143 validationMessageParams.add(Integer.toString(scale)); 144 } 145 return validationMessageParams; 146 } 147 148 /** 149 * Validates different requirements of component compiling a series of reports detailing information on errors 150 * found in the component. Used by the RiceDictionaryValidator. 151 * 152 * @param tracer Record of component's location 153 */ 154 @Override 155 public void completeValidation(ValidationTrace tracer) { 156 tracer.addBean("FixedPointPatternConstraint", getMessageKey()); 157 158 if (getPrecision() <= getScale()) { 159 String currentValues[] = {"precision =" + getPrecision(), "scale = " + getScale()}; 160 tracer.createError("Precision should greater than Scale", currentValues); 161 } 162 163 super.completeValidation(tracer.getCopy()); 164 } 165 166}