2 * Copyright (c) 2016 Cisco Systems, Inc. and others. All rights reserved.
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
9 package org.opendaylight.openflowplugin.openflow.md.core.sal.convertor;
11 import com.google.common.annotations.VisibleForTesting;
12 import java.util.Arrays;
13 import java.util.Collection;
14 import java.util.Collections;
16 import java.util.Objects;
17 import java.util.Optional;
18 import java.util.concurrent.ConcurrentHashMap;
19 import java.util.stream.Stream;
20 import org.opendaylight.openflowplugin.openflow.md.core.sal.convertor.common.Convertor;
21 import org.opendaylight.openflowplugin.openflow.md.core.sal.convertor.common.ConvertorData;
22 import org.opendaylight.yangtools.yang.binding.DataContainer;
23 import org.slf4j.Logger;
24 import org.slf4j.LoggerFactory;
27 * Manages various convertors and allows to use them all in one generic way
29 public class ConvertorManager implements ConvertorExecutor, ConvertorRegistrator {
30 private static final Logger LOG = LoggerFactory.getLogger(ConvertorManager.class);
32 // Cache, that holds all registered convertors, but they can have multiple keys,
33 // based on instanceof checks in the convert method
34 private Map<Short, Map<Class<? extends DataContainer>, Convertor<?, ?, ? extends ConvertorData>>> convertors;
37 * Create new instance of Convertor Manager
38 * @param supportedVersions supported versions
40 public ConvertorManager(final Short... supportedVersions) {
41 final Stream<Short> stream = Arrays.stream(supportedVersions);
43 if (supportedVersions.length == 1) {
44 final Optional<Short> versionOptional = stream.findFirst();
45 versionOptional.ifPresent(version -> convertors = Collections.singletonMap(version, new ConcurrentHashMap<>()));
47 convertors = new ConcurrentHashMap<>();
48 stream.forEach(version -> convertors.putIfAbsent(version, new ConcurrentHashMap<>()));
53 public ConvertorManager registerConvertor(final short version, final Convertor<?, ?, ? extends ConvertorData> convertor) {
54 final Map<Class<? extends DataContainer>, Convertor<?, ?, ? extends ConvertorData>> convertorsForVersion =
55 convertors.get(version);
57 if (Objects.nonNull(convertorsForVersion)) {
58 for (final Class<? extends DataContainer> type : convertor.getTypes()) {
59 final Convertor<?, ?, ? extends ConvertorData> result = convertorsForVersion.get(type);
61 if (Objects.isNull(result)) {
62 convertor.setConvertorExecutor(this);
63 convertorsForVersion.put(type, convertor);
64 LOG.debug("{} for version {} is now converted by {}", type, version, convertor);
66 LOG.warn("{} for version {} have already registered convertor", type, version);
70 LOG.warn("{} do not supports version {}", this, version);
77 @SuppressWarnings("unchecked")
78 public <FROM extends DataContainer, TO, DATA extends ConvertorData> Optional<TO> convert(final FROM source, final DATA data) {
79 Optional<TO> result = Optional.empty();
81 if (Objects.isNull(source)) {
82 LOG.trace("Cannot extract type from null source");
86 final Class<? extends DataContainer> type = source.getImplementedInterface();
88 if (Objects.isNull(type)) {
89 LOG.warn("Cannot extract type from {}, because getImplementedInterface() returns null", source);
93 return findConvertor(data.getVersion(), type)
94 .map(convertor -> (TO)convertor.convert(source, data));
98 @SuppressWarnings("unchecked")
99 public <FROM extends DataContainer, TO, DATA extends ConvertorData> Optional<TO> convert(final Collection<FROM> source, final DATA data) {
100 Optional<TO> result = Optional.empty();
102 if (Objects.isNull(source)) {
103 LOG.trace("Cannot extract type from null source");
107 final Optional<FROM> first = source.stream().findFirst();
109 if (!first.isPresent()) {
110 LOG.trace("Cannot extract type from empty collection");
114 final Class<? extends DataContainer> type = first.get().getImplementedInterface();
116 if (Objects.isNull(type)) {
117 LOG.warn("Cannot extract type from {}, because getImplementedInterface() returns null", source);
121 return findConvertor(data.getVersion(), type)
122 .map(convertor -> (TO)convertor.convert(source, data));
126 * Last resort. If we do not already have convertor registered,
127 * we will perform some costly operations and try to find if we
128 * can convert input using any of already registered convertors
129 * @param type input type
130 * @return found convertor
133 Optional<Convertor> findConvertor(final short version, final Class<? extends DataContainer> type) {
134 final Map<Class<? extends DataContainer>, Convertor<?, ?, ? extends ConvertorData>> convertorsForVersion =
135 convertors.get(version);
137 Optional<Convertor> convertor = Optional.empty();
139 if (Objects.nonNull(convertorsForVersion)) {
140 convertor = Optional.ofNullable(convertorsForVersion.get(type));
142 if (!convertor.isPresent()) {
143 for (final Class<? extends DataContainer> convertorType : convertorsForVersion.keySet()) {
144 if (type.isAssignableFrom(convertorType)) {
145 final Convertor<?, ?, ? extends ConvertorData> foundConvertor = convertorsForVersion.get(convertorType);
146 convertor = Optional.ofNullable(foundConvertor);
148 if (convertor.isPresent()) {
149 convertorsForVersion.put(type, foundConvertor);
150 LOG.warn("{} for version {} is now converted by {} using last resort method", type, version, foundConvertor);
156 if (!convertor.isPresent()) {
157 LOG.warn("Convertor for {} for version {} not found", type, version);
161 LOG.warn("{} do not supports version {}", this, version);