blob: 1c1cf77d728ceef5fa747ec8bcba9cb276a6a753 [file] [log] [blame]
Zhi Doueb744892023-05-10 04:02:33 +00001/*
2 * Copyright (C) 2023 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17use anyhow::Result;
18use serde::Serialize;
Joe Onorato0c4ef0f2023-05-13 11:30:11 -070019use std::path::PathBuf;
Zhi Doueb744892023-05-10 04:02:33 +000020use tinytemplate::TinyTemplate;
21
22use crate::aconfig::{FlagState, Permission};
23use crate::cache::{Cache, Item};
Mårten Kongstad066575b2023-06-07 16:29:25 +020024use crate::codegen;
Mårten Kongstadd42eeeb2023-05-12 10:01:00 +020025use crate::commands::OutputFile;
Zhi Doueb744892023-05-10 04:02:33 +000026
Mårten Kongstadd42eeeb2023-05-12 10:01:00 +020027pub fn generate_java_code(cache: &Cache) -> Result<OutputFile> {
Mårten Kongstad9fb58962023-05-31 13:02:13 +020028 let package = cache.package();
Mårten Kongstad066575b2023-06-07 16:29:25 +020029 let class_elements: Vec<ClassElement> =
30 cache.iter().map(|item| create_class_element(package, item)).collect();
31 let readwrite = class_elements.iter().any(|item| item.readwrite);
Mårten Kongstad9fb58962023-05-31 13:02:13 +020032 let context = Context { package: package.to_string(), readwrite, class_elements };
Zhi Doueb744892023-05-10 04:02:33 +000033 let mut template = TinyTemplate::new();
34 template.add_template("java_code_gen", include_str!("../templates/java.template"))?;
Mårten Kongstadd42eeeb2023-05-12 10:01:00 +020035 let contents = template.render("java_code_gen", &context)?;
Mårten Kongstadfbd71e22023-05-31 13:29:35 +020036 let mut path: PathBuf = package.split('.').collect();
Joe Onorato0c4ef0f2023-05-13 11:30:11 -070037 // TODO: Allow customization of the java class name
38 path.push("Flags.java");
Mårten Kongstadd42eeeb2023-05-12 10:01:00 +020039 Ok(OutputFile { contents: contents.into(), path })
Zhi Doueb744892023-05-10 04:02:33 +000040}
41
42#[derive(Serialize)]
43struct Context {
Mårten Kongstad9fb58962023-05-31 13:02:13 +020044 pub package: String,
Zhi Doueb744892023-05-10 04:02:33 +000045 pub readwrite: bool,
46 pub class_elements: Vec<ClassElement>,
47}
48
49#[derive(Serialize)]
50struct ClassElement {
51 pub method_name: String,
52 pub readwrite: bool,
53 pub default_value: String,
Mårten Kongstad066575b2023-06-07 16:29:25 +020054 pub device_config_namespace: String,
55 pub device_config_flag: String,
Zhi Doueb744892023-05-10 04:02:33 +000056}
57
Mårten Kongstad066575b2023-06-07 16:29:25 +020058fn create_class_element(package: &str, item: &Item) -> ClassElement {
59 let device_config_flag = codegen::create_device_config_ident(package, &item.name)
60 .expect("values checked at cache creation time");
Zhi Doueb744892023-05-10 04:02:33 +000061 ClassElement {
62 method_name: item.name.clone(),
63 readwrite: item.permission == Permission::ReadWrite,
64 default_value: if item.state == FlagState::Enabled {
65 "true".to_string()
66 } else {
67 "false".to_string()
68 },
Mårten Kongstad066575b2023-06-07 16:29:25 +020069 device_config_namespace: item.namespace.clone(),
70 device_config_flag,
Zhi Doueb744892023-05-10 04:02:33 +000071 }
72}
73
Zhi Doueb744892023-05-10 04:02:33 +000074#[cfg(test)]
75mod tests {
76 use super::*;
Mårten Kongstadfa23d292023-05-11 14:47:02 +020077 use crate::aconfig::{FlagDeclaration, FlagValue};
Mårten Kongstad2f954442023-05-17 16:51:16 +020078 use crate::cache::CacheBuilder;
Zhi Doueb744892023-05-10 04:02:33 +000079 use crate::commands::Source;
80
81 #[test]
82 fn test_generate_java_code() {
Mårten Kongstadfbd71e22023-05-31 13:29:35 +020083 let package = "com.example";
Mårten Kongstad9fb58962023-05-31 13:02:13 +020084 let mut builder = CacheBuilder::new(package.to_string()).unwrap();
Mårten Kongstad2f954442023-05-17 16:51:16 +020085 builder
Mårten Kongstadfa23d292023-05-11 14:47:02 +020086 .add_flag_declaration(
Zhi Doueb744892023-05-10 04:02:33 +000087 Source::File("test.txt".to_string()),
Mårten Kongstadfa23d292023-05-11 14:47:02 +020088 FlagDeclaration {
Zhi Doueb744892023-05-10 04:02:33 +000089 name: "test".to_string(),
Mårten Kongstad066575b2023-06-07 16:29:25 +020090 namespace: "ns".to_string(),
Zhi Doueb744892023-05-10 04:02:33 +000091 description: "buildtime enable".to_string(),
Zhi Doueb744892023-05-10 04:02:33 +000092 },
93 )
Mårten Kongstad2f954442023-05-17 16:51:16 +020094 .unwrap()
Mårten Kongstadfa23d292023-05-11 14:47:02 +020095 .add_flag_declaration(
Zhi Doueb744892023-05-10 04:02:33 +000096 Source::File("test2.txt".to_string()),
Mårten Kongstadfa23d292023-05-11 14:47:02 +020097 FlagDeclaration {
Zhi Doueb744892023-05-10 04:02:33 +000098 name: "test2".to_string(),
Mårten Kongstad066575b2023-06-07 16:29:25 +020099 namespace: "ns".to_string(),
Zhi Doueb744892023-05-10 04:02:33 +0000100 description: "runtime disable".to_string(),
Mårten Kongstadfa23d292023-05-11 14:47:02 +0200101 },
102 )
Mårten Kongstad2f954442023-05-17 16:51:16 +0200103 .unwrap()
Mårten Kongstadfa23d292023-05-11 14:47:02 +0200104 .add_flag_value(
105 Source::Memory,
106 FlagValue {
Mårten Kongstad9fb58962023-05-31 13:02:13 +0200107 package: package.to_string(),
Mårten Kongstadfa23d292023-05-11 14:47:02 +0200108 name: "test".to_string(),
109 state: FlagState::Disabled,
110 permission: Permission::ReadOnly,
Zhi Doueb744892023-05-10 04:02:33 +0000111 },
112 )
113 .unwrap();
Mårten Kongstad2f954442023-05-17 16:51:16 +0200114 let cache = builder.build();
Mårten Kongstadfbd71e22023-05-31 13:29:35 +0200115 let expect_content = r#"package com.example;
Zhi Doueb744892023-05-10 04:02:33 +0000116
117 import android.provider.DeviceConfig;
118
Joe Onorato0c4ef0f2023-05-13 11:30:11 -0700119 public final class Flags {
Zhi Doueb744892023-05-10 04:02:33 +0000120
121 public static boolean test() {
Mårten Kongstadfa23d292023-05-11 14:47:02 +0200122 return false;
Zhi Doueb744892023-05-10 04:02:33 +0000123 }
124
125 public static boolean test2() {
126 return DeviceConfig.getBoolean(
Mårten Kongstad066575b2023-06-07 16:29:25 +0200127 "ns",
128 "com.example.test2",
Zhi Doueb744892023-05-10 04:02:33 +0000129 false
130 );
131 }
132
133 }
Mårten Kongstadd42eeeb2023-05-12 10:01:00 +0200134 "#;
135 let file = generate_java_code(&cache).unwrap();
Mårten Kongstadfbd71e22023-05-31 13:29:35 +0200136 assert_eq!("com/example/Flags.java", file.path.to_str().unwrap());
Mårten Kongstadd42eeeb2023-05-12 10:01:00 +0200137 assert_eq!(
138 expect_content.replace(' ', ""),
139 String::from_utf8(file.contents).unwrap().replace(' ', "")
140 );
Zhi Doueb744892023-05-10 04:02:33 +0000141 }
142}