001    package org.junit.runners.model;
002    
003    import java.lang.reflect.Modifier;
004    import java.util.List;
005    
006    /**
007     * Parent class for {@link FrameworkField} and {@link FrameworkMethod}
008     *
009     * @since 4.7
010     */
011    public abstract class FrameworkMember<T extends FrameworkMember<T>> implements
012            Annotatable {
013        abstract boolean isShadowedBy(T otherMember);
014    
015        /**
016         * Check if this member is shadowed by any of the given members. If it
017         * is, the other member is removed.
018         * 
019         * @return member that should be used, or {@code null} if no member should be used.
020         */
021        final T handlePossibleShadowedMember(List<T> members) {
022            for (int i = members.size() - 1; i >=0; i--) {
023                T otherMember = members.get(i);
024                if (isShadowedBy(otherMember)) {
025                    if (otherMember.isBridgeMethod()) {
026                        /*
027                         *  We need to return the previously-encountered bridge method
028                         *  because JUnit won't be able to call the parent method,
029                         *  because the parent class isn't public.
030                         */
031                        members.remove(i);
032                        return otherMember;
033                    }
034                    // We found a shadowed member that isn't a bridge method. Ignore it.
035                    return null;
036                }
037            }
038            // No shadow or bridge method found. The caller should add *this* member.
039            return self();
040        }
041    
042        @SuppressWarnings("unchecked")
043        private T self() {
044            return (T) this;
045        }
046    
047        abstract boolean isBridgeMethod();
048    
049        protected abstract int getModifiers();
050    
051        /**
052         * Returns true if this member is static, false if not.
053         */
054        public boolean isStatic() {
055            return Modifier.isStatic(getModifiers());
056        }
057    
058        /**
059         * Returns true if this member is public, false if not.
060         */
061        public boolean isPublic() {
062            return Modifier.isPublic(getModifiers());
063        }
064    
065        public abstract String getName();
066    
067        public abstract Class<?> getType();
068    
069        public abstract Class<?> getDeclaringClass();
070    }