1 // file : xsd-frontend/transformations/anonymous.cxx 2 // copyright : Copyright (c) 2006-2017 Code Synthesis Tools CC 3 // license : GNU GPL v2 + exceptions; see accompanying LICENSE file 4 5 #include <xsd-frontend/transformations/anonymous.hxx> 6 7 #include <xsd-frontend/semantic-graph.hxx> 8 #include <xsd-frontend/traversal.hxx> 9 10 #include <iostream> 11 #include <sstream> 12 #include <typeinfo> 13 14 using std::wcerr; 15 using std::endl; 16 17 namespace XSDFrontend 18 { 19 namespace 20 { 21 using Transformations::AnonymousNameTranslator; 22 23 // 24 // 25 struct CompareMembers: Traversal::Element, 26 Traversal::Attribute, 27 Traversal::Any, 28 Traversal::AnyAttribute 29 { CompareMembersXSDFrontend::__anon00290d680111::CompareMembers30 CompareMembers (SemanticGraph::Nameable& m, bool& r) 31 : member_ (m), result_ (r) 32 { 33 } 34 35 virtual void traverseXSDFrontend::__anon00290d680111::CompareMembers36 traverse (SemanticGraph::Element& x) 37 { 38 using SemanticGraph::Element; 39 40 Element& y (dynamic_cast<Element&> (member_)); 41 42 // Check cardinalities. 43 // 44 if (x.min () != y.min () || x.max () != y.max ()) 45 return; 46 47 traverse_member (x); 48 } 49 50 virtual void traverseXSDFrontend::__anon00290d680111::CompareMembers51 traverse (SemanticGraph::Attribute& x) 52 { 53 using SemanticGraph::Attribute; 54 55 Attribute& y (dynamic_cast<Attribute&> (member_)); 56 57 // Check cardinalities. 58 // 59 if (x.optional_p () != y.optional_p ()) 60 return; 61 62 traverse_member (x); 63 } 64 65 virtual void traverse_memberXSDFrontend::__anon00290d680111::CompareMembers66 traverse_member (SemanticGraph::Member& x) 67 { 68 using SemanticGraph::Member; 69 70 Member& y (dynamic_cast<Member&> (member_)); 71 72 // Check name. 73 // 74 if (x.name () != y.name ()) 75 return; 76 77 // Check namespace. 78 // 79 if (x.qualified_p () || y.qualified_p ()) 80 { 81 if (!x.qualified_p () || !y.qualified_p ()) 82 return; 83 84 if (x.namespace_ ().name () != y.namespace_ ().name ()) 85 return; 86 } 87 88 // Check type. 89 // 90 // @@ What if types are anonymous and structurally equal? 91 // 92 if (&x.type () != &y.type ()) 93 return; 94 95 // Check default/fixed values. 96 // 97 if (x.default_p () != y.default_p () || x.fixed_p () != y.fixed_p ()) 98 return; 99 100 if (x.default_p () && x.value () != y.value ()) 101 return; 102 103 result_ = true; 104 } 105 106 virtual void traverseXSDFrontend::__anon00290d680111::CompareMembers107 traverse (SemanticGraph::Any&) 108 { 109 //@@ TODO 110 } 111 112 virtual void traverseXSDFrontend::__anon00290d680111::CompareMembers113 traverse (SemanticGraph::AnyAttribute&) 114 { 115 //@@ TODO 116 } 117 118 private: 119 SemanticGraph::Nameable& member_; 120 bool& result_; 121 }; 122 123 // Compare two types for structural equality. 124 // 125 struct CompareTypes: Traversal::List, 126 Traversal::Union, 127 Traversal::Enumeration, 128 Traversal::Complex 129 { CompareTypesXSDFrontend::__anon00290d680111::CompareTypes130 CompareTypes (SemanticGraph::Type& t, bool& r) 131 : type_ (t), result_ (r) 132 { 133 } 134 135 136 virtual void traverseXSDFrontend::__anon00290d680111::CompareTypes137 traverse (SemanticGraph::List&) 138 { 139 using SemanticGraph::List; 140 141 //List& y (dynamic_cast<List&> (type_)); 142 } 143 144 virtual void traverseXSDFrontend::__anon00290d680111::CompareTypes145 traverse (SemanticGraph::Union& x) 146 { 147 using SemanticGraph::Union; 148 149 Union& y (dynamic_cast<Union&> (type_)); 150 151 Union::ArgumentedIterator ix (x.argumented_begin ()), 152 iy (y.argumented_begin ()); 153 154 for (; ix != x.argumented_end () && iy != y.argumented_end (); 155 ++ix, ++iy) 156 { 157 // @@ Anon structurally equivalent. 158 // 159 if (&iy->type () != &ix->type ()) 160 return; 161 } 162 163 result_ = true; 164 } 165 166 virtual void traverseXSDFrontend::__anon00290d680111::CompareTypes167 traverse (SemanticGraph::Enumeration& x) 168 { 169 using SemanticGraph::Enumeration; 170 171 Enumeration& y (dynamic_cast<Enumeration&> (type_)); 172 173 // Bases should be the same. 174 // 175 if (&x.inherits ().base () != &y.inherits ().base ()) 176 return; 177 178 // Make sure facets match. 179 // 180 using SemanticGraph::Restricts; 181 182 Restricts& rx (dynamic_cast<Restricts&> (x.inherits ())); 183 Restricts& ry (dynamic_cast<Restricts&> (y.inherits ())); 184 185 if (rx.facets () != ry.facets ()) 186 return; 187 188 // Compare enumerators. 189 // 190 using SemanticGraph::Scope; 191 192 Scope::NamesIterator ix (x.names_begin ()), iy (y.names_begin ()); 193 for (; ix != x.names_end () && iy != y.names_end (); ++ix, ++iy) 194 { 195 if (ix->name () != iy->name ()) 196 return; 197 } 198 199 if (ix != x.names_end () || iy != y.names_end ()) 200 return; 201 202 result_ = true; 203 } 204 205 virtual void traverseXSDFrontend::__anon00290d680111::CompareTypes206 traverse (SemanticGraph::Complex& x) 207 { 208 using SemanticGraph::Complex; 209 210 Complex& y (dynamic_cast<Complex&> (type_)); 211 212 // Check inheritance. 213 // 214 if (x.inherits_p () || y.inherits_p ()) 215 { 216 // They both must inherits. 217 // 218 if (!x.inherits_p () || !y.inherits_p ()) 219 return; 220 221 // With the same kind of inheritance (restriction or extension). 222 // 223 if (typeid (x.inherits ()) != typeid (y.inherits ())) 224 return; 225 226 // Bases should be the same. 227 // 228 // @@ What if bases are anonymous? 229 // 230 if (&x.inherits ().base () != &y.inherits ().base ()) 231 return; 232 233 // If it is a restriction, make sure facets match. 234 // 235 using SemanticGraph::Restricts; 236 237 if (x.inherits ().is_a<Restricts> ()) 238 { 239 Restricts& rx (dynamic_cast<Restricts&> (x.inherits ())); 240 Restricts& ry (dynamic_cast<Restricts&> (y.inherits ())); 241 242 if (rx.facets () != ry.facets ()) 243 return; 244 } 245 } 246 247 // Check the member list. 248 // 249 // @@ Ignoring compositors at the moment. 250 // 251 using SemanticGraph::Scope; 252 253 Scope::NamesIterator ix (x.names_begin ()), iy (y.names_begin ()); 254 for (; ix != x.names_end () && iy != y.names_end (); ++ix, ++iy) 255 { 256 if (typeid (ix->named ()) != typeid (iy->named ())) 257 return; 258 259 bool equal (false); 260 CompareMembers t (iy->named (), equal); 261 t.dispatch (ix->named ()); 262 263 if (!equal) 264 return; 265 } 266 267 if (ix != x.names_end () || iy != y.names_end ()) 268 return; 269 270 result_ = true; 271 } 272 273 private: 274 SemanticGraph::Type& type_; 275 bool& result_; 276 }; 277 278 // 279 // 280 class Context 281 { 282 public: Context(SemanticGraph::Schema & schema_,SemanticGraph::Path const & file,AnonymousNameTranslator & trans_,bool du)283 Context (SemanticGraph::Schema& schema_, 284 SemanticGraph::Path const& file, 285 AnonymousNameTranslator& trans_, 286 bool du) 287 : schema_path_ (file), 288 ns_ (0), 289 failed_ (false), 290 trans (trans_), 291 detect_unstable (du), 292 schema (schema_), 293 schema_path (schema_path_), 294 ns (ns_), 295 failed (failed_) 296 { 297 298 } 299 300 protected: Context(Context & c)301 Context (Context& c) 302 : trans (c.trans), 303 detect_unstable (c.detect_unstable), 304 schema (c.schema), 305 schema_path (c.schema_path), 306 ns (c.ns), 307 failed (c.failed) 308 { 309 } 310 311 public: 312 313 bool structurally_equal(SemanticGraph::Type & x,SemanticGraph::Type & y)314 structurally_equal (SemanticGraph::Type& x, SemanticGraph::Type& y) 315 { 316 if (typeid (x) != typeid (y)) 317 return false; 318 319 bool r (false); 320 CompareTypes t (y, r); 321 t.dispatch (x); 322 return r; 323 } 324 325 struct UnstableConflict 326 { UnstableConflictXSDFrontend::__anon00290d680111::Context::UnstableConflict327 UnstableConflict (SemanticGraph::Type& type) 328 : type_ (type) 329 { 330 } 331 332 SemanticGraph::Type& typeXSDFrontend::__anon00290d680111::Context::UnstableConflict333 type () const 334 { 335 return type_; 336 } 337 338 private: 339 SemanticGraph::Type& type_; 340 }; 341 342 SemanticGraph::Type* conflict(String const & name)343 conflict (String const& name) 344 { 345 using SemanticGraph::Type; 346 using SemanticGraph::Schema; 347 348 if (Type* t1 = find (schema, name)) 349 { 350 // Check if this is a stable conflict. A conflict is unstable 351 // if a conflicting type is visible from the root schema but 352 // is not visible from the schema where the conflicting 353 // element is defined. 354 // 355 if (detect_unstable) 356 { 357 Schema& s (dynamic_cast<Schema&> (ns->scope ())); 358 359 Type* t2 (find (s, name)); 360 361 if (t1 != t2) 362 throw UnstableConflict (*t1); 363 } 364 365 return t1; 366 } 367 368 return 0; 369 } 370 371 SemanticGraph::Type* find(SemanticGraph::Schema & schema,String const & name)372 find (SemanticGraph::Schema& schema, String const& name) 373 { 374 using SemanticGraph::Type; 375 using SemanticGraph::Scope; 376 using SemanticGraph::Namespace; 377 378 String ns_name (ns->name ()); 379 380 // Get all namespaces across include/import hierarchy with 381 // our namespace name. 382 // 383 Scope::NamesIteratorPair nip (schema.find (ns_name)); 384 385 for (; nip.first != nip.second; ++nip.first) 386 { 387 Namespace& ns (dynamic_cast<Namespace&> (nip.first->named ())); 388 389 Scope::NamesIteratorPair types (ns.find (name)); 390 391 for (; types.first != types.second; ++types.first) 392 { 393 if (Type* t = dynamic_cast<Type*> (&types.first->named ())) 394 { 395 return t; 396 } 397 } 398 } 399 400 return 0; 401 } 402 403 public: 404 SemanticGraph::Path path(SemanticGraph::Nameable & n)405 path (SemanticGraph::Nameable& n) 406 { 407 using SemanticGraph::Scope; 408 using SemanticGraph::Schema; 409 using SemanticGraph::Uses; 410 411 Schema* schema (0); 412 413 for (Scope* s (dynamic_cast<Scope*> (&n) 414 ? dynamic_cast<Scope*> (&n) : &n.scope ());; 415 s = &s->scope ()) 416 { 417 if ((schema = dynamic_cast<Schema*> (s))) 418 break; 419 } 420 421 if (!schema->used_p ()) 422 return schema_path; 423 424 Uses& u (*schema->used_begin ()); 425 return u.path (); 426 } 427 428 public: 429 String xpath(SemanticGraph::Nameable & n)430 xpath (SemanticGraph::Nameable& n) 431 { 432 if (dynamic_cast<SemanticGraph::Namespace*> (&n) != 0) 433 return L"<namespace-level>"; // There is a bug if you see this. 434 435 assert (n.named_p ()); 436 437 SemanticGraph::Scope& scope (n.scope ()); 438 439 if (dynamic_cast<SemanticGraph::Namespace*> (&scope) != 0) 440 return n.name (); 441 442 return xpath (scope) + L"/" + n.name (); 443 } 444 445 private: 446 SemanticGraph::Path const schema_path_; 447 SemanticGraph::Namespace* ns_; 448 bool failed_; 449 450 public: 451 AnonymousNameTranslator& trans; 452 bool detect_unstable; 453 454 public: 455 SemanticGraph::Schema& schema; 456 SemanticGraph::Path const& schema_path; 457 SemanticGraph::Namespace*& ns; 458 bool& failed; 459 }; 460 461 462 // Go into implied/included/imported schemas while making sure 463 // we don't process the same stuff more than once. 464 // 465 struct Uses: Traversal::Uses 466 { 467 virtual void traverseXSDFrontend::__anon00290d680111::Uses468 traverse (Type& u) 469 { 470 SemanticGraph::Schema& s (u.schema ()); 471 472 if (!s.context ().count ("xsd-frontend-anonymous-seen")) 473 { 474 s.context ().set ("xsd-frontend-anonymous-seen", true); 475 Traversal::Uses::traverse (u); 476 } 477 } 478 }; 479 480 // Keep track which namespace we are in. 481 // 482 struct Namespace: Traversal::Namespace 483 { NamespaceXSDFrontend::__anon00290d680111::Namespace484 Namespace (SemanticGraph::Namespace*& ns) 485 : ns_ (ns) 486 { 487 } 488 489 void preXSDFrontend::__anon00290d680111::Namespace490 pre (SemanticGraph::Namespace& ns) 491 { 492 ns_ = &ns; 493 } 494 495 void postXSDFrontend::__anon00290d680111::Namespace496 post (SemanticGraph::Namespace&) 497 { 498 ns_ = 0; 499 } 500 501 private: 502 SemanticGraph::Namespace*& ns_; 503 }; 504 505 // 506 // 507 struct Type: Traversal::List, 508 Traversal::Union, 509 Traversal::Complex, 510 protected virtual Context 511 { TypeXSDFrontend::__anon00290d680111::Type512 Type (Context& c) 513 : Context (c) 514 { 515 } 516 517 virtual void traverseXSDFrontend::__anon00290d680111::Type518 traverse (SemanticGraph::List& l) 519 { 520 SemanticGraph::Type& t (l.argumented ().type ()); 521 522 //@@ This IDREF stuff is really ugly! 523 // 524 if (!t.named_p () && 525 !t.is_a<SemanticGraph::Fundamental::IdRef> () && 526 !t.is_a<SemanticGraph::Fundamental::IdRefs> ()) 527 { 528 try 529 { 530 // Run the name through the translation service. 531 // 532 SemanticGraph::Path file (path (l)); 533 file.normalize (); 534 String file_str; 535 536 // Try to use the portable representation of the path. If that 537 // fails, fall back to the native representation. 538 // 539 try 540 { 541 file_str = file.posix_string (); 542 } 543 catch (SemanticGraph::InvalidPath const&) 544 { 545 file_str = file.string (); 546 } 547 548 String name ( 549 trans.translate ( 550 file_str, ns->name (), l.name () + L"_item", xpath (l))); 551 552 // Make sure the name is unique. 553 // 554 unsigned long n (1); 555 String escaped (name); 556 557 while (conflict (escaped)) 558 { 559 std::wostringstream os; 560 os << n++; 561 escaped = name + os.str (); 562 } 563 564 t.context ().set ("anonymous", true); 565 schema.new_edge<SemanticGraph::Names> (*ns, t, escaped); 566 } 567 catch (UnstableConflict const& ex) 568 { 569 SemanticGraph::Type& t (ex.type ()); 570 571 wcerr << l.file () << ":" << l.line () << ":" << l.column () 572 << ": error: list type name '" << xpath (l) << "' " 573 << "creates an unstable conflict when used as a base " 574 << "for the item type name" 575 << endl; 576 577 wcerr << t.file () << ":" << t.line () << ":" << t.column () 578 << ": info: conflicting type is defined here" << endl; 579 580 wcerr << l.file () << ":" << l.line () << ":" << l.column () 581 << ": info: " 582 << "use --anonymous-regex to resolve this conflict" 583 << endl; 584 585 wcerr << l.file () << ":" << l.line () << ":" << l.column () 586 << ": info: " 587 << "and don't forget to pass the same option when " 588 << "translating '" << l.file ().leaf () << "' and all " 589 << "the schemas that refer to it" << endl; 590 591 failed = true; 592 } 593 } 594 } 595 596 virtual void traverseXSDFrontend::__anon00290d680111::Type597 traverse (SemanticGraph::Union& u) 598 { 599 String file_str; 600 601 for (SemanticGraph::Union::ArgumentedIterator i ( 602 u.argumented_begin ()); i != u.argumented_end (); ++i) 603 { 604 SemanticGraph::Type& t (i->type ()); 605 606 if (!t.named_p () && 607 !t.is_a<SemanticGraph::Fundamental::IdRef> () && 608 !t.is_a<SemanticGraph::Fundamental::IdRefs> ()) 609 { 610 try 611 { 612 // Run the name through the translation service. 613 // 614 615 if (!file_str) 616 { 617 SemanticGraph::Path file (path (u)); 618 file.normalize (); 619 620 // Try to use the portable representation of the path. If 621 // that fails, fall back to the native representation. 622 // 623 try 624 { 625 file_str = file.posix_string (); 626 } 627 catch (SemanticGraph::InvalidPath const&) 628 { 629 file_str = file.string (); 630 } 631 } 632 633 String name ( 634 trans.translate ( 635 file_str, ns->name (), u.name () + L"_member", xpath (u))); 636 637 // Make sure the name is unique. 638 // 639 unsigned long n (1); 640 String escaped (name); 641 642 while (conflict (escaped)) 643 { 644 std::wostringstream os; 645 os << n++; 646 escaped = name + os.str (); 647 } 648 649 t.context ().set ("anonymous", true); 650 schema.new_edge<SemanticGraph::Names> (*ns, t, escaped); 651 } 652 catch (UnstableConflict const& ex) 653 { 654 SemanticGraph::Type& t (ex.type ()); 655 656 wcerr << u.file () << ":" << u.line () << ":" << u.column () 657 << ": error: union type name '" << xpath (u) << "' " 658 << "creates an unstable conflict when used as a base " 659 << "for the member type name" 660 << endl; 661 662 wcerr << t.file () << ":" << t.line () << ":" << t.column () 663 << ": info: conflicting type is defined here" << endl; 664 665 wcerr << u.file () << ":" << u.line () << ":" << u.column () 666 << ": info: " 667 << "use --anonymous-regex to resolve this conflict" 668 << endl; 669 670 wcerr << u.file () << ":" << u.line () << ":" << u.column () 671 << ": info: " 672 << "and don't forget to pass the same option when " 673 << "translating '" << u.file ().leaf () << "' and all " 674 << "the schemas that refer to it" << endl; 675 676 failed = true; 677 } 678 } 679 } 680 } 681 682 virtual void traverseXSDFrontend::__anon00290d680111::Type683 traverse (SemanticGraph::Complex& c) 684 { 685 if (!c.inherits_p ()) 686 return; 687 688 SemanticGraph::Type& t (c.inherits ().base ()); 689 690 //@@ This IDREF stuff is really ugly! 691 // 692 if (!t.named_p () && 693 !t.is_a<SemanticGraph::Fundamental::IdRef> () && 694 !t.is_a<SemanticGraph::Fundamental::IdRefs> ()) 695 { 696 try 697 { 698 // Run the name through the translation service. 699 // 700 SemanticGraph::Path file (path (c)); 701 file.normalize (); 702 String file_str; 703 704 // Try to use the portable representation of the path. If that 705 // fails, fall back to the native representation. 706 // 707 try 708 { 709 file_str = file.posix_string (); 710 } 711 catch (SemanticGraph::InvalidPath const&) 712 { 713 file_str = file.string (); 714 } 715 716 String name ( 717 trans.translate ( 718 file_str, ns->name (), c.name () + L"_base", xpath (c))); 719 720 // Make sure the name is unique. 721 // 722 unsigned long n (1); 723 String escaped (name); 724 725 while (conflict (escaped)) 726 { 727 std::wostringstream os; 728 os << n++; 729 escaped = name + os.str (); 730 } 731 732 t.context ().set ("anonymous", true); 733 schema.new_edge<SemanticGraph::Names> (*ns, t, escaped); 734 } 735 catch (UnstableConflict const& ex) 736 { 737 SemanticGraph::Type& t (ex.type ()); 738 739 wcerr << c.file () << ":" << c.line () << ":" << c.column () 740 << ": error: simple type name '" << xpath (c) << "' " 741 << "creates an unstable conflict when used as a base " 742 << "for the base type name" 743 << endl; 744 745 wcerr << t.file () << ":" << t.line () << ":" << t.column () 746 << ": info: conflicting type is defined here" << endl; 747 748 wcerr << c.file () << ":" << c.line () << ":" << c.column () 749 << ": info: " 750 << "use --anonymous-regex to resolve this conflict" 751 << endl; 752 753 wcerr << c.file () << ":" << c.line () << ":" << c.column () 754 << ": info: " 755 << "and don't forget to pass the same option when " 756 << "translating '" << c.file ().leaf () << "' and all " 757 << "the schemas that refer to it" << endl; 758 759 failed = true; 760 } 761 } 762 } 763 }; 764 765 766 // 767 // 768 struct Member: Traversal::Element, 769 Traversal::Attribute, 770 protected virtual Context 771 { MemberXSDFrontend::__anon00290d680111::Member772 Member (Context& c) 773 : Context (c) 774 { 775 } 776 777 virtual void traverseXSDFrontend::__anon00290d680111::Member778 traverse (SemanticGraph::Element& e) 779 { 780 SemanticGraph::Type& t (e.type ()); 781 782 //@@ This IDREF stuff is really ugly! 783 // 784 if (!t.named_p () && 785 !t.is_a<SemanticGraph::Fundamental::IdRef> () && 786 !t.is_a<SemanticGraph::Fundamental::IdRefs> ()) 787 { 788 try 789 { 790 traverse_ (e); 791 } 792 catch (UnstableConflict const& ex) 793 { 794 SemanticGraph::Type& t (ex.type ()); 795 796 wcerr << e.file () << ":" << e.line () << ":" << e.column () 797 << ": error: element name '" << xpath (e) << "' " 798 << "creates an unstable conflict when used as a type name" 799 << endl; 800 801 wcerr << t.file () << ":" << t.line () << ":" << t.column () 802 << ": info: conflicting type is defined here" << endl; 803 804 wcerr << e.file () << ":" << e.line () << ":" << e.column () 805 << ": info: " 806 << "use --anonymous-regex to resolve this conflict" 807 << endl; 808 809 wcerr << e.file () << ":" << e.line () << ":" << e.column () 810 << ": info: " 811 << "and don't forget to pass the same option when " 812 << "translating '" << e.file ().leaf () << "' and all " 813 << "the schemas that refer to it" << endl; 814 815 failed = true; 816 } 817 } 818 } 819 820 virtual void traverseXSDFrontend::__anon00290d680111::Member821 traverse (SemanticGraph::Attribute& a) 822 { 823 SemanticGraph::Type& t (a.type ()); 824 825 //@@ This IDREF stuff us really ugly! 826 // 827 if (!t.named_p () && 828 !t.is_a<SemanticGraph::Fundamental::IdRef> () && 829 !t.is_a<SemanticGraph::Fundamental::IdRefs> ()) 830 { 831 try 832 { 833 traverse_ (a); 834 } 835 catch (UnstableConflict const& ex) 836 { 837 SemanticGraph::Type& t (ex.type ()); 838 839 wcerr << a.file () << ":" << a.line () << ":" << a.column () 840 << ": error: attribute name '" << xpath (a) << "' " 841 << "creates an unstable conflict when used as a type name" 842 << endl; 843 844 wcerr << t.file () << ":" << t.line () << ":" << t.column () 845 << ": info: conflicting type is defined here" << endl; 846 847 wcerr << a.file () << ":" << a.line () << ":" << a.column () 848 << ": info: " 849 << "use --anonymous-regex to resolve this conflict" 850 << endl; 851 852 wcerr << a.file () << ":" << a.line () << ":" << a.column () 853 << ": info: " 854 << "and don't forget to pass the same option when " 855 << "translating '" << a.file ().leaf () << "' and all " 856 << "the schemas that refer to it" << endl; 857 858 failed = true; 859 } 860 } 861 } 862 863 void traverse_XSDFrontend::__anon00290d680111::Member864 traverse_ (SemanticGraph::Member& m) 865 { 866 using SemanticGraph::Type; 867 868 Type& t (m.type ()); 869 870 // Normally this will be the member which also "defined" the type. 871 // However, in some cases of cyclic schema inclusion, this does 872 // not happen. As a result we need an extra check that will make 873 // sure we create the Names edge in the same Schema node as the 874 // one which contains the member which initially defined this 875 // type. See the cyclic-inclusion test for an example. 876 // 877 878 // Find the first member that this type classifies. 879 // 880 for (Type::ClassifiesIterator i (t.classifies_begin ()); 881 i != t.classifies_end (); ++i) 882 { 883 SemanticGraph::Instance& inst (i->instance ()); 884 885 if (inst.is_a<SemanticGraph::Member> ()) 886 { 887 // If it is the same member as the one we are traversing, 888 // then continue. 889 // 890 if (&inst == &m) 891 break; 892 else 893 return; 894 } 895 } 896 897 // Run the name through the translation service. 898 // 899 SemanticGraph::Path file (path (m)); 900 file.normalize (); 901 String file_str; 902 903 // Try to use the portable representation of the path. If that 904 // fails, fall back to the native representation. 905 // 906 try 907 { 908 file_str = file.posix_string (); 909 } 910 catch (SemanticGraph::InvalidPath const&) 911 { 912 file_str = file.string (); 913 } 914 915 String name ( 916 trans.translate (file_str, ns->name (), m.name (), xpath (m))); 917 918 // Check if this name conflicts. 919 // 920 unsigned long n (1); 921 String escaped (name); 922 923 while (SemanticGraph::Type* other = conflict (escaped)) 924 { 925 // First see if we should just use the other type. It should 926 // also have been anonymous and structurally equal to our type. 927 // 928 if (other->context ().count ("anonymous")) 929 { 930 if (structurally_equal (t, *other)) 931 { 932 // Reset the elements that are classified by this type to point 933 // to the other type. 934 // 935 for (Type::ClassifiesIterator i (t.classifies_begin ()); 936 i != t.classifies_end (); ++i) 937 { 938 schema.reset_right_node (*i, *other); 939 } 940 941 //wcerr << "equal " << name << endl; 942 return; 943 } 944 //else 945 //wcerr << "unequal " << name << endl; 946 } 947 948 std::wostringstream os; 949 os << n++; 950 escaped = name + os.str (); 951 } 952 953 t.context ().set ("anonymous", true); 954 schema.new_edge<SemanticGraph::Names> (*ns, t, escaped); 955 } 956 }; 957 } 958 959 namespace Transformations 960 { 961 Anonymous:: Anonymous(AnonymousNameTranslator & trans)962 Anonymous (AnonymousNameTranslator& trans) 963 : trans_ (trans) 964 { 965 } 966 967 void Anonymous:: transform(SemanticGraph::Schema & s,SemanticGraph::Path const & f,bool duc)968 transform (SemanticGraph::Schema& s, 969 SemanticGraph::Path const& f, 970 bool duc) 971 { 972 Context ctx (s, f, trans_, duc); 973 974 Traversal::Schema schema; 975 Uses uses; 976 977 schema >> uses >> schema; 978 979 Traversal::Names schema_names; 980 Namespace ns (ctx.ns); 981 Traversal::Names ns_names_member; 982 Traversal::Names ns_names_type; 983 984 schema >> schema_names >> ns; 985 ns >> ns_names_member; 986 ns >> ns_names_type; 987 988 Type type (ctx); 989 ns_names_type >> type; 990 991 Traversal::Scope scope; // Goes to both types and groups. 992 Member member (ctx); 993 994 ns_names_member >> scope; 995 ns_names_member >> member; 996 997 Traversal::Names names; 998 999 scope >> names >> member; 1000 1001 // Some twisted schemas do recusive inclusions. 1002 // 1003 s.context ().set ("xsd-frontend-anonymous-seen", true); 1004 1005 schema.dispatch (s); 1006 1007 if (ctx.failed) 1008 throw Failed (); 1009 } 1010 1011 AnonymousNameTranslator:: ~AnonymousNameTranslator()1012 ~AnonymousNameTranslator () 1013 { 1014 } 1015 } 1016 } 1017