001// *************************************************************************************************************************** 002// * Licensed to the Apache Software Foundation (ASF) under one or more contributor license agreements. See the NOTICE file * 003// * distributed with this work for additional information regarding copyright ownership. The ASF licenses this file * 004// * to you under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance * 005// * 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 is distributed on an * 010// * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the * 011// * specific language governing permissions and limitations under the License. * 012// *************************************************************************************************************************** 013package org.apache.juneau.transform; 014 015/** 016 * Bean property filter. 017 * 018 * <p> 019 * Registers a bean property filter with a bean class. 020 * 021 * <p> 022 * Property filters can be used to intercept calls to getters and setters and alter their values in transit. 023 * 024 * <h5 class='section'>Example:</h5> 025 * <p class='bcode w800'> 026 * <jc>// Property filter that strips out sensitive information on Address beans.</jc> 027 * <jk>public class</jk> AddressPropertyFilter <jk>extends</jk> PropertyFilter { 028 * 029 * <ja>@Override</ja> 030 * <jk>public</jk> Object readProperty(Object bean, String name, Object value) { 031 * <jk>if</jk> (<js>"taxInfo"</js>.equals(name)) 032 * <jk>return</jk> <js>"redacted"</js>; 033 * <jk>return</jk> value; 034 * } 035 * 036 * <ja>@Override</ja> 037 * <jk>public</jk> Object writeProperty(Object bean, String name, Object value) { 038 * AddressBook a = (Address)bean; 039 * <jk>if</jk> (<js>"taxInfo"</js>.equals(name) && <js>"redacted"</js>.equals(value)) 040 * <jk>return</jk> TaxInfoUtils.<jsm>lookup</jsm>(a.getStreet(), a.getCity(), a.getState()); 041 * <jk>return</jk> value; 042 * } 043 * } 044 * </p> 045 * 046 * <p> 047 * Property filters are registered in the following ways: 048 * <ul class='javatree'> 049 * <li class='ja'>{@link org.apache.juneau.annotation.Bean#propertyFilter() @Bean(propertyFilter)} 050 * <li class='jm'>{@link org.apache.juneau.transform.BeanFilterBuilder#propertyFilter(Class)} 051 * </ul> 052 * 053 * <h5 class='section'>Example:</h5> 054 * <p class='bcode w800'> 055 * <jc>// Register filter on bean class.</jc> 056 * <ja>@Bean</ja>(propertyFilter=AddressPropertyFilter.<jk>class</jk>) 057 * <jk>public class</jk> Address { 058 * <jk>public</jk> String getTaxInfo() {...} 059 * <jk>public void</jk> setTaxInfo(String s) {...} 060 * } 061 * 062 * <jc>// Or define a bean filter.</jc> 063 * <jk>public class</jk> MyFilter <jk>extends</jk> BeanFilterBuilder<Address> { 064 * <jk>public</jk> MyFilter() { 065 * <jc>// Our bean contains generic collections of Foo and Bar objects.</jc> 066 * propertyFilter(AddressPropertyFilter.<jk>class</jk>); 067 * } 068 * } 069 * 070 * <jc>// Register filter on serializer or parser.</jc> 071 * WriterSerializer s = JsonSerializer 072 * .<jsm>create</jsm>() 073 * .beanFilters(MyFilter.<jk>class</jk>) 074 * .build(); 075 * </p> 076 */ 077public class PropertyFilter { 078 079 /** 080 * Default reusable property filter instance. 081 */ 082 public static final PropertyFilter DEFAULT = new PropertyFilter(); 083 084 /** 085 * Property read interceptor. 086 * 087 * <p> 088 * Subclasses can override this property to convert property values to some other object just before serialization. 089 * 090 * <h5 class='section'>Example:</h5> 091 * <p class='bcode w800'> 092 * <jc>// Address filter that strips out sensitive information.</jc> 093 * <jk>public class</jk> AddressPropertyFilter <jk>extends</jk> PropertyFilter { 094 * 095 * <jk>public</jk> Object readProperty(Object bean, String name, Object value) { 096 * <jk>if</jk> (<js>"taxInfo"</js>.equals(name)) 097 * <jk>return</jk> <js>"redacted"</js>; 098 * <jk>return</jk> value; 099 * } 100 * } 101 * </p> 102 * 103 * @param bean The bean from which the property was read. 104 * @param name The property name. 105 * @param value The value just extracted from calling the bean getter. 106 * @return The value to serialize. Default is just to return the existing value. 107 */ 108 public Object readProperty(Object bean, String name, Object value) { 109 return value; 110 } 111 112 /** 113 * Property write interceptor. 114 * 115 * <p> 116 * Subclasses can override this property to convert property values to some other object just before calling the 117 * bean setter. 118 * 119 * <h5 class='section'>Example:</h5> 120 * <p class='bcode w800'> 121 * <jc>// Address filter that strips out sensitive information.</jc> 122 * <jk>public class</jk> AddressPropertyFilter <jk>extends</jk> PropertyFilter { 123 * 124 * <jk>public</jk> Object writeProperty(Object bean, String name, Object value) { 125 * AddressBook a = (Address)bean; 126 * <jk>if</jk> (<js>"taxInfo"</js>.equals(name) && <js>"redacted"</js>.equals(value)) 127 * <jk>return</jk> TaxInfoUtils.<jsm>lookup</jsm>(a.getStreet(), a.getCity(), a.getState()); 128 * <jk>return</jk> value; 129 * } 130 * } 131 * </p> 132 * 133 * @param bean The bean from which the property was read. 134 * @param name The property name. 135 * @param value The value just parsed. 136 * @return The value to serialize. Default is just to return the existing value. 137 */ 138 public Object writeProperty(Object bean, String name, Object value) { 139 return value; 140 } 141}