All Downloads are FREE. Search and download functionalities are using the official Maven repository.

org.apache.fulcrum.json.jackson.SimpleNameIntrospector Maven / Gradle / Ivy

The newest version!
package org.apache.fulcrum.json.jackson;

/*
 * Licensed to the Apache Software Foundation (ASF) under one
 * or more contributor license agreements.  See the NOTICE file
 * distributed with this work for additional information
 * regarding copyright ownership.  The ASF 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.
 */

import java.util.List;
import java.util.concurrent.CopyOnWriteArrayList;
import java.util.concurrent.atomic.AtomicBoolean;

import org.apache.avalon.framework.logger.LogEnabled;
import org.apache.avalon.framework.logger.Logger;

import com.fasterxml.jackson.databind.introspect.Annotated;
import com.fasterxml.jackson.databind.introspect.AnnotatedClass;
import com.fasterxml.jackson.databind.introspect.NopAnnotationIntrospector;
import com.fasterxml.jackson.databind.ser.impl.SimpleFilterProvider;

/**
 * The intent of this custom introspector is to provide filtering capabilities
 * by using String parameters (properties and class types), which could be
 * adjusted e.g. from a scriptable context (velocity template). 
 * Class Type Filtering currently not supported except for Exclude Filter: {@link Jackson2MapperService#serializeAllExceptFilter(Object, Class, Boolean, String...)}.
 * 
 * 
 * @author gk
 * @version $Id: SimpleNameIntrospector.java 1849460 2018-12-21 11:09:35Z gk $
 * 
 */
public class SimpleNameIntrospector extends NopAnnotationIntrospector implements LogEnabled {
    /**
     * 
     */
    private static final long serialVersionUID = 1L;
    
    private List> filteredClasses = new CopyOnWriteArrayList<>();
    private List externalFilterExcludeClasses = new CopyOnWriteArrayList<>();
    private List externalFilterIncludeClasses = new CopyOnWriteArrayList<>();
    // is used only for filtering by class
    private AtomicBoolean isExludeType = new AtomicBoolean(false);
    
    private static Logger logger;

    /**
     * Filtering on method types.
     * 
     */
    @Override
    public Boolean isIgnorableType(AnnotatedClass ac) {
        Boolean isIgnorable = super.isIgnorableType(ac);
        if (isIgnorable == null || !isIgnorable) {
            if (getIsExludeType()) { // could be removed, if cleaning after call ?
                if (!externalFilterExcludeClasses.isEmpty()
                        && externalFilterExcludeClasses.contains(ac.getName())) {
                    isIgnorable = true;
                }
            } else {
                // not yet used
                if (!externalFilterIncludeClasses.isEmpty()
                        && !externalFilterIncludeClasses.contains(ac.getName())) {
                        try {
                            Class.forName(ac.getName());
                            isIgnorable = true;
                        } catch (ClassNotFoundException e) {
                            // no clazz ignore, could NOT ignore as no filterable clazz
                        }
                }
            }
        }
        return isIgnorable;
    }
    /**
     * @return Object Filtering on properties returns an object, if
     *         {@link #filteredClasses} contains the class provided. The
     *         filter itself currently is {@link SimpleFilterProvider}.
     */
    @Override
    public Object findFilterId(Annotated ac) {
        Object id = super.findFilterId(ac);
        // Let's default to current behavior if annotation is found:
        // Object id = super.findFilterId(ac);
        // but use simple class name if not
        if (id == null) {
            String name = ac.getName();
            Class targetClazz = ac.getRawType();
            if (!filteredClasses.isEmpty()
                    && filteredClasses.contains(targetClazz)
                    ) {
                logger.debug("filter applying to " +name);
                id = name;
            } else {
                // check if target class is a child from filter class -> apply filter 
                for (Class filterClazz : filteredClasses) {
                    // the currently checked instance of type targetClazz is a child of the filter class filterClazz ->  filter child 
                    if (filterClazz.isAssignableFrom(targetClazz)) {
                        logger.debug("filter applying to parent " +filterClazz +" matching child class "+name );
                        id = name;
                        break;
                    }
                    // the currently checked instance of type targetClazz is a parent of the filter class filterClazz -> filter parent
                    if (targetClazz.isAssignableFrom(filterClazz)) {
                        logger.debug("filter applying to child " +filterClazz+" matching parent class "+name);
                        id = name;
                        break;
                    }
                }
            }
        }
        return id;
    }

    public List> getFilteredClasses() {
        return filteredClasses;
    }

    public void setFilteredClass(Class filteredClass) {
        if (!filteredClasses.contains(filteredClass)) {
            filteredClasses.add(filteredClass);
        }
    }

    public void setFilteredClasses(Class... classes) {

        for (int i = 0; i < classes.length; i++) {
            if (!filteredClasses.contains(classes[i])) {
                filteredClasses.add(classes[i]);
            }
//            if (classes[i].getSuperclass() != null) {
//                Class superClazz = classes[i].getSuperclass();
//                if (!externalFilterClasses.contains(superClazz)) {
//                    externalFilterClasses.add(superClazz);
//                }  
//            }
        }
    }

    public void removeFilteredClass(Class filteredClass) {
            if (filteredClasses.contains(filteredClass)) {
                filteredClasses.remove(filteredClass);
            }
    }
    
    public void setExternalFilterExcludeClasses(Class... classes) {

        for (int i = 0; i < classes.length; i++) {
            if (!externalFilterExcludeClasses.contains(classes[i].getName())) {

                externalFilterExcludeClasses.add(classes[i].getName());
            }
        }
    }
    
    public void removeExternalFilterExcludeClass(Class externalFilterClass) {
        if (externalFilterExcludeClasses.contains(externalFilterClass.getName())) {
            externalFilterExcludeClasses.remove(externalFilterClass.getName());
        }
    }
    
    public void setExternalFilterIncludeClasses(Class... classes) {

        for (int i = 0; i < classes.length; i++) {
            if (!externalFilterIncludeClasses.contains(classes[i].getName())) {

                externalFilterIncludeClasses.add(classes[i].getName());
            }
        }
    }
    
    public void removeExternalFilterIncludeClasses(Class externalFilterClass) {
        if (externalFilterIncludeClasses.contains(externalFilterClass.getName())) {
            externalFilterIncludeClasses.remove(externalFilterClass.getName());
        }
    }
    
    public boolean getIsExludeType() {
        return isExludeType.get();
    }
    public void setIsExludeType(boolean isExludeType) {
        this.isExludeType.getAndSet(isExludeType);
    }
    @Override
    public void enableLogging(Logger logger) {
        SimpleNameIntrospector.logger = logger;        
    }

}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy