/*
* To change this license header, choose License Headers in Project Properties.
* To change this template file, choose Tools | Templates
* and open the template in the editor.
*/
package se.kth.karamel.common.clusterdef.yaml;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Set;
import se.kth.karamel.common.clusterdef.Scope;
import se.kth.karamel.common.util.Settings;
import se.kth.karamel.common.clusterdef.json.JsonCookbook;
import se.kth.karamel.common.clusterdef.json.JsonScope;
import se.kth.karamel.common.util.CollectionsUtil;
import se.kth.karamel.common.exception.MetadataParseException;
import se.kth.karamel.common.exception.ValidationException;
/**
*
* @author kamal
*/
public abstract class YamlScope extends Scope {
private Map<String, Object> attrs = new HashMap<>();
public YamlScope() {
}
public YamlScope(JsonScope scope) throws MetadataParseException {
super(scope);
List<JsonCookbook> cookbooks = scope.getCookbooks();
for (JsonCookbook cb : cookbooks) {
Set<Map.Entry<String, Object>> entries = cb.getAttrs().entrySet();
for (Map.Entry<String, Object> entry : entries) {
foldOutAttr(entry.getKey(), entry.getValue(), attrs);
}
}
}
public void foldOutAttr(String key, Object value, Map<String, Object> map) throws MetadataParseException {
String[] comps = key.split(Settings.ATTR_DELIMITER);
Map<String, Object> parent = map;
for (int i = 0; i < comps.length; i++) {
String comp = comps[i];
if (i == comps.length - 1) {
if (parent.containsKey(comp) && !parent.get(comp).equals(value)) {
throw new MetadataParseException(String.format("Ambiguous value for attribute '%s' 1st '%s' 2nd '%s' ", key,
parent.get(comp), value));
} else {
parent.put(comp, value);
}
} else {
Object next = parent.get(comp);
if (next == null) {
next = new HashMap<>();
parent.put(comp, next);
} else if (!(next instanceof Map)) {
throw new MetadataParseException(String.format("Component '%s' in attributed has both simple value '%s' and "
+ "compound value '%s' ", comp, key, next, comps[i + 1]));
}
parent = (Map<String, Object>) next;
}
}
}
@Override
public Object getAttr(String key) {
String[] comps = key.split(Settings.ATTR_DELIMITER);
Map<String, Object> parent = attrs;
for (int i = 0; i < comps.length; i++) {
String comp = comps[i];
Object child = parent.get(comp);
if (child == null) {
return null;
} else if (child instanceof Map) {
parent = (Map<String, Object>) child;
} else {
if (i == comps.length - 1) {
if (child instanceof List) {
List<Object> list = (List<Object>) child;
return CollectionsUtil.asStringList(list);
} else {
return child.toString();
}
} else {
return null;
}
}
}
return null;
}
public Map<String, Object> getAttrs() {
return attrs;
}
public void setAttrs(Map<String, Object> attrs) {
this.attrs = attrs;
}
public Map<String, Object> flattenAttrs() throws ValidationException {
return flattenAttrs(attrs, "");
}
public Map<String, Object> flattenAttrs(Map<String, Object> map, String partialName) throws ValidationException {
Map<String, Object> flatten = new HashMap<>();
if (map == null) {
throw new ValidationException("attributes block cannot be empty");
}
Set<Map.Entry<String, Object>> entrySet = map.entrySet();
for (Map.Entry<String, Object> entry : entrySet) {
String key = ((partialName.isEmpty()) ? "" : partialName + "/") + entry.getKey();
Object value = entry.getValue();
if (value instanceof Map) {
flatten.putAll(flattenAttrs((Map<String, Object>) value, key));
} else {
if (value == null) {
throw new ValidationException(String.format("attribute '%s' doesn't have any value", key));
} else if (value instanceof List) {
List<Object> list = (List<Object>) value;
flatten.put(key, CollectionsUtil.asStringList(list));
} else {
flatten.put(key, value.toString());
}
}
}
return flatten;
}
}