8306cb7d4ddf8e5be134f0a2db12917a7bbea16f
[ccsdk/features.git] /
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
9  *
10  * http://www.apache.org/licenses/LICENSE-2.0
11  *
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
15  * the License.
16  * ============LICENSE_END==========================================================================
17  ******************************************************************************/
18 package org.onap.ccsdk.features.sdnr.wt.yangtools;
19
20 import java.io.IOException;
21 import javax.annotation.Nullable;
22
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;
31
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;
45
46 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.yang.types.rev130715.DateAndTime;
47 /**
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
50  */
51 public class YangToolsMapper extends ObjectMapper {
52
53         private final Logger LOG = LoggerFactory.getLogger(YangToolsMapper.class);
54         private static final long serialVersionUID = 1L;
55         private static BundleContext context;
56
57         public YangToolsMapper() {
58                 super();
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;
68         }
69
70         @Override
71         public String writeValueAsString(Object value) throws JsonProcessingException {
72                 // TODO Auto-generated method stub
73                 return super.writeValueAsString(value);
74         }
75         /**
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
80          */
81         @SuppressWarnings("unchecked")
82         public @Nullable <T extends DataObject> Builder<T> getBuilder(Class<T> clazz) {
83                 String builder = clazz.getName() + "Builder";
84                 try {
85                         Class<?> clazzBuilder = findClass(builder);
86                         return (Builder<T>) clazzBuilder.newInstance();
87                 } catch (InstantiationException | IllegalAccessException | ClassNotFoundException e) {
88                         LOG.debug("Problem ", e);
89                         return null;
90                 }
91         }
92
93         /**
94          * Callback for handling mapping failures.
95          * @return
96          */
97         public int getMappingFailures() {
98                 return 0;
99         }
100
101         /**
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
106          */
107         public @Nullable static String toCamelCaseAttributeName(final String name) {
108                 if (name == null || name.isEmpty())
109                         return null;
110
111                 final StringBuilder ret = new StringBuilder(name.length());
112                 if (!name.startsWith("_"))
113                         ret.append('_');
114                 int start = 0;
115                 for (final String word : name.split("-")) {
116                         if (!word.isEmpty()) {
117                                 if (start++ == 0) {
118                                         ret.append(Character.toLowerCase(word.charAt(0)));
119                                 } else {
120                                         ret.append(Character.toUpperCase(word.charAt(0)));
121                                 }
122                                 ret.append(word.substring(1));
123                         }
124                 }
125                 return ret.toString();
126         }
127
128         /**
129          * Adapted Builder callbacks
130          */
131         private static class YangToolsBuilderAnnotationIntrospector extends JacksonAnnotationIntrospector {
132                 private static final long serialVersionUID = 1L;
133
134                 @Override
135         public Class<?> findPOJOBuilder(AnnotatedClass ac) {
136                         try {
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()));
142
143                         } 
144                         else if(ac.getRawType().equals(DateAndTime.class)) {
145                                 builder = DateAndTimeBuilder.class.getName();
146                         }
147                         
148                         else {
149                                 if (ac.getRawType().isInterface())      {
150                                         builder = ac.getName()+"Builder";
151                                 }
152                         }
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);
159                             return innerBuilder;
160                         }
161                 } catch( ClassNotFoundException e ) {
162                     // No problem .. try next
163                 }
164            return super.findPOJOBuilder(ac);
165         }
166
167                 @Override
168                 public Value findPOJOBuilderConfig(AnnotatedClass ac) {
169                         if (ac.hasAnnotation(JsonPOJOBuilder.class)) {
170                                 return super.findPOJOBuilderConfig(ac);
171                         }
172                         return new JsonPOJOBuilder.Value("build", "set");
173                 }
174         }
175
176         private static Class<?> findClass(String name) throws ClassNotFoundException {
177                 // Try to find in other bundles
178                 if (context != null) {
179                         //OSGi environment
180                         for (Bundle b : context.getBundles()) {
181                                 try {
182                                         return b.loadClass(name);
183                                 } catch (ClassNotFoundException e) {
184                                         // No problem, this bundle doesn't have the class
185                                 }
186                         }
187                         throw new ClassNotFoundException("Can not find Class in OSGi context.");
188                 } else {
189                         return Class.forName(name);
190                 }
191             // not found in any bundle
192         }
193         public static class DateAndTimeBuilder{
194                 
195                 private final String _value;
196         
197                 public DateAndTimeBuilder(String v) {
198                         this._value= v;
199                 }
200                 
201                 public DateAndTime build() {
202                         return new DateAndTime(_value);
203                 }
204                 
205         }
206         public static class CustomDateAndTimeSerializer extends StdSerializer<DateAndTime>{
207
208                 /**
209                  * 
210                  */
211                 private static final long serialVersionUID = 1L;
212
213                 public CustomDateAndTimeSerializer() {
214                         this(null);
215                 }
216                 protected CustomDateAndTimeSerializer(Class<DateAndTime> t) {
217                         super(t);
218                 }
219
220                 @Override
221                 public void serialize(DateAndTime value, JsonGenerator gen, SerializerProvider serializers) throws IOException {
222                         gen.writeString(value.getValue());
223                 }
224                 
225         }
226 }