1 /*******************************************************************************
2 * ============LICENSE_START========================================================================
3 * ONAP : ccsdk feature sdnr wt
4 * =================================================================================================
5 * Copyright (C) 2019 highstreet technologies GmbH Intellectual Property. All rights reserved.
6 * =================================================================================================
7 * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except
8 * in compliance with the License. You may obtain a copy of the License at
10 * http://www.apache.org/licenses/LICENSE-2.0
12 * Unless required by applicable law or agreed to in writing, software distributed under the License
13 * is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
14 * or implied. See the License for the specific language governing permissions and limitations under
16 * ============LICENSE_END==========================================================================
17 ******************************************************************************/
18 package org.onap.ccsdk.features.sdnr.wt.dataprovider.yangtools;
20 import java.io.IOException;
21 import javax.annotation.Nullable;
23 import org.opendaylight.yang.gen.v1.urn.opendaylight.netconf.node.topology.rev150114.netconf.node.credentials.Credentials;
24 import org.opendaylight.yangtools.concepts.Builder;
25 import org.opendaylight.yangtools.yang.binding.DataObject;
26 import org.osgi.framework.Bundle;
27 import org.osgi.framework.BundleContext;
28 import org.osgi.framework.FrameworkUtil;
29 import org.slf4j.Logger;
30 import org.slf4j.LoggerFactory;
32 import com.fasterxml.jackson.annotation.JsonInclude.Include;
33 import com.fasterxml.jackson.core.JsonGenerator;
34 import com.fasterxml.jackson.core.JsonProcessingException;
35 import com.fasterxml.jackson.databind.DeserializationFeature;
36 import com.fasterxml.jackson.databind.ObjectMapper;
37 import com.fasterxml.jackson.databind.PropertyNamingStrategy;
38 import com.fasterxml.jackson.databind.SerializerProvider;
39 import com.fasterxml.jackson.databind.annotation.JsonPOJOBuilder;
40 import com.fasterxml.jackson.databind.annotation.JsonPOJOBuilder.Value;
41 import com.fasterxml.jackson.databind.introspect.AnnotatedClass;
42 import com.fasterxml.jackson.databind.introspect.JacksonAnnotationIntrospector;
43 import com.fasterxml.jackson.databind.module.SimpleModule;
44 import com.fasterxml.jackson.databind.ser.std.StdSerializer;
46 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.yang.types.rev130715.DateAndTime;
48 * YangToolsMapper is a specific Jackson mapper configuration for opendaylight yangtools serialization or deserialization of DataObject to/from JSON
49 * TODO ChoiceIn and Credentials deserialization only for LoginPasswordBuilder
51 public class YangToolsMapper extends ObjectMapper {
53 private final Logger LOG = LoggerFactory.getLogger(YangToolsMapper.class);
54 private static final long serialVersionUID = 1L;
55 private static BundleContext context;
57 public YangToolsMapper() {
59 configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false);
60 setPropertyNamingStrategy(PropertyNamingStrategy.KEBAB_CASE);
61 setSerializationInclusion(Include.NON_NULL);
62 setAnnotationIntrospector(new YangToolsBuilderAnnotationIntrospector());
63 SimpleModule dateAndTimeSerializerModule = new SimpleModule();
64 dateAndTimeSerializerModule.addSerializer(DateAndTime.class,new CustomDateAndTimeSerializer());
65 registerModule(dateAndTimeSerializerModule );
66 Bundle bundle = FrameworkUtil.getBundle(YangToolsMapper.class);
67 context = bundle != null ? bundle.getBundleContext() : null;
71 public String writeValueAsString(Object value) throws JsonProcessingException {
72 // TODO Auto-generated method stub
73 return super.writeValueAsString(value);
76 * Get Builder object for yang tools interface.
77 * @param <T> yang-tools base datatype
78 * @param clazz class with interface.
79 * @return builder for interface or null if not existing
81 @SuppressWarnings("unchecked")
82 public @Nullable <T extends DataObject> Builder<T> getBuilder(Class<T> clazz) {
83 String builder = clazz.getName() + "Builder";
85 Class<?> clazzBuilder = findClass(builder);
86 return (Builder<T>) clazzBuilder.newInstance();
87 } catch (InstantiationException | IllegalAccessException | ClassNotFoundException e) {
88 LOG.debug("Problem ", e);
94 * Callback for handling mapping failures.
97 public int getMappingFailures() {
102 * Provide mapping of string to attribute names, generated by yang-tools.
103 * "netconf-id" converted to "_netconfId"
104 * @param name with attribute name, not null or empty
105 * @return converted string or null if name was empty or null
107 public @Nullable static String toCamelCaseAttributeName(final String name) {
108 if (name == null || name.isEmpty())
111 final StringBuilder ret = new StringBuilder(name.length());
112 if (!name.startsWith("_"))
115 for (final String word : name.split("-")) {
116 if (!word.isEmpty()) {
118 ret.append(Character.toLowerCase(word.charAt(0)));
120 ret.append(Character.toUpperCase(word.charAt(0)));
122 ret.append(word.substring(1));
125 return ret.toString();
129 * Adapted Builder callbacks
131 private static class YangToolsBuilderAnnotationIntrospector extends JacksonAnnotationIntrospector {
132 private static final long serialVersionUID = 1L;
135 public Class<?> findPOJOBuilder(AnnotatedClass ac) {
137 String builder = null;
138 if (ac.getRawType().equals(Credentials.class)) {
139 builder = "org.opendaylight.yang.gen.v1.urn.opendaylight.netconf.node.topology.rev150114.netconf.node.credentials.credentials.LoginPasswordBuilder";
140 //System.out.println(DataContainer.class.isAssignableFrom(ac.getRawType()));
141 //System.out.println(ChoiceIn.class.isAssignableFrom(ac.getRawType()));
144 else if(ac.getRawType().equals(DateAndTime.class)) {
145 builder = DateAndTimeBuilder.class.getName();
149 if (ac.getRawType().isInterface()) {
150 builder = ac.getName()+"Builder";
153 if (builder != null) {
154 //System.out.println("XX1: "+ac.getRawType());
155 //System.out.println("XX2: "+builder);
156 //Class<?> innerBuilder = Class.forName(builder);
157 Class<?> innerBuilder = findClass(builder);
158 //System.out.println("Builder found: "+ innerBuilder);
161 } catch( ClassNotFoundException e ) {
162 // No problem .. try next
164 return super.findPOJOBuilder(ac);
168 public Value findPOJOBuilderConfig(AnnotatedClass ac) {
169 if (ac.hasAnnotation(JsonPOJOBuilder.class)) {
170 return super.findPOJOBuilderConfig(ac);
172 return new JsonPOJOBuilder.Value("build", "set");
176 private static Class<?> findClass(String name) throws ClassNotFoundException {
177 // Try to find in other bundles
178 if (context != null) {
180 for (Bundle b : context.getBundles()) {
182 return b.loadClass(name);
183 } catch (ClassNotFoundException e) {
184 // No problem, this bundle doesn't have the class
187 throw new ClassNotFoundException("Can not find Class in OSGi context.");
189 return Class.forName(name);
191 // not found in any bundle
193 public static class DateAndTimeBuilder{
195 private final String _value;
197 public DateAndTimeBuilder(String v) {
201 public DateAndTime build() {
202 return new DateAndTime(_value);
206 public static class CustomDateAndTimeSerializer extends StdSerializer<DateAndTime>{
211 private static final long serialVersionUID = 1L;
213 public CustomDateAndTimeSerializer() {
216 protected CustomDateAndTimeSerializer(Class<DateAndTime> t) {
221 public void serialize(DateAndTime value, JsonGenerator gen, SerializerProvider serializers) throws IOException {
222 gen.writeString(value.getValue());