Clean up more Sonar warnings
[yangtools.git] / data / yang-data-util / src / main / java / org / opendaylight / yangtools / yang / data / util / AbstractNamespaceCodec.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.util;
9
10 import static com.google.common.base.Preconditions.checkArgument;
11
12 import com.google.common.base.Splitter;
13 import java.util.Iterator;
14 import org.eclipse.jdt.annotation.NonNull;
15 import org.eclipse.jdt.annotation.Nullable;
16 import org.opendaylight.yangtools.yang.common.QName;
17 import org.opendaylight.yangtools.yang.common.QNameModule;
18 import org.opendaylight.yangtools.yang.common.XMLNamespace;
19 import org.opendaylight.yangtools.yang.data.api.codec.AbstractIllegalArgumentCodec;
20
21 abstract class AbstractNamespaceCodec<T> extends AbstractIllegalArgumentCodec<String, T> {
22     private static final Splitter COLON_SPLITTER = Splitter.on(':');
23
24     /**
25      * Return string prefix for a particular namespace, allocating a new one if necessary.
26      *
27      * @param namespace Namespace to map
28      * @return Allocated unique prefix, or null if the prefix cannot be mapped.
29      */
30     protected abstract @Nullable String prefixForNamespace(@NonNull XMLNamespace namespace);
31
32     /**
33      * Create a QName for a prefix and local name.
34      *
35      * @param prefix Prefix for namespace
36      * @param localName local name
37      * @return QName
38      * @throws IllegalArgumentException if the {@code prefix} cannot be resolved or if the {@code localName} does not
39      *                                  conform to YANG requirements
40      */
41     protected abstract @NonNull QName createQName(@NonNull String prefix, @NonNull String localName);
42
43     private static String getIdAndPrefixAsStr(final String pathPart) {
44         int predicateStartIndex = pathPart.indexOf('[');
45         return predicateStartIndex == -1 ? pathPart : pathPart.substring(0, predicateStartIndex);
46     }
47
48     protected final @NonNull StringBuilder appendQName(final StringBuilder sb, final QName qname) {
49         final String prefix = prefixForNamespace(qname.getNamespace());
50         checkArgument(prefix != null, "Failed to map QName %s to prefix", qname);
51         return sb.append(prefix).append(':').append(qname.getLocalName());
52     }
53
54     /**
55      * Append a QName, potentially taking into account last QNameModule encountered in the serialized path.
56      *
57      * @param sb target StringBuilder
58      * @param qname QName to append
59      * @param lastModule last QNameModule encountered, may be null
60      * @return target StringBuilder
61      */
62     protected StringBuilder appendQName(final StringBuilder sb, final QName qname,
63             final @Nullable QNameModule lastModule) {
64         // Covers XML and uncompressed JSON codec
65         return appendQName(sb, qname);
66     }
67
68     protected final QName parseQName(final String str) {
69         final String xPathPartTrimmed = getIdAndPrefixAsStr(str).trim();
70         final Iterator<String> it = COLON_SPLITTER.split(xPathPartTrimmed).iterator();
71
72         // Empty string
73         if (!it.hasNext()) {
74             return null;
75         }
76
77
78         final String first = it.next().trim();
79         if (first.isEmpty()) {
80             return null;
81         }
82
83         final String identifier;
84         final String prefix;
85         if (it.hasNext()) {
86             // It is "prefix:value"
87             prefix = first;
88             identifier = it.next().trim();
89         } else {
90             prefix = "";
91             identifier = first;
92         }
93         if (identifier.isEmpty()) {
94             return null;
95         }
96
97         return createQName(prefix, identifier);
98     }
99 }