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