--- /dev/null
+/*
+ * Copyright (c) 2014 Cisco Systems, Inc. and others. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0 which accompanies this distribution,
+ * and is available at http://www.eclipse.org/legal/epl-v10.html
+ */
+package org.opendaylight.yangtools.yang.data.codec.gson;
+
+import com.google.common.base.Preconditions;
+import com.google.gson.stream.JsonWriter;
+import java.io.IOException;
+import org.opendaylight.yangtools.yang.common.QName;
+import org.opendaylight.yangtools.yang.common.QNameModule;
+import org.opendaylight.yangtools.yang.data.util.codec.QNameCodecUtil;
+import org.opendaylight.yangtools.yang.model.api.Module;
+import org.opendaylight.yangtools.yang.model.api.SchemaContext;
+
+final class IdentityrefJSONCodec implements JSONCodec<QName> {
+ private final SchemaContext schemaContext;
+ private final QNameModule parentModule;
+
+ IdentityrefJSONCodec(final SchemaContext context, final QNameModule parentModule) {
+ this.schemaContext = Preconditions.checkNotNull(context);
+ this.parentModule = Preconditions.checkNotNull(parentModule);
+ }
+
+ @Override
+ public Class<QName> getDataType() {
+ return QName.class;
+ }
+
+ @Override
+ public QName parseValue(final Object ctx, final String value) {
+ return QNameCodecUtil.decodeQName(value, prefix -> {
+ if (prefix.isEmpty()) {
+ return parentModule;
+ }
+
+ final Module module = schemaContext.findModuleByName(prefix, null);
+ Preconditions.checkArgument(module != null, "Could not find module %s", prefix);
+ return module.getQNameModule();
+ });
+ }
+
+ /**
+ * Serialize QName with specified JsonWriter.
+ *
+ * @param writer JsonWriter
+ * @param value QName
+ */
+ @Override
+ public void writeValue(final JsonWriter writer, final QName value) throws IOException {
+ final String str = QNameCodecUtil.encodeQName(value, uri -> {
+ final Module module = schemaContext.findModuleByNamespaceAndRevision(uri.getNamespace(), null);
+ Preconditions.checkArgument(module != null, "Cannot find module for %s", uri);
+ return module.getName();
+ });
+ writer.value(str);
+ }
+}
@Override
protected JSONCodec<?> identityRefCodec(final IdentityrefTypeDefinition type, final QNameModule module) {
- return new JSONStringIdentityrefCodec(getSchemaContext(), module);
+ return new IdentityrefJSONCodec(getSchemaContext(), module);
}
@Override
+++ /dev/null
-/*
- * Copyright (c) 2014 Cisco Systems, Inc. and others. All rights reserved.
- *
- * This program and the accompanying materials are made available under the
- * terms of the Eclipse Public License v1.0 which accompanies this distribution,
- * and is available at http://www.eclipse.org/legal/epl-v10.html
- */
-package org.opendaylight.yangtools.yang.data.codec.gson;
-
-import com.google.gson.stream.JsonWriter;
-import java.io.IOException;
-import javax.annotation.Nonnull;
-import org.opendaylight.yangtools.yang.common.QName;
-import org.opendaylight.yangtools.yang.common.QNameModule;
-import org.opendaylight.yangtools.yang.data.util.ModuleStringIdentityrefCodec;
-import org.opendaylight.yangtools.yang.model.api.Module;
-import org.opendaylight.yangtools.yang.model.api.SchemaContext;
-
-final class JSONStringIdentityrefCodec extends ModuleStringIdentityrefCodec implements JSONCodec<QName> {
- JSONStringIdentityrefCodec(final SchemaContext context, final QNameModule parentModule) {
- super(context, parentModule);
- }
-
- @Override
- protected Module moduleForPrefix(@Nonnull final String prefix) {
- if (prefix.isEmpty()) {
- return context.findModuleByNamespaceAndRevision(parentModuleQname.getNamespace(),
- parentModuleQname.getRevision());
- }
-
- return context.findModuleByName(prefix, null);
- }
-
- @Override
- public Class<QName> getDataType() {
- return QName.class;
- }
-
- @Override
- public QName parseValue(final Object ctx, final String str) {
- return deserialize(str);
- }
-
- @Override
- public void writeValue(final JsonWriter ctx, final QName value) throws IOException {
- ctx.value(serialize(value));
- }
-}
package org.opendaylight.yangtools.yang.data.codec.xml;
+import com.google.common.base.Preconditions;
import java.net.URI;
-import java.util.ArrayDeque;
-import java.util.Deque;
-import javax.annotation.Nonnull;
+import java.util.Map.Entry;
import javax.xml.namespace.NamespaceContext;
import javax.xml.stream.XMLStreamException;
import javax.xml.stream.XMLStreamWriter;
import org.opendaylight.yangtools.yang.common.QName;
import org.opendaylight.yangtools.yang.common.QNameModule;
-import org.opendaylight.yangtools.yang.data.util.ModuleStringIdentityrefCodec;
+import org.opendaylight.yangtools.yang.data.util.codec.QNameCodecUtil;
import org.opendaylight.yangtools.yang.model.api.Module;
import org.opendaylight.yangtools.yang.model.api.SchemaContext;
-final class IdentityrefXmlCodec extends ModuleStringIdentityrefCodec implements XmlCodec<QName> {
- private static final ThreadLocal<Deque<NamespaceContext>> TL_NSCONTEXT = new ThreadLocal<>();
+final class IdentityrefXmlCodec implements XmlCodec<QName> {
+ private final SchemaContext schemaContext;
+ private final QNameModule parentModule;
IdentityrefXmlCodec(final SchemaContext context, final QNameModule parentModule) {
- super(context, parentModule);
- }
-
- @Override
- protected Module moduleForPrefix(@Nonnull final String prefix) {
- if (prefix.isEmpty()) {
- return context.findModuleByNamespaceAndRevision(parentModuleQname.getNamespace(),
- parentModuleQname.getRevision());
- }
-
- final String prefixedNS = getNamespaceContext().getNamespaceURI(prefix);
- return context.findModuleByNamespaceAndRevision(URI.create(prefixedNS), null);
+ this.schemaContext = Preconditions.checkNotNull(context);
+ this.parentModule = Preconditions.checkNotNull(parentModule);
}
@Override
@Override
public QName parseValue(final NamespaceContext ctx, final String str) {
- pushNamespaceContext(ctx);
- try {
- return deserialize(str);
- } finally {
- popNamespaceContext();
- }
+ return QNameCodecUtil.decodeQName(str, prefix -> {
+ if (prefix.isEmpty()) {
+ return parentModule;
+ }
+
+ final String prefixedNS = ctx.getNamespaceURI(prefix);
+ final Module module = schemaContext.findModuleByNamespaceAndRevision(URI.create(prefixedNS), null);
+ Preconditions.checkArgument(module != null, "Could not find module for namespace %s", prefixedNS);
+ return module.getQNameModule();
+ });
}
@Override
public void writeValue(final XMLStreamWriter ctx, final QName value) throws XMLStreamException {
- // FIXME: this does not work correctly, as we need to populate entries into the namespace context
- ctx.writeCharacters(serialize(value));
- }
-
- private static NamespaceContext getNamespaceContext() {
- return TL_NSCONTEXT.get().getFirst();
- }
-
- private static void popNamespaceContext() {
- final Deque<NamespaceContext> stack = TL_NSCONTEXT.get();
- stack.pop();
- if (stack.isEmpty()) {
- TL_NSCONTEXT.set(null);
- }
- }
+ final RandomPrefix prefixes = new RandomPrefix(ctx.getNamespaceContext());
+ final String str = QNameCodecUtil.encodeQName(value, uri -> prefixes.encodePrefix(uri.getNamespace()));
- private static void pushNamespaceContext(final NamespaceContext context) {
- Deque<NamespaceContext> stack = TL_NSCONTEXT.get();
- if (stack == null) {
- stack = new ArrayDeque<>(1);
- TL_NSCONTEXT.set(stack);
+ for (Entry<URI, String> e : prefixes.getPrefixes()) {
+ ctx.writeNamespace(e.getValue(), e.getKey().toString());
}
- stack.push(context);
+ ctx.writeCharacters(str);
}
}
--- /dev/null
+/*
+ * Copyright (c) 2017 Pantheon Technologies, s.r.o. and others. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0 which accompanies this distribution,
+ * and is available at http://www.eclipse.org/legal/epl-v10.html
+ */
+package org.opendaylight.yangtools.yang.data.util.codec;
+
+import com.google.common.annotations.Beta;
+import com.google.common.base.Preconditions;
+import com.google.common.base.Splitter;
+import java.util.Iterator;
+import java.util.function.Function;
+import org.opendaylight.yangtools.yang.common.QName;
+import org.opendaylight.yangtools.yang.common.QNameModule;
+
+/**
+ * Utility methods for parsing and writing QNames.
+ *
+ * @author Robert Varga
+ */
+@Beta
+public final class QNameCodecUtil {
+ private static final Splitter COLON_SPLITTER = Splitter.on(':').trimResults();
+
+ public static QName decodeQName(final String str, final Function<String, QNameModule> prefixToModule) {
+ final Iterator<String> it = COLON_SPLITTER.split(str).iterator();
+
+ // Empty string
+ final String identifier;
+ final String prefix;
+ if (it.hasNext()) {
+ final String first = it.next();
+ if (it.hasNext()) {
+ // It is "prefix:value"
+ prefix = first;
+ identifier = it.next();
+ Preconditions.checkArgument(!it.hasNext(), "Malformed QName '" + str + "'");
+ } else {
+ prefix = "";
+ identifier = first;
+ }
+ } else {
+ prefix = "";
+ identifier = "";
+ }
+
+ final QNameModule module = prefixToModule.apply(prefix);
+ Preconditions.checkArgument(module != null, "Cannot resolve prefix '%s' from %s", prefix, str);
+ return QName.create(module, identifier);
+ }
+
+ public static String encodeQName(final QName qname, final Function<QNameModule, String> moduleToPrefix) {
+ final String prefix = moduleToPrefix.apply(qname.getModule());
+ Preconditions.checkArgument(prefix != null, "Cannot allocated prefix for %s", qname);
+ return prefix.isEmpty() ? qname.getLocalName() : prefix + ":" + qname.getLocalName();
+ }
+}