/* * Copyright 2012 James Moger * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.moxie.ant; import java.io.File; import java.io.FileInputStream; import java.io.FileWriter; import java.text.MessageFormat; import java.util.ArrayList; import java.util.Collections; import java.util.List; import java.util.Properties; import org.moxie.Build; import org.moxie.utils.StringUtils; public class MxKeys extends MxTask { File propertiesFile; String className; File destDir; public MxKeys() { super(); setTaskName("mx:keys"); } public void setPropertiesfile(File file) { this.propertiesFile = file; } public void setOutputclass(String className) { this.className = className; } public void setDestdir(File dir) { this.destDir = dir; } public void setTodir(File dir) { this.destDir = dir; } public void execute() { Build build = getBuild(); if (destDir == null) { getConsole().error("Please specify an destination directory!"); throw new RuntimeException(); } if (className == null) { getConsole().error("Please specify an output classname!"); throw new RuntimeException(); } if (propertiesFile == null) { getConsole().error("Please specify an input properties file!"); throw new RuntimeException(); } // Load all keys Properties properties = new Properties(); FileInputStream is = null; try { is = new FileInputStream(propertiesFile); properties.load(is); } catch (Throwable t) { t.printStackTrace(); } finally { if (is != null) { try { is.close(); } catch (Throwable t) { // IGNORE } } } List<String> keys = new ArrayList<String>(properties.stringPropertyNames()); Collections.sort(keys); KeyGroup root = new KeyGroup(); for (String key : keys) { root.addKey(key); } // Save Keys class definition try { File file = new File(destDir, className.replace('.', '/') + ".java"); file.getParentFile().mkdirs(); FileWriter fw = new FileWriter(file, false); fw.write(root.generateClass(className)); fw.close(); titleClass(className); getConsole().key("input",propertiesFile.getAbsolutePath()); getConsole().key("output", file.getAbsolutePath()); } catch (Throwable t) { getConsole().error(t); } } private static class KeyGroup { final KeyGroup parent; final String namespace; String name; List<KeyGroup> children; List<String> fields; KeyGroup() { this.parent = null; this.namespace = ""; this.name = ""; } KeyGroup(String namespace, KeyGroup parent) { this.parent = parent; this.namespace = namespace; if (parent.children == null) { parent.children = new ArrayList<KeyGroup>(); } parent.children.add(this); } void addKey(String key) { String keyspace = ""; String field = key; if (key.indexOf('.') > -1) { keyspace = key.substring(0, key.lastIndexOf('.')); field = key.substring(key.lastIndexOf('.') + 1); KeyGroup group = addKeyGroup(keyspace); group.addKey(field); } else { if (fields == null) { fields = new ArrayList<String>(); } fields.add(key); } } KeyGroup addKeyGroup(String keyspace) { KeyGroup parent = this; KeyGroup node = null; String [] space = keyspace.split("\\."); for (int i = 0; i < space.length; i++) { StringBuilder namespace = new StringBuilder(); for (int j = 0; j <= i; j++) { namespace.append(space[j]); if (j < i) { namespace.append('.'); } } if (parent.children != null) { for (KeyGroup child : parent.children) { if (child.name.equals(space[i])) { node = child; } } } if (node == null) { node = new KeyGroup(namespace.toString(), parent); node.name = space[i]; } parent = node; node = null; } return parent; } String fullKey(String field) { if (namespace.equals("")) { return field; } return namespace + "." + field; } String generateClass(String fqn) { String packageName = ""; String className = fqn; if (fqn.indexOf('.') > -1) { packageName = fqn.substring(0, fqn.lastIndexOf('.')); className = fqn.substring(fqn.lastIndexOf('.') + 1); } StringBuilder sb = new StringBuilder(); sb.append("package ").append(packageName).append(";\n"); sb.append('\n'); sb.append("/*\n"); sb.append(" * This class is auto-generated from a properties file.\n"); sb.append(" * Do not version control!\n"); sb.append(" */\n"); sb.append(MessageFormat.format("public final class {0} '{'\n\n", className)); sb.append(generateClass(this, 0)); sb.append("}\n"); return sb.toString(); } String generateClass(KeyGroup group, int level) { String classIndent = StringUtils.leftPad("", level, '\t'); String fieldIndent = StringUtils.leftPad("", level + 1, '\t'); // begin class StringBuilder sb = new StringBuilder(); if (!group.namespace.equals("")) { sb.append(classIndent).append(MessageFormat.format("public static final class {0} '{'\n\n", group.name)); sb.append(fieldIndent).append(MessageFormat.format("public static final String _ROOT = \"{0}\";\n\n", group.namespace)); } if (group.fields != null) { // fields for (String field : group.fields) { sb.append(fieldIndent).append(MessageFormat.format("public static final String {0} = \"{1}\";\n\n", field, group.fullKey(field))); } } if (group.children != null) { // inner classes for (KeyGroup child : group.children) { sb.append(generateClass(child, level + 1)); } } // end class if (!group.namespace.equals("")) { sb.append(classIndent).append("}\n\n"); } return sb.toString(); } } }