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     */ 
017    package org.apache.commons.betwixt.strategy;
018    
019    import java.util.ArrayList;
020    import java.util.Collection;
021    import java.util.Iterator;
022    import java.util.List;
023    
024    /**
025     * Pluggable strategy specifying whether property's should be suppressed.
026     * Implementations can be used to give rules about which properties 
027     * should be ignored by Betwixt when introspecting.
028     * @since 0.7
029     * @author <a href='http://commons.apache.org'>Apache Commons Team</a>, <a href='http://www.apache.org'>Apache Software Foundation</a>
030     */
031    public abstract class PropertySuppressionStrategy {
032    
033        /**
034         * Default implementation.
035         * @see #DEFAULT
036         */
037        public static class Default extends PropertySuppressionStrategy {
038            public boolean suppressProperty(Class clazz, Class propertyType, String propertyName) {
039                boolean result = false;
040                // ignore class properties
041                if ( Class.class.equals( propertyType) && "class".equals( propertyName ) ) {
042                    result = true;
043                }
044                // ignore isEmpty for collection subclasses
045                if ( "empty".equals( propertyName ) && Collection.class.isAssignableFrom( clazz )) {
046                    result = true;
047                }
048                
049                return result;
050            }
051            
052            public String toString() {
053                return "Default Properties Suppressed";
054            }
055        }
056    
057        /**
058         * Implementation delegates to a list of strategies
059         */
060        public static class Chain extends PropertySuppressionStrategy {
061    
062            private final List strategies = new ArrayList();
063            
064            /**
065             * @see #suppressProperty(Class, Class, String)
066             */
067            public boolean suppressProperty(Class classContainingTheProperty, Class propertyType, String propertyName) {
068                boolean result = false;
069                for (Iterator it=strategies.iterator(); it.hasNext();) {
070                    PropertySuppressionStrategy strategy = (PropertySuppressionStrategy) it.next();
071                    if (strategy.suppressProperty(classContainingTheProperty, propertyType, propertyName)) {
072                        result = true;
073                        break;
074                    }
075                    
076                }
077                return result;
078            }
079            
080            /**
081             * Adds a strategy to the list
082             * @param strategy <code>PropertySuppressionStrategy</code>, not null
083             */
084            public void addStrategy(PropertySuppressionStrategy strategy) {
085                strategies.add(strategy);
086            }
087        }
088        
089        /**
090         * Default implementation suppresses the class property
091         * found on every object. Also, the <code>isEmpty</code>
092         * property is supressed for implementations of <code>Collection</code>.
093         */
094        public static final PropertySuppressionStrategy DEFAULT = new Default();
095        
096        /**
097         * Should the given property be suppressed?
098         * @param classContainingTheProperty <code>Class</code> giving the type of the bean containing the property <code>propertyName</code>
099         * @param propertyType <code>Class</code> giving the type of the property, not null
100         * @param propertyName the name of the property, not null
101         * @return true when the given property should be suppressed
102         */
103        public abstract boolean suppressProperty(Class classContainingTheProperty, Class propertyType, String propertyName);
104    }