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