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 }