X-Git-Url: https://git.opendaylight.org/gerrit/gitweb?a=blobdiff_plain;f=openflowplugin%2Fsrc%2Fmain%2Fjava%2Forg%2Fopendaylight%2Fopenflowplugin%2Fopenflow%2Fmd%2Fcore%2Fsal%2Fconvertor%2FConvertorManager.java;h=42c6af9f7b0b09e50a14afcff005a6a508d33fe4;hb=05f8db12159673d0e0a95642fe86e62c14b7dc7b;hp=cc30512e32dbff4f1693689a4d52cacbcb753c05;hpb=8339b1175433d51ad1ace15ad7084ec91535d169;p=openflowplugin.git diff --git a/openflowplugin/src/main/java/org/opendaylight/openflowplugin/openflow/md/core/sal/convertor/ConvertorManager.java b/openflowplugin/src/main/java/org/opendaylight/openflowplugin/openflow/md/core/sal/convertor/ConvertorManager.java index cc30512e32..42c6af9f7b 100644 --- a/openflowplugin/src/main/java/org/opendaylight/openflowplugin/openflow/md/core/sal/convertor/ConvertorManager.java +++ b/openflowplugin/src/main/java/org/opendaylight/openflowplugin/openflow/md/core/sal/convertor/ConvertorManager.java @@ -5,162 +5,155 @@ * terms of the Eclipse Public License v1.0 which accompanies this distribution, * and is available at http://www.eclipse.org/legal/epl-v10.html */ - package org.opendaylight.openflowplugin.openflow.md.core.sal.convertor; -import java.util.ArrayList; +import com.google.common.annotations.VisibleForTesting; +import java.util.Arrays; import java.util.Collection; -import java.util.List; +import java.util.Collections; import java.util.Map; -import java.util.Objects; +import java.util.Map.Entry; import java.util.Optional; import java.util.concurrent.ConcurrentHashMap; -import javax.annotation.Nullable; -import org.opendaylight.openflowplugin.openflow.md.core.sal.convertor.action.ActionConvertor; -import org.opendaylight.openflowplugin.openflow.md.core.sal.convertor.action.ActionResponseConvertor; +import java.util.stream.Stream; import org.opendaylight.openflowplugin.openflow.md.core.sal.convertor.common.Convertor; import org.opendaylight.openflowplugin.openflow.md.core.sal.convertor.common.ConvertorData; -import org.opendaylight.openflowplugin.openflow.md.core.sal.convertor.flow.FlowConvertor; -import org.opendaylight.openflowplugin.openflow.md.core.sal.convertor.flow.FlowInstructionResponseConvertor; -import org.opendaylight.openflowplugin.openflow.md.core.sal.convertor.flow.FlowStatsResponseConvertor; -import org.opendaylight.openflowplugin.openflow.md.core.sal.convertor.match.MatchResponseConvertor; -import org.opendaylight.openflowplugin.openflow.md.core.sal.convertor.match.MatchV10ResponseConvertor; import org.opendaylight.yangtools.yang.binding.DataContainer; import org.slf4j.Logger; import org.slf4j.LoggerFactory; /** - * Manages various convertors and allows to use them all in one generic way + * Manages various convertors and allows to use them all in one generic way. */ public class ConvertorManager implements ConvertorExecutor, ConvertorRegistrator { private static final Logger LOG = LoggerFactory.getLogger(ConvertorManager.class); - private static ConvertorManager INSTANCE; - - static { - INSTANCE = new ConvertorManager(); - // All convertors are registered here - INSTANCE.registerConvertor(new TableFeaturesConvertor()); - INSTANCE.registerConvertor(new TableFeaturesResponseConvertor()); - INSTANCE.registerConvertor(new MeterConvertor()); - INSTANCE.registerConvertor(new MeterStatsResponseConvertor()); - INSTANCE.registerConvertor(new MeterConfigStatsResponseConvertor()); - INSTANCE.registerConvertor(new PortConvertor()); - // TODO: Add MatchConvertor - INSTANCE.registerConvertor(new MatchResponseConvertor()); - INSTANCE.registerConvertor(new MatchV10ResponseConvertor()); - INSTANCE.registerConvertor(new ActionConvertor()); - INSTANCE.registerConvertor(new ActionResponseConvertor()); - INSTANCE.registerConvertor(new GroupConvertor()); - INSTANCE.registerConvertor(new GroupDescStatsResponseConvertor()); - INSTANCE.registerConvertor(new GroupStatsResponseConvertor()); - INSTANCE.registerConvertor(new PacketOutConvertor()); - INSTANCE.registerConvertor(new FlowConvertor()); - INSTANCE.registerConvertor(new FlowInstructionResponseConvertor()); - INSTANCE.registerConvertor(new FlowStatsResponseConvertor()); - } - - // Actual convertor keys - private List> convertorKeys = new ArrayList<>(); // Cache, that holds all registered convertors, but they can have multiple keys, // based on instanceof checks in the convert method - private Map, Convertor> convertors = new ConcurrentHashMap<>(); - - private ConvertorManager() { - // Hiding implicit constructor - } + private Map, Convertor>> convertors; /** - * Gets instance of Convertor Manager. + * Create new instance of Convertor Manager. * - * @return the instance + * @param supportedVersions supported versions */ - public static ConvertorManager getInstance() { - return INSTANCE; + public ConvertorManager(final Short... supportedVersions) { + final Stream stream = Arrays.stream(supportedVersions); + + if (supportedVersions.length == 1) { + final Optional versionOptional = stream.findFirst(); + versionOptional.ifPresent(version -> convertors = + Collections.singletonMap(version, new ConcurrentHashMap<>())); + } else { + convertors = new ConcurrentHashMap<>(); + stream.forEach(version -> convertors.putIfAbsent(version, new ConcurrentHashMap<>())); + } } @Override - @SuppressWarnings("unchecked") - public void registerConvertor(final Convertor convertor) { - for (final Object typeRaw : convertor.getTypes()) { - final Class type = (Class)typeRaw; - final Convertor result = convertors.get(type); - - if (Objects.isNull(result)) { - convertorKeys.add(type); - convertors.put(type, convertor); - LOG.debug("{} is now converted by {}", type, convertor); - } else { - LOG.warn("Convertor for type {} is already registered", type); + public ConvertorManager registerConvertor(final short version, + final Convertor convertor) { + final Map, Convertor> convertorsForVersion = + convertors.get(version); + + if (convertorsForVersion != null) { + for (final Class type : convertor.getTypes()) { + final Convertor result = convertorsForVersion.get(type); + + if (result == null) { + convertor.setConvertorExecutor(this); + convertorsForVersion.put(type, convertor); + LOG.debug("{} for version {} is now converted by {}", type, version, convertor); + } else { + LOG.warn("{} for version {} have already registered convertor", type, version); + } } + } else { + LOG.warn("{} do not supports version {}", this, version); } - } - public Optional convert(final FROM source) { - return convert(source, null); + return this; } @Override @SuppressWarnings("unchecked") - public Optional convert(final FROM source, @Nullable final DATA data) { - Optional result = Optional.empty(); + public Optional convert(final F source, final D data) { + Optional result = Optional.empty(); - if (Objects.isNull(source)) { + if (source == null) { LOG.trace("Cannot extract type from null source"); return result; } - final Class type = source.getImplementedInterface(); + final Class type = source instanceof DataContainer ? ((DataContainer) source).implementedInterface() + : source.getClass(); - if (Objects.isNull(type)) { - LOG.warn("Cannot extract type from source, because getImplementedInterface() returns null"); + if (type == null) { + LOG.warn("Cannot extract type from {}, because implementedInterface() returns null", source); return result; } - final Optional convertor = findConvertor(type); + return findConvertor(data.getVersion(), type).map(convertor -> (T)convertor.convert(source, data)); + } - if (convertor.isPresent()) { - result = Optional.of((TO) convertor.get().convert(source, data)); + @Override + @SuppressWarnings("unchecked") + public Optional convert(final Map source, final D data) { + Optional result = Optional.empty(); + + if (source == null) { + LOG.trace("Cannot extract type from null source"); + return result; } - return result; - } + final Optional firstOptional = source.values().stream().findFirst(); + + if (!firstOptional.isPresent()) { + LOG.trace("Cannot extract type from empty collection"); + return result; + } + + final F first = firstOptional.get(); - public Optional convert(final Collection source) { - return convert(source, null); + final Class type = first instanceof DataContainer ? ((DataContainer) first).implementedInterface() + : first.getClass(); + + if (type == null) { + LOG.warn("Cannot extract type from {}, because implementedInterface() returns null", source); + return result; + } + + return findConvertor(data.getVersion(), type).map(convertor -> (T)convertor.convert(source.values(), data)); } @Override @SuppressWarnings("unchecked") - public Optional convert(final Collection source, @Nullable final DATA data) { - Optional result = Optional.empty(); + public Optional convert(final Collection source, final D data) { + Optional result = Optional.empty(); - if (Objects.isNull(source)) { + if (source == null) { LOG.trace("Cannot extract type from null source"); return result; } - final Optional first = source.stream().findFirst(); + final Optional firstOptional = source.stream().findFirst(); - if (!first.isPresent()) { + if (!firstOptional.isPresent()) { LOG.trace("Cannot extract type from empty collection"); return result; } - final Class type = first.get().getImplementedInterface(); - - if (Objects.isNull(type)) { - LOG.warn("Cannot extract type from source, because getImplementedInterface() returns null"); - return result; - } + final F first = firstOptional.get(); - final Optional convertor = findConvertor(type); + final Class type = first instanceof DataContainer ? ((DataContainer) first).implementedInterface() + : first.getClass(); - if (convertor.isPresent()) { - result = Optional.of((TO) convertor.get().convert(source, data)); + if (type == null) { + LOG.warn("Cannot extract type from {}, because implementedInterface() returns null", source); + return result; } - return result; + return findConvertor(data.getVersion(), type).map(convertor -> (T)convertor.convert(source, data)); } /** @@ -170,25 +163,41 @@ public class ConvertorManager implements ConvertorExecutor, ConvertorRegistrator * @param type input type * @return found convertor */ - private Optional findConvertor(final Class type) { - Optional convertor = Optional.ofNullable(convertors.get(type)); - - if (!convertor.isPresent()) { - for (final Class key : convertorKeys) { - if (key.isAssignableFrom(type)) { - final Convertor foundConvertor = convertors.get(key); - convertor = Optional.ofNullable(foundConvertor); - convertors.put(type, foundConvertor); - LOG.warn("{} is now converted by {} using last resort method", type, foundConvertor); - break; - } - } + @VisibleForTesting + Optional findConvertor(final short version, final Class type) { + final Map, Convertor> convertorsForVersion = + convertors.get(version); + + Optional convertor = Optional.empty(); + + if (convertorsForVersion != null) { + convertor = Optional.ofNullable(convertorsForVersion.get(type)); if (!convertor.isPresent()) { - LOG.warn("Convertor for {} not found", type); + for (Entry, Convertor> entry : + convertorsForVersion.entrySet()) { + final Class convertorType = entry.getKey(); + if (type.isAssignableFrom(convertorType)) { + final Convertor foundConvertor = entry.getValue(); + convertor = Optional.ofNullable(foundConvertor); + + if (convertor.isPresent()) { + convertorsForVersion.put(type, foundConvertor); + LOG.warn("{} for version {} is now converted by {} using last resort method", + type, version, foundConvertor); + break; + } + } + } + + if (!convertor.isPresent()) { + LOG.warn("Convertor for {} for version {} not found", type, version); + } } + } else { + LOG.warn("{} do not supports version {}", this, version); } return convertor; } -} \ No newline at end of file +}