2 * Copyright (c) 2014 Cisco Systems, Inc. and others. All rights reserved.
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
8 package org.opendaylight.restconf.common.util;
10 import com.google.common.base.Preconditions;
11 import java.io.IOException;
12 import java.io.InputStream;
13 import java.io.PushbackInputStream;
14 import java.util.ArrayList;
15 import java.util.List;
16 import java.util.Optional;
17 import java.util.regex.Matcher;
18 import java.util.regex.Pattern;
19 import javax.xml.stream.events.StartElement;
20 import org.opendaylight.restconf.common.util.IdentityValuesDTO.IdentityValue;
21 import org.opendaylight.restconf.common.util.IdentityValuesDTO.Predicate;
22 import org.opendaylight.yangtools.yang.model.api.TypeDefinition;
24 public final class RestUtil {
26 // FIXME: BUG-1275: this is code duplicates data.impl.codec
28 public static final String SQUOTE = "'";
29 public static final String DQUOTE = "\"";
30 private static final Pattern PREDICATE_PATTERN = Pattern.compile("\\[(.*?)\\]");
32 public static TypeDefinition<?> resolveBaseTypeFrom(final TypeDefinition<?> type) {
33 TypeDefinition<?> superType = type;
34 while (superType.getBaseType() != null) {
35 superType = superType.getBaseType();
41 * Utility method to find out if is provided {@link InputStream} empty.
43 * @param entityStream {@link InputStream} to be checked if it is empty.
44 * @return Empty Optional if provided input stream is empty or Optional
45 * containing input stream otherwise.
47 * @throws IOException if an IO error arises during stream inspection.
48 * @throws NullPointerException if provided stream is null.
51 public static Optional<InputStream> isInputStreamEmpty(final InputStream entityStream) throws IOException {
52 Preconditions.checkNotNull(entityStream);
53 final PushbackInputStream pushbackInputStream = new PushbackInputStream(entityStream);
55 int firstByte = pushbackInputStream.read();
56 if (firstByte == -1) {
57 return Optional.empty();
59 pushbackInputStream.unread(firstByte);
60 return Optional.of(pushbackInputStream);
64 public static IdentityValuesDTO asInstanceIdentifier(final String value, final PrefixesMaping prefixMap) {
65 final String valueTrimmed = value.trim();
66 if (!valueTrimmed.startsWith("/")) {
69 final String[] xPathParts = valueTrimmed.split("/");
70 if (xPathParts.length < 2) { // must be at least "/pr:node"
73 final IdentityValuesDTO identityValuesDTO = new IdentityValuesDTO(value);
74 for (int i = 1; i < xPathParts.length; i++) {
75 final String xPathPartTrimmed = xPathParts[i].trim();
77 final String xPathPartStr = getIdAndPrefixAsStr(xPathPartTrimmed);
78 final IdentityValue identityValue = toIdentity(xPathPartStr, prefixMap);
79 if (identityValue == null) {
83 final List<Predicate> predicates = toPredicates(xPathPartTrimmed, prefixMap);
84 if (predicates == null) {
87 identityValue.setPredicates(predicates);
89 identityValuesDTO.add(identityValue);
91 return identityValuesDTO.getValuesWithNamespaces().isEmpty() ? null : identityValuesDTO;
94 private static String getIdAndPrefixAsStr(final String pathPart) {
95 final int predicateStartIndex = pathPart.indexOf("[");
96 return predicateStartIndex == -1 ? pathPart : pathPart.substring(0, predicateStartIndex);
99 private static IdentityValue toIdentity(final String xpathPart, final PrefixesMaping prefixMap) {
100 final String xPathPartTrimmed = xpathPart.trim();
101 if (xPathPartTrimmed.isEmpty()) {
104 final String[] prefixAndIdentifier = xPathPartTrimmed.split(":");
105 // it is not "prefix:value"
106 if (prefixAndIdentifier.length != 2) {
109 final String prefix = prefixAndIdentifier[0].trim();
110 final String identifier = prefixAndIdentifier[1].trim();
111 if (prefix.isEmpty() || identifier.isEmpty()) {
114 final String namespace = prefixMap.getNamespace(prefix);
115 return new IdentityValue(namespace, identifier);
118 private static List<Predicate> toPredicates(final String predicatesStr, final PrefixesMaping prefixMap) {
119 final List<Predicate> result = new ArrayList<>();
120 final List<String> predicates = new ArrayList<>();
121 final Matcher matcher = PREDICATE_PATTERN.matcher(predicatesStr);
122 while (matcher.find()) {
123 predicates.add(matcher.group(1).trim());
125 for (final String predicate : predicates) {
126 final int indexOfEqualityMark = predicate.indexOf("=");
127 if (indexOfEqualityMark != -1) {
128 final String predicateValue = toPredicateValue(predicate.substring(indexOfEqualityMark + 1));
129 if (predicate.startsWith(".")) { // it is leaf-list
130 if (predicateValue == null) {
133 result.add(new Predicate(null, predicateValue));
135 final IdentityValue identityValue =
136 toIdentity(predicate.substring(0, indexOfEqualityMark), prefixMap);
137 if (identityValue == null || predicateValue == null) {
140 result.add(new Predicate(identityValue, predicateValue));
147 private static String toPredicateValue(final String predicatedValue) {
148 final String predicatedValueTrimmed = predicatedValue.trim();
149 if ((predicatedValueTrimmed.startsWith(DQUOTE) || predicatedValueTrimmed.startsWith(SQUOTE))
150 && (predicatedValueTrimmed.endsWith(DQUOTE) || predicatedValueTrimmed.endsWith(SQUOTE))) {
151 return predicatedValueTrimmed.substring(1, predicatedValueTrimmed.length() - 1);
156 public interface PrefixesMaping {
157 String getNamespace(String prefix);
160 public static class PrefixMapingFromXml implements PrefixesMaping {
161 StartElement startElement = null;
163 public PrefixMapingFromXml(final StartElement startElement) {
164 this.startElement = startElement;
168 public String getNamespace(final String prefix) {
169 return startElement.getNamespaceContext().getNamespaceURI(prefix);
173 public static class PrefixMapingFromJson implements PrefixesMaping {
176 public String getNamespace(final String prefix) {