Reputation: 3
Task: Read a XML file to create a Template;
I am reading this XML file as mentioned below and putting it in a HashMap. to get a Key-Value pair, where Key is value under Element attribute "name" and Value is Element Value. eg: Key: map.abc.color.PRIMARY and Value: #FFFFFF eg: Key: map.abc.node.TEXT1 and Value: value1
<properties>
<property name="map.abc.color.PRIMARY">#FFFFFF</property>
<property name="map.abc.color.SECONDARY">#F0F0F0</property>
<property name="map.abc.node.TEXT1">value1</property>
<property name="map.abc.node.TEXT2">value2</property>
<property name="map.abc.node.lowercase">value3</property>
<property name="map.abc.strFile">/path/to/file</property>
<property name="map.pqr.color.PRIMARY">#000000</property>
<property name="map.pqr.color.SECONDARY">#ABABAB</property>
<property name="map.pqr.node.WORD1">value4</property>
<property name="map.pqr.node.WORD2">value5</property>
<property name="map.abc.node.lowercase">value6</property>
<property name="map.pqr.strFile">/path/to/file</property>
</properties>
Following is a Template(using a StringBuffer) Output to be written to a file.
abc = {
color: {PRIMARY_COLOR:"#FFFFFF",SECONDARY_COLOR:"#F0F0F0"}
node:{TEXT1:"value1",TEXT2:"value2"}
};
pqr = {
color: {PRIMARY_COLOR:"#FFFFFF",SECONDARY_COLOR:"#F0F0F0"}
node:{WORD1:"value4",WORD2:"value5"}
};
Offnote: I am using following pattern which works fine.
key.matches("map.abc.*.*\\p{Lu}$") or key.matches("map.*.*\\p{Lu}$")
I am hence looking to find a way to get all keys ending with Uppercase alphabets after the last period in the Key from the HashMap(Or possibly any other options)
Upvotes: 0
Views: 859
Reputation: 4223
OK, now that we have more detail, we can address your data structure. It appears to me that you have a hierarchical map here. Your name
seems to define the hierarchy. I'd use a map of maps to store it:
Map<String, Map<String, Map<String, String>>> structure = new HashMap<>();
to parse and populate the map (totally just psuedocode):
path = name.split(".")
// ignore path[0] since it's just 'map'
structure.get(path[1]).get(path[2]).put(path[3], value)
And to retrieve values
for (Map<String, Map<String, String>> element : structure){
for(Map<String, String> group : element) {
for(String attribute : group.keys){
if(allUpper(attribute)) { //DO YOUR THING HERE }
}
}
}
Upvotes: 1
Reputation: 14839
It looks to me like you are trying to convert from a java properties-style list of values to javascript objects.
Here is one possibility: you could "unflatten" the properties-style Map
into a recursive map of maps/values, and then leverage one of the JSON libraries to output the values. Here is some code to unflatten things:
public class Foo {
private static final String ROOT_NAME = "map";
private static boolean noLowercase(CharSequence s) {
return !s.chars().anyMatch(Character::isLowerCase);
}
private static Map<String, Object> getNextMap(Map<String, Object> map, String mapName) {
Object nextObj = map.get(mapName);
if (nextObj == null) {
nextObj = new LinkedHashMap<String, Object>();
map.put(mapName, nextObj);
}
@SuppressWarnings("unchecked")
Map<String, Object> nextMap = (Map<String, Object>)nextObj;
return nextMap;
}
public static Map<String, Object> unflatten(Map<String, String> properties) {
List<String> sortedKeys = new ArrayList<>(properties.keySet());
Collections.sort(sortedKeys);
Map<String, Object> rootObject = new LinkedHashMap<>();
for (String key : sortedKeys) {
String[] splitKey = key.split("\\.");
String lastItem = splitKey[splitKey.length - 1];
if (noLowercase(lastItem)) {
Map<String, Object> currentMap = rootObject;
for (int i = 1; i < splitKey.length - 1; ++i) {
currentMap = getNextMap(currentMap, splitKey[i]);
}
currentMap.put(lastItem, properties.get(key));
}
}
return rootObject;
}
}
Serialising with, for example, Gson or Jackson should be pretty easy after this. Here is an example using Gson:
public static void printMap(Map<String, String> map) {
Gson gson = new GsonBuilder().setPrettyPrinting().create();
for (Map.Entry<String, Object> entry : unflatten(map).entrySet()) {
System.out.format("%s = ", entry.getKey());
System.out.print(gson.toJson(entry.getValue()));
System.out.println(";");
System.out.println();
}
}
Alternatively it should not be too hard to write your own printing routines for the map of maps data structure.
Upvotes: 0
Reputation: 7870
You can match the key with the following regex and see whether it returns true:
key.matches(".*\\.[A-Z]+");
Upvotes: 1