001 /* 002 * Copyright 2002-2006 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 017 package org.springframework.binding.support; 018 019 import java.util.Map; 020 import java.util.LinkedHashMap; 021 import java.beans.PropertyDescriptor; 022 import java.lang.annotation.Annotation; 023 024 import org.springframework.binding.value.ValueModel; 025 import org.springframework.richclient.util.AnnotationUtils; 026 import org.springframework.util.Assert; 027 028 /** 029 * A JavaBean {@link org.springframework.binding.PropertyAccessStrategy 030 * PropertyAccessStrategy} that exposes JDK 1.5 Annotations for each property 031 * in the form of property level user metadata. In order to remain backward 032 * compatible with 1.4 code, the annotations will be parsed by an installed 033 * {@link AnnotationTranslator} which typically stores the content of each 034 * annotation as key + value pairs in the user metadata. If no translator is 035 * explicitly set, then this implementation will use 036 * {@link ReflectionAnnotationTranslator} by default. 037 * <p/> 038 * Note that this implementation will scan for annotations on both the getter 039 * and setter methods of the property. If both getter and setter happen to 040 * define the same annotation, then the annotation on the getter will 041 * override the annotation on the setter. 042 * 043 * @author andy 044 * @since May 8, 2006 1:57:46 PM 045 */ 046 public class AnnotationAwareBeanPropertyAccessStrategy extends BeanPropertyAccessStrategy { 047 private AnnotationTranslator annotationTranslator; 048 049 public AnnotationAwareBeanPropertyAccessStrategy(Object bean) { 050 super(bean); 051 } 052 053 public AnnotationAwareBeanPropertyAccessStrategy(final ValueModel domainObjectHolder) { 054 super(domainObjectHolder); 055 } 056 057 protected AnnotationAwareBeanPropertyAccessStrategy(final BeanPropertyAccessStrategy parent, final String basePropertyPath) { 058 super(parent, basePropertyPath); 059 } 060 061 062 063 // 064 // METHODS FROM BASE CLASS BeanPropertyAccessStrategy 065 // 066 067 068 069 /** 070 * Retrieves annotations for the specified property as user metadata. 071 * Uses the intalled {@link #getAnnotationTranslator annotation translator} 072 * to "parse" annotations to their key + value pair components. 073 * <p/> 074 * Note that currently annotations are retranslated and the returned map 075 * is rebuilt on every invocation of this method. No caching is attempted 076 * because the current use case of this method is a single call for each 077 * property during FormModel construction. If this use case or usage 078 * pattern should be changed, then we may want to consider caching the 079 * result of this method. 080 * 081 * @param propertyPath 082 */ 083 @Override 084 protected Map<String,Object> getAllUserMetadataFor(final String propertyPath) { 085 final PropertyDescriptor pd = getBeanWrapper().getPropertyDescriptor(propertyPath); 086 Assert.notNull(pd); 087 088 final AnnotationTranslator translator = getAnnotationTranslator(); 089 final Map<String,Object> ret = new LinkedHashMap<String,Object>(); 090 091 for(final Annotation annotation : AnnotationUtils.getAnnotationsFor(pd)) { 092 translator.translate(annotation, ret); 093 } 094 095 return ret; 096 } 097 098 099 100 101 102 103 104 // 105 // PROPERTY ACCESSORS 106 // 107 108 public AnnotationTranslator getAnnotationTranslator() { 109 if(this.annotationTranslator == null) { 110 this.annotationTranslator = new ReflectionAnnotationTranslator(); 111 } 112 return annotationTranslator; 113 } 114 115 public void setAnnotationTranslator(final AnnotationTranslator annotationTranslator) { 116 this.annotationTranslator = annotationTranslator; 117 } 118 }