Fix CS warnings in sal-clustering-commons and enable enforcement
[controller.git] / opendaylight / md-sal / sal-clustering-commons / src / main / java / org / opendaylight / controller / cluster / datastore / node / utils / serialization / PathArgumentSerializer.java
1 /*
2  * Copyright (c) 2014 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.controller.cluster.datastore.node.utils.serialization;
10
11 import static org.opendaylight.controller.cluster.datastore.node.utils.serialization.PathArgumentType.getSerializablePathArgumentType;
12
13 import com.google.common.base.Preconditions;
14 import java.util.ArrayList;
15 import java.util.Arrays;
16 import java.util.Collections;
17 import java.util.HashMap;
18 import java.util.HashSet;
19 import java.util.List;
20 import java.util.Map;
21 import java.util.Map.Entry;
22 import java.util.Set;
23 import org.opendaylight.controller.cluster.datastore.node.utils.NodeIdentifierFactory;
24 import org.opendaylight.controller.cluster.datastore.node.utils.QNameFactory;
25 import org.opendaylight.controller.protobuff.messages.common.NormalizedNodeMessages;
26 import org.opendaylight.yangtools.yang.common.QName;
27 import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier;
28
29 public class PathArgumentSerializer {
30     private static final String REVISION_ARG = "?revision=";
31     private static final Map<Class<?>, PathArgumentAttributesGetter> PATH_ARGUMENT_ATTRIBUTES_GETTERS = new HashMap<>();
32
33     public static NormalizedNodeMessages.PathArgument serialize(QNameSerializationContext context,
34             YangInstanceIdentifier.PathArgument pathArgument) {
35         Preconditions.checkNotNull(context, "context should not be null");
36         Preconditions.checkNotNull(pathArgument, "pathArgument should not be null");
37
38         QName nodeType = null;
39         if (!(pathArgument instanceof YangInstanceIdentifier.AugmentationIdentifier)) {
40             nodeType = pathArgument.getNodeType();
41         }
42
43         NormalizedNodeMessages.PathArgument.Builder builder =
44             NormalizedNodeMessages.PathArgument.newBuilder();
45
46         NormalizedNodeMessages.PathArgument serializablePathArgument =
47             builder
48                 .setIntType(getSerializablePathArgumentType(pathArgument))
49                 .setNodeType(encodeQName(context, nodeType))
50                 .addAllAttribute(getPathArgumentAttributes(context, pathArgument))
51                 .build();
52
53         return serializablePathArgument;
54     }
55
56
57     public static YangInstanceIdentifier.PathArgument deSerialize(QNameDeSerializationContext context,
58             NormalizedNodeMessages.PathArgument pathArgument) {
59         Preconditions.checkNotNull(context, "context should not be null");
60         Preconditions.checkNotNull(pathArgument, "pathArgument should not be null");
61
62         return parsePathArgument(context, pathArgument);
63     }
64
65
66     private interface PathArgumentAttributesGetter {
67         Iterable<? extends NormalizedNodeMessages.PathArgumentAttribute> get(
68                 QNameSerializationContext context, YangInstanceIdentifier.PathArgument pathArgument);
69     }
70
71     static {
72         PATH_ARGUMENT_ATTRIBUTES_GETTERS.put(YangInstanceIdentifier.NodeWithValue.class, (context, pathArgument) -> {
73             YangInstanceIdentifier.NodeWithValue<?> identifier = (YangInstanceIdentifier.NodeWithValue<?>) pathArgument;
74
75             NormalizedNodeMessages.PathArgumentAttribute attribute = buildAttribute(context, null,
76                     identifier.getValue());
77
78             return Arrays.asList(attribute);
79         });
80
81         PATH_ARGUMENT_ATTRIBUTES_GETTERS.put(YangInstanceIdentifier.NodeIdentifierWithPredicates.class,
82             (context, pathArgument) -> {
83                 YangInstanceIdentifier.NodeIdentifierWithPredicates identifier =
84                         (YangInstanceIdentifier.NodeIdentifierWithPredicates) pathArgument;
85
86                 Map<QName, Object> keyValues = identifier.getKeyValues();
87                 List<NormalizedNodeMessages.PathArgumentAttribute> attributes = new ArrayList<>(keyValues.size());
88                 for (Entry<QName, Object> e : keyValues.entrySet()) {
89                     NormalizedNodeMessages.PathArgumentAttribute attribute = buildAttribute(context, e.getKey(),
90                             e.getValue());
91
92                     attributes.add(attribute);
93                 }
94
95                 return attributes;
96             });
97
98         PATH_ARGUMENT_ATTRIBUTES_GETTERS.put(YangInstanceIdentifier.AugmentationIdentifier.class,
99             (context, pathArgument) -> {
100                 YangInstanceIdentifier.AugmentationIdentifier identifier =
101                         (YangInstanceIdentifier.AugmentationIdentifier) pathArgument;
102
103                 Set<QName> possibleChildNames = identifier.getPossibleChildNames();
104                 List<NormalizedNodeMessages.PathArgumentAttribute> attributes = new ArrayList<>(
105                         possibleChildNames.size());
106                 for (QName key : possibleChildNames) {
107                     Object value = key;
108                     NormalizedNodeMessages.PathArgumentAttribute attribute = buildAttribute(context, key, value);
109
110                     attributes.add(attribute);
111                 }
112
113                 return attributes;
114             });
115
116         PATH_ARGUMENT_ATTRIBUTES_GETTERS.put(YangInstanceIdentifier.NodeIdentifier.class,
117             (context, pathArgument) -> Collections.emptyList());
118     }
119
120     private static NormalizedNodeMessages.PathArgumentAttribute buildAttribute(
121             QNameSerializationContext context, QName name, Object value) {
122         NormalizedNodeMessages.PathArgumentAttribute.Builder builder =
123             NormalizedNodeMessages.PathArgumentAttribute.newBuilder();
124
125         builder.setName(encodeQName(context, name));
126         ValueSerializer.serialize(builder, context, value);
127
128         return builder.build();
129
130     }
131
132     private static NormalizedNodeMessages.QName.Builder encodeQName(QNameSerializationContext context, QName qname) {
133         if (qname == null) {
134             return NormalizedNodeMessages.QName.getDefaultInstance().toBuilder();
135         }
136         NormalizedNodeMessages.QName.Builder qnameBuilder = NormalizedNodeMessages.QName.newBuilder();
137
138         qnameBuilder.setNamespace(context.addNamespace(qname.getNamespace()));
139
140         qnameBuilder.setRevision(context.addRevision(qname.getRevision()));
141
142         qnameBuilder.setLocalName(context.addLocalName(qname.getLocalName()));
143
144         return qnameBuilder;
145     }
146
147     private static Iterable<? extends NormalizedNodeMessages.PathArgumentAttribute> getPathArgumentAttributes(
148             QNameSerializationContext context, YangInstanceIdentifier.PathArgument pathArgument) {
149
150         return PATH_ARGUMENT_ATTRIBUTES_GETTERS.get(pathArgument.getClass()).get(context, pathArgument);
151     }
152
153
154     private static String qNameToString(QNameDeSerializationContext context, NormalizedNodeMessages.QName qname) {
155         // If this serializer is used qName cannot be null (see encodeQName)
156         // adding null check only in case someone tried to deSerialize a protocol buffer node
157         // that was not serialized using the PathArgumentSerializer
158 //        Preconditions.checkNotNull(qName, "qName should not be null");
159 //        Preconditions.checkArgument(qName.getNamespace() != -1, "qName.namespace should be valid");
160
161         String namespace = context.getNamespace(qname.getNamespace());
162         String localName = context.getLocalName(qname.getLocalName());
163         StringBuilder sb;
164         if (qname.getRevision() != -1) {
165             String revision = context.getRevision(qname.getRevision());
166             sb = new StringBuilder(namespace.length() + REVISION_ARG.length() + revision.length()
167                     + localName.length() + 2);
168             sb.append('(').append(namespace).append(REVISION_ARG).append(
169                 revision).append(')').append(localName);
170         } else {
171             sb = new StringBuilder(namespace.length() + localName.length() + 2);
172             sb.append('(').append(namespace).append(')').append(localName);
173         }
174
175         return sb.toString();
176     }
177
178     /**
179      * Parse a protocol buffer PathArgument and return an MD-SAL PathArgument.
180      *
181      * @param pathArgument protocol buffer PathArgument
182      * @return MD-SAL PathArgument
183      */
184     private static YangInstanceIdentifier.PathArgument parsePathArgument(
185             QNameDeSerializationContext context, NormalizedNodeMessages.PathArgument pathArgument) {
186
187         switch (PathArgumentType.values()[pathArgument.getIntType()]) {
188             case NODE_IDENTIFIER_WITH_VALUE : {
189                 YangInstanceIdentifier.NodeWithValue<?> nodeWithValue =
190                     new YangInstanceIdentifier.NodeWithValue<>(
191                         QNameFactory.create(qNameToString(context, pathArgument.getNodeType())),
192                         parseAttribute(context, pathArgument.getAttribute(0)));
193
194                 return nodeWithValue;
195             }
196
197             case NODE_IDENTIFIER_WITH_PREDICATES : {
198                 YangInstanceIdentifier.NodeIdentifierWithPredicates
199                     nodeIdentifierWithPredicates =
200                     new YangInstanceIdentifier.NodeIdentifierWithPredicates(
201                         QNameFactory.create(qNameToString(context, pathArgument.getNodeType())),
202                         toAttributesMap(context, pathArgument.getAttributeList()));
203
204                 return nodeIdentifierWithPredicates;
205             }
206
207             case AUGMENTATION_IDENTIFIER: {
208                 Set<QName> qnameSet = new HashSet<>();
209
210                 for (NormalizedNodeMessages.PathArgumentAttribute attribute : pathArgument.getAttributeList()) {
211                     qnameSet.add(QNameFactory.create(qNameToString(context, attribute.getName())));
212                 }
213
214                 return new YangInstanceIdentifier.AugmentationIdentifier(qnameSet);
215
216             }
217             default: {
218                 return NodeIdentifierFactory.getArgument(qNameToString(context,
219                     pathArgument.getNodeType()));
220             }
221
222         }
223     }
224
225     private static Map<QName, Object> toAttributesMap(
226             QNameDeSerializationContext context,
227             List<NormalizedNodeMessages.PathArgumentAttribute> attributesList) {
228
229         Map<QName, Object> map;
230         if (attributesList.size() == 1) {
231             NormalizedNodeMessages.PathArgumentAttribute attribute = attributesList.get(0);
232             NormalizedNodeMessages.QName name = attribute.getName();
233             Object value = parseAttribute(context, attribute);
234             map = Collections.singletonMap(QNameFactory.create(qNameToString(context, name)), value);
235         } else {
236             map = new HashMap<>();
237
238             for (NormalizedNodeMessages.PathArgumentAttribute attribute : attributesList) {
239                 NormalizedNodeMessages.QName name = attribute.getName();
240                 Object value = parseAttribute(context, attribute);
241
242                 map.put(QNameFactory.create(qNameToString(context, name)), value);
243             }
244         }
245
246         return map;
247     }
248
249     private static Object parseAttribute(QNameDeSerializationContext context,
250             NormalizedNodeMessages.PathArgumentAttribute attribute) {
251         return ValueSerializer.deSerialize(context, attribute);
252     }
253 }