How to create a relationship between specific pairs of a config.properties file in java?

Viewed 67

I've multiple external JAR files, which include special proceedings for my application. The application itself just needs one proceeding at the time, depending on the proceeding name entered by the user.

With that beeing said, I've created a config.properties file, which contains relevant informations about each proceeding.

config.properties

PROC.1=NameOfProc
IMPL.1=path.to.main.class.of.jar
LIB.1=lib/somejar.jar

PROC.2=NameOfProc
IMPL.2=path.to.main.class.of.jar
LIB.2=lib/somejar.jar

...

I'm already able to read the config.properties file, but I can't create a relationship between the pairs, which belong together.

java code

try {
    Properties prop = new Properties();
    prop.load(new FileInputStream("path/to/config.properties"));
    String proc = properties.getProperty("PROC.1");
    String impl = properties.getProperty("IMPL.1");
    String lib = properties.getProperty("LIB.1");
} catch (Exception e) {

}

I am now wondering how I can create a relationship between the pairs, so that I can recieve the IMPL.X value and LIB.X value by only having the PROC.X name.

Does anybody knows how I can achieve this? I highly appreciate any kind of help, sheers!

3 Answers

You should be able to do that (with a little change in your properties file structure) using Jackson library HERE

The file format has to follow the commonly used convention with a period (“.”) as a logical path separator.

Example:

proceedings[1].name = NameOfProc
proceedings[1].implementation = path.to.main.class.of.jar
proceedings[1].libraryPath  = lib/somejar.jar

proceedings[2].name = NameOfProc2
proceedings[2].implementation = path2.to.main.class.of.jar
proceedings[2].libraryPath  = lib/somejar2.jar

Once done - you should now be able to bind it to the following structure:

public class Configuration {
   public List<Proceeding> proceedings;
}

public class Proceeding {
    String name;
    String implementation;
    String libraryPath;
}

Using something like this:

JavaPropsMapper mapper = new JavaPropsMapper();

Configuration cfg = mapper.readValue(new File("path_to_your.properties"),
   Configuration.class);

You can convert it to a nested Map.

public static void main(String[] args) {
    Properties prop = new Properties();
    prop.setProperty("PROC.1", "procOne");
    prop.setProperty("IMPL.1", "implOne");
    prop.setProperty("LIB.1", "libOne");
    prop.setProperty("PROC.2", "procTwo");
    prop.setProperty("IMPL.2", "implTwo");
    prop.setProperty("LIB.2", "libTwo");
    System.out.println("prop=" + prop);

    Map<String, Map<String, String>> mappedProp = prop.entrySet().stream()
        .map(e -> Map.entry(e.getKey().toString(), e.getValue().toString()))
        .collect(Collectors.groupingBy(
            e -> e.getKey().replaceFirst("\\..*$", ""),
            Collectors.mapping(Function.identity(),
                Collectors.toMap(e -> e.getKey().replaceFirst("^.*\\.", ""),
                    Map.Entry::getValue))));

    System.out.println("mappedProp=" + mappedProp);
    System.out.println("PROC=" + mappedProp.get("PROC"));
    System.out.println("PROC.1=" + mappedProp.get("PROC").get("1"));
}

output:

prop={IMPL.2=implTwo, PROC.1=procOne, PROC.2=procTwo, IMPL.1=implOne, LIB.2=libTwo, LIB.1=libOne}
mappedProp={IMPL={1=implOne, 2=implTwo}, PROC={1=procOne, 2=procTwo}, LIB={1=libOne, 2=libTwo}}
PROC={1=procOne, 2=procTwo}
PROC.1=procOne

Alternatively, you can do it with a simple loop.

Map<String, Map<String, String>> mappedProp = new LinkedHashMap<>();
for (Map.Entry<Object, Object> e : prop.entrySet()) {
    String key = e.getKey().toString();
    String key1 = key.replaceFirst("\\..*$", "");
    String key2 = key.replaceFirst("^.*\\.", "");
    String value = e.getValue().toString();
    mappedProp.computeIfAbsent(key1, k -> new LinkedHashMap<>()).put(key2, value);
}

Match keySet of properties against a RegEx patern as shown in this example where the collection of interresting keys is done in method grepPropertyKey()

public class PropertySample {

Properties properties = new Properties();


public static void main(String[] args) {
    
    PropertySample me = new PropertySample();
    me.run();
    
}


protected void run() {

    // Setup some properties
    properties.put("PROC.1", "NameOfProc");
    properties.put("IMPL.1", "path.to.main.class.of.jar");
    properties.put("LIB.1", "lib/somejar.jar");

    properties.put("PROC.2", "NameOfOtherProc");
    properties.put("IMPL.2", "path.to.main.someOtherClass.of.jar");
    properties.put("LIB.2", "lib/someOtherjar.jar");
    
    for(int index = 1; index <=2; index++) {
    
        /* get list of keys filtered by the RegEx:
         *   a: From begin of the string consume all characters NOT matching a literal dot
         *   b: consume one literal dot
         *   c: MATCH the literal number given by index
         *   d: match anything else up to end of string
         */
        String regEx = "^[^\\.]+\\." + Integer.toString(index) + ".*";
        
        List<String> keyList = grepPropertyKey(regEx);
        
        for(String key: keyList) {
            System.out.println(
                "index: " + index 
              + " key: " + key
              + "\t value: " + properties.get(key)
            );
            
        }
        
        System.out.println();
        
    } // index
            
} // main()


protected List<String> grepPropertyKey(final String aPattern) {
    
    // prepare result set
    List<String> result = new ArrayList<String>();
    
    // get the key set from properties
    for(Object key : properties.keySet()) {
        
        // and match each key against the filter given in aPatern 
        if(((String)key).matches(aPattern)) {
            
            // add match to result
            result.add((String)key);
            
        } // fi
        
    } // rof
    
    return result;
    
} // grepPropertyKey()

}

The output is

index: 1 key: LIB.1      value: lib/somejar.jar
index: 1 key: PROC.1     value: NameOfProc
index: 1 key: IMPL.1     value: path.to.main.class.of.jar

index: 2 key: LIB.2      value: lib/someOtherjar.jar
index: 2 key: PROC.2     value: NameOfOtherProc
index: 2 key: IMPL.2     value: path.to.main.someOtherClass.of.jar
Related