diff options
Diffstat (limited to 'sdnr/wt/common-yang/utils')
16 files changed, 1290 insertions, 0 deletions
diff --git a/sdnr/wt/common-yang/utils/pom.xml b/sdnr/wt/common-yang/utils/pom.xml new file mode 100644 index 000000000..ef3c22b4c --- /dev/null +++ b/sdnr/wt/common-yang/utils/pom.xml @@ -0,0 +1,74 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- + ~ ============LICENSE_START======================================================= + ~ ONAP : ccsdk features + ~ ================================================================================ + ~ Copyright (C) 2019 highstreet technologies GmbH Intellectual Property. + ~ All rights reserved. + ~ ================================================================================ + ~ Update Copyright (C) 2020 AT&T Intellectual Property. All rights reserved. + ~ ================================================================================ + ~ Licensed under the Apache License, Version 2.0 (the "License"); + ~ you may not use this file except in compliance with the License. + ~ You may obtain a copy of the License at + ~ + ~ http://www.apache.org/licenses/LICENSE-2.0 + ~ + ~ Unless required by applicable law or agreed to in writing, software + ~ distributed under the License is distributed on an "AS IS" BASIS, + ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + ~ See the License for the specific language governing permissions and + ~ limitations under the License. + ~ ============LICENSE_END======================================================= + ~ + --> + +<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> + <modelVersion>4.0.0</modelVersion> + + <parent> + <groupId>org.onap.ccsdk.parent</groupId> + <artifactId>binding-parent</artifactId> + <version>2.2.0-SNAPSHOT</version> + <relativePath/> + </parent> + + <groupId>org.onap.ccsdk.features.sdnr.wt</groupId> + <artifactId>sdnr-wt-yang-utils</artifactId> + <version>1.2.0-SNAPSHOT</version> + <packaging>bundle</packaging> + + <name>ccsdk-features :: ${project.artifactId}</name> + <licenses> + <license> + <name>Apache License, Version 2.0</name> + <url>http://www.apache.org/licenses/LICENSE-2.0</url> + </license> + </licenses> + + <dependencies> + <dependency> + <groupId>org.osgi</groupId> + <artifactId>org.osgi.core</artifactId> + <scope>provided</scope> + </dependency> + <dependency> + <groupId>com.google.code.findbugs</groupId> + <artifactId>annotations</artifactId> + </dependency> + <dependency> + <groupId>com.fasterxml.jackson.core</groupId> + <artifactId>jackson-annotations</artifactId> + </dependency> + <dependency> + <groupId>com.fasterxml.jackson.core</groupId> + <artifactId>jackson-databind</artifactId> + </dependency> + <dependency> + <groupId>org.opendaylight.mdsal.binding.model.ietf</groupId> + <artifactId>rfc6991-ietf-yang-types</artifactId> + <scope>provided</scope> + </dependency> + </dependencies> + +</project> diff --git a/sdnr/wt/common-yang/utils/src/main/java/org/onap/ccsdk/features/sdnr/wt/yang/mapper/YangToolsMapper.java b/sdnr/wt/common-yang/utils/src/main/java/org/onap/ccsdk/features/sdnr/wt/yang/mapper/YangToolsMapper.java new file mode 100644 index 000000000..f406ea97d --- /dev/null +++ b/sdnr/wt/common-yang/utils/src/main/java/org/onap/ccsdk/features/sdnr/wt/yang/mapper/YangToolsMapper.java @@ -0,0 +1,73 @@ +/* + * ============LICENSE_START======================================================= + * ONAP : ccsdk features + * ================================================================================ + * Copyright (C) 2019 highstreet technologies GmbH Intellectual Property. + * All rights reserved. + * ================================================================================ + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ============LICENSE_END========================================================= + * + */ +package org.onap.ccsdk.features.sdnr.wt.yang.mapper; + +import com.fasterxml.jackson.annotation.JsonInclude.Include; +import com.fasterxml.jackson.databind.DeserializationFeature; +import com.fasterxml.jackson.databind.KeyDeserializer; +import com.fasterxml.jackson.databind.MapperFeature; +import com.fasterxml.jackson.databind.ObjectMapper; +import com.fasterxml.jackson.databind.PropertyNamingStrategy; +import org.onap.ccsdk.features.sdnr.wt.yang.mapper.mapperextensions.YangToolsBuilderAnnotationIntrospector; +import org.onap.ccsdk.features.sdnr.wt.yang.mapper.mapperextensions.YangToolsModule; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +/** + * YangToolsMapper is a specific Jackson mapper configuration for opendaylight yangtools serialization or + * deserialization of DataObject to/from JSON TODO ChoiceIn and Credentials deserialization only for + * LoginPasswordBuilder + */ +public class YangToolsMapper extends ObjectMapper { + + @SuppressWarnings("unused") + private final Logger LOG = LoggerFactory.getLogger(YangToolsMapper.class); + private final YangToolsBuilderAnnotationIntrospector annotationIntrospector; + private final YangToolsModule module; + private static final long serialVersionUID = 1L; + + public YangToolsMapper() { + this(new YangToolsBuilderAnnotationIntrospector()); + } + + protected YangToolsMapper(YangToolsBuilderAnnotationIntrospector yangToolsBuilderAnnotationIntrospector) { + super(); + + this.annotationIntrospector = yangToolsBuilderAnnotationIntrospector; + this.module = new YangToolsModule(); + configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false); + setPropertyNamingStrategy(PropertyNamingStrategy.KEBAB_CASE); + setSerializationInclusion(Include.NON_NULL); + enable(MapperFeature.USE_GETTERS_AS_SETTERS); + setAnnotationIntrospector(yangToolsBuilderAnnotationIntrospector); + registerModule(this.module); + + } + public void addDeserializer(Class<?> clsToDeserialize, String builderClassName) { + this.annotationIntrospector.addDeserializer(clsToDeserialize, builderClassName); + } + + public void addKeyDeserializer(Class<?> type, KeyDeserializer deserializer) { + this.module.addKeyDeserializer(type, deserializer); + } + +} diff --git a/sdnr/wt/common-yang/utils/src/main/java/org/onap/ccsdk/features/sdnr/wt/yang/mapper/YangToolsMapper2.java b/sdnr/wt/common-yang/utils/src/main/java/org/onap/ccsdk/features/sdnr/wt/yang/mapper/YangToolsMapper2.java new file mode 100644 index 000000000..5c5aeb6de --- /dev/null +++ b/sdnr/wt/common-yang/utils/src/main/java/org/onap/ccsdk/features/sdnr/wt/yang/mapper/YangToolsMapper2.java @@ -0,0 +1,97 @@ +/* + * ============LICENSE_START======================================================= + * ONAP : ccsdk features + * ================================================================================ + * Copyright (C) 2019 highstreet technologies GmbH Intellectual Property. + * All rights reserved. + * ================================================================================ + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ============LICENSE_END========================================================= + * + */ +package org.onap.ccsdk.features.sdnr.wt.yang.mapper; + +import java.lang.reflect.InvocationTargetException; +import javax.annotation.Nullable; +import org.eclipse.jdt.annotation.NonNull; +import org.onap.ccsdk.features.sdnr.wt.yang.mapper.mapperextensions.YangToolsBuilderAnnotationIntrospector; +import org.opendaylight.yangtools.concepts.Builder; +import org.opendaylight.yangtools.yang.binding.DataObject; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +/** + * YangToolsMapper is a specific Jackson mapper configuration for opendaylight yangtools serialization or + * deserialization of DataObject to/from JSON TODO ChoiceIn and Credentials deserialization only for + * LoginPasswordBuilder + */ +public class YangToolsMapper2<T extends DataObject> extends YangToolsMapper { + + private static final Logger LOG = LoggerFactory.getLogger(YangToolsMapper2.class); + private static final long serialVersionUID = 1L; + + private @Nullable final Class<? extends Builder<? extends T>> builderClazz; + + /** + * Generic Object creation of yangtools java class builder pattern. + * + * @param <X> Class of DataObject + * @param <B> Builder for the class. + * @param clazz specifies class to be mapped + * @param builderClazz is the builder for class with name pattern "clazzBuilder".<br> + * If null the clazz is expected to support normal jackson build pattern. + * @throws ClassNotFoundException if builderClazz not available in bundle + */ + public <X extends T, B extends Builder<X>> YangToolsMapper2(@NonNull Class<T> clazz, + @Nullable Class<B> builderClazz) throws ClassNotFoundException { + super(new YangToolsBuilderAnnotationIntrospector(clazz, builderClazz)); + + this.builderClazz = + builderClazz != null ? builderClazz : getBuilderClass(YangToolsMapperHelper.getBuilderClassName(clazz)); + } + + /** + * Get Builder object for yang tools interface. + * + * @param <T> yang-tools base datatype + * @param clazz class with interface. + * @return builder for interface or null if not existing + */ + public @Nullable Builder<? extends T> getBuilder(Class<T> clazz) { + try { + if (builderClazz != null) + return builderClazz.getDeclaredConstructor().newInstance(); + else + return null; + } catch (InstantiationException | IllegalAccessException | IllegalArgumentException | InvocationTargetException + | NoSuchMethodException | SecurityException e) { + LOG.warn("Problem intantiating Builder", e); + return null; + } + } + + // --- Private functions + + /** + * Search builder in context + * + * @param name + * @return + * @throws ClassNotFoundException + */ + @SuppressWarnings("unchecked") + private <X extends T, B extends Builder<X>> Class<B> getBuilderClass(String name) throws ClassNotFoundException { + return (Class<B>) YangToolsMapperHelper.getBuilderClass(name); + } + +} diff --git a/sdnr/wt/common-yang/utils/src/main/java/org/onap/ccsdk/features/sdnr/wt/yang/mapper/YangToolsMapperHelper.java b/sdnr/wt/common-yang/utils/src/main/java/org/onap/ccsdk/features/sdnr/wt/yang/mapper/YangToolsMapperHelper.java new file mode 100644 index 000000000..ac6b1b5c5 --- /dev/null +++ b/sdnr/wt/common-yang/utils/src/main/java/org/onap/ccsdk/features/sdnr/wt/yang/mapper/YangToolsMapperHelper.java @@ -0,0 +1,270 @@ +/* + * ============LICENSE_START======================================================= + * ONAP : ccsdk features + * ================================================================================ + * Copyright (C) 2020 highstreet technologies GmbH Intellectual Property. + * All rights reserved. + * ================================================================================ + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ============LICENSE_END========================================================= + * + */ +package org.onap.ccsdk.features.sdnr.wt.yang.mapper; + +import com.fasterxml.jackson.databind.DeserializationContext; +import java.lang.reflect.Constructor; +import java.lang.reflect.InvocationTargetException; +import java.lang.reflect.Method; +import java.time.Instant; +import java.time.ZoneOffset; +import java.time.ZonedDateTime; +import java.time.format.DateTimeFormatter; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.List; +import java.util.Optional; +import java.util.concurrent.ConcurrentHashMap; +import javax.annotation.Nullable; +import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.yang.types.rev130715.DateAndTime; +import org.opendaylight.yangtools.concepts.Builder; +import org.opendaylight.yangtools.yang.binding.EventInstantAware; +import org.opendaylight.yangtools.yang.binding.Notification; +import org.osgi.framework.Bundle; +import org.osgi.framework.BundleContext; +import org.osgi.framework.FrameworkUtil; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +public class YangToolsMapperHelper { + + private static final Logger LOG = LoggerFactory.getLogger(YangToolsMapperHelper.class); + private static final String TYPEOBJECT_INSTANCE_METHOD = "getDefaultInstance"; + private static final String BUILDER = "Builder"; + private static final DateTimeFormatter formatterOutput = + DateTimeFormatter.ofPattern("yyyy-MM-dd'T'HH:mm:ss.S'Z'").withZone(ZoneOffset.UTC); + + private static BundleContext context = getBundleContext(); + private static ConcurrentHashMap<String, Class<?>> cache = new ConcurrentHashMap<>(); + + private YangToolsMapperHelper() { + //Make unaccessible + } + + public static Class<?> findClass(String name) throws ClassNotFoundException { + + //Try first in cache + Class<?> res = cache.get(name); + if (res != null) { + return res; + } + //Try first in actual bundle + try { + return loadClass(null, name); + } catch (ClassNotFoundException e) { + // No problem, this bundle doesn't have the class + } + // Try to find in other bundles + if (context != null) { + //OSGi environment + for (Bundle b : context.getBundles()) { + try { + return loadClass(b, name); + } catch (ClassNotFoundException e) { + // No problem, this bundle doesn't have the class + } + } + } + // really not found in any bundle + throw new ClassNotFoundException("Can not find class '"+name+"'"); + } + + private static Class<?> loadClass(Bundle b, String name) throws ClassNotFoundException { + Class<?> res = b == null ? Class.forName(name) : b.loadClass(name); + cache.put(name, res); + return res; + } + + /** + * Verify if builder is available + * + * @throws ClassNotFoundException + **/ + public static Class<?> assertBuilderClass(Class<?> clazz) throws ClassNotFoundException { + return getBuilderClass(getBuilderClassName(clazz)); + } + + public static Class<?> getBuilderClass(String name) throws ClassNotFoundException { + return findClass(name); + } + + public static Class<?> getBuilderClass(Class<?> clazz) throws ClassNotFoundException { + return findClass(getBuilderClassName(clazz)); + } + + /** + * Create name of builder class + * + * @param <T> + * @param clazz + * @return builders class name + * @throws ClassNotFoundException + */ + public static String getBuilderClassName(Class<?> clazz) { + return clazz.getName() + BUILDER; + } + + @SuppressWarnings("unchecked") + public static <B extends Builder<?>> Class<B> findBuilderClass(DeserializationContext ctxt, Class<?> clazz) throws ClassNotFoundException { + return (Class<B>) findClass(getBuilderClassName(clazz)); + } + + public static <B extends Builder<?>> Optional<Class<B>> findBuilderClassOptional(DeserializationContext ctxt, Class<?> clazz) { + try { + return Optional.of(findBuilderClass(ctxt, clazz)); + } catch (ClassNotFoundException e) { + return Optional.empty(); + } + } + + public static boolean hasClassDeclaredMethod(Class<?> clazz, String name) { + Method[] methods = clazz.getDeclaredMethods(); + for (Method m : methods) { + if (m.getName().equals(name)) { + return true; + } + } + return false; + } + + @SuppressWarnings("unchecked") + public static <T> Optional<T> getInstanceByConstructor(Class<?> clazz, String arg) throws InstantiationException, IllegalAccessException, IllegalArgumentException, InvocationTargetException, NoSuchMethodException, SecurityException { + List<Class<?>> ctypes = getConstructorParameterTypes(clazz, String.class); + Optional<Object> oObj; + for (Class<?> ctype : ctypes) { + if (ctype.equals(String.class)) { + return Optional.of((T) clazz.getConstructor(ctype).newInstance(arg)); + } else if ((oObj = getDefaultInstance(ctype, arg)).isPresent()) { + return Optional.of((T) clazz.getConstructor(ctype).newInstance(oObj.get())); + } else { + // TODO: recursive instantiation down to string constructor or + // getDefaultInstance method + LOG.debug("Not implemented arg:'{}' class:'{}'", arg, clazz); + } + } + return Optional.empty(); + } + + @SuppressWarnings("unchecked") + public static <T> Optional<T> getDefaultInstance(@Nullable Class<?> clazz, String arg) + throws NoSuchMethodException, SecurityException, IllegalAccessException, IllegalArgumentException, + InvocationTargetException { + LOG.trace("arg:'{}' clazz '{}'", arg, clazz.getName()); + if (clazz != null) { + Method[] methods = clazz.getDeclaredMethods(); + for (Method m : methods) { + //TODO Verify argument type to avoid exception + if (m.getName().equals(TYPEOBJECT_INSTANCE_METHOD)) { + Method method = clazz.getDeclaredMethod(TYPEOBJECT_INSTANCE_METHOD, String.class); + LOG.trace("Invoke {} available {}",TYPEOBJECT_INSTANCE_METHOD, method != null); + return Optional.of((T) method.invoke(null, arg)); + } + } + } + return Optional.empty(); + } + + public static <T> Optional<T> getDefaultInstance(Optional<Class<T>> optionalClazz, String arg) + throws NoSuchMethodException, SecurityException, IllegalAccessException, IllegalArgumentException, + InvocationTargetException { + if (optionalClazz.isPresent()) { + return getDefaultInstance(optionalClazz.get(), arg); + } + return Optional.empty(); + } + + public static List<Class<?>> getConstructorParameterTypes(Class<?> clazz, Class<?> prefer) { + + Constructor<?>[] constructors = clazz.getConstructors(); + List<Class<?>> res = new ArrayList<>(); + for (Constructor<?> c : constructors) { + Class<?>[] ptypes = c.getParameterTypes(); + if (ptypes.length == 1) { + res.add(ptypes[0]); + } + + if (prefer != null && ptypes.length == 1 && ptypes[0].equals(prefer)) { + return Arrays.asList(prefer); + } + } + return res; + } + + public static boolean implementsInterface(Class<?> clz, Class<?> ifToImplement) { + if(clz.equals(ifToImplement)) { + return true; + } + Class<?>[] ifs = clz.getInterfaces(); + for (Class<?> iff : ifs) { + if (iff.equals(ifToImplement)) { + return true; + } + } + return false; + } + + /** + * Provide mapping of string to attribute names, generated by yang-tools. "netconf-id" converted to "_netconfId" + * + * @param name with attribute name, not null or empty + * @return converted string or null if name was empty or null + */ + public @Nullable static String toCamelCaseAttributeName(final String name) { + if (name == null || name.isEmpty()) + return null; + + final StringBuilder ret = new StringBuilder(name.length()); + if (!name.startsWith("_")) + ret.append('_'); + int start = 0; + for (final String word : name.split("-")) { + if (!word.isEmpty()) { + if (start++ == 0) { + ret.append(Character.toLowerCase(word.charAt(0))); + } else { + ret.append(Character.toUpperCase(word.charAt(0))); + } + ret.append(word.substring(1)); + } + } + return ret.toString(); + } + + private static BundleContext getBundleContext() { + Bundle bundle = FrameworkUtil.getBundle(YangToolsMapperHelper.class); + return bundle != null ? bundle.getBundleContext() : null; + } + public static boolean hasTime(Notification notification) { + return notification instanceof EventInstantAware; + } + public static DateAndTime getTime(Notification notification, Instant defaultValue) { + Instant time; + if (hasTime(notification)) { // If notification class extends/implements the EventInstantAware + time = ((EventInstantAware) notification).eventInstant(); + LOG.debug("Event time {}", time); + } else { + time = defaultValue; + LOG.debug("Defaulting to actual time of processing the notification - {}", time); + } + return DateAndTime.getDefaultInstance(ZonedDateTime.ofInstant(time, ZoneOffset.UTC).format(formatterOutput)); + } +} diff --git a/sdnr/wt/common-yang/utils/src/main/java/org/onap/ccsdk/features/sdnr/wt/yang/mapper/builder/DateAndTimeBuilder.java b/sdnr/wt/common-yang/utils/src/main/java/org/onap/ccsdk/features/sdnr/wt/yang/mapper/builder/DateAndTimeBuilder.java new file mode 100644 index 000000000..f6afc578f --- /dev/null +++ b/sdnr/wt/common-yang/utils/src/main/java/org/onap/ccsdk/features/sdnr/wt/yang/mapper/builder/DateAndTimeBuilder.java @@ -0,0 +1,36 @@ +/* + * ============LICENSE_START======================================================= + * ONAP : ccsdk features + * ================================================================================ + * Copyright (C) 2020 highstreet technologies GmbH Intellectual Property. + * All rights reserved. + * ================================================================================ + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ============LICENSE_END========================================================= + * + */ +package org.onap.ccsdk.features.sdnr.wt.yang.mapper.builder; + +import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.yang.types.rev130715.DateAndTime; + +public class DateAndTimeBuilder { + private final String _value; + + public DateAndTimeBuilder(String v) { + this._value = v; + } + + public DateAndTime build() { + return new DateAndTime(_value); + } +} diff --git a/sdnr/wt/common-yang/utils/src/main/java/org/onap/ccsdk/features/sdnr/wt/yang/mapper/mapperextensions/YangToolsBuilderAnnotationIntrospector.java b/sdnr/wt/common-yang/utils/src/main/java/org/onap/ccsdk/features/sdnr/wt/yang/mapper/mapperextensions/YangToolsBuilderAnnotationIntrospector.java new file mode 100644 index 000000000..46c966076 --- /dev/null +++ b/sdnr/wt/common-yang/utils/src/main/java/org/onap/ccsdk/features/sdnr/wt/yang/mapper/mapperextensions/YangToolsBuilderAnnotationIntrospector.java @@ -0,0 +1,136 @@ +/* + * ============LICENSE_START======================================================= + * ONAP : ccsdk features + * ================================================================================ + * Copyright (C) 2020 highstreet technologies GmbH Intellectual Property. + * All rights reserved. + * ================================================================================ + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ============LICENSE_END========================================================= + * + */ +package org.onap.ccsdk.features.sdnr.wt.yang.mapper.mapperextensions; + +import com.fasterxml.jackson.databind.annotation.JsonPOJOBuilder; +import com.fasterxml.jackson.databind.annotation.JsonPOJOBuilder.Value; +import com.fasterxml.jackson.databind.cfg.MapperConfig; +import com.fasterxml.jackson.databind.introspect.AnnotatedClass; +import com.fasterxml.jackson.databind.introspect.AnnotatedMethod; +import com.fasterxml.jackson.databind.introspect.JacksonAnnotationIntrospector; +import java.math.BigInteger; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import org.onap.ccsdk.features.sdnr.wt.yang.mapper.YangToolsMapperHelper; +import org.onap.ccsdk.features.sdnr.wt.yang.mapper.builder.DateAndTimeBuilder; +//import org.onap.ccsdk.features.sdnr.wt.dataprovider.data.builders.rev201110.read.network.element.connection.list.output.DataBuilder; +import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.yang.types.rev130715.DateAndTime; +import org.opendaylight.yangtools.yang.common.Uint16; +import org.opendaylight.yangtools.yang.common.Uint32; +import org.opendaylight.yangtools.yang.common.Uint64; +import org.opendaylight.yangtools.yang.common.Uint8; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +public class YangToolsBuilderAnnotationIntrospector extends JacksonAnnotationIntrospector { + + private static final Logger LOG = LoggerFactory.getLogger(YangToolsBuilderAnnotationIntrospector.class); + private static final long serialVersionUID = 1L; + + private final Map<Class<?>, String> customDeserializer; + + public YangToolsBuilderAnnotationIntrospector() { + this(null, null); + } + + public YangToolsBuilderAnnotationIntrospector(Class<?> cls, Class<?> builderClass) { + this.customDeserializer = new HashMap<>(); + if (cls != null && builderClass != null) { + this.customDeserializer.put(cls, builderClass.getName()); + } + this.customDeserializer.put(DateAndTime.class, DateAndTimeBuilder.class.getName()); + //this.customDeserializer.put(Credentials.class, LoginPasswordBuilder.class.getName()); + } + + @Override + public Class<?> findPOJOBuilder(AnnotatedClass ac) { + try { + String builder = null; + if (this.customDeserializer.containsKey(ac.getRawType())) { + builder = this.customDeserializer.get(ac.getRawType()); + } else { + if (ac.getRawType().isInterface()) { + builder = ac.getName() + "Builder"; + } + } + if (builder != null) { + LOG.trace("map {} with builder {}", ac.getName(), builder); + Class<?> innerBuilder = YangToolsMapperHelper.findClass(builder); + return innerBuilder; + } + } catch (ClassNotFoundException e) { + LOG.trace("builder class not found for {}", ac.getName()); + } + return super.findPOJOBuilder(ac); + } + + @Override + public Value findPOJOBuilderConfig(AnnotatedClass ac) { + if (ac.hasAnnotation(JsonPOJOBuilder.class)) { + return super.findPOJOBuilderConfig(ac); + } + return new JsonPOJOBuilder.Value("build", "set"); + } + + @Override + public AnnotatedMethod resolveSetterConflict(MapperConfig<?> config, AnnotatedMethod setter1, + AnnotatedMethod setter2) { + Class<?> p1 = setter1.getRawParameterType(0); + Class<?> p2 = setter2.getRawParameterType(0); + AnnotatedMethod res = null; + + if (this.isAssignable(p1, p2, Map.class, List.class)) { + res = p1.isAssignableFrom(List.class) ? setter1 : setter2; //prefer List setter + } else if (this.isAssignable(p1, p2, Uint64.class, BigInteger.class)) { + res = setter1; + } else if (this.isAssignable(p1, p2, Uint32.class, Long.class)) { + res = setter1; + } else if (this.isAssignable(p1, p2, Uint16.class, Integer.class)) { + res = setter1; + } else if (this.isAssignable(p1, p2, Uint8.class, Short.class)) { + res = setter1; + } + if (res == null) { + res = super.resolveSetterConflict(config, setter1, setter2); + } + if(res ==null) { + LOG.warn("unable to resolve setter conflict for {}", setter1.getName()); + } + else { + LOG.debug("{} (m1={} <=> m2={} => result:{})", setter1.getName(), p1.getSimpleName(), p2.getSimpleName(), + res.getRawParameterType(0)==null?"null":res.getRawParameterType(0).getSimpleName()); + } + return res; + } + + private boolean isAssignable(Class<?> p1, Class<?> p2, Class<?> c1, Class<?> c2) { + return ((p1.isAssignableFrom(c1) && p2.isAssignableFrom(c2)) + || (p2.isAssignableFrom(c1) && p1.isAssignableFrom(c2))); + + } + + public void addDeserializer(Class<?> clazz, String builder) { + this.customDeserializer.put(clazz, builder); + } + +} diff --git a/sdnr/wt/common-yang/utils/src/main/java/org/onap/ccsdk/features/sdnr/wt/yang/mapper/mapperextensions/YangToolsDeserializerModifier.java b/sdnr/wt/common-yang/utils/src/main/java/org/onap/ccsdk/features/sdnr/wt/yang/mapper/mapperextensions/YangToolsDeserializerModifier.java new file mode 100644 index 000000000..c12d17e74 --- /dev/null +++ b/sdnr/wt/common-yang/utils/src/main/java/org/onap/ccsdk/features/sdnr/wt/yang/mapper/mapperextensions/YangToolsDeserializerModifier.java @@ -0,0 +1,111 @@ +/* + * ============LICENSE_START======================================================= + * ONAP : ccsdk features + * ================================================================================ + * Copyright (C) 2020 highstreet technologies GmbH Intellectual Property. + * All rights reserved. + * ================================================================================ + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ============LICENSE_END========================================================= + * + */ +package org.onap.ccsdk.features.sdnr.wt.yang.mapper.mapperextensions; + +import com.fasterxml.jackson.core.JsonParser; +import com.fasterxml.jackson.databind.BeanDescription; +import com.fasterxml.jackson.databind.DeserializationConfig; +import com.fasterxml.jackson.databind.DeserializationContext; +import com.fasterxml.jackson.databind.JavaType; +import com.fasterxml.jackson.databind.JsonDeserializer; +import com.fasterxml.jackson.databind.KeyDeserializer; +import com.fasterxml.jackson.databind.deser.BeanDeserializerModifier; +import java.io.IOException; +import java.lang.reflect.InvocationTargetException; +import java.lang.reflect.Method; +import java.util.NoSuchElementException; +import org.onap.ccsdk.features.sdnr.wt.yang.mapper.YangToolsMapperHelper; +import org.onap.ccsdk.features.sdnr.wt.yang.mapper.serialize.BaseIdentityDeserializer; +import org.onap.ccsdk.features.sdnr.wt.yang.mapper.serialize.ClassDeserializer; +import org.onap.ccsdk.features.sdnr.wt.yang.mapper.serialize.IdentifierDeserializer; +import org.onap.ccsdk.features.sdnr.wt.yang.mapper.serialize.TypeObjectDeserializer; +import org.opendaylight.yangtools.yang.binding.BaseIdentity; +import org.opendaylight.yangtools.yang.binding.Identifier; +import org.opendaylight.yangtools.yang.binding.ScalarTypeObject; +import org.opendaylight.yangtools.yang.binding.TypeObject; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +public class YangToolsDeserializerModifier extends BeanDeserializerModifier { + + private static final Logger LOG = LoggerFactory.getLogger(YangToolsDeserializerModifier.class); + private static final String getEnumMethodName="valueOf"; + + @Override + public JsonDeserializer<Enum<?>> modifyEnumDeserializer(DeserializationConfig config, final JavaType type, + BeanDescription beanDesc, final JsonDeserializer<?> deserializer) { + return new JsonDeserializer<Enum<?>>() { + + @Override + public Enum<?> deserialize(JsonParser jp, DeserializationContext ctxt) throws IOException { + Class<?> clazz = type.getRawClass(); + + try { + Method method = clazz.getDeclaredMethod(getEnumMethodName, String.class); + Enum<?> result = (Enum<?>) method.invoke(null, jp.getValueAsString()); + LOG.debug("Deserialize '{}' with class '{}' to '{}'", jp.getValueAsString(), clazz.getName(), result); + return result; + } catch (IllegalAccessException | IllegalArgumentException | InvocationTargetException + | NoSuchMethodException | NoSuchElementException | SecurityException e) { + LOG.warn("problem deserializing enum for {} with value {}: {}", clazz.getName(), + jp.getValueAsString(), e); + } + throw new IOException( + "unable to parse enum (" + type.getRawClass() + ")for value " + jp.getValueAsString()); + } + }; + } + + @Override + public JsonDeserializer<?> modifyDeserializer(DeserializationConfig config, BeanDescription beanDesc, + JsonDeserializer<?> deserializer) { + final JavaType type = beanDesc.getType(); + final Class<?> rawClass = type.getRawClass(); + + JsonDeserializer<?> deser = super.modifyDeserializer(config, beanDesc, deserializer); + + if (YangToolsMapperHelper.implementsInterface(rawClass, TypeObject.class)) { + deser = new TypeObjectDeserializer<TypeObject>(type, deser); + } else if (YangToolsMapperHelper.implementsInterface(rawClass, ScalarTypeObject.class)) { + deser = new TypeObjectDeserializer<ScalarTypeObject<?>>(type, deser); + } else if (YangToolsMapperHelper.implementsInterface(rawClass, BaseIdentity.class)) { + deser = new BaseIdentityDeserializer<BaseIdentity>(deser); + } else if (rawClass.equals(Class.class)) { + deser = new ClassDeserializer(rawClass); + } + + LOG.debug("Deserialize '{}' with deserializer '{}'", rawClass.getName(), deser.getClass().getName()); + return deser; + } + + @Override + public KeyDeserializer modifyKeyDeserializer(DeserializationConfig config, JavaType type, KeyDeserializer deser) { + KeyDeserializer res; + if (YangToolsMapperHelper.implementsInterface(type.getRawClass(), Identifier.class)) { + res = new IdentifierDeserializer(); + } else { + res = super.modifyKeyDeserializer(config, type, deser); + } + LOG.debug("Keydeserialize '{}' with deserializer '{}'", type.getRawClass().getName(), res.getClass().getName()); + return res; + } +} diff --git a/sdnr/wt/common-yang/utils/src/main/java/org/onap/ccsdk/features/sdnr/wt/yang/mapper/mapperextensions/YangToolsModule.java b/sdnr/wt/common-yang/utils/src/main/java/org/onap/ccsdk/features/sdnr/wt/yang/mapper/mapperextensions/YangToolsModule.java new file mode 100644 index 000000000..02628dc16 --- /dev/null +++ b/sdnr/wt/common-yang/utils/src/main/java/org/onap/ccsdk/features/sdnr/wt/yang/mapper/mapperextensions/YangToolsModule.java @@ -0,0 +1,50 @@ +/* + * ============LICENSE_START======================================================= + * ONAP : ccsdk features + * ================================================================================ + * Copyright (C) 2020 highstreet technologies GmbH Intellectual Property. + * All rights reserved. + * ================================================================================ + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ============LICENSE_END========================================================= + * + */ +package org.onap.ccsdk.features.sdnr.wt.yang.mapper.mapperextensions; + +import com.fasterxml.jackson.databind.module.SimpleModule; +import java.util.Map; +import org.onap.ccsdk.features.sdnr.wt.yang.mapper.serialize.DateAndTimeSerializer; +import org.onap.ccsdk.features.sdnr.wt.yang.mapper.serialize.EnumSerializer; +import org.onap.ccsdk.features.sdnr.wt.yang.mapper.serialize.MapSerializer; +import org.onap.ccsdk.features.sdnr.wt.yang.mapper.serialize.TypeObjectSerializer; +import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.yang.types.rev130715.DateAndTime; +import org.opendaylight.yangtools.yang.binding.ScalarTypeObject; +import org.opendaylight.yangtools.yang.binding.TypeObject; + +public class YangToolsModule extends SimpleModule { + + private static final long serialVersionUID = 1L; + + public YangToolsModule() { + super(); + setDeserializerModifier(new YangToolsDeserializerModifier()); + + addSerializer(DateAndTime.class, new DateAndTimeSerializer()); + addSerializer(TypeObject.class, new TypeObjectSerializer()); + addSerializer(ScalarTypeObject.class, new TypeObjectSerializer()); + addSerializer(Enum.class, new EnumSerializer()); + addSerializer(Map.class, new MapSerializer()); + + } + +} diff --git a/sdnr/wt/common-yang/utils/src/main/java/org/onap/ccsdk/features/sdnr/wt/yang/mapper/serialize/BaseIdentityDeserializer.java b/sdnr/wt/common-yang/utils/src/main/java/org/onap/ccsdk/features/sdnr/wt/yang/mapper/serialize/BaseIdentityDeserializer.java new file mode 100644 index 000000000..f85f80e2c --- /dev/null +++ b/sdnr/wt/common-yang/utils/src/main/java/org/onap/ccsdk/features/sdnr/wt/yang/mapper/serialize/BaseIdentityDeserializer.java @@ -0,0 +1,64 @@ +/* + * ============LICENSE_START======================================================= + * ONAP : ccsdk features + * ================================================================================ + * Copyright (C) 2020 highstreet technologies GmbH Intellectual Property. + * All rights reserved. + * ================================================================================ + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ============LICENSE_END========================================================= + * + */ +package org.onap.ccsdk.features.sdnr.wt.yang.mapper.serialize; + +import com.fasterxml.jackson.core.JsonParser; +import com.fasterxml.jackson.core.JsonProcessingException; +import com.fasterxml.jackson.databind.DeserializationContext; +import com.fasterxml.jackson.databind.JsonDeserializer; +import java.io.IOException; +import org.onap.ccsdk.features.sdnr.wt.yang.mapper.YangToolsMapperHelper; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +public class BaseIdentityDeserializer<T> extends JsonDeserializer<T> { + + private static final Logger LOG = LoggerFactory.getLogger(BaseIdentityDeserializer.class); + private final JsonDeserializer<?> deser; + + public BaseIdentityDeserializer(final JsonDeserializer<?> deser) { + this.deser = deser; + } + + @SuppressWarnings("unchecked") + @Override + public T deserialize(JsonParser parser, DeserializationContext ctxt) throws IOException, JsonProcessingException { + LOG.debug("BaseIdentityDeserializer class for '{}'",parser.getValueAsString()); + String clazzToSearch = parser.getValueAsString(); + // clazz from Elasticsearch is full qualified + int lastDot = clazzToSearch.lastIndexOf("."); + if (lastDot > -1) { + clazzToSearch = clazzToSearch.substring(lastDot+1); + } else { + clazzToSearch = clazzToSearch.substring(0, 1).toUpperCase() + clazzToSearch.substring(1); + } + Class<?> clazz; + try { + clazz = YangToolsMapperHelper.findClass(clazzToSearch); + if (clazz != null) + return (T)clazz; + } catch (ClassNotFoundException e) { + LOG.warn("BaseIdentityDeserializer class not found for '"+parser.getValueAsString()+"'",e); + } + return (T) deser.deserialize(parser, ctxt); + } +} diff --git a/sdnr/wt/common-yang/utils/src/main/java/org/onap/ccsdk/features/sdnr/wt/yang/mapper/serialize/ClassDeserializer.java b/sdnr/wt/common-yang/utils/src/main/java/org/onap/ccsdk/features/sdnr/wt/yang/mapper/serialize/ClassDeserializer.java new file mode 100644 index 000000000..9d221f504 --- /dev/null +++ b/sdnr/wt/common-yang/utils/src/main/java/org/onap/ccsdk/features/sdnr/wt/yang/mapper/serialize/ClassDeserializer.java @@ -0,0 +1,45 @@ +/* + * ============LICENSE_START======================================================= + * ONAP : ccsdk features + * ================================================================================ + * Copyright (C) 2020 highstreet technologies GmbH Intellectual Property. + * All rights reserved. + * ================================================================================ + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ============LICENSE_END========================================================= + * + */ +package org.onap.ccsdk.features.sdnr.wt.yang.mapper.serialize; + +import com.fasterxml.jackson.databind.DeserializationContext; +import com.fasterxml.jackson.databind.deser.std.FromStringDeserializer; +import java.io.IOException; +import org.onap.ccsdk.features.sdnr.wt.yang.mapper.YangToolsMapperHelper; + +public class ClassDeserializer extends FromStringDeserializer<Class<?>> { + + private static final long serialVersionUID = 1L; + + public ClassDeserializer(Class<?> vc) { + super(vc); + } + + @Override + protected Class<?> _deserialize(String value, DeserializationContext ctxt) throws IOException { + try { + return YangToolsMapperHelper.findClass(value); + } catch (ClassNotFoundException e) { + throw new IOException("Can not find class "+value,e); + } + } +} diff --git a/sdnr/wt/common-yang/utils/src/main/java/org/onap/ccsdk/features/sdnr/wt/yang/mapper/serialize/DateAndTimeSerializer.java b/sdnr/wt/common-yang/utils/src/main/java/org/onap/ccsdk/features/sdnr/wt/yang/mapper/serialize/DateAndTimeSerializer.java new file mode 100644 index 000000000..f4fd87580 --- /dev/null +++ b/sdnr/wt/common-yang/utils/src/main/java/org/onap/ccsdk/features/sdnr/wt/yang/mapper/serialize/DateAndTimeSerializer.java @@ -0,0 +1,51 @@ +/* + * ============LICENSE_START======================================================= + * ONAP : ccsdk features + * ================================================================================ + * Copyright (C) 2020 highstreet technologies GmbH Intellectual Property. + * All rights reserved. + * ================================================================================ + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ============LICENSE_END========================================================= + * + */ +package org.onap.ccsdk.features.sdnr.wt.yang.mapper.serialize; + +import com.fasterxml.jackson.core.JsonGenerator; +import com.fasterxml.jackson.databind.SerializerProvider; +import com.fasterxml.jackson.databind.ser.std.StdSerializer; +import java.io.IOException; +import org.eclipse.jdt.annotation.NonNull; +import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.yang.types.rev130715.DateAndTime; + +/** + * DateAndTime shouldn't be encapsulated into a json object to be able to use elasticsearch date time query functions. + */ +public class DateAndTimeSerializer extends StdSerializer<@NonNull DateAndTime> { + + private static final long serialVersionUID = 1L; + + public DateAndTimeSerializer() { + this(null); + } + + protected DateAndTimeSerializer(Class<DateAndTime> t) { + super(t); + } + + @Override + public void serialize(DateAndTime value, JsonGenerator gen, SerializerProvider serializers) throws IOException { + gen.writeString(value.getValue()); + } + +} diff --git a/sdnr/wt/common-yang/utils/src/main/java/org/onap/ccsdk/features/sdnr/wt/yang/mapper/serialize/EnumSerializer.java b/sdnr/wt/common-yang/utils/src/main/java/org/onap/ccsdk/features/sdnr/wt/yang/mapper/serialize/EnumSerializer.java new file mode 100644 index 000000000..55a20d6c0 --- /dev/null +++ b/sdnr/wt/common-yang/utils/src/main/java/org/onap/ccsdk/features/sdnr/wt/yang/mapper/serialize/EnumSerializer.java @@ -0,0 +1,36 @@ +/* + * ============LICENSE_START======================================================= + * ONAP : ccsdk features + * ================================================================================ + * Copyright (C) 2020 highstreet technologies GmbH Intellectual Property. + * All rights reserved. + * ================================================================================ + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ============LICENSE_END========================================================= + * + */ +package org.onap.ccsdk.features.sdnr.wt.yang.mapper.serialize; + +import com.fasterxml.jackson.core.JsonGenerator; +import com.fasterxml.jackson.databind.JsonSerializer; +import com.fasterxml.jackson.databind.SerializerProvider; +import java.io.IOException; + +@SuppressWarnings("rawtypes") +public class EnumSerializer extends JsonSerializer<Enum> { + + @Override + public void serialize(Enum value, JsonGenerator gen, SerializerProvider serializers) throws IOException { + gen.writeString(value.name()); + } +} diff --git a/sdnr/wt/common-yang/utils/src/main/java/org/onap/ccsdk/features/sdnr/wt/yang/mapper/serialize/IdentifierDeserializer.java b/sdnr/wt/common-yang/utils/src/main/java/org/onap/ccsdk/features/sdnr/wt/yang/mapper/serialize/IdentifierDeserializer.java new file mode 100644 index 000000000..6c4c25eb1 --- /dev/null +++ b/sdnr/wt/common-yang/utils/src/main/java/org/onap/ccsdk/features/sdnr/wt/yang/mapper/serialize/IdentifierDeserializer.java @@ -0,0 +1,71 @@ +/* + * ============LICENSE_START======================================================= + * ONAP : ccsdk features + * ================================================================================ + * Copyright (C) 2020 highstreet technologies GmbH Intellectual Property. + * All rights reserved. + * ================================================================================ + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ============LICENSE_END========================================================= + * + */ +package org.onap.ccsdk.features.sdnr.wt.yang.mapper.serialize; + +import com.fasterxml.jackson.databind.DeserializationContext; +import com.fasterxml.jackson.databind.KeyDeserializer; +import java.io.IOException; +import java.lang.reflect.InvocationTargetException; +import java.util.List; +import org.onap.ccsdk.features.sdnr.wt.yang.mapper.YangToolsMapperHelper; +import org.opendaylight.yangtools.yang.common.Uint16; +import org.opendaylight.yangtools.yang.common.Uint32; +import org.opendaylight.yangtools.yang.common.Uint64; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +public class IdentifierDeserializer extends KeyDeserializer { + + private static final Logger LOG = LoggerFactory.getLogger(IdentifierDeserializer.class); + + public IdentifierDeserializer() {} + + @Override + public Object deserializeKey(String key, DeserializationContext ctxt) throws IOException { + Class<?> clazz = ctxt.getClass(); + final String arg = key; + LOG.debug("Deserialization for key:{}",key); + // find constructor argument types + List<Class<?>> ctypes = YangToolsMapperHelper.getConstructorParameterTypes(clazz, String.class); + for (Class<?> ctype : ctypes) { + try { + if (ctype.equals(String.class)) { + return clazz.getConstructor(ctype).newInstance(arg); + } else if (ctype.equals(Uint16.class)) { + return clazz.getConstructor(ctype).newInstance(Uint16.valueOf(arg)); + + } else if (ctype.equals(Uint32.class)) { + return clazz.getConstructor(ctype).newInstance(Uint32.valueOf(arg)); + } else if (ctype.equals(Uint64.class)) { + return clazz.getConstructor(ctype).newInstance(Uint64.valueOf(arg)); + } + } catch (InstantiationException | IllegalAccessException | IllegalArgumentException + | InvocationTargetException | NoSuchMethodException | SecurityException e) { + LOG.warn("unable to instantiate class {} with arg {}: ", clazz, arg, e); + throw new IllegalArgumentException( + "unable to instantiate class " + clazz.getName() + " with arg '" + arg + "' ", e); + } + } + return null; + } + +} diff --git a/sdnr/wt/common-yang/utils/src/main/java/org/onap/ccsdk/features/sdnr/wt/yang/mapper/serialize/MapSerializer.java b/sdnr/wt/common-yang/utils/src/main/java/org/onap/ccsdk/features/sdnr/wt/yang/mapper/serialize/MapSerializer.java new file mode 100644 index 000000000..63689c098 --- /dev/null +++ b/sdnr/wt/common-yang/utils/src/main/java/org/onap/ccsdk/features/sdnr/wt/yang/mapper/serialize/MapSerializer.java @@ -0,0 +1,37 @@ +/* + * ============LICENSE_START======================================================= + * ONAP : ccsdk features + * ================================================================================ + * Copyright (C) 2020 highstreet technologies GmbH Intellectual Property. + * All rights reserved. + * ================================================================================ + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ============LICENSE_END========================================================= + * + */ +package org.onap.ccsdk.features.sdnr.wt.yang.mapper.serialize; + +import com.fasterxml.jackson.core.JsonGenerator; +import com.fasterxml.jackson.databind.JsonSerializer; +import com.fasterxml.jackson.databind.SerializerProvider; +import java.io.IOException; +import java.util.Map; + +@SuppressWarnings("rawtypes") +public class MapSerializer extends JsonSerializer<Map> { + + @Override + public void serialize(Map value, JsonGenerator gen, SerializerProvider serializers) throws IOException { + gen.writeObject(value.values()); + } +} diff --git a/sdnr/wt/common-yang/utils/src/main/java/org/onap/ccsdk/features/sdnr/wt/yang/mapper/serialize/TypeObjectDeserializer.java b/sdnr/wt/common-yang/utils/src/main/java/org/onap/ccsdk/features/sdnr/wt/yang/mapper/serialize/TypeObjectDeserializer.java new file mode 100644 index 000000000..b857a2ffb --- /dev/null +++ b/sdnr/wt/common-yang/utils/src/main/java/org/onap/ccsdk/features/sdnr/wt/yang/mapper/serialize/TypeObjectDeserializer.java @@ -0,0 +1,87 @@ +/* + * ============LICENSE_START======================================================= + * ONAP : ccsdk features + * ================================================================================ + * Copyright (C) 2020 highstreet technologies GmbH Intellectual Property. + * All rights reserved. + * ================================================================================ + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ============LICENSE_END========================================================= + * + */ +package org.onap.ccsdk.features.sdnr.wt.yang.mapper.serialize; + +import com.fasterxml.jackson.core.JsonParser; +import com.fasterxml.jackson.core.JsonProcessingException; +import com.fasterxml.jackson.databind.DeserializationContext; +import com.fasterxml.jackson.databind.JavaType; +import com.fasterxml.jackson.databind.JsonDeserializer; +import java.io.IOException; +import java.lang.reflect.InvocationTargetException; +import java.util.NoSuchElementException; +import java.util.Optional; +import org.onap.ccsdk.features.sdnr.wt.yang.mapper.YangToolsMapperHelper; +import org.opendaylight.yangtools.concepts.Builder; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +public class TypeObjectDeserializer<T> extends JsonDeserializer<T> { + + private static final Logger LOG = LoggerFactory.getLogger(TypeObjectDeserializer.class); + private final JavaType type; + private final JsonDeserializer<?> deser; + + + public TypeObjectDeserializer(final JavaType type, final JsonDeserializer<?> deser) { + this.type = type; + this.deser = deser; + } + + @SuppressWarnings("unchecked") + @Override + public T deserialize(JsonParser parser, DeserializationContext ctxt) throws IOException, JsonProcessingException { + + Class<T> clazz = (Class<T>) type.getRawClass(); + final String arg = parser.getValueAsString(); + LOG.debug("Try to build arg:'{}' with class {}",arg, clazz); + Optional<T> oRes = Optional.empty(); + try { + //try get method for default instance + if ((oRes = YangToolsMapperHelper.getDefaultInstance(clazz, arg)).isEmpty()) { + //try to find builder with getDefaultInstance method + Optional<Class<Builder<?>>> oBuilderClazz = YangToolsMapperHelper.findBuilderClassOptional(ctxt, clazz); + LOG.debug("Try builder class present:{}",oBuilderClazz.isPresent()); + if (oBuilderClazz.isEmpty() + || ((oRes = YangToolsMapperHelper.getDefaultInstance(oBuilderClazz.get(), arg)).isEmpty())) { + //try to find constructor with string + LOG.debug("Try constructor"); + if ((oRes = YangToolsMapperHelper.getInstanceByConstructor(clazz, arg)).isEmpty()) { + //forward to standard deserializer or throw if not available + LOG.debug("Try default deserializer"); + oRes = Optional.of((T) deser.deserialize(parser, ctxt)); + } + } + } + LOG.debug("Deserialize string value:{} for class:{} success:{}", arg, clazz, oRes.isPresent()); + } catch (IllegalAccessException | IllegalArgumentException | InvocationTargetException | NoSuchMethodException + | NoSuchElementException | SecurityException | InstantiationException e) { + LOG.warn("problem deserializing {} with value {}: {}", clazz.getName(), arg, e); + } + if (oRes.isPresent()) { + return oRes.get(); + } else { + throw new IllegalArgumentException("Could not find constructor for arg:'" + arg + "' and class: " + clazz); + } + } + +} diff --git a/sdnr/wt/common-yang/utils/src/main/java/org/onap/ccsdk/features/sdnr/wt/yang/mapper/serialize/TypeObjectSerializer.java b/sdnr/wt/common-yang/utils/src/main/java/org/onap/ccsdk/features/sdnr/wt/yang/mapper/serialize/TypeObjectSerializer.java new file mode 100644 index 000000000..b43e6c100 --- /dev/null +++ b/sdnr/wt/common-yang/utils/src/main/java/org/onap/ccsdk/features/sdnr/wt/yang/mapper/serialize/TypeObjectSerializer.java @@ -0,0 +1,52 @@ +/* + * ============LICENSE_START======================================================= + * ONAP : ccsdk features + * ================================================================================ + * Copyright (C) 2020 highstreet technologies GmbH Intellectual Property. + * All rights reserved. + * ================================================================================ + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ============LICENSE_END========================================================= + * + */ +package org.onap.ccsdk.features.sdnr.wt.yang.mapper.serialize; + +import com.fasterxml.jackson.core.JsonGenerator; +import com.fasterxml.jackson.databind.JsonSerializer; +import com.fasterxml.jackson.databind.SerializerProvider; +import java.io.IOException; +import java.lang.reflect.InvocationTargetException; +import java.lang.reflect.Method; +import org.opendaylight.yangtools.yang.binding.TypeObject; + +public class TypeObjectSerializer extends JsonSerializer<TypeObject> { + + @Override + public void serialize(TypeObject value, JsonGenerator gen, SerializerProvider serializers) throws IOException { + //stringValue + Method[] methods = value.getClass().getDeclaredMethods(); + String name; + for (Method method : methods) { + name = method.getName(); + if (method.getParameterCount()==0 && (name.equals("stringValue") || name.equals("getValue"))) { + try { + gen.writeString((String)method.invoke(value)); + break; + } catch (IllegalAccessException | IllegalArgumentException | InvocationTargetException + | IOException e) { + throw new IOException("No String getter method supported TypeObject for "+value.getClass(),e); + } + } + } + } +} |