4 * Operations to dump conceptual models for MIB modules.
6 * Copyright (c) 2000 A. Mueller, Technical University of Braunschweig.
8 * See the file "COPYING" for information on usage and redistribution
9 * of this file, and for a DISCLAIMER OF ALL WARRANTIES.
11 * @(#) $Id: dump-cm.c 2718 2005-08-24 06:59:15Z sperner $
18 * Berechnungen der UML Diagramme debuggen
43 * Definitions used by the dia output driver (node layout).
46 static const float HEADFONTSIZETABLE = (float)0.51;
47 static const float HEADSPACESIZETABLE = (float)0.6;
48 static const float ATTRFONTSIZE = (float)0.48;
49 static const float ATTRSPACESIZE = (float)2.4;
50 static const float RECTCORRECTION = (float)0.85;
51 static const float EDGEYSPACING = (float)2.0;
52 static const float TABLEHEIGHT = (float)2.6; /* headline of the table */
53 static const float TABLEELEMHEIGHT = (float)0.675; /* height of one attribute */
56 * global dia graph layout
58 static const float YSPACING = (float)3.0; /* y space between nodes */
59 static const float XSPACING = (float)4.0; /* x space between nodes */
60 static const float NEWLINEDISTANCE = (float)40.0; /* length of one line */
61 static const float XOFFSET = (float)2.0; /* left upper start of graph */
62 static const float YOFFSET = (float)5.0; /* left upper start of graph */
65 * position of the dia info note
67 static const float XNOTE = (float)1.0; /* left upper corner of note */
68 static const float YNOTE = (float)1.0; /* left upper corner of note */
73 static const char* STEREOTYPE = "smi mib class";
76 * Property String for index objects
78 static const char* INDEXPROPERTY = " {index}";
81 /* -------------- main functions ------------------------------------------- */
85 * Creates the graph nodes of the given module
87 static void algCreateNodes(SmiModule *module)
91 /* get tables and scalars from the MIB module */
92 for (node = smiGetFirstNode(module, SMI_NODEKIND_TABLE);
94 node = smiGetNextNode(node, SMI_NODEKIND_TABLE)) {
95 if (node->status != SMI_STATUS_OBSOLETE) {
96 if (!SUPPRESS_DEPRECATED || node->status != SMI_STATUS_DEPRECATED)
97 graphInsertNode(graph, node);
100 for (node = smiGetFirstNode(module, SMI_NODEKIND_SCALAR);
102 node = smiGetNextNode(node, SMI_NODEKIND_SCALAR)) {
103 if (node->status != SMI_STATUS_OBSOLETE) {
104 if (!SUPPRESS_DEPRECATED || node->status != SMI_STATUS_DEPRECATED)
105 graphInsertNode(graph, node);
112 /* ------ XML primitives ------ */
117 static void diaPrintXMLHeader()
119 printf("<?xml version=\"1.0\"?>\n");
120 printf("<diagram xmlns:dia=\"http://www.lysator.liu.se/~alla/dia/\">\n");
121 printf(" <diagramdata>\n");
122 printf(" <attribute name=\"background\">\n");
123 printf(" <color val=\"#ffffff\"/>\n");
124 printf(" </attribute>\n");
125 printf(" <attribute name=\"paper\">\n");
126 printf(" <composite type=\"paper\">\n");
127 printf(" <attribute name=\"name\">\n");
128 printf(" <string>#A4#</string>\n");
129 printf(" </attribute>\n");
130 printf(" <attribute name=\"tmargin\">\n");
131 printf(" <real val=\"2.82\"/>\n");
132 printf(" </attribute>\n");
133 printf(" <attribute name=\"bmargin\">\n");
134 printf(" <real val=\"2.82\"/>\n");
135 printf(" </attribute>\n");
136 printf(" <attribute name=\"lmargin\">\n");
137 printf(" <real val=\"2.82\"/>\n");
138 printf(" </attribute>\n");
139 printf(" <attribute name=\"rmargin\">\n");
140 printf(" <real val=\"2.82\"/>\n");
141 printf(" </attribute>\n");
142 printf(" <attribute name=\"is_portrait\">\n");
143 printf(" <boolean val=\"true\"/>\n");
144 printf(" </attribute>\n");
145 printf(" <attribute name=\"scaling\">\n");
146 printf(" <real val=\"1\"/>\n");
147 printf(" </attribute>\n");
148 printf(" <attribute name=\"fitto\">\n");
149 printf(" <boolean val=\"false\"/>\n");
150 printf(" </attribute>\n");
151 printf(" </composite>\n");
152 printf(" </attribute>\n");
153 printf(" </diagramdata>\n");
154 printf(" <layer name=\"Background\" visible=\"true\">\n");
157 static void diaPrintXMLClose()
159 printf(" </layer>\n");
160 printf("</diagram>\n");
164 * prints the type of a given node
166 static void diaPrintXMLType(SmiNode *smiNode, int index)
168 printf(" <attribute name=\"type\">\n");
170 printf(" <string>#%s%s#</string>\n",
171 algGetTypeName(smiNode), INDEXPROPERTY);
173 printf(" <string>#%s#</string>\n", algGetTypeName(smiNode));
175 printf(" </attribute>\n");
179 * index = 0 -> no index element
180 * index = 1 -> index element -> printed with "+"
182 static void diaPrintXMLAttribute(SmiNode *node, int index)
184 printf(" <composite type=\"umlattribute\">\n");
185 printf(" <attribute name=\"name\">\n");
186 printf(" <string>#%s#</string>\n", node->name);
187 printf(" </attribute>\n");
189 diaPrintXMLType(node,index);
191 printf(" <attribute name=\"value\">\n");
192 printf(" <string/>\n");
193 printf(" </attribute>\n");
194 printf(" <attribute name=\"visibility\">\n");
196 if (node->access == SMI_ACCESS_NOT_ACCESSIBLE) {
197 printf(" <enum val=\"1\"/>\n");
199 printf(" <enum val=\"0\"/>\n");
202 printf(" </attribute>\n");
203 printf(" <attribute name=\"abstract\">\n");
204 printf(" <boolean val=\"false\"/>\n");
205 printf(" </attribute>\n");
206 printf(" <attribute name=\"class_scope\">\n");
208 if (node->nodekind == SMI_NODEKIND_SCALAR) {
209 printf(" <boolean val=\"true\"/>\n");
211 printf(" <boolean val=\"false\"/>\n");
214 printf(" </attribute>\n");
215 printf(" </composite>\n");
219 * prints the related scalars for a given table
221 static void diaPrintXMLRelatedScalars(GraphNode *node)
225 for (tEdge = graphGetFirstEdgeByNode(graph, node);
227 tEdge = graphGetNextEdgeByNode(graph, tEdge, node)) {
228 if (tEdge->startNode == node &&
229 tEdge->endNode->smiNode->nodekind == SMI_NODEKIND_SCALAR) {
230 tEdge->dia.flags |= DIA_PRINT_FLAG;
231 tEdge->endNode->dia.flags |= DIA_PRINT_FLAG;
233 diaPrintXMLAttribute(tEdge->endNode->smiNode,0);
239 * prints all columns objects of the given node
241 static void diaPrintXMLAllColumns(GraphNode *node)
243 SmiModule *module = NULL;
244 SmiNode *smiNode = NULL;
247 module = smiGetNodeModule(node->smiNode);
249 for (smiNode = smiGetFirstNode(module, SMI_NODEKIND_COLUMN);
251 smiNode = smiGetNextNode(smiNode, SMI_NODEKIND_COLUMN)) {
252 ppNode = smiGetParentNode(smiNode);
253 ppNode = smiGetParentNode(ppNode);
255 if (!algIsIndexElement(node->smiNode, smiNode) &&
256 cmpSmiNodes(node->smiNode, ppNode))
257 diaPrintXMLAttribute(smiNode, 0);
262 * adds the index to an augmenting table (row-element)
264 static void diaPrintAugmentIndex(GraphNode *tNode)
267 SmiElement *smiElement;
269 for (tEdge = graphGetFirstEdgeByNode(graph, tNode);
271 tEdge = graphGetNextEdgeByNode(graph, tEdge, tNode)) {
272 if (tEdge->indexkind == SMI_INDEX_AUGMENT) {
273 for (smiElement = smiGetFirstElement(
274 smiGetFirstChildNode(tEdge->startNode->smiNode));
276 smiElement = smiGetNextElement(smiElement)) {
277 if (!cmpSmiNodes(tNode->smiNode, tEdge->startNode->smiNode)) {
278 diaPrintXMLAttribute(smiGetElementNode(smiElement),1);
285 static void diaPrintXMLObject(GraphNode *node, float x, float y)
287 SmiElement *smiElement;
290 if (node->dia.flags & DIA_PRINT_FLAG) return;
294 node->dia.flags |= DIA_PRINT_FLAG; /* object is now printed */
296 printf(" <object type=\"UML - Class\" version=\"0\" id=\"%s\">\n",
297 node->smiNode->name);
298 printf(" <attribute name=\"obj_pos\">\n");
299 printf(" <point val=\"%.2f,%.2f\"/>\n",x,y);
300 printf(" </attribute>\n");
301 printf(" <attribute name=\"obj_bb\">\n");
302 printf(" <rectangle val=\"0.0,0.0;0.0,0.0\"/>\n");
303 printf(" </attribute>\n");
304 printf(" <attribute name=\"elem_corner\">\n");
305 printf(" <point val=\"%.2f,%.2f\"/>\n",x,y);
306 printf(" </attribute>\n");
307 printf(" <attribute name=\"elem_width\">\n");
308 printf(" <real val=\"%.2f\"/>\n",node->dia.w);
309 printf(" </attribute>\n");
310 printf(" <attribute name=\"elem_height\">\n");
311 printf(" <real val=\"%.2f\"/>\n",node->dia.h);
312 printf(" </attribute>\n");
313 printf(" <attribute name=\"name\">\n");
314 printf(" <string>#%s#</string>\n",
315 smiGetFirstChildNode(node->smiNode)->name);
316 printf(" </attribute>\n");
317 printf(" <attribute name=\"stereotype\">\n");
318 printf(" <string>#%s#</string>\n", STEREOTYPE);
319 printf(" </attribute>\n");
320 printf(" <attribute name=\"abstract\">\n");
321 printf(" <boolean val=\"false\"/>\n");
322 printf(" </attribute>\n");
323 printf(" <attribute name=\"suppress_attributes\">\n");
324 printf(" <boolean val=\"false\"/>\n");
325 printf(" </attribute>\n");
326 printf(" <attribute name=\"suppress_operations\">\n");
327 printf(" <boolean val=\"true\"/>\n");
328 printf(" </attribute>\n");
329 printf(" <attribute name=\"visible_attributes\">\n");
330 printf(" <boolean val=\"true\"/>\n");
331 printf(" </attribute>\n");
332 printf(" <attribute name=\"visible_operations\">\n");
333 printf(" <boolean val=\"false\"/>\n");
334 printf(" </attribute>\n");
336 printf(" <attribute name=\"attributes\">\n");
338 if (node->smiNode->nodekind == SMI_NODEKIND_TABLE) {
340 diaPrintXMLRelatedScalars(node);
342 diaPrintAugmentIndex(node);
344 for (smiElement = smiGetFirstElement(
345 smiGetFirstChildNode(node->smiNode));
347 smiElement = smiGetNextElement(smiElement)) {
348 diaPrintXMLAttribute(smiGetElementNode(smiElement),1);
351 if (PRINT_DETAILED_ATTR) {
352 diaPrintXMLAllColumns(node);
356 printf(" </attribute>\n");
358 printf(" <attribute name=\"operations\"/>\n");
359 printf(" <attribute name=\"template\">\n");
360 printf(" <boolean val=\"false\"/>\n");
361 printf(" </attribute>\n");
362 printf(" <attribute name=\"templates\"/>\n");
363 printf(" </object>\n");
367 * prints a group of scalars denoted by group
369 static void diaPrintXMLGroup(int group, float x, float y)
373 for (tNode = graph->nodes; tNode; tNode = tNode->nextPtr) {
374 if (tNode->group == group) break;
379 printf(" <object type=\"UML - Class\" version=\"0\" id=\"%s\">\n",
380 smiGetParentNode(tNode->smiNode)->name);
381 printf(" <attribute name=\"obj_pos\">\n");
382 printf(" <point val=\"%.2f,%.2f\"/>\n",x,y);
383 printf(" </attribute>\n");
384 printf(" <attribute name=\"obj_bb\">\n");
385 printf(" <rectangle val=\"0.0,0.0;0.0,0.0\"/>\n");
386 printf(" </attribute>\n");
387 printf(" <attribute name=\"elem_corner\">\n");
388 printf(" <point val=\"%.2f,%.2f\"/>\n",x,y);
389 printf(" </attribute>\n");
390 printf(" <attribute name=\"elem_width\">\n");
391 printf(" <real val=\"%.2f\"/>\n",0.0);
392 printf(" </attribute>\n");
393 printf(" <attribute name=\"elem_height\">\n");
394 printf(" <real val=\"%.2f\"/>\n",0.0);
395 printf(" </attribute>\n");
396 printf(" <attribute name=\"name\">\n");
397 printf(" <string>#%s#</string>\n",
398 smiGetParentNode(tNode->smiNode)->name);
399 printf(" </attribute>\n");
400 printf(" <attribute name=\"stereotype\">\n");
401 printf(" <string>#%s#</string>\n", STEREOTYPE);
402 printf(" </attribute>\n");
403 printf(" <attribute name=\"abstract\">\n");
404 printf(" <boolean val=\"false\"/>\n");
405 printf(" </attribute>\n");
406 printf(" <attribute name=\"suppress_attributes\">\n");
407 printf(" <boolean val=\"false\"/>\n");
408 printf(" </attribute>\n");
409 printf(" <attribute name=\"suppress_operations\">\n");
410 printf(" <boolean val=\"true\"/>\n");
411 printf(" </attribute>\n");
412 printf(" <attribute name=\"visible_attributes\">\n");
413 printf(" <boolean val=\"true\"/>\n");
414 printf(" </attribute>\n");
415 printf(" <attribute name=\"visible_operations\">\n");
416 printf(" <boolean val=\"false\"/>\n");
417 printf(" </attribute>\n");
419 printf(" <attribute name=\"attributes\">\n");
421 for (tNode = graph->nodes; tNode; tNode = tNode->nextPtr) {
422 if (tNode->group == group) {
423 diaPrintXMLAttribute(tNode->smiNode,0);
427 printf(" </attribute>\n");
429 printf(" <attribute name=\"operations\"/>\n");
430 printf(" <attribute name=\"template\">\n");
431 printf(" <boolean val=\"false\"/>\n");
432 printf(" </attribute>\n");
433 printf(" <attribute name=\"templates\"/>\n");
434 printf(" </object>\n");
437 static float getRectSX(GraphNode *tNode)
439 return (float) (tNode->dia.w / 2.0 + tNode->dia.x - RECTCORRECTION);
442 static float getRectEX(GraphNode *tNode)
444 return (float) (tNode->dia.w / 2.0 + tNode->dia.x + RECTCORRECTION);
447 static float getRectSY(GraphNode *tNode)
449 return (float) (tNode->dia.y - 2.0 - RECTCORRECTION);
452 static float getRectEY(GraphNode *tNode)
454 return (float) (tNode->dia.y - 2.0 + RECTCORRECTION);
458 static int getConPoint(GraphNode *snode, GraphNode *enode)
468 if (x1 == x2 && y1 < y2) con = 6;
469 if (x1 == x2 && y1 > y1) con = 1;
470 if (x1 > x2 && y1 == y2) con = 3;
471 if (x1 < x2 && y1 == y2) con = 4;
472 if (x1 > x2 && y1 > y2) con = 0;
473 if (x1 > x2 && y1 < y2) con = 5;
474 if (x1 < x2 && y1 > y2) con = 2;
475 if (x1 < x2 && y1 < y2) con = 7;
480 static float getObjX(GraphNode *node, int con)
487 return (float) (node->dia.w / 2.0 + node->dia.x);
490 return node->dia.x + node->dia.w;
496 return node->dia.x + node->dia.w;
502 return (float) (node->dia.w / 2.0 + node->dia.x);
505 return node->dia.x + node->dia.w;
511 static float getObjY(GraphNode *node, int con)
524 return (float) (node->dia.y + TABLEHEIGHT / 2.0);
527 return (float) (node->dia.y + TABLEHEIGHT / 2.0);
530 return node->dia.y + node->dia.h;
533 return node->dia.y + node->dia.h;
536 return node->dia.y + node->dia.h;
542 static float getObjYRel(GraphEdge *edge, int con)
544 GraphNode *node, *node2;
547 node = edge->startNode;
548 node2 = edge->endNode;
549 if (node->dia.y < node2->dia.y) {
550 dist = ABS(((node->dia.y + node->dia.h) - node2->dia.y ) / 2.0);
552 dist = ABS((node->dia.y - (node2->dia.y + node2->dia.h)) / 2.0);
557 return node->dia.y - dist;
560 return node->dia.y - dist;
563 return node->dia.y - dist;
566 return (float) (node->dia.y + TABLEHEIGHT / 2.0);
569 return (float) (node->dia.y + TABLEHEIGHT / 2.0);
572 return node->dia.y + node->dia.h + dist;
575 return node->dia.y + node->dia.h + dist;
578 return node->dia.y + node->dia.h + dist;
585 * diaPrintXMLCoordinates
587 * prints and calculates the coordinates of a given edge
589 static void diaPrintXMLCoordinates(GraphEdge *tEdge)
593 scon = getConPoint(tEdge->startNode, tEdge->endNode);
594 econ = getConPoint(tEdge->endNode, tEdge->startNode);
596 printf(" <attribute name=\"obj_pos\">\n");
597 printf(" <point val=\"%.2f,%.2f\"/>\n"
598 ,getObjX(tEdge->startNode,scon)
599 ,getObjY(tEdge->startNode,scon));
600 printf(" </attribute>\n");
601 printf(" <attribute name=\"obj_bb\">\n");
602 printf(" <rectangle val=\"%.2f,%.2f;%.2f,%.2f\"/>\n"
603 ,getRectSX(tEdge->startNode)
604 ,getRectSY(tEdge->startNode)
605 ,getRectEX(tEdge->startNode)
606 ,getRectEY(tEdge->startNode));
607 printf(" </attribute>\n");
608 printf(" <attribute name=\"orth_points\">\n");
609 printf(" <point val=\"%.2f,%.2f\"/>\n"
610 ,getObjX(tEdge->startNode,scon)
611 ,getObjY(tEdge->startNode,scon));
612 printf(" <point val=\"%.2f,%.2f\"/>\n"
613 ,getObjX(tEdge->startNode,scon)
614 ,getObjYRel(tEdge,scon));
615 printf(" <point val=\"%.2f,%.2f\"/>\n"
616 ,getObjX(tEdge->endNode,econ)
617 ,getObjYRel(tEdge,scon));
618 printf(" <point val=\"%.2f,%.2f\"/>\n"
619 ,getObjX(tEdge->endNode,econ)
620 ,getObjY(tEdge->endNode,econ));
621 printf(" </attribute>\n");
625 * diaPrintXMLConPoints
627 * prints the connection points of an edge
629 static void diaPrintXMLConPoints(GraphEdge *tEdge)
633 scon = getConPoint(tEdge->startNode, tEdge->endNode);
634 econ = getConPoint(tEdge->endNode, tEdge->startNode);
636 printf(" <connections>\n");
637 printf(" <connection handle=\"0\" to=\"%s\" connection=\"%d\"/>\n",
638 tEdge->startNode->smiNode->name,scon);
639 printf(" <connection handle=\"1\" to=\"%s\" connection=\"%d\"/>\n",
640 tEdge->endNode->smiNode->name, econ);
641 printf(" </connections>\n");
644 static void diaPrintXMLDependency(GraphEdge *tEdge)
646 if (tEdge->dia.flags & DIA_PRINT_FLAG) return;
647 tEdge->dia.flags |= DIA_PRINT_FLAG;
649 printf(" <object type=\"UML - Dependency\" "
650 "version=\"0\" id=\"Depend:%s:%s\">\n",
651 tEdge->startNode->smiNode->name,
652 tEdge->endNode->smiNode->name);
654 diaPrintXMLCoordinates(tEdge);
656 printf(" <attribute name=\"orth_orient\">\n");
657 printf(" <enum val=\"1\"/>\n");
658 printf(" <enum val=\"0\"/>\n");
659 printf(" <enum val=\"1\"/>\n");
660 printf(" </attribute>\n");
661 printf(" <attribute name=\"draw_arrow\">\n");
662 printf(" <boolean val=\"true\"/>\n");
663 printf(" </attribute>\n");
664 printf(" <attribute name=\"name\">\n");
665 printf(" <string/>\n");
666 printf(" </attribute>\n");
667 printf(" <attribute name=\"stereotype\">\n");
668 printf(" <string/>\n");
669 printf(" </attribute>\n");
671 diaPrintXMLConPoints(tEdge);
673 printf(" </object>\n");
677 * Aggregation is a special case of the association.
678 * If aggregate = 1 it is an aggregation if 0 it is an association.
680 static void diaPrintXMLAssociation(GraphEdge *tEdge, int aggregate)
682 if (tEdge->dia.flags & DIA_PRINT_FLAG) return;
683 tEdge->dia.flags |= DIA_PRINT_FLAG;
684 if (aggregate > 1) aggregate = 1;
685 if (aggregate < 0) aggregate = 0;
687 printf(" <object type=\"UML - Association\" "
688 "version=\"0\" id=\"Assoc:%s:%s\">\n",
689 tEdge->startNode->smiNode->name,
690 tEdge->endNode->smiNode->name);
692 diaPrintXMLCoordinates(tEdge);
694 printf(" <attribute name=\"orth_orient\">\n");
695 printf(" <enum val=\"1\"/>\n");
696 printf(" <enum val=\"0\"/>\n");
697 printf(" <enum val=\"1\"/>\n");
698 printf(" </attribute>\n");
699 printf(" <attribute name=\"name\">\n");
701 switch(tEdge->indexkind) {
702 case SMI_INDEX_UNKNOWN :
703 switch (tEdge->enhancedindex) {
704 case GRAPH_ENHINDEX_UNKNOWN :
706 case GRAPH_ENHINDEX_TYPES :
707 printf(" <string>#%s#</string>\n","");
709 case GRAPH_ENHINDEX_NAMES :
710 printf(" <string>#%s#</string>\n","");
712 case GRAPH_ENHINDEX_NOTIFICATION :
713 printf(" <string>#%s#</string>\n","");
715 case GRAPH_ENHINDEX_INDEX :
716 /* should not occur - is handled below */
717 printf(" <string>#%s#</string>\n","");
719 case GRAPH_ENHINDEX_REROUTE :
720 printf(" <string>#%s#</string>\n","");
722 case GRAPH_ENHINDEX_POINTER :
723 printf(" <string>#%s#</string>\n","");
727 case SMI_INDEX_INDEX :
728 printf(" <string>#%s#</string>\n","");
730 case SMI_INDEX_AUGMENT :
731 printf(" <string>#%s#</string>\n","augments");
733 case SMI_INDEX_SPARSE :
734 printf(" <string>#%s#</string>\n","sparses");
736 case SMI_INDEX_REORDER :
737 printf(" <string>#%s#</string>\n","reorders");
739 case SMI_INDEX_EXPAND :
740 printf(" <string>#%s#</string>\n","expands");
744 printf(" </attribute>\n");
745 printf(" <attribute name=\"direction\">\n");
746 printf(" <enum val=\"0\"/>\n");
747 printf(" </attribute>\n");
748 printf(" <attribute name=\"ends\">\n");
749 printf(" <composite>\n");
750 printf(" <attribute name=\"role\">\n");
751 printf(" <string/>\n");
752 printf(" </attribute>\n");
753 printf(" <attribute name=\"multiplicity\">\n");
755 switch (tEdge->cardinality) {
756 case GRAPH_CARD_UNKNOWN :
757 printf(" <string># #</string>\n");
759 case GRAPH_CARD_ONE_TO_ONE :
760 printf(" <string>#1#</string>\n");
762 case GRAPH_CARD_ONE_TO_MANY :
763 printf(" <string>#1#</string>\n");
765 case GRAPH_CARD_ZERO_TO_ONE :
766 printf(" <string>#0#</string>\n");
768 case GRAPH_CARD_ZERO_TO_MANY :
769 printf(" <string>#0#</string>\n");
771 case GRAPH_CARD_ONE_TO_ZERO_OR_ONE :
772 printf(" <string>#1#</string>\n");
776 printf(" </attribute>\n");
777 printf(" <attribute name=\"arrow\">\n");
778 printf(" <boolean val=\"false\"/>\n");
779 printf(" </attribute>\n");
780 printf(" <attribute name=\"aggregate\">\n");
781 printf(" <enum val=\"0\"/>\n");
782 printf(" </attribute>\n");
783 printf(" </composite>\n");
784 printf(" <composite>\n");
785 printf(" <attribute name=\"role\">\n");
786 printf(" <string/>\n");
787 printf(" </attribute>\n");
789 printf(" <attribute name=\"multiplicity\">\n");
791 switch (tEdge->cardinality) {
792 case GRAPH_CARD_UNKNOWN :
793 printf(" <string># #</string>\n");
795 case GRAPH_CARD_ONE_TO_ONE :
796 printf(" <string>#1#</string>\n");
798 case GRAPH_CARD_ONE_TO_MANY :
799 printf(" <string>#*#</string>\n");
801 case GRAPH_CARD_ZERO_TO_ONE :
802 printf(" <string>#1#</string>\n");
804 case GRAPH_CARD_ZERO_TO_MANY :
805 printf(" <string>#*#</string>\n");
807 case GRAPH_CARD_ONE_TO_ZERO_OR_ONE :
808 printf(" <string>#0..1#</string>\n");
812 printf(" </attribute>\n");
813 printf(" <attribute name=\"arrow\">\n");
814 printf(" <boolean val=\"false\"/>\n");
815 printf(" </attribute>\n");
816 printf(" <attribute name=\"aggregate\">\n");
817 printf(" <enum val=\"%d\"/>\n",aggregate);
818 printf(" </attribute>\n");
819 printf(" </composite>\n");
820 printf(" </attribute>\n");
822 diaPrintXMLConPoints(tEdge);
824 printf(" </object>\n");
827 static void diaPrintXMLConnection(GraphEdge *tEdge)
829 switch (tEdge->connection) {
830 case GRAPH_CON_UNKNOWN:
832 case GRAPH_CON_AGGREGATION :
833 diaPrintXMLAssociation(tEdge,1);
835 case GRAPH_CON_DEPENDENCY :
836 diaPrintXMLDependency(tEdge);
838 case GRAPH_CON_ASSOCIATION :
839 diaPrintXMLAssociation(tEdge,0);
845 * diaPrintXMLInfoNote
847 * Prints an UML note with a short information on it (Modulename and
850 static void diaPrintXMLInfoNote(int modc, SmiModule **modv)
857 const char *s1 = "Conceptual model of ";
858 const char *s2 = "- generated by smidump " SMI_VERSION_STRING;
861 * Calculate the length of the string...
864 length = strlen(s1) + strlen(s2) + 1;
866 for (i = 0; i < modc; i++) {
867 length += strlen(modv[i]->name) + 1;
871 * ... before allocating a buffer and putting the string together.
874 note = xmalloc(length);
876 for (i = 0; i < modc; i++) {
877 strcat(note, modv[i]->name);
882 width = (float)strlen(note) * (float)0.76; /* don't ask */
884 printf("<object type=\"UML - Note\" version=\"0\" id=\"O0\">\n");
885 printf(" <attribute name=\"obj_pos\">\n");
886 printf(" <point val=\"%.2f,%.2f\"/>\n",XNOTE, YNOTE);
887 printf(" </attribute>\n");
888 printf(" <attribute name=\"obj_bb\">\n");
889 printf(" <rectangle val=\"%.2f,%.2f;%.2f,%.2f\"/>\n",
890 XNOTE-0.5, YNOTE-0.5, XNOTE-0.5 + width, YNOTE - 0.5 + 1.7);
891 printf(" </attribute>\n");
892 printf(" <attribute name=\"elem_corner\">\n");
893 printf(" <point val=\"%.2f,%.2f\"/>\n",XNOTE, YNOTE);
894 printf(" </attribute>\n");
895 printf(" <attribute name=\"elem_width\">\n");
896 printf(" <real val=\"%.2f\"/>\n", width);
897 printf(" </attribute>\n");
898 printf(" <attribute name=\"elem_height\">\n");
899 printf(" <real val=\"1.7\"/>\n");
900 printf(" </attribute>\n");
901 printf(" <attribute name=\"text\">\n");
902 printf(" <composite type=\"text\">\n");
903 printf(" <attribute name=\"string\">\n");
904 printf(" <string>#%s#</string>\n", note);
905 printf(" </attribute>\n");
906 printf(" <attribute name=\"font\">\n");
907 printf(" <font name=\"Courier\"/>\n");
908 printf(" </attribute>\n");
909 printf(" <attribute name=\"height\">\n");
910 printf(" <real val=\"0.8\"/>\n");
911 printf(" </attribute>\n");
912 printf(" <attribute name=\"pos\">\n");
913 printf(" <point val=\"%.2f,%.2f\"/>\n", XNOTE + 0.35, YNOTE + 1.28);
914 printf(" </attribute>\n");
915 printf(" <attribute name=\"color\">\n");
916 printf(" <color val=\"#000000\"/>\n");
917 printf(" </attribute>\n");
918 printf(" <attribute name=\"alignment\">\n");
919 printf(" <enum val=\"0\"/>\n");
920 printf(" </attribute>\n");
921 printf(" </composite>\n");
922 printf(" </attribute>\n");
923 printf("</object>\n");
931 * Calculates the size of a given node for the UML representation.
933 static GraphNode *diaCalcSize(GraphNode *node)
936 SmiNode *tNode,*ppNode;
937 SmiElement *smiElement;
940 if (node->smiNode->nodekind == SMI_NODEKIND_SCALAR) return node;
942 node->dia.w = (strlen(node->smiNode->name)+4) * HEADFONTSIZETABLE
943 + HEADSPACESIZETABLE;
945 node->dia.h = TABLEHEIGHT;
946 for (smiElement = smiGetFirstElement(
947 smiGetFirstChildNode(node->smiNode));
949 smiElement = smiGetNextElement(smiElement)) {
951 tNode = smiGetElementNode(smiElement);
953 node->dia.w = max(node->dia.w, (strlen(tNode->name) +
954 strlen(algGetTypeName(tNode)) +
955 strlen(INDEXPROPERTY))
958 node->dia.h += TABLEELEMHEIGHT;
961 for (tEdge = graphGetFirstEdgeByNode(graph,node);
963 tEdge = graphGetNextEdgeByNode(graph, tEdge, node)) {
964 if (tEdge->startNode == node &&
965 tEdge->endNode->smiNode->nodekind == SMI_NODEKIND_SCALAR) {
966 node->dia.h += TABLEELEMHEIGHT;
967 tNode = tEdge->endNode->smiNode;
969 node->dia.w = max(node->dia.w, (strlen(tNode->name) +
970 strlen(algGetTypeName(tNode)))
976 if (PRINT_DETAILED_ATTR && node->smiNode->nodekind == SMI_NODEKIND_TABLE) {
977 module = smiGetNodeModule(node->smiNode);
979 for (tNode = smiGetFirstNode(module, SMI_NODEKIND_COLUMN);
981 tNode = smiGetNextNode(tNode, SMI_NODEKIND_COLUMN)) {
982 ppNode = smiGetParentNode(tNode);
983 ppNode = smiGetParentNode(ppNode);
985 if (cmpSmiNodes(node->smiNode, ppNode)) {
989 typeName = algGetTypeName(tNode);
990 len = strlen(tNode->name) + (typeName ? strlen(typeName) : 0);
991 node->dia.h += TABLEELEMHEIGHT;
992 node->dia.w = max(node->dia.w, len)
1002 static float diaPrintNode(GraphNode *node, float x, float y)
1006 for (tEdge = graphGetFirstEdgeByNode(graph, node);
1008 tEdge = graphGetNextEdgeByNode(graph, tEdge, node)) {
1009 if (! (tEdge->dia.flags & DIA_PRINT_FLAG)) {
1010 if (node == tEdge->startNode) {
1011 y += tEdge->endNode->dia.h + YSPACING;
1012 diaPrintXMLObject(tEdge->endNode, x, y);
1013 diaPrintXMLConnection(tEdge);
1014 y = diaPrintNode(tEdge->startNode, x, y);
1015 /* (x+tEdge->startNode->dia.w+XSPACING),y); */
1017 y = diaPrintNode(tEdge->endNode,
1018 (x+tEdge->startNode->dia.w+XSPACING), y);
1026 static void diaPrintXML(int modc, SmiModule **modv)
1033 diaPrintXMLHeader();
1035 for (tNode = graph->nodes; tNode; tNode = tNode->nextPtr) {
1036 tNode = diaCalcSize(tNode);
1039 diaPrintXMLInfoNote(modc, modv);
1045 for (tEdge = graph->edges; tEdge; tEdge = tEdge->nextPtr) {
1046 if (! (tEdge->dia.flags & DIA_PRINT_FLAG)) {
1047 diaPrintXMLObject(tEdge->startNode, x, y);
1048 x = x + tEdge->startNode->dia.w + XSPACING;
1050 diaPrintXMLObject(tEdge->endNode, x, y);
1051 diaPrintXMLConnection(tEdge);
1053 ydiff = tEdge->startNode->dia.h;
1055 y = diaPrintNode(tEdge->startNode,x,y);
1056 y = diaPrintNode(tEdge->endNode,x,y);
1058 y = y + ydiff + YSPACING;
1067 /* printing singular tables */
1068 for (tNode = graph->nodes; tNode; tNode = tNode->nextPtr) {
1069 if (!graphGetFirstEdgeByNode(graph,tNode) &&
1070 tNode->smiNode->nodekind != SMI_NODEKIND_SCALAR) {
1071 diaPrintXMLObject(tNode,x,y);
1073 x += tNode->dia.w + XSPACING;
1074 ydiff = max(ydiff, tNode->dia.h);
1075 if (x >= NEWLINEDISTANCE) {
1077 y += ydiff + YSPACING;
1082 /* printing scalar groups */
1084 y += ydiff + YSPACING;
1086 group <= algGetNumberOfGroups();
1088 diaPrintXMLGroup(group,x,y);
1098 /* ------------------------------------------------------------------------- */
1100 static void printModuleNames(int modc, SmiModule **modv)
1104 printf("Conceptual model of: ");
1106 for (i = 0; i < modc; i++) {
1107 printf("%s ", modv[i]->name);
1110 printf("(generated by smidump " SMI_VERSION_STRING ")\n\n");
1115 static void dumpCm(int modc, SmiModule **modv, int flags, char *output)
1119 if (flags & SMIDUMP_FLAG_UNITE) {
1121 graph = xmalloc(sizeof(Graph));
1122 graph->nodes = NULL;
1123 graph->edges = NULL;
1124 graph->components = NULL;
1127 for (i = 0; i < modc; i++) {
1128 algCreateNodes(modv[i]);
1132 printModuleNames(modc, modv);
1133 printf("\n--- First Phase - loading tables and scalars\n\n");
1134 graphShowNodes(graph);
1139 algCheckLinksByName();
1140 algConnectLonelyNodes();
1141 algCheckForDependency();
1142 algCheckForPointerRels();
1145 diaPrintXML(modc, modv);
1150 for (i = 0; i < modc; i++) {
1152 graph = xmalloc(sizeof(Graph));
1153 graph->nodes = NULL;
1154 graph->edges = NULL;
1155 graph->components = NULL;
1158 algCreateNodes(modv[i]);
1161 printModuleNames(1, &(modv[i]));
1162 printf("\n--- First Phase - loading tables and scalars\n\n");
1163 graphShowNodes(graph);
1168 algCheckLinksByName();
1169 algConnectLonelyNodes();
1170 algCheckForDependency();
1171 algCheckForPointerRels();
1174 diaPrintXML(1, &(modv[i]));
1182 if (fflush(stdout) || ferror(stdout)) {
1183 perror("smidump: write error");
1192 static SmidumpDriverOption opt[] = {
1193 { "explain", OPT_FLAG, &XPLAIN, 0,
1194 "explain what the algorithm does"},
1195 { 0, OPT_END, 0, 0 }
1198 static SmidumpDriver driver = {
1202 SMIDUMP_DRIVER_CANT_OUTPUT,
1203 "reverse engineered conceptual model",
1208 smidumpRegisterDriver(&driver);