2 * ============LICENSE_START=======================================================
3 * ONAP : ccsdk features
4 * ================================================================================
5 * Copyright (C) 2019 highstreet technologies GmbH Intellectual Property.
7 * ================================================================================
8 * Licensed under the Apache License, Version 2.0 (the "License");
9 * you may not use this file except in compliance with the License.
10 * You may obtain a copy of the License at
12 * http://www.apache.org/licenses/LICENSE-2.0
14 * Unless required by applicable law or agreed to in writing, software
15 * distributed under the License is distributed on an "AS IS" BASIS,
16 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
17 * See the License for the specific language governing permissions and
18 * limitations under the License.
19 * ============LICENSE_END=========================================================
22 package org.onap.ccsdk.features.sdnr.wt.dataprovider.yangtools;
24 import java.io.IOException;
25 import javax.annotation.Nullable;
27 import org.opendaylight.yang.gen.v1.urn.opendaylight.netconf.node.topology.rev150114.netconf.node.credentials.Credentials;
28 import org.opendaylight.yangtools.concepts.Builder;
29 import org.opendaylight.yangtools.yang.binding.DataObject;
30 import org.osgi.framework.Bundle;
31 import org.osgi.framework.BundleContext;
32 import org.osgi.framework.FrameworkUtil;
33 import org.slf4j.Logger;
34 import org.slf4j.LoggerFactory;
36 import com.fasterxml.jackson.annotation.JsonInclude.Include;
37 import com.fasterxml.jackson.core.JsonGenerator;
38 import com.fasterxml.jackson.core.JsonProcessingException;
39 import com.fasterxml.jackson.databind.DeserializationFeature;
40 import com.fasterxml.jackson.databind.ObjectMapper;
41 import com.fasterxml.jackson.databind.PropertyNamingStrategy;
42 import com.fasterxml.jackson.databind.SerializerProvider;
43 import com.fasterxml.jackson.databind.annotation.JsonPOJOBuilder;
44 import com.fasterxml.jackson.databind.annotation.JsonPOJOBuilder.Value;
45 import com.fasterxml.jackson.databind.introspect.AnnotatedClass;
46 import com.fasterxml.jackson.databind.introspect.JacksonAnnotationIntrospector;
47 import com.fasterxml.jackson.databind.module.SimpleModule;
48 import com.fasterxml.jackson.databind.ser.std.StdSerializer;
50 import org.eclipse.jdt.annotation.NonNull;
51 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.yang.types.rev130715.DateAndTime;
54 * YangToolsMapper is a specific Jackson mapper configuration for opendaylight yangtools serialization or
55 * deserialization of DataObject to/from JSON TODO ChoiceIn and Credentials deserialization only for
56 * LoginPasswordBuilder
58 public class YangToolsMapper2<T extends DataObject> extends ObjectMapper {
60 private final Logger LOG = LoggerFactory.getLogger(YangToolsMapper2.class);
61 private static final long serialVersionUID = 1L;
62 private static String ENTITY = "Entity";
63 private static String BUILDER = "Builder";
65 private @Nullable Class<T> clazz;
66 private @Nullable Class<? extends Builder<? extends T>> builderClazz;
68 private BundleContext context;
70 public <X extends T, B extends Builder<X>> YangToolsMapper2(Class<T> clazz, Class<B> builderClazz)
71 throws ClassNotFoundException {
73 configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false);
74 setPropertyNamingStrategy(PropertyNamingStrategy.KEBAB_CASE);
75 setSerializationInclusion(Include.NON_NULL);
76 setAnnotationIntrospector(new YangToolsBuilderAnnotationIntrospector());
77 SimpleModule dateAndTimeSerializerModule = new SimpleModule();
78 dateAndTimeSerializerModule.addSerializer(DateAndTime.class, new CustomDateAndTimeSerializer());
79 registerModule(dateAndTimeSerializerModule);
80 Bundle bundle = FrameworkUtil.getBundle(YangToolsMapper2.class);
83 this.builderClazz = builderClazz != null ? builderClazz : getBuilderClass(getBuilderClassName(clazz));
84 context = bundle != null ? bundle.getBundleContext() : null;
87 public YangToolsMapper2() throws ClassNotFoundException {
93 public String writeValueAsString(Object value) throws JsonProcessingException {
94 return super.writeValueAsString(value);
98 * Get Builder object for yang tools interface.
100 * @param <T> yang-tools base datatype
101 * @param clazz class with interface.
102 * @return builder for interface or null if not existing
104 @SuppressWarnings("unchecked")
105 public @Nullable <T extends DataObject> Builder<T> getBuilder(Class<T> clazz) {
107 //Class<?> clazzBuilder = getBuilderClass(getBuilderClassName(clazz));
108 return (Builder<T>) builderClazz.newInstance();
109 } catch (InstantiationException | IllegalAccessException e) {
110 LOG.debug("Problem ", e);
116 * Callback for handling mapping failures.
120 public int getMappingFailures() {
125 * Provide mapping of string to attribute names, generated by yang-tools. "netconf-id" converted to "_netconfId"
127 * @param name with attribute name, not null or empty
128 * @return converted string or null if name was empty or null
130 public @Nullable static String toCamelCaseAttributeName(final String name) {
131 if (name == null || name.isEmpty())
134 final StringBuilder ret = new StringBuilder(name.length());
135 if (!name.startsWith("_"))
138 for (final String word : name.split("-")) {
139 if (!word.isEmpty()) {
141 ret.append(Character.toLowerCase(word.charAt(0)));
143 ret.append(Character.toUpperCase(word.charAt(0)));
145 ret.append(word.substring(1));
148 return ret.toString();
152 * Verify if builder is available
154 * @throws ClassNotFoundException
156 public Class<?> assertBuilderClass(Class<?> clazz) throws ClassNotFoundException {
157 return getBuilderClass(getBuilderClassName(clazz));
160 // --- Private functions
163 * Create name of builder class
167 * @return builders class name
168 * @throws ClassNotFoundException
170 private static String getBuilderClassName(Class<?> clazz) {
171 return clazz.getName() + BUILDER;
172 // String clazzName = clazz.getName();
173 // if (clazzName.endsWith(ENTITY)) {
174 // return clazzName.replace(ENTITY, BUILDER);
176 // return clazzName + BUILDER;
181 * Search builder in context
185 * @throws ClassNotFoundException
187 @SuppressWarnings("unchecked")
188 private <X extends T, B extends Builder<X>> Class<B> getBuilderClass(String name) throws ClassNotFoundException {
189 // Try to find in other bundles
190 if (context != null) {
192 for (Bundle b : context.getBundles()) {
194 return (Class<B>) b.loadClass(name);
195 } catch (ClassNotFoundException e) {
196 // No problem, this bundle doesn't have the class
199 throw new ClassNotFoundException("Can not find Class in OSGi context.");
201 return (Class<B>) Class.forName(name);
203 // not found in any bundle
209 * Adapted Builder callbacks
211 private class YangToolsBuilderAnnotationIntrospector extends JacksonAnnotationIntrospector {
212 private static final long serialVersionUID = 1L;
215 public Class<?> findPOJOBuilder(AnnotatedClass ac) {
217 if (ac.getRawType().equals(Credentials.class)) {
218 return org.opendaylight.yang.gen.v1.urn.opendaylight.netconf.node.topology.rev150114.netconf.node.credentials.credentials.LoginPasswordBuilder.class;
220 } else if (ac.getRawType().equals(DateAndTime.class)) {
221 return DateAndTimeBuilder.class;
223 } else if (ac.getRawType().equals(clazz)) {
227 if (ac.getRawType().isInterface()) {
228 String builder = getBuilderClassName(ac.getRawType());
230 Class<?> innerBuilder = getBuilderClass(builder);
232 } catch (ClassNotFoundException e) {
233 // No problem .. try next
236 return super.findPOJOBuilder(ac);
240 public Value findPOJOBuilderConfig(AnnotatedClass ac) {
241 if (ac.hasAnnotation(JsonPOJOBuilder.class)) {
242 return super.findPOJOBuilderConfig(ac);
244 return new JsonPOJOBuilder.Value("build", "set");
248 public static class DateAndTimeBuilder {
250 private final String _value;
252 public DateAndTimeBuilder(String v) {
256 public DateAndTime build() {
257 return new DateAndTime(_value);
261 public static class CustomDateAndTimeSerializer extends StdSerializer<@NonNull DateAndTime> {
263 private static final long serialVersionUID = 1L;
265 public CustomDateAndTimeSerializer() {
269 protected CustomDateAndTimeSerializer(Class<DateAndTime> t) {
274 public void serialize(DateAndTime value, JsonGenerator gen, SerializerProvider serializers) throws IOException {
275 gen.writeString(value.getValue());