Honeynode test tool
[transportpce.git] / tests / honeynode / honeynode-common / src / main / java / io / fd / honeycomb / transportpce / binding / converter / AbstractDataObjectConverter.java
1 /*
2  * Copyright © 2016 AT&T 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 io.fd.honeycomb.transportpce.binding.converter;
9
10 import com.google.common.base.Preconditions;
11
12 import io.fd.honeycomb.transportpce.binding.converter.api.DataObjectConverter;
13
14 import java.util.Map;
15 import java.util.Map.Entry;
16 import java.util.Optional;
17 import javax.annotation.Nonnull;
18 import org.opendaylight.mdsal.binding.dom.codec.api.BindingNormalizedNodeSerializer;
19 import org.opendaylight.yangtools.yang.binding.DataContainer;
20 import org.opendaylight.yangtools.yang.binding.DataObject;
21 import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
22 import org.opendaylight.yangtools.yang.binding.Notification;
23 import org.opendaylight.yangtools.yang.common.QName;
24 import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier;
25 import org.opendaylight.yangtools.yang.data.api.schema.ContainerNode;
26 import org.opendaylight.yangtools.yang.data.api.schema.NormalizedNode;
27 import org.opendaylight.yangtools.yang.data.api.schema.NormalizedNodes;
28 import org.opendaylight.yangtools.yang.model.api.SchemaContext;
29 import org.opendaylight.yangtools.yang.model.api.SchemaPath;
30 import org.slf4j.Logger;
31 import org.slf4j.LoggerFactory;
32
33 /**
34  * Converts XML and {@link DataObject} vice versa.
35  *
36  */
37 public abstract class AbstractDataObjectConverter implements DataObjectConverter {
38
39     private static final Logger LOG = LoggerFactory.getLogger(AbstractDataObjectConverter.class);
40
41     private final SchemaContext schemaContext;
42     private final BindingNormalizedNodeSerializer codecRegistry;
43
44     /**
45      * This is the default constructor, which should be used.
46      *
47      * @param schemaContext schema context for converter
48      * @param codecRegistry codec registry used for converting
49      *
50      */
51     protected AbstractDataObjectConverter(SchemaContext schemaContext, BindingNormalizedNodeSerializer codecRegistry) {
52         this.schemaContext = schemaContext;
53         this.codecRegistry = codecRegistry;
54     }
55
56     public SchemaContext getSchemaContext() {
57         return schemaContext;
58     }
59
60     public BindingNormalizedNodeSerializer getCodecRegistry() {
61         return codecRegistry;
62     }
63
64     /**
65      * Transforms the given input {@link NormalizedNode} into the given
66      * {@link DataObject}.
67      *
68      * @param normalizedNode normalized node you want to convert
69      * @param rootNode {@link QName} of converted normalized node root
70      *
71      * <p>
72      * The input object should be {@link ContainerNode}
73      * </p>
74      */
75     @Override
76     @SuppressWarnings("unchecked")
77     public <T extends DataObject> Optional<T> getDataObject(
78             @Nonnull NormalizedNode<?, ?> normalizedNode,
79             @Nonnull QName rootNode) {
80         Preconditions.checkNotNull(normalizedNode);
81         if (normalizedNode instanceof ContainerNode) {
82             YangInstanceIdentifier.PathArgument directChildIdentifier =
83                     YangInstanceIdentifier.of(rootNode).getLastPathArgument();
84             Optional<NormalizedNode<?, ?>> directChild =
85                     NormalizedNodes.getDirectChild(normalizedNode, directChildIdentifier).toJavaUtil();
86             if (!directChild.isPresent()) {
87                 throw new IllegalStateException(String.format("Could not get the direct child of %s", rootNode));
88             }
89             normalizedNode = directChild.get();
90         }
91         YangInstanceIdentifier rootNodeYangInstanceIdentifier = YangInstanceIdentifier.of(rootNode);
92
93         Map.Entry<?, ?> bindingNodeEntry =
94                 codecRegistry.fromNormalizedNode(rootNodeYangInstanceIdentifier, normalizedNode);
95         if (bindingNodeEntry == null) {
96             return Optional.empty();
97         }
98         return Optional.ofNullable((T) bindingNodeEntry.getValue());
99     }
100
101     @Override
102     @SuppressWarnings("unchecked")
103     public <T extends DataObject> Optional<T> getDataObjectFromRpc(
104             @Nonnull NormalizedNode<?, ?> normalizedNode,
105             @Nonnull SchemaPath rpcSchemaPath) {
106
107         if (! (normalizedNode instanceof ContainerNode)) {
108             LOG.error("converting normalized node is not ContainerNode. It's actual type is {}",
109                     normalizedNode.getClass().getSimpleName());
110             return Optional.empty();
111         }
112         T rpcDataObject = (T) codecRegistry.fromNormalizedNodeRpcData(rpcSchemaPath, (ContainerNode) normalizedNode);
113         return Optional.ofNullable(rpcDataObject);
114     }
115
116     @Override
117     public <T extends DataObject> Optional<NormalizedNode<?, ?>> toNormalizedNodes(@Nonnull T object,
118             Class<T> dataObjectClass) {
119         Entry<YangInstanceIdentifier, NormalizedNode<?, ?>> normalizedNode =
120                 codecRegistry.toNormalizedNode(InstanceIdentifier.create(dataObjectClass), object);
121         return Optional.ofNullable(normalizedNode.getValue());
122     }
123
124     @Override
125     public <T extends DataObject> ConvertType<T> dataContainer() {
126         return (object, objectClass) -> {
127             NormalizedNode<?, ?> value =
128                     getCodecRegistry().toNormalizedNode(InstanceIdentifier.create(objectClass), object).getValue();
129             return Optional.ofNullable(value);
130         };
131     }
132
133     @Override
134     public <T extends DataContainer> ConvertType<T> rpcData() {
135         return (object, objectClass) -> {
136             ContainerNode normalizedNodeRpcData = getCodecRegistry().toNormalizedNodeRpcData(object);
137             return Optional.ofNullable(normalizedNodeRpcData);
138         };
139     }
140
141     @Override
142     public <T extends Notification> ConvertType<T> notification() {
143         return (object, objectClass) -> {
144             ContainerNode normalizedNodeNotification = getCodecRegistry().toNormalizedNodeNotification(object);
145             return Optional.ofNullable(normalizedNodeNotification);
146         };
147     }
148 }