1# Copyright (C) 2023 The Android Open Source Project 2# 3# Licensed under the Apache License, Version 2.0 (the "License"); 4# you may not use this file except in compliance with the License. 5# You may obtain a copy of the License at 6# 7# http://www.apache.org/licenses/LICENSE-2.0 8# 9# Unless required by applicable law or agreed to in writing, software 10# distributed under the License is distributed on an "AS IS" BASIS, 11# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12# See the License for the specific language governing permissions and 13# limitations under the License. 14 15load(":library.bzl", "java_library") 16 17# Return the relative directory where the java file should be generated 18def _java_gen_dir(ctx): 19 return ctx.attr.name 20 21# Return the filename of the srcjar containing the generated .java files 22def _java_gen_srcjar(ctx): 23 return ctx.attr.name + ".srcjar" 24 25def _xsdc_args(ctx, intermediate_dir): 26 args = ctx.actions.args() 27 args.add(ctx.file.src) 28 args.add("-p", ctx.attr.package_name) 29 args.add("-j") # Generate java 30 args.add("-o", intermediate_dir.path) # Pass the output directory 31 32 if ctx.attr.nullability: 33 args.add("-n") 34 35 if ctx.attr.gen_has: 36 args.add("-g") 37 38 if ctx.attr.gen_writer: 39 args.add("-w") 40 41 if ctx.attr.boolean_getter: 42 args.add("-b") 43 44 for root_element in ctx.attr.root_elements: 45 args.add("-r", root_element) 46 47 return args 48 49def _zip_args(ctx, output_srcjar, intermediate_dir): 50 args = ctx.actions.args() 51 args.add("-jar") 52 args.add("-o", output_srcjar) 53 args.add("-C", intermediate_dir.path) 54 args.add("-D", intermediate_dir.path) 55 56 # The java files inside the sandbox are symlinks 57 # Instruct soong_zip to follow the symlinks 58 args.add("-symlinks=false") 59 return args 60 61def _java_xsd_codegen_impl(ctx): 62 intermediate_dir = ctx.actions.declare_directory( 63 _java_gen_dir(ctx), 64 ) 65 output_srcjar = ctx.actions.declare_file(_java_gen_srcjar(ctx)) 66 67 # Run xsdc to generate the .java files in an intermedite directory 68 ctx.actions.run( 69 executable = ctx.executable._xsdc, 70 inputs = [ctx.file.src] + ctx.files.include_files, 71 outputs = [intermediate_dir], 72 arguments = [ 73 _xsdc_args(ctx, intermediate_dir), 74 ], 75 tools = [ 76 ctx.executable._xsdc, 77 ], 78 mnemonic = "XsdcJavaCompile", 79 progress_message = "Generating java files for %s" % ctx.file.src, 80 ) 81 82 # Zip the intermediate directory to a srcjar 83 ctx.actions.run( 84 executable = ctx.executable._soong_zip, 85 inputs = [intermediate_dir], 86 outputs = [output_srcjar], 87 arguments = [ 88 _zip_args(ctx, output_srcjar, intermediate_dir), 89 ], 90 tools = [ 91 ctx.executable._soong_zip, 92 ], 93 mnemonic = "XsdcJavaZip", 94 progress_message = "Generating srcjar for %s" % ctx.file.src, 95 ) 96 97 return [ 98 DefaultInfo( 99 files = depset([output_srcjar]), 100 ), 101 ] 102 103_java_xsd_codegen = rule( 104 implementation = _java_xsd_codegen_impl, 105 doc = "This rule generates .java parser files from an xsd file using xsdc", 106 attrs = { 107 "src": attr.label( 108 allow_single_file = [".xsd"], 109 doc = "The main xsd file", 110 mandatory = True, 111 ), 112 "include_files": attr.label_list( 113 allow_files = [".xsd"], 114 doc = "The (transitive) xsd files included by `src` using xs:include", 115 ), 116 "package_name": attr.string( 117 doc = "Package name to use in the generated .java files", 118 mandatory = True, 119 ), 120 "nullability": attr.bool( 121 doc = "Add @NonNull or @Nullable annotation to the generated .java files", 122 default = False, 123 ), 124 "gen_has": attr.bool( 125 doc = "Generate public hasX() method", 126 default = False, 127 ), 128 "gen_writer": attr.bool( 129 doc = "Add xml writer to the generated .java files", 130 ), 131 "boolean_getter": attr.bool( 132 doc = "Whether getter name of boolean element or attribute is getX or isX. If true, getter name is isX", 133 default = False, 134 ), 135 "root_elements": attr.string_list( 136 doc = "If set, xsdc will generate parser code only for the specified root elements", 137 ), 138 "_xsdc": attr.label( 139 executable = True, 140 cfg = "exec", 141 default = Label("//system/tools/xsdc"), 142 ), 143 "_soong_zip": attr.label( 144 executable = True, 145 cfg = "exec", 146 allow_single_file = True, 147 default = Label("//build/soong/zip/cmd:soong_zip"), 148 ), 149 }, 150) 151 152def java_xsd_config_library( 153 name, 154 src, 155 sdk_version = "none", 156 include_files = [], 157 package_name = "", 158 nullability = False, 159 gen_has = False, 160 gen_writer = False, 161 boolean_getter = False, 162 root_elements = [], 163 deps = [], 164 **kwargs): 165 """ 166 Generate .java parser file from .xsd file using xsdc and wrap it in a java_library. 167 168 """ 169 _gen = name + "_gen" 170 171 _java_xsd_codegen( 172 name = _gen, 173 src = src, 174 include_files = include_files, 175 package_name = package_name, 176 nullability = nullability, 177 gen_has = gen_has, 178 gen_writer = gen_writer, 179 boolean_getter = boolean_getter, 180 root_elements = root_elements, 181 **kwargs 182 ) 183 184 java_library( 185 name = name, 186 srcs = [_gen], 187 deps = deps, 188 sdk_version = sdk_version, 189 **kwargs 190 ) 191