1 // file      : xsd/cxx/tree/serialization-source.cxx
2 // copyright : Copyright (c) 2005-2017 Code Synthesis Tools CC
3 // license   : GNU GPL v2 + exceptions; see accompanying LICENSE file
4 
5 #include <cxx/tree/serialization-source.hxx>
6 
7 #include <xsd-frontend/semantic-graph.hxx>
8 #include <xsd-frontend/traversal.hxx>
9 
10 namespace CXX
11 {
12   namespace Tree
13   {
14     namespace
15     {
16       enum schema_type
17       {
18         st_other,
19         st_double,
20         st_decimal
21       };
22 
23       enum schema_type
schema_type(SemanticGraph::Type & t)24       schema_type (SemanticGraph::Type& t)
25       {
26         if (t.is_a<SemanticGraph::Fundamental::Double> ())
27           return st_double;
28         else if (t.is_a<SemanticGraph::Fundamental::Decimal> ())
29           return st_decimal;
30         else
31           return st_other;
32       }
33 
34 
35       //
36       //
37       struct List: Traversal::List, Context
38       {
ListCXX::Tree::__anon7e6bba720111::List39         List (Context& c)
40             : Context (c)
41         {
42         }
43 
44         virtual void
traverseCXX::Tree::__anon7e6bba720111::List45         traverse (Type& l)
46         {
47           String name (ename (l));
48 
49           // If renamed name is empty then we do not need to generate
50           // anything for this type.
51           //
52           if (renamed_type (l, name) && !name)
53             return;
54 
55           SemanticGraph::Type& item_type (l.argumented ().type ());
56           String base (L"::xsd::cxx::tree::list< " +
57                        item_type_name (item_type) + L", " + char_type);
58 
59           if (item_type.is_a<SemanticGraph::Fundamental::Double> ())
60             base += L", ::xsd::cxx::tree::schema_type::double_";
61           else if (item_type.is_a<SemanticGraph::Fundamental::Decimal> ())
62             base += L", ::xsd::cxx::tree::schema_type::decimal";
63 
64           base += L" >";
65 
66           // operator<< (xercesc::DOMElement)
67           //
68           os << "void" << endl
69              << "operator<< (" << xerces_ns << "::DOMElement& e, " <<
70             "const " << name << "& i)"
71              << "{"
72              << "e << static_cast< const " << base << "& > (i);"
73              << "}";
74 
75           // operator<< (xercesc::DOMAttr)
76           //
77           os << "void" << endl
78              << "operator<< (" << xerces_ns << "::DOMAttr& a, " <<
79             "const " << name << "& i)"
80              << "{"
81              << "a << static_cast< const " << base << "& > (i);"
82              << "}";
83 
84           // operator<< (list_stream)
85           //
86           os << "void" << endl
87              << "operator<< (" << list_stream_type << "& l," << endl
88              << "const " << name << "& i)"
89              << "{"
90              << "l << static_cast< const " << base << "& > (i);"
91              << "}";
92 
93           // Register with type factory map. If this type is anonymous
94           // but substitutes, then it will be registered as part of the
95           // substitution registration.
96           //
97           if (polymorphic && polymorphic_p (l) && !anonymous_p (l))
98           {
99             // Note that we are using the original type name.
100             //
101             String const& name (ename (l));
102 
103             os << "static" << endl
104                << "const ::xsd::cxx::tree::type_serializer_initializer< " <<
105                 poly_plate << ", " << char_type << ", " << name << " >" << endl
106                << "_xsd_" << name << "_type_serializer_init (" << endl
107                << strlit (l.name ()) << "," << endl
108                << strlit (xml_ns_name (l)) << ");"
109                << endl
110                << endl;
111           }
112         }
113 
114       private:
115         String
item_type_nameCXX::Tree::__anon7e6bba720111::List116         item_type_name (SemanticGraph::Type& t)
117         {
118           std::wostringstream o;
119 
120           MemberTypeName type (*this, o);
121           type.dispatch (t);
122 
123           return o.str ();
124         }
125       };
126 
127 
128       struct Union: Traversal::Union, Context
129       {
UnionCXX::Tree::__anon7e6bba720111::Union130         Union (Context& c)
131             : Context (c)
132         {
133         }
134 
135         virtual void
traverseCXX::Tree::__anon7e6bba720111::Union136         traverse (Type& u)
137         {
138           String name (ename (u));
139 
140           // If renamed name is empty then we do not need to generate
141           // anything for this type.
142           //
143           if (renamed_type (u, name) && !name)
144             return;
145 
146           String const& base (xs_string_type);
147 
148           // operator<< (xercesc::DOMElement)
149           //
150           os << "void" << endl
151              << "operator<< (" << xerces_ns << "::DOMElement& e, " <<
152             "const " << name << "& i)"
153              << "{"
154              << "e << static_cast< const " << base << "& > (i);"
155              << "}";
156 
157           // operator<< (xercesc::DOMAttr)
158           //
159           os << "void" << endl
160              << "operator<< (" << xerces_ns << "::DOMAttr& a, " <<
161             "const " << name << "& i)"
162              << "{"
163              << "a << static_cast< const " << base << "& > (i);"
164              << "}";
165 
166           // operator<< (list_stream)
167           //
168           os << "void" << endl
169              << "operator<< (" << list_stream_type << "& l," << endl
170              << "const " << name << "& i)"
171              << "{"
172              << "l << static_cast< const " << base << "& > (i);"
173              << "}";
174 
175           // Register with type factory map. If this type is anonymous
176           // but substitutes, then it will be registered as part of the
177           // substitution registration.
178           //
179           if (polymorphic && polymorphic_p (u) && !anonymous_p (u))
180           {
181             // Note that we are using the original type name.
182             //
183             String const& name (ename (u));
184 
185             os << "static" << endl
186                << "const ::xsd::cxx::tree::type_serializer_initializer< " <<
187                 poly_plate << ", " << char_type << ", " << name << " >" << endl
188                << "_xsd_" << name << "_type_serializer_init (" << endl
189                << strlit (u.name ()) << "," << endl
190                << strlit (xml_ns_name (u)) << ");"
191                << endl
192                << endl;
193           }
194         }
195       };
196 
197 
198       struct Enumeration: Traversal::Enumeration, Context
199       {
EnumerationCXX::Tree::__anon7e6bba720111::Enumeration200         Enumeration (Context& c)
201             : Context (c), base_ (c)
202         {
203           inherits_base_ >> base_;
204         }
205 
206         virtual void
traverseCXX::Tree::__anon7e6bba720111::Enumeration207         traverse (Type& e)
208         {
209           String name (ename (e));
210 
211           // If renamed name is empty then we do not need to generate
212           // anything for this type.
213           //
214           if (renamed_type (e, name) && !name)
215             return;
216 
217           // operator<< (xercesc::DOMElement)
218           //
219           os << "void" << endl
220              << "operator<< (" << xerces_ns << "::DOMElement& e, " <<
221             "const " << name << "& i)"
222              << "{"
223              << "e << static_cast< const ";
224 
225           inherits (e, inherits_base_);
226 
227           os << "& > (i);"
228              << "}";
229 
230 
231           // operator<< (xercesc::DOMAttr)
232           //
233           os << "void" << endl
234              << "operator<< (" << xerces_ns << "::DOMAttr& a, " <<
235             "const " << name << "& i)"
236              << "{"
237              << "a << static_cast< const ";
238 
239           inherits (e, inherits_base_);
240 
241           os << "& > (i);"
242              << "}";
243 
244 
245           // operator<< (list_stream)
246           //
247           os << "void" << endl
248              << "operator<< (" << list_stream_type << "& l," << endl
249              << "const " << name << "& i)"
250              << "{"
251              << "l << static_cast< const ";
252 
253           inherits (e, inherits_base_);
254 
255           os << "& > (i);"
256              << "}";
257 
258 
259           // Register with type factory map. If this type is anonymous
260           // but substitutes, then it will be registered as part of the
261           // substitution registration.
262           //
263           if (polymorphic && polymorphic_p (e) && !anonymous_p (e))
264           {
265             // Note that we are using the original type name.
266             //
267             String const& name (ename (e));
268 
269             os << "static" << endl
270                << "const ::xsd::cxx::tree::type_serializer_initializer< " <<
271                 poly_plate << ", " << char_type << ", " << name << " >" << endl
272                << "_xsd_" << name << "_type_serializer_init (" << endl
273                << strlit (e.name ()) << "," << endl
274                << strlit (xml_ns_name (e)) << ");"
275                << endl
276                << endl;
277           }
278         }
279 
280       private:
281         Traversal::Inherits inherits_base_;
282         BaseTypeName base_;
283       };
284 
285       struct Element: Traversal::Element, Context
286       {
ElementCXX::Tree::__anon7e6bba720111::Element287         Element (Context& c, String const& scope_)
288             : Context (c), scope (scope_)
289         {
290         }
291 
292         virtual void
traverseCXX::Tree::__anon7e6bba720111::Element293         traverse (Type& e)
294         {
295           if (skip (e))
296             return;
297 
298           SemanticGraph::Complex& c (
299             dynamic_cast<SemanticGraph::Complex&> (e.scope ()));
300 
301           bool ordered (ordered_p (c));
302 
303           String const& aname (eaname (e));
304           String ns (e.qualified_p () ? e.namespace_ ().name () : "");
305           String type (scope + L"::" + etype (e));
306 
307           // Check if we need to handle xsi:type and substitution groups.
308           // If this element's type is anonymous then we don't need to do
309           // anything. Note that if the type is anonymous then it can't be
310           // derived from which makes it impossible to substitute or
311           // dynamically-type with xsi:type.
312           //
313           SemanticGraph::Type& t (e.type ());
314           bool poly (polymorphic && polymorphic_p (t) && !anonymous_p (t));
315 
316           os << "// " << comment (e.name ()) << endl
317              << "//" << endl;
318 
319           if (ordered)
320             os << "case " << scope << "::" <<
321               e.context ().get<String> ("ordered-id-name") << ":"
322                << "{";
323 
324           if (poly)
325           {
326             os << (ordered ? "" : "{")
327                << "::xsd::cxx::tree::type_serializer_map< " << char_type
328                << " >& tsm (" << endl
329                << "::xsd::cxx::tree::type_serializer_map_instance< " <<
330               poly_plate << ", " << char_type << " > ());"
331                << endl;
332           }
333 
334           if (max (e) != 1)
335           {
336             // sequence
337             //
338             if (ordered)
339               os << "const " << type << "& x (i." << aname <<
340                 " ()[b->index]);"
341                  << endl;
342             else
343               os << "for (" << scope << "::" << econst_iterator (e) << endl
344                  << "b (i." << aname << " ().begin ()), " <<
345                 "n (i." << aname << " ().end ());" << endl
346                  << "b != n; ++b)"
347                  << "{";
348 
349             char const* x (ordered ? "x" : "*b");
350 
351             if (poly)
352             {
353               os << "if (typeid (" << type << ") == typeid (" << x << "))"
354                  << "{"
355                  << xerces_ns << "::DOMElement& s (" << endl
356                  << "::xsd::cxx::xml::dom::create_element (" << endl
357                  << strlit (e.name ()) << "," << endl
358                  << (ns ? strlit (ns) + L",\n" : L"")
359                  << "e));"
360                  << endl
361                  << "s << " << x << ";"
362                  << "}"
363                  << "else" << endl
364                  << "tsm.serialize (" << endl
365                  << strlit (e.name ()) << "," << endl
366                  << strlit (ns) << "," << endl
367                  << (e.global_p () ? "true" : "false") << ", " <<
368                 (e.qualified_p () ? "true" : "false") << ", e, " << x << ");";
369             }
370             else
371             {
372               os << xerces_ns << "::DOMElement& s (" << endl
373                  << "::xsd::cxx::xml::dom::create_element (" << endl
374                  << strlit (e.name ()) << "," << endl
375                  << (ns ? strlit (ns) + L",\n" : L"")
376                  << "e));"
377                  << endl;
378 
379               switch (schema_type (t))
380               {
381               case st_other:
382                 {
383                   os << "s << " << x << ";";
384                   break;
385                 }
386               case st_double:
387                 {
388                   os << "s << " << as_double_type << " (" << x << ");";
389                   break;
390                 }
391               case st_decimal:
392                 {
393                   os << "s << " << as_decimal_type << " (" << x << ");";
394                   break;
395                 }
396               }
397             }
398           }
399           else if (min (e) == 0)
400           {
401             // optional
402             //
403             if (!ordered)
404               os << "if (i." << aname << " ())"
405                  << "{";
406 
407             if (poly)
408             {
409               os << "const " << type << "& x (*i." << aname << " ());"
410                  << "if (typeid (" << type << ") == typeid (x))"
411                  << "{"
412                  << xerces_ns << "::DOMElement& s (" << endl
413                  << "::xsd::cxx::xml::dom::create_element (" << endl
414                  << strlit (e.name ()) << "," << endl
415                  << (ns ? strlit (ns) + L",\n" : L"")
416                  << "e));"
417                  << endl
418                  << "s << x;"
419                  << "}"
420                  << "else" << endl
421                  << "tsm.serialize (" << endl
422                  << strlit (e.name ()) << "," << endl
423                  << strlit (ns) << "," << endl
424                  << (e.global_p () ? "true" : "false") << ", " <<
425                 (e.qualified_p () ? "true" : "false") << ", e, x);";
426             }
427             else
428             {
429               os << xerces_ns << "::DOMElement& s (" << endl
430                  << "::xsd::cxx::xml::dom::create_element (" << endl
431                  << strlit (e.name ()) << "," << endl
432                  << (ns ? strlit (ns) + L",\n" : L"")
433                  << "e));"
434                  << endl;
435 
436               switch (schema_type (t))
437               {
438               case st_other:
439                 {
440                   os << "s << *i." << aname << " ();";
441                   break;
442                 }
443               case st_double:
444                 {
445                   os << "s << " << as_double_type << "(*i." << aname << " ());";
446                   break;
447                 }
448               case st_decimal:
449                 {
450                   os << "s << " << as_decimal_type << "(*i." << aname << " ());";
451                   break;
452                 }
453               }
454             }
455           }
456           else
457           {
458             // one
459             //
460             if (poly)
461             {
462               os << "const " << type << "& x (i." << aname << " ());"
463                  << "if (typeid (" << type << ") == typeid (x))"
464                  << "{"
465                  << xerces_ns << "::DOMElement& s (" << endl
466                  << "::xsd::cxx::xml::dom::create_element (" << endl
467                  << strlit (e.name ()) << "," << endl
468                  << (ns ? strlit (ns) + L",\n" : L"")
469                  << "e));"
470                  << endl
471                  << "s << x;"
472                  << "}"
473                  << "else" << endl
474                  << "tsm.serialize (" << endl
475                  << strlit (e.name ()) << "," << endl
476                  << strlit (ns) << "," << endl
477                  << (e.global_p () ? "true" : "false") << ", " <<
478                 (e.qualified_p () ? "true" : "false") << ", e, x);";
479             }
480             else
481             {
482               if (!ordered)
483                 os << "{";
484 
485               os << xerces_ns << "::DOMElement& s (" << endl
486                  << "::xsd::cxx::xml::dom::create_element (" << endl
487                  << strlit (e.name ()) << "," << endl
488                  << (ns ? strlit (ns) + L",\n" : L"")
489                  << "e));"
490                  << endl;
491 
492               switch (schema_type (t))
493               {
494               case st_other:
495                 {
496                   os << "s << i." << aname << " ();";
497                   break;
498                 }
499               case st_double:
500                 {
501                   os << "s << " << as_double_type << "(i." << aname << " ());";
502                   break;
503                 }
504               case st_decimal:
505                 {
506                   os << "s << " << as_decimal_type << "(i." << aname << " ());";
507                   break;
508                 }
509               }
510             }
511           }
512 
513           if (ordered)
514           {
515             // See comment for bool text (false); below.
516             //
517             if (mixed_p (c) && c.context ().get<size_t> ("ordered-start") != 1)
518               os << "text = true;";
519 
520             os << "continue;"
521                << "}";
522           }
523           else
524           {
525             os << "}";
526 
527             if (poly && (max (e) != 1 || min (e) == 0))
528               os << "}"; // There is no extra block for poly one.
529           }
530         }
531 
532       private:
533         String scope;
534       };
535 
536       struct Any: Traversal::Any, Context
537       {
AnyCXX::Tree::__anon7e6bba720111::Any538         Any (Context& c, String const& scope_)
539             : Context (c), scope (scope_)
540         {
541         }
542 
543         virtual void
traverseCXX::Tree::__anon7e6bba720111::Any544         traverse (Type& a)
545         {
546           SemanticGraph::Complex& c (
547             dynamic_cast<SemanticGraph::Complex&> (a.scope ()));
548 
549           bool ordered (ordered_p (c));
550 
551           String const& aname (eaname (a));
552 
553           os << "// " << ename (a) << endl
554              << "//" << endl;
555 
556           if (ordered)
557             os << "case " << scope << "::" <<
558               a.context ().get<String> ("ordered-id-name") << ":";
559 
560           if (max (a) != 1)
561           {
562             // sequence
563             //
564             if (!ordered)
565               os << "for (" << scope << "::" << econst_iterator (a) << endl
566                  << "b (i." << aname << " ().begin ()), " <<
567                 "n (i." << aname << " ().end ());" << endl
568                  << "b != n; ++b)";
569 
570             os << "{"
571                << "e.appendChild (" << endl
572                << "e.getOwnerDocument ()->importNode (" << endl
573                << "const_cast< " << xerces_ns <<
574               "::DOMElement* > (&(" <<
575               (ordered ? (L"i." + aname + L" ()[b->index]") : L"*b") <<
576               ")), true));";
577           }
578           else if (min (a) == 0)
579           {
580             // optional
581             //
582             if (!ordered)
583               os << "if (i." << aname << " ())";
584 
585             os << "{"
586                << "e.appendChild (" << endl
587                << "e.getOwnerDocument ()->importNode (" << endl
588                << "const_cast< " << xerces_ns << "::DOMElement* > (&(*i." <<
589               aname << " ())), true));";
590           }
591           else
592           {
593             // one
594             //
595             if (ordered)
596               os << "{";
597 
598             os << "e.appendChild (" << endl
599                << "e.getOwnerDocument ()->importNode (" << endl
600                << "const_cast< " << xerces_ns << "::DOMElement* > (&(i." <<
601               aname << " ())), true));"
602                << endl;
603           }
604 
605           if (ordered)
606           {
607             // See comment for bool text (false); below.
608             //
609             if (mixed_p (c) && c.context ().get<size_t> ("ordered-start") != 1)
610               os << "text = true;";
611 
612             os << "continue;";
613           }
614 
615           if (ordered || max (a) != 1 || min (a) == 0)
616             os << "}";
617         }
618 
619       private:
620         String scope;
621       };
622 
623       struct Attribute: Traversal::Attribute, Context
624       {
AttributeCXX::Tree::__anon7e6bba720111::Attribute625         Attribute (Context& c, String const& scope_)
626             : Context (c), scope (scope_)
627         {
628         }
629 
630         virtual void
traverseCXX::Tree::__anon7e6bba720111::Attribute631         traverse (Type& a)
632         {
633           String const& aname (eaname (a));
634           String ns (a.qualified_p () ? a.namespace_ ().name () : "");
635 
636           os << "// " << comment (a.name ()) << endl
637              << "//" << endl;
638 
639           if (a.optional_p () && !a.default_p ())
640           {
641             os << "if (i." << aname << " ())"
642                << "{"
643                << xerces_ns << "::DOMAttr& a (" << endl
644                << "::xsd::cxx::xml::dom::create_attribute (" << endl
645                << strlit (a.name ()) << "," << endl
646                << (ns ? strlit (ns) + L",\n" : L"")
647                << "e));"
648                << endl;
649 
650             switch (schema_type (a.type ()))
651             {
652             case st_other:
653               {
654                 os << "a << *i." << aname << " ();";
655                 break;
656               }
657             case st_double:
658               {
659                 os << "a << " << as_double_type << "(*i." << aname << " ());";
660                 break;
661               }
662             case st_decimal:
663               {
664                 os << "a << " << as_decimal_type << "(*i." << aname << " ());";
665                 break;
666               }
667             }
668 
669             os << "}";
670           }
671           else
672           {
673             // Make sure we serialize required fixed attributes.
674             //
675             if (a.optional_p () && options.omit_default_attributes ())
676             {
677               os << "if (i." << aname << " () != " << scope <<
678                 "::" << edefault_value (a) << " ())";
679             }
680 
681             os << "{"
682                << xerces_ns << "::DOMAttr& a (" << endl
683                << "::xsd::cxx::xml::dom::create_attribute (" << endl
684                << strlit (a.name ()) << "," << endl
685                << (ns ? strlit (ns) + L",\n" : L"")
686                << "e));"
687                << endl;
688 
689             switch (schema_type (a.type ()))
690             {
691             case st_other:
692               {
693                 os << "a << i." << aname << " ();";
694                 break;
695               }
696             case st_double:
697               {
698                 os << "a << " << as_double_type << "(i." << aname << " ());";
699                 break;
700               }
701             case st_decimal:
702               {
703                 os << "a << " << as_decimal_type << "(i." << aname << " ());";
704                 break;
705               }
706             }
707 
708             os << "}";
709           }
710         }
711 
712       private:
713         String scope;
714       };
715 
716       struct AnyAttribute: Traversal::AnyAttribute, Context
717       {
AnyAttributeCXX::Tree::__anon7e6bba720111::AnyAttribute718         AnyAttribute (Context& c, String const& scope_)
719             : Context (c), scope (scope_)
720         {
721         }
722 
723         virtual void
traverseCXX::Tree::__anon7e6bba720111::AnyAttribute724         traverse (Type& a)
725         {
726           String const& aname (eaname (a));
727 
728           os << "// " << ename (a) << endl
729              << "//" << endl;
730 
731           os << "for (" << scope << "::" << econst_iterator (a) << endl
732              << "b (i." << aname << " ().begin ()), " <<
733             "n (i." << aname << " ().end ());" << endl
734              << "b != n; ++b)"
735              << "{"
736              << xerces_ns << "::DOMAttr* a (" << endl
737              << "static_cast< " << xerces_ns << "::DOMAttr* > (" << endl
738              << "e.getOwnerDocument ()->importNode (" << endl
739              << "const_cast< " << xerces_ns << "::DOMAttr* > (&(*b)), true)));"
740              << endl
741              << "if (a->getLocalName () == 0)" << endl
742              << "e.setAttributeNode (a);"
743              << "else" << endl
744              << "e.setAttributeNodeNS (a);"
745              << "}";
746         }
747 
748       private:
749         String scope;
750       };
751 
752       struct Complex: Traversal::Complex, Context
753       {
ComplexCXX::Tree::__anon7e6bba720111::Complex754         Complex (Context& c)
755             : Context (c), base_ (c)
756         {
757           inherits_ >> base_;
758         }
759 
760         virtual void
traverseCXX::Tree::__anon7e6bba720111::Complex761         traverse (Type& c)
762         {
763           SemanticGraph::Context& ctx (c.context ());
764 
765           String name (ename (c));
766 
767           // If renamed name is empty then we do not need to generate
768           // anything for this type.
769           //
770           if (renamed_type (c, name) && !name)
771             return;
772 
773           // operator<< (xercesc::DOMElement)
774           //
775           os << "void" << endl
776              << "operator<< (" << xerces_ns << "::DOMElement& e, " <<
777             "const " << name << "& i)"
778              << "{";
779 
780           if (c.inherits_p ())
781           {
782             os << "e << static_cast< const ";
783             inherits (c, inherits_);
784             os << "& > (i);"
785                << endl;
786           }
787           else
788             os << "e << static_cast< const " << any_type << "& > (i);"
789                << endl;
790 
791           // Serialize anyAttribute content first so that is gets
792           // overriden by schema-defined attributes.
793           //
794           if (options.generate_wildcard ())
795           {
796             AnyAttribute any_attribute (*this, name);
797             Traversal::Names names (any_attribute);
798 
799             Complex::names (c, names);
800           }
801 
802           {
803             bool o (ordered_p (c));
804             size_t start, count;
805 
806             if (o)
807             {
808               start = ctx.get<size_t> ("ordered-start");
809               count = ctx.get<size_t> ("ordered-count");
810 
811               if (start != count)
812               {
813                 String const& ci (ctx.get<String> ("order-const-iterator"));
814                 String const& an (ctx.get<String> ("order-aname"));
815 
816                 // If we have mixed content and a base, then we have to
817                 // skip the text content until we serialize one of "our"
818                 // elements.
819                 //
820                 if (mixed_p (c) && start != 1)
821                   os << "bool text (false);"
822                      << endl;
823 
824                 os << "for (" << name << "::" << ci << endl
825                    << "b (i." << an << " ().begin ()), n (i." << an <<
826                   " ().end ());" << endl
827                    << "b != n; ++b)"
828                    << "{"
829                    << "switch (b->id)"
830                    << "{";
831               }
832             }
833 
834             Traversal::Names names;
835             Any any (*this, name);
836             Element element (*this, name);
837 
838             names >> element;
839 
840             if (options.generate_wildcard ())
841               names >> any;
842 
843             Complex::names (c, names);
844 
845             if (o)
846             {
847               if (start != count)
848               {
849                 if (mixed_p (c))
850                 {
851                   //@@ propagate mixed-ordered-id to derived
852 
853                   os << "// text_content" << endl
854                      << "//" << endl
855                      << "case " << name << "::" <<
856                     ctx.get<String> ("mixed-ordered-id-name") << ":"
857                      << "{";
858 
859                   // See the comment above.
860                   //
861                   if (start != 1)
862                     os << "if (text)" << endl;
863 
864                   os << "e.appendChild (" << endl
865                      << "e.getOwnerDocument ()->createTextNode (" << endl
866                      << "::xsd::cxx::xml::string (" << endl
867                      << "i." << ctx.get<String> ("mixed-aname") <<
868                     " ()[b->index].c_str ()).c_str ()));";
869 
870                   // os << "e << i." << ctx.get<String> ("mixed-aname") <<
871                   //  " ()[b->index];";
872 
873                   os << "continue;"
874                      << "}";
875                 }
876 
877                 // Ignore content before our id range and stop serializing
878                 // if we see anything past. This handles inheritance.
879                 //
880                 os << "default:"
881                    << "{";
882 
883                 if (start != 1)
884                   os << "if (b->id < " << start << "UL)" << endl
885                      << "continue;";
886 
887                 os << "break;" // Stop (see break below).
888                    << "}";
889 
890                 os << "}"      // switch
891                    << "break;" // Unknown element past our elements.
892                    << "}";     // for
893               }
894             }
895           }
896 
897           {
898             Attribute attribute (*this, name);
899             Traversal::Names names (attribute);
900             Complex::names (c, names);
901           }
902 
903           os << "}";
904 
905           bool simple (true);
906           {
907             IsSimpleType t (simple);
908             t.dispatch (c);
909           }
910 
911           if (simple)
912           {
913             bool hb (c.inherits_p ());
914 
915             // operator<< (xercesc::DOMAttr)
916             //
917             os << "void" << endl
918                << "operator<< (" << xerces_ns << "::DOMAttr&" <<
919               (hb ? " a" : "") << ", " <<
920               "const " << name << "&" << (hb ? " i" : "") << ")"
921                << "{";
922 
923             if (hb)
924             {
925               os << "a << static_cast< const ";
926 
927               inherits (c, inherits_);
928 
929               os << "& > (i);";
930             }
931 
932             os << "}";
933 
934 
935             // operator<< (list_stream)
936             //
937             os << "void" << endl
938                << "operator<< (" << list_stream_type << "&" <<
939               (hb ? " l" : "") << "," << endl
940                << "const " << name << "&" << (hb ? " i" : "") << ")"
941                << "{";
942 
943             if (hb)
944             {
945               os << "l << static_cast< const ";
946 
947               inherits (c, inherits_);
948 
949               os << "& > (i);";
950             }
951 
952             os << "}";
953           }
954 
955           // Register with type factory map. If this type is anonymous
956           // but substitutes, then it will be registered as part of the
957           // substitution registration.
958           //
959           if (polymorphic &&
960               polymorphic_p (c) &&
961               !c.abstract_p () &&
962               !anonymous_p (c))
963           {
964             // Note that we are using the original type name.
965             //
966             String const& name (ename (c));
967 
968             os << "static" << endl
969                << "const ::xsd::cxx::tree::type_serializer_initializer< " <<
970                 poly_plate << ", " << char_type << ", " << name << " >" << endl
971                << "_xsd_" << name << "_type_serializer_init (" << endl
972                << strlit (c.name ()) << "," << endl
973                << strlit (xml_ns_name (c)) << ");"
974                << endl
975                << endl;
976           }
977         }
978 
979       private:
980         Traversal::Inherits inherits_;
981         BaseTypeName base_;
982       };
983 
984 
985       // Generate substitution group map entry.
986       //
987       struct GlobalElement: Traversal::Element,
988                             GlobalElementBase,
989                             Context
990       {
GlobalElementCXX::Tree::__anon7e6bba720111::GlobalElement991         GlobalElement (Context& c)
992             : GlobalElementBase (c), Context (c), type_name_ (c)
993         {
994           belongs_ >> type_name_;
995         }
996 
997         virtual void
traverseCXX::Tree::__anon7e6bba720111::GlobalElement998         traverse (Type& e)
999         {
1000           if (polymorphic && e.substitutes_p ())
1001           {
1002             Type& r (e.substitutes ().root ());
1003 
1004             String const& name (ename (e));
1005 
1006             os << "static" << endl
1007                << "const ::xsd::cxx::tree::element_serializer_initializer< " <<
1008                 poly_plate << ", " << char_type << ", ";
1009 
1010             belongs (e, belongs_);
1011 
1012             os << " >" << endl
1013                << "_xsd_" << name << "_element_serializer_init (" << endl
1014                << strlit (r.name ()) << "," << endl
1015                << strlit (r.namespace_ ().name ()) << "," << endl
1016                << strlit (e.name ()) << "," << endl
1017                << strlit (e.namespace_ ().name ()) << ");"
1018                << endl
1019                << endl;
1020           }
1021         }
1022 
1023       private:
1024         Traversal::Belongs belongs_;
1025         MemberTypeName type_name_;
1026 
1027       };
1028 
1029       struct ElementType: Traversal::Element,
1030                           GlobalElementBase,
1031                           Context
1032       {
ElementTypeCXX::Tree::__anon7e6bba720111::ElementType1033         ElementType (Context& c)
1034             : GlobalElementBase (c),
1035               Context (c),
1036               element_map_ (c.options.generate_element_map ())
1037         {
1038         }
1039 
1040         virtual void
traverseCXX::Tree::__anon7e6bba720111::ElementType1041         traverse (Type& e)
1042         {
1043           if (doc_root_p (e))
1044           {
1045             String const& name (ename (e));
1046 
1047             // operator<< (xercesc::DOMElement)
1048             //
1049             os << "void" << endl
1050                << "operator<< (" << xerces_ns << "::DOMElement& e, " <<
1051               "const " << name << "& i)"
1052                << "{"
1053                << "e << i." << eaname (e) << " ();"
1054                << "}";
1055 
1056             // Element map registration.
1057             //
1058             if (element_map_)
1059             {
1060               SemanticGraph::Context& ec (e.context ());
1061               String const& aname (ec.get<String> ("element-name"));
1062               String const& ans (ec.get<String> ("element-ns"));
1063 
1064               os << "static " << endl
1065                  << "const ::xsd::cxx::tree::serializer_init< " <<
1066                 name << ", " << char_type << ", " << any_type << " >" << endl
1067                  << "_xsd_" << name << "_serializer_init (" <<
1068                 name << "::" << aname << " (), " <<
1069                 name << "::" << ans << " ());"
1070                  << endl;
1071             }
1072           }
1073         }
1074 
1075       private:
1076         bool element_map_;
1077       };
1078 
1079       struct ElementFunction: Traversal::Element,
1080                               GlobalElementBase,
1081                               Context
1082       {
ElementFunctionCXX::Tree::__anon7e6bba720111::ElementFunction1083         ElementFunction (Context& c)
1084             : GlobalElementBase (c), Context (c)
1085         {
1086         }
1087 
1088         virtual void
traverseCXX::Tree::__anon7e6bba720111::ElementFunction1089         traverse (Type& e)
1090         {
1091           if (!doc_root_p (e))
1092             return;
1093 
1094           String const& name (eserializer (e));
1095           String ns (e.namespace_ ().name ());
1096           String const& error_handler (error_handler_type);
1097           String const& namespace_infomap (namespace_infomap_type);
1098 
1099           SemanticGraph::Type& type (e.type ());
1100 
1101           // Note that I am using fq-name in function calls because g++ gets
1102           // confused if the name is 'type'. (see tests/schema/anonymous)
1103           //
1104 
1105           // Check if we need to handle xsi:type and substitution groups.
1106           // If this element's type is anonymous then we don't need to do
1107           // anything.
1108           //
1109           bool poly (polymorphic &&
1110                         polymorphic_p (type) &&
1111                         !anonymous_p (type));
1112 
1113           // To std::ostream.
1114           //
1115           os << "void" << endl
1116              << name << " (::std::ostream& o," << endl
1117              << "const " << type_name (e) << "& s," << endl
1118              << "const " << namespace_infomap << "& m," << endl
1119              << "const " << string_type << "& e," << endl
1120              << flags_type << " f)"
1121              << "{"
1122              << "::xsd::cxx::xml::auto_initializer i (" << endl
1123              << "(f & " << flags_type << "::dont_initialize) == 0);"
1124              << endl
1125              << dom_auto_ptr << "< " << xerces_ns <<
1126             "::DOMDocument > d (" << endl
1127              << fq_name (e, "serializer") << " (s, m, f));"
1128              << endl
1129              << "::xsd::cxx::tree::error_handler< " << char_type << " > h;"
1130              << endl
1131              << "::xsd::cxx::xml::dom::ostream_format_target t (o);"
1132              << "if (!::xsd::cxx::xml::dom::serialize (t, *d, e, h, f))"
1133              << "{"
1134              << "h.throw_if_failed< ::xsd::cxx::tree::serialization< " <<
1135             char_type << " > > ();"
1136              << "}"
1137              << "}";
1138 
1139           os << "void" << endl
1140              << name << " (::std::ostream& o," << endl
1141              << "const " << type_name (e) << "& s," << endl
1142              << error_handler << "& h," << endl
1143              << "const " << namespace_infomap << "& m," << endl
1144              << "const " << string_type << "& e," << endl
1145              << flags_type << " f)"
1146              << "{"
1147              << "::xsd::cxx::xml::auto_initializer i (" << endl
1148              << "(f & " << flags_type << "::dont_initialize) == 0);"
1149              << endl
1150              << dom_auto_ptr << "< " << xerces_ns <<
1151             "::DOMDocument > d (" << endl
1152              << fq_name (e, "serializer") << " (s, m, f));"
1153              << "::xsd::cxx::xml::dom::ostream_format_target t (o);"
1154              << "if (!::xsd::cxx::xml::dom::serialize (t, *d, e, h, f))"
1155              << "{"
1156              << "throw ::xsd::cxx::tree::serialization< " <<
1157             char_type << " > ();"
1158              << "}"
1159              << "}";
1160 
1161           os << "void" << endl
1162              << name << " (::std::ostream& o," << endl
1163              << "const " << type_name (e) << "& s," << endl
1164              << xerces_ns << "::DOMErrorHandler& h," << endl
1165              << "const " << namespace_infomap << "& m," << endl
1166              << "const " << string_type << "& e," << endl
1167              << flags_type << " f)"
1168              << "{"
1169              << dom_auto_ptr << "< " << xerces_ns <<
1170             "::DOMDocument > d (" << endl
1171              << fq_name (e, "serializer") << " (s, m, f));"
1172              << "::xsd::cxx::xml::dom::ostream_format_target t (o);"
1173              << "if (!::xsd::cxx::xml::dom::serialize (t, *d, e, h, f))"
1174              << "{"
1175              << "throw ::xsd::cxx::tree::serialization< " <<
1176             char_type << " > ();"
1177              << "}"
1178              << "}";
1179 
1180           // To XMLFormatTarget.
1181           //
1182           os << "void" << endl
1183              << name << " (" << xerces_ns << "::XMLFormatTarget& t," << endl
1184              << "const " << type_name (e) << "& s," << endl
1185              << "const " << namespace_infomap << "& m," << endl
1186              << "const " << string_type << "& e," << endl
1187              << flags_type << " f)"
1188              << "{"
1189              << dom_auto_ptr << "< " << xerces_ns <<
1190             "::DOMDocument > d (" << endl
1191              << fq_name (e, "serializer") << " (s, m, f));"
1192              << endl
1193              << "::xsd::cxx::tree::error_handler< " << char_type << " > h;"
1194              << endl
1195              << "if (!::xsd::cxx::xml::dom::serialize (t, *d, e, h, f))"
1196              << "{"
1197              << "h.throw_if_failed< ::xsd::cxx::tree::serialization< " <<
1198             char_type << " > > ();"
1199              << "}"
1200              << "}";
1201 
1202           os << "void" << endl
1203              << name << " (" << xerces_ns << "::XMLFormatTarget& t," << endl
1204              << "const " << type_name (e) << "& s," << endl
1205              << error_handler << "& h," << endl
1206              << "const " << namespace_infomap << "& m," << endl
1207              << "const " << string_type << "& e," << endl
1208              << flags_type << " f)"
1209              << "{"
1210              << dom_auto_ptr << "< " << xerces_ns <<
1211             "::DOMDocument > d (" << endl
1212              << fq_name (e, "serializer") << " (s, m, f));"
1213              << "if (!::xsd::cxx::xml::dom::serialize (t, *d, e, h, f))"
1214              << "{"
1215              << "throw ::xsd::cxx::tree::serialization< " <<
1216             char_type << " > ();"
1217              << "}"
1218              << "}";
1219 
1220           os << "void" << endl
1221              << name << " (" << xerces_ns << "::XMLFormatTarget& t," << endl
1222              << "const " << type_name (e) << "& s," << endl
1223              << xerces_ns << "::DOMErrorHandler& h," << endl
1224              << "const " << namespace_infomap << "& m," << endl
1225              << "const " << string_type << "& e," << endl
1226              << flags_type << " f)"
1227              << "{"
1228              << dom_auto_ptr << "< " << xerces_ns <<
1229             "::DOMDocument > d (" << endl
1230              << fq_name (e, "serializer") << " (s, m, f));"
1231              << "if (!::xsd::cxx::xml::dom::serialize (t, *d, e, h, f))"
1232              << "{"
1233              << "throw ::xsd::cxx::tree::serialization< " <<
1234             char_type << " > ();"
1235              << "}"
1236              << "}";
1237 
1238           // To an existing DOM instance.
1239           //
1240           os << "void" << endl
1241              << name << " (" << xerces_ns << "::DOMDocument& d," << endl
1242              << "const " << type_name (e) << "& s," << endl
1243              << flags_type << ")"
1244              << "{"
1245              << xerces_ns << "::DOMElement& e (*d.getDocumentElement ());"
1246              << "const " << qname_type << " n (" << endl
1247              << "::xsd::cxx::xml::dom::name< " << char_type << " > (e));"
1248              << endl;
1249 
1250           if (poly)
1251           {
1252             os << "if (typeid (" << type_name (e) << ") == typeid (s))"
1253                << "{";
1254           }
1255 
1256           os << "if (n.name () == " << strlit (e.name ()) << " &&" << endl
1257              << "n.namespace_ () == " << strlit (ns) << ")"
1258              << "{";
1259 
1260           switch (schema_type (type))
1261           {
1262           case st_other:
1263             {
1264               os << "e << s;";
1265               break;
1266             }
1267           case st_double:
1268             {
1269               os << "e << " << as_double_type << "(s);";
1270               break;
1271             }
1272           case st_decimal:
1273             {
1274               os << "e << " << as_decimal_type << "(s);";
1275               break;
1276             }
1277           }
1278 
1279           os << "}"
1280              << "else"
1281              << "{"
1282              << "throw ::xsd::cxx::tree::unexpected_element < " <<
1283             char_type << " > (" << endl
1284              << "n.name ()," << endl
1285              << "n.namespace_ ()," << endl
1286              << strlit (e.name ()) << "," << endl
1287              << strlit (ns) << ");"
1288              << "}";
1289 
1290           if (poly)
1291           {
1292             os << "}"
1293                << "else"
1294                << "{"
1295                << "::xsd::cxx::tree::type_serializer_map_instance< " <<
1296               poly_plate << ", " << char_type << " > ().serialize (" << endl
1297                << strlit (e.name ()) << "," << endl
1298                << strlit (e.namespace_().name ()) << "," << endl
1299                << "e, n, s);"
1300                << "}";
1301           }
1302 
1303           os << "}";
1304 
1305 
1306           // To a new DOM instance.
1307           //
1308           os << dom_auto_ptr << "< " << xerces_ns << "::DOMDocument >" << endl
1309              << name << " (const " << type_name (e) << "& s," << endl
1310              << "const " << namespace_infomap << "& m," << endl
1311              << flags_type << " f)"
1312              << "{";
1313 
1314           if (poly)
1315           {
1316             os << dom_auto_ptr << "< " << xerces_ns << "::DOMDocument > d;"
1317                << endl
1318                << "if (typeid (" << type_name (e) << ") == typeid (s))"
1319                << "{"
1320                << "d = ::xsd::cxx::xml::dom::serialize< " <<
1321               char_type << " > (" << endl
1322                << strlit (e.name ()) << "," << endl
1323                << strlit (ns) << "," << endl
1324                << "m, f);"
1325                << "}"
1326                << "else"
1327                << "{"
1328                << "d = ::xsd::cxx::tree::type_serializer_map_instance< " <<
1329               poly_plate << ", " << char_type << " > ().serialize (" << endl
1330                << strlit (e.name ()) << "," << endl
1331                << strlit (e.namespace_().name ()) << "," << endl
1332                << "m, s, f);"
1333                << "}";
1334           }
1335           else
1336           {
1337             os << dom_auto_ptr << "< " << xerces_ns <<
1338               "::DOMDocument > d (" << endl
1339                << "::xsd::cxx::xml::dom::serialize< " <<
1340               char_type << " > (" << endl
1341                << strlit (e.name ()) << "," << endl
1342                << strlit (ns) << "," << endl
1343                << "m, f));"
1344                << endl;
1345           }
1346 
1347           os << fq_name (e, "serializer") << " (*d, s, f);"
1348              << "return d;"
1349              << "}";
1350 
1351         }
1352 
1353       private:
1354         String
type_nameCXX::Tree::__anon7e6bba720111::ElementFunction1355         type_name (Type& e)
1356         {
1357           std::wostringstream o;
1358 
1359           MemberTypeName type (*this, o);
1360           type.dispatch (e.type ());
1361 
1362           return o.str ();
1363         }
1364       };
1365     }
1366 
1367     void
generate_serialization_source(Context & ctx,size_t first,size_t last)1368     generate_serialization_source (Context& ctx, size_t first, size_t last)
1369     {
1370       bool elemen_type (ctx.options.generate_element_type ());
1371 
1372       if (!elemen_type)
1373         ctx.os << "#include <ostream>" << endl
1374                << "#include <xsd/cxx/tree/error-handler.hxx>" << endl;
1375 
1376       ctx.os << "#include <xsd/cxx/xml/dom/serialization-source.hxx>" << endl
1377              << endl;
1378 
1379       if (ctx.polymorphic)
1380       {
1381         ctx.os << "#include <xsd/cxx/tree/type-serializer-map.hxx>" << endl
1382                << endl;
1383 
1384         bool import_maps (ctx.options.import_maps ());
1385         bool export_maps (ctx.options.export_maps ());
1386 
1387         if (import_maps || export_maps)
1388         {
1389           ctx.os << "#ifndef XSD_NO_EXPORT" << endl
1390                  << endl
1391                  << "namespace xsd"
1392                  << "{"
1393                  << "namespace cxx"
1394                  << "{"
1395                  << "namespace tree"
1396                  << "{"
1397                  << "#ifdef _MSC_VER" << endl;
1398 
1399           if (export_maps)
1400             ctx.os << "template struct __declspec (dllexport) " <<
1401               "type_serializer_plate< " << ctx.poly_plate << ", " <<
1402               ctx.char_type << " >;";
1403 
1404           if (import_maps)
1405             ctx.os << "template struct __declspec (dllimport) " <<
1406               "type_serializer_plate< " << ctx.poly_plate << ", " <<
1407               ctx.char_type << " >;";
1408 
1409           ctx.os << "#elif defined(__GNUC__) && __GNUC__ >= 4" << endl
1410                  << "template struct __attribute__ ((visibility(\"default\"))) " <<
1411             "type_serializer_plate< " << ctx.poly_plate << ", " <<
1412             ctx.char_type << " >;";
1413 
1414           ctx.os << "#elif defined(XSD_MAP_VISIBILITY)" << endl
1415                  << "template struct XSD_MAP_VISIBILITY " <<
1416             "type_serializer_plate< " << ctx.poly_plate << ", " <<
1417             ctx.char_type << " >;";
1418 
1419           ctx.os << "#endif" << endl
1420                  << "}"  // tree
1421                  << "}"  // cxx
1422                  << "}"  // xsd
1423                  << "#endif // XSD_NO_EXPORT" << endl
1424                  << endl;
1425         }
1426 
1427         ctx.os << "namespace _xsd"
1428                << "{"
1429                << "static" << endl
1430                << "const ::xsd::cxx::tree::type_serializer_plate< " <<
1431                 ctx.poly_plate << ", " << ctx.char_type << " >" << endl
1432                << "type_serializer_plate_init;"
1433                << "}";
1434       }
1435 
1436       Traversal::Schema schema;
1437 
1438       Sources sources;
1439       Traversal::Names names_ns, names;
1440 
1441       Namespace ns (ctx, first, last);
1442 
1443       List list (ctx);
1444       Union union_ (ctx);
1445       Complex complex (ctx);
1446       Enumeration enumeration (ctx);
1447       GlobalElement element (ctx);
1448       ElementType element_type (ctx);
1449       ElementFunction element_function (ctx);
1450 
1451 
1452       schema >> sources >> schema;
1453       schema >> names_ns >> ns >> names;
1454 
1455       names >> list;
1456       names >> union_;
1457       names >> complex;
1458       names >> enumeration;
1459       names >> element;
1460 
1461       if (elemen_type)
1462         names >> element_type;
1463       else
1464         names >> element_function;
1465 
1466       schema.dispatch (ctx.schema_root);
1467     }
1468   }
1469 }
1470