X-Git-Url: http://source.jalview.org/gitweb/?a=blobdiff_plain;ds=sidebyside;f=srcjar%2Forg%2Fapache%2Flog4j%2For%2FRendererMap.java;fp=srcjar%2Forg%2Fapache%2Flog4j%2For%2FRendererMap.java;h=6b3483e8a755554ac6ffc51b97dc9311e336ffcc;hb=2d6292c0377bc6b773c6844a45d3f2c5fac352c7;hp=0000000000000000000000000000000000000000;hpb=954af328a2a6a0055572cd1a09ee035301222574;p=jalview.git diff --git a/srcjar/org/apache/log4j/or/RendererMap.java b/srcjar/org/apache/log4j/or/RendererMap.java new file mode 100644 index 0000000..6b3483e --- /dev/null +++ b/srcjar/org/apache/log4j/or/RendererMap.java @@ -0,0 +1,202 @@ +/* + * 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. + */ + +package org.apache.log4j.or; + +import org.apache.log4j.spi.RendererSupport; +import org.apache.log4j.helpers.LogLog; +import org.apache.log4j.helpers.Loader; +import org.apache.log4j.helpers.OptionConverter; +import java.util.Hashtable; + +/** + Map class objects to an {@link ObjectRenderer}. + + @author Ceki Gülcü + @since version 1.0 */ +public class RendererMap { + + Hashtable map; + + static ObjectRenderer defaultRenderer = new DefaultRenderer(); + + public + RendererMap() { + map = new Hashtable(); + } + + /** + Add a renderer to a hierarchy passed as parameter. + */ + static + public + void addRenderer(RendererSupport repository, String renderedClassName, + String renderingClassName) { + LogLog.debug("Rendering class: ["+renderingClassName+"], Rendered class: ["+ + renderedClassName+"]."); + ObjectRenderer renderer = (ObjectRenderer) + OptionConverter.instantiateByClassName(renderingClassName, + ObjectRenderer.class, + null); + if(renderer == null) { + LogLog.error("Could not instantiate renderer ["+renderingClassName+"]."); + return; + } else { + try { + Class renderedClass = Loader.loadClass(renderedClassName); + repository.setRenderer(renderedClass, renderer); + } catch(ClassNotFoundException e) { + LogLog.error("Could not find class ["+renderedClassName+"].", e); + } + } + } + + + /** + Find the appropriate renderer for the class type of the + o parameter. This is accomplished by calling the + {@link #get(Class)} method. Once a renderer is found, it is + applied on the object o and the result is returned + as a {@link String}. */ + public + String findAndRender(Object o) { + if(o == null) { + return null; + } else { + return get(o.getClass()).doRender(o); + } + } + + + /** + Syntactic sugar method that calls {@link #get(Class)} with the + class of the object parameter. */ + public + ObjectRenderer get(Object o) { + if(o == null) { + return null; + } else { + return get(o.getClass()); + } + } + + + /** + Search the parents of clazz for a renderer. The + renderer closest in the hierarchy will be returned. If no + renderers could be found, then the default renderer is returned. + +

The search first looks for a renderer configured for + clazz. If a renderer could not be found, then the + search continues by looking at all the interfaces implemented by + clazz including the super-interfaces of each + interface. If a renderer cannot be found, then the search looks + for a renderer defined for the parent (superclass) of + clazz. If that fails, then all the interfaces + implemented by the parent of clazz are searched and + so on. + +

For example, if A0, A1, A2 are classes and X0, X1, X2, Y0, Y1 + are interfaces where A2 extends A1 which in turn extends A0 and + similarly X2 extends X1 which extends X0 and Y1 extends Y0. Let + us also assume that A1 implements the Y0 interface and that A2 + implements the X2 interface. + +

The table below shows the results returned by the + get(A2.class) method depending on the renderers + added to the map. + +

+ + +
Added renderersValue returned by get(A2.class)
A0Renderer + A0Renderer + +
A0Renderer, A1Renderer + A1Renderer + +
X0Renderer + X0Renderer + +
A1Renderer, X0Renderer + X0Renderer + +
+ +

This search algorithm is not the most natural, although it is + particularly easy to implement. Future log4j versions + may implement a more intuitive search + algorithm. However, the present algorithm should be acceptable in + the vast majority of circumstances. + + */ + public + ObjectRenderer get(Class clazz) { + //System.out.println("\nget: "+clazz); + ObjectRenderer r = null; + for(Class c = clazz; c != null; c = c.getSuperclass()) { + //System.out.println("Searching for class: "+c); + r = (ObjectRenderer) map.get(c); + if(r != null) { + return r; + } + r = searchInterfaces(c); + if(r != null) { + return r; + } + } + return defaultRenderer; + } + + ObjectRenderer searchInterfaces(Class c) { + //System.out.println("Searching interfaces of class: "+c); + + ObjectRenderer r = (ObjectRenderer) map.get(c); + if(r != null) { + return r; + } else { + Class[] ia = c.getInterfaces(); + for(int i = 0; i < ia.length; i++) { + r = searchInterfaces(ia[i]); + if(r != null) { + return r; + } + } + } + return null; + } + + + public + ObjectRenderer getDefaultRenderer() { + return defaultRenderer; + } + + + public + void clear() { + map.clear(); + } + + /** + Register an {@link ObjectRenderer} for clazz. + */ + public + void put(Class clazz, ObjectRenderer or) { + map.put(clazz, or); + } +}