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.yangtools.yang.data.util;
10 import static com.google.common.base.Preconditions.checkArgument;
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.concepts.AbstractIllegalArgumentCodec;
17 import org.opendaylight.yangtools.yang.common.QName;
18 import org.opendaylight.yangtools.yang.common.QNameModule;
19 import org.opendaylight.yangtools.yang.common.XMLNamespace;
21 abstract class AbstractNamespaceCodec<T> extends AbstractIllegalArgumentCodec<String, T> {
22 private static final Splitter COLON_SPLITTER = Splitter.on(':');
25 * Return string prefix for a particular namespace, allocating a new one if necessary.
27 * @param namespace Namespace to map
28 * @return Allocated unique prefix, or null if the prefix cannot be mapped.
30 protected abstract @Nullable String prefixForNamespace(@NonNull XMLNamespace namespace);
33 * Create a QName for a prefix and local name.
35 * @param prefix Prefix for namespace
36 * @param localName local name
38 * @throws IllegalArgumentException if the prefix cannot be resolved
40 // FIXME: 9.0.0: this should really be @NonNull, right? we can also throw if localName is not valid
41 protected abstract @Nullable QName createQName(@NonNull String prefix, @NonNull String localName);
43 private static String getIdAndPrefixAsStr(final String pathPart) {
44 int predicateStartIndex = pathPart.indexOf('[');
45 return predicateStartIndex == -1 ? pathPart : pathPart.substring(0, predicateStartIndex);
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());
55 * Append a QName, potentially taking into account last QNameModule encountered in the serialized path.
57 * @param sb target StringBuilder
58 * @param qname QName to append
59 * @param lastModule last QNameModule encountered, may be null
60 * @return target StringBuilder
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);
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();
78 final String first = it.next().trim();
79 if (first.isEmpty()) {
83 final String identifier;
86 // It is "prefix:value"
88 identifier = it.next().trim();
93 if (identifier.isEmpty()) {
97 return createQName(prefix, identifier);