Fix double translation of messages.
[openflowplugin.git] / openflowplugin / src / main / java / org / opendaylight / openflowplugin / openflow / md / queue / TicketProcessorFactory.java
1 /**
2  * Copyright (c) 2013 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 package org.opendaylight.openflowplugin.openflow.md.queue;
9
10 import java.util.ArrayList;
11 import java.util.Collection;
12 import java.util.List;
13 import java.util.Map;
14
15 import org.opendaylight.openflowplugin.openflow.md.core.ConnectionConductor;
16 import org.opendaylight.openflowplugin.openflow.md.core.IMDMessageTranslator;
17 import org.opendaylight.openflowplugin.openflow.md.core.SwitchConnectionDistinguisher;
18 import org.opendaylight.openflowplugin.openflow.md.core.TranslatorKey;
19 import org.slf4j.Logger;
20 import org.slf4j.LoggerFactory;
21
22 /**
23  * @param <IN>
24  * @param <OUT>
25  */
26 public class TicketProcessorFactory<IN, OUT> {
27
28     protected static final Logger LOG = LoggerFactory
29             .getLogger(TicketProcessorFactory.class);
30     
31     protected VersionExtractor<IN> versionExtractor;
32     protected RegisteredTypeExtractor<IN> registeredTypeExtractor;
33     protected Map<TranslatorKey, Collection<IMDMessageTranslator<IN, List<OUT>>>> translatorMapping;
34     protected MessageSpy<IN, OUT> spy;
35     
36     /**
37      * @param versionExtractor the versionExtractor to set
38      */
39     public void setVersionExtractor(VersionExtractor<IN> versionExtractor) {
40         this.versionExtractor = versionExtractor;
41     }
42
43     /**
44      * @param registeredTypeExtractor the registeredTypeExtractor to set
45      */
46     public void setRegisteredTypeExtractor(
47             RegisteredTypeExtractor<IN> registeredTypeExtractor) {
48         this.registeredTypeExtractor = registeredTypeExtractor;
49     }
50
51     /**
52      * @param translatorMapping the translatorMapping to set
53      */
54     public void setTranslatorMapping(
55             Map<TranslatorKey, Collection<IMDMessageTranslator<IN, List<OUT>>>> translatorMapping) {
56         this.translatorMapping = translatorMapping;
57     }
58
59     /**
60      * @param spy the spy to set
61      */
62     public void setSpy(MessageSpy<IN, OUT> spy) {
63         this.spy = spy;
64     }
65
66
67     /**
68      * @param ticket
69      * @return runnable ticket processor
70      */
71     public Runnable createProcessor(final Ticket<IN, OUT> ticket) {
72         
73         Runnable ticketProcessor = new Runnable() {
74             @Override
75             public void run() {
76                 LOG.debug("message received, type: {}", registeredTypeExtractor.extractRegisteredType(
77                         ticket.getMessage()).getSimpleName());
78                 List<OUT> translate;
79                 try {
80                     translate = translate();
81                     ticket.getResult().set(translate);
82                     // spying on result
83                     if (spy != null) {
84                         spy.spyIn(ticket.getMessage());
85                         spy.spyOut(ticket.getResult().get());
86                     }
87                 } catch (Exception e) {
88                     LOG.error("translation problem: {}", e.getMessage());
89                     ticket.getResult().setException(e);
90                 }
91                 LOG.debug("message processing done (type: {}, ticket: {})",
92                         registeredTypeExtractor.extractRegisteredType(ticket.getMessage()).getSimpleName(),
93                         System.identityHashCode(ticket));
94             }
95
96             /**
97              *
98              */
99             private List<OUT> translate() {
100                 List<OUT> result = new ArrayList<>();
101
102                 IN message = ticket.getMessage();
103                 Class<? extends IN> messageType = registeredTypeExtractor.extractRegisteredType(ticket.getMessage());
104                 ConnectionConductor conductor = ticket.getConductor();
105                 Collection<IMDMessageTranslator<IN, List<OUT>>> translators = null;
106                 LOG.debug("translating ticket: {}, ticket: {}", messageType.getSimpleName(), System.identityHashCode(ticket));
107
108                 Short version = versionExtractor.extractVersion(message);
109                 if (version == null) {
110                     throw new IllegalArgumentException("version is NULL");
111                 }
112                 TranslatorKey tKey = new TranslatorKey(version, messageType.getName());
113                 translators = translatorMapping.get(tKey);
114
115                 LOG.debug("translatorKey: {} + {}", version, messageType.getName());
116
117                 if (translators != null) {
118                     for (IMDMessageTranslator<IN, List<OUT>> translator : translators) {
119                         SwitchConnectionDistinguisher cookie = null;
120                         // Pass cookie only for PACKT_IN
121                         if (messageType.equals("PacketInMessage.class")) {
122                             cookie = conductor.getAuxiliaryKey();
123                         }
124                         List<OUT> translatorOutput = translator.translate(cookie, conductor.getSessionContext(), message);
125                         if(translatorOutput != null && !translatorOutput.isEmpty()) {
126                             result.addAll(translatorOutput);
127                         }
128                     }
129                 } else {
130                     LOG.warn("No translators for this message Type: {}", messageType);
131                 }
132                 return result;
133             }
134         };
135
136         return ticketProcessor;
137     }
138 }