package alien4cloud.tosca.parser.impl.base; import java.util.Map; import javax.annotation.Resource; import org.springframework.beans.BeanWrapper; import org.springframework.beans.BeanWrapperImpl; import org.springframework.beans.factory.config.ConfigurableBeanFactory; import org.springframework.context.annotation.Scope; import org.springframework.stereotype.Component; import org.yaml.snakeyaml.nodes.MappingNode; import org.yaml.snakeyaml.nodes.Node; import org.yaml.snakeyaml.nodes.NodeTuple; import org.yaml.snakeyaml.nodes.ScalarNode; import com.google.common.collect.Maps; import alien4cloud.tosca.parser.INodeParser; import alien4cloud.tosca.parser.ParserUtils; import alien4cloud.tosca.parser.ParsingContextExecution; @Component @Scope(value = ConfigurableBeanFactory.SCOPE_PROTOTYPE) public class MapParser<T> implements INodeParser<Map<String, T>> { @Resource private ScalarParser scalarParser; private INodeParser<T> valueParser; /** The tosca type of the map. */ private String toscaType; /** Optional value to inject the key into the value object. */ private String keyPath; public MapParser(INodeParser<T> valueParser, String toscaType) { this.valueParser = valueParser; this.toscaType = toscaType; this.keyPath = null; } public MapParser(INodeParser<T> valueParser, String toscaType, String keyPath) { this.valueParser = valueParser; this.toscaType = toscaType; this.keyPath = keyPath; } protected void setValueParser(INodeParser<T> valueParser) { this.valueParser = valueParser; } @Override public Map<String, T> parse(Node node, ParsingContextExecution context) { if (node instanceof MappingNode) { return doParse((MappingNode) node, context); } else if (node instanceof ScalarNode) { String scalarValue = ((ScalarNode) node).getValue(); if (scalarValue == null || scalarValue.trim().isEmpty()) { // node is just not defined, return null. return null; } } ParserUtils.addTypeError(node, context.getParsingErrors(), toscaType); return null; } private Map<String, T> doParse(MappingNode node, ParsingContextExecution context) { Map<String, T> map = Maps.newLinkedHashMap(); for (NodeTuple entry : node.getValue()) { String key = scalarParser.parse(entry.getKeyNode(), context); T value = null; value = valueParser.parse(entry.getValueNode(), context); if (value != null) { if (keyPath != null) { BeanWrapper valueWrapper = new BeanWrapperImpl(value); valueWrapper.setPropertyValue(keyPath, key); } map.put(key, value); } } return map; } }