| /* |
| * 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.onosproject.net.intent.constraint; |
| |
| import com.google.common.annotations.Beta; |
| import com.google.common.base.MoreObjects; |
| import com.google.common.collect.ImmutableList; |
| import org.onosproject.net.DeviceId; |
| import org.onosproject.net.Link; |
| import org.onosproject.net.Path; |
| import org.onosproject.net.intent.Constraint; |
| import org.onosproject.net.intent.ResourceContext; |
| |
| import java.util.Collections; |
| import java.util.LinkedList; |
| import java.util.List; |
| import java.util.Objects; |
| |
| import static com.google.common.base.Preconditions.checkArgument; |
| import static com.google.common.base.Preconditions.checkNotNull; |
| |
| /** |
| * Constraint that evaluates elements passed through in order. |
| */ |
| @Beta |
| public class WaypointConstraint implements Constraint { |
| |
| private final List<DeviceId> waypoints; |
| |
| /** |
| * Creates a new waypoint constraint. |
| * |
| * @param waypoints waypoints |
| */ |
| public WaypointConstraint(DeviceId... waypoints) { |
| checkNotNull(waypoints, "waypoints cannot be null"); |
| checkArgument(waypoints.length > 0, "length of waypoints should be more than 0"); |
| this.waypoints = ImmutableList.copyOf(waypoints); |
| } |
| |
| // Constructor for serialization |
| private WaypointConstraint() { |
| this.waypoints = Collections.emptyList(); |
| } |
| |
| public List<DeviceId> waypoints() { |
| return waypoints; |
| } |
| |
| // doesn't use LinkResourceService |
| @Override |
| public double cost(Link link, ResourceContext context) { |
| // Always consider the number of hops |
| return 1; |
| } |
| |
| // doesn't use LinkResourceService |
| @Override |
| public boolean validate(Path path, ResourceContext context) { |
| // explicitly call a method not depending on LinkResourceService |
| return validate(path); |
| } |
| |
| private boolean validate(Path path) { |
| LinkedList<DeviceId> waypoints = new LinkedList<>(this.waypoints); |
| DeviceId current = waypoints.poll(); |
| // This is safe because Path class ensures the number of links are more than 0 |
| Link firstLink = path.links().get(0); |
| if (firstLink.src().elementId().equals(current)) { |
| current = waypoints.poll(); |
| } |
| |
| for (Link link : path.links()) { |
| if (link.dst().elementId().equals(current)) { |
| current = waypoints.poll(); |
| // Empty waypoints means passing through all waypoints in the specified order |
| if (current == null) { |
| return true; |
| } |
| } |
| } |
| |
| return false; |
| } |
| |
| @Override |
| public int hashCode() { |
| return waypoints.hashCode(); |
| } |
| |
| @Override |
| public boolean equals(Object obj) { |
| if (this == obj) { |
| return true; |
| } |
| |
| if (!(obj instanceof WaypointConstraint)) { |
| return false; |
| } |
| |
| final WaypointConstraint that = (WaypointConstraint) obj; |
| return Objects.equals(this.waypoints, that.waypoints); |
| } |
| |
| @Override |
| public String toString() { |
| return MoreObjects.toStringHelper(this) |
| .add("waypoints", waypoints) |
| .toString(); |
| } |
| } |