Remove use of thread-local output
[controller.git] / opendaylight / md-sal / sal-clustering-commons / src / main / java / org / opendaylight / controller / cluster / datastore / node / utils / stream / SerializationUtils.java
1 /*
2  * Copyright (c) 2014 Brocade Communications 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 package org.opendaylight.controller.cluster.datastore.node.utils.stream;
9
10 import java.io.ByteArrayInputStream;
11 import java.io.DataInput;
12 import java.io.DataInputStream;
13 import java.io.DataOutput;
14 import java.io.IOException;
15 import org.eclipse.jdt.annotation.NonNull;
16 import org.eclipse.jdt.annotation.Nullable;
17 import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier;
18 import org.opendaylight.yangtools.yang.data.api.schema.NormalizedNode;
19
20 /**
21  * Provides various utility methods for serialization and de-serialization.
22  *
23  * @author Thomas Pantelis
24  */
25 public final class SerializationUtils {
26     public static final ThreadLocal<NormalizedNodeDataInput> REUSABLE_READER_TL = new ThreadLocal<>();
27
28     private SerializationUtils() {
29     }
30
31     public interface Applier<T> {
32         void apply(T instance, YangInstanceIdentifier path, NormalizedNode<?, ?> node);
33     }
34
35     private static NormalizedNodeDataInput streamReader(final DataInput in) throws IOException {
36         NormalizedNodeDataInput streamReader = REUSABLE_READER_TL.get();
37         if (streamReader == null) {
38             streamReader = NormalizedNodeInputOutput.newDataInput(in);
39         }
40
41         return streamReader;
42     }
43
44     public static <T> void deserializePathAndNode(final DataInput in, final T instance, final Applier<T> applier) {
45         try {
46             NormalizedNodeDataInput streamReader = streamReader(in);
47             NormalizedNode<?, ?> node = streamReader.readNormalizedNode();
48             YangInstanceIdentifier path = streamReader.readYangInstanceIdentifier();
49             applier.apply(instance, path, node);
50         } catch (IOException e) {
51             throw new IllegalArgumentException("Error deserializing path and Node", e);
52         }
53     }
54
55     private static NormalizedNode<?, ?> tryDeserializeNormalizedNode(final DataInput in) throws IOException {
56         boolean present = in.readBoolean();
57         if (present) {
58             NormalizedNodeDataInput streamReader = streamReader(in);
59             return streamReader.readNormalizedNode();
60         }
61
62         return null;
63     }
64
65     public static NormalizedNode<?, ?> deserializeNormalizedNode(final DataInput in) {
66         try {
67             return tryDeserializeNormalizedNode(in);
68         } catch (IOException e) {
69             throw new IllegalArgumentException("Error deserializing NormalizedNode", e);
70         }
71     }
72
73     public static NormalizedNode<?, ?> deserializeNormalizedNode(final byte [] bytes) {
74         try {
75             return tryDeserializeNormalizedNode(new DataInputStream(new ByteArrayInputStream(bytes)));
76         } catch (IOException e) {
77             throw new IllegalArgumentException("Error deserializing NormalizedNode", e);
78         }
79     }
80
81     public static void writeNormalizedNode(final DataOutput out, final @Nullable NormalizedNode<?, ?> node)
82             throws IOException {
83         if (node != null) {
84             out.writeBoolean(true);
85
86             try (NormalizedNodeDataOutput stream = NormalizedNodeInputOutput.newDataOutput(out)) {
87                 stream.writeNormalizedNode(node);
88             }
89         } else {
90             out.writeBoolean(false);
91         }
92     }
93
94     public static void writePath(final DataOutput out, final @NonNull YangInstanceIdentifier path)
95             throws IOException {
96         try (NormalizedNodeDataOutput stream = NormalizedNodeInputOutput.newDataOutput(out)) {
97             stream.writeYangInstanceIdentifier(path);
98         }
99     }
100
101     public static void writeNodeAndPath(final DataOutput out, final YangInstanceIdentifier path,
102             final NormalizedNode<?, ?> node) throws IOException {
103         try (NormalizedNodeDataOutput stream = NormalizedNodeInputOutput.newDataOutput(out)) {
104             stream.writeNormalizedNode(node);
105             stream.writeYangInstanceIdentifier(path);
106         }
107     }
108
109     public static void writePathAndNode(final DataOutput out, final YangInstanceIdentifier path,
110             final NormalizedNode<?, ?> node) throws IOException {
111         try (NormalizedNodeDataOutput stream = NormalizedNodeInputOutput.newDataOutput(out)) {
112             stream.writeYangInstanceIdentifier(path);
113             stream.writeNormalizedNode(node);
114         }
115     }
116
117     public static YangInstanceIdentifier deserializePath(final DataInput in) {
118         try {
119             NormalizedNodeDataInput streamReader = streamReader(in);
120             return streamReader.readYangInstanceIdentifier();
121         } catch (IOException e) {
122             throw new IllegalArgumentException("Error deserializing path", e);
123         }
124     }
125 }