bp2build for java libraries using xsd_config srcs

In Soong, java libraries can use src files generated from xsd_config. In
Bazel, instead of providing srcs, java_xsd_config_library will provide a
jar. Update bp2build so that all src references to xsd_config modules in
srcs get routed to deps and exports attributes

This CL creates an interface in build/soong/android to get around a
circular dependency issue. The bp2build logic needs to exist in
soong-java, but soong-java does have soong-xsdc in its package path. Use
the interface and type assertions to special case xsd_config references

Bug: 211678537
Test: bp2build test in sibling CL in system/tools/xsdc
Change-Id: Ida924bb20b1fd7eb8beeef950b070d37a9c6f3b5
diff --git a/android/module.go b/android/module.go
index 98084f3..ba32710 100644
--- a/android/module.go
+++ b/android/module.go
@@ -4014,3 +4014,53 @@
 	WriteFileRule(ctx, outFile, string(j))
 	ctx.Phony("soong_config_trace", outFile)
 }
+
+// Interface implemented by xsd_config which has 1:many mappings in bp2build workspace
+// This interface exists because we want to
+// 1. Determine the name of the additional targets generated by the primary soong module
+// 2. Enable distinguishing an xsd_config module from other Soong modules using type assertion
+type XsdConfigBp2buildTargets interface {
+	CppBp2buildTargetName() string
+	JavaBp2buildTargetName() string
+}
+
+// PartitionXsdSrcs partitions srcs into xsd_config modules and others
+// Since xsd_config are soong modules, we cannot use file extension for partitioning
+func PartitionXsdSrcs(ctx BazelConversionPathContext, srcs []string) ([]string, []string) {
+	//isXsd returns true if src is a soong module of type xsd_config
+	isXsd := func(src string) bool {
+		mod, exists := ctx.ModuleFromName(src)
+		if !exists {
+			return false
+		}
+		_, _isXsd := mod.(XsdConfigBp2buildTargets)
+		return _isXsd
+	}
+	nonXsd := []string{}
+	xsd := []string{}
+
+	for _, src := range srcs {
+		if isXsd(src) {
+			xsd = append(xsd, src)
+		} else {
+			nonXsd = append(nonXsd, src)
+		}
+	}
+
+	return nonXsd, xsd
+}
+
+// Replaces //a/b/my_xsd_config with //a/b/my_xsd_config-{cpp|java}
+// The new target name is provided by the `targetName` callback function
+func XsdConfigBp2buildTarget(ctx BazelConversionPathContext, mod blueprint.Module, targetName func(xsd XsdConfigBp2buildTargets) string) string {
+	xsd, isXsd := mod.(XsdConfigBp2buildTargets)
+	if !isXsd {
+		ctx.ModuleErrorf("xsdConfigJavaTarget called on %v, which is not an xsd_config", mod)
+	}
+	ret := BazelModuleLabel(ctx, mod)
+	// Remove the base module name
+	ret = strings.TrimSuffix(ret, mod.Name())
+	// Append the language specific target name
+	ret += targetName(xsd)
+	return ret
+}
diff --git a/java/java.go b/java/java.go
index aa9f936..d5ddbbe 100644
--- a/java/java.go
+++ b/java/java.go
@@ -2798,6 +2798,14 @@
 	hasKotlin bool
 }
 
+// Replaces //a/b/my_xsd_config with //a/b/my_xsd_config-java
+func xsdConfigJavaTarget(ctx android.BazelConversionPathContext, mod blueprint.Module) string {
+	callback := func(xsd android.XsdConfigBp2buildTargets) string {
+		return xsd.JavaBp2buildTargetName()
+	}
+	return android.XsdConfigBp2buildTarget(ctx, mod, callback)
+}
+
 // convertLibraryAttrsBp2Build returns a javaCommonAttributes struct with
 // converted attributes shared across java_* modules and a bp2BuildJavaInfo struct
 // which has other non-attribute information needed for bp2build conversion
@@ -2812,8 +2820,15 @@
 	for axis, configToProps := range archVariantProps {
 		for config, _props := range configToProps {
 			if archProps, ok := _props.(*CommonProperties); ok {
-				archSrcs := android.BazelLabelForModuleSrcExcludes(ctx, archProps.Srcs, archProps.Exclude_srcs)
+				srcsNonXsd, srcsXsd := android.PartitionXsdSrcs(ctx, archProps.Srcs)
+				excludeSrcsNonXsd, _ := android.PartitionXsdSrcs(ctx, archProps.Exclude_srcs)
+				archSrcs := android.BazelLabelForModuleSrcExcludes(ctx, srcsNonXsd, excludeSrcsNonXsd)
 				srcs.SetSelectValue(axis, config, archSrcs)
+
+				// Add to static deps
+				xsdJavaConfigLibraryLabels := android.BazelLabelForModuleDepsWithFn(ctx, srcsXsd, xsdConfigJavaTarget)
+				staticDeps.Append(xsdJavaConfigLibraryLabels)
+
 			}
 		}
 	}