/* * Copyright (c) 2016 Pantheon Technologies s.r.o. and others. All rights reserved. * * This program and the accompanying materials are made available under the * terms of the Eclipse Public License v1.0 which accompanies this distribution, * and is available at http://www.eclipse.org/legal/epl-v10.html */ package org.opendaylight.openflowplugin.impl.protocol.serialization.util; import com.google.common.collect.Ordering; import io.netty.buffer.ByteBuf; import java.util.List; import java.util.Optional; import org.opendaylight.openflowjava.protocol.api.extensibility.HeaderSerializer; import org.opendaylight.openflowjava.protocol.api.extensibility.OFSerializer; import org.opendaylight.openflowjava.protocol.api.extensibility.SerializerRegistry; import org.opendaylight.openflowjava.protocol.api.keys.MessageTypeKey; import org.opendaylight.openflowjava.protocol.impl.util.TypeKeyMakerFactory; import org.opendaylight.openflowplugin.extension.api.ConverterExtensionKey; import org.opendaylight.openflowplugin.extension.api.ConvertorActionToOFJava; import org.opendaylight.openflowplugin.extension.api.ConvertorToOFJava; import org.opendaylight.openflowplugin.extension.api.TypeVersionKey; import org.opendaylight.openflowplugin.extension.api.core.extension.ExtensionConverterProvider; import org.opendaylight.openflowplugin.openflow.md.core.sal.convertor.common.OrderComparator; import org.opendaylight.openflowplugin.openflow.md.core.session.OFSessionUtil; import org.opendaylight.yang.gen.v1.urn.opendaylight.action.types.rev131112.action.Action; import org.opendaylight.yang.gen.v1.urn.opendaylight.openflowplugin.extension.general.rev140714.ExtensionKey; import org.opendaylight.yang.gen.v1.urn.opendaylight.openflowplugin.extension.general.rev140714.GeneralExtensionGrouping; import org.slf4j.Logger; import org.slf4j.LoggerFactory; /** * Utility class for action serialization */ public class ActionUtil { private static final Logger LOG = LoggerFactory.getLogger(ActionUtil.class); private static final Ordering<org.opendaylight.yang.gen.v1.urn.opendaylight.action.types.rev131112.action.list.Action> ACTION_ORDERING = Ordering.from(OrderComparator.<org.opendaylight.yang.gen.v1.urn.opendaylight.action.types.rev131112.action.list.Action>build()); /** * Sort actions based on order * @param actions actions * @return sorted copy of actions */ 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) { return ACTION_ORDERING.sortedCopy(actions); } /** * Serialize OpenFlow action, using extension converter if available * TODO: Remove also extension converters * * @param action OpenFlowPlugin action * @param version OpenFlow version * @param registry serializer registry * @param outBuffer output buffer */ @SuppressWarnings("unchecked") public static void writeAction(Action action, short version, SerializerRegistry registry, ByteBuf outBuffer) { try { Optional.ofNullable(OFSessionUtil.getExtensionConvertorProvider()) .flatMap(provider -> (GeneralExtensionGrouping.class.isInstance(action) ? convertExtensionGrouping(provider, action, version) : convertGenericAction(provider, action, version)) .map(ofjAction -> { final OFSerializer<org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.common .action.rev150203.actions.grouping.Action> serializer = registry .getSerializer(TypeKeyMakerFactory.createActionKeyMaker(version) .make(ofjAction)); serializer.serialize(ofjAction, outBuffer); return action; }) ).orElseGet(() -> { final OFSerializer<Action> serializer = registry.getSerializer( new MessageTypeKey<>( version, (Class<? extends Action>) action.getImplementedInterface())); serializer.serialize(action, outBuffer); return action; }); } catch (final IllegalStateException | ClassCastException e) { LOG.warn("Serializer for action {} for version {} not found.", action.getImplementedInterface(), version); } } /** * Serialize OpenFlow action header, using extension converter if available * TODO: Remove also extension converters * * @param action OpenFlowPlugin action * @param version OpenFlow version * @param registry serializer registry * @param outBuffer output buffer */ @SuppressWarnings("unchecked") public static void writeActionHeader(Action action, short version, SerializerRegistry registry, ByteBuf outBuffer) { try { Optional.ofNullable(OFSessionUtil.getExtensionConvertorProvider()) .flatMap(provider -> (GeneralExtensionGrouping.class.isInstance(action) ? convertExtensionGrouping(provider, action, version) : convertGenericAction(provider, action, version)) .map(ofjAction -> { final HeaderSerializer<org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.common .action.rev150203.actions.grouping.Action> serializer = registry .getSerializer(TypeKeyMakerFactory.createActionKeyMaker(version) .make(ofjAction)); serializer.serializeHeader(ofjAction, outBuffer); return action; }) ).orElseGet(() -> { final HeaderSerializer<Action> serializer = registry.getSerializer( new MessageTypeKey<>( version, (Class<? extends Action>) action.getImplementedInterface())); serializer.serializeHeader(action, outBuffer); return action; }); } catch (final IllegalStateException | ClassCastException e) { LOG.warn("Header Serializer for action {} for version {} not found.", action.getImplementedInterface(), version); } } /** * Try to convert action that implements #{@link org.opendaylight.yang.gen.v1.urn.opendaylight.openflowplugin.extension.general.rev140714.GeneralExtensionGrouping} * to OpenFlowJava action * * @param provider extension converter provider * @param action OpenFlowPlugin action * @param version OpenFlow version * @return optional OpenFlowJava action */ private static Optional<org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.common.action.rev150203.actions .grouping.Action> convertExtensionGrouping(final ExtensionConverterProvider provider, final Action action, final short version) { final ConverterExtensionKey<? extends ExtensionKey> key = new ConverterExtensionKey<>(GeneralExtensionGrouping.class.cast(action).getExtensionKey(), version); final ConvertorToOFJava<org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.common.action.rev150203.actions .grouping.Action> converter = provider.getConverter(key); return Optional.ofNullable(converter).map(c -> c.convert(((GeneralExtensionGrouping) action).getExtension())); } /** * Try to convert generic OpenFlowPlugin action to OpenFlowJava action * * @param provider extension converter provider * @param action OpenFlowPlugin action * @param version OpenFlow version * @return optional OpenFlowJava action */ @SuppressWarnings("unchecked") private static Optional<org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.common.action.rev150203.actions .grouping.Action> convertGenericAction(final ExtensionConverterProvider provider, final Action action, final short version) { final TypeVersionKey<Action> key = new TypeVersionKey<>((Class<? extends Action>) action.getImplementedInterface(), version); final ConvertorActionToOFJava<Action, org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.common.action .rev150203.actions.grouping.Action> converter = provider.getConverter(key); return Optional.ofNullable(converter).map(c -> c.convert(action)); } }