JAL-3026 srcjar files for VARNA and log4j
[jalview.git] / srcjar / org / apache / log4j / or / RendererMap.java
diff --git a/srcjar/org/apache/log4j/or/RendererMap.java b/srcjar/org/apache/log4j/or/RendererMap.java
new file mode 100644 (file)
index 0000000..6b3483e
--- /dev/null
@@ -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
+     <code>o</code> parameter. This is accomplished by calling the
+     {@link #get(Class)} method. Once a renderer is found, it is
+     applied on the object <code>o</code> 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 <code>clazz</code> for a renderer. The
+     renderer closest in the hierarchy will be returned. If no
+     renderers could be found, then the default renderer is returned.
+
+     <p>The search first looks for a renderer configured for
+     <code>clazz</code>. If a renderer could not be found, then the
+     search continues by looking at all the interfaces implemented by
+     <code>clazz</code> 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
+     <code>clazz</code>. If that fails, then all the interfaces
+     implemented by the parent of <code>clazz</code> are searched and
+     so on.
+
+     <p>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.
+
+     <p>The table below shows the results returned by the
+     <code>get(A2.class)</code> method depending on the renderers
+     added to the map.
+
+     <p><table border="1">
+     <tr><th>Added renderers</th><th>Value returned by <code>get(A2.class)</code></th>
+
+     <tr><td><code>A0Renderer</code>
+         <td align="center"><code>A0Renderer</code>
+
+     <tr><td><code>A0Renderer, A1Renderer</code>
+         <td align="center"><code>A1Renderer</code>
+
+     <tr><td><code>X0Renderer</code>
+         <td align="center"><code>X0Renderer</code>
+
+     <tr><td><code>A1Renderer, X0Renderer</code>
+         <td align="center"><code>X0Renderer</code>
+
+     </table>
+
+     <p>This search algorithm is not the most natural, although it is
+     particularly easy to implement. Future log4j versions
+     <em>may</em> 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 <code>clazz</code>.
+  */
+  public
+  void put(Class clazz, ObjectRenderer or) {
+    map.put(clazz, or);
+  }
+}