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

org.spf4j.io.ConfigurableAppenderSupplier Maven / Gradle / Ivy

Go to download

A continuously growing collection of utilities to measure performance, get better diagnostics, improve performance, or do things more reliably, faster that other open source libraries...

The newest version!
/*
 * Copyright (c) 2001-2017, Zoltan Farkas All Rights Reserved.
 *
 * This library is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Lesser General Public
 * License as published by the Free Software Foundation; either
 * version 2.1 of the License, or (at your option) any later version.
 *
 * This library is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public
 * License along with this program; if not, write to the Free Software
 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
 *
 * Additionally licensed with:
 *
 * Licensed 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.spf4j.io;

import com.google.common.annotations.Beta;
import edu.umd.cs.findbugs.annotations.SuppressFBWarnings;
import java.io.IOException;
import java.lang.reflect.ParameterizedType;
import java.lang.reflect.Type;
import java.util.Arrays;
import java.util.Iterator;
import java.util.ServiceLoader;
import java.util.function.Function;
import java.util.function.Predicate;
import javax.annotation.CheckReturnValue;
import javax.annotation.ParametersAreNonnullByDefault;
import javax.annotation.concurrent.ThreadSafe;
import org.spf4j.base.CoreTextMediaType;
import org.spf4j.reflect.CachingTypeMapWrapper;
import org.spf4j.reflect.GraphTypeMap;

/**
 *
 * @author zoly
 */
@Beta
@ThreadSafe
@ParametersAreNonnullByDefault
public final class ConfigurableAppenderSupplier implements ObjectAppenderSupplier {


  private final CachingTypeMapWrapper[] appenderMap;

  public ConfigurableAppenderSupplier() {
    this(true, (t) -> false);
  }

  @SuppressFBWarnings("RV_RETURN_VALUE_IGNORED")
  public ConfigurableAppenderSupplier(final boolean registerFromServiceLoader, final Predicate> except,
          final ObjectAppender... appenders) {
    appenderMap = new CachingTypeMapWrapper[CoreTextMediaType.values().length];
    for (int i = 0; i < appenderMap.length; i++) {
      appenderMap[i] = new CachingTypeMapWrapper<>(new GraphTypeMap());
    }
    if (registerFromServiceLoader) {
      @SuppressWarnings("unchecked")
      ServiceLoader> load = (ServiceLoader) ServiceLoader.load(ObjectAppender.class,
              ObjectAppender.class.getClassLoader());
      Iterator> iterator = load.iterator();
      while (iterator.hasNext()) {
        ObjectAppender appender = iterator.next();
        Class appenderType = getAppenderType(appender);
        if (!except.test(appenderType)) {
          if (!ConfigurableAppenderSupplier.this.tryRegister((Class) appenderType, (ObjectAppender) appender)) {
            throw new IllegalArgumentException("Attempting to register duplicate appender(" + appender + ") for "
                    + appenderType);
          }
        }
      }
    }
    for (ObjectAppender appender : appenders) {
      if (!ConfigurableAppenderSupplier.this.tryRegister(getAppenderType(appender), (ObjectAppender) appender)) {
        throw new IllegalArgumentException("Cannot register appender " + appender);
      }
    }
    appenderMap[ObjectAppender.TOSTRING_APPENDER.getAppendedType().ordinal()]
            .putIfNotPresent(Object.class, ObjectAppender.TOSTRING_APPENDER);
  }

  public static Class getAppenderType(final ObjectAppender appender) {

    Class aClass = appender.getClass();
    Class appenderType = null;
    do {
      Type[] genericInterfaces = aClass.getGenericInterfaces();
      for (Type type : genericInterfaces) {
        if (type instanceof ParameterizedType) {
          ParameterizedType pType = (ParameterizedType) type;
          if (pType.getRawType() == ObjectAppender.class) {
            Type actualTypeArgument = pType.getActualTypeArguments()[0];
            if (actualTypeArgument instanceof ParameterizedType) {
              appenderType = (Class) ((ParameterizedType) actualTypeArgument).getRawType();
            } else {
              appenderType = (Class) actualTypeArgument;
            }
            break;
          }
        }
      }
      aClass = aClass.getSuperclass();
    } while (appenderType == null && aClass != null);
    if (appenderType == null) {
      throw new IllegalArgumentException("Improperly declared Appender " + appender);
    }
    return appenderType;
  }

  @SuppressWarnings("unchecked")
  public  int register(final Class type, final ObjectAppender... appenders) {
    int i = 0;
    for (ObjectAppender appender : appenders) {
      if (ConfigurableAppenderSupplier.this.tryRegister(type, appender)) {
        i++;
      }
    }
    return i;
  }

  public  void replace(final CoreTextMediaType mt, final Class type,
          final Function, ObjectAppender> replace) {
    appenderMap[mt.ordinal()].replace(type, (Function) replace);
  }

  public  void register(final Class type, final ObjectAppender appender) {
    if (!tryRegister(type, appender)) {
      throw new IllegalArgumentException("Cannnot Register " + appender + " for " + type);
    }
  }

  @CheckReturnValue
  public  boolean tryRegister(final Class type, final ObjectAppender appender) {
    return appenderMap[appender.getAppendedType().ordinal()].putIfNotPresent(type, appender);
  }

  public  void register(final Class type, final CoreTextMediaType contentType,
          final ObjectAppender appender) {
     if (!tryRegister(type, contentType, appender)) {
       throw new IllegalArgumentException("Cannnot Register " + appender + " for " + type);
     }
  }

  @CheckReturnValue
  public  boolean tryRegister(final Class type, final CoreTextMediaType contentType,
          final ObjectAppender appender) {
    return appenderMap[contentType.ordinal()].putIfNotPresent(type,
            new ObjectAppenderContentTypeAdapter(appender, contentType));
  }


  public boolean unregister(final Class type) {
    boolean result = false;
    for (int i = 0, l = CoreTextMediaType.values().length;  i < l; i++) {
      boolean removed = appenderMap[i].remove(type);
      if (removed) {
        result = true;
      }
    }
    return result;
  }

  @Override
  public ObjectAppender get(final CoreTextMediaType mt,  final Type type) {
    return appenderMap[mt.ordinal()].get(type);
  }

  @Override
  public String toString() {
    return "ConfigurableAppenderSupplier{" + "lookup=" + Arrays.toString(appenderMap)  + '}';
  }

  private static final class ObjectAppenderContentTypeAdapter implements ObjectAppender {

    private final ObjectAppender appender;
    private final CoreTextMediaType contentType;

    ObjectAppenderContentTypeAdapter(final ObjectAppender appender, final CoreTextMediaType contentType) {
      this.appender = appender;
      this.contentType = contentType;
    }

    @Override
    public void append(final T object, final Appendable appendTo) throws IOException {
      appender.append(object, appendTo);
    }

    @Override
    public void append(final T object, final Appendable appendTo, final ObjectAppenderSupplier appenderSupplier)
            throws IOException {
      appender.append(object, appendTo, appenderSupplier);
    }

    @Override
    public CoreTextMediaType getAppendedType() {
      return contentType;
    }
  }

}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy