Cleanup use of Guava library
[yangtools.git] / yang / yang-data-codec-xml / src / main / java / org / opendaylight / yangtools / yang / data / codec / xml / XmlStringInstanceIdentifierCodec.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 static com.google.common.base.Preconditions.checkArgument;
12 import static java.util.Objects.requireNonNull;
13
14 import java.net.URI;
15 import java.util.ArrayDeque;
16 import java.util.Deque;
17 import javax.annotation.Nonnull;
18 import javax.xml.namespace.NamespaceContext;
19 import javax.xml.stream.XMLStreamException;
20 import javax.xml.stream.XMLStreamWriter;
21 import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier;
22 import org.opendaylight.yangtools.yang.data.util.AbstractModuleStringInstanceIdentifierCodec;
23 import org.opendaylight.yangtools.yang.data.util.DataSchemaContextTree;
24 import org.opendaylight.yangtools.yang.model.api.DataSchemaNode;
25 import org.opendaylight.yangtools.yang.model.api.LeafSchemaNode;
26 import org.opendaylight.yangtools.yang.model.api.Module;
27 import org.opendaylight.yangtools.yang.model.api.SchemaContext;
28
29 final class XmlStringInstanceIdentifierCodec extends AbstractModuleStringInstanceIdentifierCodec
30         implements XmlCodec<YangInstanceIdentifier> {
31
32     private static final ThreadLocal<Deque<NamespaceContext>> TL_CONTEXT = new ThreadLocal<>();
33
34     private final DataSchemaContextTree dataContextTree;
35     private final XmlCodecFactory codecFactory;
36     private final SchemaContext context;
37
38     XmlStringInstanceIdentifierCodec(final SchemaContext context, final XmlCodecFactory xmlCodecFactory) {
39         this.context = requireNonNull(context);
40         this.dataContextTree = DataSchemaContextTree.from(context);
41         this.codecFactory = requireNonNull(xmlCodecFactory);
42     }
43
44     @Override
45     protected Module moduleForPrefix(@Nonnull final String prefix) {
46         final String prefixedNS = getNamespaceContext().getNamespaceURI(prefix);
47         return context.findModuleByNamespaceAndRevision(URI.create(prefixedNS), null);
48     }
49
50     @Override
51     protected String prefixForNamespace(@Nonnull final URI namespace) {
52         final Module module = context.findModuleByNamespaceAndRevision(namespace, null);
53         return module == null ? null : module.getName();
54     }
55
56     @Nonnull
57     @Override
58     protected DataSchemaContextTree getDataContextTree() {
59         return dataContextTree;
60     }
61
62     @Override
63     protected Object deserializeKeyValue(final DataSchemaNode schemaNode, final String value) {
64         requireNonNull(schemaNode, "schemaNode cannot be null");
65         checkArgument(schemaNode instanceof LeafSchemaNode, "schemaNode must be of type LeafSchemaNode");
66         final XmlCodec<?> objectXmlCodec = codecFactory.codecFor((LeafSchemaNode) schemaNode);
67         return objectXmlCodec.parseValue(getNamespaceContext(), value);
68     }
69
70     @Override
71     public Class<YangInstanceIdentifier> getDataType() {
72         return YangInstanceIdentifier.class;
73     }
74
75     @Override
76     public YangInstanceIdentifier parseValue(final NamespaceContext ctx, final String str) {
77         pushNamespaceContext(ctx);
78         try {
79             return deserialize(str);
80         } finally {
81             popNamespaceContext();
82         }
83     }
84
85     @Override
86     public void writeValue(final XMLStreamWriter ctx, final YangInstanceIdentifier value)
87             throws XMLStreamException {
88         ctx.writeCharacters(serialize(value));
89     }
90
91     private static NamespaceContext getNamespaceContext() {
92         return TL_CONTEXT.get().getFirst();
93     }
94
95     private static void popNamespaceContext() {
96         final Deque<NamespaceContext> stack = TL_CONTEXT.get();
97         stack.pop();
98         if (stack.isEmpty()) {
99             TL_CONTEXT.set(null);
100         }
101     }
102
103     private static void pushNamespaceContext(final NamespaceContext context) {
104         Deque<NamespaceContext> stack = TL_CONTEXT.get();
105         if (stack == null) {
106             stack = new ArrayDeque<>(1);
107             TL_CONTEXT.set(stack);
108         }
109         stack.push(context);
110     }
111 }