21df404f24ab513faea1dfae0796fb7ea526d3a6
[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> getDataClass() {
44         return QName.class;
45     }
46
47     /**
48      * Serialize QName with specified XMLStreamWriter.
49      *
50      * @param writer XMLStreamWriter
51      * @param value QName
52      */
53     @Override
54     public void serializeToWriter(final XMLStreamWriter writer, final QName value) throws XMLStreamException {
55         // FIXME: this does not work correctly, as we need to populate entries into the namespace context
56         writer.writeCharacters(serialize(value));
57     }
58
59     @Override
60     public QName deserializeFromString(final NamespaceContext namespaceContext, final String value) {
61         pushNamespaceContext(namespaceContext);
62         try {
63             return deserialize(value);
64         } finally {
65             popNamespaceContext();
66         }
67     }
68
69     private static NamespaceContext getNamespaceContext() {
70         return TL_NSCONTEXT.get().getFirst();
71     }
72
73     private static void popNamespaceContext() {
74         final Deque<NamespaceContext> stack = TL_NSCONTEXT.get();
75         stack.pop();
76         if (stack.isEmpty()) {
77             TL_NSCONTEXT.set(null);
78         }
79     }
80
81     private static void pushNamespaceContext(final NamespaceContext context) {
82         Deque<NamespaceContext> stack = TL_NSCONTEXT.get();
83         if (stack == null) {
84             stack = new ArrayDeque<>(1);
85             TL_NSCONTEXT.set(stack);
86         }
87         stack.push(context);
88     }
89 }