001/* 002 * Licensed to the Apache Software Foundation (ASF) under one or more 003 * contributor license agreements. See the NOTICE file distributed with 004 * this work for additional information regarding copyright ownership. 005 * The ASF licenses this file to You under the Apache License, Version 2.0 006 * (the "License"); you may not use this file except in compliance with 007 * the License. You may obtain a copy of the License at 008 * 009 * http://www.apache.org/licenses/LICENSE-2.0 010 * 011 * Unless required by applicable law or agreed to in writing, software 012 * distributed under the License is distributed on an "AS IS" BASIS, 013 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 014 * See the License for the specific language governing permissions and 015 * limitations under the License. 016 */ 017package org.apache.juneau.swap; 018 019/** 020 * Bean interceptor. 021 * 022 * <p> 023 * Bean interceptors intercept calls to bean getters and setters to allow them to override values in transit. 024 * 025 * <h5 class='section'>Example:</h5> 026 * <p class='bjava'> 027 * <jc>// Interceptor that strips out sensitive information on Address beans.</jc> 028 * <jk>public class</jk> AddressInterceptor <jk>extends</jk> BeanInterceptor<Address> { 029 * 030 * <ja>@Override</ja> 031 * <jk>public</jk> Object readProperty(Address <jv>bean</jv>, String <jv>name</jv>, Object <jv>value</jv>) { 032 * <jk>if</jk> (<js>"taxInfo"</js>.equals(<jv>name</jv>)) 033 * <jk>return</jk> <js>"redacted"</js>; 034 * <jk>return</jk> <jv>value</jv>; 035 * } 036 * 037 * <ja>@Override</ja> 038 * <jk>public</jk> Object writeProperty(Address <jv>bean</jv>, String <jv>name</jv>, Object <jv>value</jv>) { 039 * <jk>if</jk> (<js>"taxInfo"</js>.equals(<jv>name</jv>) && <js>"redacted"</js>.equals(<jv>value</jv>)) 040 * <jk>return</jk> TaxInfoUtils.<jsm>lookup</jsm>(<jv>bean</jv>.getStreet(), <jv>bean</jv>.getCity(), <jv>bean</jv>.getState()); 041 * <jk>return</jk> <jv>value</jv>; 042 * } 043 * } 044 * </p> 045 * 046 * <p> 047 * Bean interceptors are registered in the following way: 048 * <ul class='javatree'> 049 * <li class='ja'>{@link org.apache.juneau.annotation.Bean#interceptor() @Bean(interceptor)} 050 * <li class='jm'>{@link org.apache.juneau.BeanContext.Builder#beanInterceptor(Class,Class)} 051 * </ul> 052 * 053 * <h5 class='section'>Example:</h5> 054 * <p class='bjava'> 055 * <jc>// Register interceptor on bean class.</jc> 056 * <ja>@Bean</ja>(interceptor=AddressInterceptor.<jk>class</jk>) 057 * <jk>public class</jk> Address { 058 * <jk>public</jk> String getTaxInfo() {...} 059 * <jk>public void</jk> setTaxInfo(String <jv>value</jv>) {...} 060 * } 061 * </p> 062 * 063 * <h5 class='section'>See Also:</h5><ul> 064 * <li class='link'><a class="doclink" href="https://juneau.apache.org/docs/topics/SwapBasics">Swap Basics</a> 065 * </ul> 066 * 067 * @param <T> The bean type. 068 */ 069public class BeanInterceptor<T> { 070 071 /** Non-existent bean interceptor. */ 072 public static final class Void extends BeanInterceptor<Object> {} 073 074 /** 075 * Default reusable property filter instance. 076 */ 077 public static final BeanInterceptor<Object> DEFAULT = new BeanInterceptor<>(); 078 079 /** 080 * Property read interceptor. 081 * 082 * <p> 083 * Subclasses can override this property to convert property values to some other object just before serialization. 084 * 085 * <h5 class='section'>Example:</h5> 086 * <p class='bjava'> 087 * <jc>// Address filter that strips out sensitive information.</jc> 088 * <jk>public class</jk> AddressInterceptor <jk>extends</jk> BeanInterceptor<Address> { 089 * 090 * <jk>public</jk> Object readProperty(Address <jv>bean</jv>, String <jv>name</jv>, Object <jv>value</jv>) { 091 * <jk>if</jk> (<js>"taxInfo"</js>.equals(<jv>name</jv>)) 092 * <jk>return</jk> <js>"redacted"</js>; 093 * <jk>return</jk> <jv>value</jv>; 094 * } 095 * } 096 * </p> 097 * 098 * @param bean The bean from which the property was read. 099 * @param name The property name. 100 * @param value The value just extracted from calling the bean getter. 101 * @return The value to serialize. Default is just to return the existing value. 102 */ 103 public Object readProperty(T bean, String name, Object value) { 104 return value; 105 } 106 107 /** 108 * Property write interceptor. 109 * 110 * <p> 111 * Subclasses can override this property to convert property values to some other object just before calling the 112 * bean setter. 113 * 114 * <h5 class='section'>Example:</h5> 115 * <p class='bjava'> 116 * <jc>// Address filter that strips out sensitive information.</jc> 117 * <jk>public class</jk> AddressInterceptor <jk>extends</jk> BeanInterceptor<Address> { 118 * 119 * <jk>public</jk> Object writeProperty(Address <jv>bean</jv>, String <jv>name</jv>, Object <jv>value</jv>) { 120 * <jk>if</jk> (<js>"taxInfo"</js>.equals(<jv>name</jv>) && <js>"redacted"</js>.equals(<jv>value</jv>)) 121 * <jk>return</jk> TaxInfoUtils.<jsm>lookup</jsm>(<jv>bean</jv>.getStreet(), <jv>bean</jv>.getCity(), <jv>bean</jv>.getState()); 122 * <jk>return</jk> <jv>value</jv>; 123 * } 124 * } 125 * </p> 126 * 127 * @param bean The bean from which the property was read. 128 * @param name The property name. 129 * @param value The value just parsed. 130 * @return The value to serialize. Default is just to return the existing value. 131 */ 132 public Object writeProperty(T bean, String name, Object value) { 133 return value; 134 } 135}