1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
use crate::java::*;
use crate::tools::*;

pub trait Generatable {
    fn generate(&self) -> Result<String, String>;
}

impl Generatable for JVariable {
    fn generate(&self) -> Result<String, String> {
        let jstatic = if self.is_static() { "static" } else { "" };
        let jfinal = if self.is_final() { "final" } else { "" };
        let mut s = format!("{} {} {} {} {};", self.access(), jstatic, jfinal, self.jtype(), self.name());
        s = s.trim().to_string();
        s = s.remove_duplicate_spaces();
        Ok(s)
    }
}

impl Generatable for JMethod {
    fn generate(&self) -> Result<String, String> {
        let jstatic = if self.is_static() { "static" } else { "" };
        let jfinal = if self.is_final() { "final" } else { "" };
        let parameters: Vec<String> = self.args().iter()
            .map(|(name, jtype)| format!("{} {}", jtype, name))
            .collect();
        let parameters = parameters.join(", ");
        let head = format!("{} {} {} {} {}({}) {{", self.access(), jstatic, jfinal, self.return_type(), self.name(), parameters);
        let head = head.trim().to_string();
        let head = head.remove_duplicate_spaces();
        Ok(format!("{}\n{}\n}}", head, self.src().clone().indent(4)))
    }
}

impl Generatable for JClass {
    fn generate(&self) -> Result<String, String> {
        let jfinal = if self.is_final() { "final" } else { "" };
        let head = format!("{} {} class {} {{", self.access(), jfinal, self.name());
        let fields: Vec<String> = self.fields().iter()
            .map(|f| f.generate().unwrap())
            .collect();
        let fields = fields.join("\n\n");
        let methods: Vec<String> = self.methods().iter()
            .map(|m| m.generate().unwrap())
            .collect();
        let methods = methods.join("\n\n");
        let body = format!("{}\n{}", fields, methods);
        Ok((format!(
"package {};

{}

{}
}}", self.package(), head, body)))
    }
}

mod tests {
    use crate::java::*;

    #[test]
    fn default_int() {
        let v = JVariable::new(
            "di",
            JType::Primitive(JPrimitive::Int),
            JAccessModifier::Default,
            false,
            false,
        );
        let expected = "int di;";
        assert_eq!(expected, v.generate().unwrap());
    }

    #[test]
    fn public_static_final_string() {
        let v = JVariable::new(
            "psfs",
            JType::Class("String".to_string()),
            JAccessModifier::Public,
            true,
            true,
        );
        let expected = "public static final String psfs;";
        assert_eq!(expected, v.generate().unwrap());
    }

    #[test]
    fn public_static_final_boolean_method() {
        let args = vec![
            ("v1".to_string(), JType::Class("String".to_string())),
            ("v2".to_string(), JType::Primitive(JPrimitive::Int)),
        ];
        let m = JMethod::new(
            "stringEqualsInt".to_string(),
            "boolean equal = Integer.parseInt(v2).equals(v1);\nreturn equal;".to_string(),
            args,
            JType::Primitive(JPrimitive::Boolean),
            JAccessModifier::Public,
            true,
            true,
        );
        let expected =
"public static final boolean stringEqualsInt(String v1, int v2) {
    boolean equal = Integer.parseInt(v2).equals(v1);
    return equal;
}";
        assert_eq!(expected, m.generate().unwrap());
    }
}