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.match.MatchResponseConvertor;
25 import org.opendaylight.openflowplugin.openflow.md.core.sal.convertor.match.MatchV10ResponseConvertor;
26 import org.slf4j.Logger;
27 import org.slf4j.LoggerFactory;
30 * Manages various convertors and allows to use them all in one generic way
32 public class ConvertorManager {
33 private static final Logger LOG = LoggerFactory.getLogger(ConvertorManager.class);
34 private static ConvertorManager INSTANCE;
37 INSTANCE = new ConvertorManager();
38 // All convertors are registered here
39 INSTANCE.registerConvertor(new TableFeaturesConvertor());
40 INSTANCE.registerConvertor(new TableFeaturesResponseConvertor());
41 INSTANCE.registerConvertor(new MeterConvertor());
42 INSTANCE.registerConvertor(new MeterStatsResponseConvertor());
43 INSTANCE.registerConvertor(new MeterConfigStatsResponseConvertor());
44 INSTANCE.registerConvertor(new PortConvertor());
45 // TODO: Add MatchConvertor
46 INSTANCE.registerConvertor(new MatchResponseConvertor());
47 INSTANCE.registerConvertor(new MatchV10ResponseConvertor());
48 INSTANCE.registerConvertor(new ActionConvertor());
49 INSTANCE.registerConvertor(new ActionResponseConvertor());
50 INSTANCE.registerConvertor(new GroupConvertor());
51 INSTANCE.registerConvertor(new GroupDescStatsResponseConvertor());
52 INSTANCE.registerConvertor(new GroupStatsResponseConvertor());
53 INSTANCE.registerConvertor(new PacketOutConvertor());
56 // Actual convertor keys
57 private List<Class<?>> convertorKeys = new ArrayList<>();
58 private List<Class<?>> parametrizedConvertorKeys = new ArrayList<>();
60 // Cache, that holds all registered convertors, but they can have multiple keys,
61 // based on instanceof checks in the convert method
62 private Map<Class<?>, Convertor> convertors = new HashMap<>();
63 private Map<Class<?>, ParametrizedConvertor> parametrizedConvertors = new HashMap<>();
65 private ConvertorManager() {
66 // Hiding implicit constructor
70 * Gets instance of Convertor Manager.
72 * @return the instance
74 public static ConvertorManager getInstance() {
81 * @param convertor the convertor
82 * @return if registration was successful
84 public boolean registerConvertor(final Convertor convertor) {
85 final Class<?> type = convertor.getType();
87 if (convertors.containsKey(type)) {
88 LOG.warn("Convertor for type {} is already registered", type);
92 convertorKeys.add(type);
93 convertors.put(type, convertor);
94 LOG.debug("{} is now converted by {}", type, convertor);
101 * @param convertor the convertor
102 * @return if registration was successful
104 public boolean registerConvertor(final ParametrizedConvertor convertor) {
105 final Class<?> type = convertor.getType();
107 if (parametrizedConvertors.containsKey(type)) {
108 LOG.warn("Convertor for type {} is already registered", type);
112 parametrizedConvertorKeys.add(type);
113 parametrizedConvertors.put(type, convertor);
114 LOG.debug("{} is now converted by {}", type, convertor);
119 * Lookup and use convertor by specified type, then converts source and returns converted result
121 * @param <FROM> the source type
122 * @param <TO> the result type
123 * @param source the source
124 * @return the result (can be empty, if no convertor was found)
126 @SuppressWarnings("unchecked")
127 public <FROM, TO> Optional<TO> convert(final FROM source) {
128 if (Objects.isNull(source)) {
129 LOG.trace("Cannot convert source, because it is null");
130 return Optional.empty();
133 Class<?> type = source.getClass();
135 if (source instanceof Collection) {
136 final Iterator it = ((Collection) source).iterator();
143 if (Objects.isNull(next)) {
144 LOG.trace("Cannot convert {}, because it is empty collection", type);
145 return Optional.empty();
148 type = next.getClass();
151 Convertor convertor = null;
153 if (!convertors.containsKey(type)) {
154 boolean found = false;
156 for (Class<?> key : convertorKeys) {
157 if (key.isAssignableFrom(type)) {
158 convertor = convertors.get(key);
159 convertors.put(type, convertor);
160 LOG.debug("{} is now converted by {}", type, convertor);
167 LOG.error("Convertor for {} not found", type);
168 return Optional.empty();
172 if (Objects.isNull(convertor)) {
173 convertor = convertors.get(type);
176 final Object result = convertor.convert(source);
177 return Optional.of((TO) result);
181 * Lookup and use convertor by specified type, then converts source and returns converted result
183 * @param <FROM> the source type
184 * @param <TO> the result type
185 * @param <DATA> the data type
186 * @param source the source
187 * @param data convertor data
188 * @return the result (can be empty, if no convertor was found)
190 @SuppressWarnings("unchecked")
191 public <FROM, TO, DATA extends ConvertorData> Optional<TO> convert(final FROM source, final DATA data) {
192 if (Objects.isNull(source)) {
193 LOG.trace("Cannot convert source, because it is null");
194 return Optional.empty();
197 Class<?> type = source.getClass();
199 if (source instanceof Collection) {
200 final Iterator it = ((Collection) source).iterator();
207 if (Objects.isNull(next)) {
208 LOG.trace("Cannot convert {}, because it is empty collection", type);
209 return Optional.empty();
212 type = next.getClass();
215 ParametrizedConvertor convertor = null;
217 if (!parametrizedConvertors.containsKey(type)) {
218 boolean found = false;
220 for (Class<?> key : parametrizedConvertorKeys) {
221 if (key.isAssignableFrom(type)) {
222 convertor = parametrizedConvertors.get(key);
223 parametrizedConvertors.put(type, convertor);
224 LOG.debug("{} is now converted by {}", type, convertor);
231 LOG.error("Convertor for {} not found", type);
232 return Optional.empty();
236 if (Objects.isNull(convertor)) {
237 convertor = parametrizedConvertors.get(type);
240 final Object result = convertor.convert(source, data);
241 return Optional.of((TO) result);