00001
00002
00003
00004
00005
00006
00007
00008
00044 #ifdef _MSC_VER
00045 #pragma once
00046 #endif
00047
00048
00049
00050 #ifndef OGDF_OGMLPARSER_H
00051 #define OGDF_OGMLPARSER_H
00052
00053 #include <ogdf/fileformats/Ogml.h>
00054 #include <ogdf/fileformats/DinoXmlParser.h>
00055 #include <ogdf/basic/Hashing.h>
00056 #include <ogdf/basic/List.h>
00057 #include <ogdf/basic/String.h>
00058
00059 #include <ogdf/cluster/ClusterGraph.h>
00060
00061
00062 #include <ogdf/basic/GraphAttributes.h>
00063 #include <ogdf/cluster/ClusterGraphAttributes.h>
00064
00065
00066
00067
00068 #include <stdlib.h>
00069 #include <stdarg.h>
00070 #include <sstream>
00071
00072 namespace ogdf {
00073
00074
00075 struct OgmlNodeTemplate{
00076 String m_id;
00077 int m_shapeType;
00078 double m_width;
00079 double m_height;
00080 String m_color;
00081 GraphAttributes::BrushPattern m_pattern;
00082 String m_patternColor;
00083 GraphAttributes::EdgeStyle m_lineType;
00084 double m_lineWidth;
00085 String m_lineColor;
00086
00087
00088 String m_nodeTemplate;
00089
00090
00091 OgmlNodeTemplate(String id): m_id(id) {};
00092 };
00093
00094 struct OgmlEdgeTemplate{
00095 String m_id;
00096 GraphAttributes::EdgeStyle m_lineType;
00097 double m_lineWidth;
00098 String m_color;
00099 int m_sourceType;
00100
00101
00102
00103 int m_targetType;
00104
00105
00106
00107
00108
00109 OgmlEdgeTemplate(String id): m_id(id) {};
00110 };
00111
00112
00113
00114
00115
00116
00117 struct OgmlSegment{
00118 DPoint point1, point2;
00119 };
00120
00121
00122
00123
00124
00125
00128 class OgmlAttributeValue {
00129
00133 int id;
00134
00135 public:
00136
00137 OgmlAttributeValue() : id(av_any) {}
00138 OgmlAttributeValue(int id) {
00139 if(id>=0 && id<ATT_VAL_NUM) this->id = id;
00140 else id = av_any;
00141 }
00142
00143 ~OgmlAttributeValue() {}
00144
00145 const int& getId() const { return id; }
00146 const String& getValue() const { return ogmlAttributeValueNames[id]; }
00147
00148 void setId(int id) {
00149 if(id>=0 && id<ATT_VAL_NUM) this->id = id;
00150 else id = av_any;
00151 }
00152
00153
00154
00155
00156
00157 OgmlAttributeValueId getTypeOfString(const String& input) const {
00158
00159
00160
00161
00162
00163
00164
00165
00166
00167
00168 bool isInt = true;
00169 bool isNum = true;
00170 bool isHex = true;
00171
00172 bool numPoint = false;
00173
00174
00175 if (input == "true" || input == "false" )
00176 return av_bool;
00177
00178 if (input.length() > 0){
00179 char actChar = input[0];
00180 int actCharInt = static_cast<int>(actChar);
00181
00182 if (!isalnum(actChar)){
00183
00184 if ((actCharInt == 35)){
00185
00186 isInt = false;
00187 isNum = false;
00188 }
00189 else
00190 {
00191
00192
00193 if (!(actCharInt == 45) && !(actChar == 43)){
00194 isInt = isNum = false;
00195 }
00196 else
00197 {
00198
00199 if (input.length() > 1){
00200
00201 actChar = input[1];
00202 actCharInt = static_cast<int>(actChar);
00203 if (!isdigit(actChar)){
00204 isInt = false;
00205 isNum = false;
00206 if (!isxdigit(actChar))
00207 return av_string;
00208 }
00209 }
00210 else
00211 return av_string;
00212 }
00213 }
00214 }
00215 else{
00216 if (!isdigit(actChar)){
00217 isInt = false;
00218 isNum = false;
00219 }
00220 if (!isxdigit(actChar)){
00221 isHex = false;
00222 }
00223 }
00224
00225
00226
00227 for(size_t it=1; ( (it<input.length()) && ((isInt) || (isNum) || (isHex)) ); it++)
00228 {
00229 actChar = input[it];
00230 actCharInt = static_cast<int>(actChar);
00231
00232
00233 if (actChar == 46){
00234 isInt = false;
00235 isHex = false;
00236 if (!numPoint){
00237 numPoint = true;
00238 }
00239 else
00240 isNum = false;
00241 }
00242 else {
00243 if (!(isdigit(actChar))){
00244 isInt = false;
00245 isNum = false;
00246 }
00247 if (!(isxdigit(actChar)))
00248 isHex = false;
00249 }
00250 }
00251 }
00252 else{
00253
00254 return av_none;
00255 }
00256
00257 if (isInt) return av_int;
00258 if (isNum) return av_num;
00259 if (isHex) return av_hex;
00260
00261 return av_string;
00262
00263 }
00264
00265
00278 int validValue(const String &attributeValue,
00279 const XmlTagObject* xmlTag,
00280 Hashing<String, const XmlTagObject*>& ids) const {
00281
00282
00283 OgmlAttributeValueId stringType = getTypeOfString(attributeValue);
00284
00285 HashElement<String, const XmlTagObject*>* he;
00286
00287 int valid = vs_attValueErr;
00288
00289 switch(id) {
00290 case av_any: {
00291 valid = vs_valid;
00292 break;
00293 }
00294 case av_int: {
00295 if (stringType == av_int) valid = vs_valid;
00296 break;
00297 }
00298 case av_num: {
00299 if (stringType == av_num) valid = vs_valid;
00300 if (stringType == av_int) valid = vs_valid;
00301 break;
00302 }
00303 case av_bool: {
00304 if (stringType == av_bool) valid = vs_valid;
00305 break;
00306 }
00307 case av_string: {
00308 valid = vs_valid;
00309 break;
00310 }
00311 case av_hex: {
00312 if (stringType == av_hex) valid = vs_valid;
00313 if (stringType == av_int) valid = vs_valid;
00314 break;
00315 }
00316 case av_oct: {
00317 valid = vs_attValueErr;
00318 break;
00319 }
00320 case av_id: {
00321
00322 if( !(he = ids.lookup(attributeValue)) ) {
00323 ids.fastInsert(attributeValue, xmlTag);
00324 valid = vs_valid;
00325 }
00326 else valid = vs_idNotUnique;
00327 break;
00328 }
00329
00330
00331 case av_nodeIdRef: {
00332
00333 if( (he = ids.lookup(attributeValue)) && (he->info()->getName() == ogmlTagNames[t_node]) ) valid = vs_valid;
00334 else valid = vs_idRefErr;
00335 break;
00336 }
00337
00338 case av_edgeIdRef: {
00339
00340 if( (he = ids.lookup(attributeValue)) && (he->info()->getName() == ogmlTagNames[t_edge]) ) valid = vs_valid;
00341 else valid = vs_idRefErr;
00342 break;
00343 }
00344
00345 case av_labelIdRef: {
00346
00347 if( (he = ids.lookup(attributeValue)) && (he->info()->getName() == ogmlTagNames[t_label]) ) valid = vs_valid;
00348 else valid = vs_idRefErr;
00349 break;
00350 }
00351
00352 case av_sourceIdRef: {
00353
00354 if( (he = ids.lookup(attributeValue)) && (he->info()->getName() == ogmlTagNames[t_source]) ) valid = vs_valid;
00355 else valid = vs_idRefErr;
00356 break;
00357 }
00358
00359 case av_targetIdRef: {
00360
00361 if( (he = ids.lookup(attributeValue)) && (he->info()->getName() == ogmlTagNames[t_target]) ) valid = vs_valid;
00362 else valid = vs_idRefErr;
00363 break;
00364 }
00365
00366 case av_nodeStyleTemplateIdRef: {
00367
00368 if( (he = ids.lookup(attributeValue)) && (he->info()->getName() == ogmlTagNames[t_nodeStyleTemplate]) ) valid = vs_valid;
00369 else valid = vs_idRefErr;
00370 break;
00371 }
00372
00373 case av_edgeStyleTemplateIdRef: {
00374
00375 if( (he = ids.lookup(attributeValue)) && (he->info()->getName() == ogmlTagNames[t_edgeStyleTemplate]) ) valid = vs_valid;
00376 else valid = vs_idRefErr;
00377 break;
00378 }
00379
00380 case av_labelStyleTemplateIdRef: {
00381
00382 if( (he = ids.lookup(attributeValue)) && (he->info()->getName() == ogmlTagNames[t_labelStyleTemplate]) ) valid = vs_valid;
00383 else valid = vs_idRefErr;
00384 break;
00385 }
00386 case av_pointIdRef: {
00387
00388 if( (he = ids.lookup(attributeValue)) && (he->info()->getName() == ogmlTagNames[t_point]) ) valid = vs_valid;
00389 else valid = vs_idRefErr;
00390 break;
00391 }
00392 default: {
00393
00394 if(getValue() == attributeValue) valid = vs_valid;
00395 break;
00396 }
00397 }
00398
00399 return valid;
00400 }
00401
00402 };
00403
00404
00405
00406
00407
00408
00409
00410
00411
00414 class OgmlAttribute {
00415
00419 int id;
00422 List<OgmlAttributeValue*> values;
00423
00424 public:
00425
00426
00427 OgmlAttribute() : id(a_none), values() {}
00428 OgmlAttribute(int id) : values() {
00429 if(id>=0 && id<ATT_NUM) this->id = id;
00430 else this->id = a_none;
00431 }
00432
00433 ~OgmlAttribute() {}
00434
00435 const int& getId() const { return id; }
00436 const String& getName() const { return ogmlAttributeNames[id]; }
00437 const List<OgmlAttributeValue*>& getValueList() const { return values; }
00438
00439
00440 void setId(int id) {
00441 if(id>=0 && id<ATT_NUM) this->id = id;
00442 else this->id = a_none;
00443 }
00444
00451 void pushValues(Hashing<int, OgmlAttributeValue> &val, int key, ...) {
00452 va_list argp;
00453 int arg = key;
00454 HashElement<int, OgmlAttributeValue>* he;
00455 va_start(argp, key);
00456 while(arg!=-1) {
00457 if((he = val.lookup(arg))) values.pushBack( &(he->info()) );
00458 arg = va_arg(argp,int);
00459 }
00460 va_end(argp);
00461 }
00462
00465 void print(ostream &os) const {
00466 ListConstIterator<OgmlAttributeValue*> it;
00467 os << "\"" << getName() << "\"={ ";
00468 for(it = values.begin(); it.valid(); it++) {
00469 os << (**it).getValue() << " ";
00470 }
00471 os << "}\n";
00472 }
00473
00480 int validAttribute(const XmlAttributeObject &xmlAttribute,
00481 const XmlTagObject* xmlTag,
00482 Hashing<String, const XmlTagObject*>& ids) const {
00483
00484 int valid = vs_expAttNotFound;
00485
00486 if( xmlAttribute.getName() == getName() ) {
00487 ListConstIterator<OgmlAttributeValue*> it;
00488 for(it = values.begin(); it.valid(); it++) {
00489 if ( (valid = (**it).validValue( xmlAttribute.getValue(), xmlTag, ids )) == vs_valid ) break;
00490 }
00491 }
00492
00493 return valid;
00494 }
00495
00496
00497 };
00498
00499
00500
00501 ostream& operator<<(ostream& os, const OgmlAttribute& oa);
00502
00503
00504
00505
00506
00507
00508
00511 class OgmlTag {
00512
00516 int id;
00519 int minOccurs, maxOccurs;
00524 bool ignoreContent;
00527 List<OgmlAttribute*> compulsiveAttributes;
00531 List<OgmlAttribute*> choiceAttributes;
00534 List<OgmlAttribute*> optionalAttributes;
00535
00536 List<OgmlTag*> compulsiveTags;
00537
00538 List<OgmlTag*> choiceTags;
00539
00540 List<OgmlTag*> optionalTags;
00541
00542
00543 void printOwnedTags(ostream &os, int mode) const {
00544
00545 String s;
00546 const List<OgmlTag*> *list;
00547
00548 switch(mode) {
00549 case 0: {
00550 list = &compulsiveTags;
00551 s+="compulsive";
00552 break;
00553 }
00554 case 1: {
00555 list = &choiceTags;
00556 s+="selectable";
00557 break;
00558 }
00559 case 2: {
00560 list = &optionalTags;
00561 s+="optional";
00562 break;
00563 }
00564 }
00565
00566 if(list->empty()) os << "Tag \"<" << getName() <<">\" doesn't include " << s << " tag(s).\n";
00567 else {
00568 os << "Tag \"<" << getName() <<">\" includes the following " << s << " tag(s): \n";
00569 ListConstIterator<OgmlTag*> currTag;
00570 for(currTag = list->begin(); currTag.valid(); currTag++) os << "\t<" << (**currTag).getName() << ">\n";
00571 }
00572 }
00573
00574 void printOwnedAttributes(ostream &os, int mode) const {
00575
00576 String s;
00577 const List<OgmlAttribute*> *list;
00578
00579 switch(mode) {
00580 case 0: {
00581 list = &compulsiveAttributes;
00582 s+="compulsive";
00583 break;
00584 }
00585 case 1: {
00586 list = &choiceAttributes;
00587 s+="selectable";
00588 break;
00589 }
00590 case 2: {
00591 list = &optionalAttributes;
00592 s+="optional";
00593 break;
00594 }
00595 }
00596
00597 if(list->empty()) os << "Tag \"<" << getName() <<">\" doesn't include " << s << " attribute(s).\n";
00598 else {
00599 cout << "Tag \"<" << getName() <<">\" includes the following " << s << " attribute(s): \n";
00600 ListConstIterator<OgmlAttribute*> currAtt;
00601 for(currAtt = list->begin(); currAtt.valid(); currAtt++) os << "\t" << (**currAtt);
00602 }
00603 }
00604
00605
00606 public:
00607
00608 bool ownsCompulsiveTags() {
00609 return !compulsiveTags.empty();
00610 }
00611
00612 bool ownsChoiceTags() {
00613 return !choiceTags.empty();
00614 }
00615
00616 bool ownsOptionalTags() {
00617 return !optionalTags.empty();
00618 }
00619
00620 const List<OgmlTag*>& getCompulsiveTags() const {return compulsiveTags;}
00621
00622 const List<OgmlTag*>& getChoiceTags() const {return choiceTags;}
00623
00624 const List<OgmlTag*>& getOptionalTags() const {return optionalTags;}
00625
00626
00627 const int& getMinOccurs() const { return minOccurs; }
00628
00629 const int& getMaxOccurs() const { return maxOccurs; }
00630
00631 const bool& ignoresContent() const { return ignoreContent; }
00632
00633 void setMinOccurs(int occurs) { minOccurs = occurs; }
00634
00635 void setMaxOccurs(int occurs) { maxOccurs = occurs; }
00636
00637 void setIgnoreContent(bool ignore) { ignoreContent = ignore; }
00638
00639
00640 OgmlTag() : id(t_none), ignoreContent(0) { }
00641 OgmlTag(int id) : id(t_none), ignoreContent(0) {
00642 if(id>=0 && id<TAG_NUM) this->id = id;
00643 else id = a_none;
00644 }
00645
00646 ~OgmlTag() {}
00647
00648 const int& getId() const { return id; }
00649 const String& getName() const { return ogmlTagNames[id]; }
00650
00651 void setId(int id){
00652 if(id>=0 && id<TAG_NUM) this->id = id;
00653 else id = a_none;
00654 }
00655
00656
00657 void printOwnedTags(ostream& os) const {
00658 printOwnedTags(os, 0);
00659 printOwnedTags(os, 1);
00660 printOwnedTags(os, 2);
00661 }
00662
00663 void printOwnedAttributes(ostream& os) const {
00664 printOwnedAttributes(os, 0);
00665 printOwnedAttributes(os, 1);
00666 printOwnedAttributes(os, 2);
00667 }
00668
00675 void pushAttributes(int mode, Hashing<int, OgmlAttribute> &attrib, int key, ...) {
00676
00677 List<OgmlAttribute*>* list;
00678
00679 if(mode==0) list = &compulsiveAttributes;
00680 else if(mode==1) list = &choiceAttributes;
00681 else list = &optionalAttributes;
00682
00683 va_list argp;
00684 int arg = key;
00685 HashElement<int, OgmlAttribute>* he;
00686 va_start(argp, key);
00687 while(arg!=-1) {
00688 if((he = attrib.lookup(arg))) (*list).pushBack( &(he->info()) );
00689 arg = va_arg(argp,int);
00690 }
00691 va_end(argp);
00692 }
00693
00700 void pushTags(int mode, Hashing<int, OgmlTag> &tag, int key, ...) {
00701
00702 List<OgmlTag*>* list;
00703
00704 if(mode==0) list = &compulsiveTags;
00705 else if(mode==1) list = &choiceTags;
00706 else list = &optionalTags;
00707
00708 va_list argp;
00709 int arg = key;
00710 HashElement<int, OgmlTag>* he;
00711 va_start(argp, key);
00712
00713 while(arg!=-1) {
00714 if((he = tag.lookup(arg))) (*list).pushBack( &(he->info()) );
00715 arg = va_arg(argp,int);
00716 }
00717 va_end(argp);
00718 }
00719
00726 int validTag(const XmlTagObject &o,
00727 Hashing<String, const XmlTagObject*>& ids) const {
00728
00729 int valid = vs_unexpTag;
00730
00731 if( o.getName() == getName() ) {
00732
00733 ListConstIterator<OgmlAttribute*> it;
00734 XmlAttributeObject* att;
00735
00736
00737 if(!compulsiveAttributes.empty()) {
00738
00739 for(it = compulsiveAttributes.begin(); it.valid(); it++) {
00740
00741 if(!o.findXmlAttributeObjectByName((**it).getName(), att) ) return valid = vs_expAttNotFound;
00742 if( (valid = (**it).validAttribute(*att, &o, ids) ) <0 ) return valid;
00743
00744 att->setValid();
00745 }
00746
00747 }
00748
00749
00750 if(!choiceAttributes.empty()) {
00751
00752 bool tookChoice = false;
00753
00754 for(it = choiceAttributes.begin(); it.valid(); it++) {
00755
00756 if( o.findXmlAttributeObjectByName((**it).getName(), att) ) {
00757
00758 if( (valid = (**it).validAttribute(*att, &o, ids)) <0 ) return valid;
00759 tookChoice = true;
00760 att->setValid();
00761 }
00762 }
00763
00764 if(!tookChoice) return valid = vs_expAttNotFound;
00765
00766 }
00767
00768 if(!optionalAttributes.empty() && !o.isAttributeLess()) {
00769
00770
00771 for(it = optionalAttributes.begin(); it.valid(); it++) {
00772 if( o.findXmlAttributeObjectByName((**it).getName(), att) ) {
00773 if( (valid = (**it).validAttribute(*att, &o, ids)) <0 ) return valid;
00774 att->setValid();
00775 }
00776 }
00777 }
00778
00779
00780 att = o.m_pFirstAttribute;
00781 while(att) {
00782 if(!att->valid()) return valid = vs_unexpAtt;
00783 att = att->m_pNextAttribute;
00784 }
00785
00786 valid = vs_valid;
00787 }
00788
00789 return valid;
00790
00791 }
00792
00793
00794
00795
00796 };
00797
00798
00799
00800 ostream& operator<<(ostream& os, const OgmlTag& ot);
00801
00802
00803
00804
00805
00806
00807
00810 class OgmlParser {
00811
00812 private:
00815 static Hashing<int, OgmlTag> tags;
00816
00819 static Hashing<int, OgmlAttribute> attributes;
00820
00823 static Hashing<int, OgmlAttributeValue> attValues;
00824
00827 static bool hashTablesBuilt;
00828
00831 static void buildHashTables();
00832
00835 mutable GraphType graphType;
00836
00839 Hashing<String, const XmlTagObject*> ids;
00840
00848 int validate(const XmlTagObject *xmlTag, int ogmlTag);
00849
00853
00856 void printValidityInfo(const OgmlTag &ot,
00857 const XmlTagObject &xto,
00858 int valStatus,
00859 int line);
00860
00866
00867
00872 bool checkGraphType(const XmlTagObject *xmlTag) const;
00873
00876
00877 bool isGraphHierarchical(const XmlTagObject *xmlTag) const;
00878
00881 bool isNodeHierarchical(const XmlTagObject *xmlTag) const;
00882
00883 GraphType getGraphType() { return graphType; };
00884
00885
00886
00887
00888
00889 Hashing<String, node> m_nodes;
00890 Hashing<String, edge> m_edges;
00891 Hashing<String, cluster> m_clusters;
00892
00893
00894 Hashing<String, DPoint> points;
00895
00896
00897
00898
00899 Hashing<int, String> m_nodeIds;
00900 Hashing<int, String> m_edgeIds;
00901 Hashing<int, String> m_clusterIds;
00902
00903
00904
00905
00906
00907 bool buildGraph(Graph &G);
00908
00909
00910 bool buildCluster(
00911 const XmlTagObject *rootTag,
00912 Graph &G,
00913 ClusterGraph &CG);
00914
00915
00916 bool buildClusterRecursive(
00917 const XmlTagObject *xmlTag,
00918 cluster parent,
00919 Graph &G,
00920 ClusterGraph &CG);
00921
00922
00923
00924
00925
00926
00927
00928
00929
00930
00931
00932
00933
00934
00935
00936
00937
00938
00939
00940 bool buildAttributedClusterGraph(
00941 Graph &G,
00942 ClusterGraphAttributes &CGA,
00943 const XmlTagObject *root);
00944
00945
00946
00947
00948
00949
00950
00951
00952 bool setLabelsRecursive(
00953 Graph &G,
00954 ClusterGraphAttributes &CGA,
00955 XmlTagObject *root);
00956
00957
00958
00959
00960
00961
00962
00963
00964
00965
00966
00967
00968
00969
00970
00971 XmlTagObject* m_constraintsTag;
00972
00973
00974
00975 Hashing<String, OgmlNodeTemplate*> m_ogmlNodeTemplates;
00976 Hashing<String, OgmlEdgeTemplate*> m_ogmlEdgeTemplates;
00977
00978
00979
00980
00981 int getBrushPatternAsInt(String s);
00982
00983
00984 int getShapeAsInt(String s);
00985
00986
00987 String getNodeTemplateFromOgmlValue(String s);
00988
00989
00990 int getLineTypeAsInt(String s);
00991
00992
00993 int getImageStyleAsInt(String s);
00994
00995
00996 int getImageAlignmentAsInt(String s);
00997
00998
00999
01000
01001 int getArrowStyleAsInt(String s, String sot);
01002
01003
01004 GraphAttributes::EdgeArrow getArrowStyle(int i);
01005
01006
01007
01008
01009
01010
01011 String getLabelCaptionFromString(String str);
01012
01013
01014 bool getIdFromString(String str, int id);
01015
01016
01017 void validate(const char* fileName);
01018
01019 public:
01020
01021
01022 OgmlParser() { }
01023
01024 ~OgmlParser() {}
01025
01026
01027
01028
01029
01030
01031 bool read(
01032 const char* fileName,
01033 Graph &G,
01034 ClusterGraph &CG);
01035
01036 bool read(
01037 const char* fileName,
01038 Graph &G,
01039 ClusterGraph &CG,
01040 ClusterGraphAttributes &CGA);
01041
01042
01043
01044
01045
01046
01047
01048
01049
01050
01051
01052
01053
01054
01055
01056 };
01057
01058 }
01059
01060 #endif
01061