/*
* Copyright (c) 2015 Hewlett Packard Enterprise Development Company, L.P. and others. All rights reserved.
*
* This program and the accompanying materials are made available under the
* terms of the Eclipse Public License v1.0 which accompanies this distribution,
* and is available at http://www.eclipse.org/legal/epl-v10.html
*/
package org.opendaylight.nic.graph.impl;
import org.opendaylight.nic.graph.api.Interval;
import java.util.ArrayList;
import java.util.Collections;
import java.util.LinkedList;
import java.util.List;
@SuppressWarnings("serial")
public class IntervalImpl implements Interval, Comparable<IntervalImpl> {
private final int start;
private final int end;
public static final IntervalImpl INTERVAL_NULL = new IntervalImpl(
Integer.MIN_VALUE, Integer.MIN_VALUE);
@Override
public int start() {
return start;
}
@Override
public int end() {
return end;
}
/**
* @param start start of instance
* @param end end of instance
* @return Interval
*/
public static IntervalImpl getInstance(int start, int end) {
if (start > end) {
return INTERVAL_NULL;
}
return new IntervalImpl(start, end);
}
/**
* @param value value of instance
* @return Interval
*/
public static IntervalImpl getInstance(int value) {
return new IntervalImpl(value, value);
}
/**
* @param start start of interval
* @param end end of interval
*/
protected IntervalImpl(int start, int end) {
this.start = start;
this.end = end;
}
/**
* is Null
* @return boolean
*/
public boolean isNull() {
return this == INTERVAL_NULL;
}
@Override
public String toString() {
StringBuilder result = new StringBuilder("Interval { start:");
// String NEW_LINE = System.getProperty("line.separator");
result.append(start);
result.append(", end:");
result.append(end);
result.append(" }");
return result.toString();
}
/**
* is Null
* @param obj Any object
* @return boolean
*/
public boolean notEquals(Object obj) {
return !equals(obj);
}
/**
* self "greater than" other: other must be a subset of self
* @param other interval
* @return boolean
*/
public boolean greaterThan(IntervalImpl other) {
if ((this.start < other.start) && (this.end >= other.end)) {
return true;
}
if ((this.start <= other.start) && (this.end > other.end)) {
return true;
}
return false;
}
// Removing the symbols from the comments to remove Javadoc errors.
/**
* self "less than" other: self must be a subset of other
* @param other interval
* @return T or F
*/
public boolean lessThan(IntervalImpl other) {
return other.greaterThan(this);
}
/**
* self "greater than or equal to" other: other must be a subset or equal to self
* @param other interval
* @return T or F
*/
public boolean greaterThanOrEqual(IntervalImpl other) {
if ((this.start <= other.start) && (this.end >= other.end)) {
return true;
}
return false;
}
/**
* self "less than or equal to" other: self must be a subset or equal to other
* @param other interval
* @return T or F
*/
public boolean lessThanOrEqual(IntervalImpl other) {
return other.greaterThanOrEqual(this);
}
/**
* self - other: this is the difference operator for Intervals.
*
* @param other interval
* @return List of Intervals, since operator may result in 0 or more
* intervals
*/
public List<IntervalImpl> sub(IntervalImpl other) {
IntervalImpl overlap = and(other);
if (overlap == INTERVAL_NULL) {
// no overlap so nothing is subtracted
return createList(this);
}
if (this.equals(overlap)) {
// complete overlap so return list with null interval
return List_NULL;
} else if (start() == overlap.start()) {
// overlap exists
// Check if start or end of overlap is the same as this Interval.
// If not then make 2 new Intervals.
// overlap at start
return createList(new IntervalImpl(overlap.end() + 1, end()));
} else if (end() == overlap.end()) {
// overlap at end
return createList(new IntervalImpl(start(), overlap.start() - 1));
} else {
// overlap inside of this Interval
IntervalImpl i1 = new IntervalImpl(start(), overlap.start() - 1);
IntervalImpl i2 = new IntervalImpl(overlap.end() + 1, end());
return createList(i1, i2);
}
}
/**
* <em>and</em> operator. Finds the overlap between two intervals.
*
* @param other Interval
* @return an Interval containing the overlap
*/
public IntervalImpl and(IntervalImpl other) {
int start = Math.max(this.start, other.start);
int end = Math.min(this.end, other.end);
if (start <= end) {
return new IntervalImpl(start, end);
}
return INTERVAL_NULL;
}
@Override
public int hashCode() {
final int prime = 31;
int result = 1;
result = prime * result + end;
result = prime * result + start;
return result;
}
@Override
public boolean equals(Object obj) {
if (this == obj) {
return true;
}
if (obj == null) {
return false;
}
if (getClass() != obj.getClass()) {
return false;
}
IntervalImpl other = (IntervalImpl) obj;
if (end != other.end) {
return false;
}
if (start != other.start) {
return false;
}
return true;
}
// @Override
@Override
public int compareTo(IntervalImpl in) {
if (this.start < in.start()) {
return -1;
}
if (this.start > in.start()) {
return 1;
}
return 0;
}
/**
* This member function sorts and combines a list of Intervals.
* <p>
* Intervals which overlap or are adjacent are combined into single
* intervals. The list is sorted by the start of each Interval.
* @param intervals List of invertals
*/
static void sortAndCombine(List<IntervalImpl> intervals) {
if (intervals.isEmpty()) {
return;
}
if (intervals.size() == 1) {
if (intervals.get(0) == INTERVAL_NULL) {
intervals.clear();
}
return;
}
Collections.sort(intervals);
IntervalImpl i1 = INTERVAL_NULL;
IntervalImpl i2 = INTERVAL_NULL;
List<IntervalImpl> result = new LinkedList<IntervalImpl>();
// loop through the intervals
while (intervals.size() > 1) {
i1 = intervals.remove(0); // remove current interval
i2 = intervals.get(0); // get reference to next interval
if (i1 == INTERVAL_NULL) {
continue;
}
if (i1.end() >= i2.start()) {
// overlap case, update i2 and dispose of i1
i2 = getInstance(i1.start(), Math.max(i1.end(), i2.end()));
intervals.set(0, i2);
} else if (i1.end() == i2.start() - 1) {
// adjacent case, update i2 and dispose of i1
i2 = getInstance(i1.start(), i2.end());
intervals.set(0, i2);
} else {
// no overlap or adjacency, add i1 to result
result.add(i1);
}
}
if (i2 != INTERVAL_NULL) {
result.add(i2);
}
intervals.clear();
intervals.addAll(result);
}
private static final List<IntervalImpl> List_NULL = new ArrayList<IntervalImpl>() {
{
add(INTERVAL_NULL);
}
};
private static List<IntervalImpl> createList(IntervalImpl interval) {
List<IntervalImpl> list = new ArrayList<IntervalImpl>();
list.add(interval);
return list;
}
private static List<IntervalImpl> createList(IntervalImpl i1,
IntervalImpl i2) {
List<IntervalImpl> list = new ArrayList<IntervalImpl>();
list.add(i1);
list.add(i2);
return list;
}
}