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 }