BUG-7983: unify JSONCodec and XmlCodec methods
[yangtools.git] / yang / yang-data-codec-xml / src / main / java / org / opendaylight / yangtools / yang / data / codec / xml / IdentityrefXmlCodec.java
1 /*
2  * Copyright (c) 2016 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
9 package org.opendaylight.yangtools.yang.data.codec.xml;
10
11 import java.net.URI;
12 import java.util.ArrayDeque;
13 import java.util.Deque;
14 import javax.annotation.Nonnull;
15 import javax.xml.namespace.NamespaceContext;
16 import javax.xml.stream.XMLStreamException;
17 import javax.xml.stream.XMLStreamWriter;
18 import org.opendaylight.yangtools.yang.common.QName;
19 import org.opendaylight.yangtools.yang.common.QNameModule;
20 import org.opendaylight.yangtools.yang.data.util.ModuleStringIdentityrefCodec;
21 import org.opendaylight.yangtools.yang.model.api.Module;
22 import org.opendaylight.yangtools.yang.model.api.SchemaContext;
23
24 final class IdentityrefXmlCodec extends ModuleStringIdentityrefCodec implements XmlCodec<QName> {
25     private static final ThreadLocal<Deque<NamespaceContext>> TL_NSCONTEXT = new ThreadLocal<>();
26
27     IdentityrefXmlCodec(final SchemaContext context, final QNameModule parentModule) {
28         super(context, parentModule);
29     }
30
31     @Override
32     protected Module moduleForPrefix(@Nonnull final String prefix) {
33         if (prefix.isEmpty()) {
34             return context.findModuleByNamespaceAndRevision(parentModuleQname.getNamespace(),
35                     parentModuleQname.getRevision());
36         }
37
38         final String prefixedNS = getNamespaceContext().getNamespaceURI(prefix);
39         return context.findModuleByNamespaceAndRevision(URI.create(prefixedNS), null);
40     }
41
42     @Override
43     public Class<QName> getDataType() {
44         return QName.class;
45     }
46
47     @Override
48     public QName parseValue(final NamespaceContext ctx, final String str) {
49         pushNamespaceContext(ctx);
50         try {
51             return deserialize(str);
52         } finally {
53             popNamespaceContext();
54         }
55     }
56
57     @Override
58     public void writeValue(final XMLStreamWriter ctx, final QName value) throws XMLStreamException {
59         // FIXME: this does not work correctly, as we need to populate entries into the namespace context
60         ctx.writeCharacters(serialize(value));
61     }
62
63     private static NamespaceContext getNamespaceContext() {
64         return TL_NSCONTEXT.get().getFirst();
65     }
66
67     private static void popNamespaceContext() {
68         final Deque<NamespaceContext> stack = TL_NSCONTEXT.get();
69         stack.pop();
70         if (stack.isEmpty()) {
71             TL_NSCONTEXT.set(null);
72         }
73     }
74
75     private static void pushNamespaceContext(final NamespaceContext context) {
76         Deque<NamespaceContext> stack = TL_NSCONTEXT.get();
77         if (stack == null) {
78             stack = new ArrayDeque<>(1);
79             TL_NSCONTEXT.set(stack);
80         }
81         stack.push(context);
82     }
83 }