blob: 3fd7e085bf665748a3a901e9f39401bf2ebee608 [file] [log] [blame]
/*
* Copyright 2017-present Open Networking Foundation
*
* 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.pi.runtime;
import com.google.common.annotations.Beta;
import com.google.common.base.MoreObjects;
import com.google.common.base.Objects;
import com.google.common.collect.ImmutableMap;
import com.google.common.collect.Maps;
import org.onosproject.net.DeviceId;
import org.onosproject.net.pi.model.PiActionProfileId;
import java.util.Collection;
import java.util.Map;
import java.util.Optional;
import static com.google.common.base.Preconditions.checkArgument;
import static com.google.common.base.Preconditions.checkNotNull;
/**
* Instance of an action profile group of a protocol-independent pipeline.
*/
@Beta
public final class PiActionProfileGroup implements PiEntity {
private final PiActionProfileId actionProfileId;
private final PiActionProfileGroupId groupId;
private final ImmutableMap<PiActionProfileMemberId, WeightedMember> members;
private final int maxSize;
private PiActionProfileGroup(PiActionProfileGroupId groupId,
ImmutableMap<PiActionProfileMemberId, WeightedMember> members,
PiActionProfileId actionProfileId,
int maxSize) {
this.groupId = groupId;
this.members = members;
this.actionProfileId = actionProfileId;
this.maxSize = maxSize;
}
/**
* Returns the ID of this action profile group.
*
* @return action profile group ID
*/
public PiActionProfileGroupId id() {
return groupId;
}
/**
* Returns the list of member references of this action profile group.
*
* @return collection of action profile members.
*/
public Collection<WeightedMember> members() {
return members.values();
}
/**
* Returns the group member identified by the given action profile member
* ID, if present.
*
* @param memberId action profile member ID
* @return optional group member
*/
public Optional<WeightedMember> member(PiActionProfileMemberId memberId) {
return Optional.of(members.get(memberId));
}
/**
* Returns the maximum number of members that this group can hold. 0
* signifies that a limit is not set.
*
* @return maximum number of members that this group can hold
*/
public int maxSize() {
return maxSize;
}
/**
* Returns the ID of the action profile where this group belong.
*
* @return action profile ID
*/
public PiActionProfileId actionProfile() {
return actionProfileId;
}
@Override
public boolean equals(Object obj) {
if (this == obj) {
return true;
}
if (obj == null || getClass() != obj.getClass()) {
return false;
}
final PiActionProfileGroup other = (PiActionProfileGroup) obj;
return Objects.equal(this.groupId, other.groupId)
&& Objects.equal(this.members, other.members)
&& Objects.equal(this.maxSize, other.maxSize)
&& Objects.equal(this.actionProfileId, other.actionProfileId);
}
@Override
public int hashCode() {
return Objects.hashCode(groupId, members, maxSize, actionProfileId);
}
@Override
public String toString() {
return MoreObjects.toStringHelper(this)
.add("actionProfile", actionProfileId)
.add("id", groupId)
.add("members", members.values())
.add("maxSize", maxSize)
.toString();
}
/**
* Returns a new builder of action profile groups.
*
* @return action profile group builder
*/
public static Builder builder() {
return new Builder();
}
@Override
public PiEntityType piEntityType() {
return PiEntityType.ACTION_PROFILE_GROUP;
}
@Override
public PiActionProfileGroupHandle handle(DeviceId deviceId) {
return PiActionProfileGroupHandle.of(deviceId, this);
}
/**
* Builder of action profile groups.
*/
public static final class Builder {
private PiActionProfileGroupId groupId;
private Map<PiActionProfileMemberId, WeightedMember> members = Maps.newHashMap();
private PiActionProfileId actionProfileId;
private int maxSize;
private Builder() {
// hides constructor.
}
/**
* Sets the ID of this action profile group.
*
* @param id action profile group ID
* @return this
*/
public Builder withId(PiActionProfileGroupId id) {
this.groupId = id;
return this;
}
/**
* Adds one member to this action profile.
*
* @param member member to add
* @return this
*/
public Builder addMember(WeightedMember member) {
checkNotNull(member);
members.put(member.id(), member);
return this;
}
/**
* Adds one member to this action profile group with default weight.
*
* @param memberId ID of the action profile member to add
* @return this
*/
public Builder addMember(PiActionProfileMemberId memberId) {
addMember(new WeightedMember(memberId, WeightedMember.DEFAULT_WEIGHT));
return this;
}
/**
* Adds one member to this action profile group with default weight.
*
* @param memberInstance the action profile member instance to add
* @return this
*/
public Builder addMember(PiActionProfileMember memberInstance) {
addMember(new WeightedMember(memberInstance, WeightedMember.DEFAULT_WEIGHT));
return this;
}
/**
* Adds all members to this action profile group with default weight.
*
* @param memberInstances the action profile member instance to add
* @return this
*/
public Builder addMembers(Iterable<PiActionProfileMember> memberInstances) {
memberInstances.forEach(this::addMember);
return this;
}
/**
* Adds one member to this action profile group with the given weight.
*
* @param memberId ID of the action profile member to add
* @param weight weight
* @return this
*/
public Builder addMember(PiActionProfileMemberId memberId, int weight) {
addMember(new WeightedMember(memberId, weight));
return this;
}
/**
* Adds one member to this action profile group with the given weight.
*
* @param memberInstance the action profile member instance to add
* @param weight weight
* @return this
*/
public Builder addMember(PiActionProfileMember memberInstance, int weight) {
addMember(new WeightedMember(memberInstance, weight));
return this;
}
/**
* Sets the ID of the action profile.
*
* @param piActionProfileId the ID of the action profile
* @return this
*/
public Builder withActionProfileId(PiActionProfileId piActionProfileId) {
this.actionProfileId = piActionProfileId;
return this;
}
/**
* Sets the maximum number of members that this group can hold.
*
* @param maxSize maximum number of members that this group can hold
* @return this
*/
public Builder withMaxSize(int maxSize) {
checkArgument(maxSize >= 0, "maxSize cannot be negative");
this.maxSize = maxSize;
return this;
}
/**
* Creates a new action profile group.
*
* @return action profile group
*/
public PiActionProfileGroup build() {
checkNotNull(groupId);
checkNotNull(actionProfileId);
checkArgument(maxSize == 0 || members.size() <= maxSize,
"The number of members cannot exceed maxSize");
final boolean validActionProfileId = members.isEmpty() || members.values()
.stream().allMatch(m -> m.instance() == null || m.instance()
.actionProfile().equals(actionProfileId));
checkArgument(
validActionProfileId,
"The members' action profile ID must match the group one");
return new PiActionProfileGroup(
groupId, ImmutableMap.copyOf(members), actionProfileId, maxSize);
}
}
/**
* Weighted reference to an action profile member as used in an action
* profile group.
*/
public static final class WeightedMember {
public static final int DEFAULT_WEIGHT = 1;
private final PiActionProfileMemberId memberId;
private final int weight;
private final PiActionProfileMember memberInstance;
/**
* Creates a new reference for the given action profile member ID and
* weight.
*
* @param memberId action profile member ID
* @param weight weight
*/
public WeightedMember(PiActionProfileMemberId memberId, int weight) {
checkNotNull(memberId);
this.memberId = memberId;
this.weight = weight;
this.memberInstance = null;
}
/**
* Creates a new reference from the given action profile member instance
* and weight. This constructor should be used when performing one-shot
* group programming (see {@link #instance()}).
*
* @param memberInstance action profile member instance
* @param weight weight
*/
public WeightedMember(PiActionProfileMember memberInstance, int weight) {
checkNotNull(memberInstance);
this.memberId = memberInstance.id();
this.weight = weight;
this.memberInstance = memberInstance;
}
/**
* Returns the ID of the action profile member.
*
* @return action profile member ID
*/
public PiActionProfileMemberId id() {
return memberId;
}
/**
* Returns the weight of this group member.
*
* @return weight
*/
public int weight() {
return weight;
}
/**
* If present, returns the instance of the action profile member pointed
* by this reference, otherwise returns null. This method is provided as
* a convenient way to perform one-shot group programming, and as such
* is meaningful only when performing write operations to a device. In
* other words, when reading groups from a device only the member
* reference should be returned and not the actual instance, hence this
* method should return null.
*
* @return action profile member instance, or null
*/
public PiActionProfileMember instance() {
return memberInstance;
}
@Override
public int hashCode() {
return Objects.hashCode(memberId, weight);
}
@Override
public boolean equals(Object obj) {
if (this == obj) {
return true;
}
if (obj == null || getClass() != obj.getClass()) {
return false;
}
final WeightedMember other = (WeightedMember) obj;
return Objects.equal(this.memberId, other.memberId)
&& Objects.equal(this.weight, other.weight);
}
@Override
public String toString() {
return MoreObjects.toStringHelper(this)
.add("memberId", memberId)
.add("weight", weight)
.toString();
}
}
}