1 /* 2 * Copyright (C) 2018 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17 package com.android.xsdc.cpp; 18 19 import com.android.xsdc.CodeWriter; 20 import com.android.xsdc.FileSystem; 21 import com.android.xsdc.XmlSchema; 22 import com.android.xsdc.XsdConstants; 23 import com.android.xsdc.tag.*; 24 25 import java.io.IOException; 26 import java.util.ArrayList; 27 import java.util.Collections; 28 import java.util.HashMap; 29 import java.util.HashSet; 30 import java.util.List; 31 import java.util.Map; 32 import java.util.Set; 33 34 import javax.xml.namespace.QName; 35 36 public class CppCodeGenerator { 37 public static final int GENERATE_ENUMS = 1 << 0; 38 public static final int GENERATE_PARSER = 1 << 1; 39 40 private XmlSchema xmlSchema; 41 private String pkgName; 42 private Map<String, CppSimpleType> cppSimpleTypeMap; 43 private CodeWriter enumsCppFile; 44 private CodeWriter enumsHeaderFile; 45 private CodeWriter parserCppFile; 46 private CodeWriter parserHeaderFile; 47 private boolean hasAttr; 48 private boolean writer; 49 private int generators; 50 private boolean booleanGetter; 51 52 private static final String UNKNOWN_ENUM = "UNKNOWN"; 53 CppCodeGenerator(XmlSchema xmlSchema, String pkgName, boolean writer, int generators, boolean booleanGetter)54 public CppCodeGenerator(XmlSchema xmlSchema, String pkgName, boolean writer, int generators, 55 boolean booleanGetter) throws CppCodeGeneratorException { 56 this.xmlSchema = xmlSchema; 57 this.pkgName = pkgName; 58 this.writer = writer; 59 this.generators = generators; 60 this.booleanGetter = booleanGetter; 61 62 // class naming validation 63 { 64 Set<String> nameSet = new HashSet<>(); 65 nameSet.add("XmlParser"); 66 for (XsdType type : xmlSchema.getTypeMap().values()) { 67 if ((type instanceof XsdComplexType) || (type instanceof XsdRestriction && 68 ((XsdRestriction)type).getEnums() != null)) { 69 String name = Utils.toClassName(type.getName()); 70 if (nameSet.contains(name)) { 71 throw new CppCodeGeneratorException( 72 String.format("duplicate class name : %s", name)); 73 } 74 nameSet.add(name); 75 if (type instanceof XsdComplexType && !hasAttr) { 76 hasAttr = hasAttribute((XsdComplexType)type); 77 } 78 } 79 } 80 for (XsdElement element : xmlSchema.getElementMap().values()) { 81 XsdType type = element.getType(); 82 if (type.getRef() == null && type instanceof XsdComplexType) { 83 String name = Utils.toClassName(element.getName()); 84 if (nameSet.contains(name)) { 85 throw new CppCodeGeneratorException( 86 String.format("duplicate class name : %s", name)); 87 } 88 nameSet.add(name); 89 if (!hasAttr) { 90 hasAttr = hasAttribute((XsdComplexType)type); 91 } 92 } 93 } 94 } 95 96 cppSimpleTypeMap = new HashMap<>(); 97 for (XsdType type : xmlSchema.getTypeMap().values()) { 98 if (type instanceof XsdSimpleType) { 99 XsdType refType = new XsdType(null, new QName(type.getName())); 100 parseSimpleType(refType, true); 101 } 102 } 103 } 104 print(FileSystem fs)105 public void print(FileSystem fs) 106 throws CppCodeGeneratorException, IOException { 107 // cpp file, header file init 108 String fileNameStem = pkgName.replace('.', '_'); 109 String enumsCppFileName = fileNameStem + "_enums.cpp"; 110 String enumsHeaderFileName = fileNameStem + "_enums.h"; 111 String parserCppFileName = fileNameStem + ".cpp"; 112 String parserHeaderFileName = fileNameStem + ".h"; 113 if ((this.generators & GENERATE_ENUMS) == GENERATE_ENUMS) { 114 enumsCppFile = new CodeWriter(fs.getPrintWriter(enumsCppFileName)); 115 enumsHeaderFile = new CodeWriter(fs.getPrintWriter("include/" + enumsHeaderFileName)); 116 } else { 117 enumsCppFile = new CodeWriter(); 118 enumsHeaderFile = new CodeWriter(); 119 } 120 if ((this.generators & GENERATE_PARSER) == GENERATE_PARSER) { 121 parserCppFile = new CodeWriter(fs.getPrintWriter(parserCppFileName)); 122 parserHeaderFile = new CodeWriter(fs.getPrintWriter("include/" + parserHeaderFileName)); 123 } else { 124 parserCppFile = new CodeWriter(); 125 parserHeaderFile = new CodeWriter(); 126 } 127 128 boolean hasEnums = false; 129 for (XsdType type : xmlSchema.getTypeMap().values()) { 130 if (type instanceof XsdRestriction && 131 ((XsdRestriction)type).getEnums() != null) { 132 hasEnums = true; 133 break; 134 } 135 } 136 137 String enumsHeaderMacro = enumsHeaderFileName.toUpperCase().replace('.', '_'); 138 String parserHeaderMacro = parserHeaderFileName.toUpperCase().replace('.', '_'); 139 enumsHeaderFile.printf("#ifndef %s\n", enumsHeaderMacro); 140 enumsHeaderFile.printf("#define %s\n", enumsHeaderMacro); 141 enumsHeaderFile.printf("\n"); 142 enumsHeaderFile.printf("#include <array>\n"); 143 enumsHeaderFile.printf("#include <string>\n"); 144 enumsHeaderFile.printf("\n"); 145 parserHeaderFile.printf("#ifndef %s\n", parserHeaderMacro); 146 parserHeaderFile.printf("#define %s\n", parserHeaderMacro); 147 parserHeaderFile.printf("\n"); 148 parserHeaderFile.printf("#include <array>\n"); 149 parserHeaderFile.printf("#include <map>\n"); 150 parserHeaderFile.printf("#include <optional>\n"); 151 parserHeaderFile.printf("#include <string>\n"); 152 parserHeaderFile.printf("#include <vector>\n"); 153 if (writer) { 154 parserHeaderFile.printf("#include <iostream>\n"); 155 } 156 parserHeaderFile.printf("\n"); 157 parserHeaderFile.printf("#if __has_include(<libxml/parser.h>)\n"); 158 parserHeaderFile.printf("#include <libxml/parser.h>\n"); 159 parserHeaderFile.printf("#include <libxml/xinclude.h>\n"); 160 parserHeaderFile.printf("#else\n"); 161 parserHeaderFile.printf("#error Require libxml2 library. "); 162 parserHeaderFile.printf("Please add libxml2 to shared_libs or static_libs\n"); 163 parserHeaderFile.printf("#endif\n"); 164 if (hasEnums) { 165 enumsHeaderFile.printf("#include <xsdc/XsdcSupport.h>\n"); 166 enumsHeaderFile.printf("\n"); 167 } 168 parserHeaderFile.printf("\n"); 169 parserHeaderFile.printf("#include \"%s\"\n", enumsHeaderFileName); 170 parserHeaderFile.printf("\n"); 171 172 enumsCppFile.printf("#include <map>\n"); 173 enumsCppFile.printf("\n"); 174 enumsCppFile.printf("#include \"%s\"\n\n", enumsHeaderFileName); 175 parserCppFile.printf("#define LOG_TAG \"%s\"\n", pkgName); 176 parserCppFile.printf("#include \"%s\"\n\n", parserHeaderFileName); 177 178 List<String> namespace = new java.util.ArrayList<>(); 179 for (String token : pkgName.split("\\.")) { 180 if (token.isEmpty()) { 181 continue; 182 } 183 if (Character.isDigit(token.charAt(0))) { 184 token = "_" + token; 185 } 186 namespace.add(token); 187 enumsHeaderFile.printf("namespace %s {\n", token); 188 enumsCppFile.printf("namespace %s {\n", token); 189 parserHeaderFile.printf("namespace %s {\n", token); 190 parserCppFile.printf("namespace %s {\n", token); 191 } 192 193 printPrototype(); 194 printXmlParser(); 195 if (writer) { 196 printXmlWriter(); 197 } 198 199 for (XsdType type : xmlSchema.getTypeMap().values()) { 200 if (type instanceof XsdRestriction && 201 ((XsdRestriction)type).getEnums() != null) { 202 String name = Utils.toClassName(type.getName()); 203 XsdRestriction restrictionType = (XsdRestriction) type; 204 printEnum(name, restrictionType); 205 } 206 } 207 for (XsdType type : xmlSchema.getTypeMap().values()) { 208 if (type instanceof XsdComplexType) { 209 String name = Utils.toClassName(type.getName()); 210 XsdComplexType complexType = (XsdComplexType) type; 211 printClass(name, "", complexType); 212 } 213 } 214 for (XsdElement element : xmlSchema.getElementMap().values()) { 215 XsdType type = element.getType(); 216 if (type.getRef() == null && type instanceof XsdComplexType) { 217 String name = Utils.toClassName(element.getName()); 218 XsdComplexType complexType = (XsdComplexType) type; 219 printClass(name, "", complexType); 220 } 221 } 222 223 Collections.reverse(namespace); 224 for (String token : namespace) { 225 enumsHeaderFile.printf("} // %s\n", token); 226 enumsCppFile.printf("} // %s\n", token); 227 parserHeaderFile.printf("} // %s\n", token); 228 parserCppFile.printf("} // %s\n", token); 229 } 230 231 if (hasEnums) { 232 enumsHeaderFile.printf("\n//\n// global type declarations for package\n//\n\n"); 233 enumsHeaderFile.printf("namespace android {\nnamespace details {\n"); 234 Collections.reverse(namespace); 235 for (XsdType type : xmlSchema.getTypeMap().values()) { 236 if (type instanceof XsdRestriction && 237 ((XsdRestriction)type).getEnums() != null) { 238 String name = Utils.toClassName(type.getName()); 239 XsdRestriction restrictionType = (XsdRestriction) type; 240 printEnumValues(namespace, name, restrictionType); 241 } 242 } 243 enumsHeaderFile.printf("} // namespace details\n} // namespace android\n\n"); 244 } 245 246 parserHeaderFile.printf("#endif // %s\n", parserHeaderMacro); 247 enumsHeaderFile.printf("#endif // %s\n", enumsHeaderMacro); 248 parserCppFile.close(); 249 parserHeaderFile.close(); 250 enumsCppFile.close(); 251 enumsHeaderFile.close(); 252 } 253 printEnum(String name, XsdRestriction restrictionType)254 private void printEnum(String name, XsdRestriction restrictionType) 255 throws CppCodeGeneratorException { 256 enumsHeaderFile.printf("enum class %s {\n", name); 257 enumsCppFile.printf("const std::map<std::string, %s> %sString {\n", name, name); 258 List<XsdEnumeration> enums = restrictionType.getEnums(); 259 260 enumsHeaderFile.printf("%s = %d,\n", UNKNOWN_ENUM, -1); 261 for (XsdEnumeration tag : enums) { 262 String value = tag.getValue(); 263 enumsHeaderFile.printf("%s,\n", Utils.toEnumName(value)); 264 enumsCppFile.printf("{ \"%s\", %s::%s },\n", tag.getValue(), name, 265 Utils.toEnumName(value)); 266 } 267 enumsHeaderFile.printf("};\n"); 268 enumsCppFile.printf("};\n\n"); 269 270 enumsHeaderFile.printf("%s stringTo%s(const std::string& value);\n", 271 name, name); 272 enumsCppFile.printf("%s stringTo%s(const std::string& value) {\n" 273 + "auto enumValue = %sString.find(value);\n" 274 + "return enumValue != %sString.end() ? enumValue->second : %s::%s;\n" 275 + "}\n\n", name, name, name, name, name, UNKNOWN_ENUM); 276 277 enumsHeaderFile.printf("std::string toString(%s o);\n\n", name); 278 enumsCppFile.printf("std::string toString(%s o) {\n", name); 279 enumsCppFile.printf("switch (o) {\n"); 280 for (XsdEnumeration tag : enums) { 281 String value = tag.getValue(); 282 enumsCppFile.printf("case %s::%s: return \"%s\";\n", 283 name, Utils.toEnumName(value), tag.getValue()); 284 } 285 enumsCppFile.printf("default: return std::to_string(static_cast<int>(o));\n}\n"); 286 enumsCppFile.printf("}\n\n"); 287 } 288 printEnumValues(List<String> namespace, String name, XsdRestriction restrictionType)289 private void printEnumValues(List<String> namespace, String name, 290 XsdRestriction restrictionType) throws CppCodeGeneratorException { 291 List<XsdEnumeration> enums = restrictionType.getEnums(); 292 String absoluteNamespace = "::" + String.join("::", namespace); 293 enumsHeaderFile.printf("template<> inline constexpr std::array<%s::%s, %d> " 294 + "xsdc_enum_values<%s::%s> = {\n", 295 absoluteNamespace, name, enums.size(), absoluteNamespace, name); 296 for (XsdEnumeration tag : enums) { 297 String value = tag.getValue(); 298 enumsHeaderFile.printf("%s::%s::%s,\n", 299 absoluteNamespace, name, Utils.toEnumName(value)); 300 } 301 enumsHeaderFile.printf("};\n"); 302 } 303 printPrototype()304 private void printPrototype() throws CppCodeGeneratorException { 305 for (XsdType type : xmlSchema.getTypeMap().values()) { 306 if (type instanceof XsdComplexType) { 307 String name = Utils.toClassName(type.getName()); 308 parserHeaderFile.printf("class %s;\n", name); 309 } 310 } 311 for (XsdElement element : xmlSchema.getElementMap().values()) { 312 XsdType type = element.getType(); 313 if (type.getRef() == null && type instanceof XsdComplexType) { 314 String name = Utils.toClassName(element.getName()); 315 parserHeaderFile.printf("class %s;\n", name); 316 } 317 } 318 } 319 printClass(String name, String nameScope, XsdComplexType complexType)320 private void printClass(String name, String nameScope, XsdComplexType complexType) 321 throws CppCodeGeneratorException { 322 assert name != null; 323 // need element, attribute name duplicate validation? 324 325 String baseName = getBaseName(complexType); 326 CppSimpleType valueType = (complexType instanceof XsdSimpleContent) ? 327 getValueType((XsdSimpleContent) complexType, false) : null; 328 329 parserHeaderFile.printf("class %s ", name); 330 331 if (baseName != null) { 332 parserHeaderFile.printf(": public %s {\n", baseName); 333 } else { 334 parserHeaderFile.println("{"); 335 } 336 337 // parse types for elements and attributes 338 List<CppType> elementTypes = new ArrayList<>(); 339 List<XsdElement> elements = new ArrayList<>(); 340 elements.addAll(getAllElements(complexType.getGroup())); 341 elements.addAll(complexType.getElements()); 342 343 for (XsdElement element : elements) { 344 CppType cppType; 345 XsdElement elementValue = resolveElement(element); 346 if (element.getRef() == null && element.getType().getRef() == null 347 && element.getType() instanceof XsdComplexType) { 348 // print inner class for anonymous types 349 parserHeaderFile.printf("public:\n"); 350 String innerName = Utils.toClassName(getElementName(element)); 351 XsdComplexType innerType = (XsdComplexType) element.getType(); 352 printClass(innerName, nameScope + name + "::", innerType); 353 parserHeaderFile.println(); 354 cppType = new CppComplexType(nameScope + name + "::"+ innerName); 355 } else { 356 cppType = parseType(elementValue.getType(), getElementName(elementValue)); 357 } 358 elementTypes.add(cppType); 359 } 360 List<CppSimpleType> attributeTypes = new ArrayList<>(); 361 List<XsdAttribute> attributes = new ArrayList(); 362 for (XsdAttributeGroup attributeGroup : complexType.getAttributeGroups()) { 363 attributes.addAll(getAllAttributes(resolveAttributeGroup(attributeGroup))); 364 } 365 attributes.addAll(complexType.getAttributes()); 366 367 for (XsdAttribute attribute : attributes) { 368 XsdType type = resolveAttribute(attribute).getType(); 369 attributeTypes.add(parseSimpleType(type, false)); 370 } 371 372 // print member variables 373 374 parserHeaderFile.printf("private:\n"); 375 for (int i = 0; i < elementTypes.size(); ++i) { 376 CppType type = elementTypes.get(i); 377 XsdElement element = elements.get(i); 378 XsdElement elementValue = resolveElement(element); 379 String typeName = Utils.elementTypeName(type.getName(), 380 element.isMultiple() || type instanceof CppComplexType); 381 parserHeaderFile.printf("const %s %s_;\n", typeName, 382 Utils.toVariableName(getElementName(elementValue))); 383 } 384 for (int i = 0; i < attributeTypes.size(); ++i) { 385 CppType type = attributeTypes.get(i); 386 XsdAttribute attribute = resolveAttribute(attributes.get(i)); 387 String variableName = Utils.toVariableName(attribute.getName()); 388 if (attribute.isRequired()) { 389 parserHeaderFile.printf("const %s %s_;\n", type.getName(), variableName); 390 } else { 391 parserHeaderFile.printf("const std::optional<%s> %s_;\n", 392 type.getName(), variableName); 393 } 394 } 395 if (valueType != null) { 396 parserHeaderFile.printf("const std::optional<%s> _value;\n", valueType.getName()); 397 } 398 399 parserHeaderFile.printf("public:\n"); 400 String constructorArgs = printConstructor(name, nameScope, complexType, elements, 401 attributes, baseName); 402 403 // print getters and setters 404 for (int i = 0; i < elementTypes.size(); ++i) { 405 CppType type = elementTypes.get(i); 406 XsdElement element = elements.get(i); 407 XsdElement elementValue = resolveElement(element); 408 printGetter(nameScope + name, type, 409 Utils.toVariableName(getElementName(elementValue)), 410 type instanceof CppComplexType ? true : element.isMultiple(), 411 type instanceof CppComplexType ? false : ((CppSimpleType)type).isList(), 412 false); 413 } 414 for (int i = 0; i < attributeTypes.size(); ++i) { 415 CppType type = attributeTypes.get(i); 416 XsdAttribute attribute = resolveAttribute(attributes.get(i)); 417 printGetter(nameScope + name, type, Utils.toVariableName(attribute.getName()), 418 false, false, attribute.isRequired()); 419 } 420 if (valueType != null) { 421 printGetter(nameScope + name, valueType, "value", false, false, false); 422 } 423 424 printParser(name, nameScope, complexType, constructorArgs); 425 426 if (writer) { 427 printWriter(name, nameScope, complexType); 428 } 429 430 parserHeaderFile.println("};\n"); 431 } 432 printParser(String name, String nameScope, XsdComplexType complexType, String args)433 private void printParser(String name, String nameScope, XsdComplexType complexType, String args) 434 throws CppCodeGeneratorException { 435 CppSimpleType baseValueType = (complexType instanceof XsdSimpleContent) ? 436 getValueType((XsdSimpleContent) complexType, true) : null; 437 List<XsdElement> allElements = new ArrayList<>(); 438 List<XsdAttribute> allAttributes = new ArrayList<>(); 439 stackComponents(complexType, allElements, allAttributes); 440 441 // parse types for elements and attributes 442 List<CppType> allElementTypes = new ArrayList<>(); 443 for (XsdElement element : allElements) { 444 XsdElement elementValue = resolveElement(element); 445 CppType cppType = parseType(elementValue.getType(), elementValue.getName()); 446 allElementTypes.add(cppType); 447 } 448 List<CppSimpleType> allAttributeTypes = new ArrayList<>(); 449 for (XsdAttribute attribute : allAttributes) { 450 XsdType type = resolveAttribute(attribute).getType(); 451 allAttributeTypes.add(parseSimpleType(type, false)); 452 } 453 454 String fullName = nameScope + name; 455 parserHeaderFile.printf("static %s read(xmlNode *root);\n", fullName, Utils.lowerize(name)); 456 parserCppFile.printf("\n%s %s::read(xmlNode *root) {\n", fullName, fullName); 457 458 parserCppFile.print("std::string raw;\n"); 459 460 for (int i = 0; i < allAttributes.size(); ++i) { 461 CppSimpleType type = allAttributeTypes.get(i); 462 XsdAttribute attribute = resolveAttribute(allAttributes.get(i)); 463 String variableName = Utils.toVariableName(attribute.getName()); 464 parserCppFile.printf("raw = getXmlAttribute(root, \"%s\");\n", attribute.getName()); 465 if (attribute.isRequired()) { 466 if (type.isEnum()) { 467 parserCppFile.printf("%s %s = %s::%s;\n", 468 type.getName(), variableName, type.getName(), UNKNOWN_ENUM); 469 } else { 470 parserCppFile.printf("%s %s{};\n", type.getName(), variableName); 471 } 472 } else { 473 parserCppFile.printf("std::optional<%s> %s = std::nullopt;\n", type.getName(), 474 variableName); 475 } 476 parserCppFile.printf("if (raw != \"\") {\n"); 477 parserCppFile.print(type.getParsingExpression()); 478 parserCppFile.printf("%s = value;\n}\n", variableName); 479 } 480 481 if (baseValueType != null) { 482 parserCppFile.printf("auto xmlValue = make_xmlUnique(xmlNodeListGetString(" 483 + "root->doc, root->xmlChildrenNode, 1));\n" 484 + "if (xmlValue != nullptr) {\n" 485 + "raw = reinterpret_cast<const char*>(xmlValue.get());\n"); 486 487 parserCppFile.print(baseValueType.getParsingExpression()); 488 parserCppFile.printf("instance.setValue(value);\n"); 489 parserCppFile.printf("}\n"); 490 } else if (!allElements.isEmpty()) { 491 for (int i = 0; i < allElements.size(); ++i) { 492 CppType type = allElementTypes.get(i); 493 XsdElement element = allElements.get(i); 494 XsdElement elementValue = resolveElement(element); 495 String variableName = Utils.toVariableName(getElementName(elementValue)); 496 parserCppFile.printf("%s %s;\n", Utils.elementTypeName(type.getName(), 497 element.isMultiple() || type instanceof CppComplexType), variableName); 498 } 499 parserCppFile.print("for (xmlNode *child = root->xmlChildrenNode; child != nullptr;" 500 + " child = child->next) {\n"); 501 for (int i = 0; i < allElements.size(); ++i) { 502 CppType type = allElementTypes.get(i); 503 XsdElement element = allElements.get(i); 504 XsdElement elementValue = resolveElement(element); 505 String variableName = Utils.toVariableName(getElementName(elementValue)); 506 507 if (i != 0) parserCppFile.printf("} else "); 508 parserCppFile.print("if (!xmlStrcmp(child->name, reinterpret_cast<const xmlChar*>"); 509 parserCppFile.printf("(\"%s\"))) {\n", elementValue.getName()); 510 511 if (type instanceof CppSimpleType) { 512 parserCppFile.print("auto xmlValue = make_xmlUnique(xmlNodeListGetString("); 513 parserCppFile.print("child->doc, child->xmlChildrenNode, 1));\n"); 514 parserCppFile.print("if (xmlValue == nullptr) {\nraw = \"\";\n} else {\n"); 515 parserCppFile.print("raw = reinterpret_cast<const char*>(xmlValue.get());\n}"); 516 parserCppFile.print("\n"); 517 } 518 519 parserCppFile.print(type.getParsingExpression()); 520 521 if (element.isMultiple() || type instanceof CppComplexType) { 522 parserCppFile.printf("%s.push_back(std::move(value));\n", variableName); 523 } else { 524 parserCppFile.printf("%s = std::move(value);\n", variableName); 525 } 526 } 527 parserCppFile.printf("}\n}\n"); 528 } 529 parserCppFile.printf("%s instance%s;\n", 530 fullName, args.length() > 0 ? "(" + args + ")" : ""); 531 parserCppFile.print("return instance;\n}\n"); 532 } 533 printWriter(String name, String nameScope, XsdComplexType complexType)534 private void printWriter(String name, String nameScope, XsdComplexType complexType) 535 throws CppCodeGeneratorException { 536 CppSimpleType baseValueType = (complexType instanceof XsdSimpleContent) ? 537 getValueType((XsdSimpleContent) complexType, true) : null; 538 List<XsdElement> allElements = new ArrayList<>(); 539 List<XsdAttribute> allAttributes = new ArrayList<>(); 540 stackComponents(complexType, allElements, allAttributes); 541 542 // parse types for elements and attributes 543 List<CppType> allElementTypes = new ArrayList<>(); 544 for (XsdElement element : allElements) { 545 XsdElement elementValue = resolveElement(element); 546 CppType cppType = parseType(elementValue.getType(), elementValue.getName()); 547 allElementTypes.add(cppType); 548 } 549 List<CppSimpleType> allAttributeTypes = new ArrayList<>(); 550 for (XsdAttribute attribute : allAttributes) { 551 XsdType type = resolveAttribute(attribute).getType(); 552 allAttributeTypes.add(parseSimpleType(type, false)); 553 } 554 555 String fullName = nameScope + name; 556 parserHeaderFile.printf("void write(std::ostream& out, const std::string& name) const;\n"); 557 parserCppFile.printf( 558 "\nvoid %s::write(std::ostream& out, const std::string& name) const {\n", 559 fullName); 560 561 parserCppFile.printf("out << printIndent() << \"<\" << name;\n"); 562 for (int i = 0; i < allAttributes.size(); ++i) { 563 CppType type = allAttributeTypes.get(i); 564 XsdAttribute attribute = resolveAttribute(allAttributes.get(i)); 565 String variableName = Utils.toVariableName(attribute.getName()); 566 parserCppFile.printf("if (has%s()) {\n", Utils.capitalize(variableName)); 567 parserCppFile.printf("out << \" %s=\\\"\";\n", attribute.getName()); 568 parserCppFile.print(type.getWritingExpression(String.format("%s%s()", 569 getterName(type.getName()), Utils.capitalize(variableName)), 570 attribute.getName())); 571 parserCppFile.printf("out << \"\\\"\";\n}\n"); 572 } 573 parserCppFile.print("out << \">\" << std::endl;\n"); 574 parserCppFile.print("++indentIndex;\n"); 575 576 if (!allElements.isEmpty()) { 577 for (int i = 0; i < allElements.size(); ++i) { 578 CppType type = allElementTypes.get(i); 579 XsdElement element = allElements.get(i); 580 XsdElement elementValue = resolveElement(element); 581 String elementName = getElementName(elementValue); 582 String variableName = Utils.toVariableName(elementName); 583 584 if (type instanceof CppComplexType || element.isMultiple()) { 585 parserCppFile.printf("for (auto& value : get%s()) {\n", 586 Utils.capitalize(variableName)); 587 if (type instanceof CppSimpleType) { 588 parserCppFile.printf("out << printIndent() << \"<%s>\";\n", 589 elementValue.getName()); 590 } 591 parserCppFile.printf( 592 type.getWritingExpression("value", elementValue.getName())); 593 if (type instanceof CppSimpleType) { 594 parserCppFile.printf("out << \"</%s>\" << std::endl;\n", 595 elementValue.getName()); 596 } 597 parserCppFile.printf("}\n"); 598 } else { 599 parserCppFile.printf("if (has%s()) {\n", Utils.capitalize(variableName)); 600 if (type instanceof CppSimpleType) { 601 parserCppFile.printf("out << printIndent() << \"<%s>\";\n", 602 elementValue.getName()); 603 } 604 parserCppFile.print(type.getWritingExpression(String.format("%s%s()", 605 getterName(type.getName()), Utils.capitalize(variableName)), 606 elementValue.getName())); 607 if (type instanceof CppSimpleType) { 608 parserCppFile.printf("out << \"</%s>\" << std::endl;\n", 609 elementValue.getName()); 610 } 611 parserCppFile.print("}\n"); 612 } 613 } 614 } 615 parserCppFile.print("--indentIndex;\n"); 616 parserCppFile.printf("out << printIndent() << \"</\" << name << \">\" << std::endl;\n"); 617 parserCppFile.printf("}\n"); 618 } 619 printGetter(String name, CppType type, String variableName, boolean isMultiple, boolean isMultipleType, boolean isRequired)620 private void printGetter(String name, CppType type, String variableName, 621 boolean isMultiple, boolean isMultipleType, boolean isRequired) { 622 String typeName = isMultiple ? String.format("std::vector<%s>", 623 type.getName()) : type.getName(); 624 625 parserHeaderFile.printf("const %s& %s%s() const;\n", typeName, getterName(typeName), 626 Utils.capitalize(variableName)); 627 628 parserCppFile.println(); 629 parserCppFile.printf("const %s& %s::%s%s() const {\n" 630 + "return %s;\n}\n\n", 631 typeName, name, getterName(typeName), Utils.capitalize(variableName), 632 isMultiple || isRequired ? 633 variableName + "_" : String.format("%s_.value()", variableName)); 634 635 parserHeaderFile.printf("bool has%s() const;\n", Utils.capitalize(variableName)); 636 parserCppFile.printf("bool %s::has%s() const {\n", name, Utils.capitalize(variableName)); 637 if (isMultiple) { 638 parserCppFile.printf("return !(%s_.empty());\n}\n", variableName); 639 } else if (isRequired){ 640 parserCppFile.print("return true;\n}\n"); 641 } else { 642 parserCppFile.printf("return %s_.has_value();\n}\n", variableName); 643 } 644 645 if (isMultiple || isMultipleType) { 646 String elementTypeName = type instanceof CppComplexType ? type.getName() : 647 ((CppSimpleType)type).getTypeName(); 648 if (elementTypeName.equals("bool")) { 649 parserHeaderFile.printf("%s getFirst%s() const;\n", 650 elementTypeName, Utils.capitalize(variableName)); 651 parserCppFile.println(); 652 parserCppFile.printf("%s %s::getFirst%s() const {\n" 653 + "if (%s_%sempty()) {\n" 654 + "return false;\n" 655 + "}\n" 656 + "return %s;\n" 657 + "}\n", 658 elementTypeName, name, Utils.capitalize(variableName), variableName, 659 isMultiple ? "." : "->", 660 isMultiple ? String.format("%s_[0]", variableName) : 661 String.format("%s_.value()[0]", variableName)); 662 } else { 663 parserHeaderFile.printf("const %s* getFirst%s() const;\n", 664 elementTypeName, Utils.capitalize(variableName)); 665 parserCppFile.println(); 666 parserCppFile.printf("const %s* %s::getFirst%s() const {\n" 667 + "if (%s_%sempty()) {\n" 668 + "return nullptr;\n" 669 + "}\n" 670 + "return &%s;\n" 671 + "}\n", 672 elementTypeName, name, Utils.capitalize(variableName), variableName, 673 isMultiple ? "." : "->", 674 isMultiple ? String.format("%s_[0]", variableName) : 675 String.format("%s_.value()[0]", variableName)); 676 } 677 } 678 } 679 printConstructor(String name, String nameScope, XsdComplexType complexType, List<XsdElement> elements, List<XsdAttribute> attributes, String baseName)680 private String printConstructor(String name, String nameScope, XsdComplexType complexType, 681 List<XsdElement> elements, List<XsdAttribute> attributes, String baseName) 682 throws CppCodeGeneratorException { 683 String fullName = nameScope + name; 684 StringBuilder constructorArgs = new StringBuilder(); 685 StringBuilder parentArgs = new StringBuilder(); 686 StringBuilder constructor = new StringBuilder(); 687 StringBuilder args = new StringBuilder(); 688 689 List<XsdElement> allElements = new ArrayList<>(); 690 List<XsdAttribute> allAttributes = new ArrayList<>(); 691 stackComponents(complexType, allElements, allAttributes); 692 693 List<CppType> allElementTypes = new ArrayList<>(); 694 for (XsdElement element : allElements) { 695 XsdElement elementValue = resolveElement(element); 696 CppType type = parseType(elementValue.getType(), elementValue.getName()); 697 String variableName = Utils.toVariableName(getElementName(elementValue)); 698 constructorArgs.append(String.format(", %s %s", Utils.elementTypeName(type.getName(), 699 element.isMultiple() || type instanceof CppComplexType), variableName)); 700 args.append(String.format(", %s", variableName)); 701 boolean isMultipleType; 702 if (type instanceof CppComplexType) { 703 isMultipleType = true; 704 } else if (((CppSimpleType)type).isList()) { 705 isMultipleType = true; 706 } else { 707 isMultipleType = false; 708 } 709 710 if (elements.contains(element)) { 711 constructor.append(String.format(", %s_(%s)", variableName, 712 Utils.toAssignmentName(type.getName(), variableName, isMultipleType))); 713 } else { 714 parentArgs.append(String.format(", %s", variableName)); 715 } 716 } 717 List<CppSimpleType> allAttributeTypes = new ArrayList<>(); 718 for (XsdAttribute attribute : allAttributes) { 719 CppType type = parseSimpleType(resolveAttribute(attribute).getType(), false); 720 String variableName = Utils.toVariableName(resolveAttribute(attribute).getName()); 721 if (attribute.isRequired()) { 722 constructorArgs.append(String.format(", %s %s", type.getName(), variableName)); 723 } else { 724 constructorArgs.append(String.format(", std::optional<%s> %s", type.getName(), 725 variableName)); 726 } 727 args.append(String.format(", %s", variableName)); 728 boolean isMultipleType = ((CppSimpleType)type).isList() ? true : false; 729 if (attributes.contains(attribute)) { 730 constructor.append(String.format(", %s_(%s)", variableName, 731 Utils.toAssignmentName(type.getName(), variableName, isMultipleType))); 732 } else { 733 parentArgs.append(String.format(", %s", variableName)); 734 } 735 } 736 737 String constructorArgsString = constructorArgs.toString(); 738 String constructorString = constructor.toString(); 739 if (constructorArgsString.length() > 0) { 740 constructorArgsString = constructorArgsString.substring(2); 741 } 742 743 boolean useExplicit = 744 !(constructorArgsString.isEmpty() || constructorArgsString.contains(",")); 745 if (useExplicit) { 746 parserHeaderFile.printf("explicit %s(%s);\n", name, constructorArgsString); 747 } else { 748 parserHeaderFile.printf("%s(%s);\n", name, constructorArgsString); 749 } 750 parserCppFile.printf("\n%s::%s(%s) : ", fullName, name, constructorArgsString); 751 752 String parentArgsString = parentArgs.toString(); 753 if (parentArgsString.length() > 0) { 754 parentArgsString = parentArgsString.substring(2); 755 parserCppFile.printf("%s(%s)", baseName, parentArgsString); 756 } else { 757 constructorString = constructorString.substring(2); 758 } 759 parserCppFile.printf("%s {\n}\n", constructorString); 760 761 String argsString = args.toString(); 762 if (argsString.length() > 0) { 763 argsString = argsString.substring(2); 764 } 765 return argsString; 766 } 767 printXmlParser()768 private void printXmlParser() throws CppCodeGeneratorException { 769 parserCppFile.printf("template <class T>\n" 770 + "constexpr void (*xmlDeleter)(T* t);\n" 771 + "template <>\nconstexpr auto xmlDeleter<xmlDoc> = xmlFreeDoc;\n" 772 + "template <>\nauto xmlDeleter<xmlChar> = [](xmlChar *s) { xmlFree(s); };\n\n" 773 + "template <class T>\n" 774 + "constexpr auto make_xmlUnique(T *t) {\n" 775 + "auto deleter = [](T *t) { xmlDeleter<T>(t); };\n" 776 + "return std::unique_ptr<T, decltype(deleter)>{t, deleter};\n" 777 + "}\n\n"); 778 779 if (hasAttr) { 780 parserCppFile.printf("static std::string getXmlAttribute" 781 + "(const xmlNode *cur, const char *attribute) {\n" 782 + "auto xmlValue = make_xmlUnique(xmlGetProp(cur, " 783 + "reinterpret_cast<const xmlChar*>(attribute)));\n" 784 + "if (xmlValue == nullptr) {\n" 785 + "return \"\";\n" 786 + "}\n" 787 + "std::string value(reinterpret_cast<const char*>(xmlValue.get()));\n" 788 + "return value;\n" 789 + "}\n\n"); 790 } 791 792 String className = Utils.toClassName(pkgName); 793 794 boolean isMultiRootElement = xmlSchema.getElementMap().values().size() > 1; 795 for (XsdElement element : xmlSchema.getElementMap().values()) { 796 CppType cppType = parseType(element.getType(), element.getName()); 797 String elementName = element.getName(); 798 String VariableName = Utils.toVariableName(elementName); 799 String typeName = cppType instanceof CppSimpleType ? cppType.getName() : 800 Utils.toClassName(cppType.getName()); 801 802 parserHeaderFile.printf("std::optional<%s> read%s(const char* configFile);\n\n", 803 typeName, isMultiRootElement ? Utils.capitalize(typeName) : ""); 804 parserCppFile.printf("std::optional<%s> read%s(const char* configFile) {\n", 805 typeName, isMultiRootElement ? Utils.capitalize(typeName) : ""); 806 parserCppFile.printf("auto doc = make_xmlUnique(xmlParseFile(configFile));\n" 807 + "if (doc == nullptr) {\n" 808 + "return std::nullopt;\n" 809 + "}\n" 810 + "xmlNodePtr child = xmlDocGetRootElement(doc.get());\n" 811 + "if (child == nullptr) {\n" 812 + "return std::nullopt;\n" 813 + "}\n" 814 + "if (xmlXIncludeProcess(doc.get()) < 0) {\n" 815 + "return std::nullopt;\n" 816 + "}\n\n" 817 + "if (!xmlStrcmp(child->name, reinterpret_cast<const xmlChar*>" 818 + "(\"%s\"))) {\n", 819 elementName); 820 821 if (cppType instanceof CppSimpleType) { 822 parserCppFile.printf("%s value = getXmlAttribute(child, \"%s\");\n", 823 elementName, elementName); 824 } else { 825 parserCppFile.printf(cppType.getParsingExpression()); 826 } 827 parserCppFile.printf("return value;\n}\n"); 828 parserCppFile.printf("return std::nullopt;\n"); 829 parserCppFile.printf("}\n\n"); 830 } 831 } 832 printXmlWriter()833 private void printXmlWriter() throws CppCodeGeneratorException { 834 for (XsdElement element : xmlSchema.getElementMap().values()) { 835 CppType cppType = parseType(element.getType(), element.getName()); 836 String elementName = element.getName(); 837 String VariableName = Utils.toVariableName(elementName); 838 String typeName = cppType instanceof CppSimpleType ? cppType.getName() : 839 Utils.toClassName(cppType.getName()); 840 parserHeaderFile.printf("void write(std::ostream& out, %s& %s);\n\n", 841 typeName, VariableName); 842 parserCppFile.printf("void write(std::ostream& out, %s& %s) {\n", 843 typeName, VariableName); 844 845 parserCppFile.print( 846 "out << \"<?xml version=\\\"1.0\\\" encoding=\\\"utf-8\\\"?>\\n\";\n"); 847 parserCppFile.printf("%s.write(out, \"%s\");\n", VariableName, elementName); 848 parserCppFile.printf("}\n\n"); 849 } 850 851 parserCppFile.print("static int indentIndex = 0;\n" 852 + "std::string printIndent() {\n" 853 + "std::string s = \"\";\n" 854 + "for (int index = 0; index < indentIndex; ++index) {\n" 855 + "s += \" \";\n" 856 + "}\nreturn s;\n}\n\n"); 857 } 858 getElementName(XsdElement element)859 private String getElementName(XsdElement element) { 860 if (element instanceof XsdChoice) { 861 return element.getName() + "_optional"; 862 } else if (element instanceof XsdAll) { 863 return element.getName() + "_all"; 864 } 865 return element.getName(); 866 } 867 getterName(String type)868 private String getterName(String type) { 869 if (type.equals("bool") && booleanGetter) { 870 return "is"; 871 } 872 return "get"; 873 } 874 stackComponents(XsdComplexType complexType, List<XsdElement> elements, List<XsdAttribute> attributes)875 private void stackComponents(XsdComplexType complexType, List<XsdElement> elements, 876 List<XsdAttribute> attributes) throws CppCodeGeneratorException { 877 if (complexType.getBase() != null) { 878 QName baseRef = complexType.getBase().getRef(); 879 if (baseRef != null && !baseRef.getNamespaceURI().equals(XsdConstants.XSD_NAMESPACE)) { 880 XsdType parent = getType(baseRef.getLocalPart()); 881 if (parent instanceof XsdComplexType) { 882 stackComponents((XsdComplexType) parent, elements, attributes); 883 } 884 } 885 } 886 elements.addAll(getAllElements(complexType.getGroup())); 887 elements.addAll(complexType.getElements()); 888 for (XsdAttributeGroup attributeGroup : complexType.getAttributeGroups()) { 889 attributes.addAll(getAllAttributes(resolveAttributeGroup(attributeGroup))); 890 } 891 attributes.addAll(complexType.getAttributes()); 892 } 893 getAllAttributes(XsdAttributeGroup attributeGroup)894 private List<XsdAttribute> getAllAttributes(XsdAttributeGroup attributeGroup) 895 throws CppCodeGeneratorException{ 896 List<XsdAttribute> attributes = new ArrayList<>(); 897 for (XsdAttributeGroup attrGroup : attributeGroup.getAttributeGroups()) { 898 attributes.addAll(getAllAttributes(resolveAttributeGroup(attrGroup))); 899 } 900 attributes.addAll(attributeGroup.getAttributes()); 901 return attributes; 902 } 903 getAllElements(XsdGroup group)904 private List<XsdElement> getAllElements(XsdGroup group) throws CppCodeGeneratorException { 905 List<XsdElement> elements = new ArrayList<>(); 906 if (group == null) { 907 return elements; 908 } 909 elements.addAll(getAllElements(resolveGroup(group))); 910 elements.addAll(group.getElements()); 911 return elements; 912 } 913 914 getBaseName(XsdComplexType complexType)915 private String getBaseName(XsdComplexType complexType) throws CppCodeGeneratorException { 916 if (complexType.getBase() == null) return null; 917 if (complexType.getBase().getRef().getNamespaceURI().equals(XsdConstants.XSD_NAMESPACE)) { 918 return null; 919 } 920 XsdType base = getType(complexType.getBase().getRef().getLocalPart()); 921 if (base instanceof XsdComplexType) { 922 return Utils.toClassName(base.getName()); 923 } 924 return null; 925 } 926 getValueType(XsdSimpleContent simpleContent, boolean traverse)927 private CppSimpleType getValueType(XsdSimpleContent simpleContent, boolean traverse) 928 throws CppCodeGeneratorException { 929 assert simpleContent.getBase() != null; 930 QName baseRef = simpleContent.getBase().getRef(); 931 assert baseRef != null; 932 if (baseRef.getNamespaceURI().equals(XsdConstants.XSD_NAMESPACE)) { 933 return predefinedType(baseRef.getLocalPart()); 934 } else { 935 XsdType parent = getType(baseRef.getLocalPart()); 936 if (parent instanceof XsdSimpleType) { 937 return parseSimpleTypeReference(baseRef, false); 938 } 939 if (!traverse) return null; 940 if (parent instanceof XsdSimpleContent) { 941 return getValueType((XsdSimpleContent) parent, true); 942 } else { 943 throw new CppCodeGeneratorException( 944 String.format("base not simple : %s", baseRef.getLocalPart())); 945 } 946 } 947 } 948 parseType(XsdType type, String defaultName)949 private CppType parseType(XsdType type, String defaultName) throws CppCodeGeneratorException { 950 if (type.getRef() != null) { 951 String name = type.getRef().getLocalPart(); 952 if (type.getRef().getNamespaceURI().equals(XsdConstants.XSD_NAMESPACE)) { 953 return predefinedType(name); 954 } else { 955 XsdType typeValue = getType(name); 956 if (typeValue instanceof XsdSimpleType) { 957 return parseSimpleTypeReference(type.getRef(), false); 958 } 959 return parseType(typeValue, name); 960 } 961 } 962 if (type instanceof XsdComplexType) { 963 return new CppComplexType(Utils.toClassName(defaultName)); 964 } else if (type instanceof XsdSimpleType) { 965 return parseSimpleTypeValue((XsdSimpleType) type, false); 966 } else { 967 throw new CppCodeGeneratorException( 968 String.format("unknown type name : %s", defaultName)); 969 } 970 } 971 parseSimpleType(XsdType type, boolean traverse)972 private CppSimpleType parseSimpleType(XsdType type, boolean traverse) 973 throws CppCodeGeneratorException { 974 if (type.getRef() != null) { 975 return parseSimpleTypeReference(type.getRef(), traverse); 976 } else { 977 return parseSimpleTypeValue((XsdSimpleType) type, traverse); 978 } 979 } 980 parseSimpleTypeReference(QName typeRef, boolean traverse)981 private CppSimpleType parseSimpleTypeReference(QName typeRef, boolean traverse) 982 throws CppCodeGeneratorException { 983 assert typeRef != null; 984 String typeName = typeRef.getLocalPart(); 985 if (typeRef.getNamespaceURI().equals(XsdConstants.XSD_NAMESPACE)) { 986 return predefinedType(typeName); 987 } 988 if (cppSimpleTypeMap.containsKey(typeName)) { 989 return cppSimpleTypeMap.get(typeName); 990 } else if (traverse) { 991 XsdSimpleType simpleType = getSimpleType(typeName); 992 CppSimpleType ret = parseSimpleTypeValue(simpleType, true); 993 cppSimpleTypeMap.put(typeName, ret); 994 return ret; 995 } else { 996 throw new CppCodeGeneratorException(String.format("unknown type name : %s", typeName)); 997 } 998 } 999 parseSimpleTypeValue(XsdSimpleType simpleType, boolean traverse)1000 private CppSimpleType parseSimpleTypeValue(XsdSimpleType simpleType, boolean traverse) 1001 throws CppCodeGeneratorException { 1002 if (simpleType instanceof XsdList) { 1003 XsdList list = (XsdList) simpleType; 1004 return parseSimpleType(list.getItemType(), traverse).newListType(); 1005 } else if (simpleType instanceof XsdRestriction) { 1006 // we don't consider any restrictions. 1007 XsdRestriction restriction = (XsdRestriction) simpleType; 1008 if (restriction.getEnums() != null) { 1009 String name = Utils.toClassName(restriction.getName()); 1010 return new CppSimpleType(name, "stringTo" + name + "(%s)", false, true); 1011 } 1012 return parseSimpleType(restriction.getBase(), traverse); 1013 } else if (simpleType instanceof XsdUnion) { 1014 // unions are almost always interpreted as java.lang.String 1015 // Exceptionally, if any of member types of union are 'list', then we interpret it as 1016 // List<String> 1017 XsdUnion union = (XsdUnion) simpleType; 1018 for (XsdType memberType : union.getMemberTypes()) { 1019 if (parseSimpleType(memberType, traverse).isList()) { 1020 return new CppSimpleType("std::string", "%s", true); 1021 } 1022 } 1023 return new CppSimpleType("std::string", "%s", false); 1024 } else { 1025 // unreachable 1026 throw new IllegalStateException("unknown simple type"); 1027 } 1028 } 1029 resolveElement(XsdElement element)1030 private XsdElement resolveElement(XsdElement element) throws CppCodeGeneratorException { 1031 if (element.getRef() == null) return element; 1032 String name = element.getRef().getLocalPart(); 1033 XsdElement ret = xmlSchema.getElementMap().get(name); 1034 if (ret != null) return ret; 1035 throw new CppCodeGeneratorException(String.format("no element named : %s", name)); 1036 } 1037 resolveGroup(XsdGroup group)1038 private XsdGroup resolveGroup(XsdGroup group) throws CppCodeGeneratorException { 1039 if (group.getRef() == null) return null; 1040 String name = group.getRef().getLocalPart(); 1041 XsdGroup ret = xmlSchema.getGroupMap().get(name); 1042 if (ret != null) return ret; 1043 throw new CppCodeGeneratorException(String.format("no group named : %s", name)); 1044 } 1045 resolveAttribute(XsdAttribute attribute)1046 private XsdAttribute resolveAttribute(XsdAttribute attribute) 1047 throws CppCodeGeneratorException { 1048 if (attribute.getRef() == null) return attribute; 1049 String name = attribute.getRef().getLocalPart(); 1050 XsdAttribute ret = xmlSchema.getAttributeMap().get(name); 1051 if (ret != null) return ret; 1052 throw new CppCodeGeneratorException(String.format("no attribute named : %s", name)); 1053 } 1054 resolveAttributeGroup(XsdAttributeGroup attributeGroup)1055 private XsdAttributeGroup resolveAttributeGroup(XsdAttributeGroup attributeGroup) 1056 throws CppCodeGeneratorException { 1057 if (attributeGroup.getRef() == null) return attributeGroup; 1058 String name = attributeGroup.getRef().getLocalPart(); 1059 XsdAttributeGroup ret = xmlSchema.getAttributeGroupMap().get(name); 1060 if (ret != null) return ret; 1061 throw new CppCodeGeneratorException(String.format("no attribute group named : %s", name)); 1062 } 1063 getType(String name)1064 private XsdType getType(String name) throws CppCodeGeneratorException { 1065 XsdType type = xmlSchema.getTypeMap().get(name); 1066 if (type != null) return type; 1067 throw new CppCodeGeneratorException(String.format("no type named : %s", name)); 1068 } 1069 getSimpleType(String name)1070 private XsdSimpleType getSimpleType(String name) throws CppCodeGeneratorException { 1071 XsdType type = getType(name); 1072 if (type instanceof XsdSimpleType) return (XsdSimpleType) type; 1073 throw new CppCodeGeneratorException(String.format("not a simple type : %s", name)); 1074 } 1075 hasAttribute(XsdComplexType complexType)1076 private boolean hasAttribute(XsdComplexType complexType) throws CppCodeGeneratorException { 1077 if (complexType.getAttributes().size() > 0 || 1078 complexType.getAttributeGroups().size() > 0) { 1079 return true; 1080 } 1081 boolean results = false; 1082 for (XsdElement element : complexType.getElements()) { 1083 XsdElement elementValue = resolveElement(element); 1084 if (element.getRef() == null && element.getType().getRef() == null 1085 && element.getType() instanceof XsdComplexType) { 1086 results = hasAttribute((XsdComplexType) element.getType()); 1087 if (results) { 1088 return results; 1089 } 1090 } 1091 } 1092 return results; 1093 } 1094 predefinedType(String name)1095 private static CppSimpleType predefinedType(String name) throws CppCodeGeneratorException { 1096 switch (name) { 1097 case "string": 1098 case "token": 1099 case "normalizedString": 1100 case "language": 1101 case "ENTITY": 1102 case "ID": 1103 case "Name": 1104 case "NCName": 1105 case "NMTOKEN": 1106 case "anyURI": 1107 case "anyType": 1108 case "QName": 1109 case "NOTATION": 1110 case "IDREF": 1111 return new CppSimpleType("std::string", "%s", false); 1112 case "ENTITIES": 1113 case "NMTOKENS": 1114 case "IDREFS": 1115 return new CppSimpleType("std::string", "%s", true); 1116 case "date": 1117 case "dateTime": 1118 case "time": 1119 case "gDay": 1120 case "gMonth": 1121 case "gYear": 1122 case "gMonthDay": 1123 case "gYearMonth": 1124 case "duration": 1125 return new CppSimpleType("std::string", "%s", false); 1126 case "decimal": 1127 return new CppSimpleType("double", "std::stod(%s)", false); 1128 case "integer": 1129 case "negativeInteger": 1130 case "nonNegativeInteger": 1131 case "positiveInteger": 1132 case "nonPositiveInteger": 1133 return new CppSimpleType("int64_t", "std::stoll(%s)", false); 1134 case "unsignedLong": 1135 return new CppSimpleType("uint64_t", "std::stoull(%s)", false); 1136 case "long": 1137 return new CppSimpleType("int64_t", "std::stoll(%s)", false); 1138 case "unsignedInt": 1139 return new CppSimpleType("unsigned int", 1140 "static_cast<unsigned int>(stoul(%s))", false); 1141 case "int": 1142 return new CppSimpleType("int", "std::stoi(%s)", false); 1143 case "unsignedShort": 1144 return new CppSimpleType("unsigned short", 1145 "static_cast<unsigned short>(std::stoi(%s))", false); 1146 case "short": 1147 return new CppSimpleType("short", "static_cast<short>(std::stoi(%s))", false); 1148 case "unsignedByte": 1149 return new CppSimpleType("unsigned char", 1150 "static_cast<unsigned char>(std::stoi(%s))", false); 1151 case "byte": 1152 return new CppSimpleType("char", "static_cast<char>(std::stoi(%s))", false); 1153 case "boolean": 1154 return new CppSimpleType("bool", "%s == \"true\"", false); 1155 case "double": 1156 return new CppSimpleType("double", "std::stod(%s)", false); 1157 case "float": 1158 return new CppSimpleType("float", "std::stof(%s)", false); 1159 case "base64Binary": 1160 case "hexBinary": 1161 return new CppSimpleType("std::string", "%s", false); 1162 } 1163 throw new CppCodeGeneratorException("unknown xsd predefined type : " + name); 1164 } 1165 } 1166