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.support;
017
018 import java.util.HashMap;
019 import java.util.Iterator;
020 import java.util.List;
021 import java.util.Map;
022
023 import org.apache.commons.logging.Log;
024 import org.apache.commons.logging.LogFactory;
025 import org.springframework.core.style.ToStringCreator;
026 import org.springframework.richclient.util.ClassUtils;
027 import org.springframework.rules.Rules;
028 import org.springframework.rules.RulesSource;
029 import org.springframework.rules.constraint.ConstraintsAccessor;
030 import org.springframework.rules.constraint.property.PropertyConstraint;
031 import org.springframework.util.Assert;
032 import org.springframework.util.CachingMapDecorator;
033 import org.springframework.util.StringUtils;
034
035 /**
036 * A default rules source implementation which is simply a in-memory registry for bean validation rules backed by a map.
037 *
038 * @author Keith Donald
039 */
040 public class DefaultRulesSource extends ConstraintsAccessor implements RulesSource {
041 protected final Log logger = LogFactory.getLog(getClass());
042
043 private static final String DEFAULT_CONTEXT_ID = "default";
044
045 private Map ruleContexts = new CachingMapDecorator() {
046 protected Object create(Object key) {
047 return new HashMap();
048 }
049 };
050
051 /**
052 * Add or update the rules for a single bean class.
053 *
054 * @param rules
055 * The rules.
056 */
057 public void addRules(Rules rules) {
058 if (logger.isDebugEnabled()) {
059 logger.debug("Adding rules -> " + rules);
060 }
061 addRules(DEFAULT_CONTEXT_ID, rules);
062 }
063
064 public void addRules(String contextId, Rules rules) {
065 Assert.notNull(contextId);
066 Assert.notNull(rules);
067 Map context = getRuleContext(contextId);
068 context.put(rules.getDomainObjectType(), rules);
069 }
070
071 private Map getRuleContext(String contextId) {
072 return (Map) ruleContexts.get(contextId);
073 }
074
075 /**
076 * Set the list of rules retrievable by this source, where each item in the list is a <code>Rules</code> object
077 * which maintains validation rules for a bean class.
078 *
079 * @param rules
080 * The list of rules.
081 */
082 public void setRules(List rules) {
083 Assert.notNull(rules);
084 if (logger.isDebugEnabled()) {
085 logger.debug("Configuring rules in source...");
086 }
087 getRuleContext(DEFAULT_CONTEXT_ID).clear();
088 for (Iterator i = rules.iterator(); i.hasNext();) {
089 addRules((Rules) i.next());
090 }
091 }
092
093 public Rules getRules(Class bean) {
094 return getRules(bean, DEFAULT_CONTEXT_ID);
095 }
096
097 public Rules getRules(Class beanType, String contextId) {
098 Assert.notNull(beanType);
099 if (!StringUtils.hasText(contextId)) {
100 contextId = DEFAULT_CONTEXT_ID;
101 }
102 return (Rules) ClassUtils.getValueFromMapForClass(beanType, getRuleContext(contextId));
103 }
104
105 public PropertyConstraint getPropertyConstraint(Class bean, String propertyName) {
106 return getPropertyConstraint(bean, propertyName, DEFAULT_CONTEXT_ID);
107 }
108
109 public PropertyConstraint getPropertyConstraint(Class bean, String propertyName, String contextId) {
110 if (logger.isDebugEnabled()) {
111 logger.debug("Retrieving rules for bean '" + bean + "', context = " + contextId + ", property '"
112 + propertyName + "'");
113 }
114 Rules rules = getRules(bean, contextId);
115 if (rules != null)
116 return rules.getPropertyConstraint(propertyName);
117
118 return null;
119 }
120
121 public String toString() {
122 return new ToStringCreator(this).append("rules", ruleContexts).toString();
123 }
124
125 }