Package org.apache.niolex.commons.reflect

Source Code of org.apache.niolex.commons.reflect.FieldFilter

/**
* FieldFilter.java
*
* Copyright 2014 the original author or authors.
*
* We licenses this file to you under the Apache License, version 2.0
* (the "License"); you may not use this file except in compliance with the
* License.  You may obtain a copy of the License at:
*
*    http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.  See the
* License for the specific language governing permissions and limitations
* under the License.
*/
package org.apache.niolex.commons.reflect;

import java.lang.reflect.Field;
import java.lang.reflect.Modifier;
import java.util.List;
import java.util.regex.Pattern;

import org.apache.commons.lang.ClassUtils;
import org.apache.niolex.commons.reflect.FieldUtil.Filter;
import org.apache.niolex.commons.test.Check;

import com.google.common.collect.Lists;

/**
* This class is used to help user to build filter to filter field when
* try to get the correct field from a class.
* <br>
* And user can use the method {@link #find()} to find the correct fields
* and then operate on them.
*
* @param <FT> the filtered field type, set to Object if not known
* @author <a href="mailto:xiejiyun@foxmail.com">Xie, Jiyun</a>
* @version 1.0.0
* @since 2014-1-6
*/
public class FieldFilter<FT> implements Filter {

    // ========================================================================
    // The static methods.
    // ========================================================================

    /**
     * A short cut for method {@link #create()}.
     *
     * @param <CT> the filtered field type
     * @return a newly created field filter
     */
    public static final <CT> FieldFilter<CT> c() {
        return create();
    }

    /**
     * Create a new field filter.
     *
     * @param <CT> the filtered field type
     * @return a newly created field filter
     */
    public static final <CT> FieldFilter<CT> create() {
        return new FieldFilter<CT>();
    }

    /**
     * A short cut for method {@link #forType(Class)}.
     *
     * @param <QT> the filtered field type
     * @param type the field type
     * @return a newly created field filter
     */
    public static final <QT> FieldFilter<QT> t(final Class<QT> type) {
        return forType(type);
    }

    /**
     * Create a new filter with this type as the filtered field type. Unlike {@link #exactType(Class)},
     * we do widening of primitive classes and match sub classes too.
     *
     * @param <QT> the filtered field type
     * @param type the field type
     * @return a newly created field filter
     */
    public static final <QT> FieldFilter<QT> forType(final Class<QT> type) {
        // Step 1. Create a new field filter.
        FieldFilter<QT> e = new FieldFilter<QT>();
        // Step 2. Add filter.
        e.add(new Filter(){
            @Override
            public boolean isValid(Field f) {
                return ClassUtils.isAssignable(f.getType(), type);
            }});
        return e;
    }

    /**
     * Filter the fields exactly with this type.
     *
     * @param <E> the exact field type
     * @param type the field type
     * @return a newly created field filter
     */
    public static final <E> FieldFilter<E> exactType(final Class<E> type) {
        // Step 1. Create a new field filter.
        FieldFilter<E> e = new FieldFilter<E>();
        // Step 2. Add filter.
        e.filterList.add(new Filter(){
            @Override
            public boolean isValid(Field f) {
                return type.equals(f.getType());
            }});
        return e;
    }

    // ========================================================================
    // The class fields.
    // ========================================================================

    /**
     * The list to save all the filters
     */
    private final List<Filter> filterList = Lists.newArrayList();

    /**
     * The host variable
     */
    private Object host;

    /**
     * The host class
     */
    private Class<?> clazz;

    // ========================================================================
    // The instance methods.
    // ========================================================================

    /**
     * This is the override of super method.
     * @see org.apache.niolex.commons.reflect.FieldUtil.Filter#isValid(java.lang.reflect.Field)
     */
    @Override
    public boolean isValid(Field f) {
        for (Filter filter : filterList) {
            if (!filter.isValid(f)) return false;
        }
        return true;
    }

    /**
     * Add a new filter to this composite filter.
     *
     * @param filter the filter to be added
     * @return this
     */
    public FieldFilter<FT> add(Filter filter) {
        filterList.add(filter);
        return this;
    }

    /**
     * Find the fields match this filter.
     *
     * @return the field result
     * @throws IllegalStateException if neither host variable nor host class was set
     */
    public final FieldResult<FT> find() {
        if (clazz != null) {
            return new FieldResult<FT>(host, FieldUtil.getFields(clazz, this));
        } else {
            throw new IllegalStateException("Please set host variable or class first!");
        }
    }

    // ========================================================================
    // The chain methods for clients.
    // ========================================================================

    /**
     * Set the host variable.
     *
     * @param host the host variable
     * @return this
     */
    public final FieldFilter<FT> host(Object host) {
        this.host = host;
        this.clazz = host.getClass();
        return this;
    }

    /**
     * Set the host class.
     *
     * @param clazz the host class
     * @return this
     */
    public final FieldFilter<FT> clazz(Class<?> clazz) {
        this.clazz = clazz;
        return this;
    }

    /**
     * Filter the fields with this name.<br>
     * A short cut for method {@link #withName(String)}.
     *
     * @param fieldName the field name
     * @return this
     */
    public final FieldFilter<FT> name(final String fieldName) {
        return withName(fieldName);
    }

    /**
     * Filter the fields with this name.
     *
     * @param fieldName the field name
     * @return this
     */
    public final FieldFilter<FT> withName(final String fieldName) {
        Check.notNull(fieldName, "fieldName should not be null.");
        return this.add(new Filter(){
            @Override
            public boolean isValid(Field f) {
                return fieldName.equals(f.getName());
            }});
    }

    /**
     * Filter the fields who's field name matches this regex expression.
     *
     * @param nameRegex the field name regex expression
     * @return this
     */
    public final FieldFilter<FT> nameLike(final String nameRegex) {
        final Pattern p = Pattern.compile(nameRegex);
        return this.add(new Filter(){
            @Override
            public boolean isValid(Field f) {
                return p.matcher(f.getName()).matches();
            }});
    }

    /**
     * Filter the fields with only static fields.
     *
     * @return this
     */
    public final FieldFilter<FT> onlyStatic() {
        return this.add(new Filter(){
            @Override
            public boolean isValid(Field f) {
                return Modifier.isStatic(f.getModifiers());
            }});
    }

    /**
     * Filter the fields without static fields.
     *
     * @return this
     */
    public final FieldFilter<FT> noStatic() {
        return this.add(new Filter(){
            @Override
            public boolean isValid(Field f) {
                return !Modifier.isStatic(f.getModifiers());
            }});
    }

    /**
     * Filter the fields without synthetic fields.
     *
     * @return this
     */
    public final FieldFilter<FT> noSynthetic() {
        return this.add(new Filter(){
            @Override
            public boolean isValid(Field f) {
                return !f.isSynthetic();
            }});
    }

}
TOP

Related Classes of org.apache.niolex.commons.reflect.FieldFilter

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.