use std::{
io::Write as _,
path::{Path, PathBuf},
};
use include_dir::include_dir;
use crate::{
Registry,
generation::{
CodeGeneratorConfig, Encoding, Error, ExternalPackage, ExternalPackages, SERDE_NAMESPACE,
SourceInstaller, java::CodeGenerator, module,
},
};
#[deprecated(
since = "0.16.0",
note = "The Java generator is deprecated. Use the Kotlin generator instead."
)]
pub struct Installer {
package_name: String,
install_dir: PathBuf,
external_packages: ExternalPackages,
encoding: Encoding,
}
impl Installer {
#[must_use]
pub fn new(package_name: &str, install_dir: impl AsRef<Path>) -> Self {
Installer {
package_name: package_name.to_string(),
install_dir: install_dir.as_ref().to_path_buf(),
external_packages: ExternalPackages::new(),
encoding: Encoding::default(),
}
}
#[must_use]
pub fn encoding(mut self, encoding: Encoding) -> Self {
self.encoding = encoding;
self
}
#[must_use]
pub fn external_packages(mut self, packages: &[ExternalPackage]) -> Self {
self.external_packages = packages
.iter()
.map(|d| (d.for_namespace.clone(), d.clone()))
.collect();
self
}
pub fn generate(mut self, registry: &Registry) -> Result<(), Error> {
if !self.encoding.is_none() && !self.external_packages.contains_key(SERDE_NAMESPACE) {
self.install_serde_runtime()?;
if let Encoding::Bincode = self.encoding {
self.install_bincode_runtime()?;
}
}
for (m, module_registry) in module::split(&self.package_name, registry) {
let config = m
.config()
.clone()
.with_parent(&self.package_name)
.with_encoding(self.encoding);
self.install_module(&config, &module_registry)?;
}
Ok(())
}
fn install_runtime(
&self,
source_dir: &include_dir::Dir,
path: &str,
) -> std::result::Result<(), Error> {
let dir_path = self.install_dir.join(path);
std::fs::create_dir_all(&dir_path)?;
for entry in source_dir.files() {
let mut file = std::fs::File::create(dir_path.join(entry.path()))?;
file.write_all(entry.contents())?;
}
Ok(())
}
}
impl SourceInstaller for Installer {
fn install_module(
&mut self,
config: &CodeGeneratorConfig,
registry: &Registry,
) -> std::result::Result<(), Error> {
let module_parts: Vec<&str> = config.module_name().split('.').collect();
let namespace = module_parts.last().map_or("", |v| *v);
let skip_module = self.external_packages.contains_key(namespace);
if skip_module {
return Ok(());
}
let mut updated_config = config.clone();
updated_config.external_packages = self.external_packages.clone();
let generator = CodeGenerator::new(&updated_config);
generator.write_source_files(self.install_dir.clone(), registry)?;
Ok(())
}
fn install_serde_runtime(&mut self) -> std::result::Result<(), Error> {
self.install_runtime(
&include_dir!("$CARGO_MANIFEST_DIR/runtime/java/com/novi/serde"),
"com/novi/serde",
)
}
fn install_bincode_runtime(&self) -> std::result::Result<(), Error> {
self.install_runtime(
&include_dir!("$CARGO_MANIFEST_DIR/runtime/java/com/novi/bincode"),
"com/novi/bincode",
)
}
}