9deb2ca0329ed30416db6f913d6d9dfdb4013294
[netconf.git] / restconf / restconf-common / src / main / java / org / opendaylight / restconf / common / util / RestUtil.java
1 /*
2  * Copyright (c) 2014 Cisco Systems, Inc. and others.  All rights reserved.
3  *
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
7  */
8 package org.opendaylight.restconf.common.util;
9
10 import java.util.ArrayList;
11 import java.util.List;
12 import java.util.regex.Matcher;
13 import java.util.regex.Pattern;
14 import javax.xml.stream.events.StartElement;
15 import org.opendaylight.restconf.common.util.IdentityValuesDTO.IdentityValue;
16 import org.opendaylight.restconf.common.util.IdentityValuesDTO.Predicate;
17 import org.opendaylight.yangtools.yang.model.api.TypeDefinition;
18
19 public final class RestUtil {
20
21     // FIXME: BUG-1275: this is code duplicates data.impl.codec
22
23     public static final String SQUOTE = "'";
24     public static final String DQUOTE = "\"";
25     private static final Pattern PREDICATE_PATTERN = Pattern.compile("\\[(.*?)\\]");
26
27     public static TypeDefinition<?> resolveBaseTypeFrom(final TypeDefinition<?> type) {
28         TypeDefinition<?> superType = type;
29         while (superType.getBaseType() != null) {
30             superType = superType.getBaseType();
31         }
32         return superType;
33     }
34
35     public static IdentityValuesDTO asInstanceIdentifier(final String value, final PrefixesMaping prefixMap) {
36         final String valueTrimmed = value.trim();
37         if (!valueTrimmed.startsWith("/")) {
38             return null;
39         }
40         final String[] xPathParts = valueTrimmed.split("/");
41         if (xPathParts.length < 2) { // must be at least "/pr:node"
42             return null;
43         }
44         final IdentityValuesDTO identityValuesDTO = new IdentityValuesDTO(value);
45         for (int i = 1; i < xPathParts.length; i++) {
46             final String xPathPartTrimmed = xPathParts[i].trim();
47
48             final String xPathPartStr = getIdAndPrefixAsStr(xPathPartTrimmed);
49             final IdentityValue identityValue = toIdentity(xPathPartStr, prefixMap);
50             if (identityValue == null) {
51                 return null;
52             }
53
54             final List<Predicate> predicates = toPredicates(xPathPartTrimmed, prefixMap);
55             if (predicates == null) {
56                 return null;
57             }
58             identityValue.setPredicates(predicates);
59
60             identityValuesDTO.add(identityValue);
61         }
62         return identityValuesDTO.getValuesWithNamespaces().isEmpty() ? null : identityValuesDTO;
63     }
64
65     private static String getIdAndPrefixAsStr(final String pathPart) {
66         final int predicateStartIndex = pathPart.indexOf("[");
67         return predicateStartIndex == -1 ? pathPart : pathPart.substring(0, predicateStartIndex);
68     }
69
70     private static IdentityValue toIdentity(final String xpathPart, final PrefixesMaping prefixMap) {
71         final String xPathPartTrimmed = xpathPart.trim();
72         if (xPathPartTrimmed.isEmpty()) {
73             return null;
74         }
75         final String[] prefixAndIdentifier = xPathPartTrimmed.split(":");
76         // it is not "prefix:value"
77         if (prefixAndIdentifier.length != 2) {
78             return null;
79         }
80         final String prefix = prefixAndIdentifier[0].trim();
81         final String identifier = prefixAndIdentifier[1].trim();
82         if (prefix.isEmpty() || identifier.isEmpty()) {
83             return null;
84         }
85         final String namespace = prefixMap.getNamespace(prefix);
86         return new IdentityValue(namespace, identifier);
87     }
88
89     private static List<Predicate> toPredicates(final String predicatesStr, final PrefixesMaping prefixMap) {
90         final List<Predicate> result = new ArrayList<>();
91         final List<String> predicates = new ArrayList<>();
92         final Matcher matcher = PREDICATE_PATTERN.matcher(predicatesStr);
93         while (matcher.find()) {
94             predicates.add(matcher.group(1).trim());
95         }
96         for (final String predicate : predicates) {
97             final int indexOfEqualityMark = predicate.indexOf("=");
98             if (indexOfEqualityMark != -1) {
99                 final String predicateValue = toPredicateValue(predicate.substring(indexOfEqualityMark + 1));
100                 if (predicate.startsWith(".")) { // it is leaf-list
101                     if (predicateValue == null) {
102                         return null;
103                     }
104                     result.add(new Predicate(null, predicateValue));
105                 } else {
106                     final IdentityValue identityValue =
107                             toIdentity(predicate.substring(0, indexOfEqualityMark), prefixMap);
108                     if (identityValue == null || predicateValue == null) {
109                         return null;
110                     }
111                     result.add(new Predicate(identityValue, predicateValue));
112                 }
113             }
114         }
115         return result;
116     }
117
118     private static String toPredicateValue(final String predicatedValue) {
119         final String predicatedValueTrimmed = predicatedValue.trim();
120         if ((predicatedValueTrimmed.startsWith(DQUOTE) || predicatedValueTrimmed.startsWith(SQUOTE))
121                 && (predicatedValueTrimmed.endsWith(DQUOTE) || predicatedValueTrimmed.endsWith(SQUOTE))) {
122             return predicatedValueTrimmed.substring(1, predicatedValueTrimmed.length() - 1);
123         }
124         return null;
125     }
126
127     public interface PrefixesMaping {
128         String getNamespace(String prefix);
129     }
130
131     public static class PrefixMapingFromXml implements PrefixesMaping {
132         StartElement startElement = null;
133
134         public PrefixMapingFromXml(final StartElement startElement) {
135             this.startElement = startElement;
136         }
137
138         @Override
139         public String getNamespace(final String prefix) {
140             return startElement.getNamespaceContext().getNamespaceURI(prefix);
141         }
142     }
143
144     public static class PrefixMapingFromJson implements PrefixesMaping {
145
146         @Override
147         public String getNamespace(final String prefix) {
148             return prefix;
149         }
150     }
151
152 }