001    /*
002     * Copyright 2002-2004 the original author or authors.
003     * 
004     * Licensed under the Apache License, Version 2.0 (the "License"); you may not
005     * use this file except in compliance with the License. You may obtain a copy of
006     * 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, WITHOUT
012     * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
013     * License for the specific language governing permissions and limitations under
014     * the License.
015     */
016    package org.springframework.rules.constraint;
017    
018    import java.util.Collection;
019    import java.util.Map;
020    
021    import org.springframework.rules.constraint.Constraint;
022    import org.springframework.rules.reporting.TypeResolvable;
023    import org.springframework.util.StringUtils;
024    
025    /**
026     * Validates a required property. Required is defined as non-null and, if the
027     * object is a string, not empty and not blank. If the object is an instance of
028     * {@link Collection}, {@link Map} or an array it will test if it is empty.
029     * 
030     * @author Keith Donald
031     * @author Mathias Broekelmann
032     */
033    public class Required implements Constraint, TypeResolvable {
034            private static final Required required = new Required();
035    
036            private static final Required present = new Required("present");
037    
038            private final String type;
039    
040            /**
041             * Creates a required constraint by using a custom type. This is primarly
042             * used to separate required and present constraint. These constraints where
043             * equaly implemented but where used differently
044             * 
045             * @param type the type of the constraint. see {@link #getType()}
046             */
047            public Required(String type) {
048                    this.type = type;
049            }
050    
051            /**
052             * Default constructor which creates a required constraint by using the type
053             * <code>required</code>
054             */
055            public Required() {
056                    this("required");
057            }
058    
059            /**
060             * Tests if this argument is present (non-null, not-empty, not blank)
061             * 
062             * @see Constraint#test(java.lang.Object)
063             */
064            public boolean test(Object argument) {
065                    if (argument != null) {
066                            if (argument instanceof String) {
067                                    if (StringUtils.hasText((String) argument)) {
068                                            return true;
069                                    }
070                            }
071                            else if (argument instanceof Collection) {
072                                    return !((Collection) argument).isEmpty();
073                            }
074                            else if (argument instanceof Map) {
075                                    return !((Map) argument).isEmpty();
076                            }
077                            else if (argument.getClass().isArray()) {
078                                    return ((Object[]) argument).length > 0;
079                            }
080                            else {
081                                    return true;
082                            }
083                    }
084                    return false;
085            }
086    
087            /**
088             * returns the required instance
089             * 
090             * @return the required instance (never null)
091             */
092            public static Required instance() {
093                    return required;
094            }
095    
096            /**
097             * returns the present instance
098             * 
099             * @return the present instance (never null)
100             */
101            public static Required present() {
102                    return present;
103            }
104    
105            public String toString() {
106                    return getType();
107            }
108    
109            public String getType() {
110                    return type;
111            }
112    }