Bug 5540 - ConvertorManager base
[openflowplugin.git] / openflowplugin / src / main / java / org / opendaylight / openflowplugin / openflow / md / core / sal / convertor / common / ConvertorProcessor.java
1 /*
2  * Copyright (c) 2016 Cisco Systems, Inc. and others.  All rights reserved.
3  *
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
7  */
8
9 package org.opendaylight.openflowplugin.openflow.md.core.sal.convertor.common;
10
11 import java.util.HashMap;
12 import java.util.Map;
13 import java.util.Optional;
14 import org.slf4j.Logger;
15 import org.slf4j.LoggerFactory;
16
17 /**
18  * Processes source and return result based on convertor cases added to this processor.
19  *
20  * @param <FROM> the source type
21  * @param <TO>   the result type
22  * @param <DATA> the type of convertor data
23  */
24 public class ConvertorProcessor<FROM, TO, DATA extends ConvertorData> {
25     private static final short OFP_VERSION_ALL = 0x00;
26     private static final Logger LOG = LoggerFactory.getLogger(ConvertorProcessor.class);
27
28     private final Map<InjectionKey, ConvertorCase<?, TO, DATA>> conversions = new HashMap<>();
29     private ConvertorCase<?, TO, DATA> defaultCase;
30
31     /**
32      * Add convertor processor case.
33      *
34      * @param processorCase the processor case
35      * @return the convertor processor
36      */
37     public ConvertorProcessor<FROM, TO, DATA> addCase(final ConvertorCase<?, TO, DATA> processorCase) {
38         if (processorCase.getSupportedVersions().isEmpty()) {
39             final InjectionKey key = new InjectionKey(OFP_VERSION_ALL, processorCase.getType());
40             conversions.putIfAbsent(key, processorCase);
41         } else {
42             for (short supportedVersion : processorCase.getSupportedVersions()) {
43                 final InjectionKey key = new InjectionKey(supportedVersion, processorCase.getType());
44                 conversions.putIfAbsent(key, processorCase);
45             }
46         }
47
48         return this;
49     }
50
51     /**
52      * Process source and return result based on convertor cases, or empty if no match is found.
53      *
54      * @param source the source
55      * @return the optional
56      */
57     public Optional<TO> process(final FROM source) {
58         return process(source, null);
59     }
60
61     /**
62      * Process source and return result based on convertor cases, or empty if no match is found.
63      *
64      * @param source the source
65      * @param data   the data
66      * @return the optional
67      */
68     public Optional<TO> process(final FROM source, final DATA data) {
69         Optional<TO> result = Optional.empty();
70         final short version = data != null ? data.getVersion() : OFP_VERSION_ALL;
71
72         if (source == null) {
73             LOG.trace("Failed to convert null for version {}", version);
74             return result;
75         }
76
77         Class<?> clazz = source.getClass();
78         final Class<?>[] interfaces = clazz.getInterfaces();
79
80         if (interfaces.length > 0) {
81             clazz = interfaces[0];
82         }
83
84         final InjectionKey key = new InjectionKey(version, clazz);
85         ConvertorCase<?, TO, DATA> rule = defaultCase;
86
87         if (conversions.containsKey(key)) {
88             rule = conversions.get(key);
89         }
90
91         if (rule != null) {
92             result = rule.processRaw(source, data);
93
94             if (rule.isErrorOnEmpty() && !result.isPresent()) {
95                 LOG.error("Failed to convert {} for version {}", clazz, version);
96             }
97         } else {
98             LOG.trace("Failed to convert {} for version {}", clazz, version);
99         }
100
101         return result;
102     }
103
104     /**
105      * Sets default case, what will be used when we do not find any matching convertor case for source.
106      *
107      * @param defaultCase the default case
108      * @return the default case
109      */
110     public ConvertorProcessor<FROM, TO, DATA> setDefaultCase(final ConvertorCase<?, TO, DATA> defaultCase) {
111         this.defaultCase = defaultCase;
112         return this;
113     }
114 }