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 java.util.ArrayList;
12 import java.util.Collection;
13 import java.util.HashMap;
14 import java.util.Iterator;
15 import java.util.List;
17 import java.util.Objects;
18 import java.util.Optional;
19 import org.opendaylight.openflowplugin.openflow.md.core.sal.convertor.action.ActionConvertor;
20 import org.opendaylight.openflowplugin.openflow.md.core.sal.convertor.action.ActionResponseConvertor;
21 import org.opendaylight.openflowplugin.openflow.md.core.sal.convertor.common.Convertor;
22 import org.opendaylight.openflowplugin.openflow.md.core.sal.convertor.common.ConvertorData;
23 import org.opendaylight.openflowplugin.openflow.md.core.sal.convertor.common.ParametrizedConvertor;
24 import org.opendaylight.openflowplugin.openflow.md.core.sal.convertor.flow.FlowConvertor;
25 import org.opendaylight.openflowplugin.openflow.md.core.sal.convertor.flow.FlowInstructionResponseConvertor;
26 import org.opendaylight.openflowplugin.openflow.md.core.sal.convertor.flow.FlowStatsResponseConvertor;
27 import org.opendaylight.openflowplugin.openflow.md.core.sal.convertor.match.MatchResponseConvertor;
28 import org.opendaylight.openflowplugin.openflow.md.core.sal.convertor.match.MatchV10ResponseConvertor;
29 import org.slf4j.Logger;
30 import org.slf4j.LoggerFactory;
33 * Manages various convertors and allows to use them all in one generic way
35 public class ConvertorManager {
36 private static final Logger LOG = LoggerFactory.getLogger(ConvertorManager.class);
37 private static ConvertorManager INSTANCE;
40 INSTANCE = new ConvertorManager();
41 // All convertors are registered here
42 INSTANCE.registerConvertor(new TableFeaturesConvertor());
43 INSTANCE.registerConvertor(new TableFeaturesResponseConvertor());
44 INSTANCE.registerConvertor(new MeterConvertor());
45 INSTANCE.registerConvertor(new MeterStatsResponseConvertor());
46 INSTANCE.registerConvertor(new MeterConfigStatsResponseConvertor());
47 INSTANCE.registerConvertor(new PortConvertor());
48 // TODO: Add MatchConvertor
49 INSTANCE.registerConvertor(new MatchResponseConvertor());
50 INSTANCE.registerConvertor(new MatchV10ResponseConvertor());
51 INSTANCE.registerConvertor(new ActionConvertor());
52 INSTANCE.registerConvertor(new ActionResponseConvertor());
53 INSTANCE.registerConvertor(new GroupConvertor());
54 INSTANCE.registerConvertor(new GroupDescStatsResponseConvertor());
55 INSTANCE.registerConvertor(new GroupStatsResponseConvertor());
56 INSTANCE.registerConvertor(new PacketOutConvertor());
57 INSTANCE.registerConvertor(new FlowConvertor());
58 INSTANCE.registerConvertor(new FlowInstructionResponseConvertor());
59 INSTANCE.registerConvertor(new FlowStatsResponseConvertor());
62 // Actual convertor keys
63 private List<Class<?>> convertorKeys = new ArrayList<>();
64 private List<Class<?>> parametrizedConvertorKeys = new ArrayList<>();
66 // Cache, that holds all registered convertors, but they can have multiple keys,
67 // based on instanceof checks in the convert method
68 private Map<Class<?>, Convertor> convertors = new HashMap<>();
69 private Map<Class<?>, ParametrizedConvertor> parametrizedConvertors = new HashMap<>();
71 private ConvertorManager() {
72 // Hiding implicit constructor
76 * Gets instance of Convertor Manager.
78 * @return the instance
80 public static ConvertorManager getInstance() {
87 * @param convertor the convertor
88 * @return if registration was successful
90 public boolean registerConvertor(final Convertor convertor) {
91 final Class<?> type = convertor.getType();
93 if (convertors.containsKey(type)) {
94 LOG.warn("Convertor for type {} is already registered", type);
98 convertorKeys.add(type);
99 convertors.put(type, convertor);
100 LOG.debug("{} is now converted by {}", type, convertor);
105 * Register convertor.
107 * @param convertor the convertor
108 * @return if registration was successful
110 public boolean registerConvertor(final ParametrizedConvertor convertor) {
111 final Class<?> type = convertor.getType();
113 if (parametrizedConvertors.containsKey(type)) {
114 LOG.warn("Convertor for type {} is already registered", type);
118 parametrizedConvertorKeys.add(type);
119 parametrizedConvertors.put(type, convertor);
120 LOG.debug("{} is now converted by {}", type, convertor);
125 * Lookup and use convertor by specified type, then converts source and returns converted result
127 * @param <FROM> the source type
128 * @param <TO> the result type
129 * @param source the source
130 * @return the result (can be empty, if no convertor was found)
132 @SuppressWarnings("unchecked")
133 public <FROM, TO> Optional<TO> convert(final FROM source) {
134 if (Objects.isNull(source)) {
135 LOG.trace("Cannot convert source, because it is null");
136 return Optional.empty();
139 Class<?> type = source.getClass();
141 if (source instanceof Collection) {
142 final Iterator it = ((Collection) source).iterator();
149 if (Objects.isNull(next)) {
150 LOG.trace("Cannot convert {}, because it is empty collection", type);
151 return Optional.empty();
154 type = next.getClass();
157 Convertor convertor = null;
159 if (!convertors.containsKey(type)) {
160 boolean found = false;
162 for (Class<?> key : convertorKeys) {
163 if (key.isAssignableFrom(type)) {
164 convertor = convertors.get(key);
165 convertors.put(type, convertor);
166 LOG.debug("{} is now converted by {}", type, convertor);
173 LOG.error("Convertor for {} not found", type);
174 return Optional.empty();
178 if (Objects.isNull(convertor)) {
179 convertor = convertors.get(type);
182 final Object result = convertor.convert(source);
183 return Optional.of((TO) result);
187 * Lookup and use convertor by specified type, then converts source and returns converted result
189 * @param <FROM> the source type
190 * @param <TO> the result type
191 * @param <DATA> the data type
192 * @param source the source
193 * @param data convertor data
194 * @return the result (can be empty, if no convertor was found)
196 @SuppressWarnings("unchecked")
197 public <FROM, TO, DATA extends ConvertorData> Optional<TO> convert(final FROM source, final DATA data) {
198 if (Objects.isNull(source)) {
199 LOG.trace("Cannot convert source, because it is null");
200 return Optional.empty();
203 Class<?> type = source.getClass();
205 if (source instanceof Collection) {
206 final Iterator it = ((Collection) source).iterator();
213 if (Objects.isNull(next)) {
214 LOG.trace("Cannot convert {}, because it is empty collection", type);
215 return Optional.empty();
218 type = next.getClass();
221 ParametrizedConvertor convertor = null;
223 if (!parametrizedConvertors.containsKey(type)) {
224 boolean found = false;
226 for (Class<?> key : parametrizedConvertorKeys) {
227 if (key.isAssignableFrom(type)) {
228 convertor = parametrizedConvertors.get(key);
229 parametrizedConvertors.put(type, convertor);
230 LOG.debug("{} is now converted by {}", type, convertor);
237 LOG.error("Convertor for {} not found", type);
238 return Optional.empty();
242 if (Objects.isNull(convertor)) {
243 convertor = parametrizedConvertors.get(type);
246 final Object result = convertor.convert(source, data);
247 return Optional.of((TO) result);