/* * $Revision: 2565 $ * * last checkin: * $Author: gutwenger $ * $Date: 2012-07-07 17:14:54 +0200 (Sa, 07. Jul 2012) $ ***************************************************************/ /** \file * \brief Implementation of OGML parser. * * \author Christian Wolf and Bernd Zey * * \par License: * This file is part of the Open Graph Drawing Framework (OGDF). * * \par * Copyright (C)
* See README.txt in the root directory of the OGDF installation for details. * * \par * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * Version 2 or 3 as published by the Free Software Foundation; * see the file LICENSE.txt included in the packaging of this file * for details. * * \par * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * \par * You should have received a copy of the GNU General Public * License along with this program; if not, write to the Free * Software Foundation, Inc., 51 Franklin Street, Fifth Floor, * Boston, MA 02110-1301, USA. * * \see http://www.gnu.org/copyleft/gpl.html ***************************************************************/ #include "OgmlParser.h" #include "Ogml.h" namespace ogdf { //--------------------------------------------------------- // OgmlParser::OgmlNodeTemplate //--------------------------------------------------------- // struct definitions for mapping of templates struct OgmlParser::OgmlNodeTemplate { String m_id; int m_shapeType; double m_width; double m_height; String m_color; GraphAttributes::BrushPattern m_pattern; String m_patternColor; GraphAttributes::EdgeStyle m_lineType; double m_lineWidth; String m_lineColor; // nodeTemplate stores the graphical type // e.g. rectangle, ellipse, hexagon, ... String m_nodeTemplate; //Constructor: OgmlNodeTemplate(const String &id): m_id(id) { } }; //--------------------------------------------------------- // OgmlParser::OgmlEdgeTemplate //--------------------------------------------------------- struct OgmlParser::OgmlEdgeTemplate { String m_id; GraphAttributes::EdgeStyle m_lineType; double m_lineWidth; String m_color; int m_sourceType; // actually this is only a boolean value 0 or 1 // ogdf doesn't support source-arrow-color and size // String m_sourceColor; // double m_sourceSize; int m_targetType; // actually this is only a boolean value 0 or 1 // ogdf doesn't support target-arrow-color and size // String m_targetColor; // double m_targetSize; //Constructor: OgmlEdgeTemplate(const String &id): m_id(id) { } }; // struct OgmlParser::OgmlLabelTemplate{ // String m_id; // }; //--------------------------------------------------------- // OgmlParser::OgmlSegment //--------------------------------------------------------- struct OgmlParser::OgmlSegment { DPoint point1, point2; }; //--------------------------------------------------------- // OgmlParser::OgmlAttributeValue //--------------------------------------------------------- //! Objects of this class represent a value set of an attribute in Ogml. class OgmlParser::OgmlAttributeValue { int id; //!< Id of the attribute value; for possible ones see Ogml.h. public: // Construction OgmlAttributeValue() : id(Ogml::av_any) { } OgmlAttributeValue(int id) { if(id >= 0 && id < Ogml::ATT_VAL_NUM) this->id = id; else id = Ogml::av_any; } // Destruction ~OgmlAttributeValue() { } // Getter const int& getId() const { return id; } const String& getValue() const { return Ogml::s_attributeValueNames[id]; } // Setter void setId(int id) { if(id >= 0 && id < Ogml::ATT_VAL_NUM) this->id = id; else id = Ogml::av_any; } /** * Checks the type of the input given in string * and returns an OgmlAttributeValueId defined in Ogml.h */ Ogml::AttributeValueId getTypeOfString(const String& input) const { // |--------------------| // | char | ascii-value | // |--------------------| // | '.' | 46 | // | '-' | 45 | // | '+' | 43 | // | '#' | 35 | // bool values bool isInt = true; bool isNum = true; bool isHex = true; // value for point seperator bool numPoint = false; // input is a boolean value if (input == "true" || input == "false" /*|| input == "0" || input == "1"*/) return Ogml::av_bool; if (input.length() > 0){ char actChar = input[0]; int actCharInt = static_cast(actChar); //check the first char if (!isalnum(actChar)){ if (actCharInt == 35){ // support hex values with starting "#" isInt = false; isNum = false; } else { // (actChar != '-') and (actChar != '+') if (!(actCharInt == 45) && !(actChar == 43)){ isInt = isNum = false; } else { // input[0] == '-' or '+' if (input.length() > 1){ // 2nd char have to be a digit or xdigit actChar = input[1]; actCharInt = static_cast(actChar); if (!isdigit(actChar)){ isInt = false; isNum = false; if (!isxdigit(actChar)) return Ogml::av_string; } } else return Ogml::av_string; } // else... (input[0] == '-') } } else{ if (!isdigit(actChar)){ isInt = false; isNum = false; } if (!isxdigit(actChar)){ isHex = false; } } // check every input char // and set bool value to false if char-type is wrong for(size_t it=1; ( (it(actChar); // actChar == '.' if (actChar == 46){ isInt = false; isHex = false; if (!numPoint){ numPoint = true; } else isNum = false; }// if (actChar == '.') else { if (!(isdigit(actChar))){ isInt = false; isNum = false; } if (!(isxdigit(actChar))) isHex = false; }//else... (actChar != '.') }//for }//if (input.length() > 0) else{ // input.length() == 0 return Ogml::av_none; } // return correct value if (isInt) return Ogml::av_int; if (isNum) return Ogml::av_num; if (isHex) return Ogml::av_hex; // if all bool values are false return av_string return Ogml::av_string; }//getTypeOfString /** * According to id this method proofs whether s is a valid value * of the value set. * E.g. if id=av_int s should contain an integer value. * It returns the following validity states: * vs_idNotUnique =-10, //id already exhausted * vs_idRefErr = -9, //referenced id wasn't found or wrong type of referenced tag * vs_idRefErr = -8, //referenced id wrong * vs_attValueErr = -3, //attribute-value error * Ogml::vs_valid = 1 //attribute-value is valid * * TODO: Completion of the switch-case statement. */ int validValue( const String &attributeValue, const XmlTagObject* xmlTag, //owns an attribute with attributeValue Hashing& ids) const //hashtable with id-tagName pairs { //get attribute value type of string Ogml::AttributeValueId stringType = getTypeOfString(attributeValue); HashElement* he; int valid = Ogml::vs_attValueErr; switch(id) { case Ogml::av_any: valid = Ogml::vs_valid; break; case Ogml::av_int: if (stringType == Ogml::av_int) valid = Ogml::vs_valid; break; case Ogml::av_num: if (stringType == Ogml::av_num) valid = Ogml::vs_valid; if (stringType == Ogml::av_int) valid = Ogml::vs_valid; break; case Ogml::av_bool: if (stringType == Ogml::av_bool) valid = Ogml::vs_valid; break; case Ogml::av_string: valid = Ogml::vs_valid; break; case Ogml::av_hex: if (stringType == Ogml::av_hex) valid = Ogml::vs_valid; if (stringType == Ogml::av_int) valid = Ogml::vs_valid; break; case Ogml::av_oct: valid = Ogml::vs_attValueErr; break; case Ogml::av_id: // id mustn't exist if( !(he = ids.lookup(attributeValue)) ) { ids.fastInsert(attributeValue, xmlTag); valid = Ogml::vs_valid; } else valid = Ogml::vs_idNotUnique; break; // attribute idRef of elements source, target, nodeRef, nodeStyle case Ogml::av_nodeIdRef: // element exists && is tagname expected if( (he = ids.lookup(attributeValue)) && (he->info()->getName() == Ogml::s_tagNames[Ogml::t_node]) ) valid = Ogml::vs_valid; else valid = Ogml::vs_idRefErr; break; // attribute idRef of elements edgeRef, edgeStyle case Ogml::av_edgeIdRef: // element exists && is tagname expected if( (he = ids.lookup(attributeValue)) && (he->info()->getName() == Ogml::s_tagNames[Ogml::t_edge]) ) valid = Ogml::vs_valid; else valid = Ogml::vs_idRefErr; break; // attribute idRef of elements labelRef, labelStyle case Ogml::av_labelIdRef: // element exists && is tagname expected if( (he = ids.lookup(attributeValue)) && (he->info()->getName() == Ogml::s_tagNames[Ogml::t_label]) ) valid = Ogml::vs_valid; else valid = Ogml::vs_idRefErr; break; // attribute idRef of element endpoint case Ogml::av_sourceIdRef: // element exists && is tagname expected if( (he = ids.lookup(attributeValue)) && (he->info()->getName() == Ogml::s_tagNames[Ogml::t_source]) ) valid = Ogml::vs_valid; else valid = Ogml::vs_idRefErr; break; // attribute idRef of element endpoint case Ogml::av_targetIdRef: // element exists && is tagname expected if( (he = ids.lookup(attributeValue)) && (he->info()->getName() == Ogml::s_tagNames[Ogml::t_target]) ) valid = Ogml::vs_valid; else valid = Ogml::vs_idRefErr; break; // attribute idRef of subelement template of element nodeStyle case Ogml::av_nodeStyleTemplateIdRef: // element exists && is tagname expected if( (he = ids.lookup(attributeValue)) && (he->info()->getName() == Ogml::s_tagNames[Ogml::t_nodeStyleTemplate]) ) valid = Ogml::vs_valid; else valid = Ogml::vs_idRefErr; break; // attribute idRef of subelement template of element edgeStyle case Ogml::av_edgeStyleTemplateIdRef: // element exists && is tagname expected if( (he = ids.lookup(attributeValue)) && (he->info()->getName() == Ogml::s_tagNames[Ogml::t_edgeStyleTemplate]) ) valid = Ogml::vs_valid; else valid = Ogml::vs_idRefErr; break; // attribute idRef of subelement template of element labelStyle case Ogml::av_labelStyleTemplateIdRef: // element exists && is tagname expected if( (he = ids.lookup(attributeValue)) && (he->info()->getName() == Ogml::s_tagNames[Ogml::t_labelStyleTemplate]) ) valid = Ogml::vs_valid; else valid = Ogml::vs_idRefErr; break; case Ogml::av_pointIdRef: // element exists && is tagname expected if( (he = ids.lookup(attributeValue)) && (he->info()->getName() == Ogml::s_tagNames[Ogml::t_point]) ) valid = Ogml::vs_valid; else valid = Ogml::vs_idRefErr; break; default: // Proof string for equality if(getValue() == attributeValue) valid = Ogml::vs_valid; break; } return valid; } };//class OgmlAttributeValue //--------------------------------------------------------- // OgmlParser::OgmlAttribute //--------------------------------------------------------- /** Objects of this class represent an attribute and its value set in Ogml. */ class OgmlParser::OgmlAttribute { /** */ int id; //!< Integer identifier of object; for possible ids see Ogml.h. List values; //!< Represents the value set of this attribute. public: // Construction OgmlAttribute() : id(Ogml::a_none), values() { } OgmlAttribute(int id) : values() { if(id >= 0 && id < Ogml::ATT_NUM) this->id = id; else this->id = Ogml::a_none; } // Destruction ~OgmlAttribute() { } // Getter const int& getId() const { return id; } const String& getName() const { return Ogml::s_attributeNames[id]; } const List& getValueList() const { return values; } // Setter void setId(int id) { if(id >= 0 && id < Ogml::ATT_NUM) this->id = id; else this->id = Ogml::a_none; } /** * Pushes pointers to OgmlAttributeValue objects back to list values. * These value objects are looked up in hashtable values. * * NOTE: This method uses a variable parameter list. The last parameter * need to be -1! */ void pushValues(Hashing *val, int key, ...) { va_list argp; int arg = key; HashElement* he; va_start(argp, key); while(arg!=-1) { if((he = val->lookup(arg))) values.pushBack( &(he->info()) ); arg = va_arg(argp,int); } va_end(argp); } // Prints the value set of the attribute. void print(ostream &os) const { ListConstIterator it; os << "\"" << getName() << "\"={ "; for(it = values.begin(); it.valid(); it++) { os << (**it).getValue() << " "; } os << "}\n"; } /**This method proofs whether o is a valid attribute in comparison * to this object. * That means if the name of o and this object are equal and if * o has a valid value. * It returns a validity state code (see Ogml.h). **/ int validAttribute(const XmlAttributeObject &xmlAttribute, const XmlTagObject* xmlTag, Hashing& ids) const { int valid = Ogml::vs_expAttNotFound; if( xmlAttribute.getName() == getName() ) { ListConstIterator it; for(it = values.begin(); it.valid(); it++) { if ( (valid = (**it).validValue( xmlAttribute.getValue(), xmlTag, ids )) == Ogml::vs_valid ) break; } } return valid; } };//class OgmlAttribute //--------------------------------------------------------- // OgmlParser::OgmlTag //--------------------------------------------------------- /**Objects of this class represent a tag in Ogml with attributes. */ class OgmlParser::OgmlTag { int id; //!< Integer identifier of object; for possible ids see Ogml.h. int minOccurs, maxOccurs; // Min. occurs and max. occurs of this tag. /** * Flag denotes whether tag content can be ignored. * It is possible to exchange this flag by a list of contents for more * complex purposes ;-) */ bool ignoreContent; List compulsiveAttributes; //!< Represents the compulsive attributes of this object. List choiceAttributes; //!< Represents the attributes of this object of which at least one needs to exist. List optionalAttributes; //!< Represents the optional attributes of this object. List compulsiveTags; List choiceTags; List optionalTags; void printOwnedTags(ostream &os, int mode) const { String s; const List *list = 0; switch(mode) { case 0: list = &compulsiveTags; s += "compulsive"; break; case 1: list = &choiceTags; s += "selectable"; break; case 2: list = &optionalTags; s += "optional"; break; } if(list->empty()) os << "Tag \"<" << getName() <<">\" doesn't include " << s << " tag(s).\n"; else { os << "Tag \"<" << getName() <<">\" includes the following " << s << " tag(s): \n"; ListConstIterator currTag; for(currTag = list->begin(); currTag.valid(); currTag++) os << "\t<" << (**currTag).getName() << ">\n"; } } void printOwnedAttributes(ostream &os, int mode) const { String s; const List *list = 0; switch(mode) case 0: { list = &compulsiveAttributes; s += "compulsive"; break; case 1: list = &choiceAttributes; s += "selectable"; break; case 2: list = &optionalAttributes; s += "optional"; break; } if(list->empty()) os << "Tag \"<" << getName() <<">\" doesn't include " << s << " attribute(s).\n"; else { cout << "Tag \"<" << getName() <<">\" includes the following " << s << " attribute(s): \n"; ListConstIterator currAtt; for(currAtt = list->begin(); currAtt.valid(); currAtt++) os << "\t" << (**currAtt); } } public: bool ownsCompulsiveTags() { return !compulsiveTags.empty(); } bool ownsChoiceTags() { return !choiceTags.empty(); } bool ownsOptionalTags() { return !optionalTags.empty(); } const List& getCompulsiveTags() const { return compulsiveTags; } const List& getChoiceTags() const { return choiceTags; } const List& getOptionalTags() const { return optionalTags; } const int& getMinOccurs() const { return minOccurs; } const int& getMaxOccurs() const { return maxOccurs; } const bool& ignoresContent() const { return ignoreContent; } void setMinOccurs(int occurs) { minOccurs = occurs; } void setMaxOccurs(int occurs) { maxOccurs = occurs; } void setIgnoreContent(bool ignore) { ignoreContent = ignore; } //Construction OgmlTag() : id(Ogml::t_none), ignoreContent(0) { } OgmlTag(int id) : id(Ogml::t_none), ignoreContent(0) { if(id >= 0 && id < Ogml::TAG_NUM) this->id = id; else id = Ogml::a_none; } //Destruction ~OgmlTag() {} //Getter const int& getId() const { return id; } const String& getName() const { return Ogml::s_tagNames[id]; } //Setter void setId(int id){ if(id >= 0 && id < Ogml::TAG_NUM) this->id = id; else id = Ogml::a_none; } void printOwnedTags(ostream& os) const { printOwnedTags(os, 0); printOwnedTags(os, 1); printOwnedTags(os, 2); } void printOwnedAttributes(ostream& os) const { printOwnedAttributes(os, 0); printOwnedAttributes(os, 1); printOwnedAttributes(os, 2); } /**Pushes pointers to OgmlAttribute objects back to list reqAttributes. * These value objects are looked up in hashtable attrib. * * NOTE: This method uses a variable parameter list. The last parameter * need to be -1! */ void pushAttributes(int mode, Hashing *attrib, int key, ...) { List* list; if(mode==0) list = &compulsiveAttributes; else if(mode==1) list = &choiceAttributes; else list = &optionalAttributes; va_list argp; int arg = key; HashElement* he; va_start(argp, key); while(arg!=-1) { if((he = attrib->lookup(arg))) (*list).pushBack( &(he->info()) ); arg = va_arg(argp,int); } va_end(argp); } /**Pushes pointers to OgmlAttribute objects back to list reqAttributes. * These value objects are looked up in hashtable tag. * * NOTE: This method uses a variable parameter list. The last parameter * need to be -1! */ void pushTags(int mode, Hashing *tag, int key, ...) { List* list; if(mode==0) list = &compulsiveTags; else if(mode==1) list = &choiceTags; else list = &optionalTags; va_list argp; int arg = key; HashElement* he; va_start(argp, key); while(arg!=-1) { if((he = tag->lookup(arg))) (*list).pushBack( &(he->info()) ); arg = va_arg(argp,int); } va_end(argp); } /**This method proofs whether o is a valid tag in comparison * to this object. * That means if the name of o and this object are equal and if * the attribute list of o is valid (see also validAttribute(...) * in OgmlAttribute.h). Otherwise false. */ int validTag(const XmlTagObject &o, Hashing& ids) const { int valid = Ogml::vs_unexpTag; if( o.getName() == getName() ) { ListConstIterator it; XmlAttributeObject* att; //Tag requires attributes if(!compulsiveAttributes.empty()) { for(it = compulsiveAttributes.begin(); it.valid(); it++) { //Att not found or invalid if(!o.findXmlAttributeObjectByName((**it).getName(), att) ) return valid = Ogml::vs_expAttNotFound; if( (valid = (**it).validAttribute(*att, &o, ids) ) <0 ) return valid; //Att is valid att->setValid(); } } //Choice attributes if(!choiceAttributes.empty()) { bool tookChoice = false; for(it = choiceAttributes.begin(); it.valid(); it++) { //Choice att found if( o.findXmlAttributeObjectByName((**it).getName(), att) ) { //Proof if valid if( (valid = (**it).validAttribute(*att, &o, ids)) <0 ) return valid; tookChoice = true; att->setValid(); } } if(!tookChoice) return valid = Ogml::vs_expAttNotFound; } if(!optionalAttributes.empty() && !o.isAttributeLess()) { //Check optional attributes for(it = optionalAttributes.begin(); it.valid(); it++) { if( o.findXmlAttributeObjectByName((**it).getName(), att) ) { if( (valid = (**it).validAttribute(*att, &o, ids)) <0 ) return valid; att->setValid(); } } } //Are there still invalid attributes? att = o.m_pFirstAttribute; while(att) { if(!att->valid()) return valid = Ogml::vs_unexpAtt; att = att->m_pNextAttribute; } valid = Ogml::vs_valid; } return valid; } };//class OgmlTag //--------------------------------------------------------- // OgmlParser //--------------------------------------------------------- // Definition of Hashtables Hashing < int, OgmlParser::OgmlTag > *OgmlParser::s_tags = 0; Hashing < int, OgmlParser::OgmlAttribute > *OgmlParser::s_attributes = 0; Hashing < int, OgmlParser::OgmlAttributeValue > *OgmlParser::s_attValues = 0; // *********************************************************** // // b u i l d H a s h T a b l e s // // *********************************************************** void OgmlParser::buildHashTables() { if(s_tags != 0) // hash tables already built? return; s_tags = new Hashing < int, OgmlParser::OgmlTag >; s_attributes = new Hashing < int, OgmlParser::OgmlAttribute >; s_attValues = new Hashing < int, OgmlParser::OgmlAttributeValue >; // Create OgmlAttributeValue objects and fill hashtable s_attValues. for (int i = 0; i < Ogml::ATT_VAL_NUM; i++) s_attValues->fastInsert(i, OgmlAttributeValue(i)); for (int i = 0; i < Ogml::ATT_NUM; i++) s_attributes->fastInsert(i, OgmlAttribute(i)); // Create OgmlAttribute objects and fill hashtable attributes. for (int i = 0; i < Ogml::ATT_NUM; i++) { OgmlAttribute &att = s_attributes->lookup(i)->info(); switch (i) { case Ogml::a_alignment: att.pushValues(s_attValues, Ogml::av_left, Ogml::av_center, Ogml::av_right, Ogml::av_justify, -1); break; case Ogml::a_angle: att.pushValues(s_attValues, Ogml::av_int, -1); break; case Ogml::a_color: att.pushValues(s_attValues, Ogml::av_hex, -1); break; case Ogml::a_decoration: att.pushValues(s_attValues, Ogml::av_underline, Ogml::av_overline, Ogml::av_lineThrough, Ogml::av_blink, Ogml::av_none, -1); break; case Ogml::a_defaultEdgeTemplate: att.pushValues(s_attValues, Ogml::av_any, -1); break; case Ogml::a_defaultLabelTemplate: att.pushValues(s_attValues, Ogml::av_any, -1); break; case Ogml::a_defaultNodeTemplate: att.pushValues(s_attValues, Ogml::av_any, -1); break; case Ogml::a_family: att.pushValues(s_attValues, Ogml::av_serif, Ogml::av_sansSerif, Ogml::av_cursive, Ogml::av_fantasy, Ogml::av_monospace, -1); break; case Ogml::a_height: att.pushValues(s_attValues, Ogml::av_num, -1); break; case Ogml::a_id: att.pushValues(s_attValues, Ogml::av_id, -1); break; case Ogml::a_nodeIdRef: att.pushValues(s_attValues, Ogml::av_nodeIdRef, -1); break; case Ogml::a_edgeIdRef: att.pushValues(s_attValues, Ogml::av_edgeIdRef, -1); break; case Ogml::a_labelIdRef: att.pushValues(s_attValues, Ogml::av_labelIdRef, -1); break; case Ogml::a_sourceIdRef: att.pushValues(s_attValues, Ogml::av_nodeIdRef, Ogml::av_edgeIdRef, -1); break; case Ogml::a_targetIdRef: att.pushValues(s_attValues, Ogml::av_nodeIdRef, Ogml::av_edgeIdRef, -1); break; case Ogml::a_nodeStyleTemplateIdRef: att.pushValues(s_attValues, Ogml::av_nodeStyleTemplateIdRef, -1); break; case Ogml::a_edgeStyleTemplateIdRef: att.pushValues(s_attValues, Ogml::av_edgeStyleTemplateIdRef, -1); break; case Ogml::a_labelStyleTemplateIdRef: att.pushValues(s_attValues, Ogml::av_labelStyleTemplateIdRef, -1); break; case Ogml::a_endpointIdRef: att.pushValues(s_attValues, Ogml::av_pointIdRef, Ogml::av_sourceIdRef, Ogml::av_targetIdRef, -1); break; case Ogml::a_name: att.pushValues(s_attValues, Ogml::av_any, -1); break; // attribute type of subelement line of tag nodeStyleTemplate case Ogml::a_nLineType: att.pushValues(s_attValues, Ogml::av_solid, Ogml::av_dotted, Ogml::av_dashed, Ogml::av_double, Ogml::av_triple, Ogml::av_groove, Ogml::av_ridge, Ogml::av_inset, Ogml::av_outset, Ogml::av_none, Ogml::av_esNoPen, Ogml::av_esSolid, Ogml::av_esDash, Ogml::av_esDot, Ogml::av_esDashdot, Ogml::av_esDashdotdot, -1); break; // attribute type of subelement shape of tag nodeStyleTemplate case Ogml::a_nShapeType: att.pushValues(s_attValues, Ogml::av_rect, Ogml::av_rectSimple, Ogml::av_triangle, Ogml::av_circle, Ogml::av_ellipse, Ogml::av_hexagon, Ogml::av_rhomb, Ogml::av_trapeze, Ogml::av_upTrapeze, Ogml::av_lParallelogram, Ogml::av_rParallelogram, Ogml::av_pentagon, Ogml::av_octagon, Ogml::av_umlClass, Ogml::av_image, -1); break; case Ogml::a_pattern: att.pushValues(s_attValues, Ogml::av_solid, Ogml::av_striped, Ogml::av_checked, Ogml::av_dotted, Ogml::av_none, Ogml::av_bpNone, Ogml::av_bpSolid, Ogml::av_bpDense1, Ogml::av_bpDense2, Ogml::av_bpDense3, Ogml::av_bpDense4, Ogml::av_bpDense5, Ogml::av_bpDense6, Ogml::av_bpDense7, Ogml::av_bpHorizontal, Ogml::av_bpVertical, Ogml::av_bpCross, Ogml::av_bpBackwardDiagonal, Ogml::av_bpForwardDiagonal, Ogml::av_bpDiagonalCross, -1); break; case Ogml::a_patternColor: att.pushValues(s_attValues, Ogml::av_hex, -1); break; case Ogml::a_rotation: att.pushValues(s_attValues, Ogml::av_int, -1); break; case Ogml::a_size: att.pushValues(s_attValues, Ogml::av_int, -1); break; case Ogml::a_stretch: att.pushValues(s_attValues, Ogml::av_normal, Ogml::av_wider, Ogml::av_narrower, Ogml::av_ultraCondensed, Ogml::av_extraCondensed, Ogml::av_condensed, Ogml::av_semiCondensed, Ogml::av_semiExpanded, Ogml::av_expanded, Ogml::av_extraExpanded, Ogml::av_ultraExpanded, -1); break; case Ogml::a_style: att.pushValues(s_attValues, Ogml::av_normal, Ogml::av_italic, Ogml::av_oblique, -1); break; case Ogml::a_transform: att.pushValues(s_attValues, Ogml::av_capitalize, Ogml::av_uppercase, Ogml::av_lowercase, Ogml::av_none, -1); break; // attribute type of subelements source-/targetStyle of tag edgeStyleTemplate case Ogml::a_type: att.pushValues(s_attValues, Ogml::av_circle, Ogml::av_halfCircle, Ogml::av_filledCircle, Ogml::av_filledHalfCircle, Ogml::av_box, Ogml::av_halfBox, Ogml::av_filledBox, Ogml::av_filledHalfBox, Ogml::av_rhomb, Ogml::av_halfRhomb, Ogml::av_filledRhomb, Ogml::av_filledHalfRhomb, Ogml::av_diamond, Ogml::av_halfDiamond, Ogml::av_filledDiamond, Ogml::av_filledHalfDiamond, Ogml::av_smurf, Ogml::av_arrow, Ogml::av_slash, Ogml::av_doubleSlash, Ogml::av_solid, Ogml::av_line, Ogml::av_none, -1); break; case Ogml::a_uri: att.pushValues(s_attValues, Ogml::av_uri, -1); break; case Ogml::a_intValue: att.pushValues(s_attValues, Ogml::av_int, -1); break; case Ogml::a_numValue: att.pushValues(s_attValues, Ogml::av_num, -1); break; case Ogml::a_boolValue: att.pushValues(s_attValues, Ogml::av_bool, -1); break; case Ogml::a_variant: att.pushValues(s_attValues, Ogml::av_normal, Ogml::av_smallCaps, -1); break; case Ogml::a_weight: att.pushValues(s_attValues, Ogml::av_normal, Ogml::av_bold, Ogml::av_bolder, Ogml::av_lighter, Ogml::av_int, -1); break; case Ogml::a_width: att.pushValues(s_attValues, Ogml::av_num, -1); break; case Ogml::a_x: att.pushValues(s_attValues, Ogml::av_num, -1); break; case Ogml::a_y: att.pushValues(s_attValues, Ogml::av_num, -1); break; case Ogml::a_z: att.pushValues(s_attValues, Ogml::av_num, -1); case Ogml::a_imageUri: att.pushValues(s_attValues, Ogml::av_string, -1); case Ogml::a_imageStyle: att.pushValues(s_attValues, Ogml::av_freeScale, Ogml::av_fixScale, -1); case Ogml::a_imageAlignment: att.pushValues(s_attValues, Ogml::av_topLeft, Ogml::av_topCenter, Ogml::av_topRight, Ogml::av_centerLeft, Ogml::av_center, Ogml::av_centerRight, Ogml::av_bottomLeft, Ogml::av_bottomCenter, Ogml::av_bottomRight, -1); case Ogml::a_imageDrawLine: att.pushValues(s_attValues, Ogml::av_bool, -1); case Ogml::a_imageWidth: att.pushValues(s_attValues, Ogml::av_num, -1); case Ogml::a_imageHeight: att.pushValues(s_attValues, Ogml::av_num, -1); case Ogml::a_constraintType: att.pushValues(s_attValues, Ogml::av_constraintAlignment, Ogml::av_constraintAnchor, Ogml::av_constraintSequence, -1); case Ogml::a_disabled: att.pushValues(s_attValues, Ogml::av_bool, -1); } } // Create OgmlTag objects and fill hashtable tags. for (int i = 0; i < Ogml::TAG_NUM; i++) s_tags->fastInsert(i, OgmlTag(i)); enum Mode { compMode = 0, choiceMode, optMode }; // Create tag relations. for (int i = 0; i < Ogml::TAG_NUM; i++) { OgmlTag &tag = s_tags->lookup(i)->info(); switch (i) { case Ogml::t_bool: tag.setMinOccurs(0); tag.setMaxOccurs(Ogml::MAX_TAG_COUNT); tag.pushAttributes(compMode, s_attributes, Ogml::a_boolValue, -1); tag.pushAttributes(optMode, s_attributes, Ogml::a_name, -1); break; case Ogml::t_composed: tag.setMinOccurs(0); tag.setMaxOccurs(Ogml::MAX_TAG_COUNT); tag.pushAttributes(optMode, s_attributes, Ogml::a_name, -1); tag.pushTags(choiceMode, s_tags, Ogml::t_num, Ogml::t_int, Ogml::t_bool, Ogml::t_string, Ogml::t_nodeRef, Ogml::t_edgeRef, Ogml::t_labelRef, Ogml::t_composed, -1); break; case Ogml::t_constraint: tag.setMinOccurs(0); tag.setMaxOccurs(Ogml::MAX_TAG_COUNT); tag.pushAttributes(compMode, s_attributes, Ogml::a_constraintType, -1); tag.pushAttributes(choiceMode, s_attributes, Ogml::a_id, Ogml::a_name, Ogml::a_disabled, -1); tag.pushTags(choiceMode, s_tags, Ogml::t_num, Ogml::t_int, Ogml::t_bool, Ogml::t_string, Ogml::t_nodeRef, Ogml::t_edgeRef, Ogml::t_labelRef, Ogml::t_composed, Ogml::t_constraint, -1); break; case Ogml::t_constraints: tag.setMinOccurs(0); tag.setMaxOccurs(1); tag.pushTags(compMode, s_tags, Ogml::t_constraint, -1); break; case Ogml::t_content: tag.setMinOccurs(0); tag.setMaxOccurs(1); tag.setIgnoreContent(true); break; case Ogml::t_data: tag.setMinOccurs(0); tag.setMaxOccurs(Ogml::MAX_TAG_COUNT); tag.pushAttributes(optMode, s_attributes, Ogml::a_name, -1); tag.pushTags(choiceMode, s_tags, Ogml::t_int, Ogml::t_bool, Ogml::t_num, Ogml::t_string, Ogml::t_data, -1); break; case Ogml::t_default: tag.setMinOccurs(0); tag.setMaxOccurs(1); break; case Ogml::t_edge: tag.setMinOccurs(0); tag.setMaxOccurs(Ogml::MAX_TAG_COUNT); tag.pushAttributes(compMode, s_attributes, Ogml::a_id, -1); tag.pushTags(choiceMode, s_tags, Ogml::t_source, Ogml::t_target, -1); tag.pushTags(optMode, s_tags, Ogml::t_data, Ogml::t_label, -1); break; case Ogml::t_edgeRef: tag.setMinOccurs(0); tag.setMaxOccurs(Ogml::MAX_TAG_COUNT); tag.pushAttributes(compMode, s_attributes, Ogml::a_edgeIdRef, -1); tag.pushAttributes(optMode, s_attributes, Ogml::a_name, -1); break; case Ogml::t_edgeStyle: tag.setMinOccurs(0); tag.setMaxOccurs(Ogml::MAX_TAG_COUNT); tag.pushAttributes(compMode, s_attributes, Ogml::a_edgeIdRef, -1); tag.pushTags(choiceMode, s_tags, Ogml::t_edgeStyleTemplateRef, Ogml::t_line, Ogml::t_sourceStyle, Ogml::t_targetStyle, Ogml::t_point, Ogml::t_segment, -1); tag.pushTags(optMode, s_tags, Ogml::t_data, -1); break; case Ogml::t_edgeStyleTemplate: tag.setMinOccurs(0); tag.setMaxOccurs(Ogml::MAX_TAG_COUNT); tag.pushAttributes(compMode, s_attributes, Ogml::a_id, -1); tag.pushTags(choiceMode, s_tags, Ogml::t_line, Ogml::t_sourceStyle, Ogml::t_targetStyle, -1); tag.pushTags(optMode, s_tags, Ogml::t_data, Ogml::t_edgeStyleTemplateRef, -1); break; case Ogml::t_endpoint: tag.setMinOccurs(2); tag.setMaxOccurs(2); tag.pushAttributes(compMode, s_attributes, Ogml::a_endpointIdRef, -1); tag.pushAttributes(optMode, s_attributes, Ogml::a_type, Ogml::a_color, Ogml::a_size, -1); break; case Ogml::t_fill: tag.setMinOccurs(0); tag.setMaxOccurs(1); tag.pushAttributes(compMode, s_attributes, Ogml::a_color, Ogml::a_pattern, Ogml::a_patternColor, -1); break; case Ogml::t_font: tag.setMinOccurs(0); tag.setMaxOccurs(1); tag.pushAttributes(compMode, s_attributes, Ogml::a_family, -1); tag.pushAttributes(optMode, s_attributes, Ogml::a_style, Ogml::a_variant, Ogml::a_weight, Ogml::a_stretch, Ogml::a_size, Ogml::a_color, -1); break; case Ogml::t_graph: tag.setMinOccurs(1); tag.setMaxOccurs(1); tag.pushTags(compMode, s_tags, Ogml::t_structure, -1); tag.pushTags(optMode, s_tags, Ogml::t_layout, Ogml::t_data, -1); break; case Ogml::t_graphStyle: tag.setMinOccurs(0); tag.setMaxOccurs(1); tag.pushAttributes(choiceMode, s_attributes, Ogml::a_defaultNodeTemplate, Ogml::a_defaultEdgeTemplate, Ogml::a_defaultLabelTemplate, -1); break; case Ogml::t_int: tag.setMinOccurs(0); tag.setMaxOccurs(Ogml::MAX_TAG_COUNT); tag.pushAttributes(compMode, s_attributes, Ogml::a_intValue, -1); tag.pushAttributes(optMode, s_attributes, Ogml::a_name, -1); break; case Ogml::t_label: tag.setMinOccurs(0); tag.setMaxOccurs(Ogml::MAX_TAG_COUNT); tag.pushAttributes(compMode, s_attributes, Ogml::a_id, -1); tag.pushTags(compMode, s_tags, Ogml::t_content, -1); tag.pushTags(optMode, s_tags, Ogml::t_data, -1); break; case Ogml::t_labelRef: tag.setMinOccurs(0); tag.setMaxOccurs(Ogml::MAX_TAG_COUNT); tag.pushAttributes(compMode, s_attributes, Ogml::a_labelIdRef, -1); tag.pushAttributes(optMode, s_attributes, Ogml::a_name, -1); break; case Ogml::t_labelStyle: tag.setMinOccurs(0); tag.setMaxOccurs(Ogml::MAX_TAG_COUNT); tag.pushAttributes(compMode, s_attributes, Ogml::a_labelIdRef, -1); tag.pushTags(choiceMode, s_tags, Ogml::t_labelStyleTemplateRef, Ogml::t_data, Ogml::t_text, Ogml::t_font, Ogml::t_location, -1); break; case Ogml::t_labelStyleTemplate: tag.setMinOccurs(0); tag.setMaxOccurs(Ogml::MAX_TAG_COUNT); tag.pushAttributes(compMode, s_attributes, Ogml::a_id, -1); tag.pushTags(compMode, s_tags, Ogml::t_text, Ogml::t_font, -1); tag.pushTags(optMode, s_tags, Ogml::t_data, Ogml::t_labelStyleTemplateRef, -1); break; case Ogml::t_layout: tag.setMinOccurs(0); tag.setMaxOccurs(1); tag.pushTags(optMode, s_tags, Ogml::t_data, Ogml::t_styleTemplates, Ogml::t_styles, Ogml::t_constraints, -1); break; case Ogml::t_line: tag.setMinOccurs(0); tag.setMaxOccurs(1); tag.pushAttributes(choiceMode, s_attributes, Ogml::a_nLineType, Ogml::a_width, Ogml::a_color, -1); break; case Ogml::t_location: tag.setMinOccurs(0); tag.setMaxOccurs(1); tag.pushAttributes(compMode, s_attributes, Ogml::a_x, Ogml::a_y, -1); tag.pushAttributes(optMode, s_attributes, Ogml::a_z, -1); break; case Ogml::t_node: tag.setMinOccurs(1); tag.setMaxOccurs(Ogml::MAX_TAG_COUNT); tag.pushAttributes(compMode, s_attributes, Ogml::a_id, -1); tag.pushTags(optMode, s_tags, Ogml::t_data, Ogml::t_label, Ogml::t_node, -1); break; case Ogml::t_nodeRef: tag.setMinOccurs(0); tag.setMaxOccurs(Ogml::MAX_TAG_COUNT); tag.pushAttributes(compMode, s_attributes, Ogml::a_nodeIdRef, -1); tag.pushAttributes(optMode, s_attributes, Ogml::a_name, -1); break; case Ogml::t_nodeStyle: tag.setMinOccurs(0); tag.setMaxOccurs(Ogml::MAX_TAG_COUNT); tag.pushAttributes(compMode, s_attributes, Ogml::a_nodeIdRef, -1); tag.pushTags(choiceMode, s_tags, Ogml::t_location, Ogml::t_shape, Ogml::t_fill, Ogml::t_line, Ogml::t_image, -1); tag.pushTags(optMode, s_tags, Ogml::t_data, Ogml::t_nodeStyleTemplateRef, -1); break; case Ogml::t_nodeStyleTemplate: tag.setMinOccurs(0); tag.setMaxOccurs(Ogml::MAX_TAG_COUNT); tag.pushAttributes(compMode, s_attributes, Ogml::a_id, -1); tag.pushTags(choiceMode, s_tags, Ogml::t_shape, Ogml::t_fill, Ogml::t_line, -1); tag.pushTags(optMode, s_tags, Ogml::t_data, Ogml::t_nodeStyleTemplateRef, -1); break; case Ogml::t_num: tag.setMinOccurs(0); tag.setMaxOccurs(Ogml::MAX_TAG_COUNT); tag.pushAttributes(compMode, s_attributes, Ogml::a_numValue, -1); tag.pushAttributes(optMode, s_attributes, Ogml::a_name, -1); break; case Ogml::t_ogml: tag.setMinOccurs(1); tag.setMaxOccurs(1); tag.pushTags(compMode, s_tags, Ogml::t_graph, -1); break; case Ogml::t_point: tag.setMinOccurs(0); tag.setMaxOccurs(Ogml::MAX_TAG_COUNT); tag.pushAttributes(compMode, s_attributes, Ogml::a_id, Ogml::a_x, Ogml::a_y, -1); tag.pushAttributes(optMode, s_attributes, Ogml::a_z, -1); tag.pushTags(optMode, s_tags, Ogml::t_data, -1); break; case Ogml::t_port: tag.setMinOccurs(0); tag.setMaxOccurs(Ogml::MAX_TAG_COUNT); tag.pushAttributes(compMode, s_attributes, Ogml::a_id, Ogml::a_x, Ogml::a_y, -1); break; case Ogml::t_segment: tag.setMinOccurs(0); tag.setMaxOccurs(Ogml::MAX_TAG_COUNT); tag.pushTags(compMode, s_tags, Ogml::t_endpoint, -1); tag.pushTags(optMode, s_tags, Ogml::t_data, Ogml::t_line, -1); break; case Ogml::t_shape: tag.setMinOccurs(0); tag.setMaxOccurs(1); tag.pushAttributes(choiceMode, s_attributes, Ogml::a_nShapeType, Ogml::a_width, Ogml::a_height, /*a_uri,*/ -1); // comment (BZ): uri is obsolete, images got an own tag break; case Ogml::t_source: tag.setMinOccurs(0); tag.setMaxOccurs(Ogml::MAX_TAG_COUNT); tag.pushAttributes(compMode, s_attributes, Ogml::a_sourceIdRef, -1); tag.pushAttributes(optMode, s_attributes, Ogml::a_id, -1); tag.pushTags(optMode, s_tags, Ogml::t_data, Ogml::t_label, -1); break; case Ogml::t_sourceStyle: tag.setMinOccurs(0); tag.setMaxOccurs(1); tag.pushAttributes(choiceMode, s_attributes, Ogml::a_type, Ogml::a_color, Ogml::a_size, -1); break; case Ogml::t_string: tag.setMinOccurs(0); tag.setMaxOccurs(Ogml::MAX_TAG_COUNT); tag.pushAttributes(optMode, s_attributes, Ogml::a_name, -1); tag.setIgnoreContent(true); break; case Ogml::t_structure: tag.setMinOccurs(1); tag.setMaxOccurs(1); tag.pushTags(compMode, s_tags, Ogml::t_node, -1); tag.pushTags(optMode, s_tags, Ogml::t_edge, Ogml::t_label, Ogml::t_data, -1); break; case Ogml::t_styles: tag.setMinOccurs(0); tag.setMaxOccurs(1); tag.pushTags(choiceMode, s_tags, Ogml::t_nodeStyle, Ogml::t_edgeStyle, Ogml::t_labelStyle, -1); tag.pushTags(optMode, s_tags, Ogml::t_graphStyle, Ogml::t_data, -1); break; case Ogml::t_styleTemplates: tag.setMinOccurs(0); tag.setMaxOccurs(1); tag.pushTags(choiceMode, s_tags, Ogml::t_nodeStyleTemplate, Ogml::t_edgeStyleTemplate, Ogml::t_labelStyleTemplate, -1); tag.pushTags(optMode, s_tags, Ogml::t_data, -1); break; case Ogml::t_target: tag.setMinOccurs(0); tag.setMaxOccurs(Ogml::MAX_TAG_COUNT); tag.pushAttributes(compMode, s_attributes, Ogml::a_targetIdRef, -1); tag.pushAttributes(optMode, s_attributes, Ogml::a_id, -1); tag.pushTags(optMode, s_tags, Ogml::t_data, Ogml::t_label, -1); break; case Ogml::t_targetStyle: tag.setMinOccurs(0); tag.setMaxOccurs(1); tag.pushAttributes(choiceMode, s_attributes, Ogml::a_type, Ogml::a_color, Ogml::a_size, -1); break; case Ogml::t_labelStyleTemplateRef: tag.setMinOccurs(0); tag.setMaxOccurs(1); tag.pushAttributes(compMode, s_attributes, Ogml::a_labelStyleTemplateIdRef, -1); break; case Ogml::t_nodeStyleTemplateRef: tag.setMinOccurs(0); tag.setMaxOccurs(1); tag.pushAttributes(compMode, s_attributes, Ogml::a_nodeStyleTemplateIdRef, -1); break; case Ogml::t_edgeStyleTemplateRef: tag.setMinOccurs(0); tag.setMaxOccurs(1); tag.pushAttributes(compMode, s_attributes, Ogml::a_edgeStyleTemplateIdRef, -1); break; case Ogml::t_text: tag.setMinOccurs(0); tag.setMaxOccurs(1); tag.pushAttributes(choiceMode, s_attributes, Ogml::a_alignment, Ogml::a_decoration, Ogml::a_transform, Ogml::a_rotation, -1); break; case Ogml::t_image: tag.setMinOccurs(0); tag.setMaxOccurs(1); tag.pushAttributes(compMode, s_attributes, Ogml::a_imageUri, -1); tag.pushAttributes(optMode, s_attributes, Ogml::a_imageStyle, Ogml::a_imageAlignment, Ogml::a_imageDrawLine, Ogml::a_imageWidth, Ogml::a_imageHeight, -1); break; } } } // ******************************************************** // // v a l i d a t e // // ******************************************************** int OgmlParser::validate(const XmlTagObject * xmlTag, int ogmlTagId) { OgmlTag *ogmlTag = &s_tags->lookup(ogmlTagId)->info(); ListConstIterator < OgmlTag * > it; XmlTagObject *sonTag; int valid; // Perhaps xmlTag is already valid if(xmlTag->valid()) return valid = Ogml::vs_valid; if(!ogmlTag) { cerr << "Didn't found tag with id \"" << ogmlTagId << "\" in hashtable in OgmlParser::validate! Aborting.\n"; return false; } if((valid = ogmlTag->validTag(*xmlTag, m_ids)) < 0) { this->printValidityInfo(*ogmlTag, *xmlTag, valid, __LINE__); return valid; } // if tag ignores its content simply return if(ogmlTag->ignoresContent()) { xmlTag->setValid(); #ifdef OGDF_DEBUG this->printValidityInfo(*ogmlTag, *xmlTag, valid = Ogml::vs_valid, __LINE__); #endif return valid = Ogml::vs_valid; } // Check if all required son tags exist if(ogmlTag->ownsCompulsiveTags()) { // find all obligatoric sons: all obligatoric sons for (it = ogmlTag->getCompulsiveTags().begin(); it.valid(); it++) { int cnt = 0; // search for untested sons sonTag = xmlTag->m_pFirstSon; while(sonTag) { if(sonTag->getName() == (**it).getName()) { cnt++; if((valid = validate(sonTag, (**it).getId())) < 0) return valid; } sonTag = sonTag->m_pBrother; } // Exp. son not found if(cnt == 0) { this->printValidityInfo(*ogmlTag, *xmlTag, valid = Ogml::vs_expTagNotFound, __LINE__); return valid; } // Check cardinality if(cnt < (**it).getMinOccurs() || cnt > (**it).getMaxOccurs()) { this->printValidityInfo((**it), *xmlTag, valid = Ogml::vs_cardErr, __LINE__); return valid; } } } // Check if choice son tags exist if(ogmlTag->ownsChoiceTags()) { bool tookChoice = false; // find all obligatoric sons: all obligatoric sons for (it = ogmlTag->getChoiceTags().begin(); it.valid(); it++) { int cnt = 0; // search for untested sons sonTag = xmlTag->m_pFirstSon; while(sonTag) { if(sonTag->getName() == (**it).getName()) { if((valid = validate(sonTag, (**it).getId())) < 0) return valid; tookChoice = true; cnt++; } sonTag = sonTag->m_pBrother; } // Check cardinality if(cnt > 0 && (cnt < (**it).getMinOccurs() || cnt > (**it).getMaxOccurs())) { this->printValidityInfo((**it), *xmlTag, valid = Ogml::vs_cardErr, __LINE__); return valid; } } if ((!tookChoice) && (xmlTag->m_pFirstSon)) { this->printValidityInfo((**it), *xmlTag, valid = Ogml::vs_tagEmptIncl, __LINE__); return valid; } } //Check choice son tags // Check if opt son tags exist if(ogmlTag->ownsOptionalTags()) { // find all obligatoric sons: all obligatoric sons for (it = ogmlTag->getOptionalTags().begin(); it.valid(); ++it) { int cnt = 0; // search for untested sons sonTag = xmlTag->m_pFirstSon; while(sonTag) { if(sonTag->getName() == (**it).getName()) { if((valid = validate(sonTag, (**it).getId())) < 0) return valid; cnt++; } sonTag = sonTag->m_pBrother; } // Check cardinality // if( (cnt<(**it).getMinOccurs() || cnt>(**it).getMaxOccurs()) ) { if(cnt > (**it).getMaxOccurs()) { this->printValidityInfo((**it), *xmlTag, valid = Ogml::vs_cardErr, __LINE__); return valid; } } } // Are there invalid son tags left? sonTag = xmlTag->m_pFirstSon; while(sonTag) { // tag already valid if(!sonTag->valid()) { this->printValidityInfo(*ogmlTag, *xmlTag, valid = Ogml::vs_unexpTag, __LINE__); return valid; } sonTag = sonTag->m_pBrother; } // Finally xmlTag is valid :-) xmlTag->setValid(); #ifdef OGDF_DEBUG this->printValidityInfo(*ogmlTag, *xmlTag, valid = Ogml::vs_valid, __LINE__); #endif return Ogml::vs_valid; } // // v a l i d a t e // void OgmlParser::validate(const char *fileName) { DinoXmlParser p(fileName); p.createParseTree(); const XmlTagObject *root = &p.getRootTag(); buildHashTables(); validate(root, Ogml::t_ogml); } // // o p e r a t o r < < // ostream& operator<<(ostream& os, const OgmlParser::OgmlAttribute& oa) { oa.print(os); return os; } // // o p e r a t o r < < // ostream& operator<<(ostream& os, const OgmlParser::OgmlTag& ot) { ot.printOwnedTags(os); ot.printOwnedAttributes(os); return os; } // *********************************************************** // // p r i n t V a l i d i t y I n f o // // *********************************************************** void OgmlParser::printValidityInfo(const OgmlTag & ot, const XmlTagObject & xto, int valStatus, int /*line*/) { const String &ogmlTagName = ot.getName(); switch (valStatus) { case Ogml::vs_tagEmptIncl: cerr << "ERROR: tag \"<" << ogmlTagName << ">\" expects tag(s) to include! "; cerr << "(Input source line: " << xto. getLine() << ", recursion depth: " << xto.getDepth() << ")\n"; ot.printOwnedTags(cerr); break; case Ogml::vs_idNotUnique: cerr << "ERROR: tag \"<" << ogmlTagName << ">\" owns already assigned id! "; cerr << "(Input source line: " << xto. getLine() << ", recursion depth: " << xto.getDepth() << ")\n"; break; case Ogml::vs_idRefErr: cerr << "ERROR: tag \"<" << ogmlTagName << ">\" references unknown or wrong id! "; cerr << "(Input source line: " << xto. getLine() << ", recursion depth: " << xto.getDepth() << ")\n"; break; case Ogml::vs_unexpTag: cerr << "ERROR: tag \"<" << ogmlTagName << ">\" owns unexpected tag! "; cerr << "(Input source line: " << xto. getLine() << ", recursion depth: " << xto.getDepth() << ")\n"; ot.printOwnedTags(cerr); break; case Ogml::vs_unexpAtt: cerr << "ERROR: tag \"<" << ogmlTagName << ">\" owns unexpected attribute(s)! "; cerr << "(Input source line: " << xto. getLine() << ", recursion depth: " << xto.getDepth() << ")\n"; ot.printOwnedAttributes(cerr); break; case Ogml::vs_expTagNotFound: cerr << "ERROR: tag \"<" << ogmlTagName << ">\" doesn't own compulsive tag(s)! "; cerr << "(Input source line: " << xto. getLine() << ", recursion depth: " << xto.getDepth() << ")\n"; ot.printOwnedTags(cerr); break; case Ogml::vs_expAttNotFound: cerr << "ERROR: tag \"<" << ogmlTagName << ">\" doesn't own compulsive attribute(s)! "; cerr << "(Input source line: " << xto. getLine() << ", recursion depth: " << xto.getDepth() << ")\n"; ot.printOwnedAttributes(cerr); break; case Ogml::vs_attValueErr: cerr << "ERROR: tag \"<" << ogmlTagName << ">\" owns attribute with wrong value! "; cerr << "(Input source line: " << xto. getLine() << ", recursion depth: " << xto.getDepth() << ")\n"; ot.printOwnedAttributes(cerr); break; case Ogml::vs_cardErr: cerr << "ERROR: tag \"<" << ogmlTagName << ">\" occurence exceeds the number of min. (" << ot. getMinOccurs() << ") or max. (" << ot.getMaxOccurs() << ") occurences in its context! "; cerr << "(Input source line: " << xto. getLine() << ", recursion depth: " << xto.getDepth() << ")\n"; break; case Ogml::vs_invalid: cerr << "ERROR: tag \"<" << ogmlTagName << ">\" is invalid! No further information available. "; cerr << "(Input source line: " << xto. getLine() << ", recursion depth: " << xto.getDepth() << ")\n"; cerr << ot; break; case Ogml::vs_valid: //cout << "INFO: tag \"<" << ogmlTagName << ">\" is valid :-) "; //cout << "(Input source line: " << xto. // getLine() << ", recursion depth: " << xto.getDepth() << ")\n"; break; } //#ifdef OGDF_DEBUG // if(valStatus != Ogml::vs_valid) // cout << "(Line OgmlParser::validate: " << line << ")\n"; //#endif } // *********************************************************** // // i s G r a p h H i e r a r c h i c a l // // *********************************************************** bool OgmlParser::isGraphHierarchical(const XmlTagObject *xmlTag) const { if(xmlTag->getName() == Ogml::s_tagNames[Ogml::t_node] && isNodeHierarchical(xmlTag)) return true; // Depth-Search only if ret!=true if(xmlTag->m_pFirstSon && isGraphHierarchical(xmlTag->m_pFirstSon)) return true; // Breadth-Search only if ret!=true if(xmlTag->m_pBrother && isGraphHierarchical(xmlTag->m_pBrother)) return true; return false; } // *********************************************************** // // i s N o d e H i e r a r c h i c a l // // *********************************************************** bool OgmlParser::isNodeHierarchical(const XmlTagObject *xmlTag) const { bool ret = false; if(xmlTag->getName() == Ogml::s_tagNames[Ogml::t_node]) { XmlTagObject* dum; // check if an ancestor is a node ret = xmlTag->findSonXmlTagObjectByName(Ogml::s_tagNames[Ogml::t_node], dum); } return ret; } // *********************************************************** // // c h e c k G r a p h T y p e // // *********************************************************** bool OgmlParser::checkGraphType(const XmlTagObject *xmlTag) const { if(xmlTag->getName() != Ogml::s_tagNames[Ogml::t_ogml]) { cerr << "ERROR: Expecting root tag \"" << Ogml::s_tagNames[Ogml::t_ogml] << "\" in OgmlParser::checkGraphType!\n"; return false; } // Normal graph present if(!isGraphHierarchical(xmlTag)) { m_graphType = Ogml::graph; return true; } // Cluster-/Compound graph present m_graphType = Ogml::clusterGraph; // Traverse the parse tree and collect all edge tags List edges; if(xmlTag->getName() == Ogml::s_tagNames[Ogml::t_edge]) edges.pushBack(xmlTag); XmlTagObject* son = xmlTag->m_pFirstSon; while(son) { if(son->getName() == Ogml::s_tagNames[Ogml::t_edge]) edges.pushBack(son); son = son->m_pBrother; } // Cluster graph already present if(edges.empty()) return true; // Traverse edges ListConstIterator edgeIt; for(edgeIt = edges.begin(); edgeIt.valid() && m_graphType != Ogml::compoundGraph; edgeIt++) { // Traverse the sources/targets son = (*edgeIt)->m_pFirstSon; // Parse tree is valid so one edge contains at least one source/target // with idRef attribute while(son) { XmlAttributeObject* att; if(son->findXmlAttributeObjectByName(Ogml::s_attributeNames[Ogml::a_nodeIdRef], att)) { const XmlTagObject *refTag = m_ids.lookup(att->getValue())->info(); if(isNodeHierarchical(refTag)) { m_graphType = Ogml::compoundGraph; break; } } son = son->m_pBrother; } } return true; } // *********************************************************** // // a u x i l i a r y m e t h o d s // // *********************************************************** // => Mapping of OGML to OGDF <= // Mapping Brush Pattern int OgmlParser::getBrushPatternAsInt(String s) { if (s == Ogml::s_attributeValueNames[Ogml::av_bpNone]) return 0; if (s == Ogml::s_attributeValueNames[Ogml::av_bpSolid]) return 1; if (s == Ogml::s_attributeValueNames[Ogml::av_bpDense1]) return 2; if (s == Ogml::s_attributeValueNames[Ogml::av_bpDense2]) return 3; if (s == Ogml::s_attributeValueNames[Ogml::av_bpDense3]) return 4; if (s == Ogml::s_attributeValueNames[Ogml::av_bpDense4]) return 5; if (s == Ogml::s_attributeValueNames[Ogml::av_bpDense5]) return 6; if (s == Ogml::s_attributeValueNames[Ogml::av_bpDense6]) return 7; if (s == Ogml::s_attributeValueNames[Ogml::av_bpDense7]) return 8; if (s == Ogml::s_attributeValueNames[Ogml::av_bpHorizontal]) return 9; if (s == Ogml::s_attributeValueNames[Ogml::av_bpVertical]) return 10; if (s == Ogml::s_attributeValueNames[Ogml::av_bpCross]) return 11; if (s == Ogml::s_attributeValueNames[Ogml::av_bpBackwardDiagonal]) return 12; if (s == Ogml::s_attributeValueNames[Ogml::av_bpForwardDiagonal]) return 13; if (s == Ogml::s_attributeValueNames[Ogml::av_bpDiagonalCross]) return 14; // default return bpSolid return 1; } // Mapping Shape to Integer int OgmlParser::getShapeAsInt(String s) { //TODO: has to be completed if other shape types are implemented!!! // SMALL PROBLEM: OGML DOESN'T SUPPORT SHAPES // -> change XSD, if necessary if (s=="rect" || s=="rectangle") return GraphAttributes::rectangle; // default return rectangle return GraphAttributes::rectangle; } // Mapping OgmlNodeShape to OGDF::NodeTemplate String OgmlParser::getNodeTemplateFromOgmlValue(String s) { // Mapping OGML-Values to ogdf // rect | triangle | circle | ellipse | hexagon | rhomb // | trapeze | upTrapeze | lParallelogram | rParallelogram | pentagon // | octagon | umlClass | image if (s == Ogml::s_attributeValueNames[Ogml::av_rect]) return "ogdf:std:rect"; if (s == Ogml::s_attributeValueNames[Ogml::av_rectSimple]) return "ogdf:std:rect simple"; if (s == Ogml::s_attributeValueNames[Ogml::av_triangle]) s = "ogdf:std:rect"; if (s == Ogml::s_attributeValueNames[Ogml::av_circle]) return "ogdf:std:ellipse"; if (s == Ogml::s_attributeValueNames[Ogml::av_ellipse]) return "ogdf:std:ellipse"; if (s == Ogml::s_attributeValueNames[Ogml::av_hexagon]) return "ogdf:std:hexagon"; if (s == Ogml::s_attributeValueNames[Ogml::av_rhomb]) return "ogdf:std:rect"; if (s == Ogml::s_attributeValueNames[Ogml::av_trapeze]) return "ogdf:std:rect"; if (s == Ogml::s_attributeValueNames[Ogml::av_upTrapeze]) return "ogdf:std:rect"; if (s == Ogml::s_attributeValueNames[Ogml::av_lParallelogram]) return "ogdf:std:rect"; if (s == Ogml::s_attributeValueNames[Ogml::av_rParallelogram]) return "ogdf:std:rect"; if (s == Ogml::s_attributeValueNames[Ogml::av_pentagon]) return "ogdf:std:rect"; if (s == Ogml::s_attributeValueNames[Ogml::av_octagon]) return"ogdf:std:rect"; if (s == Ogml::s_attributeValueNames[Ogml::av_umlClass]) return "ogdf:std:UML class"; if (s == Ogml::s_attributeValueNames[Ogml::av_image]) return "ogdf:std:rect"; // default return "ogdf:std:rect"; } // Mapping Line type to Integer int OgmlParser::getLineTypeAsInt(String s) { if (s == Ogml::s_attributeValueNames[Ogml::av_esNoPen]) return 0; if (s == Ogml::s_attributeValueNames[Ogml::av_esSolid]) return 1; if (s == Ogml::s_attributeValueNames[Ogml::av_esDash]) return 2; if (s == Ogml::s_attributeValueNames[Ogml::av_esDot]) return 3; if (s == Ogml::s_attributeValueNames[Ogml::av_esDashdot]) return 4; if (s == Ogml::s_attributeValueNames[Ogml::av_esDashdotdot]) return 5; // Mapping OGML-Values to ogdf // solid | dotted | dashed | double | triple // | groove | ridge | inset | outset | none if (s == Ogml::s_attributeValueNames[Ogml::av_solid]) return 1; if (s == Ogml::s_attributeValueNames[Ogml::av_dotted]) return 3; if (s == Ogml::s_attributeValueNames[Ogml::av_dashed]) return 2; if (s == Ogml::s_attributeValueNames[Ogml::av_double]) return 4; if (s == Ogml::s_attributeValueNames[Ogml::av_triple]) return 5; if (s == Ogml::s_attributeValueNames[Ogml::av_groove]) return 5; if (s == Ogml::s_attributeValueNames[Ogml::av_ridge]) return 1; if (s == Ogml::s_attributeValueNames[Ogml::av_inset]) return 1; if (s == Ogml::s_attributeValueNames[Ogml::av_outset]) return 1; if (s == Ogml::s_attributeValueNames[Ogml::av_none]) return 0; //default return bpSolid return 1; } // Mapping ArrowStyles to Integer int OgmlParser::getArrowStyleAsInt(String s, String /*sot*/) { // sot = "source" or "target", actually not necessary // TODO: Complete, if new arrow styles are implemented in ogdf if (s == "none") return 0; else return 1; // default return 0 return 0; } // Mapping ArrowStyles to EdgeArrow GraphAttributes::EdgeArrow OgmlParser::getArrowStyle(int i) { switch (i){ case 0: return GraphAttributes::none; break; case 1: return GraphAttributes::last; break; case 2: return GraphAttributes::first; break; case 3: return GraphAttributes::both; break; default: return GraphAttributes::last; } } // Mapping Image Style to Integer int OgmlParser::getImageStyleAsInt(String s) { if (s == Ogml::s_attributeValueNames[Ogml::av_freeScale]) return 0; if (s == Ogml::s_attributeValueNames[Ogml::av_fixScale]) return 1; //default return freeScale return 0; } // Mapping Image Alignment to Integer int OgmlParser::getImageAlignmentAsInt(String s) { if (s == Ogml::s_attributeValueNames[Ogml::av_topLeft]) return 0; if (s == Ogml::s_attributeValueNames[Ogml::av_topCenter]) return 1; if (s == Ogml::s_attributeValueNames[Ogml::av_topRight]) return 2; if (s == Ogml::s_attributeValueNames[Ogml::av_centerLeft]) return 3; if (s == Ogml::s_attributeValueNames[Ogml::av_center]) return 4; if (s == Ogml::s_attributeValueNames[Ogml::av_centerRight]) return 5; if (s == Ogml::s_attributeValueNames[Ogml::av_bottomLeft]) return 6; if (s == Ogml::s_attributeValueNames[Ogml::av_bottomCenter]) return 7; if (s == Ogml::s_attributeValueNames[Ogml::av_bottomRight]) return 8; //default return center return 4; } // returns the string with "<" substituted for "<" // and ">" substituted for ">" String OgmlParser::getLabelCaptionFromString(String str) { String output; size_t i=0; while (i it; if(!root) { cout << "WARNING: can't determine layout information, no parse tree available!\n"; } else { // root tag isn't a NULL pointer... let's start... XmlTagObject* son = root->m_pFirstSon; // first traverse to the structure- and the layout block if (son->getName() != Ogml::s_tagNames[Ogml::t_graph]){ while (son->getName() != Ogml::s_tagNames[Ogml::t_graph]){ son = son->m_pFirstSon; if (!son){ // wrong rootTag given or graph tag wasn't found return false; } } //while } //if // now son is the graph tag which first child is structure XmlTagObject* structure = son->m_pFirstSon; if (structure->getName() != Ogml::s_tagNames[Ogml::t_structure]){ return false; } // now structure is what it is meant to be // traverse the children of structure // and set the labels son = structure->m_pFirstSon; while(son) { //Set labels of nodes if ((son->getName() == Ogml::s_tagNames[Ogml::t_node]) && (CGA.attributes() & GraphAttributes::nodeLabel)) { if (!isNodeHierarchical(son)) { // get the id of the actual node XmlAttributeObject *att; if(son->findXmlAttributeObjectByName(Ogml::s_attributeNames[Ogml::a_id], att)) { // lookup for node node actNode = (m_nodes.lookup(att->getValue()))->info(); // find label tag XmlTagObject* label; if (son->findSonXmlTagObjectByName(Ogml::s_tagNames[Ogml::t_label], label)) { // get content tag XmlTagObject* content = label->m_pFirstSon; // get the content as string if (content->m_pTagValue) { String str = content->getValue(); String labelStr = getLabelCaptionFromString(str); // now set the label of the node CGA.labelNode(actNode) = labelStr; } } } }// "normal" nodes else { // get the id of the actual cluster XmlAttributeObject *att; if(son->findXmlAttributeObjectByName(Ogml::s_attributeNames[Ogml::a_id], att)) { // lookup for cluster cluster actCluster = (m_clusters.lookup(att->getValue()))->info(); // find label tag XmlTagObject* label; if (son->findSonXmlTagObjectByName(Ogml::s_tagNames[Ogml::t_label], label)) { // get content tag XmlTagObject* content = label->m_pFirstSon; // get the content as string if (content->m_pTagValue) { String str = content->getValue(); String labelStr = getLabelCaptionFromString(str); // now set the label of the node CGA.clusterLabel(actCluster) = labelStr; } } } // hierSon = hierarchical Son XmlTagObject *hierSon; if (son->m_pFirstSon) { hierSon = son->m_pFirstSon; while(hierSon) { // recursive call for setting labels of child nodes if (!setLabelsRecursive(G, CGA, hierSon)) return false; hierSon = hierSon->m_pBrother; } } }//cluster nodes }// node labels //Set labels of edges if ((son->getName() == Ogml::s_tagNames[Ogml::t_edge]) && (CGA.attributes() & GraphAttributes::edgeLabel)) { // get the id of the actual edge XmlAttributeObject *att; if (son->findXmlAttributeObjectByName(Ogml::s_attributeNames[Ogml::a_id], att)) { // lookup for edge // 0, if (hyper)edge not read from file if(m_edges.lookup(att->getValue())){ edge actEdge = (m_edges.lookup(att->getValue()))->info(); // find label tag XmlTagObject* label; if(son->findSonXmlTagObjectByName(Ogml::s_tagNames[Ogml::t_label], label)) { // get content tag XmlTagObject* content = label->m_pFirstSon; // get the content as string if (content->m_pTagValue) { String str = content->getValue(); String labelStr = getLabelCaptionFromString(str); // now set the label of the node CGA.labelEdge(actEdge) = labelStr; } } } } }// edge labels // Labels // ACTUALLY NOT IMPLEMENTED IN OGDF //if (son->getName() == Ogml::s_tagNames[t_label]) { // get the id of the actual edge //XmlAttributeObject *att; //if (son->findXmlAttributeObjectByName(Ogml::s_attributeNames[Ogml::a_id], att)){ // lookup for label //label actLabel = (labels.lookup(att->getValue()))->info(); // get content tag //XmlTagObject* content = son->m_pFirstSon; // get the content as string //if (content->m_pTagValue){ //String str = content->getValue(); //String labelStr = getLabelCaptionFromString(str); //now set the label of the node // CGA.labelLabel(actLabel) = labelStr; //} //} //}// Labels // go to the next brother son = son->m_pBrother; }// while(son) // son <=> children of structure // get the layout tag XmlTagObject* layout; if (structure->m_pBrother != NULL) { layout = structure->m_pBrother; } else layout = 0; if ((layout) && (layout->getName() == Ogml::s_tagNames[Ogml::t_layout])) { // layout exists // first get the styleTemplates XmlTagObject *layoutSon; if (layout->m_pFirstSon) { // layout has at least one child-tag layoutSon = layout->m_pFirstSon; // ->loop through all of them while (layoutSon) { // style templates if (layoutSon->getName() == Ogml::s_tagNames[Ogml::t_styleTemplates]) { // has children data, nodeStyleTemplate, edgeStyleTemplate, labelStyleTemplate XmlTagObject *styleTemplatesSon; if (layoutSon->m_pFirstSon) { styleTemplatesSon = layoutSon->m_pFirstSon; while (styleTemplatesSon) { // nodeStyleTemplate if (styleTemplatesSon->getName() == Ogml::s_tagNames[Ogml::t_nodeStyleTemplate]) { XmlAttributeObject *actAtt; if (styleTemplatesSon->findXmlAttributeObjectByName(Ogml::s_attributeNames[Ogml::a_id], actAtt)) { const String &actKey = actAtt->getValue(); OgmlNodeTemplate *actTemplate = new OgmlNodeTemplate(actKey); // when will this be deleted? XmlTagObject *actTag; // template inheritance if (styleTemplatesSon->findSonXmlTagObjectByName(Ogml::s_tagNames[Ogml::t_nodeStyleTemplateRef], actTag)) { if (actTag->findXmlAttributeObjectByName(Ogml::s_attributeNames[Ogml::a_nodeStyleTemplateIdRef], actAtt)) { // actual template references another // get it from the hash table OgmlNodeTemplate *refTemplate = m_ogmlNodeTemplates.lookup(actAtt->getValue())->info(); if (refTemplate) { // the referenced template was inserted into the hash table // so copy the values String actId = actTemplate->m_id; *actTemplate = *refTemplate; actTemplate->m_id = actId; } } }// template inheritance // // data // if (styleTemplatesSon->findSonXmlTagObjectByName(Ogml::s_tagNames[t_data], actTag)){ // // found data for nodeStyleTemplate // // no implementation required for ogdf // }// data // shape tag if (styleTemplatesSon->findSonXmlTagObjectByName(Ogml::s_tagNames[Ogml::t_shape], actTag)) { // type if (actTag->findXmlAttributeObjectByName(Ogml::s_attributeNames[Ogml::a_nShapeType], actAtt)) { // TODO: change, if shapes are expanded // actually shape and template are calculated from the same value!!! actTemplate->m_nodeTemplate = getNodeTemplateFromOgmlValue(actAtt->getValue()); actTemplate->m_shapeType = getShapeAsInt(actAtt->getValue()); } // width if (actTag->findXmlAttributeObjectByName(Ogml::s_attributeNames[Ogml::a_width], actAtt)) actTemplate->m_width = atof(actAtt->getValue().cstr()); // height if (actTag->findXmlAttributeObjectByName(Ogml::s_attributeNames[Ogml::a_height], actAtt)) actTemplate->m_height = atof(actAtt->getValue().cstr()); // uri //ACTUALLY NOT SUPPORTED //if (actTag->findXmlAttributeObjectByName(Ogml::s_attributeNames[a_uri], actAtt)) // CGA.uri(actNode) = actAtt->getValue(); }// shape // fill tag if (styleTemplatesSon->findSonXmlTagObjectByName(Ogml::s_tagNames[Ogml::t_fill], actTag)) { // fill color if (actTag->findXmlAttributeObjectByName(Ogml::s_attributeNames[Ogml::a_color], actAtt)) actTemplate->m_color = actAtt->getValue(); // fill pattern if (actTag->findXmlAttributeObjectByName(Ogml::s_attributeNames[Ogml::a_pattern], actAtt)) actTemplate->m_pattern = GraphAttributes::intToPattern(getBrushPatternAsInt(actAtt->getValue())); // fill patternColor //TODO: check if pattern color exists //if (actTag->findXmlAttributeObjectByName(Ogml::s_attributeNames[a_patternColor], actAtt)); // actTemplate->m_patternColor = actAtt->getValue()); }// fill // line tag if (styleTemplatesSon->findSonXmlTagObjectByName(Ogml::s_tagNames[Ogml::t_line], actTag)) { // type if (actTag->findXmlAttributeObjectByName(Ogml::s_attributeNames[Ogml::a_nLineType], actAtt)) actTemplate->m_lineType = GraphAttributes::intToStyle(getLineTypeAsInt(actAtt->getValue())); // width if (actTag->findXmlAttributeObjectByName(Ogml::s_attributeNames[Ogml::a_width], actAtt)) actTemplate->m_lineWidth = atof(actAtt->getValue().cstr()); // color if (actTag->findXmlAttributeObjectByName(Ogml::s_attributeNames[Ogml::a_color], actAtt)) actTemplate->m_lineColor = actAtt->getValue(); }// line //insert actual template into hash table m_ogmlNodeTemplates.fastInsert(actKey, actTemplate); } }//nodeStyleTemplate // edgeStyleTemplate if (styleTemplatesSon->getName() == Ogml::s_tagNames[Ogml::t_edgeStyleTemplate]) { XmlAttributeObject *actAtt; if (styleTemplatesSon->findXmlAttributeObjectByName(Ogml::s_attributeNames[Ogml::a_id], actAtt)) { const String &actKey = actAtt->getValue(); OgmlEdgeTemplate *actTemplate = new OgmlEdgeTemplate(actKey); // when will this be deleted? XmlTagObject *actTag; // template inheritance if (styleTemplatesSon->findSonXmlTagObjectByName(Ogml::s_tagNames[Ogml::t_edgeStyleTemplateRef], actTag)){ if (actTag->findXmlAttributeObjectByName(Ogml::s_attributeNames[Ogml::a_edgeStyleTemplateIdRef], actAtt)){ // actual template references another // get it from the hash table OgmlEdgeTemplate *refTemplate = m_ogmlEdgeTemplates.lookup(actAtt->getValue())->info(); if (refTemplate){ // the referenced template was inserted into the hash table // so copy the values String actId = actTemplate->m_id; *actTemplate = *refTemplate; actTemplate->m_id = actId; } } }// template inheritance // // data // if (styleTemplatesSon->findSonXmlTagObjectByName(Ogml::s_tagNames[t_data], actTag)){ // // found data for edgeStyleTemplate // // no implementation required for ogdf // }// data // line tag if (styleTemplatesSon->findSonXmlTagObjectByName(Ogml::s_tagNames[Ogml::t_line], actTag)) { // type if (actTag->findXmlAttributeObjectByName(Ogml::s_attributeNames[Ogml::a_type], actAtt)) actTemplate->m_lineType = GraphAttributes::intToStyle(getLineTypeAsInt(actAtt->getValue())); // width if (actTag->findXmlAttributeObjectByName(Ogml::s_attributeNames[Ogml::a_width], actAtt)) actTemplate->m_lineWidth = atof(actAtt->getValue().cstr()); // color if (actTag->findXmlAttributeObjectByName(Ogml::s_attributeNames[Ogml::a_color], actAtt)) actTemplate->m_color = actAtt->getValue(); }// line // sourceStyle tag if (styleTemplatesSon->findSonXmlTagObjectByName(Ogml::s_tagNames[Ogml::t_sourceStyle], actTag)) { // type if (actTag->findXmlAttributeObjectByName(Ogml::s_attributeNames[Ogml::a_type], actAtt)) actTemplate->m_sourceType = getArrowStyleAsInt(actAtt->getValue(), Ogml::s_tagNames[Ogml::t_source]); // color //if (actTag->findXmlAttributeObjectByName(Ogml::s_attributeNames[a_color], actAtt)) // actTemplate->m_sourceColor = actAtt->getValue(); // size //if (actTag->findXmlAttributeObjectByName(Ogml::s_attributeNames[a_size], actAtt)) // actTemplate->m_sourceSize = atof(actAtt->getValue()); } // targetStyle tag if (styleTemplatesSon->findSonXmlTagObjectByName(Ogml::s_tagNames[Ogml::t_targetStyle], actTag)){ // type if (actTag->findXmlAttributeObjectByName(Ogml::s_attributeNames[Ogml::a_type], actAtt)) actTemplate->m_targetType = getArrowStyleAsInt(actAtt->getValue(), Ogml::s_tagNames[Ogml::t_target]); // color //if (actTag->findXmlAttributeObjectByName(Ogml::s_attributeNames[a_color], actAtt)) // actTemplate->m_targetColor = actAtt->getValue(); // size //if (actTag->findXmlAttributeObjectByName(Ogml::s_attributeNames[a_size], actAtt)) // actTemplate->m_targetSize = atof(actAtt->getValue()); } //insert actual template into hash table m_ogmlEdgeTemplates.fastInsert(actKey, actTemplate); } }//edgeStyleTemplate // labelStyleTemplate if (styleTemplatesSon->getName() == Ogml::s_tagNames[Ogml::t_labelStyleTemplate]){ // ACTUALLY NOT SUPPORTED }//labelStyleTemplate styleTemplatesSon = styleTemplatesSon->m_pBrother; } } }// styleTemplates //STYLES if (layoutSon->getName() == Ogml::s_tagNames[Ogml::t_styles]) { // has children graphStyle, nodeStyle, edgeStyle, labelStyle XmlTagObject *stylesSon; if (layoutSon->m_pFirstSon) { stylesSon = layoutSon->m_pFirstSon; while (stylesSon) { // GRAPHSTYLE if (stylesSon->getName() == Ogml::s_tagNames[Ogml::t_graphStyle]) { XmlAttributeObject *actAtt; // defaultNodeTemplate if (stylesSon->findXmlAttributeObjectByName(Ogml::s_attributeNames[Ogml::a_defaultNodeTemplate], actAtt)) { OgmlNodeTemplate* actTemplate = m_ogmlNodeTemplates.lookup(actAtt->getValue())->info(); // XmlTagObject *actTag; // // data // if (stylesSon->findSonXmlTagObjectByName(Ogml::s_tagNames[t_data], actTag)){ // // found data for graphStyle // // no implementation required for ogdf // }// data // set values for ALL nodes node v; forall_nodes(v, G){ if (CGA.attributes() & GraphAttributes::nodeType){ CGA.templateNode(v) = actTemplate->m_nodeTemplate; CGA.shapeNode(v) = actTemplate->m_shapeType; } if (CGA.attributes() & GraphAttributes::nodeGraphics){ CGA.width(v) = actTemplate->m_width; CGA.height(v) = actTemplate->m_height; } if (CGA.attributes() & GraphAttributes::nodeColor) CGA.colorNode(v) = actTemplate->m_color; if (CGA.attributes() & GraphAttributes::nodeStyle){ CGA.nodePattern(v) = actTemplate->m_pattern; //CGA.nodePatternColor(v) = actTemplate->m_patternColor; CGA.styleNode(v) = actTemplate->m_lineType; CGA.lineWidthNode(v) = actTemplate->m_lineWidth; CGA.nodeLine(v) = actTemplate->m_lineColor; } }// forall_nodes }// defaultNodeTemplate // // defaultClusterTemplate // if (stylesSon->findXmlAttributeObjectByName(Ogml::s_attributeNames[a_defaultCompoundTemplate], actAtt)){ // // OgmlNodeTemplate* actTemplate = m_ogmlNodeTemplates.lookup(actAtt->getValue())->info(); // // // set values for ALL Cluster // cluster c; // forall_clusters(c, G){ // // if (CGA.attributes() & GraphAttributes::nodeType){ // CGA.templateCluster(c) = actTemplate->m_nodeTemplate; // // no shape definition for clusters // //CGA.shapeNode(c) = actTemplate->m_shapeType; // } // if (CGA.attributes() & GraphAttributes::nodeGraphics){ // CGA.clusterWidth(c) = actTemplate->m_width; // CGA.clusterHeight(c) = actTemplate->m_height; // } // if (CGA.attributes() & GraphAttributes::nodeColor) // CGA.clusterFillColor(c) = actTemplate->m_color; // if (CGA.attributes() & GraphAttributes::nodeStyle){ // CGA.clusterFillPattern(c) = actTemplate->m_pattern; // CGA.clusterBackColor(c) = actTemplate->m_patternColor; // CGA.clusterLineStyle(c) = actTemplate->m_lineType; // CGA.clusterLineWidth(c) = actTemplate->m_lineWidth; // CGA.clusterColor(c) = actTemplate->m_lineColor; // } // }// forall_clusters // }// defaultClusterTemplate // defaultEdgeTemplate if (stylesSon->findXmlAttributeObjectByName(Ogml::s_attributeNames[Ogml::a_defaultEdgeTemplate], actAtt)) { OgmlEdgeTemplate* actTemplate = m_ogmlEdgeTemplates.lookup(actAtt->getValue())->info(); // set values for ALL edges edge e; forall_edges(e, G) { if (CGA.attributes() & GraphAttributes::edgeStyle) { CGA.styleEdge(e) = actTemplate->m_lineType; CGA.edgeWidth(e) = actTemplate->m_lineWidth; } if (CGA.attributes() & GraphAttributes::edgeColor) { CGA.colorEdge(e) = actTemplate->m_color; } //edgeArrow if ((CGA.attributes()) & (GraphAttributes::edgeArrow)) { if (actTemplate->m_sourceType == 0) { if (actTemplate->m_targetType == 0) { // source = no_arrow, target = no_arrow // =>none CGA.arrowEdge(e) = GraphAttributes::none; } else { // source = no_arrow, target = arrow // =>last CGA.arrowEdge(e) = GraphAttributes::last; } } else { if (actTemplate->m_targetType == 0){ // source = arrow, target = no_arrow // =>first CGA.arrowEdge(e) = GraphAttributes::first; } else { // source = arrow, target = arrow // =>both CGA.arrowEdge(e) = GraphAttributes::both; } } }//edgeArrow }//forall_edges }//defaultEdgeTemplate // defaultLabelTemplate //if (stylesSon->findXmlAttributeObjectByName(Ogml::s_attributeNames[a_defaultLabelTemplate], actAtt)){ // // set values for ALL labels // // ACTUALLY NOT IMPLEMENTED // label l; // forall_labels(l, G){ // // } //}//defaultLabelTemplate }// graphStyle // NODESTYLE if (stylesSon->getName() == Ogml::s_tagNames[Ogml::t_nodeStyle]) { // get the id of the actual node XmlAttributeObject *att; if(stylesSon->findXmlAttributeObjectByName(Ogml::s_attributeNames[Ogml::a_nodeIdRef], att)) { // check if referenced id is a node or a cluster/compound if (m_nodes.lookup(att->getValue())) { // lookup for node node actNode = (m_nodes.lookup(att->getValue()))->info(); // actTag is the actual tag that is considered XmlTagObject* actTag; XmlAttributeObject *actAtt; // // data // if (stylesSon->findSonXmlTagObjectByName(Ogml::s_tagNames[t_data], actTag)){ // // found data for nodeStyle // // no implementation required for ogdf // }// data // check if actual nodeStyle references a template if (stylesSon->findSonXmlTagObjectByName(Ogml::s_tagNames[Ogml::t_nodeStyleTemplateRef], actTag)) { // get referenced template id if (actTag->findXmlAttributeObjectByName(Ogml::s_attributeNames[Ogml::a_nodeStyleTemplateIdRef], actAtt)) { // actual nodeStyle references a template OgmlNodeTemplate* actTemplate = m_ogmlNodeTemplates.lookup(actAtt->getValue())->info(); if (CGA.attributes() & GraphAttributes::nodeType) { CGA.templateNode(actNode) = actTemplate->m_nodeTemplate; CGA.shapeNode(actNode) = actTemplate->m_shapeType; } if (CGA.attributes() & GraphAttributes::nodeGraphics) { CGA.width(actNode) = actTemplate->m_width; CGA.height(actNode) = actTemplate->m_height; } if (CGA.attributes() & GraphAttributes::nodeColor) CGA.colorNode(actNode) = actTemplate->m_color; if (CGA.attributes() & GraphAttributes::nodeStyle) { CGA.nodePattern(actNode) = actTemplate->m_pattern; //CGA.nodePatternColor(actNode) = actTemplate->m_patternColor; CGA.styleNode(actNode) = actTemplate->m_lineType; CGA.lineWidthNode(actNode) = actTemplate->m_lineWidth; CGA.nodeLine(actNode) = actTemplate->m_lineColor; } } }//template // Graph::nodeType //TODO: COMPLETE, IF NECESSARY CGA.type(actNode) = Graph::vertex; // location tag if ((stylesSon->findSonXmlTagObjectByName(Ogml::s_tagNames[Ogml::t_location], actTag)) && (CGA.attributes() & GraphAttributes::nodeGraphics)) { // set location of node // x if (actTag->findXmlAttributeObjectByName(Ogml::s_attributeNames[Ogml::a_x], actAtt)) CGA.x(actNode) = atof(actAtt->getValue().cstr()); // y if (actTag->findXmlAttributeObjectByName(Ogml::s_attributeNames[Ogml::a_y], actAtt)) CGA.y(actNode) = atof(actAtt->getValue().cstr()); // z //if (actTag->findXmlAttributeObjectByName(Ogml::s_attributeNames[a_x], actAtt)) //CGA.z(actNode) = atof(actAtt->getValue()); }// location // shape tag if ((stylesSon->findSonXmlTagObjectByName(Ogml::s_tagNames[Ogml::t_shape], actTag)) && (CGA.attributes() & GraphAttributes::nodeType)) { // set shape of node // type if (actTag->findXmlAttributeObjectByName(Ogml::s_attributeNames[Ogml::a_nShapeType], actAtt)) { CGA.templateNode(actNode) = getNodeTemplateFromOgmlValue(actAtt->getValue()); // TODO: change, if shapes are expanded // actually shape and template are calculated from the same value!!! CGA.shapeNode(actNode) = getShapeAsInt(actAtt->getValue()); } // width if (actTag->findXmlAttributeObjectByName(Ogml::s_attributeNames[Ogml::a_width], actAtt)) CGA.width(actNode) = atof(actAtt->getValue().cstr()); // height if (actTag->findXmlAttributeObjectByName(Ogml::s_attributeNames[Ogml::a_height], actAtt)) CGA.height(actNode) = atof(actAtt->getValue().cstr()); // uri //ACTUALLY NOT SUPPORTED //if (actTag->findXmlAttributeObjectByName(Ogml::s_attributeNames[a_uri], actAtt)) // CGA.uri(actNode) = actAtt->getValue(); }// shape // fill tag if ((stylesSon->findSonXmlTagObjectByName(Ogml::s_tagNames[Ogml::t_fill], actTag)) && (CGA.attributes() & GraphAttributes::nodeStyle)) { // fill color if (actTag->findXmlAttributeObjectByName(Ogml::s_attributeNames[Ogml::a_color], actAtt)) CGA.colorNode(actNode) = actAtt->getValue(); // fill pattern if (actTag->findXmlAttributeObjectByName(Ogml::s_attributeNames[Ogml::a_pattern], actAtt)) CGA.nodePattern(actNode) = GraphAttributes::intToPattern(getBrushPatternAsInt(actAtt->getValue())); // fill patternColor //TODO: check if pattern color exists //if (actTag->findXmlAttributeObjectByName(Ogml::s_attributeNames[a_patternColor], actAtt)) // CGA.nodePatternColor(actNode) = actAtt->getValue()); }// fill // line tag if ((stylesSon->findSonXmlTagObjectByName(Ogml::s_tagNames[Ogml::t_line], actTag)) && (CGA.attributes() & GraphAttributes::nodeStyle)) { // type if (actTag->findXmlAttributeObjectByName(Ogml::s_attributeNames[Ogml::a_nLineType], actAtt)) CGA.styleNode(actNode) = GraphAttributes::intToStyle(getLineTypeAsInt(actAtt->getValue())); // width if (actTag->findXmlAttributeObjectByName(Ogml::s_attributeNames[Ogml::a_width], actAtt)) CGA.lineWidthNode(actNode) = atof(actAtt->getValue().cstr()); // color if (actTag->findXmlAttributeObjectByName(Ogml::s_attributeNames[Ogml::a_color], actAtt)) CGA.nodeLine(actNode) = actAtt->getValue().cstr(); }// line // // ports // // go through all ports with dummy tagObject port // XmlTagObject* port = stylesSon->m_pFirstSon; // while(port){ // if (port->getName() == ogmlTagObjects[t_port]){ // // TODO: COMPLETE // // ACTUALLY NOT IMPLEMENTED IN OGDF // } // // // go to next tag // port = port->m_pBrother; // } } else // CLUSTER NODE STYLE { // get the id of the cluster/compound XmlAttributeObject *att; if(stylesSon->findXmlAttributeObjectByName(Ogml::s_attributeNames[Ogml::a_nodeIdRef], att)) { // lookup for node cluster actCluster = (m_clusters.lookup(att->getValue()))->info(); // actTag is the actual tag that is considered XmlTagObject* actTag; XmlAttributeObject *actAtt; // // data // if (stylesSon->findSonXmlTagObjectByName(Ogml::s_tagNames[t_data], actTag)){ // // found data for nodeStyle (CLuster/Compound) // // no implementation required for ogdf // }// data // check if actual nodeStyle (equal to cluster) references a template if (stylesSon->findSonXmlTagObjectByName(Ogml::s_tagNames[Ogml::t_nodeStyleTemplateRef], actTag)) { // get referenced template id if (actTag->findXmlAttributeObjectByName(Ogml::s_attributeNames[Ogml::a_nodeStyleTemplateIdRef], actAtt)) { // actual nodeStyle references a template OgmlNodeTemplate* actTemplate = m_ogmlNodeTemplates.lookup(actAtt->getValue())->info(); if (CGA.attributes() & GraphAttributes::nodeType) { CGA.templateCluster(actCluster) = actTemplate->m_nodeTemplate; // no shape definition for clusters //CGA.shapeNode(actCluster) = actTemplate->m_shapeType; } if (CGA.attributes() & GraphAttributes::nodeGraphics) { CGA.clusterWidth(actCluster) = actTemplate->m_width; CGA.clusterHeight(actCluster) = actTemplate->m_height; } if (CGA.attributes() & GraphAttributes::nodeColor) CGA.clusterFillColor(actCluster) = actTemplate->m_color; if (CGA.attributes() & GraphAttributes::nodeStyle) { CGA.clusterFillPattern(actCluster) = actTemplate->m_pattern; CGA.clusterBackColor(actCluster) = actTemplate->m_patternColor; CGA.clusterLineStyle(actCluster) = actTemplate->m_lineType; CGA.clusterLineWidth(actCluster) = actTemplate->m_lineWidth; CGA.clusterColor(actCluster) = actTemplate->m_lineColor; } } }//template // Graph::nodeType //TODO: COMPLETE, IF NECESSARY // not supported for clusters!!! //CGA.type(actCluster) = Graph::vertex; // location tag if ((stylesSon->findSonXmlTagObjectByName(Ogml::s_tagNames[Ogml::t_location], actTag)) && (CGA.attributes() & GraphAttributes::nodeGraphics)) { // set location of node // x if (actTag->findXmlAttributeObjectByName(Ogml::s_attributeNames[Ogml::a_x], actAtt)) CGA.clusterXPos(actCluster) = atof(actAtt->getValue().cstr()); // y if (actTag->findXmlAttributeObjectByName(Ogml::s_attributeNames[Ogml::a_y], actAtt)) CGA.clusterYPos(actCluster) = atof(actAtt->getValue().cstr()); // z //if (actTag->findXmlAttributeObjectByName(Ogml::s_attributeNames[a_x], actAtt)) //CGA.clusterZPos(actCluster) = atof(actAtt->getValue()); }// location // shape tag if ((stylesSon->findSonXmlTagObjectByName(Ogml::s_tagNames[Ogml::t_shape], actTag)) && (CGA.attributes() & GraphAttributes::nodeType)) { // set shape of node // type if (actTag->findXmlAttributeObjectByName(Ogml::s_attributeNames[Ogml::a_nShapeType], actAtt)) { CGA.templateCluster(actCluster) = getNodeTemplateFromOgmlValue(actAtt->getValue().cstr()); // no shape definition for clusters //CGA.shapeNode(actCluster) = getShapeAsInt(actAtt->getValue()); } // width if (actTag->findXmlAttributeObjectByName(Ogml::s_attributeNames[Ogml::a_width], actAtt)) CGA.clusterWidth(actCluster) = atof(actAtt->getValue().cstr()); // height if (actTag->findXmlAttributeObjectByName(Ogml::s_attributeNames[Ogml::a_height], actAtt)) CGA.clusterHeight(actCluster) = atof(actAtt->getValue().cstr()); // uri //ACTUALLY NOT SUPPORTED //if (actTag->findXmlAttributeObjectByName(Ogml::s_attributeNames[a_uri], actAtt)) // CGA.uriCluster(actCluster) = actAtt->getValue(); }// shape // fill tag if ((stylesSon->findSonXmlTagObjectByName(Ogml::s_tagNames[Ogml::t_fill], actTag)) && (CGA.attributes() & GraphAttributes::nodeStyle)) { // fill color if (actTag->findXmlAttributeObjectByName(Ogml::s_attributeNames[Ogml::a_color], actAtt)) CGA.clusterFillColor(actCluster) = actAtt->getValue().cstr(); // fill pattern if (actTag->findXmlAttributeObjectByName(Ogml::s_attributeNames[Ogml::a_pattern], actAtt)) CGA.clusterFillPattern(actCluster) = GraphAttributes::intToPattern(getBrushPatternAsInt(actAtt->getValue())); // fill patternColor if (actTag->findXmlAttributeObjectByName(Ogml::s_attributeNames[Ogml::a_patternColor], actAtt)) CGA.clusterBackColor(actCluster) = actAtt->getValue().cstr(); }// fill // line tag if ((stylesSon->findSonXmlTagObjectByName(Ogml::s_tagNames[Ogml::t_line], actTag)) && (CGA.attributes() & GraphAttributes::nodeStyle)) { // type if (actTag->findXmlAttributeObjectByName(Ogml::s_attributeNames[Ogml::a_nLineType], actAtt)) CGA.clusterLineStyle(actCluster) = GraphAttributes::intToStyle(getLineTypeAsInt(actAtt->getValue())); // width if (actTag->findXmlAttributeObjectByName(Ogml::s_attributeNames[Ogml::a_width], actAtt)) CGA.clusterLineWidth(actCluster) = atof(actAtt->getValue().cstr()); // color if (actTag->findXmlAttributeObjectByName(Ogml::s_attributeNames[Ogml::a_color], actAtt)) CGA.clusterColor(actCluster) = actAtt->getValue(); }// line // // ports // // go through all ports with dummy tagObject port // XmlTagObject* port = stylesSon->m_pFirstSon; // while(port){ // if (port->getName() == ogmlTagObjects[t_port]){ // // TODO: COMPLETE // // no implementation required for ogdf // } // // // go to next tag // port = port->m_pBrother; // } }//nodeIdRef (with cluster) }// nodeStyle for cluster }//nodeIdRef }//nodeStyle // EDGESTYLE if (stylesSon->getName() == Ogml::s_tagNames[Ogml::t_edgeStyle]) { // get the id of the actual edge XmlAttributeObject *att; if(stylesSon->findXmlAttributeObjectByName(Ogml::s_attributeNames[Ogml::a_edgeIdRef], att)) { // lookup for edge edge actEdge = (m_edges.lookup(att->getValue()))->info(); // actTag is the actual tag that is considered XmlTagObject* actTag; XmlAttributeObject *actAtt; // // data // if (stylesSon->findSonXmlTagObjectByName(Ogml::s_tagNames[t_data], actTag)){ // // found data for edgeStyle // // no implementation required for ogdf // }// data // check if actual edgeStyle references a template if (stylesSon->findSonXmlTagObjectByName(Ogml::s_tagNames[Ogml::t_edgeStyleTemplateRef], actTag)) { // get referenced template id if (actTag->findXmlAttributeObjectByName(Ogml::s_attributeNames[Ogml::a_edgeStyleTemplateIdRef], actAtt)) { // actual edgeStyle references a template OgmlEdgeTemplate* actTemplate = m_ogmlEdgeTemplates.lookup(actAtt->getValue())->info(); if (CGA.attributes() & GraphAttributes::edgeStyle) { CGA.styleEdge(actEdge) = actTemplate->m_lineType; CGA.edgeWidth(actEdge) = actTemplate->m_lineWidth; } if (CGA.attributes() & GraphAttributes::edgeColor) { CGA.colorEdge(actEdge) = actTemplate->m_color; } //edgeArrow if ((CGA.attributes()) & (GraphAttributes::edgeArrow)) { if (actTemplate->m_sourceType == 0) { if (actTemplate->m_targetType == 0) { // source = no_arrow, target = no_arrow // =>none CGA.arrowEdge(actEdge) = GraphAttributes::none; } else { // source = no_arrow, target = arrow // =>last CGA.arrowEdge(actEdge) = GraphAttributes::last; } } else { if (actTemplate->m_targetType == 0) { // source = arrow, target = no_arrow // =>first CGA.arrowEdge(actEdge) = GraphAttributes::first; } else { // source = arrow, target = arrow // =>both CGA.arrowEdge(actEdge) = GraphAttributes::both; } } }//edgeArrow } }//template // Graph::edgeType //TODO: COMPLETE, IF NECESSARY CGA.type(actEdge) = Graph::association; // line tag if ((stylesSon->findSonXmlTagObjectByName(Ogml::s_tagNames[Ogml::t_line], actTag)) && (CGA.attributes() & GraphAttributes::edgeType)) { // type if (actTag->findXmlAttributeObjectByName(Ogml::s_attributeNames[Ogml::a_nLineType], actAtt)) CGA.styleEdge(actEdge) = GraphAttributes::intToStyle(getLineTypeAsInt(actAtt->getValue())); // width if (actTag->findXmlAttributeObjectByName(Ogml::s_attributeNames[Ogml::a_width], actAtt)) CGA.edgeWidth(actEdge) = atof(actAtt->getValue().cstr()); // color if ((actTag->findXmlAttributeObjectByName(Ogml::s_attributeNames[Ogml::a_color], actAtt)) && (CGA.attributes() & GraphAttributes::edgeType)) CGA.colorEdge(actEdge) = actAtt->getValue(); }// line // mapping of arrows if (CGA.attributes() & GraphAttributes::edgeArrow) { // values for mapping edge arrows to GDE // init to -1 for a simple check int sourceInt = -1; int targetInt = -1; // sourceStyle tag if (stylesSon->findSonXmlTagObjectByName(Ogml::s_tagNames[Ogml::t_sourceStyle], actTag)) { // type if (actTag->findXmlAttributeObjectByName(Ogml::s_attributeNames[Ogml::a_type], actAtt)) sourceInt = getArrowStyleAsInt((actAtt->getValue()), Ogml::s_attributeNames[Ogml::t_source]); // color //if (actTag->findXmlAttributeObjectByName(Ogml::s_attributeNames[a_color], actAtt)) // ; // size //if (actTag->findXmlAttributeObjectByName(Ogml::s_attributeNames[a_size], actAtt)) // ; }// sourceStyle // targetStyle tag if (stylesSon->findSonXmlTagObjectByName(Ogml::s_tagNames[Ogml::t_targetStyle], actTag)) { // type if (actTag->findXmlAttributeObjectByName(Ogml::s_attributeNames[Ogml::a_type], actAtt)) targetInt = getArrowStyleAsInt((actAtt->getValue()), Ogml::s_attributeNames[Ogml::t_target]); // color //if (actTag->findXmlAttributeObjectByName(Ogml::s_attributeNames[a_color], actAtt)) // ; // size //if (actTag->findXmlAttributeObjectByName(Ogml::s_attributeNames[a_size], actAtt)) // ; }// targetStyle // map edge arrows if ((sourceInt != -1) || (targetInt != -1)) { if (sourceInt <= 0) { if (targetInt <= 0) { //source=no arrow, target=no arrow // => none CGA.arrowEdge(actEdge) = GraphAttributes::none; } else { // source=no arrow, target=arrow // => last CGA.arrowEdge(actEdge) = GraphAttributes::last; } } else { if (targetInt <= 0) { //source=arrow, target=no arrow // => first CGA.arrowEdge(actEdge) = GraphAttributes::first; } else { //source=target=arrow // => both CGA.arrowEdge(actEdge) = GraphAttributes::both; } } } }//arrow // points & segments // bool value for checking if segments exist bool segmentsExist = stylesSon->findSonXmlTagObjectByName(Ogml::s_tagNames[Ogml::t_segment], actTag); if ((stylesSon->findSonXmlTagObjectByName(Ogml::s_tagNames[Ogml::t_point], actTag)) && (CGA.attributes() & GraphAttributes::edgeGraphics)) { // at least one point exists XmlTagObject *pointTag = stylesSon->m_pFirstSon; DPolyline dpl; dpl.clear(); // traverse all points in the order given in the ogml file while (pointTag) { if (pointTag->getName() == Ogml::s_tagNames[Ogml::t_point]) { if (pointTag->findXmlAttributeObjectByName(Ogml::s_attributeNames[Ogml::a_id], actAtt)) { DPoint dp; // here we have a point if (pointTag->findXmlAttributeObjectByName(Ogml::s_attributeNames[Ogml::a_x], actAtt)) { dp.m_x = atof(actAtt->getValue().cstr()); } if (pointTag->findXmlAttributeObjectByName(Ogml::s_attributeNames[Ogml::a_y], actAtt)) { dp.m_y = atof(actAtt->getValue().cstr()); } //if (actTag->findXmlAttributeObjectByName(Ogml::s_attributeNames[a_z], actAtt)) // dp.m_z = atof(actAtt->getValue()); // insert point into hash table pointTag->findXmlAttributeObjectByName(Ogml::s_attributeNames[Ogml::a_id], actAtt); m_points.fastInsert(actAtt->getValue(), dp); //insert point into polyline if (!segmentsExist) dpl.pushBack(dp); } } // go to next tag pointTag = pointTag->m_pBrother; }// while (pointTag) //concatenate polyline if (!segmentsExist) { CGA.bends(actEdge).conc(dpl); } else{ // work with segments // one error can occur: // if a segments is going to be inserted, // which doesn't match with any other, // the order can be not correct at the end // then the edge is relly corrupted!! // TODO: this implementation doesn't work with hyperedges // cause hyperedges have more than one source/target // segmentsUnsorted stores all found segments List segmentsUnsorted; XmlTagObject *segmentTag = stylesSon->m_pFirstSon; while (segmentTag) { if (segmentTag->getName() == Ogml::s_tagNames[Ogml::t_segment]) { XmlTagObject *endpointTag = segmentTag->m_pFirstSon; OgmlSegment actSeg; int endpointsSet = 0; while ((endpointTag) && (endpointsSet <2)) { if (endpointTag->getName() == Ogml::s_tagNames[Ogml::t_endpoint]) { // get the referenced point endpointTag->findXmlAttributeObjectByName(Ogml::s_attributeNames[Ogml::a_endpointIdRef], actAtt); DPoint dp = (m_points.lookup(actAtt->getValue()))->info(); if (endpointsSet == 0) actSeg.point1 = dp; else actSeg.point2 = dp; endpointsSet++; } endpointTag = endpointTag->m_pBrother; }// while // now we created a segment // we can insert this easily into in segmentsUnsorted if (actSeg.point1 != actSeg.point2) { segmentsUnsorted.pushBack(actSeg); } // point1 != point2 }// if (segment) // go to next tag segmentTag = segmentTag->m_pBrother; }// while (segmentTag) // now are the segments stored in the segmentsUnsorted list // but we have to sort it in segments list while inserting List segments; ListIterator segIt; // check the number of re-insertions int checkNumOfSegReInserts = segmentsUnsorted.size()+2; while ((segmentsUnsorted.size() > 0) && (checkNumOfSegReInserts > 0)) { OgmlSegment actSeg = segmentsUnsorted.front(); segmentsUnsorted.popFront(); // actSeg has to be inserted in correct order // and then being deleted // OR waiting in list until it can be inserted // size == 0 => insert if (segments.size() == 0) { segments.pushFront(actSeg); } else { // segments contains >1 segment segIt = segments.begin(); bool inserted = false; while (segIt.valid() && !inserted) { if ((actSeg.point1 == (*segIt).point1) || (actSeg.point1 == (*segIt).point2) || (actSeg.point2 == (*segIt).point1) || (actSeg.point2 == (*segIt).point2)) { // found two matching segments // now we can insert // there are some cases to check if (actSeg.point1 == (*segIt).point1) { DPoint dumP = actSeg.point1; actSeg.point1 = actSeg.point2; actSeg.point2 = dumP; segments.insertBefore(actSeg, segIt); } else if (actSeg.point2 == (*segIt).point1) { segments.insertBefore(actSeg, segIt); } else if ((actSeg.point2 == (*segIt).point2)) { DPoint dumP = actSeg.point1; actSeg.point1 = actSeg.point2; actSeg.point2 = dumP; segments.insertAfter(actSeg, segIt); } else { segments.insertAfter(actSeg, segIt); } inserted = true; } // first if segIt++; } //while if (!inserted) { // segment doesn't found matching segment, // so insert it again into unsorted segments list // so it will be inserted later segmentsUnsorted.pushBack(actSeg); checkNumOfSegReInserts--; } }//else }//while segmentsUnsorted.size() > 0 if (checkNumOfSegReInserts==0){ cout << "WARNING! Segment definition is not correct" << endl << flush; cout << "Not able to work with #"<< segmentsUnsorted.size() << " segments" << endl << flush; cout << "Please check connection and sorting of segments!" << endl << flush; // // inserting the bends although there might be an error // // I commented this, because in this case in ogdf the edge will // // be a straight edge and there will not be any artefacts // // TODO: uncomment if desired // for (segIt = segments.begin(); segIt.valid(); segIt++){ // dpl.pushBack((*segIt).point1); // dpl.pushBack((*segIt).point2); } else { // the segments are now ordered (perhaps in wrong way)... // so we have to check if the first and last point // are graphically laying in the source- and target- node bool invertSegments = false; segIt = segments.begin(); node target = actEdge->target(); node source = actEdge->source(); // check if source is a normal node or a cluster //if (...){ //} //else{ // big if-check: if (first point is in target // and not in source) // AND // (last point is in source // and not in target) if (( ( (CGA.x(target) + CGA.width(target))>= (*segIt).point1.m_x ) && (CGA.x(target) <= (*segIt).point1.m_x ) && ( (CGA.y(target) + CGA.height(target))>= (*segIt).point1.m_y ) && (CGA.y(target) <= (*segIt).point1.m_y ) ) && (!( ( (CGA.x(source) + CGA.width(source))>= (*segIt).point1.m_x ) && (CGA.x(source) <= (*segIt).point1.m_x ) && ( (CGA.y(source) + CGA.height(source))>= (*segIt).point1.m_y ) && (CGA.y(source) <= (*segIt).point1.m_y ) ))) { segIt = segments.rbegin(); if (( ( (CGA.x(source) + CGA.width(source))>= (*segIt).point2.m_x ) && (CGA.x(source) <= (*segIt).point2.m_x ) && ( (CGA.y(source) + CGA.height(source))>= (*segIt).point2.m_y ) && (CGA.y(source) <= (*segIt).point2.m_y ) ) && (!( ( (CGA.x(target) + CGA.width(source))>= (*segIt).point2.m_x ) && (CGA.x(target) <= (*segIt).point2.m_x ) && ( (CGA.y(target) + CGA.height(source))>= (*segIt).point2.m_y ) && (CGA.y(target) <= (*segIt).point2.m_y ) ))) { // invert the segment-line invertSegments = true; } } //} if (!invertSegments){ for (segIt = segments.begin(); segIt.valid(); segIt++) { dpl.pushBack((*segIt).point1); dpl.pushBack((*segIt).point2); } } else { for (segIt = segments.rbegin(); segIt.valid(); segIt--) { dpl.pushBack((*segIt).point2); dpl.pushBack((*segIt).point1); } } // unify bends = delete superfluous points dpl.unify(); // finally concatenate/set the bends CGA.bends(actEdge).conc(dpl); }// else (checkNumOfSegReInserts==0) }// else (segments exist) }// points & segments }//edgeIdRef }// edgeStyle // // LABELSTYLE // if (stylesSon->getName() == Ogml::s_tagNames[t_labelStyle]){ // // labelStyle // // ACTUALLY NOT SUPPORTED // }// labelStyle stylesSon = stylesSon->m_pBrother; } // while } } //styles // CONSTRAINTS if (layoutSon->getName() == Ogml::s_tagNames[Ogml::t_constraints]) { // this code is encapsulated in the method // OgmlParser::buildConstraints // has to be called by read methods after building // here we only set the pointer, // so we don't have to traverse the parse tree // to the constraints tag later m_constraintsTag = layoutSon; }// constraints // go to next brother layoutSon = layoutSon->m_pBrother; }// while(layoutSon) }//if (layout->m_pFirstSon) }// if ((layout) && (layout->getName() == Ogml::s_tagNames[t_layout])) }// else // cout << "buildAttributedClusterGraph COMPLETE. Check... " << endl << flush; // edge e; // forall_edges(e, G){ // //cout << "CGA.labelEdge" << e << " = " << CGA.labelEdge(e) << endl << flush; // cout << "CGA.arrowEdge" << e << " = " << CGA.arrowEdge(e) << endl << flush; // cout << "CGA.styleEdge" << e << " = " << CGA.styleEdge(e) << endl << flush; // cout << "CGA.edgeWidth" << e << " = " << CGA.edgeWidth(e) << endl << flush; // cout << "CGA.colorEdge" << e << " = " << CGA.colorEdge(e) << endl << flush; // cout << "CGA.type " << e << " = " << CGA.type(e) << endl << flush; // ListConstIterator it; // for(it = CGA.bends(e).begin(); it!=CGA.bends(e).end(); ++it) { // cout << "point " << " x=" << (*it).m_x << " y=" << (*it).m_y << endl << flush; // } // // } // // node n; // forall_nodes(n, G){ // cout << "CGA.labelNode(" << n << ") = " << CGA.labelNode(n) << endl << flush; // cout << "CGA.templateNode(" << n << ") = " << CGA.templateNode(n) << endl << flush; // cout << "CGA.shapeNode(" << n << ") = " << CGA.shapeNode(n) << endl << flush; // cout << "CGA.width(" << n << ") = " << CGA.width(n) << endl << flush; // cout << "CGA.height(" << n << ") = " << CGA.height(n) << endl << flush; // cout << "CGA.colorNode(" << n << ") = " << CGA.colorNode(n) << endl << flush; // cout << "CGA.nodePattern(" << n << ") = " << CGA.nodePattern(n) << endl << flush; // cout << "CGA.styleNode(" << n << ") = " << CGA.styleNode(n) << endl << flush; // cout << "CGA.lineWidthNode(" << n << ") = " << CGA.lineWidthNode(n) << endl << flush; // cout << "CGA.nodeLine(" << n << ") = " << CGA.nodeLine(n) << endl << flush; // cout << "CGA.x(" << n << ") = " << CGA.x(n) << endl << flush; // cout << "CGA.y(" << n << ") = " << CGA.y(n) << endl << flush; // cout << "CGA.type(" << n << ") = " << CGA.type(n) << endl << flush; // } // // cluster c; // forall_clusters(c, CGA.constClusterGraph()){ // cout << "CGA.templateCluster(" << c << ") = " << CGA.templateCluster(c) << endl << flush; // cout << "CGA.clusterWidth(" << c << ") = " << CGA.clusterWidth(c) << endl << flush; // cout << "CGA.clusterHeight(" << c << ") = " << CGA.clusterHeight(c) << endl << flush; // cout << "CGA.clusterFillColor(" << c << ") = " << CGA.clusterFillColor(c) << endl << flush; // cout << "CGA.clusterFillPattern(" << c << ") = " << CGA.clusterFillPattern(c) << endl << flush; // cout << "CGA.clusterBackColor(" << c << ") = " << CGA.clusterBackColor(c) << endl << flush; // cout << "CGA.clusterLineStyle(" << c << ") = " << CGA.clusterLineStyle(c) << endl << flush; // cout << "CGA.clusterLineWidth(" << c << ") = " << CGA.clusterLineWidth(c) << endl << flush; // cout << "CGA.clusterColor(" << c << ") = " << CGA.clusterColor(c) << endl << flush; // cout << "CGA.clusterXPos(" << c << ") = " << CGA.clusterXPos(c) << endl << flush; // cout << "CGA.clusterYPos(" << c << ") = " << CGA.clusterYPos(c) << endl << flush; // } // cout << "buildAttributedClusterGraph COMPLETE... Check COMPLETE... Let's have fun in GDE ;) " << endl << flush; // building terminated, so return true return true; }//buildAttributedClusterGraph // *********************************************************** // // s e t l a b e l s r e c u r s i v e f o r c l u s t e r s // // *********************************************************** // sets the labels of hierarchical nodes => cluster bool OgmlParser::setLabelsRecursive(Graph &G, ClusterGraphAttributes &CGA, XmlTagObject *root) { if ((root->getName() == Ogml::s_tagNames[Ogml::t_node]) && (CGA.attributes() & GraphAttributes::nodeLabel)) { if (!isNodeHierarchical(root)) { // get the id of the actual node XmlAttributeObject *att; if(root->findXmlAttributeObjectByName(Ogml::s_attributeNames[Ogml::a_id], att)) { // lookup for node node actNode = (m_nodes.lookup(att->getValue()))->info(); // find label tag XmlTagObject* label; if (root->findSonXmlTagObjectByName(Ogml::s_tagNames[Ogml::t_label], label)) { // get content tag XmlTagObject* content = label->m_pFirstSon; // get the content as string if (content->m_pTagValue){ String str = content->getValue(); String labelStr = getLabelCaptionFromString(str); // now set the label of the node CGA.labelNode(actNode) = labelStr; } } } }// "normal" nodes else { // get the id of the actual cluster XmlAttributeObject *att; if(root->findXmlAttributeObjectByName(Ogml::s_attributeNames[Ogml::a_id], att)) { // lookup for cluster cluster actCluster = (m_clusters.lookup(att->getValue()))->info(); // find label tag XmlTagObject* label; if (root->findSonXmlTagObjectByName(Ogml::s_tagNames[Ogml::t_label], label)) { // get content tag XmlTagObject* content = label->m_pFirstSon; // get the content as string if (content->m_pTagValue) { String str = content->getValue(); String labelStr = getLabelCaptionFromString(str); // now set the label of the node CGA.clusterLabel(actCluster) = labelStr; } } } // hierSon = hierarchical Son XmlTagObject *hierSon; if (root->m_pFirstSon) { hierSon = root->m_pFirstSon; while(hierSon) { // recursive call for setting labels of child nodes if (!setLabelsRecursive(G, CGA, hierSon)) return false; hierSon = hierSon->m_pBrother; } } }//cluster nodes } return true; }// setLabelsRecursive // *********************************************************** // // b u i l d g r a p h // // *********************************************************** bool OgmlParser::buildGraph(Graph &G) { G.clear(); int id = 0; //Build nodes first HashConstIterator it; for(it = m_ids.begin(); it.valid(); ++it) { if( it.info()->getName() == Ogml::s_tagNames[Ogml::t_node] && !isNodeHierarchical(it.info())) { // get id string from xmlTag XmlAttributeObject *idAtt; if ( (it.info())->findXmlAttributeObjectByName(Ogml::s_attributeNames[Ogml::a_id], idAtt) && (getIdFromString(idAtt->getValue(), id)) ) { // now we got an id from the id-string // we have to check, if this id was assigned if (m_nodeIds.lookup(id)) { // new id was assigned to another node id = G.maxNodeIndex() + 1; } } else { // default id setting id = G.maxNodeIndex() + 1; } m_nodes.fastInsert(it.key(), G.newNode(id)); m_nodeIds.fastInsert(id, idAtt->getValue()); } }//for nodes id = 0; //Build edges second for(it = m_ids.begin(); it.valid(); ++it) { if( it.info()->getName() == Ogml::s_tagNames[Ogml::t_edge] ) { //Check sources/targets Stack srcTgt; const XmlTagObject* son = it.info()->m_pFirstSon; while(son) { if( son->getName() == Ogml::s_tagNames[Ogml::t_source] || son->getName() == Ogml::s_tagNames[Ogml::t_target] ) { XmlAttributeObject *att; son->findXmlAttributeObjectByName(Ogml::s_attributeNames[Ogml::a_nodeIdRef], att); //Validate if source/target is really a node if(m_ids.lookup(att->getValue())->info()->getName() != Ogml::s_tagNames[Ogml::t_node]) { cout << "WARNING: edge relation between graph elements of none type node " << "are temporarily not supported!\n"; } else { srcTgt.push(m_nodes.lookup(att->getValue())->info()); } } son = son->m_pBrother; } if(srcTgt.size() != 2) { cout << "WARNING: hyperedges are temporarily not supported! Discarding edge.\n"; } else { // create edge // get id string from xmlTag XmlAttributeObject *idAtt; if ( (it.info())->findXmlAttributeObjectByName(Ogml::s_attributeNames[Ogml::a_id], idAtt) && (getIdFromString(idAtt->getValue(), id)) ) { if (m_edgeIds.lookup(id)) { // new id was assigned to another edge id = G.maxEdgeIndex() + 1; } } else { // default id setting id = G.maxEdgeIndex() + 1; } m_edges.fastInsert(it.key(), G.newEdge(srcTgt.pop(), srcTgt.pop(), id)); m_edgeIds.fastInsert(id, idAtt->getValue()); } } }//for edges //Structure data determined, so building the graph was successfull. return true; }//buildGraph // *********************************************************** // // b u i l d c l u s t e r -- g r a p h // // *********************************************************** bool OgmlParser::buildClusterRecursive( const XmlTagObject *xmlTag, cluster parent, Graph &G, ClusterGraph &CG) { // create new cluster // first get the id int id = -1; XmlAttributeObject *idAtt; if ( (xmlTag->findXmlAttributeObjectByName(Ogml::s_attributeNames[Ogml::a_id], idAtt)) && (getIdFromString(idAtt->getValue(), id)) ) { if (m_clusterIds.lookup(id)) { // id was assigned to another cluster id = CG.maxClusterIndex() + 1; } } else { // default id setting id = CG.maxClusterIndex() + 1; } // create cluster and insert into hash tables cluster actCluster = CG.newCluster(parent, id); m_clusters.fastInsert(idAtt->getValue(), actCluster); m_clusterIds.fastInsert(id, idAtt->getValue()); // check children of cluster tag XmlTagObject *son = xmlTag->m_pFirstSon; while(son) { if (son->getName() == Ogml::s_tagNames[Ogml::t_node]) { if (isNodeHierarchical(son)) // recursive call buildClusterRecursive(son, actCluster, G, CG); else { // the actual node tag is a child of the cluster XmlAttributeObject *att; //parse tree is valid so tag owns id attribute son->findXmlAttributeObjectByName(Ogml::s_attributeNames[Ogml::a_id], att); // get node from lookup table with the id in att node v = m_nodes.lookup(att->getValue())->info(); // assign node to actual cluster CG.reassignNode(v, actCluster); } } son = son->m_pBrother; }//while return true; }//buildClusterRecursive bool OgmlParser::buildCluster( const XmlTagObject *rootTag, Graph &G, ClusterGraph &CG) { CG.clear(); CG.init(G); if(rootTag->getName() != Ogml::s_tagNames[Ogml::t_ogml]) { cerr << "ERROR: Expecting root tag \"" << Ogml::s_tagNames[Ogml::t_ogml] << "\" in OgmlParser::buildCluster!\n"; return false; } //Search for first node tag XmlTagObject *nodeTag; rootTag->findSonXmlTagObjectByName(Ogml::s_tagNames[Ogml::t_graph], nodeTag); nodeTag->findSonXmlTagObjectByName(Ogml::s_tagNames[Ogml::t_structure], nodeTag); nodeTag->findSonXmlTagObjectByName(Ogml::s_tagNames[Ogml::t_node], nodeTag); while (nodeTag) { if(nodeTag->getName() == Ogml::s_tagNames[Ogml::t_node] && isNodeHierarchical(nodeTag)) { if (!buildClusterRecursive(nodeTag, CG.rootCluster(), G, CG)) return false; } nodeTag = nodeTag->m_pBrother; } return true; }//buildCluster // *********************************************************** // // b u i l d c o n s t r a i n t s // // *********************************************************** //Commented out due to missing graphconstraints in OGDF /* bool OgmlParser::buildConstraints(Graph& G, GraphConstraints &GC) { // constraints-tag was already set // if not, then return... job's done if (!m_constraintsTag) return true; if (m_constraintsTag->getName() != Ogml::s_tagNames[t_constraints]){ cerr << "Error: constraints tag is not the required tag!" << endl; return false; } XmlTagObject* constraintTag; if(! m_constraintsTag->findSonXmlTagObjectByName(Ogml::s_tagNames[t_constraint], constraintTag) ) { cerr << "Error: no constraint block in constraints block of valid parse tree found!" << endl; return false; } while(constraintTag) { // // found data // if (constraintTag->getName() == Ogml::s_tagNames[t_data]){ // // found data for constraints in general // // no implementation required for ogdf // }//data if(constraintTag->getName() == Ogml::s_tagNames[t_constraint]) { XmlAttributeObject* actAtt; String cId; String cType; if (constraintTag->findXmlAttributeObjectByName(Ogml::s_attributeNames[Ogml::a_id], actAtt)) // set id of the constraint cId = actAtt->getValue(); if (constraintTag->findXmlAttributeObjectByName(Ogml::s_attributeNames[a_type], actAtt)) cType = actAtt->getValue(); else { cerr << "Error: constraint doesn't own compulsive attribute \'type\' in valid parse tree!" << endl; return false; } // now we need a constraint manager to create a constraint // with the type of the name stored in cType // create the constraint Constraint* c = ConstraintManager::createConstraintByName(G, &cType); // check if the constraintManager doesn't return a null pointer // that occurs if cM doesn't know the constraint name if (c) { // let the constraint load itself if (c->buildFromOgml(constraintTag, &m_nodes)){ // add constraint if true is returned GC.addConstraint(c); } else cerr << "Error while building constraint with name \""<m_pBrother; }//while // terminated, so return true return true; } */ // *********************************************************** // // p u b l i c r e a d m e t h o d s // // *********************************************************** bool OgmlParser::read( const char* fileName, Graph &G, ClusterGraph &CG) { try { // DinoXmlParser for parsing the ogml file DinoXmlParser p(fileName); p.createParseTree(); // get root object of the parse tree const XmlTagObject *root = &p.getRootTag(); // build the required hash tables buildHashTables(); // valide the document if ( validate(root, Ogml::t_ogml) == Ogml::vs_valid ) { checkGraphType(root); // build graph if (buildGraph(G)) { Ogml::GraphType gt = getGraphType(); // switch GraphType switch (gt){ //normal graph case Ogml::graph: break; // cluster graph case Ogml::clusterGraph: // build cluster if (!buildCluster(root, G, CG)) return false; break; // compound graph case Ogml::compoundGraph: // build cluster because we got a cluster graph variable // although we have a compound graph in the ogml file if (!buildCluster(root, G, CG)) return false; break; // corrupt compound graph case Ogml::corruptCompoundGraph: // build cluster because we got a cluster graph variable // although we have a corrupted compound graph in the ogml file if (!buildCluster(root, G, CG)) return false; break; } } else return false; } else return false; } catch(const char *error) { cout << error << endl << flush; return false; } return true; }; bool OgmlParser::read( const char* fileName, Graph &G, ClusterGraph &CG, ClusterGraphAttributes &CGA) { try { // DinoXmlParser for parsing the ogml file DinoXmlParser p(fileName); p.createParseTree(); // get root object of the parse tree const XmlTagObject *root = &p.getRootTag(); // build the required hash tables buildHashTables(); // valide the document if ( validate(root, Ogml::t_ogml) == Ogml::vs_valid ) { checkGraphType(root); // build graph if (buildGraph(G)) { Ogml::GraphType gt = getGraphType(); // switch GraphType switch (gt){ // normal graph case Ogml::graph: if (!buildAttributedClusterGraph(G, CGA, root)) return false; break; // cluster graph case Ogml::clusterGraph: if (!buildCluster(root, G, CG)) return false; if (!buildAttributedClusterGraph(G, CGA, root)) return false; break; // compound graph case Ogml::compoundGraph: // build cluster because we got a cluster graph variable // although we have a compound graph in the ogml file if (!buildCluster(root, G, CG)) return false; if (!buildAttributedClusterGraph(G, CGA, root)) return false; break; // corrupt compound graph case Ogml::corruptCompoundGraph: // build cluster because we got a cluster graph variable // although we have a corrupted compound graph in the ogml file if (!buildCluster(root, G, CG)) return false; if (!buildAttributedClusterGraph(G, CGA, root)) return false; } } else return false; } else return false; } catch(const char *error) { cout << error << endl << flush; return false; } return true; }; }//namespace ogdf