Add multipart request message serializers
[openflowplugin.git] / openflowplugin-impl / src / main / java / org / opendaylight / openflowplugin / impl / protocol / serialization / util / ActionUtil.java
1 /*
2  * Copyright (c) 2016 Pantheon Technologies s.r.o. 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.impl.protocol.serialization.util;
10
11 import com.google.common.collect.Ordering;
12 import io.netty.buffer.ByteBuf;
13 import java.util.List;
14 import java.util.Optional;
15 import org.opendaylight.openflowjava.protocol.api.extensibility.HeaderSerializer;
16 import org.opendaylight.openflowjava.protocol.api.extensibility.OFSerializer;
17 import org.opendaylight.openflowjava.protocol.api.extensibility.SerializerRegistry;
18 import org.opendaylight.openflowjava.protocol.api.keys.MessageTypeKey;
19 import org.opendaylight.openflowjava.protocol.impl.util.TypeKeyMakerFactory;
20 import org.opendaylight.openflowplugin.extension.api.ConverterExtensionKey;
21 import org.opendaylight.openflowplugin.extension.api.ConvertorActionToOFJava;
22 import org.opendaylight.openflowplugin.extension.api.ConvertorToOFJava;
23 import org.opendaylight.openflowplugin.extension.api.TypeVersionKey;
24 import org.opendaylight.openflowplugin.extension.api.core.extension.ExtensionConverterProvider;
25 import org.opendaylight.openflowplugin.openflow.md.core.sal.convertor.common.OrderComparator;
26 import org.opendaylight.openflowplugin.openflow.md.core.session.OFSessionUtil;
27 import org.opendaylight.yang.gen.v1.urn.opendaylight.action.types.rev131112.action.Action;
28 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflowplugin.extension.general.rev140714.ExtensionKey;
29 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflowplugin.extension.general.rev140714.GeneralExtensionGrouping;
30 import org.slf4j.Logger;
31 import org.slf4j.LoggerFactory;
32
33 /**
34  * Utility class for action serialization
35  */
36 public class ActionUtil {
37     private static final Logger LOG = LoggerFactory.getLogger(ActionUtil.class);
38
39     private static final Ordering<org.opendaylight.yang.gen.v1.urn.opendaylight.action.types.rev131112.action.list.Action> ACTION_ORDERING =
40             Ordering.from(OrderComparator.<org.opendaylight.yang.gen.v1.urn.opendaylight.action.types.rev131112.action.list.Action>build());
41
42     /**
43      * Sort actions based on order
44      * @param actions actions
45      * @return sorted copy of actions
46      */
47     public static List<org.opendaylight.yang.gen.v1.urn.opendaylight.action.types.rev131112.action.list.Action> sortActions(final Iterable<org.opendaylight.yang.gen.v1.urn.opendaylight.action.types.rev131112.action.list.Action> actions) {
48         return ACTION_ORDERING.sortedCopy(actions);
49     }
50
51     /**
52      * Serialize OpenFlow action, using extension converter if available
53      * TODO: Remove also extension converters
54      *
55      * @param action    OpenFlowPlugin action
56      * @param version   OpenFlow version
57      * @param registry  serializer registry
58      * @param outBuffer output buffer
59      */
60     @SuppressWarnings("unchecked")
61     public static void writeAction(Action action, short version, SerializerRegistry registry, ByteBuf outBuffer) {
62         try {
63             Optional.ofNullable(OFSessionUtil.getExtensionConvertorProvider())
64                 .flatMap(provider ->
65                     (GeneralExtensionGrouping.class.isInstance(action)
66                         ? convertExtensionGrouping(provider, action, version)
67                         : convertGenericAction(provider, action, version))
68                         .map(ofjAction -> {
69                             final OFSerializer<org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.common
70                                 .action.rev150203.actions.grouping.Action> serializer = registry
71                                 .getSerializer(TypeKeyMakerFactory.createActionKeyMaker(version)
72                                     .make(ofjAction));
73
74                             serializer.serialize(ofjAction, outBuffer);
75                             return action;
76                         })
77                 ).orElseGet(() -> {
78                 final OFSerializer<Action> serializer = registry.getSerializer(
79                     new MessageTypeKey<>(
80                         version, (Class<? extends Action>) action.getImplementedInterface()));
81
82                 serializer.serialize(action, outBuffer);
83                 return action;
84             });
85         } catch (final IllegalStateException | ClassCastException e) {
86             LOG.warn("Serializer for action {} for version {} not found.", action.getImplementedInterface(), version);
87         }
88     }
89
90     /**
91      * Serialize OpenFlow action header, using extension converter if available
92      * TODO: Remove also extension converters
93      *
94      * @param action    OpenFlowPlugin action
95      * @param version   OpenFlow version
96      * @param registry  serializer registry
97      * @param outBuffer output buffer
98      */
99     @SuppressWarnings("unchecked")
100     public static void writeActionHeader(Action action, short version, SerializerRegistry registry, ByteBuf outBuffer) {
101         try {
102             Optional.ofNullable(OFSessionUtil.getExtensionConvertorProvider())
103                 .flatMap(provider ->
104                     (GeneralExtensionGrouping.class.isInstance(action)
105                         ? convertExtensionGrouping(provider, action, version)
106                         : convertGenericAction(provider, action, version))
107                         .map(ofjAction -> {
108                             final HeaderSerializer<org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.common
109                                 .action.rev150203.actions.grouping.Action> serializer = registry
110                                 .getSerializer(TypeKeyMakerFactory.createActionKeyMaker(version)
111                                     .make(ofjAction));
112
113                             serializer.serializeHeader(ofjAction, outBuffer);
114                             return action;
115                         })
116                 ).orElseGet(() -> {
117                 final HeaderSerializer<Action> serializer = registry.getSerializer(
118                     new MessageTypeKey<>(
119                         version, (Class<? extends Action>) action.getImplementedInterface()));
120
121                 serializer.serializeHeader(action, outBuffer);
122                 return action;
123             });
124         } catch (final IllegalStateException | ClassCastException e) {
125             LOG.warn("Header Serializer for action {} for version {} not found.", action.getImplementedInterface(), version);
126         }
127     }
128
129     /**
130      * Try to convert action that implements #{@link org.opendaylight.yang.gen.v1.urn.opendaylight.openflowplugin.extension.general.rev140714.GeneralExtensionGrouping}
131      * to OpenFlowJava action
132      *
133      * @param provider extension converter provider
134      * @param action OpenFlowPlugin action
135      * @param version OpenFlow version
136      * @return optional OpenFlowJava action
137      */
138     private static Optional<org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.common.action.rev150203.actions
139             .grouping.Action> convertExtensionGrouping(final ExtensionConverterProvider provider,
140                                                        final Action action,
141                                                        final short version) {
142         final ConverterExtensionKey<? extends ExtensionKey> key =
143                 new ConverterExtensionKey<>(GeneralExtensionGrouping.class.cast(action).getExtensionKey(), version);
144
145         final ConvertorToOFJava<org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.common.action.rev150203.actions
146                 .grouping.Action> converter = provider.getConverter(key);
147
148         return Optional.ofNullable(converter).map(c -> c.convert(((GeneralExtensionGrouping) action).getExtension()));
149     }
150
151     /**
152      * Try to convert generic OpenFlowPlugin action to OpenFlowJava action
153      *
154      * @param provider extension converter provider
155      * @param action OpenFlowPlugin action
156      * @param version OpenFlow version
157      * @return optional OpenFlowJava action
158      */
159     @SuppressWarnings("unchecked")
160     private static Optional<org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.common.action.rev150203.actions
161             .grouping.Action> convertGenericAction(final ExtensionConverterProvider provider,
162                                                    final Action action,
163                                                    final short version) {
164
165         final TypeVersionKey<Action> key =
166                 new TypeVersionKey<>((Class<? extends Action>) action.getImplementedInterface(), version);
167
168         final ConvertorActionToOFJava<Action, org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.common.action
169                 .rev150203.actions.grouping.Action> converter = provider.getConverter(key);
170
171
172         return Optional.ofNullable(converter).map(c -> c.convert(action));
173
174     }
175 }