Sho SHIMIZU

Use concrete types instead of abstract types

- ResourceId -> DiscreteResourceId/ContinuousResourceId
- Resource -> DiscreteResource/ContinuousResource

In addition, stop sharing the implementations in the super classes

Change-Id: I44662f6b7c23a23c30844a5b693e1cabab2cc091
......@@ -16,8 +16,11 @@
package org.onosproject.net.newresource;
import com.google.common.annotations.Beta;
import com.google.common.base.MoreObjects;
import java.util.List;
import java.util.Objects;
import java.util.Optional;
/**
* Represents a resource path which specifies a resource which can be measured
......@@ -27,15 +30,20 @@ import java.util.Objects;
* implementation only. It is not for resource API user.
*/
@Beta
// TODO: consider how to restrict the visibility
public final class ContinuousResource extends Resource {
public final class ContinuousResource implements Resource {
private final ContinuousResourceId id;
private final double value;
ContinuousResource(ResourceId id, double value) {
super(id);
ContinuousResource(ContinuousResourceId id, double value) {
this.id = id;
this.value = value;
}
@Override
public ContinuousResourceId id() {
return id;
}
/**
* The user of this methods must receive the return value as Double or double.
* Otherwise, this methods throws an exception.
......@@ -49,6 +57,44 @@ public final class ContinuousResource extends Resource {
return (T) Double.valueOf(value);
}
/**
* Returns the value of the resource amount.
*
* @return the value of the resource amount
*/
// FIXME: overlapping a purpose with volume()
public double value() {
return value;
}
@Override
public List<Object> components() {
return id.components;
}
@Override
public Object last() {
if (id.components.isEmpty()) {
return null;
}
return id.components.get(id.components.size() - 1);
}
@Override
public DiscreteResource child(Object child) {
throw new UnsupportedOperationException();
}
@Override
public ContinuousResource child(Class<?> child, double value) {
throw new UnsupportedOperationException();
}
@Override
public Optional<DiscreteResource> parent() {
return Optional.ofNullable(id.parent()).map(DiscreteResource::new);
}
@Override
public int hashCode() {
return Objects.hash(id(), value);
......@@ -67,13 +113,11 @@ public final class ContinuousResource extends Resource {
&& Objects.equals(this.value, other.value);
}
/**
* Returns the value of the resource amount.
*
* @return the value of the resource amount
*/
// FIXME: overlapping a purpose with volume()
public double value() {
return value;
@Override
public String toString() {
return MoreObjects.toStringHelper(this)
.add("id", id)
.add("volume", value)
.toString();
}
}
......
......@@ -18,6 +18,8 @@ package org.onosproject.net.newresource;
import com.google.common.annotations.Beta;
import com.google.common.collect.ImmutableList;
import java.util.Objects;
import static com.google.common.base.Preconditions.checkNotNull;
/**
......@@ -27,16 +29,73 @@ import static com.google.common.base.Preconditions.checkNotNull;
* implementation only. It is not for resource API user.
*/
@Beta
// TODO: consider how to restrict the visibility
public final class ContinuousResourceId extends ResourceId {
final ImmutableList<Object> components;
// for printing purpose only (used in toString() implementation)
private final String name;
ContinuousResourceId(ImmutableList<Object> components, String name) {
super(components);
this.components = components;
this.name = checkNotNull(name);
}
ContinuousResourceId(ImmutableList.Builder<Object> parentComponents, Class<?> last) {
this.components = parentComponents.add(last.getCanonicalName()).build();
this.name = last.getSimpleName();
}
/**
* {@inheritDoc}
*
* A child of a continuous-type resource is prohibited.
* {@link UnsupportedOperationException} is always thrown.
*/
@Override
public DiscreteResourceId child(Object child) {
throw new UnsupportedOperationException();
}
/**
* {@inheritDoc}
*
* A child of a continuous-type resource is prohibited.
* {@link UnsupportedOperationException} is always thrown.
*/
@Override
public ContinuousResourceId child(Class<?> child) {
throw new UnsupportedOperationException();
}
@Override
DiscreteResourceId parent() {
if (components.size() == 0) {
return null;
}
if (components.size() == 1) {
return ROOT;
} else {
return new DiscreteResourceId(components.subList(0, components.size() - 1));
}
}
@Override
public int hashCode() {
return components.hashCode();
}
@Override
public boolean equals(Object obj) {
if (this == obj) {
return true;
}
if (obj == null || getClass() != obj.getClass()) {
return false;
}
final ContinuousResourceId other = (ContinuousResourceId) obj;
return Objects.equals(this.components, other.components);
}
@Override
public String toString() {
// due to performance consideration, the value might need to be stored in a field
......
......@@ -16,8 +16,13 @@
package org.onosproject.net.newresource;
import com.google.common.annotations.Beta;
import com.google.common.base.MoreObjects;
import java.util.List;
import java.util.Objects;
import java.util.Optional;
import static com.google.common.base.Preconditions.checkArgument;
/**
* Represents a resource path which specifies a resource which can be measured
......@@ -28,14 +33,20 @@ import java.util.Objects;
* </p>
*/
@Beta
// TODO: consider how to restrict the visibility
public final class DiscreteResource extends Resource {
public final class DiscreteResource implements Resource {
private final DiscreteResourceId id;
DiscreteResource(DiscreteResourceId id) {
this.id = id;
}
protected DiscreteResource() {
super();
this.id = ResourceId.ROOT;
}
DiscreteResource(ResourceId id) {
super(id);
@Override
public DiscreteResourceId id() {
return id;
}
/**
......@@ -53,6 +64,36 @@ public final class DiscreteResource extends Resource {
}
@Override
public List<Object> components() {
return id.components;
}
@Override
public Object last() {
if (id.components.isEmpty()) {
return null;
}
return id.components.get(id.components.size() - 1);
}
@Override
public DiscreteResource child(Object child) {
checkArgument(!(child instanceof Class<?>));
return new DiscreteResource(id().child(child));
}
@Override
public ContinuousResource child(Class<?> child, double value) {
return new ContinuousResource(id.child(child), value);
}
@Override
public Optional<DiscreteResource> parent() {
return Optional.ofNullable(id.parent()).map(DiscreteResource::new);
}
@Override
public int hashCode() {
// the value returing from volume() is excluded due to optimization
return id().hashCode();
......@@ -70,4 +111,12 @@ public final class DiscreteResource extends Resource {
// the value returing from volume() is excluded due to optimization
return Objects.equals(this.id(), other.id());
}
@Override
public String toString() {
return MoreObjects.toStringHelper(this)
.add("id", id)
.add("volume", volume())
.toString();
}
}
......
......@@ -18,6 +18,11 @@ package org.onosproject.net.newresource;
import com.google.common.annotations.Beta;
import com.google.common.collect.ImmutableList;
import java.util.Objects;
import static com.google.common.base.Preconditions.checkArgument;
import static com.google.common.base.Preconditions.checkNotNull;
/**
* ResourceId for {@link DiscreteResource}.
*
......@@ -25,13 +30,65 @@ import com.google.common.collect.ImmutableList;
* implementation only. It is not for resource API user.
*/
@Beta
// TODO: consider how to restrict the visibility
public final class DiscreteResourceId extends ResourceId {
final ImmutableList<Object> components;
DiscreteResourceId(ImmutableList<Object> components) {
super(components);
this.components = components;
}
DiscreteResourceId() {
super();
this.components = ImmutableList.of();
}
@Override
public DiscreteResourceId child(Object child) {
checkArgument(!(child instanceof Class<?>));
return new DiscreteResourceId(ImmutableList.builder()
.addAll(components)
.add(child)
.build());
}
@Override
public ContinuousResourceId child(Class<?> child) {
checkNotNull(child);
return new ContinuousResourceId(ImmutableList.builder().addAll(components), child);
}
@Override
DiscreteResourceId parent() {
if (components.size() == 0) {
return null;
}
if (components.size() == 1) {
return ROOT;
} else {
return new DiscreteResourceId(components.subList(0, components.size() - 1));
}
}
@Override
public int hashCode() {
return components.hashCode();
}
@Override
public boolean equals(Object obj) {
if (this == obj) {
return true;
}
if (obj == null || getClass() != obj.getClass()) {
return false;
}
final DiscreteResourceId other = (DiscreteResourceId) obj;
return Objects.equals(this.components, other.components);
}
@Override
public String toString() {
return components.toString();
}
}
......
......@@ -16,7 +16,6 @@
package org.onosproject.net.newresource;
import com.google.common.annotations.Beta;
import com.google.common.base.MoreObjects;
import org.onosproject.net.DeviceId;
import org.onosproject.net.PortNumber;
......@@ -24,8 +23,6 @@ import java.util.List;
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 represent a resource in a network.
......@@ -44,14 +41,11 @@ import static com.google.common.base.Preconditions.checkState;
* VLAN ID:100/Device:1/Port:1 is not valid because a link is not a sub-component of a VLAN ID.
*/
@Beta
public abstract class Resource {
public interface Resource {
private final DiscreteResource parent;
private final ResourceId id;
DiscreteResource ROOT = new DiscreteResource();
public static final DiscreteResource ROOT = new DiscreteResource();
public static Resource discrete(DeviceId device) {
static DiscreteResource discrete(DeviceId device) {
return new DiscreteResource(ResourceId.discrete(device));
}
......@@ -62,7 +56,7 @@ public abstract class Resource {
* @param components following components of the path. The order represents hierarchical structure of the resource.
* @return resource path instance
*/
public static Resource discrete(DeviceId device, Object... components) {
static DiscreteResource discrete(DeviceId device, Object... components) {
return new DiscreteResource(ResourceId.discrete(device, components));
}
......@@ -74,7 +68,7 @@ public abstract class Resource {
* @param components following components of the path. The order represents hierarchical structure of the resource.
* @return resource path instance
*/
public static Resource discrete(DeviceId device, PortNumber port, Object... components) {
static DiscreteResource discrete(DeviceId device, PortNumber port, Object... components) {
return new DiscreteResource(ResourceId.discrete(device, port, components));
}
......@@ -88,7 +82,7 @@ public abstract class Resource {
* an IllegalArgumentException.
* @return resource path instance
*/
public static Resource continuous(double value, DeviceId device, Object... components) {
static ContinuousResource continuous(double value, DeviceId device, Object... components) {
checkArgument(components.length > 0,
"Length of components must be greater thant 0, but " + components.length);
......@@ -106,40 +100,16 @@ public abstract class Resource {
* an IllegalArgumentException.
* @return resource path instance
*/
public static Resource continuous(double value, DeviceId device, PortNumber port, Object... components) {
static ContinuousResource continuous(double value, DeviceId device, PortNumber port, Object... components) {
return new ContinuousResource(ResourceId.continuous(device, port, components), value);
}
/**
* Creates an resource path from the specified id.
*
* @param id id of the path
*/
protected Resource(ResourceId id) {
checkNotNull(id);
this.id = id;
if (id.components.size() == 1) {
this.parent = ROOT;
} else {
this.parent = new DiscreteResource(id.parent());
}
}
// for serialization
protected Resource() {
this.parent = null;
this.id = ResourceId.ROOT;
}
/**
* Returns the components of this resource path.
*
* @return the components of this resource path
*/
public List<Object> components() {
return id.components;
}
List<Object> components();
/**
* Returns the volume of this resource.
......@@ -147,7 +117,7 @@ public abstract class Resource {
* @return the volume of this resource
*/
// TODO: think about other naming possibilities. amount? quantity?
public abstract <T> T volume();
<T> T volume();
/**
* Returns the parent resource path of this instance.
......@@ -156,9 +126,7 @@ public abstract class Resource {
* @return the parent resource path of this instance.
* If there is no parent, empty instance will be returned.
*/
public Optional<DiscreteResource> parent() {
return Optional.ofNullable(parent);
}
Optional<DiscreteResource> parent();
/**
* Returns a child resource path of this instance with specifying the child object.
......@@ -167,11 +135,7 @@ public abstract class Resource {
* @param child child object
* @return a child resource path
*/
public Resource child(Object child) {
checkState(this instanceof DiscreteResource);
return new DiscreteResource(id().child(child));
}
DiscreteResource child(Object child);
/**
* Returns a child resource path of this instance with specifying a child object and
......@@ -181,11 +145,7 @@ public abstract class Resource {
* @param value value
* @return a child resource path
*/
public Resource child(Object child, double value) {
checkState(this instanceof DiscreteResource);
return new ContinuousResource(id.child(child), value);
}
ContinuousResource child(Class<?> child, double value);
/**
* Returns the last component of this instance.
......@@ -193,28 +153,12 @@ public abstract class Resource {
* @return the last component of this instance.
* The return value is equal to the last object of {@code components()}.
*/
public Object last() {
if (id.components.isEmpty()) {
return null;
}
return id.components.get(id.components.size() - 1);
}
Object last();
/**
* Returns the ID of this resource path.
*
* @return the ID of this resource path
*/
public ResourceId id() {
return id;
}
@Override
public String toString() {
return MoreObjects.toStringHelper(this)
.add("id", id())
.add("volume", volume())
.toString();
}
ResourceId id();
}
......
......@@ -21,11 +21,8 @@ import org.onosproject.net.DeviceId;
import org.onosproject.net.PortNumber;
import java.util.Arrays;
import java.util.Objects;
import static com.google.common.base.Preconditions.checkArgument;
import static com.google.common.base.Preconditions.checkNotNull;
import static com.google.common.base.Preconditions.checkState;
/**
* Represents identifier of resource.
......@@ -33,18 +30,16 @@ import static com.google.common.base.Preconditions.checkState;
*/
@Beta
public abstract class ResourceId {
static final ResourceId ROOT = new DiscreteResourceId();
static final DiscreteResourceId ROOT = new DiscreteResourceId();
final ImmutableList<Object> components;
static ResourceId discrete(DeviceId device, Object... components) {
static DiscreteResourceId discrete(DeviceId device, Object... components) {
return new DiscreteResourceId(ImmutableList.builder()
.add(device)
.add(components)
.build());
}
static ResourceId discrete(DeviceId device, PortNumber port, Object... components) {
static DiscreteResourceId discrete(DeviceId device, PortNumber port, Object... components) {
return new DiscreteResourceId(ImmutableList.builder()
.add(device)
.add(port)
......@@ -52,92 +47,41 @@ public abstract class ResourceId {
.build());
}
static ResourceId continuous(DeviceId device, Object... components) {
static ContinuousResourceId continuous(DeviceId device, Object... components) {
Object last = components[components.length - 1];
checkArgument(last instanceof Class<?>);
return continuous(ImmutableList.builder()
return new ContinuousResourceId(ImmutableList.builder()
.add(device)
.add(Arrays.copyOfRange(components, 0, components.length - 1)), (Class<?>) last);
}
static ResourceId continuous(DeviceId device, PortNumber port, Object... components) {
static ContinuousResourceId continuous(DeviceId device, PortNumber port, Object... components) {
Object last = components[components.length - 1];
checkArgument(last instanceof Class<?>);
return continuous(ImmutableList.builder()
return new ContinuousResourceId(ImmutableList.builder()
.add(device)
.add(port)
.add(Arrays.copyOfRange(components, 0, components.length - 1)), (Class<?>) last);
}
private static ResourceId continuous(ImmutableList.Builder<Object> parentComponents, Class<?> last) {
return new ContinuousResourceId(parentComponents
.add(last.getCanonicalName())
.build(), last.getSimpleName());
}
protected ResourceId(ImmutableList<Object> components) {
this.components = checkNotNull(components);
}
// for serializer
protected ResourceId() {
this.components = ImmutableList.of();
}
// IndexOutOfBoundsException is raised when the instance is equal to ROOT
ResourceId parent() {
if (components.size() == 1) {
return ROOT;
} else {
return new DiscreteResourceId(components.subList(0, components.size() - 1));
}
}
abstract DiscreteResourceId parent();
/**
* Returns a resource ID of a child of this resource based on the specified object.
* If the argument is an instance of {@link Class}, this method returns an instance of
* {@link ContinuousResourceId}. Otherwise, it returns an instance of {@link DiscreteResourceId}
* This method only work when the receiver is {@link DiscreteResourceId}. Otherwise,
* this method throws an exception.
* If the given object is a {@link Class} instance, {@link IllegalArgumentException} is thrown.
*
* @param child the last component of the child
* @return a child resource ID
*/
public ResourceId child(Object child) {
checkState(this instanceof DiscreteResourceId);
if (child instanceof Class<?>) {
return continuous(ImmutableList.builder().addAll(components), (Class<?>) child);
} else {
return new DiscreteResourceId(ImmutableList.builder()
.addAll(components)
.add(child)
.build());
}
}
@Override
public int hashCode() {
return components.hashCode();
}
@Override
public boolean equals(Object obj) {
if (this == obj) {
return true;
}
if (obj == null || getClass() != obj.getClass()) {
return false;
}
final ResourceId other = (ResourceId) obj;
return Objects.equals(this.components, other.components);
}
@Override
public String toString() {
return components.toString();
}
public abstract DiscreteResourceId child(Object child);
/**
* Returns a resource ID of a child of this resource based on the specified object.
*
* @param child the last component of the child
* @return a child resource ID
*/
public abstract ContinuousResourceId child(Class<?> child);
}
......
......@@ -181,8 +181,6 @@ import org.onosproject.net.newresource.ContinuousResourceId;
import org.onosproject.net.newresource.DiscreteResource;
import org.onosproject.net.newresource.DiscreteResourceId;
import org.onosproject.net.newresource.ResourceAllocation;
import org.onosproject.net.newresource.ResourceId;
import org.onosproject.net.newresource.Resource;
import org.onosproject.net.packet.DefaultOutboundPacket;
import org.onosproject.net.packet.DefaultPacketRequest;
import org.onosproject.net.packet.PacketPriority;
......@@ -442,10 +440,8 @@ public final class KryoNamespaces {
DefaultLinkResourceAllocations.class,
BandwidthResourceAllocation.class,
LambdaResourceAllocation.class,
Resource.class,
DiscreteResource.class,
ContinuousResource.class,
ResourceId.class,
DiscreteResourceId.class,
ContinuousResourceId.class,
ResourceAllocation.class,
......