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