9#ifndef CLASSDESC_XSD_GENERATE_BASE_H
10#define CLASSDESC_XSD_GENERATE_BASE_H
23 std::map<string, string> xsdDefs;
24 std::map<string, std::set<string> > dependencies;
26 struct TypeBeingAddedTo
30 string name, description, baseClass;
31 TypeBeingAddedTo(
const string& name=
"",
const string& d=
"",
bool complete=
false):
32 complete(complete), sequenceAdded(
false), name(name), description(d) {}
35 std::vector<TypeBeingAddedTo> typeBeingaddedTo;
36 std::set<string> written;
38 void outputType(std::ostream& o,
const string& type)
40 if (!written.insert(type).second)
return;
42 const std::set<string>& deps=dependencies[type];
43 for (std::set<string>::const_iterator d=deps.begin(); d!=deps.end(); ++d)
59 Optional(xsd_generate_t& x,
bool o): x(x), prev_opt(x.optional) {x.optional=o;}
60 ~Optional() {x.optional=prev_opt;}
66 void addMember(
const string& name,
const string& memberType)
69 !typeBeingaddedTo.empty() && !typeBeingaddedTo.back().complete)
71 if (!typeBeingaddedTo.back().sequenceAdded)
72 xsdDefs[typeBeingaddedTo.back().name]+=
" <xs:sequence>\n";
73 typeBeingaddedTo.back().sequenceAdded=
true;
74 xsdDefs[typeBeingaddedTo.back().name]+=
75 " <xs:element name=\""+name+
"\" type=\""
76 +memberType+(
optional?
"\" minOccurs=\"0":
"")+
"\"/>\n";
84 if (!typeBeingaddedTo.empty() && !typeBeingaddedTo.back().complete)
86 if (typeBeingaddedTo.back().baseClass.empty())
88 xsdDefs[typeBeingaddedTo.back().name]+=
89 " <xs:complexContent>\n"
90 " <xs:extension base=\""+base+
"\">\n";
91 typeBeingaddedTo.back().baseClass=base;
93 else if (typeBeingaddedTo.back().baseClass!=base)
95 (
"Multiple inheritance not supported: "+typeBeingaddedTo.back().name);
103 if (dependency.substr(0,4)==
"tns:")
104 dependencies[type].insert(dependency.substr(4));
110 void openType(
const string& type,
const string& description)
112 typeBeingaddedTo.push_back
113 (TypeBeingAddedTo(type, description, xsdDefs.count(type)>0));
114 if (!typeBeingaddedTo.back().complete)
115 xsdDefs[type]=
" <xs:complexType name=\""+type+
"\">\n";
120 if (!typeBeingaddedTo.empty() && !typeBeingaddedTo.back().complete)
124 xsdDefs[typeBeingaddedTo.back().name]+=
125 " <xs:any minOccurs=\"0\" "
126 "maxOccurs=\"unbounded\" processContents=\"lax\"/>\n";
127 if (typeBeingaddedTo.back().sequenceAdded)
128 xsdDefs[typeBeingaddedTo.back().name]+=
" </xs:sequence>\n";
129 if (!typeBeingaddedTo.back().baseClass.empty())
130 xsdDefs[typeBeingaddedTo.back().name]+=
" </xs:extension>\n"
131 " </xs:complexContent>\n";
132 xsdDefs[typeBeingaddedTo.back().name]+=
" </xs:complexType>\n";
134 typeBeingaddedTo.pop_back();
137 string currentDescription()
const
139 if (!typeBeingaddedTo.empty())
140 return typeBeingaddedTo.back().description;
148 if (xsdDefs.count(type)==0)
155 void output(std::ostream& o,
const string& targetNS)
158 o<<
"<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n";
159 o<<
"<xs:schema targetNamespace=\"";
161 o<<
"\"\n xmlns:xs=\"http://www.w3.org/2001/XMLSchema\"\n";
162 o<<
" xmlns:tns=\""<<targetNS<<
"\"\n";
163 o<<
" elementFormDefault=\"qualified\" attributeFormDefault=\"unqualified\">\n";
165 for (std::map<string, string>::const_iterator i=xsdDefs.begin();
166 i!=xsdDefs.end(); ++i)
167 outputType(o, i->first);
169 o<<
" <xs:element name=\""<<
rootName<<
"\" type=\""<<rootType<<
"\"/>\n";
174 template <
class T>
struct UnknownSchema:
public exception
177 UnknownSchema(): msg(
"unknown schema for "+typeName<T>()) {}
178 ~UnknownSchema()
throw() {}
179 const char* what()
const throw()
180 {
return msg.c_str();}
199 inline string transformTypeName(
string x)
201 for (string::size_type i=0; i<x.length(); ++i)
207 template <
class T>
string xsd_typeName()
208 {
return "tns:"+transformTypeName(typeName<T>());}
214 Or<is_fundamental<T>,is_container<T> >,
224 if (!d.empty() && d.find(
'.')==string::npos)
227 g.rootType=xsd_typeName<T>();
230 if (g.currentDescription()==d)
235 g.
openType(transformTypeName(typeName<T>()), d);
247 {xsd_generate(g,
"",a);}
250 inline void processExtraClass(
xsd_generate_t& g,
const string& d,
const std::string& a)
253 template <
class T,
class U>
254 void processExtraClass(
xsd_generate_t& g,
const string& d,
const std::pair<T,U>& a)
255 {xsd_generate(g,
"",a);}
257 template <>
inline string xsd_typeName<bool>() {
return "xs:boolean";}
258 template <>
inline string xsd_typeName<char>() {
return "xs:string";}
259 template <>
inline string xsd_typeName<signed char>() {
return "xs:string";}
260 template <>
inline string xsd_typeName<short>() {
return "xs:short";}
261 template <>
inline string xsd_typeName<int>() {
return "xs:int";}
262 template <>
inline string xsd_typeName<long>() {
return "xs:long";}
263 template <>
inline string xsd_typeName<unsigned char>() {
return "xs:string";}
264 template <>
inline string xsd_typeName<unsigned short>() {
return "xs:unsignedShort";}
265 template <>
inline string xsd_typeName<unsigned int>() {
return "xs:unsignedInt";}
266 template <>
inline string xsd_typeName<unsigned long>() {
return "xs:unsignedLong";}
269 template <>
inline string xsd_typeName<long long>() {
return "xs:long";}
270 template <>
inline string xsd_typeName<unsigned long long>() {
return "xs:unsignedLong";}
273 template <>
inline string xsd_typeName<float>() {
return "xs:float";}
274 template <>
inline string xsd_typeName<double>() {
return "xs:double";}
276 template <>
inline string xsd_typeName<long double>() {
return "xs:double";}
277 template <>
inline string xsd_typeName<string>() {
return "xs:string";}
278 template <>
inline string xsd_typeName<std::wstring>() {
return "xs:string";}
283 {g.addMember(tail(d),xsd_typeName<T>());}
286 void xsd_generate(
xsd_generate_t& g,
const string& d,
const std::basic_string<T>& a)
287 {g.addMember(tail(d),
"xs:string");}
293 int dims,
size_t ncopies, ...)
295 std::ostringstream type;
296 type <<
"__builtin_array_"+transformTypeName(typeName<T>())<<
"_"<<ncopies;
298 va_start(ap,ncopies);
299 for (
int i=1; i<dims; i++)
302 int dim=va_arg(ap,
int);
308 std::ostringstream os;
309 os<<
" <xs:complexType name=\""+type.str()+
"\">\n";
310 os<<
" <xs:sequence minOccurs=\""<<ncopies<<
311 "\" maxOccurs=\""<<ncopies<<
"\">\n";
312 os<<
" <xs:element name=\""<<typeName<T>()<<
"\" type=\""<<
313 xsd_typeName<T>()<<
"\"/>\n";
314 os<<
" </xs:sequence>\n";
315 os<<
" </xs:complexType>\n";
324 typename enable_if<is_enum<E>,
void>:: T
333 void xsd_generate(xsd_generate_t& g,
const string& d,
const Enum_handle<E>& e)
335 string type=transformTypeName(typeName<E>());
336 std::ostringstream os;
337 os <<
" <xs:simpleType name=\""<<type<<
"\">\n";
338 os <<
" <xs:restriction base=\"xs:string\">\n";
339 for (
typename EnumKeys<E>::iterator i=enum_keysData<E>::keys.begin();
340 i!=enum_keysData<E>::keys.end(); ++i)
341 os <<
" <xs:enumeration value=\""<<i->second<<
"\"/>\n";
342 os <<
" </xs:restriction>\n";
343 os <<
" </xs:simpleType>\n";
344 g.defineType(type, os.str());
345 g.addMember(tail(d), xsd_typeName<E>());
353 std::ostringstream os;
355 string eName=typeName<typename T::value_type>().c_str();
356 eName=eName.substr(0,eName.find(
'<'));
358 const char *el=eName.c_str()+eName.length();
359 while (el!=eName.c_str() && *(el-1)!=
' ' && *(el-1)!=
':') el--;
361 string type=transformTypeName(typeName<T>());
362 os <<
" <xs:complexType name=\"" << type <<
"\">\n";
363 os <<
" <xs:sequence minOccurs=\"0\" maxOccurs=\"unbounded\">\n";
364 os <<
" <xs:element name=\""<<el<<
365 "\" type=\""<<xsd_typeName<typename T::value_type>()<<
"\"/>\n";
366 os <<
" </xs:sequence>\n";
367 os <<
" </xs:complexType>\n";
368 g.addMember(tail(d), xsd_typeName<T>());
369 g.defineType(type, os.str());
370 g.addDependency(type, xsd_typeName<typename T::value_type>());
372 processExtraClass(g, d+transformTypeName(typeName<typename T::value_type>()),
typename T::value_type());
375#if defined(__cplusplus) && __cplusplus>=201103L
376 template <
class T, std::
size_t N>
377 void xsd_generate(
xsd_generate_t& g,
const string& d,
const std::array<T,N>& e)
379 std::ostringstream os;
381 string eName=typeName<T>().c_str();
382 eName=eName.substr(0,eName.find(
'<'));
384 const char *el=eName.c_str()+eName.length();
385 while (el!=eName.c_str() && *(el-1)!=
' ' && *(el-1)!=
':') el--;
387 string type=transformTypeName(typeName<std::array<T,N>>());
388 os <<
" <xs:complexType name=\"" << type <<
"\">\n";
389 os <<
" <xs:sequence minOccurs=\""<<N<<
"\" maxOccurs=\""<<N<<
"\">\n";
390 os <<
" <xs:element name=\""<<el<<
391 "\" type=\""<<xsd_typeName<T>()<<
"\"/>\n";
392 os <<
" </xs:sequence>\n";
393 os <<
" </xs:complexType>\n";
394 g.addMember(tail(d), xsd_typeName<std::array<T,N>>());
395 g.defineType(type, os.str());
396 g.addDependency(type, xsd_typeName<T>());
398 processExtraClass(g, d+transformTypeName(typeName<T>()),
T());
403 template <
class T,
class U>
404 void xsd_generate(
xsd_generate_t& g,
const string& d,
const std::pair<T,U>& a)
406 g.openType(transformTypeName(typeName<std::pair<T,U> >()), d);
407 xsd_generate(g,d+
".first",a.first);
408 xsd_generate(g,d+
".second",a.second);
424 void xsd_generate(
xsd_generate_t& g,
const string& d,
const shared_ptr<T>& a)
427 xsd_generate(g,d,*a);
438 g.openType(transformTypeName(typeName<T>()), d);
439 classdesc_access::access_xsd_generate<T>()(g,d,
const_cast<T&
>(a));
445#include "use_mbr_pointers.h"
446CLASSDESC_USE_OLDSTYLE_MEMBER_OBJECTS(xsd_generate)
447CLASSDESC_FUNCTION_NOP(xsd_generate)
449using classdesc::xsd_generate;
450using classdesc::xsd_generate_onbase;
Definition classdesc.h:868
Definition classdesc.h:920
Definition classdesc.h:923
Definition xsd_generate_base.h:22
bool optional
set to true if next addMember refers to an optional element
Definition xsd_generate_base.h:52
void addMember(const string &name, const string &memberType)
add an attribute name with XSD type memberType
Definition xsd_generate_base.h:66
void defineType(const string &type, const string &def)
add a complete XSD definition for type
Definition xsd_generate_base.h:146
void addDependency(const string &type, const string &dependency)
add a dependency between type and dependency (XSD qualifed name)
Definition xsd_generate_base.h:100
void openType(const string &type, const string &description)
Definition xsd_generate_base.h:110
void addBase(const string &base)
add a base class to the current definition
Definition xsd_generate_base.h:82
void closeType()
complete type definition - matching last nested openType
Definition xsd_generate_base.h:118
string rootName
name of the root element, and its XSD type, in the Schema
Definition xsd_generate_base.h:50
void output(std::ostream &o, const string &targetNS)
Definition xsd_generate_base.h:155
Contains access_* structs, and nothing else. These structs are used to gain access to private members...
Definition classdesc_access.h:20
Contains definitions related to classdesc functionality.
string basename()
returns a valid identifier to append to the descriptor of a base class
Definition classdesc.h:1127
Definition xsd_generate_base.h:217
Definition classdesc.h:1012
Definition classdesc.h:405
Definition xsd_generate_base.h:175
controlled template specialisation: stolen from boost::enable_if.
Definition classdesc.h:282
base class for exceptions thrown by classdesc
Definition classdesc.h:546
RAII helper class to set optional to opt for current scope.
Definition xsd_generate_base.h:56
Definition xsd_generate_base.h:188