751c96f2b65f290429b91487bd3dbada16c71f4d
[controller.git] / opendaylight / md-sal / sal-clustering-commons / src / main / java / org / opendaylight / controller / cluster / datastore / node / utils / transformer / ReusableNormalizedNodePruner.java
1 /*
2  * Copyright (c) 2019 PANTHEON.tech, s.r.o. 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.transformer;
9
10 import com.google.common.annotations.Beta;
11 import java.io.IOException;
12 import java.math.BigInteger;
13 import org.eclipse.jdt.annotation.NonNull;
14 import org.opendaylight.yangtools.yang.common.Uint16;
15 import org.opendaylight.yangtools.yang.common.Uint32;
16 import org.opendaylight.yangtools.yang.common.Uint64;
17 import org.opendaylight.yangtools.yang.common.Uint8;
18 import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier;
19 import org.opendaylight.yangtools.yang.data.util.DataSchemaContextNode;
20 import org.opendaylight.yangtools.yang.data.util.DataSchemaContextTree;
21 import org.opendaylight.yangtools.yang.model.api.DataSchemaNode;
22 import org.opendaylight.yangtools.yang.model.api.SchemaContext;
23 import org.opendaylight.yangtools.yang.model.api.TypeDefinition;
24 import org.opendaylight.yangtools.yang.model.api.TypedDataSchemaNode;
25 import org.opendaylight.yangtools.yang.model.api.type.Uint16TypeDefinition;
26 import org.opendaylight.yangtools.yang.model.api.type.Uint32TypeDefinition;
27 import org.opendaylight.yangtools.yang.model.api.type.Uint64TypeDefinition;
28 import org.opendaylight.yangtools.yang.model.api.type.Uint8TypeDefinition;
29 import org.slf4j.Logger;
30 import org.slf4j.LoggerFactory;
31
32 /**
33  * The NormalizedNodePruner removes all nodes from the input NormalizedNode that do not have a corresponding
34  * schema element in the passed in SchemaContext.
35  *
36  * <p>
37  * Unlike {@link NormalizedNodePruner}, this class can be reused multiple times and must be initialized before each use
38  * through {@link #initializeForPath(YangInstanceIdentifier)}.
39  */
40 @Beta
41 public abstract class ReusableNormalizedNodePruner extends AbstractNormalizedNodePruner {
42     private static final class SimplePruner extends ReusableNormalizedNodePruner {
43         SimplePruner(final SchemaContext schemaContext) {
44             super(schemaContext);
45         }
46
47         SimplePruner(final DataSchemaContextTree tree) {
48             super(tree);
49         }
50
51         @Override
52         public ReusableNormalizedNodePruner duplicate() {
53             return new SimplePruner(getTree());
54         }
55     }
56
57     private static final class UintAdaptingPruner extends ReusableNormalizedNodePruner {
58         private static final Logger LOG = LoggerFactory.getLogger(UintAdaptingPruner.class);
59
60         UintAdaptingPruner(final DataSchemaContextTree tree) {
61             super(tree);
62         }
63
64         @Override
65         public ReusableNormalizedNodePruner duplicate() {
66             return new UintAdaptingPruner(getTree());
67         }
68
69         @Override
70         Object translateScalar(final DataSchemaContextNode<?> context, final Object value) throws IOException {
71             final DataSchemaNode schema = context.getDataSchemaNode();
72             if (schema instanceof TypedDataSchemaNode) {
73                 final TypeDefinition<?> type = ((TypedDataSchemaNode) schema).getType();
74                 if (value instanceof Short && type instanceof Uint8TypeDefinition) {
75                     LOG.trace("Translating legacy uint8 {}", value);
76                     return Uint8.valueOf((Short) value);
77                 } else if (value instanceof Integer && type instanceof Uint16TypeDefinition) {
78                     LOG.trace("Translating legacy uint16 {}", value);
79                     return Uint16.valueOf((Integer) value);
80                 } else if (value instanceof Long && type instanceof Uint32TypeDefinition) {
81                     LOG.trace("Translating legacy uint32 {}", value);
82                     return Uint32.valueOf((Long) value);
83                 } else if (value instanceof BigInteger && type instanceof Uint64TypeDefinition) {
84                     LOG.trace("Translating legacy uint64 {}", value);
85                     return Uint64.valueOf((BigInteger) value);
86                 }
87             }
88             return value;
89         }
90     }
91
92     ReusableNormalizedNodePruner(final SchemaContext schemaContext) {
93         super(schemaContext);
94     }
95
96     ReusableNormalizedNodePruner(final DataSchemaContextTree tree) {
97         super(tree);
98     }
99
100     /**
101      * Create a new pruner bound to a SchemaContext.
102      *
103      * @param schemaContext SchemaContext to use
104      * @return A new uninitialized pruner
105      * @throws NullPointerException if {@code schemaContext} is null
106      */
107     public static @NonNull ReusableNormalizedNodePruner forSchemaContext(final SchemaContext schemaContext) {
108         return new SimplePruner(schemaContext);
109     }
110
111     /**
112      * Create a new pruner bound to a DataSchemaContextTree. This is a more efficient alternative of
113      * {@link #forSchemaContext(SchemaContext)}.
114      *
115      * @param tree DataSchemaContextTree to use
116      * @return A new uninitialized pruner
117      * @throws NullPointerException if {@code schemaContext} is null
118      */
119     public static @NonNull ReusableNormalizedNodePruner forDataSchemaContext(final DataSchemaContextTree tree) {
120         return new SimplePruner(tree);
121     }
122
123     /**
124      * Return a new instance, which is backed but the same DataSchemaContextTree, but does not share any state and is
125      * uninitialized. This is equivalent to {@link #forDataSchemaContext(DataSchemaContextTree)} and is provided for
126      * convenience.
127      *
128      * @return A new uninitialized pruner bound to the same SchemaContext as this one.
129      */
130     public abstract @NonNull ReusableNormalizedNodePruner duplicate();
131
132     /**
133      * Initialize this pruner for processing a node at specified path.
134      *
135      * @param path Path that will be processed next
136      * @throws NullPointerException if {@code path} is null
137      */
138     public final void initializeForPath(final YangInstanceIdentifier path) {
139         initialize(path);
140     }
141
142     public final @NonNull ReusableNormalizedNodePruner withUintAdaption() {
143         return new UintAdaptingPruner(getTree());
144     }
145 }