001/* 002 * Copyright 2011 Atteo. 003 * 004 * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except 005 * in compliance with the License. You may obtain a copy of the License at 006 * 007 * http://www.apache.org/licenses/LICENSE-2.0 008 * 009 * Unless required by applicable law or agreed to in writing, software distributed under the License 010 * is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express 011 * or implied. See the License for the specific language governing permissions and limitations under 012 * the License. 013 */ 014package org.atteo.evo.jaxb; 015 016import java.lang.annotation.Annotation; 017import java.lang.reflect.Field; 018import java.lang.reflect.Method; 019import java.lang.reflect.Type; 020import java.util.Properties; 021 022import javax.xml.bind.annotation.XmlElement; 023 024import org.atteo.evo.filtering.Filtering; 025import org.atteo.evo.filtering.PropertiesPropertyResolver; 026import org.atteo.evo.filtering.PropertyNotFoundException; 027import org.atteo.evo.filtering.PropertyResolver; 028 029import com.sun.xml.bind.v2.model.annotation.Locatable; 030import com.sun.xml.bind.v2.model.annotation.RuntimeAnnotationReader; 031import com.sun.xml.bind.v2.model.annotation.RuntimeInlineAnnotationReader; 032import com.sun.xml.bind.v2.model.core.ErrorHandler; 033 034/** 035 * Custom JAXB annotation reader which filters {@link XmlElement} 036 * {@link XmlElement#defaultValue() default values} with properties. 037 */ 038public class FilteringAnnotationReader implements RuntimeAnnotationReader { 039 private RuntimeAnnotationReader delegate = new RuntimeInlineAnnotationReader(); 040 private PropertyResolver propertyResolver; 041 042 public FilteringAnnotationReader(PropertyResolver propertyResolver) { 043 this.propertyResolver = propertyResolver; 044 } 045 046 public FilteringAnnotationReader(Properties properties) { 047 this(new PropertiesPropertyResolver(properties)); 048 } 049 050 @Override 051 public void setErrorHandler(ErrorHandler errorHandler) { 052 delegate.setErrorHandler(errorHandler); 053 } 054 055 @Override 056 public <A extends Annotation> A getFieldAnnotation(Class<A> annotation, Field field, 057 Locatable srcpos) { 058 A original = delegate.getFieldAnnotation(annotation, field, srcpos); 059 if (annotation == XmlElement.class && original != null) { 060 final XmlElement xmlElement = (XmlElement) original; 061 final String defaultValue; 062 try { 063 String originalValue = xmlElement.defaultValue(); 064 if ("\u0000".equals(originalValue)) { 065 return original; 066 } 067 defaultValue = Filtering.filter(originalValue, propertyResolver); 068 if (defaultValue == null || defaultValue.equals(originalValue)) { 069 return original; 070 } 071 } catch (PropertyNotFoundException e) { 072 return original; 073 } 074 075 return annotation.cast(new XmlElement() { 076 @Override 077 public String name() { 078 return xmlElement.name(); 079 } 080 081 @Override 082 public boolean nillable() { 083 return xmlElement.nillable(); 084 } 085 086 @Override 087 public boolean required() { 088 return xmlElement.required(); 089 } 090 091 @Override 092 public String namespace() { 093 return xmlElement.namespace(); 094 } 095 096 @Override 097 public String defaultValue() { 098 return defaultValue; 099 } 100 101 @SuppressWarnings("rawtypes") 102 @Override 103 public Class type() { 104 return xmlElement.type(); 105 } 106 107 @Override 108 public Class<? extends Annotation> annotationType() { 109 return xmlElement.annotationType(); 110 } 111 }); 112 } 113 return original; 114 } 115 116 @Override 117 public boolean hasFieldAnnotation(Class<? extends Annotation> annotationType, Field field) { 118 return delegate.hasFieldAnnotation(annotationType, field); 119 } 120 121 @SuppressWarnings("rawtypes") 122 @Override 123 public boolean hasClassAnnotation(Class clazz, Class<? extends Annotation> annotationType) { 124 return delegate.hasClassAnnotation(clazz, annotationType); 125 } 126 127 @Override 128 public Annotation[] getAllFieldAnnotations(Field field, Locatable srcPos) { 129 return delegate.getAllFieldAnnotations(field, srcPos); 130 } 131 132 @Override 133 public <A extends Annotation> A getMethodAnnotation(Class<A> annotation, Method getter, 134 Method setter, Locatable srcpos) { 135 return delegate.getMethodAnnotation(annotation, getter, setter, srcpos); 136 } 137 138 @Override 139 public boolean hasMethodAnnotation(Class<? extends Annotation> annotation, String propertyName, 140 Method getter, Method setter, Locatable srcPos) { 141 return delegate.hasMethodAnnotation(annotation, propertyName, getter, setter, srcPos); 142 } 143 144 @Override 145 public Annotation[] getAllMethodAnnotations(Method method, Locatable srcPos) { 146 return delegate.getAllMethodAnnotations(method, srcPos); 147 } 148 149 @Override 150 public <A extends Annotation> A getMethodAnnotation(Class<A> annotation, Method method, 151 Locatable srcpos) { 152 return delegate.getMethodAnnotation(annotation, method, srcpos); 153 } 154 155 @Override 156 public boolean hasMethodAnnotation(Class<? extends Annotation> annotation, Method method) { 157 return delegate.hasMethodAnnotation(annotation, method); 158 } 159 160 @Override 161 public <A extends Annotation> A getMethodParameterAnnotation(Class<A> annotation, 162 Method method, int paramIndex, Locatable srcPos) { 163 return delegate.getMethodParameterAnnotation(annotation, method, paramIndex, srcPos); 164 } 165 166 @SuppressWarnings("rawtypes") 167 @Override 168 public <A extends Annotation> A getClassAnnotation(Class<A> annotation, Class clazz, 169 Locatable srcpos) { 170 return delegate.getClassAnnotation(annotation, clazz, srcpos); 171 } 172 173 @SuppressWarnings("rawtypes") 174 @Override 175 public <A extends Annotation> A getPackageAnnotation(Class<A> annotation, Class clazz, 176 Locatable srcpos) { 177 return delegate.getPackageAnnotation(annotation, clazz, srcpos); 178 } 179 180 @Override 181 public Type getClassValue(Annotation a, String name) { 182 return delegate.getClassValue(a, name); 183 } 184 185 @Override 186 public Type[] getClassArrayValue(Annotation a, String name) { 187 return delegate.getClassArrayValue(a, name); 188 } 189}