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