/*
 * Copyright (c) 2003, Franz-Josef Elmer, All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without 
 * modification, are permitted provided that the following conditions are met:
 * 
 * - Redistributions of source code must retain the above copyright notice, 
 *   this list of conditions and the following disclaimer.
 * - Redistributions in binary form must reproduce the above copyright notice, 
 *   this list of conditions and the following disclaimer in the documentation 
 *   and/or other materials provided with the distribution.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 
 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED 
 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 
 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR 
 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, 
 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, 
 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
 * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, 
 * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR 
 * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, 
 * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 
 */
package classycle.renderer;

import java.text.MessageFormat;

import classycle.ClassAttributes;
import classycle.graph.AtomicVertex;

/**
 * XML renderer of an {@link AtomicVertex} with 
 * {@link ClassAttributes}.
 * 
 * @author Franz-Josef Elmer
 */
public class XMLClassRenderer implements AtomicVertexRenderer {
  public static final String CLASS_ELEMENT = "class",
                             CLASS_REF_ELEMENT = "classRef";
  private static final MessageFormat CLASS_START_FORMAT 
      = new MessageFormat("    <" + CLASS_ELEMENT
                          + " name=\"{0}\" type=\"{1}\" innerClass=\"{3}\""
                          + " size=\"{2}\" usedBy=\"{4}\""
                          + " usesInternal=\"{5}\" usesExternal=\"{6}\""
                          + " layer=\"{7}\">\n");
  private static final String CLASS_END_TEMPLATE 
      = "    </" + CLASS_ELEMENT + ">\n";
  private static final MessageFormat CLASS_REF_FORMAT 
      = new MessageFormat("      <" + CLASS_REF_ELEMENT + " name=\"{0}\"" 
                          + " type=\"{1}\"/>\n");

  /**
   * Renderes the specified vertex. It is assumed that the vertex attributes
   * are of the type {@link classycle.ClassAttributes}.
   * @param vertex Vertex to be rendered.
   * @return the rendered vertex.
   */
  public String render(AtomicVertex vertex, int layerIndex) {
    StringBuffer result = new StringBuffer();
    String[] values = new String[8];
    ClassAttributes attributes = (ClassAttributes) vertex.getAttributes();
    values[0] = attributes.getName();
    values[1] = attributes.getType();
    values[2] = Long.toString(attributes.getSize());
    values[3] = attributes.isInnerClass() ? "true" : "false";
    values[4] = Integer.toString(vertex.getNumberOfIncomingArcs());
    int usesInternal = 0;
    int usesExternal = 0;
    for (int i = 0, n = vertex.getNumberOfOutgoingArcs(); i < n; i++) {
      if (((AtomicVertex) vertex.getHeadVertex(i)).isGraphVertex()) {
        usesInternal++;
      } else {
        usesExternal++;
      }
    }
    values[5] = Integer.toString(usesInternal);
    values[6] = Integer.toString(usesExternal);
    values[7] = Integer.toString(layerIndex);
    CLASS_START_FORMAT.format(values, result, null);

    for (int i = 0, n = vertex.getNumberOfIncomingArcs(); i < n; i++) {
      values[0] = ((ClassAttributes) vertex.getTailVertex(i).getAttributes())
                  .getName();
      values[1] = "usedBy";
      CLASS_REF_FORMAT.format(values, result, null);
    }
    for (int i = 0, n = vertex.getNumberOfOutgoingArcs(); i < n; i++) {
      values[0] = ((ClassAttributes) vertex.getHeadVertex(i).getAttributes())
                  .getName();
      values[1] = ((AtomicVertex) vertex.getHeadVertex(i)).isGraphVertex()
                                            ? "usesInternal" : "usesExternal";
      CLASS_REF_FORMAT.format(values, result, null);
    }
    result.append(CLASS_END_TEMPLATE);
    return new String(result);
  }
} //class
@@ -1835,67 +1835,82 @@
 nal 
-MessageFormat CLASS_START_FORMAT %0A      = new MessageFormat
+AtomicVertexRenderer CLASS_RENDERER%0A      = new TemplateBasedClassRenderer
 (%22  
@@ -1940,36 +1940,24 @@
             
-          
-  
 + %22 name=%5C%22%7B
@@ -1996,97 +1996,54 @@
 3%7D%5C%22
-%22%0A                          + %22 size=%5C%22%7B2%7D%5C%22 usedBy=%5C%22%7B4%7D%5C%22%22%0A                          + 
+ size=%5C%22%7B2%7D%5C%22%22%0A              + %22 usedBy=%5C%22%7B4%7D%5C
 %22 us
@@ -2083,28 +2083,16 @@
 %22%7B6%7D%5C%22%22%0A
-            
         
@@ -2705,867 +2705,117 @@
 ult 
-= new StringBuffer();%0A    String%5B%5D values = new String%5B8%5D;%0A    ClassAttributes attributes = (ClassAttributes) vertex.getAttributes();%0A    values%5B0%5D = attributes.getName();%0A    values%5B1%5D = attributes.getType();%0A    values%5B2%5D = Long.toString(attributes.getSize());%0A    values%5B3%5D = attributes.isInnerClass() ? %22true%22 : %22false%22;%0A    values%5B4%5D = Integer.toString(vertex.getNumberOfIncomingArcs());%0A    int usesInternal = 0;%0A    int usesExternal = 0;%0A    for (int i = 0, n = vertex.getNumberOfOutgoingArcs(); i %3C n; i++) %7B%0A      if (((AtomicVertex) vertex.getHeadVertex(i)).isGraphVertex()) %7B%0A        usesInternal++;%0A      %7D else %7B%0A        usesExternal++;%0A      %7D%0A    %7D%0A    values%5B5%5D = Integer.toString(usesInternal);%0A    values%5B6%5D = Integer.toString(usesExternal);%0A    values%5B7%5D = Integer.toString(layerIndex);%0A    CLASS_START_FORMAT.format(values, result, null);%0A
+%0A        = new StringBuffer(CLASS_RENDERER.render(vertex, layerIndex));%0A%0A    String%5B%5D values = new String%5B2%5D;
 %0A   

change - using TemplateBasedClassRenderer