How to create a dynamic Interface with properties file at compile time?

前端 未结 2 1552
执念已碎
执念已碎 2021-01-15 15:46

The problem here is that the property file we use has insanely huge name as the key and most of us run into incorrect key naming issues . so it got me thinking if there\'s a

相关标签:
2条回答
  • 2021-01-15 16:37

    I would not generate a class or interface from properties because you would lose the abilities to :

    • document those properties, as they would be represented by a java element + javadocs
    • references those properties in your code, as they would be play old java constant, and the compiler would have full knowledge of them. Refactoring them would also be possible while it would not be possible with automatic names.

    You can also use enums, or create some special Property class, with a name as only and final field. Then, you only need a get method that would take a Properties, a Map or whatever.

    As for your request, you can execute code with the maven-exec-plugin.

    You should simply create a main that would read your properties file, and for each keys:

    • convert the key to a valid java identifier (you can use isJavaIdentifierStart and isJavaIdentifierPart to replace invalid char by a _)
    • write your class/interface/whatever you like using plain old Java (and don't forget to escape for eventual doublequote or backslashes !)

    Since it would be a part of your build, say before building other classes that would depends on those constants, I would recommend you to create a specific maven project to isolate those build.

    Still, I would really don't do that and use a POJO loaded with whatever need (CDI, Spring, Static initialization, etc).

    0 讨论(0)
  • 2021-01-15 16:49

    There is an old rule about programming and not only about it, if something looks beautiful, then most probably it is the right way to do.

    This approach does not look good, from my point of view.

    The first thing:

    Do not declare constants in interfaces. It violates the incapsulation approach. Check this article please: http://en.wikipedia.org/wiki/Constant_interface

    The second thing:

    Use a prefix for name part of your properties which are somehow special, let say: key_

    And when you load your properties file, iterate over keys and extract keys with name that starts with key_ and use values of these keys as you planned to use those constants in your question.


    UPDATE

    Assume, we generate a huge properties file upon compilation process, using our Apache Ant script.

    For example, let's properties file (myapp.properties) looks like that:

    key_A = Apple
    key_B = Banana
    key_C = Cherry
    anotherPropertyKey1 = blablabla1
    anotherPropertyKey2 = blablabla2
    

    our special properties which we want to handle have key names start with key_ prefix.

    So, we write the following code (please note, it is not optimized, it is just proof of concept):

    package propertiestest;
    
    import java.io.FileInputStream;
    import java.io.FileNotFoundException;
    import java.io.IOException;
    import java.io.InputStream;
    import java.util.Arrays;
    import java.util.Enumeration;
    import java.util.HashSet;
    import java.util.Properties;
    import java.util.Set;
    
    
    public class PropertiesTest {
    
      public static void main(String[] args) throws IOException {
           final String PROPERTIES_FILENAME = "myapp.properties";      
    
           SpecialPropertyKeysStore spkStore = 
                                new SpecialPropertyKeysStore(PROPERTIES_FILENAME);
    
           System.out.println(Arrays.toString(spkStore.getKeysArray()));
    
       }
    }
    
    
    class SpecialPropertyKeysStore {
    
        private final Set<String> keys;
    
        public SpecialPropertyKeysStore(String propertiesFileName) 
                                        throws FileNotFoundException, IOException {
    
    
            // prefix of name of a special property key
            final String KEY_PREFIX = "key_";        
    
        Properties propertiesHandler = new Properties();
            keys = new HashSet<>();
    
        try (InputStream input = new FileInputStream(propertiesFileName)) {
    
                propertiesHandler.load(input);
    
                Enumeration<?> enumeration = propertiesHandler.propertyNames();
                while (enumeration.hasMoreElements()) {
                    String key = (String) enumeration.nextElement();
                    if (key.startsWith(KEY_PREFIX)) {
                        keys.add(key);
                    }
                }
        }        
        }
    
        public boolean isKeyPresent(String keyName) {
            return keys.contains(keyName);
        }
    
        public String[] getKeysArray() {
            String[] strTypeParam = new String[0];
    
            return keys.toArray(strTypeParam);
        }
    }
    

    Class SpecialPropertyKeysStore filters and collects all special keys into its instance.

    And you can get an array of these keys, or check whether is key present or not.

    If you run this code, you will get:

    [key_C, key_B, key_A]
    

    It is a string representation of returned array with special key names.

    Change this code as you want to meet your requirements.

    0 讨论(0)
提交回复
热议问题