package alien4cloud.tosca.parser.impl.advanced; import java.util.HashMap; import java.util.List; import java.util.Map; import java.util.regex.Matcher; import java.util.regex.Pattern; import org.springframework.stereotype.Component; import org.yaml.snakeyaml.nodes.MappingNode; import org.yaml.snakeyaml.nodes.Node; import org.yaml.snakeyaml.nodes.ScalarNode; import org.yaml.snakeyaml.nodes.SequenceNode; import com.google.common.collect.Lists; import alien4cloud.tosca.parser.INodeParser; import alien4cloud.tosca.parser.ParserUtils; import alien4cloud.tosca.parser.ParsingContextExecution; import alien4cloud.tosca.parser.ParsingError; import alien4cloud.tosca.parser.impl.ErrorCode; /** * Parse a tosca Scalar unit field. */ @Component public class PropertyValueParser implements INodeParser<Object> { private static final Map<String, Double> factorMap = new HashMap<String, Double>(5); private static final Pattern scalarUnitPattern = Pattern.compile("([0-9.]+)\\s*([a-zA-Z]+)"); static { factorMap.put("b", 1d); factorMap.put("kb", 1000d); factorMap.put("mb", 1000000d); factorMap.put("gb", 1000000000d); factorMap.put("tb", 1000000000000d); } private final double factor; public PropertyValueParser() { this("b"); } /** * Create a scalar unit parser. * * @param targetFactor The factor as expected in the object model. */ public PropertyValueParser(String targetFactor) { factor = factorMap.get(targetFactor.toLowerCase()); } @Override public Object parse(Node node, ParsingContextExecution context) { if (node instanceof ScalarNode) { String scalarValue = ParserUtils.getScalar(node, context); // parse to get the number value and the unit value Matcher matcher = scalarUnitPattern.matcher(scalarValue); if (matcher.matches()) { Double value = Double.valueOf(matcher.group(1)); String unitValue = matcher.group(2).toLowerCase(); Double unitFactor = factorMap.get(unitValue); if (unitFactor == null) { context.getParsingErrors().add(new ParsingError(ErrorCode.INVALID_SCALAR_UNIT, "Unable to parse Tosca scalar-unit.", node.getStartMark(), "Unit is not a valid tosca unit, should be one of (B, kB, MB, GB, TB).", node.getEndMark(), scalarValue)); return null; } return new Double(value.doubleValue() * unitFactor.doubleValue() / factor).toString(); } return scalarValue; } else if (node instanceof SequenceNode) { SequenceNode sequenceNode = (SequenceNode) node; List<Object> valueList = Lists.newArrayList(); for (Node valueNode : sequenceNode.getValue()) { Object value = parse(valueNode, context); valueList.add(value); } return valueList; } else if (node instanceof MappingNode) { context.getParsingErrors().add(new ParsingError(ErrorCode.ALIEN_MAPPING_ERROR, "Alien is currently not able to manage complex objects as property values.", node.getStartMark(), "", node.getEndMark(), "")); } return null; } }