blob: 33ffeac178ea4d96580cf48293c22abfe482b827 [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.pipelines.fabric.pipeliner;
import com.google.common.base.MoreObjects;
import com.google.common.collect.ImmutableMap;
import com.google.common.collect.Maps;
import org.onosproject.net.flow.FlowId;
import org.onosproject.net.flow.FlowRule;
import org.onosproject.net.flowobjective.ObjectiveError;
import org.onosproject.net.group.GroupDescription;
import java.util.Collection;
import java.util.Collections;
import java.util.Map;
import java.util.Objects;
import java.util.Optional;
import static com.google.common.base.Preconditions.checkNotNull;
import static java.lang.String.format;
/**
* Result of a pipeliner translation from an objective to flows and groups.
*/
final class ObjectiveTranslation {
private final ImmutableMap<FlowId, FlowRule> flowRules;
private final ImmutableMap<Integer, GroupDescription> groups;
private final ObjectiveError error;
private ObjectiveTranslation(Map<FlowId, FlowRule> flowRules,
Map<Integer, GroupDescription> groups,
ObjectiveError error) {
this.flowRules = ImmutableMap.copyOf(flowRules);
this.groups = ImmutableMap.copyOf(groups);
this.error = error;
}
/**
* Returns flow rules of this translation.
*
* @return flow rules
*/
Collection<FlowRule> flowRules() {
return flowRules.values();
}
/**
* Returns groups of this translation.
*
* @return groups
*/
Collection<GroupDescription> groups() {
return groups.values();
}
/**
* Returns the error of this translation, is any.
*
* @return optional error
*/
Optional<ObjectiveError> error() {
return Optional.ofNullable(error);
}
/**
* Creates a new builder.
*
* @return the builder
*/
static Builder builder() {
return new Builder();
}
/**
* Creates a new translation that signals the given error.
*
* @param error objective error
* @return new objective translation
*/
static ObjectiveTranslation ofError(ObjectiveError error) {
checkNotNull(error);
return new ObjectiveTranslation(
Collections.emptyMap(), Collections.emptyMap(), error);
}
@Override
public String toString() {
return MoreObjects.toStringHelper(this)
.add("flowRules", flowRules)
.add("groups", groups)
.add("error", error)
.toString();
}
@Override
public int hashCode() {
return Objects.hash(flowRules, groups, error);
}
@Override
public boolean equals(Object obj) {
if (this == obj) {
return true;
}
if (obj == null || getClass() != obj.getClass()) {
return false;
}
final ObjectiveTranslation other = (ObjectiveTranslation) obj;
return flowRulesExactMatch(other.flowRules)
&& Objects.equals(this.groups, other.groups)
&& Objects.equals(this.error, other.error);
}
private boolean flowRulesExactMatch(Map<FlowId, FlowRule> otherFlowRules) {
if (otherFlowRules == null || otherFlowRules.size() != this.flowRules.size()) {
return false;
}
return this.flowRules.values().stream()
.allMatch(f -> otherFlowRules.containsKey(f.id())
&& otherFlowRules.get(f.id()).exactMatch(f));
}
/**
* Builder for ObjectiveTranslation. This implementation checks that flow
* and groups are not added when an existing one with same ID (FlowId or
* GroupId) has already been added.
*/
static final class Builder {
private final Map<FlowId, FlowRule> flowRules = Maps.newHashMap();
private final Map<Integer, GroupDescription> groups = Maps.newHashMap();
// Hide default constructor
private Builder() {
}
/**
* Adds a flow rule to this translation.
*
* @param flowRule flow rule
* @return this
* @throws FabricPipelinerException if a FlowRule with same FlowId
* already exists in this translation
*/
Builder addFlowRule(FlowRule flowRule)
throws FabricPipelinerException {
checkNotNull(flowRule);
if (flowRules.containsKey(flowRule.id())) {
final FlowRule existingFlowRule = flowRules.get(flowRule.id());
if (!existingFlowRule.exactMatch(flowRule)) {
throw new FabricPipelinerException(format(
"Another FlowRule with same ID has already been " +
"added to this translation: existing=%s, new=%s",
existingFlowRule, flowRule));
}
}
flowRules.put(flowRule.id(), flowRule);
return this;
}
/**
* Adds group to this translation.
*
* @param group group
* @return this
* @throws FabricPipelinerException if a FlowRule with same GroupId
* already exists in this translation
*/
Builder addGroup(GroupDescription group)
throws FabricPipelinerException {
checkNotNull(group);
if (groups.containsKey(group.givenGroupId())) {
final GroupDescription existingGroup = groups.get(group.givenGroupId());
if (!existingGroup.equals(group)) {
throw new FabricPipelinerException(format(
"Another Group with same ID has already been " +
"added to this translation: existing=%s, new=%s",
existingGroup, group));
}
}
groups.put(group.givenGroupId(), group);
return this;
}
/**
* Creates ane translation.
*
* @return translation instance
*/
ObjectiveTranslation build() {
return new ObjectiveTranslation(flowRules, groups, null);
}
}
}