Added tests for yang.model.util
[yangtools.git] / yang / yang-data-codec-gson / src / main / java / org / opendaylight / yangtools / yang / data / codec / gson / helpers / InstanceIdentifierCodecImpl.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 package org.opendaylight.yangtools.yang.data.codec.gson.helpers;
9
10 import java.net.URI;
11 import java.util.ArrayList;
12 import java.util.HashMap;
13 import java.util.List;
14 import java.util.Map;
15
16 import org.opendaylight.yangtools.yang.common.QName;
17 import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier;
18 import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier.NodeIdentifier;
19 import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier.NodeIdentifierWithPredicates;
20 import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier.NodeWithValue;
21 import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier.PathArgument;
22 import org.opendaylight.yangtools.yang.data.api.codec.InstanceIdentifierCodec;
23 import org.opendaylight.yangtools.yang.data.codec.gson.helpers.IdentityValuesDTO.IdentityValue;
24 import org.opendaylight.yangtools.yang.data.codec.gson.helpers.IdentityValuesDTO.Predicate;
25 import org.opendaylight.yangtools.yang.model.api.DataNodeContainer;
26 import org.opendaylight.yangtools.yang.model.api.DataSchemaNode;
27 import org.opendaylight.yangtools.yang.model.api.LeafListSchemaNode;
28 import org.opendaylight.yangtools.yang.model.api.ListSchemaNode;
29 import org.opendaylight.yangtools.yang.model.api.Module;
30 import org.slf4j.Logger;
31 import org.slf4j.LoggerFactory;
32
33 class InstanceIdentifierCodecImpl extends AbstractCodecImpl implements InstanceIdentifierCodec<IdentityValuesDTO> {
34     private static final Logger LOG = LoggerFactory.getLogger(InstanceIdentifierCodecImpl.class);
35
36     InstanceIdentifierCodecImpl(final SchemaContextUtils schema) {
37         super(schema);
38     }
39
40     @Override
41     public IdentityValuesDTO serialize(final YangInstanceIdentifier data) {
42         IdentityValuesDTO identityValuesDTO = new IdentityValuesDTO();
43         for (PathArgument pathArgument : data.getPathArguments()) {
44             IdentityValue identityValue = qNameToIdentityValue(pathArgument.getNodeType());
45             if (pathArgument instanceof NodeIdentifierWithPredicates && identityValue != null) {
46                 List<Predicate> predicates = keyValuesToPredicateList(((NodeIdentifierWithPredicates) pathArgument)
47                         .getKeyValues());
48                 identityValue.setPredicates(predicates);
49             } else if (pathArgument instanceof NodeWithValue && identityValue != null) {
50                 List<Predicate> predicates = new ArrayList<>();
51                 String value = String.valueOf(((NodeWithValue) pathArgument).getValue());
52                 predicates.add(new Predicate(null, value));
53                 identityValue.setPredicates(predicates);
54             }
55             identityValuesDTO.add(identityValue);
56         }
57         return identityValuesDTO;
58     }
59
60     @Override
61     public YangInstanceIdentifier deserialize(final IdentityValuesDTO data) {
62         List<PathArgument> result = new ArrayList<PathArgument>();
63         IdentityValue valueWithNamespace = data.getValuesWithNamespaces().get(0);
64         Module module = getModuleByNamespace(valueWithNamespace.getNamespace());
65         if (module == null) {
66             LOG.info("Module by namespace '{}' of first node in instance-identiefier was not found.",
67                     valueWithNamespace.getNamespace());
68             LOG.info("Instance-identifier will be translated as NULL for data - {}",
69                     String.valueOf(valueWithNamespace.getValue()));
70             return null;
71         }
72
73         DataNodeContainer parentContainer = module;
74         List<IdentityValue> identities = data.getValuesWithNamespaces();
75         for (int i = 0; i < identities.size(); i++) {
76             IdentityValue identityValue = identities.get(i);
77             URI validNamespace = resolveValidNamespace(identityValue.getNamespace());
78             DataSchemaNode node = getSchema().findInstanceDataChildByNameAndNamespace(
79                     parentContainer, identityValue.getValue(), validNamespace);
80             if (node == null) {
81                 LOG.info("'{}' node was not found in {}", identityValue, parentContainer.getChildNodes());
82                 LOG.info("Instance-identifier will be translated as NULL for data - {}",
83                         String.valueOf(identityValue.getValue()));
84                 return null;
85             }
86             QName qName = node.getQName();
87             PathArgument pathArgument = null;
88             if (identityValue.getPredicates().isEmpty()) {
89                 pathArgument = new NodeIdentifier(qName);
90             } else {
91                 if (node instanceof LeafListSchemaNode) { // predicate is value of leaf-list entry
92                     Predicate leafListPredicate = identityValue.getPredicates().get(0);
93                     if (!leafListPredicate.isLeafList()) {
94                         LOG.info("Predicate's data is not type of leaf-list. It should be in format \".='value'\"");
95                         LOG.info("Instance-identifier will be translated as NULL for data - {}",
96                                 String.valueOf(identityValue.getValue()));
97                         return null;
98                     }
99                     pathArgument = new NodeWithValue(qName, leafListPredicate.getValue());
100                 } else if (node instanceof ListSchemaNode) { // predicates are keys of list
101                     DataNodeContainer listNode = (DataNodeContainer) node;
102                     Map<QName, Object> predicatesMap = new HashMap<>();
103                     for (Predicate predicate : identityValue.getPredicates()) {
104                         validNamespace = resolveValidNamespace(predicate.getName().getNamespace());
105                         DataSchemaNode listKey = getSchema()
106                                 .findInstanceDataChildByNameAndNamespace(listNode, predicate.getName().getValue(),
107                                         validNamespace);
108                         predicatesMap.put(listKey.getQName(), predicate.getValue());
109                     }
110                     pathArgument = new NodeIdentifierWithPredicates(qName, predicatesMap);
111                 } else {
112                     LOG.info("Node {} is not List or Leaf-list.", node);
113                     LOG.info("Instance-identifier will be translated as NULL for data - {}",
114                             String.valueOf(identityValue.getValue()));
115                     return null;
116                 }
117             }
118             result.add(pathArgument);
119             if (i < identities.size() - 1) { // last element in instance-identifier can be other than
120                 // DataNodeContainer
121                 if (node instanceof DataNodeContainer) {
122                     parentContainer = (DataNodeContainer) node;
123                 } else {
124                     LOG.info("Node {} isn't instance of DataNodeContainer", node);
125                     LOG.info("Instance-identifier will be translated as NULL for data - {}",
126                             String.valueOf(identityValue.getValue()));
127                     return null;
128                 }
129             }
130         }
131
132         return result.isEmpty() ? null : YangInstanceIdentifier.create(result);
133     }
134
135     private static List<Predicate> keyValuesToPredicateList(final Map<QName, Object> keyValues) {
136         List<Predicate> result = new ArrayList<>(keyValues.size());
137         for (Map.Entry<QName, Object> e : keyValues.entrySet()) {
138             result.add(new Predicate(qNameToIdentityValue(e.getKey()), String.valueOf(e.getValue())));
139         }
140         return result;
141     }
142
143     private static IdentityValue qNameToIdentityValue(final QName qName) {
144         if (qName != null) {
145             // FIXME: the prefix here is completely arbitrary
146             return new IdentityValue(qName.getNamespace().toString(), qName.getLocalName(), qName.getPrefix());
147         }
148         return null;
149     }
150 }