defs/ClassDef.java

/* [<][>]
[^][v][top][bottom][index][help] */

FUNCTIONS

This source file includes following functions.
  1. ClassDef
  2. getNodeValue
  3. createAttributes
  4. createForeignAttrs
  5. toCString
  6. getName
  7. getCode
  8. getStatus
  9. getDescription
  10. getDbaseCode
  11. getWidth
  12. getAttributes
  13. getForeignAttrs
  14. getEnum
  15. getTemplate
  16. getTemplateV
  17. getDiagram
  18. toString
  19. ClassDiagram
  20. toString

import java.util.*;
import org.w3c.dom.*;
import com.sun.xml.tree.*;

/**
 * RIPE class.
 *
 * @author ottrey@ripe.net
 * @version $Version$
 *
 */
public class ClassDef {
/* [<][>][^][v][top][bottom][index][help] */

  public static final int EXTRA_BIT=11;

  private String    name;
  private String    code;
  private String    status;
  private String    description;
  private Vector    attributes;
  private int       dbaseCode;

  private int       width;        // The longest attribute name.
  private Hashtable foreignAttrs;

  // -----------------oOo-----------------
  //              Constructors
  // -----------------oOo-----------------
  /**
   * Creates a RIPE class.
   *               
   * @author ottrey@ripe.net
   * @version $Version$
   *               
   * @param obj The node from which a RIPE class is made.
   * 
   * NOTE: No-one has implemented a Node.getNodeValue() method yet.  ;-(
   *       description = tw.getNextElement("description").getNodeValue();
   *       So I wrote a crappy one here.
   * @see getNodeValue
   */
  public ClassDef(Node obj, Hashtable ripeAttributes) {
    width = 0;
    name      = obj.getAttributes().getNamedItem("name").getNodeValue();
    code      = obj.getAttributes().getNamedItem("code").getNodeValue();
    status    = obj.getAttributes().getNamedItem("status").getNodeValue();

    // Prepare to walk the tree.
    TreeWalker tw = new TreeWalker(obj);

    // Extract the "description".
    description = getNodeValue(tw.getNextElement("description"));

    // Create the attributes.
    attributes = createAttributes(tw.getNextElement("attributes"), ripeAttributes);
    
    // Get the dbase_code.
    dbaseCode = -1;
    Node dcn = tw.getNextElement("dbase_code");
    if (dcn != null) {
      String dbaseCodeStr = dcn.getAttributes().getNamedItem("value").getNodeValue();
      try {
        dbaseCode = Integer.parseInt(dbaseCodeStr);
      }
      catch (NumberFormatException e) {
        System.err.println("Bad dbaseCode: " + dbaseCodeStr); 
        System.err.println("\tencounterd in Object: " + obj); 
        System.exit(-1);
      }
    }

    // Create the foreignAttrs.
    foreignAttrs = createForeignAttrs();

  } // ClassDef()

  
  /**
   * Aaaargh I shouldn't have to write this. :-(
   *
   * @param        node
   * @return       The value of the node.
   * @see          ClassDef
   *
   */
  private String getNodeValue(Node node) {
/* [<][>][^][v][top][bottom][index][help] */
    String nodeStr = node.toString();
    int startIndex = nodeStr.indexOf('>') + 1;
    int endIndex = nodeStr.lastIndexOf('<') - 1;
    
    return nodeStr.substring(startIndex, endIndex);
  } // getNodeValue()
  
  /**
   * Create the attributes for this class from the attributes already created.
   *
   * @param  attrs          The head node of the attributes tree from the classes DOM.
   * @param  ripeAttributes The attributes created from the attributes DOM.
   * @return       (methods only)
   *
   */
  private Vector createAttributes(Node attrs, Hashtable ripeAttributes) {
/* [<][>][^][v][top][bottom][index][help] */
    // Create a set of attributes for this class.
    Vector result = new Vector();

    Node attrNode;
    AttributeDef adTmp;
    String attrCode=null;
    String status;

    // Prepare to walk the tree.
    TreeWalker tw = new TreeWalker(attrs);
    try {
      // Get the attribute node from the tree.
      while ((attrNode = tw.getNext()) != null) {
        // Get the attribute code from the node.
        attrCode = new String(attrNode.getNodeName());

        // Get the attribute from the ripeAttributes.
        adTmp = (AttributeDef)ripeAttributes.get(attrCode);

        // Keep track of the longest attribute name.
        if ( adTmp.getName().length() > width ) {
          width = adTmp.getName().length();
        }

        // If the attribute is "valid"
        if ((status=adTmp.getStatus()).equals("valid")) {

          // Create a clone of the attribute.
          AttributeDef ad = null;
          try {
            ad = (AttributeDef)adTmp.clone();
          }
          catch (CloneNotSupportedException e) {
            System.err.println("Doh!");
          }

          // Set the min attribute.
          ad.setChoice(attrNode.getAttributes().getNamedItem("choice").getNodeValue());

          // Set the max attribute.
          ad.setNumber(attrNode.getAttributes().getNamedItem("number").getNodeValue());

          // Add the attribute to this class.
          result.addElement(ad);
        }
        else {
          System.err.println("Warning: Class " + name + " contains a " +
                             status + " attribute: " + attrCode);
        }
      }
    }
    catch (NullPointerException e) {
      // We tried to do something with a null - No worries, we caught it!
      System.err.println("Trouble creating attributes: " + e);
      System.err.println("attrCode=" + attrCode);
      System.err.println("attrs=" + attrs);
    }
    
    return result;
  } // createAttributes()

  private Hashtable createForeignAttrs() {
/* [<][>][^][v][top][bottom][index][help] */
    // Create a set of foreign attributes for this class.
    Hashtable result = new Hashtable();

    Enumeration e = attributes.elements();
    while (e.hasMoreElements()) {
      AttributeDef ad = (AttributeDef)e.nextElement();
      String code = ad.getCode();
      String foreign = ad.getForeign();
      if (foreign.length() > 1 ) {
        result.put(code, foreign);
      }
    }
    return result;
  } // createAttributes()

  private String toCString(String str) {
/* [<][>][^][v][top][bottom][index][help] */
    String result = new String();
    char c;
    
    result += "\"";
    for(int i=0; i < str.length(); i++) {
      c = str.charAt(i);
      switch (c) {
        case '\n':
          result += "\\n\"\n\"";
        break;
        
        case '"':
          result += "\\\"";
        break;
        
        case '&':
          if(str.regionMatches(true, i, "&lt;", 0, 4)) {
            result += "<";
            i += 3;
          } else if(str.regionMatches(true, i, "&gt;", 0, 4)) {
            result += ">";
            i += 3;
          }
          else {
            result += c;
          }
        break;

        default:
          result += c;
      }
    }
    result += "\"";

    return result;
  } // toCString

  public String getName() {
/* [<][>][^][v][top][bottom][index][help] */
    return name;
  } // getCode()

  public String getCode() {
/* [<][>][^][v][top][bottom][index][help] */
    return code;
  } // getCode()

  public String getStatus() {
/* [<][>][^][v][top][bottom][index][help] */
    return status;
  } // getStatus()

  public String getDescription(boolean CStyle) {
/* [<][>][^][v][top][bottom][index][help] */
    String result = description;

    if (CStyle) {
      result = toCString(description);
    }

    return result;
  } // getDescription()

  public int getDbaseCode() {
/* [<][>][^][v][top][bottom][index][help] */
    return dbaseCode;
  } // getDbaseCode()

  public int getWidth() {
/* [<][>][^][v][top][bottom][index][help] */
    return width + EXTRA_BIT;
  } // getWidth()

  public Vector getAttributes() {
/* [<][>][^][v][top][bottom][index][help] */
    return attributes;
  } // getAttributes()

  public Hashtable getForeignAttrs() {
/* [<][>][^][v][top][bottom][index][help] */
    return foreignAttrs;
  } // getForeignAttrs()

  public String getEnum() {
/* [<][>][^][v][top][bottom][index][help] */
    return new String("C_" + code).toUpperCase();
  } // getEnum()

 /**
  * Returns a template for the class in the form:
  *
  * boolean CStyle Returns in C style eg, with "\n\" at the end of each line.
  *
  * person:      [mandatory]  [single]     [primary/look-up key]    
  * address:     [mandatory]  [multiple]   [ ]                      
  * phone:       [mandatory]  [multiple]   [ ]                      
  * fax-no:      [optional]   [multiple]   [ ]                      
  * e-mail:      [optional]   [multiple]   [look-up key]            
  * nic-hdl:     [mandatory]  [single]     [primary/look-up key]    
  * remarks:     [optional]   [multiple]   [ ]                      
  * notify:      [optional]   [multiple]   [inverse key]            
  * mnt-by:      [optional]   [multiple]   [inverse key]            
  * changed:     [mandatory]  [multiple]   [ ]                      
  * source:      [mandatory]  [single]     [ ]                      
  *
  * @return String the template.
  */
  public String getTemplate(boolean CStyle) {
/* [<][>][^][v][top][bottom][index][help] */
    String result = new String();

    String pad1 = "              "; /* XXX It is a crappy! assumption of the longest attribute name. */
    String pad2 = "           ";
    String pad3 = "           ";

    String sofl = new String();
    String eofl = new String();
    if(CStyle) {
      sofl = "\"";
      eofl = "\\n\"\n";
    }
    else {
      sofl = "";
      eofl = "\n";
    }

    AttributeDef ad;
    String name, choice, number, keytype;
    Enumeration e = attributes.elements();
    while (e.hasMoreElements()) {
      ad = (AttributeDef)e.nextElement();
      name = ad.getName();
      choice = ad.getChoice();
      number = ad.getNumber();
      keytype = ad.getKeytype2();
      result += (sofl + name + ":"                                 +
                 pad1.substring(0, pad1.length()-name.length())    +
                 "[" + choice + "]"                                +
                 pad2.substring(0, pad2.length()-choice.length())  +
                 "[" + number + "]"                                +
                 pad3.substring(0, pad3.length()-number.length())  +
                 "[" + keytype + "]"                               +
                 eofl
                );
    }

    return result;
  } // getTemplate()

  public String getTemplateV(boolean CStyle) {
/* [<][>][^][v][top][bottom][index][help] */
    String result=new String();
    String templ = getTemplate(CStyle);

    String sofl = new String();
    String eofl = new String();
    if(CStyle) {
      sofl = "\"";
      eofl = "\\n\"\n";
    }
    else {
      sofl = "";
      eofl = "\n";
    }

    result += (sofl + "The " + name + " class:" + eofl          +
               toCString(description)                           +
               sofl + eofl                                      +
               templ                                            +
               sofl + eofl                                      +
               sofl + "The content of the attributes of the "   +
               name + " class are defined below:" + eofl        +
               sofl + eofl
              );

    AttributeDef ad;
    String name, description, format;
    Enumeration e = attributes.elements();
    while (e.hasMoreElements()) {
      ad = (AttributeDef)e.nextElement();
      name = ad.getName();
      if (CStyle) {
        description = toCString(ad.getDescription());
        format = toCString(ad.getFormat());
      }
      else {
        description = ad.getDescription();
        format = ad.getFormat();
      }

      result += (sofl + name + eofl +
                 description        +
                 format             +
                 sofl + eofl     
                );
    }

    result += (sofl + eofl                                               +
               sofl + "Further information may be found at:" + eofl      +
               sofl + eofl                                               +
               sofl + "http://www.ripe.net/docs/ripe-157.html" + eofl    +
               sofl + "ftp://ftp.ripe.net/ripe/docs/ripe-157.ps" + eofl  +
               sofl + "ftp://ftp.ripe.net/ripe/docs/ripe-157.txt" + eofl +
               sofl + eofl
              );

    return result;
  } // getTemplateV()

  public String getDiagram(int maxWidth, Hashtable foreigns) {
/* [<][>][^][v][top][bottom][index][help] */
    ClassDiagram om = new ClassDiagram(this, maxWidth, foreigns);

    return om.toString();
  } // getDiagram()

  /*
  public boolean equals(ClassDef ro) {
    return code.equals(ro.getCode());
  } // equals()
  */
    
  public String toString() {
/* [<][>][^][v][top][bottom][index][help] */
    return new String("ripe class={" +
                         "\n\tname="         + name          +
                         "\n\tcode="         + code          +
                         "\n\tstatus="       + status        +
                         "\n\tdescription="  + description   +
                         "\n\tattributes="   + attributes    +
                         "\n\tdbaseCode="    + dbaseCode     +
                         "\n\twidth="        + width         +
                         "\n\tforeignAttrs=" + foreignAttrs  +
                         "\n}");
  } // toString()

  /**
   * RIPE class diagram.
   *
   * @author ottrey@ripe.net
   * @version $Version$
   *
   */
  public class ClassDiagram {
/* [<][>][^][v][top][bottom][index][help] */
    private Vector    diagram;

    // -----------------oOo-----------------
    //              Constructors
    // -----------------oOo-----------------
    /**
     * Creates a RIPE class diagram.
     *               
     * @author ottrey@ripe.net
     * @version $Version$
     *               
     * @param od Definition to make diagram from.
     */
    public ClassDiagram(ClassDef od, int maxWidth, Hashtable foreigns) {
      diagram = new Vector();
      String line = new String();

      String border = new String();
      border = "+-"; 
      for (int i=0; i < getWidth(); i++) {
        border += ("-");
      }
      border += "-+   "; 
      for (int i=od.getWidth(); i < maxWidth; i++) {
        border += (" ");
      }
      Enumeration e1 = foreigns.keys();
      while (e1.hasMoreElements()) {
        String foreign = (String)e1.nextElement();
        if (e1.hasMoreElements()) {
          border += ("|--");
        }
      }
      border += ("|\n");
      diagram.addElement(border);

      line = ("| " + od.getCode() + ": " + od.getName());
      for (int i=od.getName().length()+4; i < getWidth(); i++) {
        line += (" ");
      }
      line += (" |   ");
      for (int i=od.getWidth(); i < maxWidth; i++) {
        line += (" ");
      }
      Enumeration e3 = foreigns.keys();
      while (e3.hasMoreElements()) {
        String foreign = (String)e3.nextElement();
        line += (foreign + " ");
      }
      line += ("\n");
      diagram.addElement(line);

      diagram.addElement(border);

      AttributeDef ad;
      Enumeration e = od.getAttributes().elements();
      while (e.hasMoreElements()) {
        ad = (AttributeDef)e.nextElement();
        String name = ad.getName();
        String keytype = ad.getKeytype3();
        line = ("| " + ad.getCode() + ": " + name + " ");
        for (int i=name.length(); i < width; i++) {
          line += (" ");
        }
        line += (keytype + " |");

        // The horizontal line.
        // Is a foreign key.
        boolean f = (ad.getForeign().length() > 1);
        // Is a referenced key.
        boolean p = (foreigns.contains(ad.getCode()));
        if (f) {
          line += ("->-");
        }
        else if (p) {
          line += ("-|-");
        } else {
          line += ("   ");
        }
        for (int i=od.getWidth(); i < maxWidth; i++) {
          if (f || p) {
            line += ("-");
          }
          else {
            line += (" ");
          }
        }

        // Add the xrefs.
        Enumeration e2 = foreigns.keys();
        while (e2.hasMoreElements()) {
          String foreign = (String)e2.nextElement();
          String code = ad.getCode();
          if (foreign.equals(code)) {
            line += ("X");
          }
          else if (foreigns.get(foreign).equals(code)) {
            line += ("o");
          }
          else {
            line += ("|");
          }
          if (e2.hasMoreElements()) {
            line += ("--");
          }
        }
        line += ("\n");
        diagram.addElement(line);
      }

      diagram.addElement(border);
    } // ClassDiagram()

    public String toString() {
/* [<][>][^][v][top][bottom][index][help] */
      String result = new String();

      Enumeration e = diagram.elements();
      while (e.hasMoreElements()) {
        String line = (String)e.nextElement();
        result += line;
      }
      
      return result;
    } // toString()

  } // ClassDiagram

} // ClassDef

/* [<][>][^][v][top][bottom][index][help] */