/*
 * Copyright 2014 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.onlab.onos.net.intent.impl;

import org.apache.felix.scr.annotations.Component;
import org.apache.felix.scr.annotations.Reference;
import org.apache.felix.scr.annotations.ReferenceCardinality;
import org.onlab.onos.net.ElementId;
import org.onlab.onos.net.Path;
import org.onlab.onos.net.intent.ConnectivityIntent;
import org.onlab.onos.net.intent.Constraint;
import org.onlab.onos.net.intent.IntentCompiler;
import org.onlab.onos.net.intent.IntentExtensionService;
import org.onlab.onos.net.provider.ProviderId;
import org.onlab.onos.net.resource.LinkResourceService;
import org.onlab.onos.net.topology.LinkWeight;
import org.onlab.onos.net.topology.PathService;
import org.onlab.onos.net.topology.TopologyEdge;

import java.util.Iterator;
import java.util.List;
import java.util.Set;

/**
 * Base class for compilers of various
 * {@link org.onlab.onos.net.intent.ConnectivityIntent connectivity intents}.
 */
@Component(immediate = true)
public abstract class ConnectivityIntentCompiler<T extends ConnectivityIntent>
        implements IntentCompiler<T> {

    private static final ProviderId PID = new ProviderId("core", "org.onlab.onos.core", true);

    @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
    protected IntentExtensionService intentManager;

    @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
    protected PathService pathService;

    @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
    protected LinkResourceService resourceService;

    /**
     * Returns an edge-weight capable of evaluating links on the basis of the
     * specified constraints.
     *
     * @param constraints path constraints
     * @return edge-weight function
     */
    protected LinkWeight weight(List<Constraint> constraints) {
        return new ConstraintBasedLinkWeight(constraints);
    }

    /**
     * Validates the specified path against the given constraints.
     *
     * @param path        path to be checked
     * @param constraints path constraints
     * @return true if the path passes all constraints
     */
    protected boolean checkPath(Path path, List<Constraint> constraints) {
        for (Constraint constraint : constraints) {
            if (!constraint.validate(path, resourceService)) {
                return false;
            }
        }
        return true;
    }

    /**
     * Computes a path between two ConnectPoints.
     *
     * @param intent intent on which behalf path is being computed
     * @param one    start of the path
     * @param two    end of the path
     * @return Path between the two
     * @throws PathNotFoundException if a path cannot be found
     */
    protected Path getPath(ConnectivityIntent intent,
                           ElementId one, ElementId two) {
        Set<Path> paths = pathService.getPaths(one, two, weight(intent.constraints()));
        if (paths.isEmpty()) {
            throw new PathNotFoundException("No packet path from " + one + " to " + two);
        }
        // TODO: let's be more intelligent about this eventually
        return paths.iterator().next();
    }

    /**
     * Edge-weight capable of evaluating link cost using a set of constraints.
     */
    protected class ConstraintBasedLinkWeight implements LinkWeight {

        private final List<Constraint> constraints;

        /**
         * Creates a new edge-weight function capable of evaluating links
         * on the basis of the specified constraints.
         *
         * @param constraints path constraints
         */
        ConstraintBasedLinkWeight(List<Constraint> constraints) {
            this.constraints = constraints;
        }

        @Override
        public double weight(TopologyEdge edge) {
            if (constraints == null || !constraints.iterator().hasNext()) {
                return 1.0;
            }

            // iterate over all constraints in order and return the weight of
            // the first one with fast fail over the first failure
            Iterator<Constraint> it = constraints.iterator();

            double cost = it.next().cost(edge.link(), resourceService);
            while (it.hasNext() && cost > 0) {
                if (it.next().cost(edge.link(), resourceService) < 0) {
                    return -1;
                }
            }
            return cost;

        }
    }

}

@@ -644,16 +644,64 @@
 .impl;%0A%0A
+import com.google.common.collect.ImmutableList;%0A
 import o
@@ -1377,16 +1377,46 @@
 yEdge;%0A%0A
+import java.util.Collections;%0A
 import j
@@ -4310,39 +4310,199 @@
     
-this.constraints = constraints;
+if (constraints == null) %7B%0A                this.constraints = Collections.emptyList();%0A            %7D else %7B%0A                this.constraints = ImmutableList.copyOf(constraints);%0A            %7D
 %0A   
@@ -4573,24 +4573,24 @@
 dge edge) %7B%0A
+
             
@@ -4597,31 +4597,8 @@
 if (
-constraints == null %7C%7C 
 !con

Improve null safety and simplify branch conditioin