defs/ClassDef.java
/* [<][>][^][v][top][bottom][index][help] */
FUNCTIONS
This source file includes following functions.
- ClassDef
- getNodeRawValue
- createAttributes
- createForeignAttrs
- toCString
- getName
- getCode
- getStatus
- getDescription
- getDbaseCode
- getWidth
- getAttributes
- getForeignAttrs
- getEnum
- getTemplate
- getTemplateV
- getDiagram
- toString
- ClassDiagram
- toString
1 /******************
2 Copyright (c) 2002 RIPE NCC
3
4 All Rights Reserved
5
6 Permission to use, copy, modify, and distribute this software and its
7 documentation for any purpose and without fee is hereby granted,
8 provided that the above copyright notice appear in all copies and that
9 both that copyright notice and this permission notice appear in
10 supporting documentation, and that the name of the author not be
11 used in advertising or publicity pertaining to distribution of the
12 software without specific, written prior permission.
13
14 THE AUTHOR DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING
15 ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS; IN NO EVENT SHALL
16 AUTHOR BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY
17 DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN
18 AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
19 OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
20 ***************************************/
21
22 import java.util.*;
23 import org.w3c.dom.*;
24 //import org.w3c.dom.traversal.*;
25
26 /**
27 * RIPE class.
28 *
29 * @author ottrey@ripe.net
30 * @version $Version$
31 *
32 */
33 public class ClassDef {
/* [<][>][^][v][top][bottom][index][help] */
34
35 public static final int EXTRA_BIT=11;
36
37 private String name;
38 private String enum;
39 private String code;
40 private String status;
41 private String description;
42 private Vector attributes;
43 private int dbaseCode;
44
45 private int width; // The longest attribute name.
46 private Hashtable foreignAttrs;
47
48 // -----------------oOo-----------------
49 // Constructors
50 // -----------------oOo-----------------
51 /**
52 * Creates a RIPE class.
53 *
54 * @author ottrey@ripe.net
55 * @version $Version$
56 *
57 * @param obj The node from which a RIPE class is made.
58 *
59 * NOTE: No-one has implemented a Node.getNodeValue() method yet. ;-(
60 * description = tw.getNextElement("description").getNodeValue();
61 * So I wrote a crappy one here.
62 * @see getNodeValue
63 */
64 public ClassDef(Node obj, Hashtable ripeAttributes) {
65 width = 0;
66 name = obj.getAttributes().getNamedItem("name").getNodeValue();
67 code = obj.getAttributes().getNamedItem("code").getNodeValue();
68 status = obj.getAttributes().getNamedItem("status").getNodeValue();
69 enum = new String("C_" + code).toUpperCase();
70
71 Node search = obj.getFirstChild();
72 while (search != null) {
73 String nodeName = search.getNodeName();
74 if (nodeName.equals("description")) {
75 // Extract the "description".
76 description = getNodeRawValue(search);
77 } else if (nodeName.equals("attributes")) {
78 // Create the attributes.
79 attributes = createAttributes(search, ripeAttributes);
80 } else if (nodeName.equals("dbase_code")) {
81 // Get the dbase_code.
82 String dbaseCodeStr =
83 search.getAttributes().getNamedItem("value").getNodeValue();
84 try {
85 dbaseCode = Integer.parseInt(dbaseCodeStr);
86 } catch (NumberFormatException e) {
87 System.err.println("Bad dbaseCode: " + dbaseCodeStr);
88 System.err.println("\tencounterd in Object: " + obj);
89 System.exit(1);
90 }
91 }
92 search = search.getNextSibling();
93 }
94
95 // Create the foreignAttrs.
96 foreignAttrs = createForeignAttrs();
97
98 } // ClassDef()
99
100
101 /**
102 * Aaaargh I shouldn't have to write this. :-(
103 *
104 * @param node
105 * @return The value of the node.
106 * @see ClassDef
107 *
108 */
109 private String getNodeRawValue(Node node) {
/* [<][>][^][v][top][bottom][index][help] */
110 // String nodeStr = node.toString();
111 // int startIndex = nodeStr.indexOf('>') + 1;
112 // int endIndex = nodeStr.lastIndexOf('<') - 1;
113 //
114 // return nodeStr.substring(startIndex, endIndex);
115
116 StringBuffer sb = new StringBuffer();
117 Node kid = node.getFirstChild();
118 while (kid != null) {
119 if (kid.getNodeType() == Node.TEXT_NODE) {
120 sb.append(kid.getNodeValue());
121 }
122 kid = kid.getNextSibling();
123 }
124 return sb.toString();
125 } // getNodeRawValue()
126
127 /**
128 * Create the attributes for this class from the attributes already created.
129 *
130 * @param attrs The head node of the attributes tree from the classes DOM.
131 * @param ripeAttributes The attributes created from the attributes DOM.
132 * @return (methods only)
133 *
134 */
135 private Vector createAttributes(Node attrs, Hashtable ripeAttributes) {
/* [<][>][^][v][top][bottom][index][help] */
136 // Create a set of attributes for this class.
137 Vector result = new Vector();
138
139 AttributeDef adTmp;
140 String attrCode=null;
141 String status;
142
143 // Prepare to walk the tree.
144 // try {
145 Node attrNode = attrs.getFirstChild();
146 // Get the attribute node from the tree.
147 while (attrNode != null) {
148 // skip random noise
149 if (attrNode.getNodeType() != Node.ELEMENT_NODE) {
150 attrNode = attrNode.getNextSibling();
151 continue;
152 }
153
154 // Get the attribute code from the node.
155 attrCode = new String(attrNode.getNodeName());
156
157 // Get the attribute from the ripeAttributes.
158 adTmp = (AttributeDef)ripeAttributes.get(attrCode);
159 if (adTmp == null)
160 {
161 System.err.println("Missing definition for attribute '" + attrCode + "'");
162 System.exit(1);
163 }
164
165 // Keep track of the longest attribute name.
166 if ( adTmp.getName().length() > width ) {
167 width = adTmp.getName().length();
168 }
169
170 // If the attribute is "valid"
171 if ((status=adTmp.getStatus()).equals("valid")) {
172
173 // Create a clone of the attribute.
174 AttributeDef ad = null;
175 try {
176 ad = (AttributeDef)adTmp.clone();
177 }
178 catch (CloneNotSupportedException e) {
179 System.err.println("Doh!");
180 }
181
182 // Set the min attribute.
183 ad.setChoice(attrNode.getAttributes().getNamedItem("choice").getNodeValue());
184
185 // Set the max attribute.
186 ad.setNumber(attrNode.getAttributes().getNamedItem("number").getNodeValue());
187
188 // set the "pseudo" attribute, if requested
189 Node pseudo = attrNode.getAttributes().getNamedItem("pseudo");
190 if (pseudo != null) {
191 if (pseudo.getNodeValue().equalsIgnoreCase("yes")) {
192 ad.setPseudo(true);
193 }
194 }
195
196 // Add the attribute to this class.
197 result.addElement(ad);
198 }
199 else {
200 System.err.println("Warning: Class " + name + " contains a " +
201 status + " attribute: " + attrCode);
202 }
203
204 attrNode = attrNode.getNextSibling();
205 }
206 // }
207 // catch (NullPointerException e) {
208 // We tried to do something with a null - No worries, we caught it!
209 // System.err.println("Trouble creating attributes: " + e);
210 // System.err.println("attrCode=" + attrCode);
211 // System.err.println("attrs=" + attrs);
212 // }
213
214 return result;
215 } // createAttributes()
216
217 private Hashtable createForeignAttrs() {
/* [<][>][^][v][top][bottom][index][help] */
218 // Create a set of foreign attributes for this class.
219 Hashtable result = new Hashtable();
220
221 Enumeration e = attributes.elements();
222 while (e.hasMoreElements()) {
223 AttributeDef ad = (AttributeDef)e.nextElement();
224 //System.err.println("ad:" + ad);
225 String code = ad.getCode();
226 String foreign = ad.getForeign();
227 //System.err.println("foreign:" + foreign);
228 if (foreign.length() > 1 ) {
229 result.put(code, foreign);
230 }
231 }
232 return result;
233 } // createAttributes()
234
235 private String toCString(String str) {
/* [<][>][^][v][top][bottom][index][help] */
236 String result = new String();
237 char c;
238
239 result += "\"";
240 for(int i=0; i < str.length(); i++) {
241 c = str.charAt(i);
242 switch (c) {
243 case '\n':
244 result += "\\n\"\n\"";
245 break;
246
247 case '"':
248 result += "\\\"";
249 break;
250
251 case '&':
252 if(str.regionMatches(true, i, "<", 0, 4)) {
253 result += "<";
254 i += 3;
255 } else if(str.regionMatches(true, i, ">", 0, 4)) {
256 result += ">";
257 i += 3;
258 }
259 else {
260 result += c;
261 }
262 break;
263
264 default:
265 result += c;
266 }
267 }
268 result += "\"";
269
270 return result;
271 } // toCString
272
273 public String getName() {
/* [<][>][^][v][top][bottom][index][help] */
274 return name;
275 } // getCode()
276
277 public String getCode() {
/* [<][>][^][v][top][bottom][index][help] */
278 return code;
279 } // getCode()
280
281 public String getStatus() {
/* [<][>][^][v][top][bottom][index][help] */
282 return status;
283 } // getStatus()
284
285 public String getDescription(boolean CStyle) {
/* [<][>][^][v][top][bottom][index][help] */
286 String result = description;
287
288 if (CStyle) {
289 result = toCString(description);
290 }
291
292 return result;
293 } // getDescription()
294
295 public int getDbaseCode() {
/* [<][>][^][v][top][bottom][index][help] */
296 return dbaseCode;
297 } // getDbaseCode()
298
299 public int getWidth() {
/* [<][>][^][v][top][bottom][index][help] */
300 return width + EXTRA_BIT;
301 } // getWidth()
302
303 public Vector getAttributes() {
/* [<][>][^][v][top][bottom][index][help] */
304 return attributes;
305 } // getAttributes()
306
307 public Hashtable getForeignAttrs() {
/* [<][>][^][v][top][bottom][index][help] */
308 return foreignAttrs;
309 } // getForeignAttrs()
310
311 public String getEnum() {
/* [<][>][^][v][top][bottom][index][help] */
312 return enum;
313 } // getEnum()
314
315 /**
316 * Returns a template for the class in the form:
317 *
318 * boolean CStyle Returns in C style eg, with "\n\" at the end of each line.
319 *
320 * person: [mandatory] [single] [primary/look-up key]
321 * address: [mandatory] [multiple] [ ]
322 * phone: [mandatory] [multiple] [ ]
323 * fax-no: [optional] [multiple] [ ]
324 * e-mail: [optional] [multiple] [look-up key]
325 * nic-hdl: [mandatory] [single] [primary/look-up key]
326 * remarks: [optional] [multiple] [ ]
327 * notify: [optional] [multiple] [inverse key]
328 * mnt-by: [optional] [multiple] [inverse key]
329 * changed: [mandatory] [multiple] [ ]
330 * source: [mandatory] [single] [ ]
331 *
332 * @return String the template.
333 */
334 public String getTemplate(boolean CStyle) {
/* [<][>][^][v][top][bottom][index][help] */
335 String result = new String();
336
337 String pad1 = " "; /* XXX It is a crappy! assumption of the longest attribute name. */
338 String pad2 = " ";
339 String pad3 = " ";
340
341 String sofl = new String();
342 String eofl = new String();
343 if(CStyle) {
344 sofl = "\"";
345 eofl = "\\n\"\n";
346 }
347 else {
348 sofl = "";
349 eofl = "\n";
350 }
351
352 AttributeDef ad;
353 String name, choice, number, keytype;
354 Enumeration e = attributes.elements();
355 while (e.hasMoreElements()) {
356 ad = (AttributeDef)e.nextElement();
357 boolean pseudo = ad.getPseudo();
358 if (pseudo) {
359 continue;
360 }
361 name = ad.getName();
362 choice = ad.getChoice();
363 number = ad.getNumber();
364 keytype = ad.getKeytype2();
365 result += (sofl + name + ":" +
366 pad1.substring(0, pad1.length()-name.length()) +
367 "[" + choice + "]" +
368 pad2.substring(0, pad2.length()-choice.length()) +
369 "[" + number + "]" +
370 pad3.substring(0, pad3.length()-number.length()) +
371 "[" + keytype + "]" +
372 eofl
373 );
374 }
375
376 return result;
377 } // getTemplate()
378
379 public String getTemplateV(boolean CStyle, RPSLSyntax syntaxes) {
/* [<][>][^][v][top][bottom][index][help] */
380 String result=new String();
381 String templ = getTemplate(CStyle);
382
383 String sofl = new String();
384 String eofl = new String();
385 if(CStyle) {
386 sofl = "\"";
387 eofl = "\\n\"\n";
388 }
389 else {
390 sofl = "";
391 eofl = "\n";
392 }
393
394 result += (sofl + "The " + name + " class:" + eofl +
395 toCString(description) +
396 sofl + eofl +
397 templ +
398 sofl + eofl +
399 sofl + "The content of the attributes of the " +
400 name + " class are defined below:" + eofl +
401 sofl + eofl
402 );
403
404 // XXX: add formatting information
405 // String name, description, format;
406 Enumeration e = attributes.elements();
407 while (e.hasMoreElements()) {
408 AttributeDef ad = (AttributeDef)e.nextElement();
409 boolean pseudo = ad.getPseudo();
410 if (pseudo) {
411 continue;
412 }
413 String name = ad.getName();
414 AttributeSyntax syntax = syntaxes.getSyntaxByName(ad.getSyntax());
415 if (syntax == null) {
416 System.err.println("Unknown syntax '" + ad.getSyntax() + "'");
417 System.exit(1);
418 }
419 String description;
420 String syntaxDescription;
421 if (CStyle) {
422 description = toCString(ad.getDescription());
423 syntaxDescription = toCString(syntax.getDescription());
424 // XXX: formatting...
425 // format = toCString(ad.getFormat());
426 }
427 else {
428 description = ad.getDescription();
429 syntaxDescription = syntax.getDescription();
430 // XXX: formatting...
431 // format = ad.getFormat();
432 }
433
434 result += (sofl + name + eofl +
435 description +
436 syntaxDescription +
437 // XXX: formatting...
438 // format +
439 sofl + eofl
440 );
441 }
442
443 /* result += (sofl + eofl +
444 sofl + "Further information may be found at:" + eofl +
445 sofl + eofl +
446 sofl + "http://www.ripe.net/docs/ripe-157.html" + eofl +
447 sofl + "ftp://ftp.ripe.net/ripe/docs/ripe-157.ps" + eofl +
448 sofl + "ftp://ftp.ripe.net/ripe/docs/ripe-157.txt" + eofl +
449 sofl + eofl
450 );*/
451
452 return result;
453 } // getTemplateV()
454
455 public String getDiagram(int maxWidth, Hashtable foreigns) {
/* [<][>][^][v][top][bottom][index][help] */
456 ClassDiagram om = new ClassDiagram(this, maxWidth, foreigns);
457
458 return om.toString();
459 } // getDiagram()
460
461 /*
462 public boolean equals(ClassDef ro) {
463 return code.equals(ro.getCode());
464 } // equals()
465 */
466
467 public String toString() {
/* [<][>][^][v][top][bottom][index][help] */
468 return new String("ripe class={" +
469 "\n\tname=" + name +
470 "\n\tcode=" + code +
471 "\n\tstatus=" + status +
472 "\n\tdescription=" + description +
473 "\n\tattributes=" + attributes +
474 "\n\tdbaseCode=" + dbaseCode +
475 "\n\twidth=" + width +
476 "\n\tforeignAttrs=" + foreignAttrs +
477 "\n}");
478 } // toString()
479
480 /**
481 * RIPE class diagram.
482 *
483 * @author ottrey@ripe.net
484 * @version $Version$
485 *
486 */
487 public class ClassDiagram {
/* [<][>][^][v][top][bottom][index][help] */
488 private Vector diagram;
489
490 // -----------------oOo-----------------
491 // Constructors
492 // -----------------oOo-----------------
493 /**
494 * Creates a RIPE class diagram.
495 *
496 * @author ottrey@ripe.net
497 * @version $Version$
498 *
499 * @param od Definition to make diagram from.
500 */
501 public ClassDiagram(ClassDef od, int maxWidth, Hashtable foreigns) {
502 diagram = new Vector();
503 String line = new String();
504
505 String border = new String();
506 border = "+-";
507 for (int i=0; i < getWidth(); i++) {
508 border += ("-");
509 }
510 border += "-+ ";
511 for (int i=od.getWidth(); i < maxWidth; i++) {
512 border += (" ");
513 }
514 Enumeration e1 = foreigns.keys();
515 while (e1.hasMoreElements()) {
516 String foreign = (String)e1.nextElement();
517 if (e1.hasMoreElements()) {
518 border += ("|--");
519 }
520 }
521 border += ("|\n");
522 diagram.addElement(border);
523
524 line = ("| " + od.getCode() + ": " + od.getName());
525 for (int i=od.getName().length()+4; i < getWidth(); i++) {
526 line += (" ");
527 }
528 line += (" | ");
529 for (int i=od.getWidth(); i < maxWidth; i++) {
530 line += (" ");
531 }
532 Enumeration e3 = foreigns.keys();
533 while (e3.hasMoreElements()) {
534 String foreign = (String)e3.nextElement();
535 line += (foreign + " ");
536 }
537 line += ("\n");
538 diagram.addElement(line);
539
540 diagram.addElement(border);
541
542 AttributeDef ad;
543 Enumeration e = od.getAttributes().elements();
544 while (e.hasMoreElements()) {
545 ad = (AttributeDef)e.nextElement();
546 String name = ad.getName();
547 String keytype = ad.getKeytype3();
548 line = ("| " + ad.getCode() + ": " + name + " ");
549 for (int i=name.length(); i < width; i++) {
550 line += (" ");
551 }
552 line += (keytype + " |");
553
554 // The horizontal line.
555 // Is a foreign key.
556 boolean f = (ad.getForeign().length() > 1);
557 // Is a referenced key.
558 boolean p = (foreigns.contains(ad.getCode()));
559 if (f) {
560 line += ("->-");
561 }
562 else if (p) {
563 line += ("-|-");
564 } else {
565 line += (" ");
566 }
567 for (int i=od.getWidth(); i < maxWidth; i++) {
568 if (f || p) {
569 line += ("-");
570 }
571 else {
572 line += (" ");
573 }
574 }
575
576 // Add the xrefs.
577 Enumeration e2 = foreigns.keys();
578 while (e2.hasMoreElements()) {
579 String foreign = (String)e2.nextElement();
580 String code = ad.getCode();
581 if (foreign.equals(code)) {
582 line += ("X");
583 }
584 else if (foreigns.get(foreign).equals(code)) {
585 line += ("o");
586 }
587 else {
588 line += ("|");
589 }
590 if (e2.hasMoreElements()) {
591 line += ("--");
592 }
593 }
594 line += ("\n");
595 diagram.addElement(line);
596 }
597
598 diagram.addElement(border);
599 } // ClassDiagram()
600
601 public String toString() {
/* [<][>][^][v][top][bottom][index][help] */
602 String result = new String();
603
604 Enumeration e = diagram.elements();
605 while (e.hasMoreElements()) {
606 String line = (String)e.nextElement();
607 result += line;
608 }
609
610 return result;
611 } // toString()
612
613 } // ClassDiagram
614
615 } // ClassDef