/* * Copyright 2015 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.newresource; import com.google.common.annotations.Beta; import com.google.common.base.MoreObjects; import com.google.common.collect.ImmutableList; import java.util.LinkedList; import java.util.List; import java.util.Objects; import java.util.Optional; import static com.google.common.base.Preconditions.checkArgument; import static com.google.common.base.Preconditions.checkNotNull; import static com.google.common.base.Preconditions.checkState; /** * An object that is used to locate a resource in a network. * A ResourcePath represents a path that is hierarchical and composed of a sequence * of elementary resources that are not globally identifiable. A ResourcePath can be a globally * unique resource identifier. * * Two types of resource are considered. One is discrete type and the other is continuous type. * Discrete type resource is a resource whose amount is measured as a discrete unit. VLAN ID and * MPLS label are examples of discrete type resource. Continuous type resource is a resource whose * amount is measured as a continuous value. Bandwidth is an example of continuous type resource. * A double value is associated with a continuous type value. * * Users of this class must keep the semantics of resources regarding the hierarchical structure. * For example, resource path, Link:1/VLAN ID:100, is valid, but resource path, VLAN ID:100/Link:1 * is not valid because a link is not a sub-component of a VLAN ID. */ @Beta public abstract class ResourcePath { private final Discrete parent; private final Object last; public static final Discrete ROOT = new Discrete(); /** * Creates an resource path which represents a discrete-type resource from the specified components. * * @param components components of the path. The order represents hierarchical structure of the resource. */ public static ResourcePath discrete(Object... components) { if (components.length == 0) { return ROOT; } else { return new Discrete(ImmutableList.copyOf(components)); } } /** * Creates an resource path which represents a continuous-type resource from the specified components. * * @param value amount of the resource * @param components components of the path. The order represents hierarchical structure of the resource. */ public static ResourcePath continuous(double value, Object... components) { return new Continuous(ImmutableList.copyOf(components), value); } /** * Creates an resource path from the specified components. * * @param components components of the path. The order represents hierarchical structure of the resource. */ ResourcePath(List components) { checkNotNull(components); checkArgument(!components.isEmpty()); LinkedList children = new LinkedList<>(components); this.last = children.pollLast(); if (children.isEmpty()) { this.parent = ROOT; } else { this.parent = new Discrete(children); } } /** * Creates an resource path from the specified parent and child. * * @param parent the parent of this resource * @param last a child of the parent */ ResourcePath(Discrete parent, Object last) { checkNotNull(parent); checkNotNull(last); this.parent = parent; this.last = last; } // for serialization private ResourcePath() { this.parent = null; this.last = null; } /** * Returns the components of this resource path. * * @return the components of this resource path */ public List components() { LinkedList components = new LinkedList<>(); ResourcePath current = this; while (current.parent().isPresent()) { components.addFirst(current.last); current = current.parent; } return components; } /** * Returns the parent resource path of this instance. * E.g. if this path is Link:1/VLAN ID:100, the return value is the resource path for Link:1. * * @return the parent resource path of this instance. * If there is no parent, empty instance will be returned. */ public Optional parent() { return Optional.ofNullable(parent); } public ResourcePath child(Object child) { checkState(this instanceof Discrete); return new Discrete((Discrete) this, child); } public ResourcePath child(Object child, double value) { checkState(this instanceof Discrete); return new Continuous((Discrete) this, child, value); } /** * Returns the last component of this instance. * * @return the last component of this instance. * The return value is equal to the last object of {@code components()}. */ public Object last() { return last; } @Override public int hashCode() { return Objects.hash(this.parent, this.last); } @Override public boolean equals(Object obj) { if (this == obj) { return true; } if (!(obj instanceof ResourcePath)) { return false; } final ResourcePath that = (ResourcePath) obj; return Objects.equals(this.parent, that.parent) && Objects.equals(this.last, that.last); } @Override public String toString() { return MoreObjects.toStringHelper(this) .add("parent", parent) .add("last", last) .toString(); } /** * Represents a resource path which specifies a resource which can be measured * as a discrete unit. A VLAN ID and a MPLS label of a link are examples of the resource. *

* Note: This class is exposed to the public, but intended to be used in the resource API * implementation only. It is not for resource API user. *

*/ public static final class Discrete extends ResourcePath { private Discrete() { super(); } private Discrete(List components) { super(components); } private Discrete(Discrete parent, Object last) { super(parent, last); } } /** * Represents a resource path which specifies a resource which can be measured * as continuous value. Bandwidth of a link is an example of the resource. *

* Note: This class is exposed to the public, but intended to be used in the resource API * implementation only. It is not for resource API user. */ public static final class Continuous extends ResourcePath { // Note: value is not taken into account for equality private final double value; private Continuous(List components, double value) { super(components); this.value = value; } public Continuous(Discrete parent, Object last, double value) { super(parent, last); this.value = value; } /** * Returns the value of the resource amount. * * @return the value of the resource amount */ public double value() { return value; } } }