/*
 * Copyright 2015-present Open Networking Laboratory
 *
 * 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.codec.impl;

import java.time.Duration;
import java.util.ArrayList;
import java.util.stream.IntStream;

import org.onlab.util.Bandwidth;
import org.onosproject.net.DeviceId;
import org.onosproject.net.Link;
import org.onosproject.net.intent.Constraint;
import org.onosproject.net.intent.constraint.AnnotationConstraint;
import org.onosproject.net.intent.constraint.AsymmetricPathConstraint;
import org.onosproject.net.intent.constraint.BandwidthConstraint;
import org.onosproject.net.intent.constraint.LatencyConstraint;
import org.onosproject.net.intent.constraint.LinkTypeConstraint;
import org.onosproject.net.intent.constraint.ObstacleConstraint;
import org.onosproject.net.intent.constraint.WaypointConstraint;

import com.fasterxml.jackson.databind.JsonNode;
import com.fasterxml.jackson.databind.node.ObjectNode;

import static org.onlab.util.Tools.nullIsIllegal;

/**
 * Constraint JSON decoder.
 */
public final class DecodeConstraintCodecHelper {
    private final ObjectNode json;

    /**
     * Constructs a constraint decoder.
     *
     * @param json object node to decode
     */
    public DecodeConstraintCodecHelper(ObjectNode json) {
        this.json = json;
    }

    /**
     * Decodes a link type constraint.
     *
     * @return link type constraint object.
     */
    private Constraint decodeLinkTypeConstraint() {
        boolean inclusive = nullIsIllegal(json.get(ConstraintCodec.INCLUSIVE),
                ConstraintCodec.INCLUSIVE + ConstraintCodec.MISSING_MEMBER_MESSAGE).asBoolean();

        JsonNode types = nullIsIllegal(json.get(ConstraintCodec.TYPES),
                ConstraintCodec.TYPES + ConstraintCodec.MISSING_MEMBER_MESSAGE);
        if (types.size() < 1) {
            throw new IllegalArgumentException(
                    "types array in link constraint must have at least one value");
        }

        ArrayList<Link.Type> typesEntries = new ArrayList<>(types.size());
        IntStream.range(0, types.size())
                .forEach(index ->
                        typesEntries.add(Link.Type.valueOf(types.get(index).asText())));

        return new LinkTypeConstraint(inclusive,
                typesEntries.toArray(new Link.Type[types.size()]));
    }

    /**
     * Decodes an annotation constraint.
     *
     * @return annotation constraint object.
     */
    private Constraint decodeAnnotationConstraint() {
        String key = nullIsIllegal(json.get(ConstraintCodec.KEY),
                ConstraintCodec.KEY + ConstraintCodec.MISSING_MEMBER_MESSAGE)
                .asText();
        double threshold = nullIsIllegal(json.get(ConstraintCodec.THRESHOLD),
                ConstraintCodec.THRESHOLD + ConstraintCodec.MISSING_MEMBER_MESSAGE)
                .asDouble();

        return new AnnotationConstraint(key, threshold);
    }

    /**
     * Decodes a latency constraint.
     *
     * @return latency constraint object.
     */
    private Constraint decodeLatencyConstraint() {
        long latencyMillis = nullIsIllegal(json.get(ConstraintCodec.LATENCY_MILLIS),
                ConstraintCodec.LATENCY_MILLIS + ConstraintCodec.MISSING_MEMBER_MESSAGE)
                .asLong();

        return new LatencyConstraint(Duration.ofMillis(latencyMillis));
    }

    /**
     * Decodes an obstacle constraint.
     *
     * @return obstacle constraint object.
     */
    private Constraint decodeObstacleConstraint() {
        JsonNode obstacles = nullIsIllegal(json.get(ConstraintCodec.OBSTACLES),
                ConstraintCodec.OBSTACLES + ConstraintCodec.MISSING_MEMBER_MESSAGE);
        if (obstacles.size() < 1) {
            throw new IllegalArgumentException(
                    "obstacles array in obstacles constraint must have at least one value");
        }

        ArrayList<DeviceId> obstacleEntries = new ArrayList<>(obstacles.size());
        IntStream.range(0, obstacles.size())
                .forEach(index ->
                        obstacleEntries.add(DeviceId.deviceId(obstacles.get(index).asText())));

        return new ObstacleConstraint(
                obstacleEntries.toArray(new DeviceId[obstacles.size()]));
    }

    /**
     * Decodes a waypoint constraint.
     *
     * @return waypoint constraint object.
     */
    private Constraint decodeWaypointConstraint() {
        JsonNode waypoints = nullIsIllegal(json.get(ConstraintCodec.WAYPOINTS),
                ConstraintCodec.WAYPOINTS + ConstraintCodec.MISSING_MEMBER_MESSAGE);
        if (waypoints.size() < 1) {
            throw new IllegalArgumentException(
                    "obstacles array in obstacles constraint must have at least one value");
        }

        ArrayList<DeviceId> waypointEntries = new ArrayList<>(waypoints.size());
        IntStream.range(0, waypoints.size())
                .forEach(index ->
                        waypointEntries.add(DeviceId.deviceId(waypoints.get(index).asText())));

        return new WaypointConstraint(
                waypointEntries.toArray(new DeviceId[waypoints.size()]));
    }

    /**
     * Decodes an asymmetric path constraint.
     *
     * @return asymmetric path constraint object.
     */
    private Constraint decodeAsymmetricPathConstraint() {
        return new AsymmetricPathConstraint();
    }

    /**
     * Decodes a bandwidth constraint.
     *
     * @return bandwidth constraint object.
     */
    private Constraint decodeBandwidthConstraint() {
        double bandwidth = nullIsIllegal(json.get(ConstraintCodec.BANDWIDTH),
                ConstraintCodec.BANDWIDTH + ConstraintCodec.MISSING_MEMBER_MESSAGE)
                .asDouble();

        return new BandwidthConstraint(Bandwidth.bps(bandwidth));
    }

    /**
     * Decodes the given constraint.
     *
     * @return constraint object.
     */
    public Constraint decode() {
        final String type = nullIsIllegal(json.get(ConstraintCodec.TYPE),
                ConstraintCodec.TYPE + ConstraintCodec.MISSING_MEMBER_MESSAGE)
                .asText();

        if (type.equals(BandwidthConstraint.class.getSimpleName())) {
            return decodeBandwidthConstraint();
        } else if (type.equals(LinkTypeConstraint.class.getSimpleName())) {
            return decodeLinkTypeConstraint();
        } else if (type.equals(AnnotationConstraint.class.getSimpleName())) {
            return decodeAnnotationConstraint();
        } else if (type.equals(LatencyConstraint.class.getSimpleName())) {
            return decodeLatencyConstraint();
        } else if (type.equals(ObstacleConstraint.class.getSimpleName())) {
            return decodeObstacleConstraint();
        } else if (type.equals(WaypointConstraint.class.getSimpleName())) {
            return decodeWaypointConstraint();
        } else if (type.equals(AsymmetricPathConstraint.class.getSimpleName())) {
            return decodeAsymmetricPathConstraint();
        } else if (type.equals(LinkTypeConstraint.class.getSimpleName())) {
            return decodeLinkTypeConstraint();
        } else if (type.equals(AnnotationConstraint.class.getSimpleName())) {
            return decodeAnnotationConstraint();
        }
        throw new IllegalArgumentException("Instruction type "
                + type + " is not supported");
    }
}

@@ -7484,258 +7484,8 @@
 ();%0A
-        %7D else if (type.equals(LinkTypeConstraint.class.getSimpleName())) %7B%0A            return decodeLinkTypeConstraint();%0A        %7D else if (type.equals(AnnotationConstraint.class.getSimpleName())) %7B%0A            return decodeAnnotationConstraint();%0A
     

Fix duplicated lines of code in method decode()