use std::{collections::HashMap, path::PathBuf};
use crate::{
Registry,
generation::{
CodeGen, CodeGeneratorConfig,
indent::{IndentConfig, IndentedWriter},
java::emitter::JavaEmitter,
},
reflection::format::ContainerFormat,
};
#[deprecated(
since = "0.16.0",
note = "The Java generator is deprecated. Use the Kotlin generator instead."
)]
pub struct CodeGenerator<'a> {
pub(crate) config: &'a CodeGeneratorConfig,
pub(crate) external_qualified_names: HashMap<String, String>,
}
impl<'a> CodeGen<'a> for CodeGenerator<'a> {
fn new(config: &'a CodeGeneratorConfig) -> Self {
CodeGenerator::new(config)
}
fn write_output<W: std::io::Write>(
&mut self,
writer: &mut W,
registry: &Registry,
) -> std::io::Result<()> {
let current_namespace = self
.config
.module_name
.split('.')
.map(String::from)
.collect::<Vec<_>>();
let mut emitter = JavaEmitter {
out: IndentedWriter::new(writer, IndentConfig::Space(4)),
generator: self,
current_namespace,
current_reserved_names: HashMap::new(),
};
emitter.output_preamble()?;
for (name, format) in registry {
emitter.output_container(&name.name, format)?;
}
if self.config.has_encoding() {
emitter.output_trait_helpers(registry)?;
}
Ok(())
}
}
impl<'a> CodeGenerator<'a> {
#[must_use]
pub fn new(config: &'a CodeGeneratorConfig) -> Self {
let mut external_qualified_names = HashMap::new();
for (namespace, names) in &config.external_definitions {
let package_name =
if let Some(external_package) = config.external_packages.get(namespace) {
match &external_package.location {
crate::generation::PackageLocation::Path(path) => path.clone(),
crate::generation::PackageLocation::Url(_) => {
format!("{}.{}", config.module_name(), namespace)
}
}
} else {
format!("{}.{}", config.module_name(), namespace)
};
for name in names {
external_qualified_names.insert(name.clone(), format!("{package_name}.{name}"));
}
}
Self {
config,
external_qualified_names,
}
}
pub fn write_source_files(
&self,
install_dir: PathBuf,
registry: &Registry,
) -> std::io::Result<()> {
let current_namespace = self
.config
.module_name
.split('.')
.map(String::from)
.collect::<Vec<_>>();
let mut dir_path = install_dir;
for part in ¤t_namespace {
dir_path = dir_path.join(part);
}
std::fs::create_dir_all(&dir_path)?;
for (name, format) in registry {
self.write_container_class(&dir_path, current_namespace.clone(), &name.name, format)?;
}
if self.config.has_encoding() {
self.write_helper_class(&dir_path, current_namespace, registry)?;
}
Ok(())
}
fn write_container_class(
&self,
dir_path: &std::path::Path,
current_namespace: Vec<String>,
name: &str,
format: &ContainerFormat,
) -> std::io::Result<()> {
let mut file = std::fs::File::create(dir_path.join(name.to_string() + ".java"))?;
let mut emitter = JavaEmitter {
out: IndentedWriter::new(&mut file, IndentConfig::Space(4)),
generator: self,
current_namespace,
current_reserved_names: HashMap::new(),
};
emitter.output_preamble()?;
emitter.output_container(name, format)
}
fn write_helper_class(
&self,
dir_path: &std::path::Path,
current_namespace: Vec<String>,
registry: &Registry,
) -> std::io::Result<()> {
let mut file = std::fs::File::create(dir_path.join("TraitHelpers.java"))?;
let mut emitter = JavaEmitter {
out: IndentedWriter::new(&mut file, IndentConfig::Space(4)),
generator: self,
current_namespace,
current_reserved_names: HashMap::new(),
};
emitter.output_preamble()?;
emitter.output_trait_helpers(registry)
}
}