001    package org.apache.fulcrum.intake.validator;
002    
003    /*
004     * Licensed to the Apache Software Foundation (ASF) under one
005     * or more contributor license agreements.  See the NOTICE file
006     * distributed with this work for additional information
007     * regarding copyright ownership.  The ASF licenses this file
008     * to you under the Apache License, Version 2.0 (the
009     * "License"); you may not use this file except in compliance
010     * with the License.  You may obtain a copy of the License at
011     *
012     *   http://www.apache.org/licenses/LICENSE-2.0
013     *
014     * Unless required by applicable law or agreed to in writing,
015     * software distributed under the License is distributed on an
016     * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
017     * KIND, either express or implied.  See the License for the
018     * specific language governing permissions and limitations
019     * under the License.
020     */
021    
022    import java.util.Map;
023    import java.util.regex.Pattern;
024    import java.util.regex.PatternSyntaxException;
025    
026    import org.apache.commons.lang.StringUtils;
027    
028    /**
029     * A validator that will compare a testValue against the following
030     * constraints:
031     * <table>
032     * <tr><th>Name</th><th>Valid Values</th><th>Default Value</th></tr>
033     * <tr><td>required</td><td>true|false</td><td>false</td></tr>
034     * <tr><td>mask</td><td>regexp</td><td>&nbsp;</td></tr>
035     * <tr><td>minLength</td><td>integer</td><td>0</td></tr>
036     * <tr><td>maxLength</td><td>integer</td><td>&nbsp;</td></tr>
037     * </table>
038     *
039     * This validator can serve as the base class for more specific validators
040     *
041     * @author <a href="mailto:jmcnally@collab.net">John McNally</a>
042     * @author <a href="mailto:quintonm@bellsouth.net">Quinton McCombs</a>
043     * @author <a href="mailto:Colin.Chalmers@maxware.nl">Colin Chalmers</a>
044     * @author <a href="mailto:jh@byteaction.de">J&uuml;rgen Hoffmann</a>
045     * @author <a href="mailto:tv@apache.org">Thomas Vandahl</a>
046     * @version $Id: StringValidator.java 832048 2009-11-02 18:55:08Z tv $
047     */
048    public class StringValidator
049            extends DefaultValidator
050    {
051        /** The matching mask String as supplied by the XML input */
052        protected String maskString = null;
053    
054        /** The compiled Regular Expression */
055        protected Pattern maskPattern = null;
056    
057        /** The message to report if the mask constraint is not satisfied */
058        protected String maskMessage = null;
059    
060    
061        /**
062         * Constructor
063         *
064         * @param paramMap a <code>Map</code> of <code>Rule</code>'s
065         * containing constraints on the input.
066         * @exception InvalidMaskException An invalid mask was specified for one of the rules
067    
068        */
069        public StringValidator(Map paramMap)
070                throws InvalidMaskException
071        {
072            init(paramMap);
073        }
074    
075        /**
076         * Default constructor
077         */
078        public StringValidator()
079        {
080            // do nothing
081        }
082    
083        /**
084         * Extract the relevant parameters from the constraints listed
085         * in <rule> tags within the intake.xml file.
086         *
087         * @param paramMap a <code>Map</code> of <code>Rule</code>'s
088         * containing constraints on the input.
089         * @exception InvalidMaskException An invalid mask was specified for one of the rules
090         */
091        public void init(Map paramMap)
092                throws InvalidMaskException
093        {
094            super.init(paramMap);
095    
096            Constraint constraint = (Constraint) paramMap.get(MASK_RULE_NAME);
097            if (constraint != null)
098            {
099                String param = constraint.getValue();
100                setMask(param);
101                maskMessage = constraint.getMessage();
102            }
103    
104        }
105    
106        /**
107         * Determine whether a testValue meets the criteria specified
108         * in the constraints defined for this validator
109         *
110         * @param testValue a <code>String</code> to be tested
111         * @exception ValidationException containing an error message if the
112         * testValue did not pass the validation tests.
113         */
114        public void assertValidity(String testValue)
115                throws ValidationException
116        {
117            super.assertValidity(testValue);
118    
119            if ((required || StringUtils.isNotEmpty(testValue)) && maskPattern != null)
120            {
121                /** JDK 1.4 matcher */
122                boolean patternMatch = maskPattern.matcher(testValue).matches();
123    
124                log.debug("Trying to match " + testValue
125                        + " to pattern " + maskString);
126    
127                if (!patternMatch)
128                {
129                    errorMessage = maskMessage;
130                    throw new ValidationException(maskMessage);
131                }
132            }
133        }
134    
135        // ************************************************************
136        // **                Bean accessor methods                   **
137        // ************************************************************
138    
139        /**
140         * Get the value of mask.
141         *
142         * @return value of mask.
143         */
144        public String getMask()
145        {
146            return maskString;
147        }
148    
149        /**
150         * Set the value of mask.
151         *
152         * @param mask  Value to assign to mask.
153         * @throws InvalidMaskException the mask could not be compiled.
154         */
155        public void setMask(String mask)
156                throws InvalidMaskException
157        {
158            maskString = mask;
159    
160            // Fixme. We should make this configureable by the XML file -- hps
161            int maskOptions = 0;
162    
163            try
164            {
165                log.debug("Compiling pattern " + maskString);
166                maskPattern = Pattern.compile(maskString, maskOptions);
167            }
168            catch (PatternSyntaxException pe)
169            {
170                throw new InvalidMaskException("Could not compile pattern " + maskString, pe);
171            }
172        }
173    
174        /**
175         * Get the value of maskMessage.
176         *
177         * @return value of maskMessage.
178         */
179        public String getMaskMessage()
180        {
181            return maskMessage;
182        }
183    
184        /**
185         * Set the value of maskMessage.
186         *
187         * @param message  Value to assign to maskMessage.
188         */
189        public void setMaskMessage(String message)
190        {
191            this.maskMessage = message;
192        }
193    }