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