Don't import ogdf namespace
[TortoiseGit.git] / ext / OGDF / src / fileformats / GmlParser.cpp
blob0e5ceb2dae13f29c27fb7e48c30bfcb86fb9e71e
1 /*
2 * $Revision: 2565 $
4 * last checkin:
5 * $Author: gutwenger $
6 * $Date: 2012-07-07 17:14:54 +0200 (Sa, 07. Jul 2012) $
7 ***************************************************************/
9 /** \file
10 * \brief Implementation of GML parser (class GmlParser)
11 * (used for parsing and reading GML files)
13 * \author Carsten Gutwenger
15 * \par License:
16 * This file is part of the Open Graph Drawing Framework (OGDF).
18 * \par
19 * Copyright (C)<br>
20 * See README.txt in the root directory of the OGDF installation for details.
22 * \par
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
27 * for details.
29 * \par
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.
35 * \par
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>
46 #include <ctype.h>
47 #include <string.h>
49 extern ofstream os;
51 namespace ogdf {
53 GmlParser::GmlParser(const char *fileName, bool doCheck)
55 ifstream is(fileName, ios::in); // open file
56 doInit(is,doCheck);
60 GmlParser::GmlParser(istream &is, bool doCheck)
62 doInit(is,doCheck);
66 void GmlParser::doInit(istream &is, bool doCheck)
68 m_objectTree = 0;
70 if (!is) {
71 setError("Cannot open file.");
72 return;
75 createObjectTree(is,doCheck);
77 int minId, maxId;
78 m_graphObject = getNodeIdRange(minId, maxId);
79 m_mapToNode.init(minId,maxId,0);
83 void GmlParser::createObjectTree(istream &is, bool doCheck)
85 initPredefinedKeys();
86 m_error = false;
88 m_is = &is;
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;
159 for( ; ; ) {
160 GmlObjectType symbol = getNextSymbol();
162 if (symbol == closingKey || symbol == gmlError)
163 return firstSon;
165 if (symbol != gmlKey) {
166 setError("key expected");
167 return firstSon;
170 GmlKey key = m_keySymbol;
172 symbol = getNextSymbol();
173 GmlObject *object = 0;
175 switch (symbol) {
176 case gmlIntValue:
177 object = OGDF_NEW GmlObject(key,m_intSymbol);
178 break;
180 case gmlDoubleValue:
181 object = OGDF_NEW GmlObject(key,m_doubleSymbol);
182 break;
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); }
191 break;
193 case gmlListBegin:
194 object = OGDF_NEW GmlObject(key);
195 object->m_pFirstSon = parseList(gmlListEnd,gmlEOF);
196 break;
198 case gmlListEnd:
199 setError("unexpected end of list");
200 return firstSon;
202 case gmlKey:
203 setError("unexpected key");
204 return firstSon;
206 case gmlEOF:
207 setError("missing value");
208 return firstSon;
210 case gmlError:
211 return firstSon;
213 OGDF_NODEFAULT // one of the cases above has to occur
216 *pPrev = object;
217 pPrev = &object->m_pBrother;
220 return firstSon;
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);
236 delete object;
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()
250 do {
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);
254 if (m_is->fail())
255 return false;
256 for(m_pCurrent = m_lineBuffer;
257 *m_pCurrent && isspace(*m_pCurrent); ++m_pCurrent) ;
258 } while (*m_pCurrent == '#' || *m_pCurrent == 0);
260 return true;
264 GmlObjectType GmlParser::getNextSymbol()
266 *m_pStore = m_cStore;
268 // eat whitespace
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!
280 if (*pStart == '\"')
281 { // string
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)) {
290 case 0:
291 *m_pCurrent = 0;
292 break;
293 case '\\':
294 *pWrite++ = '\\';
295 m_pCurrent += 2;
296 break;
297 case '\"':
298 *pWrite++ = '\"';
299 m_pCurrent += 2;
300 break;
301 default:
302 // just copy the escape sequence as is
303 *pWrite++ = *m_pCurrent++;
304 *pWrite++ = *m_pCurrent++;
307 } else
308 *pWrite++ = *m_pCurrent++;
311 if (*m_pCurrent == 0)
313 *pWrite = 0;
314 m_longString = (pStart+1);
315 while(getLine())
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)) {
324 case 0:
325 *m_pCurrent = 0;
326 break;
327 case '\\':
328 *pWrite++ = '\\';
329 m_pCurrent += 2;
330 break;
331 case '\"':
332 *pWrite++ = '\"';
333 m_pCurrent += 2;
334 break;
335 default:
336 // just copy the escape sequence as is
337 *pWrite++ = *m_pCurrent++;
338 *pWrite++ = *m_pCurrent++;
341 } else
342 *pWrite++ = *m_pCurrent++;
345 if (*m_pCurrent == 0) {
346 *pWrite = 0;
347 m_longString += m_lineBuffer;
349 } else {
350 m_cStore = *(m_pStore = m_pCurrent);
351 ++m_pCurrent;
352 *pWrite = 0;
353 m_longString += m_lineBuffer;
354 break;
357 m_stringSymbol = m_longString.cstr();
359 } else {
360 m_cStore = *(m_pStore = m_pCurrent);
361 ++m_pCurrent;
362 *pWrite = 0;
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);
372 *m_pCurrent = 0;
374 if(isalpha(*pStart)) { // key
376 // check if really a correct key (error if not)
377 if (m_doCheck) {
378 for (char *p = pStart+1; *p; ++p)
379 if (!(isalpha(*p) || isdigit(*p))) {
380 setError("malformed key");
381 return gmlError;
385 m_keySymbol = hashString(pStart);
386 return gmlKey;
388 } else if (*pStart == '[') {
389 return gmlListBegin;
391 } else if (*pStart == ']') {
392 return gmlListEnd;
394 } else if (*pStart == '-' || isdigit(*pStart)) { // int or double
395 char *p = pStart+1;
396 while(isdigit(*p)) ++p;
398 if (*p == '.') { // double
399 // check to be done
401 sscanf(pStart,"%lf",&m_doubleSymbol);
402 return gmlDoubleValue;
404 } else { // int
405 if (*p != 0) {
406 setError("malformed number");
407 return gmlError;
410 sscanf(pStart,"%d",&m_intSymbol);
411 return gmlIntValue;
415 setError("unknown symbol");
417 return gmlError;
421 GmlKey GmlParser::hashString(const String &str)
423 GmlKey key = m_hashTable.insertByNeed(str,-1);
424 if(key->info() == -1) key->info() = m_num++;
426 return key;
430 GmlObject *GmlParser::getNodeIdRange(int &minId,int &maxId)
432 minId = maxId = 0;
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;
440 bool first = true;
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;
451 if (first) {
452 minId = maxId = nodeSonId;
453 first = false;
454 } else {
455 if (nodeSonId < minId) minId = nodeSonId;
456 if (nodeSonId > maxId) maxId = nodeSonId;
463 return graphObject;
467 bool GmlParser::read(Graph &G)
469 G.clear();
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)
478 switch(id(son))
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");
499 return false;
502 // create new node if necessary
503 if (m_mapToNode[vId] == 0) m_mapToNode[vId] = G.newNode(); }
504 break;
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;
520 break;
522 case targetPredefKey:
523 if (edgeSon->m_valueType != gmlIntValue) break;
524 targetId = edgeSon->m_intValue;
525 break;
529 // check if everything required is defined correctly
530 if (sourceId == notDefined || targetId == notDefined) {
531 setError("source or target id not defined");
532 return false;
534 } else if (sourceId < minId || maxId < sourceId ||
535 targetId < minId || maxId < targetId) {
536 setError("source or target id out of range");
537 return false;
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]);
545 }//case edge
546 break;
547 }//switch
548 }//for sons
550 return true;
554 bool GmlParser::read(Graph &G, GraphAttributes &AG)
556 OGDF_ASSERT(&G == &(AG.constGraph()))
558 G.clear();
560 int minId = m_mapToNode.low();
561 int maxId = m_mapToNode.high();
562 int notDefined = minId-1; //indicates not defined id key
564 DPolyline bends;
566 GmlObject *son = m_graphObject->m_pFirstSon;
567 for(; son; son = son->m_pBrother) {
569 switch(id(son)) {
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;
576 String label;
577 String templ;
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)) {
589 case idPredefKey:
590 if(nodeSon->m_valueType != gmlIntValue) break;
591 vId = nodeSon->m_intValue;
592 break;
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)) {
602 case xPredefKey:
603 if(graphicsObject->m_valueType != gmlDoubleValue) break;
604 x = graphicsObject->m_doubleValue;
605 break;
607 case yPredefKey:
608 if(graphicsObject->m_valueType != gmlDoubleValue) break;
609 y = graphicsObject->m_doubleValue;
610 break;
612 case wPredefKey:
613 if(graphicsObject->m_valueType != gmlDoubleValue) break;
614 w = graphicsObject->m_doubleValue;
615 break;
617 case hPredefKey:
618 if(graphicsObject->m_valueType != gmlDoubleValue) break;
619 h = graphicsObject->m_doubleValue;
620 break;
622 case fillPredefKey:
623 if(graphicsObject->m_valueType != gmlStringValue) break;
624 fill = graphicsObject->m_stringValue;
625 break;
627 case linePredefKey:
628 if(graphicsObject->m_valueType != gmlStringValue) break;
629 line = graphicsObject->m_stringValue;
630 break;
632 case lineWidthPredefKey:
633 if(graphicsObject->m_valueType != gmlDoubleValue) break;
634 lineWidth = graphicsObject->m_doubleValue;
635 break;
637 case typePredefKey:
638 if(graphicsObject->m_valueType != gmlStringValue) break;
639 shape = graphicsObject->m_stringValue;
640 break;
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;
649 break; }
651 case templatePredefKey:
652 if (nodeSon->m_valueType != gmlStringValue) break;
654 templ = nodeSon->m_stringValue;
655 break;
657 case labelPredefKey:
658 if (nodeSon->m_valueType != gmlStringValue) break;
660 label = nodeSon->m_stringValue;
661 break;
665 // check if everything required is defined correctly
666 if (vId == notDefined) {
667 setError("node id not defined");
668 return false;
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;
679 if (shape == "oval")
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]) =
702 lineWidth;
704 }//node
705 //Todo: line style set stipple value
706 break;
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;
731 break;
733 case targetPredefKey:
734 if (edgeSon->m_valueType != gmlIntValue) break;
735 targetId = edgeSon->m_intValue;
736 break;
738 case subGraphPredefKey:
739 if (edgeSon->m_valueType != gmlIntValue) break;
740 subGraph = edgeSon->m_intValue;
741 break;
743 case labelPredefKey:
744 if (edgeSon->m_valueType != gmlStringValue) break;
745 label = edgeSon->m_stringValue;
746 break;
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;
775 }//for graphics
778 case generalizationPredefKey:
779 if (edgeSon->m_valueType != gmlIntValue) break;
780 umlType = (edgeSon->m_intValue == 0) ?
781 Graph::association : Graph::generalization;
782 break;
787 // check if everything required is defined correctly
788 if (sourceId == notDefined || targetId == notDefined) {
789 setError("source or target id not defined");
790 return false;
792 } else if (sourceId < minId || maxId < sourceId ||
793 targetId < minId || maxId < targetId) {
794 setError("source or target id out of range");
795 return false;
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) {
813 if (arrow == "none")
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;
821 else
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;
837 break; }
838 case directedPredefKey: {
839 if(son->m_valueType != gmlIntValue) break;
840 AG.directed(son->m_intValue > 0);
841 break; }
845 return true;
846 }//read
849 //to be called AFTER calling read(G, AG)
850 bool GmlParser::readAttributedCluster(
851 Graph &G,
852 ClusterGraph& CG,
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;
863 if(rootObject == 0)
864 return true;
866 if (id(rootObject) != rootClusterPredefKey)
868 setError("missing rootcluster key");
869 return false;
872 if (rootObject->m_valueType != gmlListBegin) return false;
874 attributedClusterRead(rootObject, CG, ACG);
876 return true;
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");
897 return false;
900 if (rootObject->m_valueType != gmlListBegin) return false;
902 clusterRead(rootObject, CG);
904 return true;
905 }//read clustergraph
908 //read all cluster tree information
909 bool GmlParser::clusterRead(
910 GmlObject* rootCluster,
911 ClusterGraph& CG)
914 //the root cluster is only allowed to hold child clusters and
915 //nodes in a list
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);
937 } //case cluster
938 break;
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++)
961 // vIDChar
963 }//case vertex
964 }//switch
965 }//for all rootcluster sons
967 return true;
969 }//clusterread
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,
977 ClusterGraph& CG,
978 ClusterGraphAttributes& ACG)
981 //the root cluster is only allowed to hold child clusters and
982 //nodes in a list
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);
1004 } //case cluster
1005 break;
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++)
1029 // vIDChar
1031 }//case vertex
1032 }//switch
1033 }//for all rootcluster sons
1035 return true;
1037 }//attributedclusterread
1040 bool GmlParser::readClusterAttributes(
1041 GmlObject* cGraphics,
1042 cluster c,
1043 ClusterGraphAttributes& ACG)
1045 String label;
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))
1058 case xPredefKey:
1059 if(graphicsObject->m_valueType != gmlDoubleValue) return false;
1060 ACG.clusterXPos(c) = graphicsObject->m_doubleValue;
1061 break;
1063 case yPredefKey:
1064 if(graphicsObject->m_valueType != gmlDoubleValue) return false;
1065 ACG.clusterYPos(c) = graphicsObject->m_doubleValue;
1066 break;
1068 case widthPredefKey:
1069 if(graphicsObject->m_valueType != gmlDoubleValue) return false;
1070 ACG.clusterWidth(c) = graphicsObject->m_doubleValue;
1071 break;
1073 case heightPredefKey:
1074 if(graphicsObject->m_valueType != gmlDoubleValue) return false;
1075 ACG.clusterHeight(c) = graphicsObject->m_doubleValue;
1076 break;
1077 case fillPredefKey:
1078 if(graphicsObject->m_valueType != gmlStringValue) return false;
1079 ACG.clusterFillColor(c) = graphicsObject->m_stringValue;
1080 break;
1081 case patternPredefKey:
1082 if(graphicsObject->m_valueType != gmlIntValue) return false;
1083 pattern = graphicsObject->m_intValue;
1084 break;
1085 //line style
1086 case colorPredefKey: // line color
1087 if(graphicsObject->m_valueType != gmlStringValue) return false;
1088 ACG.clusterColor(c) = graphicsObject->m_stringValue;
1089 break;
1091 case stipplePredefKey:
1092 if(graphicsObject->m_valueType != gmlIntValue) return false;
1093 stipple = graphicsObject->m_intValue;
1094 break;
1095 case lineWidthPredefKey:
1096 if(graphicsObject->m_valueType != gmlDoubleValue) return false;
1097 lineWidth =
1098 graphicsObject->m_doubleValue;
1099 break;
1100 //TODO: backgroundcolor
1101 //case stylePredefKey:
1102 //case boderwidthPredefKey:
1103 }//switch
1104 }//for
1106 //Hier eigentlich erst abfragen, ob clusterattributes setzbar in ACG,
1107 //dann setzen
1108 ACG.clusterLineStyle(c) = GraphAttributes::intToStyle(stipple); //defaulting 1
1109 ACG.clusterLineWidth(c) = lineWidth;
1110 ACG.clusterFillPattern(c) = GraphAttributes::intToPattern(pattern);
1112 return true;
1113 }//readclusterattributes
1115 //recursively read cluster subtree information
1116 bool GmlParser::recursiveClusterRead(GmlObject* clusterObject,
1117 ClusterGraph& CG,
1118 cluster c)
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
1129 //id and sons
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);
1140 break;
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++)
1162 // vIDChar
1164 }//case vertex
1165 }//switch
1166 }//for clustersons
1168 return true;
1170 }//recursiveclusterread
1172 //recursively read cluster subtree information
1173 bool GmlParser::recursiveAttributedClusterRead(GmlObject* clusterObject,
1174 ClusterGraph& CG,
1175 ClusterGraphAttributes& ACG,
1176 cluster c)
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
1187 //id and sons
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);
1198 break;
1199 case labelPredefKey:
1201 if (clusterSon->m_valueType != gmlStringValue) return false;
1202 ACG.clusterLabel(c) = clusterSon->m_stringValue;
1204 break;
1205 case templatePredefKey:
1207 if (clusterSon->m_valueType != gmlStringValue) return false;
1208 ACG.templateCluster(c) = clusterSon->m_stringValue;
1209 break;
1211 case graphicsPredefKey: //read the info for cluster c
1213 if (clusterSon->m_valueType != gmlListBegin) return false;
1215 readClusterAttributes(clusterSon, c , ACG);
1216 }//graphics
1217 break;
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);
1236 }//case vertex
1237 }//switch
1238 }//for clustersons
1240 return true;
1241 }//recursiveAttributedClusterRead
1243 void GmlParser::readLineAttribute(GmlObject *object, DPolyline &dpl)
1245 dpl.clear();
1246 for(; object; object = object->m_pBrother) {
1247 if (id(object) == pointPredefKey &&
1248 object->m_valueType == gmlListBegin)
1250 DPoint dp;
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;
1261 dpl.pushBack(dp);
1267 void GmlParser::setError(const char *errorString)
1269 m_error = true;
1270 m_errorString = errorString;
1274 void GmlParser::indent(ostream &os, int d)
1276 for(int i = 1; i <= d; ++i)
1277 os << " ";
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) {
1286 case gmlIntValue:
1287 os << " " << object->m_intValue << "\n";
1288 break;
1290 case gmlDoubleValue:
1291 os << " " << object->m_doubleValue << "\n";
1292 break;
1294 case gmlStringValue:
1295 os << " \"" << object->m_stringValue << "\"\n";
1296 break;
1298 case gmlListBegin:
1299 os << "\n";
1300 output(os, object->m_pFirstSon, d+2);
1301 break;
1302 case gmlListEnd:
1303 break;
1304 case gmlKey:
1305 break;
1306 case gmlEOF:
1307 break;
1308 case gmlError:
1309 break;
1315 } // end namespace ogdf