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; 18 19 import java.io.File; 20 import java.io.FileInputStream; 21 import java.nio.file.Paths; 22 23 import static java.lang.System.exit; 24 25 import com.android.xsdc.java.JavaCodeGenerator; 26 import com.android.xsdc.cpp.CppCodeGenerator; 27 28 import org.apache.commons.cli.CommandLine; 29 import org.apache.commons.cli.CommandLineParser; 30 import org.apache.commons.cli.GnuParser; 31 import org.apache.commons.cli.HelpFormatter; 32 import org.apache.commons.cli.Option; 33 import org.apache.commons.cli.OptionBuilder; 34 import org.apache.commons.cli.OptionGroup; 35 import org.apache.commons.cli.Options; 36 import org.apache.commons.cli.ParseException; 37 38 import javax.xml.parsers.SAXParser; 39 import javax.xml.parsers.SAXParserFactory; 40 41 public class Main { main(String[] args)42 public static void main(String[] args) throws Exception { 43 Options options = new Options(); 44 options.addOption(OptionBuilder 45 .withLongOpt("package") 46 .hasArgs(1) 47 .withDescription("Package name of the generated java file. " + 48 "file name of generated cpp file and header") 49 .create("p")); 50 options.addOption(OptionBuilder 51 .withLongOpt("outDir") 52 .hasArgs(1) 53 .withDescription("Out Directory") 54 .create("o")); 55 options.addOption(OptionBuilder 56 .withLongOpt("java") 57 .hasArgs(0) 58 .withDescription("Generate Java code.") 59 .create("j")); 60 options.addOption(OptionBuilder 61 .withLongOpt("cpp") 62 .hasArgs(0) 63 .withDescription("Generate Cpp code.") 64 .create("c")); 65 options.addOption(OptionBuilder 66 .withLongOpt("writer") 67 .hasArgs(0) 68 .withDescription("Generate Writer code.") 69 .create("w")); 70 options.addOption(OptionBuilder 71 .withLongOpt("nullability") 72 .hasArgs(0) 73 .withDescription("Add @NonNull or @Nullable annotation to generated java code.") 74 .create("n")); 75 options.addOption(OptionBuilder 76 .withLongOpt("genHas") 77 .hasArgs(0) 78 .withDescription("Generate public hasX() method") 79 .create("g")); 80 options.addOption(OptionBuilder 81 .withLongOpt("booleanGetter") 82 .hasArgs(0) 83 .withDescription("Generate isX() for boolean element or attribute.") 84 .create("b")); 85 Option genEnumsOnly = OptionBuilder 86 .withLongOpt("genEnumsOnly") 87 .hasArgs(0) 88 .withDescription("Only generate enum converters in Cpp code.") 89 .create("e"); 90 options.addOption(genEnumsOnly); 91 Option genParserOnly = OptionBuilder 92 .withLongOpt("genParserOnly") 93 .hasArgs(0) 94 .withDescription("Only generate XML parser in Cpp code.") 95 .create("x"); 96 options.addOption(genParserOnly); 97 // "Only generate enums" and "Only generate parser" options are mutually exclusive. 98 OptionGroup genOnlyGroup = new OptionGroup(); 99 genOnlyGroup.setRequired(false); 100 genOnlyGroup.addOption(genEnumsOnly); 101 genOnlyGroup.addOption(genParserOnly); 102 options.addOptionGroup(genOnlyGroup); 103 104 CommandLineParser CommandParser = new GnuParser(); 105 CommandLine cmd; 106 107 try { 108 cmd = CommandParser.parse(options, args); 109 } catch (ParseException e) { 110 System.err.println(e.getMessage()); 111 help(options); 112 return; 113 } 114 115 String[] xsdFile = cmd.getArgs(); 116 String packageName = cmd.getOptionValue('p', null); 117 String outDir = cmd.getOptionValue('o', null); 118 boolean writer = cmd.hasOption('w'); 119 boolean nullability = cmd.hasOption('n'); 120 boolean genHas = cmd.hasOption('g'); 121 boolean enumsOnly = cmd.hasOption('e'); 122 boolean parserOnly = cmd.hasOption('x'); 123 boolean booleanGetter = cmd.hasOption('b'); 124 125 if (xsdFile.length != 1 || packageName == null) { 126 System.err.println("Error: no xsd files or package name"); 127 help(options); 128 } 129 130 if (outDir == null) { 131 outDir = "."; 132 } 133 134 XmlSchema xmlSchema = parse(xsdFile[0]); 135 136 if (cmd.hasOption('j')) { 137 File packageDir = new File(Paths.get(outDir, packageName.replace(".", "/")).toString()); 138 packageDir.mkdirs(); 139 FileSystem fs = new FileSystem(packageDir); 140 JavaCodeGenerator javaCodeGenerator = 141 new JavaCodeGenerator(xmlSchema, packageName, writer, nullability, genHas, 142 booleanGetter); 143 javaCodeGenerator.print(fs); 144 } else if (cmd.hasOption('c')) { 145 File includeDir = new File(Paths.get(outDir, "include").toString()); 146 includeDir.mkdirs(); 147 FileSystem fs = new FileSystem(new File(outDir)); 148 int generators = enumsOnly ? CppCodeGenerator.GENERATE_ENUMS : 149 (parserOnly ? CppCodeGenerator.GENERATE_PARSER : 150 CppCodeGenerator.GENERATE_ENUMS | CppCodeGenerator.GENERATE_PARSER); 151 CppCodeGenerator cppCodeGenerator = 152 new CppCodeGenerator(xmlSchema, packageName, writer, generators, booleanGetter); 153 cppCodeGenerator.print(fs); 154 } 155 } 156 parse(String xsdFile)157 private static XmlSchema parse(String xsdFile) throws Exception { 158 XmlSchema xmlSchema; 159 try (FileInputStream in = new FileInputStream(xsdFile)) { 160 SAXParserFactory factory = SAXParserFactory.newInstance(); 161 factory.setNamespaceAware(true); 162 SAXParser parser = factory.newSAXParser(); 163 XsdHandler xsdHandler = new XsdHandler(); 164 parser.parse(in, xsdHandler); 165 xmlSchema = xsdHandler.getSchema(); 166 } 167 for (String file : xmlSchema.getIncludeList()) { 168 XmlSchema temp = parse(Paths.get(xsdFile).resolveSibling(file).toString()); 169 xmlSchema.include(temp); 170 } 171 return xmlSchema; 172 } 173 help(Options options)174 private static void help(Options options) { 175 new HelpFormatter().printHelp( 176 "xsdc path/to/xsd_file.xsd","", options, null, true); 177 System.exit(1); 178 } 179 } 180