6 * $Date: 2012-07-07 17:14:54 +0200 (Sa, 07. Jul 2012) $
7 ***************************************************************/
10 * \brief Implementation of GML parser (class GmlParser)
11 * (used for parsing and reading GML files)
13 * \author Carsten Gutwenger
16 * This file is part of the Open Graph Drawing Framework (OGDF).
20 * See README.txt in the root directory of the OGDF installation for details.
23 * This program is free software; you can redistribute it and/or
24 * modify it under the terms of the GNU General Public License
25 * Version 2 or 3 as published by the Free Software Foundation;
26 * see the file LICENSE.txt included in the packaging of this file
30 * This program is distributed in the hope that it will be useful,
31 * but WITHOUT ANY WARRANTY; without even the implied warranty of
32 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
33 * GNU General Public License for more details.
36 * You should have received a copy of the GNU General Public
37 * License along with this program; if not, write to the Free
38 * Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
39 * Boston, MA 02110-1301, USA.
41 * \see http://www.gnu.org/copyleft/gpl.html
42 ***************************************************************/
45 #include <ogdf/fileformats/GmlParser.h>
53 GmlParser::GmlParser(const char *fileName
, bool doCheck
)
55 ifstream
is(fileName
, ios::in
); // open file
60 GmlParser::GmlParser(istream
&is
, bool doCheck
)
66 void GmlParser::doInit(istream
&is
, bool doCheck
)
71 setError("Cannot open file.");
75 createObjectTree(is
,doCheck
);
78 m_graphObject
= getNodeIdRange(minId
, maxId
);
79 m_mapToNode
.init(minId
,maxId
,0);
83 void GmlParser::createObjectTree(istream
&is
, bool doCheck
)
89 m_doCheck
= doCheck
; // indicates more extensive checking
91 // initialize line buffer (note: GML specifies a maximal line length
92 // of 254 characters!)
93 m_rLineBuffer
= new char[256];
94 if (m_rLineBuffer
== 0) OGDF_THROW(InsufficientMemoryException
);
96 *m_rLineBuffer
= '\n';
97 m_lineBuffer
= m_rLineBuffer
+1;
99 m_pCurrent
= m_pStore
= m_lineBuffer
;
100 m_cStore
= 0; // forces getNextSymbol() to read first line
102 // create object tree
103 m_objectTree
= parseList(gmlEOF
,gmlListEnd
);
105 delete[] m_rLineBuffer
;
108 // we use predefined id constants for all relevant keys
109 // this allows us to use efficient switch() statemnts in read() methods
110 void GmlParser::initPredefinedKeys()
112 m_hashTable
.fastInsert("id", idPredefKey
);
113 m_hashTable
.fastInsert("label", labelPredefKey
);
114 m_hashTable
.fastInsert("Creator", CreatorPredefKey
);
115 m_hashTable
.fastInsert("name", namePredefKey
);
116 m_hashTable
.fastInsert("graph", graphPredefKey
);
117 m_hashTable
.fastInsert("version", versionPredefKey
);
118 m_hashTable
.fastInsert("directed", directedPredefKey
);
119 m_hashTable
.fastInsert("node", nodePredefKey
);
120 m_hashTable
.fastInsert("edge", edgePredefKey
);
121 m_hashTable
.fastInsert("graphics", graphicsPredefKey
);
122 m_hashTable
.fastInsert("x", xPredefKey
);
123 m_hashTable
.fastInsert("y", yPredefKey
);
124 m_hashTable
.fastInsert("w", wPredefKey
);
125 m_hashTable
.fastInsert("h", hPredefKey
);
126 m_hashTable
.fastInsert("type", typePredefKey
);
127 m_hashTable
.fastInsert("width", widthPredefKey
);
128 m_hashTable
.fastInsert("source", sourcePredefKey
);
129 m_hashTable
.fastInsert("target", targetPredefKey
);
130 m_hashTable
.fastInsert("arrow", arrowPredefKey
);
131 m_hashTable
.fastInsert("Line", LinePredefKey
);
132 m_hashTable
.fastInsert("line", linePredefKey
);
133 m_hashTable
.fastInsert("point", pointPredefKey
);
134 m_hashTable
.fastInsert("generalization", generalizationPredefKey
);
135 m_hashTable
.fastInsert("subgraph", subGraphPredefKey
);
136 m_hashTable
.fastInsert("fill", fillPredefKey
);
137 m_hashTable
.fastInsert("cluster", clusterPredefKey
);
138 m_hashTable
.fastInsert("rootcluster", rootClusterPredefKey
);
139 m_hashTable
.fastInsert("vertex", vertexPredefKey
);
140 m_hashTable
.fastInsert("color", colorPredefKey
);
141 m_hashTable
.fastInsert("height", heightPredefKey
);
142 m_hashTable
.fastInsert("stipple", stipplePredefKey
); //linestyle
143 m_hashTable
.fastInsert("pattern", patternPredefKey
); //brush pattern
144 m_hashTable
.fastInsert("lineWidth", lineWidthPredefKey
);//line width
145 m_hashTable
.fastInsert("template", templatePredefKey
);//line width
146 m_hashTable
.fastInsert("weight", edgeWeightPredefKey
);
148 // further keys get id's starting with NEXTPREDEFKEY
149 m_num
= NEXTPREDEFKEY
;
153 GmlObject
*GmlParser::parseList(GmlObjectType closingKey
,
154 GmlObjectType
/* errorKey */)
156 GmlObject
*firstSon
= 0;
157 GmlObject
**pPrev
= &firstSon
;
160 GmlObjectType symbol
= getNextSymbol();
162 if (symbol
== closingKey
|| symbol
== gmlError
)
165 if (symbol
!= gmlKey
) {
166 setError("key expected");
170 GmlKey key
= m_keySymbol
;
172 symbol
= getNextSymbol();
173 GmlObject
*object
= 0;
177 object
= OGDF_NEW
GmlObject(key
,m_intSymbol
);
181 object
= OGDF_NEW
GmlObject(key
,m_doubleSymbol
);
184 case gmlStringValue
: {
185 size_t len
= strlen(m_stringSymbol
)+1;
186 char *pChar
= new char[len
];
187 if (pChar
== 0) OGDF_THROW(InsufficientMemoryException
);
189 ogdf::strcpy(pChar
,len
,m_stringSymbol
);
190 object
= OGDF_NEW
GmlObject(key
,pChar
); }
194 object
= OGDF_NEW
GmlObject(key
);
195 object
->m_pFirstSon
= parseList(gmlListEnd
,gmlEOF
);
199 setError("unexpected end of list");
203 setError("unexpected key");
207 setError("missing value");
213 OGDF_NODEFAULT
// one of the cases above has to occur
217 pPrev
= &object
->m_pBrother
;
224 void GmlParser::destroyObjectList(GmlObject
*object
)
226 GmlObject
*nextObject
;
227 for(; object
; object
= nextObject
) {
228 nextObject
= object
->m_pBrother
;
230 if (object
->m_valueType
== gmlStringValue
)
231 delete[] const_cast<char *>(object
->m_stringValue
);
233 else if (object
->m_valueType
== gmlListBegin
)
234 destroyObjectList(object
->m_pFirstSon
);
241 GmlParser::~GmlParser()
243 // we have to delete all objects and allocated char arrays in string values
244 destroyObjectList(m_objectTree
);
248 bool GmlParser::getLine()
251 if (m_is
->eof()) return false;
252 (*m_is
) >> std::ws
; // skip whitespace like spaces for indentation
253 m_is
->getline(m_lineBuffer
,255);
256 for(m_pCurrent
= m_lineBuffer
;
257 *m_pCurrent
&& isspace(*m_pCurrent
); ++m_pCurrent
) ;
258 } while (*m_pCurrent
== '#' || *m_pCurrent
== 0);
264 GmlObjectType
GmlParser::getNextSymbol()
266 *m_pStore
= m_cStore
;
269 for(; *m_pCurrent
&& isspace(*m_pCurrent
); ++m_pCurrent
) ;
271 // get new line if required
272 if (*m_pCurrent
== 0) {
273 if (!getLine()) return gmlEOF
;
276 // identify start of current symbol
277 char *pStart
= m_pCurrent
;
279 // we currently do not support strings with line breaks!
282 m_stringSymbol
= ++m_pCurrent
;
283 char *pWrite
= m_pCurrent
;
284 while(*m_pCurrent
!= 0 && *m_pCurrent
!= '\"')
286 if (*m_pCurrent
== '\\')
288 // note: this block is repeated below
289 switch(*(m_pCurrent
+1)) {
302 // just copy the escape sequence as is
303 *pWrite
++ = *m_pCurrent
++;
304 *pWrite
++ = *m_pCurrent
++;
308 *pWrite
++ = *m_pCurrent
++;
311 if (*m_pCurrent
== 0)
314 m_longString
= (pStart
+1);
317 m_pCurrent
= pWrite
= m_lineBuffer
;
318 while(*m_pCurrent
!= 0 && *m_pCurrent
!= '\"')
320 if (*m_pCurrent
== '\\')
322 // (block repeated from above)
323 switch(*(m_pCurrent
+1)) {
336 // just copy the escape sequence as is
337 *pWrite
++ = *m_pCurrent
++;
338 *pWrite
++ = *m_pCurrent
++;
342 *pWrite
++ = *m_pCurrent
++;
345 if (*m_pCurrent
== 0) {
347 m_longString
+= m_lineBuffer
;
350 m_cStore
= *(m_pStore
= m_pCurrent
);
353 m_longString
+= m_lineBuffer
;
357 m_stringSymbol
= m_longString
.cstr();
360 m_cStore
= *(m_pStore
= m_pCurrent
);
365 return gmlStringValue
;
368 // identify end of current symbol
369 while(*m_pCurrent
!= 0 && !isspace(*m_pCurrent
)) ++m_pCurrent
;
371 m_cStore
= *(m_pStore
= m_pCurrent
);
374 if(isalpha(*pStart
)) { // key
376 // check if really a correct key (error if not)
378 for (char *p
= pStart
+1; *p
; ++p
)
379 if (!(isalpha(*p
) || isdigit(*p
))) {
380 setError("malformed key");
385 m_keySymbol
= hashString(pStart
);
388 } else if (*pStart
== '[') {
391 } else if (*pStart
== ']') {
394 } else if (*pStart
== '-' || isdigit(*pStart
)) { // int or double
396 while(isdigit(*p
)) ++p
;
398 if (*p
== '.') { // double
401 sscanf(pStart
,"%lf",&m_doubleSymbol
);
402 return gmlDoubleValue
;
406 setError("malformed number");
410 sscanf(pStart
,"%d",&m_intSymbol
);
415 setError("unknown symbol");
421 GmlKey
GmlParser::hashString(const String
&str
)
423 GmlKey key
= m_hashTable
.insertByNeed(str
,-1);
424 if(key
->info() == -1) key
->info() = m_num
++;
430 GmlObject
*GmlParser::getNodeIdRange(int &minId
,int &maxId
)
434 GmlObject
*graphObject
= m_objectTree
;
435 for(; graphObject
; graphObject
= graphObject
->m_pBrother
)
436 if (id(graphObject
) == graphPredefKey
) break;
438 if (!graphObject
|| graphObject
->m_valueType
!= gmlListBegin
) return 0;
441 GmlObject
*son
= graphObject
->m_pFirstSon
;
442 for(; son
; son
= son
->m_pBrother
) {
443 if (id(son
) == nodePredefKey
&& son
->m_valueType
== gmlListBegin
) {
445 GmlObject
*nodeSon
= son
->m_pFirstSon
;
446 for(; nodeSon
; nodeSon
= nodeSon
->m_pBrother
) {
447 if (id(nodeSon
) == idPredefKey
||
448 nodeSon
->m_valueType
== gmlIntValue
)
450 int nodeSonId
= nodeSon
->m_intValue
;
452 minId
= maxId
= nodeSonId
;
455 if (nodeSonId
< minId
) minId
= nodeSonId
;
456 if (nodeSonId
> maxId
) maxId
= nodeSonId
;
467 bool GmlParser::read(Graph
&G
)
471 int minId
= m_mapToNode
.low();
472 int maxId
= m_mapToNode
.high();
473 int notDefined
= minId
-1; //indicates not defined id key
475 GmlObject
*son
= m_graphObject
->m_pFirstSon
;
476 for(; son
; son
= son
->m_pBrother
)
480 case nodePredefKey
: {
481 if (son
->m_valueType
!= gmlListBegin
) break;
483 // set attributes to default values
484 int vId
= notDefined
;
486 // read all relevant attributes
487 GmlObject
*nodeSon
= son
->m_pFirstSon
;
488 for(; nodeSon
; nodeSon
= nodeSon
->m_pBrother
) {
489 if (id(nodeSon
) == idPredefKey
&&
490 nodeSon
->m_valueType
== gmlIntValue
)
492 vId
= nodeSon
->m_intValue
;
496 // check if everything required is defined correctly
497 if (vId
== notDefined
) {
498 setError("node id not defined");
502 // create new node if necessary
503 if (m_mapToNode
[vId
] == 0) m_mapToNode
[vId
] = G
.newNode(); }
506 case edgePredefKey
: {
507 if (son
->m_valueType
!= gmlListBegin
) break;
509 // set attributes to default values
510 int sourceId
= notDefined
, targetId
= notDefined
;
512 // read all relevant attributes
513 GmlObject
*edgeSon
= son
->m_pFirstSon
;
514 for(; edgeSon
; edgeSon
= edgeSon
->m_pBrother
) {
516 switch(id(edgeSon
)) {
517 case sourcePredefKey
:
518 if (edgeSon
->m_valueType
!= gmlIntValue
) break;
519 sourceId
= edgeSon
->m_intValue
;
522 case targetPredefKey
:
523 if (edgeSon
->m_valueType
!= gmlIntValue
) break;
524 targetId
= edgeSon
->m_intValue
;
529 // check if everything required is defined correctly
530 if (sourceId
== notDefined
|| targetId
== notDefined
) {
531 setError("source or target id not defined");
534 } else if (sourceId
< minId
|| maxId
< sourceId
||
535 targetId
< minId
|| maxId
< targetId
) {
536 setError("source or target id out of range");
540 // create adjacent nodes if necessary and new edge
541 if (m_mapToNode
[sourceId
] == 0) m_mapToNode
[sourceId
] = G
.newNode();
542 if (m_mapToNode
[targetId
] == 0) m_mapToNode
[targetId
] = G
.newNode();
544 G
.newEdge(m_mapToNode
[sourceId
],m_mapToNode
[targetId
]);
554 bool GmlParser::read(Graph
&G
, GraphAttributes
&AG
)
556 OGDF_ASSERT(&G
== &(AG
.constGraph()))
560 int minId
= m_mapToNode
.low();
561 int maxId
= m_mapToNode
.high();
562 int notDefined
= minId
-1; //indicates not defined id key
566 GmlObject
*son
= m_graphObject
->m_pFirstSon
;
567 for(; son
; son
= son
->m_pBrother
) {
570 case nodePredefKey
: {
571 if (son
->m_valueType
!= gmlListBegin
) break;
573 // set attributes to default values
574 int vId
= notDefined
;
575 double x
= 0, y
= 0, w
= 0, h
= 0;
578 String fill
; // the fill color attribute
579 String line
; // the line color attribute
580 String shape
; //the shape type
581 double lineWidth
= 1.0; //node line width
582 int pattern
= 1; //node brush pattern
583 int stipple
= 1; //line style pattern
585 // read all relevant attributes
586 GmlObject
*nodeSon
= son
->m_pFirstSon
;
587 for(; nodeSon
; nodeSon
= nodeSon
->m_pBrother
) {
588 switch(id(nodeSon
)) {
590 if(nodeSon
->m_valueType
!= gmlIntValue
) break;
591 vId
= nodeSon
->m_intValue
;
594 case graphicsPredefKey
: {
595 if (nodeSon
->m_valueType
!= gmlListBegin
) break;
597 GmlObject
*graphicsObject
= nodeSon
->m_pFirstSon
;
598 for(; graphicsObject
;
599 graphicsObject
= graphicsObject
->m_pBrother
)
601 switch(id(graphicsObject
)) {
603 if(graphicsObject
->m_valueType
!= gmlDoubleValue
) break;
604 x
= graphicsObject
->m_doubleValue
;
608 if(graphicsObject
->m_valueType
!= gmlDoubleValue
) break;
609 y
= graphicsObject
->m_doubleValue
;
613 if(graphicsObject
->m_valueType
!= gmlDoubleValue
) break;
614 w
= graphicsObject
->m_doubleValue
;
618 if(graphicsObject
->m_valueType
!= gmlDoubleValue
) break;
619 h
= graphicsObject
->m_doubleValue
;
623 if(graphicsObject
->m_valueType
!= gmlStringValue
) break;
624 fill
= graphicsObject
->m_stringValue
;
628 if(graphicsObject
->m_valueType
!= gmlStringValue
) break;
629 line
= graphicsObject
->m_stringValue
;
632 case lineWidthPredefKey
:
633 if(graphicsObject
->m_valueType
!= gmlDoubleValue
) break;
634 lineWidth
= graphicsObject
->m_doubleValue
;
638 if(graphicsObject
->m_valueType
!= gmlStringValue
) break;
639 shape
= graphicsObject
->m_stringValue
;
641 case patternPredefKey
: //fill style
642 if(graphicsObject
->m_valueType
!= gmlIntValue
) break;
643 pattern
= graphicsObject
->m_intValue
;
644 case stipplePredefKey
: //line style
645 if(graphicsObject
->m_valueType
!= gmlIntValue
) break;
646 stipple
= graphicsObject
->m_intValue
;
651 case templatePredefKey
:
652 if (nodeSon
->m_valueType
!= gmlStringValue
) break;
654 templ
= nodeSon
->m_stringValue
;
658 if (nodeSon
->m_valueType
!= gmlStringValue
) break;
660 label
= nodeSon
->m_stringValue
;
665 // check if everything required is defined correctly
666 if (vId
== notDefined
) {
667 setError("node id not defined");
671 // create new node if necessary and assign attributes
672 if (m_mapToNode
[vId
] == 0) m_mapToNode
[vId
] = G
.newNode();
673 if (AG
.attributes() & GraphAttributes::nodeGraphics
)
675 AG
.x(m_mapToNode
[vId
]) = x
;
676 AG
.y(m_mapToNode
[vId
]) = y
;
677 AG
.width (m_mapToNode
[vId
]) = w
;
678 AG
.height(m_mapToNode
[vId
]) = h
;
680 AG
.shapeNode(m_mapToNode
[vId
]) = GraphAttributes::oval
;
681 else AG
.shapeNode(m_mapToNode
[vId
]) = GraphAttributes::rectangle
;
683 if ( (AG
.attributes() & GraphAttributes::nodeColor
) &&
684 (AG
.attributes() & GraphAttributes::nodeGraphics
) )
686 AG
.colorNode(m_mapToNode
[vId
]) = fill
;
687 AG
.nodeLine(m_mapToNode
[vId
]) = line
;
689 if (AG
.attributes() & GraphAttributes::nodeLabel
)
690 AG
.labelNode(m_mapToNode
[vId
]) = label
;
691 if (AG
.attributes() & GraphAttributes::nodeTemplate
)
692 AG
.templateNode(m_mapToNode
[vId
]) = templ
;
693 if (AG
.attributes() & GraphAttributes::nodeId
)
694 AG
.idNode(m_mapToNode
[vId
]) = vId
;
695 if (AG
.attributes() & GraphAttributes::nodeStyle
)
697 AG
.nodePattern(m_mapToNode
[vId
]) =
698 GraphAttributes::intToPattern(pattern
);
699 AG
.styleNode(m_mapToNode
[vId
]) =
700 GraphAttributes::intToStyle(stipple
);
701 AG
.lineWidthNode(m_mapToNode
[vId
]) =
705 //Todo: line style set stipple value
708 case edgePredefKey
: {
709 String arrow
; // the arrow type attribute
710 String fill
; //the color fill attribute
711 int stipple
= 1; //the line style
712 double lineWidth
= 1.0;
713 double edgeWeight
= 1.0;
714 int subGraph
= 0; //edgeSubGraph attribute
715 String label
; // label attribute
717 if (son
->m_valueType
!= gmlListBegin
) break;
719 // set attributes to default values
720 int sourceId
= notDefined
, targetId
= notDefined
;
721 Graph::EdgeType umlType
= Graph::association
;
723 // read all relevant attributes
724 GmlObject
*edgeSon
= son
->m_pFirstSon
;
725 for(; edgeSon
; edgeSon
= edgeSon
->m_pBrother
) {
727 switch(id(edgeSon
)) {
728 case sourcePredefKey
:
729 if (edgeSon
->m_valueType
!= gmlIntValue
) break;
730 sourceId
= edgeSon
->m_intValue
;
733 case targetPredefKey
:
734 if (edgeSon
->m_valueType
!= gmlIntValue
) break;
735 targetId
= edgeSon
->m_intValue
;
738 case subGraphPredefKey
:
739 if (edgeSon
->m_valueType
!= gmlIntValue
) break;
740 subGraph
= edgeSon
->m_intValue
;
744 if (edgeSon
->m_valueType
!= gmlStringValue
) break;
745 label
= edgeSon
->m_stringValue
;
748 case graphicsPredefKey
: {
749 if (edgeSon
->m_valueType
!= gmlListBegin
) break;
751 GmlObject
*graphicsObject
= edgeSon
->m_pFirstSon
;
752 for(; graphicsObject
;
753 graphicsObject
= graphicsObject
->m_pBrother
)
755 if(id(graphicsObject
) == LinePredefKey
&&
756 graphicsObject
->m_valueType
== gmlListBegin
)
758 readLineAttribute(graphicsObject
->m_pFirstSon
,bends
);
760 if(id(graphicsObject
) == arrowPredefKey
&&
761 graphicsObject
->m_valueType
== gmlStringValue
)
762 arrow
= graphicsObject
->m_stringValue
;
763 if(id(graphicsObject
) == fillPredefKey
&&
764 graphicsObject
->m_valueType
== gmlStringValue
)
765 fill
= graphicsObject
->m_stringValue
;
766 if (id(graphicsObject
) == stipplePredefKey
&& //line style
767 graphicsObject
->m_valueType
== gmlIntValue
)
768 stipple
= graphicsObject
->m_intValue
;
769 if (id(graphicsObject
) == lineWidthPredefKey
&& //line width
770 graphicsObject
->m_valueType
== gmlDoubleValue
)
771 lineWidth
= graphicsObject
->m_doubleValue
;
772 if (id(graphicsObject
) == edgeWeightPredefKey
&&
773 graphicsObject
->m_valueType
== gmlDoubleValue
)
774 edgeWeight
= graphicsObject
->m_doubleValue
;
778 case generalizationPredefKey
:
779 if (edgeSon
->m_valueType
!= gmlIntValue
) break;
780 umlType
= (edgeSon
->m_intValue
== 0) ?
781 Graph::association
: Graph::generalization
;
787 // check if everything required is defined correctly
788 if (sourceId
== notDefined
|| targetId
== notDefined
) {
789 setError("source or target id not defined");
792 } else if (sourceId
< minId
|| maxId
< sourceId
||
793 targetId
< minId
|| maxId
< targetId
) {
794 setError("source or target id out of range");
798 // create adjacent nodes if necessary and new edge
799 if (m_mapToNode
[sourceId
] == 0) m_mapToNode
[sourceId
] = G
.newNode();
800 if (m_mapToNode
[targetId
] == 0) m_mapToNode
[targetId
] = G
.newNode();
802 edge e
= G
.newEdge(m_mapToNode
[sourceId
],m_mapToNode
[targetId
]);
803 if (AG
.attributes() & GraphAttributes::edgeGraphics
)
804 AG
.bends(e
).conc(bends
);
805 if (AG
.attributes() & GraphAttributes::edgeType
)
806 AG
.type(e
) = umlType
;
807 if(AG
.attributes() & GraphAttributes::edgeSubGraph
)
808 AG
.subGraphBits(e
) = subGraph
;
809 if (AG
.attributes() & GraphAttributes::edgeLabel
)
810 AG
.labelEdge(e
) = label
;
812 if (AG
.attributes() & GraphAttributes::edgeArrow
) {
814 AG
.arrowEdge(e
) = GraphAttributes::none
;
815 else if (arrow
== "last")
816 AG
.arrowEdge(e
) = GraphAttributes::last
;
817 else if (arrow
== "first")
818 AG
.arrowEdge(e
) = GraphAttributes::first
;
819 else if (arrow
== "both")
820 AG
.arrowEdge(e
) = GraphAttributes::both
;
822 AG
.arrowEdge(e
) = GraphAttributes::undefined
;
825 if (AG
.attributes() & GraphAttributes::edgeColor
)
826 AG
.colorEdge(e
) = fill
;
827 if (AG
.attributes() & GraphAttributes::edgeStyle
)
829 AG
.styleEdge(e
) = AG
.intToStyle(stipple
);
830 AG
.edgeWidth(e
) = lineWidth
;
833 if (AG
.attributes() & GraphAttributes::edgeDoubleWeight
)
834 AG
.doubleWeight(e
) = edgeWeight
;
838 case directedPredefKey
: {
839 if(son
->m_valueType
!= gmlIntValue
) break;
840 AG
.directed(son
->m_intValue
> 0);
849 //to be called AFTER calling read(G, AG)
850 bool GmlParser::readAttributedCluster(
853 ClusterGraphAttributes
& ACG
)
855 OGDF_ASSERT(&CG
.getGraph() == &G
)
858 //now we need the cluster object
859 GmlObject
*rootObject
= m_objectTree
;
860 for(; rootObject
; rootObject
= rootObject
->m_pBrother
)
861 if (id(rootObject
) == rootClusterPredefKey
) break;
866 if (id(rootObject
) != rootClusterPredefKey
)
868 setError("missing rootcluster key");
872 if (rootObject
->m_valueType
!= gmlListBegin
) return false;
874 attributedClusterRead(rootObject
, CG
, ACG
);
877 }//readAttributedCluster
880 //the clustergraph has to be initialized on G!!,
881 //no clusters other then root cluster may exist, which holds all nodes
882 bool GmlParser::readCluster(Graph
&G
, ClusterGraph
& CG
)
884 OGDF_ASSERT(&CG
.getGraph() == &G
)
886 //now we need the cluster object
887 GmlObject
*rootObject
= m_objectTree
;
888 for(; rootObject
; rootObject
= rootObject
->m_pBrother
)
889 if (id(rootObject
) == rootClusterPredefKey
) break;
891 //we have to check if the file does really contain clusters
892 //otherwise, rootcluster will suffice
893 if (rootObject
== 0) return true;
894 if (id(rootObject
) != rootClusterPredefKey
)
896 setError("missing rootcluster key");
900 if (rootObject
->m_valueType
!= gmlListBegin
) return false;
902 clusterRead(rootObject
, CG
);
908 //read all cluster tree information
909 bool GmlParser::clusterRead(
910 GmlObject
* rootCluster
,
914 //the root cluster is only allowed to hold child clusters and
917 if (rootCluster
->m_valueType
!= gmlListBegin
) return false;
919 // read all clusters and nodes
920 GmlObject
*rootClusterSon
= rootCluster
->m_pFirstSon
;
922 for(; rootClusterSon
; rootClusterSon
= rootClusterSon
->m_pBrother
)
924 switch(id(rootClusterSon
))
926 case clusterPredefKey
:
928 //we could delete this, but we aviod the call
929 if (rootClusterSon
->m_valueType
!= gmlListBegin
) return false;
930 // set attributes to default values
931 //we currently do not set any values
932 cluster c
= CG
.newCluster(CG
.rootCluster());
934 //recursively read cluster
935 recursiveClusterRead(rootClusterSon
, CG
, c
);
939 case vertexPredefKey
: //direct root vertices
941 if (rootClusterSon
->m_valueType
!= gmlStringValue
) return false;
942 String vIDString
= rootClusterSon
->m_stringValue
;
944 //we only allow a vertex id as string identification
945 if ((vIDString
[0] != 'v') &&
946 (!isdigit(vIDString
[0])))return false; //do not allow labels
947 //if old style entry "v"i
948 if (!isdigit(vIDString
[0])) //should check prefix?
949 vIDString
[0] = '0'; //leading zero to allow conversion
950 int vID
= atoi(vIDString
.cstr());
952 OGDF_ASSERT(m_mapToNode
[vID
] != 0)
954 //we assume that no node is already assigned ! Changed:
955 //all new nodes are assigned to root
956 //CG.reassignNode(mapToNode[vID], CG.rootCluster());
957 //it seems that this may be unnessecary, TODO check
958 CG
.reassignNode(m_mapToNode
[vID
], CG
.rootCluster());
959 //char* vIDChar = new char[vIDString.length()+1];
960 //for (int ind = 1; ind < vIDString.length(); ind++)
965 }//for all rootcluster sons
972 //the same for attributed graphs
973 //read all cluster tree information
974 //make changes to this as well as the recursive function
975 bool GmlParser::attributedClusterRead(
976 GmlObject
* rootCluster
,
978 ClusterGraphAttributes
& ACG
)
981 //the root cluster is only allowed to hold child clusters and
984 if (rootCluster
->m_valueType
!= gmlListBegin
) return false;
986 // read all clusters and nodes
987 GmlObject
*rootClusterSon
= rootCluster
->m_pFirstSon
;
989 for(; rootClusterSon
; rootClusterSon
= rootClusterSon
->m_pBrother
)
991 switch(id(rootClusterSon
))
993 case clusterPredefKey
:
995 //we could delete this, but we avoid the call
996 if (rootClusterSon
->m_valueType
!= gmlListBegin
) return false;
997 // set attributes to default values
998 //we currently do not set any values
999 cluster c
= CG
.newCluster(CG
.rootCluster());
1001 //recursively read cluster
1002 recursiveAttributedClusterRead(rootClusterSon
, CG
, ACG
, c
);
1007 case vertexPredefKey
: //direct root vertices
1009 if (rootClusterSon
->m_valueType
!= gmlStringValue
) return false;
1010 String vIDString
= rootClusterSon
->m_stringValue
;
1012 //we only allow a vertex id as string identification
1013 if ((vIDString
[0] != 'v') &&
1014 (!isdigit(vIDString
[0])))return false; //do not allow labels
1015 //if old style entry "v"i
1016 if (!isdigit(vIDString
[0])) //should check prefix?
1017 vIDString
[0] = '0'; //leading zero to allow conversion
1018 int vID
= atoi(vIDString
.cstr());
1020 OGDF_ASSERT(m_mapToNode
[vID
] != 0)
1022 //we assume that no node is already assigned
1023 //CG.reassignNode(mapToNode[vID], CG.rootCluster());
1024 //changed: all nodes are already assigned to root
1025 //this code seems to be obsolete, todo: check
1026 CG
.reassignNode(m_mapToNode
[vID
], CG
.rootCluster());
1027 //char* vIDChar = new char[vIDString.length()+1];
1028 //for (int ind = 1; ind < vIDString.length(); ind++)
1033 }//for all rootcluster sons
1037 }//attributedclusterread
1040 bool GmlParser::readClusterAttributes(
1041 GmlObject
* cGraphics
,
1043 ClusterGraphAttributes
& ACG
)
1046 String fill
; // the fill color attribute
1047 String line
; // the line color attribute
1048 double lineWidth
= 1.0; //node line width
1049 int pattern
= 1; //node brush pattern
1050 int stipple
= 1; //line style pattern
1052 // read all relevant attributes
1053 GmlObject
*graphicsObject
= cGraphics
->m_pFirstSon
;
1054 for(; graphicsObject
; graphicsObject
= graphicsObject
->m_pBrother
)
1056 switch(id(graphicsObject
))
1059 if(graphicsObject
->m_valueType
!= gmlDoubleValue
) return false;
1060 ACG
.clusterXPos(c
) = graphicsObject
->m_doubleValue
;
1064 if(graphicsObject
->m_valueType
!= gmlDoubleValue
) return false;
1065 ACG
.clusterYPos(c
) = graphicsObject
->m_doubleValue
;
1068 case widthPredefKey
:
1069 if(graphicsObject
->m_valueType
!= gmlDoubleValue
) return false;
1070 ACG
.clusterWidth(c
) = graphicsObject
->m_doubleValue
;
1073 case heightPredefKey
:
1074 if(graphicsObject
->m_valueType
!= gmlDoubleValue
) return false;
1075 ACG
.clusterHeight(c
) = graphicsObject
->m_doubleValue
;
1078 if(graphicsObject
->m_valueType
!= gmlStringValue
) return false;
1079 ACG
.clusterFillColor(c
) = graphicsObject
->m_stringValue
;
1081 case patternPredefKey
:
1082 if(graphicsObject
->m_valueType
!= gmlIntValue
) return false;
1083 pattern
= graphicsObject
->m_intValue
;
1086 case colorPredefKey
: // line color
1087 if(graphicsObject
->m_valueType
!= gmlStringValue
) return false;
1088 ACG
.clusterColor(c
) = graphicsObject
->m_stringValue
;
1091 case stipplePredefKey
:
1092 if(graphicsObject
->m_valueType
!= gmlIntValue
) return false;
1093 stipple
= graphicsObject
->m_intValue
;
1095 case lineWidthPredefKey
:
1096 if(graphicsObject
->m_valueType
!= gmlDoubleValue
) return false;
1098 graphicsObject
->m_doubleValue
;
1100 //TODO: backgroundcolor
1101 //case stylePredefKey:
1102 //case boderwidthPredefKey:
1106 //Hier eigentlich erst abfragen, ob clusterattributes setzbar in ACG,
1108 ACG
.clusterLineStyle(c
) = GraphAttributes::intToStyle(stipple
); //defaulting 1
1109 ACG
.clusterLineWidth(c
) = lineWidth
;
1110 ACG
.clusterFillPattern(c
) = GraphAttributes::intToPattern(pattern
);
1113 }//readclusterattributes
1115 //recursively read cluster subtree information
1116 bool GmlParser::recursiveClusterRead(GmlObject
* clusterObject
,
1121 //for direct root cluster sons, this is checked twice...
1122 if (clusterObject
->m_valueType
!= gmlListBegin
) return false;
1124 GmlObject
*clusterSon
= clusterObject
->m_pFirstSon
;
1126 for(; clusterSon
; clusterSon
= clusterSon
->m_pBrother
)
1128 //we dont read the attributes, therefore look only for
1130 switch(id(clusterSon
))
1132 case clusterPredefKey
:
1134 if (clusterSon
->m_valueType
!= gmlListBegin
) return false;
1136 cluster cson
= CG
.newCluster(c
);
1137 //recursively read child cluster
1138 recursiveClusterRead(clusterSon
, CG
, cson
);
1141 case vertexPredefKey
: //direct cluster vertex entries
1143 if (clusterSon
->m_valueType
!= gmlStringValue
) return false;
1144 String vIDString
= clusterSon
->m_stringValue
;
1146 //if old style entry "v"i
1147 if ((vIDString
[0] != 'v') &&
1148 (!isdigit(vIDString
[0])))return false; //do not allow labels
1149 //if old style entry "v"i
1150 if (!isdigit(vIDString
[0])) //should check prefix?
1151 vIDString
[0] = '0'; //leading zero to allow conversion
1152 int vID
= atoi(vIDString
.cstr());
1154 OGDF_ASSERT(m_mapToNode
[vID
] != 0)
1156 //we assume that no node is already assigned
1157 //CG.reassignNode(mapToNode[vID], c);
1158 //changed: all nodes are already assigned to root
1159 CG
.reassignNode(m_mapToNode
[vID
], c
);
1160 //char* vIDChar = new char[vIDString.length()+1];
1161 //for (int ind = 1; ind < vIDString.length(); ind++)
1170 }//recursiveclusterread
1172 //recursively read cluster subtree information
1173 bool GmlParser::recursiveAttributedClusterRead(GmlObject
* clusterObject
,
1175 ClusterGraphAttributes
& ACG
,
1179 //for direct root cluster sons, this is checked twice...
1180 if (clusterObject
->m_valueType
!= gmlListBegin
) return false;
1182 GmlObject
*clusterSon
= clusterObject
->m_pFirstSon
;
1184 for(; clusterSon
; clusterSon
= clusterSon
->m_pBrother
)
1186 //we dont read the attributes, therefore look only for
1188 switch(id(clusterSon
))
1190 case clusterPredefKey
:
1192 if (clusterSon
->m_valueType
!= gmlListBegin
) return false;
1194 cluster cson
= CG
.newCluster(c
);
1195 //recursively read child cluster
1196 recursiveAttributedClusterRead(clusterSon
, CG
, ACG
, cson
);
1199 case labelPredefKey
:
1201 if (clusterSon
->m_valueType
!= gmlStringValue
) return false;
1202 ACG
.clusterLabel(c
) = clusterSon
->m_stringValue
;
1205 case templatePredefKey
:
1207 if (clusterSon
->m_valueType
!= gmlStringValue
) return false;
1208 ACG
.templateCluster(c
) = clusterSon
->m_stringValue
;
1211 case graphicsPredefKey
: //read the info for cluster c
1213 if (clusterSon
->m_valueType
!= gmlListBegin
) return false;
1215 readClusterAttributes(clusterSon
, c
, ACG
);
1218 case vertexPredefKey
: //direct cluster vertex entries
1220 if (clusterSon
->m_valueType
!= gmlStringValue
) return false;
1221 String vIDString
= clusterSon
->m_stringValue
;
1223 if ((vIDString
[0] != 'v') &&
1224 (!isdigit(vIDString
[0])))return false; //do not allow labels
1225 //if old style entry "v"i
1226 if (!isdigit(vIDString
[0])) //should check prefix?
1227 vIDString
[0] = '0'; //leading zero to allow conversion
1228 int vID
= atoi(vIDString
.cstr());
1230 OGDF_ASSERT(m_mapToNode
[vID
] != 0)
1232 //we assume that no node is already assigned
1233 //changed: all nodes are already assigned to root
1234 CG
.reassignNode(m_mapToNode
[vID
], c
);
1241 }//recursiveAttributedClusterRead
1243 void GmlParser::readLineAttribute(GmlObject
*object
, DPolyline
&dpl
)
1246 for(; object
; object
= object
->m_pBrother
) {
1247 if (id(object
) == pointPredefKey
&&
1248 object
->m_valueType
== gmlListBegin
)
1252 GmlObject
*pointObject
= object
->m_pFirstSon
;
1253 for (; pointObject
; pointObject
= pointObject
->m_pBrother
) {
1254 if (pointObject
->m_valueType
!= gmlDoubleValue
) continue;
1255 if (id(pointObject
) == xPredefKey
)
1256 dp
.m_x
= pointObject
->m_doubleValue
;
1257 else if (id(pointObject
) == yPredefKey
)
1258 dp
.m_y
= pointObject
->m_doubleValue
;
1267 void GmlParser::setError(const char *errorString
)
1270 m_errorString
= errorString
;
1274 void GmlParser::indent(ostream
&os
, int d
)
1276 for(int i
= 1; i
<= d
; ++i
)
1280 void GmlParser::output(ostream
&os
, GmlObject
*object
, int d
)
1282 for(; object
; object
= object
->m_pBrother
) {
1283 indent(os
,d
); os
<< object
->m_key
->key();
1285 switch(object
->m_valueType
) {
1287 os
<< " " << object
->m_intValue
<< "\n";
1290 case gmlDoubleValue
:
1291 os
<< " " << object
->m_doubleValue
<< "\n";
1294 case gmlStringValue
:
1295 os
<< " \"" << object
->m_stringValue
<< "\"\n";
1300 output(os
, object
->m_pFirstSon
, d
+2);
1315 } // end namespace ogdf