/*
 * Copyright 2016-present Open Networking Foundation
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package org.onosproject.segmentrouting.config;

import com.fasterxml.jackson.databind.JsonNode;
import com.fasterxml.jackson.databind.node.JsonNodeFactory;
import com.fasterxml.jackson.databind.node.ObjectNode;
import com.google.common.collect.ImmutableSet;
import org.apache.felix.scr.annotations.Reference;
import org.apache.felix.scr.annotations.ReferenceCardinality;
import org.onlab.packet.MplsLabel;
import org.onlab.packet.VlanId;
import org.onosproject.cli.AbstractShellCommand;
import org.onosproject.core.ApplicationId;
import org.onosproject.net.ConnectPoint;
import org.onosproject.net.config.Config;
import org.onosproject.net.device.DeviceService;
import org.onosproject.net.intf.InterfaceService;
import org.onosproject.segmentrouting.pwaas.DefaultL2Tunnel;
import org.onosproject.segmentrouting.pwaas.DefaultL2TunnelDescription;
import org.onosproject.segmentrouting.pwaas.DefaultL2TunnelPolicy;
import org.onosproject.segmentrouting.pwaas.L2Mode;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.util.HashMap;
import java.util.HashSet;
import java.util.Map;
import java.util.Set;
import java.util.stream.Collectors;

/**
 * App configuration object for Pwaas.
 */
public class PwaasConfig extends Config<ApplicationId> {

    @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
    public DeviceService deviceService;

    @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
    public InterfaceService intfService;

    private static Logger log = LoggerFactory
            .getLogger(PwaasConfig.class);

    private static final String SRC_CP = "cP1";
    private static final String DST_CP = "cP2";
    private static final String SRC_OUTER_TAG = "cP1OuterTag";
    private static final String DST_OUTER_TAG = "cP2OuterTag";
    private static final String SRC_INNER_TAG = "cP1InnerTag";
    private static final String DST_INNER_TAG = "cP2InnerTag";
    private static final String MODE = "mode";
    private static final String SD_TAG = "sdTag";
    private static final String PW_LABEL = "pwLabel";

    public PwaasConfig(DeviceService devS, InterfaceService intfS) {

        super();

        deviceService = devS;
        intfService = intfS;
    }

    public PwaasConfig() {

        super();

        deviceService = AbstractShellCommand.get(DeviceService.class);
        intfService = AbstractShellCommand.get(InterfaceService.class);
    }
    /**
     * Error message for missing parameters.
     */
    private static final String MISSING_PARAMS = "Missing parameters in pseudo wire description";

    /**
     * Error message for invalid l2 mode.
     */
    private static final String INVALID_L2_MODE = "Invalid pseudo wire mode";

    /**
     * Error message for invalid VLAN.
     */
    private static final String INVALID_VLAN = "Vlan should be either int or */-";

    /**
     * Error message for invalid PW label.
     */
    private static final String INVALID_PW_LABEL = "Pseudowire label should be an integer";

    /**
     * Verify if the pwaas configuration block is valid.
     *
     * Here we try to ensure that the provided pseudowires will get instantiated
     * correctly in the network. We also check for any collisions with already used
     * interfaces and also between different pseudowires. Most of the restrictions stem
     * from the fact that all vlan matching is done in table 10 of ofdpa.
     *
     * @return true, if the configuration block is valid.
     *         False otherwise.
     */
    @Override
    public boolean isValid() {

        Set<DefaultL2TunnelDescription> pseudowires;
        try {
            pseudowires = getPwIds().stream()
                    .map(this::getPwDescription)
                    .collect(Collectors.toSet());

            // check semantics now and return
            return configurationValidity(pseudowires);

        } catch (IllegalArgumentException e) {
            log.warn("{}", e.getMessage());
            return false;
        }
    }

    /**
     * Helper method to verify if the tunnel is whether or not
     * supported.
     *
     * @param l2Tunnel the tunnel to verify
     * @return the result of the verification
     */
    private void verifyTunnel(DefaultL2Tunnel l2Tunnel) {

        // Service delimiting tag not supported yet.
        if (!l2Tunnel.sdTag().equals(VlanId.NONE)) {
            throw new IllegalArgumentException(String.format("Service delimiting tag not supported yet for " +
                                                             "pseudowire %d.", l2Tunnel.tunnelId()));
        }

        // Tag mode not supported yet.
        if (l2Tunnel.pwMode() == L2Mode.TAGGED) {
            throw new IllegalArgumentException(String.format("Tagged mode not supported yet for pseudowire %d.",
                                                                            l2Tunnel.tunnelId()));
        }

        // Raw mode without service delimiting tag
        // is the only mode supported for now.
    }

    /**
     * Helper method to verify if the policy is whether or not
     * supported and if policy will be successfully instantiated in the
     * network.
     *
     * @param ingressInner the ingress inner tag
     * @param ingressOuter the ingress outer tag
     * @param egressInner the egress inner tag
     * @param egressOuter the egress outer tag
     * @return the result of verification
     */
    private void verifyPolicy(ConnectPoint cP1,
                              ConnectPoint cP2,
                              VlanId ingressInner,
                              VlanId ingressOuter,
                              VlanId egressInner,
                              VlanId egressOuter,
                              Long tunnelId) {

        if (cP1.deviceId().equals(cP2.deviceId())) {
            throw new IllegalArgumentException(String.format("Pseudowire connection points can not reside in the " +
                                                             "same node, in pseudowire %d.", tunnelId));
        }

        // We can have multiple tags, all of them can be NONE,
        // indicating untagged traffic, however, the outer tag can
        // not have value if the inner tag is None
        if (ingressInner.equals(VlanId.NONE) && !ingressOuter.equals(VlanId.NONE)) {
            throw new IllegalArgumentException(String.format("Inner tag should not be empty when " +
                                                             "outer tag is set for pseudowire %d for cP1.",
                                                              tunnelId));
        }

        if (egressInner.equals(VlanId.NONE) && !egressOuter.equals(VlanId.NONE)) {
            throw new IllegalArgumentException(String.valueOf(String.format("Inner tag should not be empty when" +
                                                                            " outer tag is set for pseudowire %d " +
                                                                            "for cP2.", tunnelId)));
        }

        if (ingressInner.equals(VlanId.ANY) ||
                ingressOuter.equals(VlanId.ANY) ||
                egressInner.equals(VlanId.ANY) ||
                egressOuter.equals(VlanId.ANY)) {
            throw new IllegalArgumentException(String.valueOf(String.format("Wildcard VLAN matching not yet " +
                                                                            "supported for pseudowire %d.",
                                                                            tunnelId)));
        }

        if (((!ingressOuter.equals(VlanId.NONE) && !ingressInner.equals(VlanId.NONE)) &&
                (egressOuter.equals(VlanId.NONE) && egressInner.equals(VlanId.NONE)))
                || ((ingressOuter.equals(VlanId.NONE) && ingressInner.equals(VlanId.NONE)) &&
                (!egressOuter.equals(VlanId.NONE) && !egressInner.equals(VlanId.NONE)))) {
            throw new IllegalArgumentException(String.valueOf(String.format("Support for double tag <-> untag is not" +
                                                                                    "supported for pseudowire %d.",
                                                                            tunnelId)));
        }
        if ((!ingressInner.equals(VlanId.NONE) &&
                ingressOuter.equals(VlanId.NONE) &&
                !egressOuter.equals(VlanId.NONE))
           || (egressOuter.equals(VlanId.NONE) &&
                !egressInner.equals(VlanId.NONE) &&
                !ingressOuter.equals(VlanId.NONE))) {
                throw new IllegalArgumentException(String.valueOf(String.format("Support for double-tag<->" +
                                                                                "single-tag is not supported" +
                                                                                " for pseudowire %d.", tunnelId)));
        }

        if ((ingressInner.equals(VlanId.NONE) && !egressInner.equals(VlanId.NONE))
                || (!ingressInner.equals(VlanId.NONE) && egressInner.equals(VlanId.NONE))) {
            throw new IllegalArgumentException(String.valueOf(String.format("single-tag <-> untag is not supported" +
                                                                            " for pseudowire %d.", tunnelId)));
        }


        if (!ingressInner.equals(egressInner) && !ingressOuter.equals(egressOuter)) {
            throw new IllegalArgumentException(String.valueOf(String.format("We do not support changing both tags " +
                                                                             "in double tagged pws, only the outer," +
                                                                             " for pseudowire %d.", tunnelId)));
        }

        // check if cp1 and port of cp1 exist
        if (deviceService.getDevice(cP1.deviceId()) == null) {
            throw new IllegalArgumentException(String.valueOf(String.format("cP1 device %s does not exist for" +
                                                                            " pseudowire %d.", cP1.deviceId(),
                                                                            tunnelId)));
        }

        if (deviceService.getPort(cP1) == null) {
            throw new IllegalArgumentException(String.valueOf(String.format("Port %s for cP1 device %s does not" +
                                                                            " exist for pseudowire %d.", cP1.port(),
                                                                            cP1.deviceId(), tunnelId)));
        }

        // check if cp2 and port of cp2 exist
        if (deviceService.getDevice(cP2.deviceId()) == null) {
            throw new IllegalArgumentException(String.valueOf(String.format("cP2 device %s does not exist for" +
                                                                            " pseudowire %d.", cP2.deviceId(),
                                                                            tunnelId)));
        }

        if (deviceService.getPort(cP2) == null) {
            throw new IllegalArgumentException(String.valueOf(String.format("Port %s for cP2 device %s does " +
                                                                            "not exist for pseudowire %d.",
                                                                            cP2.port(), cP2.deviceId(), tunnelId)));
        }
    }

    /**
     * Verifies that the pseudowires will not conflict with each other.
     *
     * Further, check if vlans for connect points are already used.
     *
     * @param tunnel Tunnel for pw
     * @param policy Policy for pw
     * @param labelSet Label set used so far with this configuration
     * @param vlanSet Vlan set used with this configuration
     * @param tunnelSet Tunnel set used with this configuration
     */
    private void verifyGlobalValidity(DefaultL2Tunnel tunnel,
                                      DefaultL2TunnelPolicy policy,
                                      Set<MplsLabel> labelSet,
                                      Map<ConnectPoint, Set<VlanId>> vlanSet,
                                      Set<Long> tunnelSet) {

        if (tunnelSet.contains(tunnel.tunnelId())) {
            throw new IllegalArgumentException(String.valueOf(String.format("Tunnel Id %d already used by" +
                                                                           " another pseudowire, in " +
                                                                           "pseudowire %d!", tunnel.tunnelId(),
                                                                            tunnel.tunnelId())));
        }
        tunnelSet.add(tunnel.tunnelId());

        // check if tunnel id is used again
        ConnectPoint cP1 = policy.cP1();
        ConnectPoint cP2 = policy.cP2();

        // insert cps to hashmap if this is the first time seen
        if (!vlanSet.containsKey(cP1)) {
            vlanSet.put(cP1, new HashSet<VlanId>());
        }
        if (!vlanSet.containsKey(cP2)) {
            vlanSet.put(cP2, new HashSet<VlanId>());
        }

        // if single tagged or untagged vlan is the inner
        // if double tagged vlan is the outer
        VlanId vlanToCheckCP1;
        if (policy.cP1OuterTag().equals(VlanId.NONE)) {
            vlanToCheckCP1 = policy.cP1InnerTag();
        } else {
            vlanToCheckCP1 = policy.cP1OuterTag();
        }

        VlanId vlanToCheckCP2;
        if (policy.cP2OuterTag().equals(VlanId.NONE)) {
            vlanToCheckCP2 = policy.cP2InnerTag();
        } else {
            vlanToCheckCP2 = policy.cP2OuterTag();
        }

        if (labelSet.contains(tunnel.pwLabel())) {
            throw new IllegalArgumentException(String.valueOf(String.format("Label %s already used by another" +
                                                                            " pseudowire, in pseudowire %d!",
                                                                            tunnel.pwLabel(), tunnel.tunnelId())));
        }
        labelSet.add(tunnel.pwLabel());

        if (vlanSet.get(cP1).contains(vlanToCheckCP1)) {
            throw new IllegalArgumentException(String.valueOf(String.format("Vlan '%s' for cP1 %s already used " +
                                                                            "by another pseudowire, in pseudowire" +
                                                                            " %d!", vlanToCheckCP1,  cP1,
                                                                            tunnel.tunnelId())));
        }
        vlanSet.get(cP1).add(vlanToCheckCP1);

        if (vlanSet.get(cP2).contains(vlanToCheckCP2)) {
            throw new IllegalArgumentException(String.valueOf(String.format("Vlan '%s' for cP2 %s already used" +
                                                                            " by another pseudowire, in" +
                                                                            " pseudowire %d!", vlanToCheckCP2, cP2,
                                                                            tunnel.tunnelId())));
        }
        vlanSet.get(cP2).add(vlanToCheckCP2);

        // check that vlans for the connect points are not used
        intfService.getInterfacesByPort(cP1).stream()
                .forEach(intf -> {

                    // check if tagged pw affects tagged interface
                    if (intf.vlanTagged().contains(vlanToCheckCP1)) {
                        throw new IllegalArgumentException(String.valueOf(String.format("Vlan '%s' for cP1 %s already" +
                                                                                        " used for this interface, in" +
                                                                                        " pseudowire %d!",
                                                                                        vlanToCheckCP1, cP1,
                                                                                        tunnel.tunnelId())));
                    }

                    // if vlanNative != null this interface is configured with untagged traffic also
                    // check if it collides with untagged interface
                    if ((intf.vlanNative() != null) && vlanToCheckCP1.equals(VlanId.NONE)) {
                        throw new IllegalArgumentException(String.valueOf(String.format("Untagged traffic for cP1 " +
                                                                                         "%s already used for this " +
                                                                                         "interface, in pseudowire " +
                                                                                         "%d!", cP1,
                                                                                         tunnel.tunnelId())));
                    }

                    // if vlanUntagged != null this interface is configured only with untagged traffic
                    // check if it collides with untagged interface
                    if ((intf.vlanUntagged() != null) && vlanToCheckCP1.equals(VlanId.NONE)) {
                        throw new IllegalArgumentException(String.valueOf(String.format("Untagged traffic for " +
                                                                                         "cP1 %s already" +
                                                                                         " used for this interface," +
                                                                                         " in pseudowire %d!",
                                                                                         cP1, tunnel.tunnelId())));
                    }
                });

        intfService.getInterfacesByPort(cP2).stream()
                .forEach(intf -> {
                    if (intf.vlanTagged().contains(vlanToCheckCP2)) {
                        throw new IllegalArgumentException(String.valueOf(String.format("Vlan '%s' for cP2 %s already" +
                                                                                        " used for  this interface, " +
                                                                                        "in pseudowire %d!",
                                                                                        vlanToCheckCP2, cP2,
                                                                                        tunnel.tunnelId())));
                    }

                    // if vlanNative != null this interface is configured with untagged traffic also
                    // check if it collides with untagged interface
                    if ((intf.vlanNative() != null) && vlanToCheckCP2.equals(VlanId.NONE)) {
                        throw new IllegalArgumentException(String.valueOf(String.format("Untagged traffic for cP2 %s " +
                                                                                        "already used for this" +
                                                                                        " interface, " +
                                                                                        "in pseudowire %d!",
                                                                                        cP2, tunnel.tunnelId())));
                    }

                    // if vlanUntagged != null this interface is configured only with untagged traffic
                    // check if it collides with untagged interface
                    if ((intf.vlanUntagged() != null) && vlanToCheckCP2.equals(VlanId.NONE)) {
                        throw new IllegalArgumentException(String.valueOf(String.format("Untagged traffic for cP2 %s" +
                                                                                        " already" +
                                                                                        " used for this interface, " +
                                                                                        "in pseudowire %d!",
                                                                                        cP2, tunnel.tunnelId())));
                    }
                });

    }

    /**
     * Helper method to verify the integrity of the pseudo wire.
     *
     * @param l2TunnelDescription the pseudo wire description
     * @return the result of the check
     */
    private void verifyPseudoWire(DefaultL2TunnelDescription l2TunnelDescription,
                                  Set<MplsLabel> labelSet,
                                  Map<ConnectPoint, Set<VlanId>> vlanset,
                                  Set<Long> tunnelSet) {

        DefaultL2Tunnel l2Tunnel = l2TunnelDescription.l2Tunnel();
        DefaultL2TunnelPolicy l2TunnelPolicy = l2TunnelDescription.l2TunnelPolicy();

        verifyTunnel(l2Tunnel);

        verifyPolicy(
                l2TunnelPolicy.cP1(),
                l2TunnelPolicy.cP2(),
                l2TunnelPolicy.cP1InnerTag(),
                l2TunnelPolicy.cP1OuterTag(),
                l2TunnelPolicy.cP2InnerTag(),
                l2TunnelPolicy.cP2OuterTag(),
                l2Tunnel.tunnelId()
        );

        verifyGlobalValidity(l2Tunnel,
                             l2TunnelPolicy,
                             labelSet,
                             vlanset,
                             tunnelSet);

    }

    /**
     * Checks if the configured pseudowires will create problems in the network.
     * If yes, then no pseudowires is deployed from this configuration.
     *
     * @param pseudowires Set of pseudowries to validate
     * @return returns true if everything goes well.
     */
    public boolean configurationValidity(Set<DefaultL2TunnelDescription> pseudowires) {

        // structures to keep pw information
        // in order to see if instantiating them will create
        // problems
        Set<Long> tunIds = new HashSet<>();
        Set<MplsLabel> labelsUsed = new HashSet<>();
        Map<ConnectPoint, Set<VlanId>> vlanIds = new HashMap<>();

        // check that pseudowires can be instantiated in the network
        // we try to guarantee that all the pws will work before
        // instantiating any of them
        for (DefaultL2TunnelDescription pw : pseudowires) {
            verifyPseudoWire(pw, labelsUsed, vlanIds, tunIds);
        }

        return true;
    }

    /**
     * Returns all pseudo wire keys.
     *
     * @return all keys (tunnels id)
     * @throws IllegalArgumentException if wrong format
     */
    public Set<Long> getPwIds() {
        ImmutableSet.Builder<Long> builder = ImmutableSet.builder();
        object.fields().forEachRemaining(entry -> {
            Long tunnelId = Long.parseLong(entry.getKey());
            builder.add(tunnelId);
        });
        return builder.build();
    }

    /**
     * Parses a vlan as a string. Returns the VlanId if
     * provided String can be parsed as an integer or is '' / '*'
     *
     * @param vlan string as read from configuration
     * @return VlanId
     * @throws IllegalArgumentException if wrong format of vlan
     */
    public VlanId parseVlan(String vlan) {

        if (vlan.equals("*") || vlan.equals("Any")) {
            return VlanId.vlanId("Any");
        } else if (vlan.equals("") || vlan.equals("None")) {
            return VlanId.vlanId("None");
        } else {
            try {
                VlanId newVlan = VlanId.vlanId(vlan);
                return newVlan;
            } catch (IllegalArgumentException e) {
                throw new IllegalArgumentException(INVALID_VLAN);
            }
        }
    }

    /**
     *
     * @param mode RAW or TAGGED
     * @return the L2Mode if input is correct
     * @throws  IllegalArgumentException if not supported mode
     */
    public L2Mode parseMode(String mode) {

        if (!mode.equals("RAW") && !mode.equals("TAGGED")) {
            throw  new IllegalArgumentException(INVALID_L2_MODE);
        }

        return L2Mode.valueOf(mode);
    }

    /**
     *
     * @param label the mpls label of the pseudowire
     * @return the MplsLabel
     * @throws IllegalArgumentException if label is invalid
     */
    public MplsLabel parsePWLabel(String label) {

        try {
            MplsLabel pwLabel = MplsLabel.mplsLabel(label);
            return pwLabel;
        } catch (Exception e) {
            throw new IllegalArgumentException(INVALID_PW_LABEL);
        }
    }

    /**
     * Returns pw description of given pseudo wire id.
     *
     * @param tunnelId pseudo wire key
     * @return set of l2 tunnel descriptions
     * @throws IllegalArgumentException if wrong format
     */
    public DefaultL2TunnelDescription getPwDescription(Long tunnelId) {
        JsonNode pwDescription = object.get(tunnelId.toString());
        if (!hasFields((ObjectNode) pwDescription,
                      SRC_CP, SRC_INNER_TAG, SRC_OUTER_TAG,
                      DST_CP, DST_INNER_TAG, DST_OUTER_TAG,
                      MODE, SD_TAG, PW_LABEL)) {
            throw new IllegalArgumentException(MISSING_PARAMS);
        }
        String tempString;

        tempString = pwDescription.get(SRC_CP).asText();
        ConnectPoint srcCp = ConnectPoint.deviceConnectPoint(tempString);

        tempString = pwDescription.get(DST_CP).asText();
        ConnectPoint dstCp = ConnectPoint.deviceConnectPoint(tempString);

        tempString = pwDescription.get(SRC_INNER_TAG).asText();
        VlanId srcInnerTag = parseVlan(tempString);

        tempString = pwDescription.get(SRC_OUTER_TAG).asText();
        VlanId srcOuterTag = parseVlan(tempString);

        tempString = pwDescription.get(DST_INNER_TAG).asText();
        VlanId dstInnerTag = parseVlan(tempString);

        tempString = pwDescription.get(DST_OUTER_TAG).asText();
        VlanId dstOuterTag = parseVlan(tempString);

        tempString = pwDescription.get(MODE).asText();
        L2Mode l2Mode = parseMode(tempString);

        tempString = pwDescription.get(SD_TAG).asText();
        VlanId sdTag = parseVlan(tempString);

        tempString = pwDescription.get(PW_LABEL).asText();
        MplsLabel pwLabel = parsePWLabel(tempString);

        DefaultL2Tunnel l2Tunnel = new DefaultL2Tunnel(
                l2Mode,
                sdTag,
                tunnelId,
                pwLabel
        );

        DefaultL2TunnelPolicy l2TunnelPolicy = new DefaultL2TunnelPolicy(
                tunnelId,
                srcCp,
                srcInnerTag,
                srcOuterTag,
                dstCp,
                dstInnerTag,
                dstOuterTag
        );

        return new DefaultL2TunnelDescription(l2Tunnel, l2TunnelPolicy);
    }

    /**
     * Removes a pseudowire from the configuration tree.
     * @param pwId Pseudowire id
     * @return null if pwId did not exist, or the object representing the
     * udpated configuration tree
     */
    public ObjectNode removePseudowire(String pwId) {

        JsonNode value = object.remove(pwId);
        if (value == null) {
            return (ObjectNode) value;
        } else {
            return object;
        }
    }

    /**
     * Adds a pseudowire to the configuration tree of pwwas. It also checks
     * if the configuration is valid, if not return null and does not add the node,
     * if yes return the new configuration. Caller will propagate update events.
     *
     * If the pseudowire already exists in the configuration it gets updated.
     *
     * @param tunnelId Id of tunnel
     * @param pwLabel PW label of tunnel
     * @param cP1 Connection point 1
     * @param cP1InnerVlan Inner vlan of cp1
     * @param cP1OuterVlan Outer vlan of cp2
     * @param cP2 Connection point 2
     * @param cP2InnerVlan Inner vlan of cp2
     * @param cP2OuterVlan Outer vlan of cp2
     * @param mode Mode for the pw
     * @param sdTag Service delimiting tag for the pw
     * @return The ObjectNode config if configuration is valid with the new pseudowire
     * or null.
     */
    public ObjectNode addPseudowire(String tunnelId, String pwLabel, String cP1,
                                    String cP1InnerVlan, String cP1OuterVlan, String cP2,
                                    String cP2InnerVlan, String cP2OuterVlan,
                                    String mode, String sdTag) {


        ObjectNode newPw = new ObjectNode(JsonNodeFactory.instance);

        // add fields for pseudowire
        newPw.put(SRC_CP, cP1);
        newPw.put(DST_CP, cP2);
        newPw.put(PW_LABEL, pwLabel);
        newPw.put(SRC_INNER_TAG, cP1InnerVlan);
        newPw.put(SRC_OUTER_TAG, cP1OuterVlan);
        newPw.put(DST_INNER_TAG, cP2InnerVlan);
        newPw.put(DST_OUTER_TAG, cP2OuterVlan);
        newPw.put(SD_TAG, sdTag);
        newPw.put(MODE, mode);

        object.set(tunnelId, newPw);

        if (!isValid()) {
            log.info("Pseudowire could not be created : {}");
            object.remove(tunnelId);
            return null;
        }

        return object;
    }
}
