# Copyright (C) 2023 The Android Open Source Project # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. load(":library.bzl", "java_library") # Return the relative directory where the java file should be generated def _java_gen_dir(ctx): return ctx.attr.name # Return the filename of the srcjar containing the generated .java files def _java_gen_srcjar(ctx): return ctx.attr.name + ".srcjar" def _xsdc_args(ctx, intermediate_dir): args = ctx.actions.args() args.add(ctx.file.src) args.add("-p", ctx.attr.package_name) args.add("-j") # Generate java args.add("-o", intermediate_dir.path) # Pass the output directory if ctx.attr.nullability: args.add("-n") if ctx.attr.gen_has: args.add("-g") if ctx.attr.gen_writer: args.add("-w") if ctx.attr.boolean_getter: args.add("-b") for root_element in ctx.attr.root_elements: args.add("-r", root_element) return args def _zip_args(ctx, output_srcjar, intermediate_dir): args = ctx.actions.args() args.add("-jar") args.add("-o", output_srcjar) args.add("-C", intermediate_dir.path) args.add("-D", intermediate_dir.path) # The java files inside the sandbox are symlinks # Instruct soong_zip to follow the symlinks args.add("-symlinks=false") return args def _java_xsd_codegen_impl(ctx): intermediate_dir = ctx.actions.declare_directory( _java_gen_dir(ctx), ) output_srcjar = ctx.actions.declare_file(_java_gen_srcjar(ctx)) # Run xsdc to generate the .java files in an intermedite directory ctx.actions.run( executable = ctx.executable._xsdc, inputs = [ctx.file.src] + ctx.files.include_files, outputs = [intermediate_dir], arguments = [ _xsdc_args(ctx, intermediate_dir), ], tools = [ ctx.executable._xsdc, ], mnemonic = "XsdcJavaCompile", progress_message = "Generating java files for %s" % ctx.file.src, ) # Zip the intermediate directory to a srcjar ctx.actions.run( executable = ctx.executable._soong_zip, inputs = [intermediate_dir], outputs = [output_srcjar], arguments = [ _zip_args(ctx, output_srcjar, intermediate_dir), ], tools = [ ctx.executable._soong_zip, ], mnemonic = "XsdcJavaZip", progress_message = "Generating srcjar for %s" % ctx.file.src, ) return [ DefaultInfo( files = depset([output_srcjar]), ), ] _java_xsd_codegen = rule( implementation = _java_xsd_codegen_impl, doc = "This rule generates .java parser files from an xsd file using xsdc", attrs = { "src": attr.label( allow_single_file = [".xsd"], doc = "The main xsd file", mandatory = True, ), "include_files": attr.label_list( allow_files = [".xsd"], doc = "The (transitive) xsd files included by `src` using xs:include", ), "package_name": attr.string( doc = "Package name to use in the generated .java files", mandatory = True, ), "nullability": attr.bool( doc = "Add @NonNull or @Nullable annotation to the generated .java files", default = False, ), "gen_has": attr.bool( doc = "Generate public hasX() method", default = False, ), "gen_writer": attr.bool( doc = "Add xml writer to the generated .java files", ), "boolean_getter": attr.bool( doc = "Whether getter name of boolean element or attribute is getX or isX. If true, getter name is isX", default = False, ), "root_elements": attr.string_list( doc = "If set, xsdc will generate parser code only for the specified root elements", ), "_xsdc": attr.label( executable = True, cfg = "exec", default = Label("//system/tools/xsdc"), ), "_soong_zip": attr.label( executable = True, cfg = "exec", allow_single_file = True, default = Label("//build/soong/zip/cmd:soong_zip"), ), }, ) def java_xsd_config_library( name, src, sdk_version = "none", include_files = [], package_name = "", nullability = False, gen_has = False, gen_writer = False, boolean_getter = False, root_elements = [], deps = [], **kwargs): """ Generate .java parser file from .xsd file using xsdc and wrap it in a java_library. """ _gen = name + "_gen" _java_xsd_codegen( name = _gen, src = src, include_files = include_files, package_name = package_name, nullability = nullability, gen_has = gen_has, gen_writer = gen_writer, boolean_getter = boolean_getter, root_elements = root_elements, **kwargs ) java_library( name = name, srcs = [_gen], deps = deps, sdk_version = sdk_version, **kwargs )