2 * Copyright (c) 2014 Cisco Systems, Inc. and others. All rights reserved.
4 * This program and the accompanying materials are made available under the
5 * terms of the Eclipse Public License v1.0 which accompanies this distribution,
6 * and is available at http://www.eclipse.org/legal/epl-v10.html
8 package org.opendaylight.yangtools.yang.data.util;
10 import com.google.common.annotations.Beta;
11 import com.google.common.base.Preconditions;
12 import com.google.common.base.Splitter;
14 import java.util.ArrayList;
15 import java.util.HashMap;
16 import java.util.Iterator;
17 import java.util.List;
19 import java.util.regex.Matcher;
20 import java.util.regex.Pattern;
22 import org.opendaylight.yangtools.yang.common.QName;
23 import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier;
24 import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier.NodeIdentifierWithPredicates;
25 import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier.NodeWithValue;
26 import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier.PathArgument;
27 import org.opendaylight.yangtools.yang.data.api.codec.InstanceIdentifierCodec;
30 * Abstract utility class for representations which encode {@link YangInstanceIdentifier} as a
31 * prefix:name tuple. Typical uses are RESTCONF/JSON (module:name) and XML (prefix:name).
34 public abstract class AbstractStringInstanceIdentifierCodec extends AbstractNamespaceCodec implements InstanceIdentifierCodec<String> {
35 private static final Pattern PREDICATE_PATTERN = Pattern.compile("\\[(.*?)\\]");
36 private static final Splitter SLASH_SPLITTER = Splitter.on('/');
39 public final String serialize(final YangInstanceIdentifier data) {
40 StringBuilder sb = new StringBuilder();
41 for (PathArgument arg : data.getPathArguments()) {
43 appendQName(sb, arg.getNodeType());
45 if (arg instanceof NodeIdentifierWithPredicates) {
46 for (Map.Entry<QName, Object> entry : ((NodeIdentifierWithPredicates) arg).getKeyValues().entrySet()) {
48 appendQName(sb, entry.getKey());
50 sb.append(String.valueOf(entry.getValue()));
53 } else if (arg instanceof NodeWithValue) {
55 sb.append(((NodeWithValue) arg).getValue());
64 public final YangInstanceIdentifier deserialize(final String data) {
65 Preconditions.checkNotNull(data, "Data may not be null");
67 final Iterator<String> xPathParts = SLASH_SPLITTER.split(data).iterator();
69 // must be at least "/pr:node"
70 if (!xPathParts.hasNext() || !xPathParts.next().isEmpty() || !xPathParts.hasNext()) {
74 List<PathArgument> result = new ArrayList<>();
75 while (xPathParts.hasNext()) {
76 String xPathPartTrimmed = xPathParts.next().trim();
78 PathArgument pathArgument = toPathArgument(xPathPartTrimmed);
79 if (pathArgument != null) {
80 result.add(pathArgument);
83 return YangInstanceIdentifier.create(result);
86 private PathArgument toPathArgument(final String xPathArgument) {
87 final QName mainQName = parseQName(xPathArgument);
90 final Matcher matcher = PREDICATE_PATTERN.matcher(xPathArgument);
91 final Map<QName, Object> predicates = new HashMap<>();
92 QName currentQName = mainQName;
94 while (matcher.find()) {
95 final String predicateStr = matcher.group(1).trim();
96 final int indexOfEqualityMark = predicateStr.indexOf('=');
97 if (indexOfEqualityMark != -1) {
98 final String predicateValue = toPredicateValue(predicateStr.substring(indexOfEqualityMark + 1));
99 if (predicateValue == null) {
103 if (predicateStr.charAt(0) != '.') {
104 // target is not a leaf-list
105 currentQName = parseQName(predicateStr.substring(0, indexOfEqualityMark));
106 if (currentQName == null) {
110 predicates.put(currentQName, predicateValue);
114 if (predicates.isEmpty()) {
115 return new YangInstanceIdentifier.NodeIdentifier(mainQName);
117 return new YangInstanceIdentifier.NodeIdentifierWithPredicates(mainQName, predicates);
121 private static String toPredicateValue(final String predicatedValue) {
122 final String predicatedValueTrimmed = predicatedValue.trim();
123 if (predicatedValue.isEmpty()) {
127 switch (predicatedValueTrimmed.charAt(0)) {
129 return trimIfEndIs(predicatedValueTrimmed, '"');
131 return trimIfEndIs(predicatedValueTrimmed, '\'');
137 private static String trimIfEndIs(final String str, final char end) {
138 final int l = str.length() - 1;
139 if (str.charAt(l) != end) {
143 return str.substring(1, l);