Please wait. This can take some minutes ...
Many resources are needed to download a project. Please understand that we have to compensate our server costs. Thank you in advance.
Project price only 1 $
You can buy this project and download/modify it how often you want.
org.kie.dmn.validation.dtanalysis.model.Interval Maven / Gradle / Ivy
/**
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you 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.kie.dmn.validation.dtanalysis.model;
import java.util.ArrayDeque;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Deque;
import java.util.Iterator;
import java.util.List;
import java.util.stream.Collectors;
import java.util.stream.Stream;
import org.kie.dmn.feel.runtime.Range;
import org.kie.dmn.feel.runtime.Range.RangeBoundary;
import org.kie.dmn.feel.runtime.impl.RangeImpl;
import org.kie.dmn.feel.util.Generated;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
public class Interval {
private static final Logger LOG = LoggerFactory.getLogger(Interval.class);
public static final Comparable> POS_INF = new Comparable() {
@Override
public int compareTo(Object o) {
return o == this ? 0 : +1;
}
@Override
public String toString() {
return "+Inf";
}
};
public static final Comparable> NEG_INF = new Comparable() {
@Override
public int compareTo(Object o) {
return o == this ? 0 : -1;
}
@Override
public String toString() {
return "-Inf";
}
};
private final Bound> lowerBound;
private final Bound> upperBound;
private final int rule;
private final int col;
private final Range asRange;
public Interval(RangeBoundary lowBoundary, Comparable> start, Comparable> end, RangeBoundary highBoundary, int rule, int col) {
this.lowerBound = new Bound(start, lowBoundary, this);
this.upperBound = new Bound(end, highBoundary, this);
this.rule = rule;
this.col = col;
this.asRange = new RangeImpl(lowBoundary, nullIfInfinity(start), nullIfInfinity(end), highBoundary);
}
private Interval(Bound> lowerBound, Bound> upperBound) {
this.lowerBound = new Bound(lowerBound.getValue(), lowerBound.getBoundaryType(), this);
this.upperBound = new Bound(upperBound.getValue(), upperBound.getBoundaryType(), this);
if (lowerBound.getParent() != null && upperBound.getParent() != null && lowerBound.getParent().rule == upperBound.getParent().rule && lowerBound.getParent().col == upperBound.getParent().col) {
this.rule = lowerBound.getParent().rule;
this.col = lowerBound.getParent().col;
} else {
this.rule = 0;
this.col = 0;
}
this.asRange = new RangeImpl(lowerBound.getBoundaryType(), nullIfInfinity(lowerBound.getValue()), nullIfInfinity(upperBound.getValue()), upperBound.getBoundaryType());
}
public static Interval newFromBounds(Bound> lowerBound, Bound> upperBound) {
return new Interval(lowerBound, upperBound);
}
private static Comparable> nullIfInfinity(Comparable> input) {
if (input != POS_INF && input != NEG_INF) {
return input;
} else {
return null;
}
}
@Override
public String toString() {
return (lowerBound.getBoundaryType() == RangeBoundary.OPEN ? "(" : "[") +
" " + Bound.boundValueToString(lowerBound.getValue()) +
" .. " + Bound.boundValueToString(upperBound.getValue()) +
" " + (upperBound.getBoundaryType() == RangeBoundary.OPEN ? ")" : "]");
}
public Bound> getLowerBound() {
return lowerBound;
}
public Bound> getUpperBound() {
return upperBound;
}
public int getRule() {
return rule;
}
public int getCol() {
return col;
}
@Generated("org.eclipse.jdt.internal.corext.codemanipulation")
@Override
public int hashCode() {
final int prime = 31;
int result = 1;
result = prime * result + ((lowerBound == null) ? 0 : lowerBound.hashCode());
result = prime * result + ((upperBound == null) ? 0 : upperBound.hashCode());
return result;
}
@Generated("org.eclipse.jdt.internal.corext.codemanipulation")
@Override
public boolean equals(Object obj) {
if (this == obj) {
return true;
}
if (obj == null) {
return false;
}
if (getClass() != obj.getClass()) {
return false;
}
Interval other = (Interval) obj;
if (lowerBound == null) {
if (other.lowerBound != null) {
return false;
}
} else if (!lowerBound.equals(other.lowerBound)) {
return false;
}
if (upperBound == null) {
if (other.upperBound != null) {
return false;
}
} else if (!upperBound.equals(other.upperBound)) {
return false;
}
return true;
}
public boolean asRangeIncludes(Object param) {
Boolean result = this.asRange.includes(param);
if (result != null) {
return result;
} else if (this.lowerBound.getValue() == NEG_INF &&
this.lowerBound.getBoundaryType() == RangeBoundary.CLOSED &&
this.upperBound.getValue() == POS_INF &&
this.upperBound.getBoundaryType() == RangeBoundary.CLOSED) {
return true;
} else {
return false;
}
}
public boolean includes(Interval o) {
return this.lowerBound.compareTo((Bound) o.lowerBound) <= 0 && this.upperBound.compareTo((Bound) o.upperBound) >= 0;
}
public boolean leftAdjOrOverlap(Interval o) {
boolean thisLeftLower = this.lowerBound.compareTo((Bound) o.lowerBound) <= 0;
boolean oRightHigher = o.upperBound.compareTo((Bound) this.upperBound) >= 0;
boolean chained = BoundValueComparator.compareValueDispatchingToInf(o.lowerBound, this.upperBound) < 0;
boolean adj = Bound.adOrOver(o.lowerBound, this.upperBound);
return thisLeftLower && oRightHigher && (chained || adj);
}
public static Range.RangeBoundary invertBoundary(Range.RangeBoundary b) {
if (b == RangeBoundary.OPEN) {
return RangeBoundary.CLOSED;
} else if (b == RangeBoundary.CLOSED) {
return RangeBoundary.OPEN;
} else {
throw new IllegalStateException("invertBoundary for: " + b);
}
}
public static List flatten(List intervals) {
List results = new ArrayList<>();
LOG.debug("intervals {}", intervals);
List bounds = intervals.stream().flatMap(i -> Stream.of(i.getLowerBound(), i.getUpperBound())).collect(Collectors.toList());
Collections.sort(bounds);
LOG.debug("bounds (sorted) {}", bounds);
Deque stack = new ArrayDeque<>();
Interval candidate = null;
for (Bound cur : bounds) {
if (stack.isEmpty() && !cur.isLowerBound()) {
throw new RuntimeException("Inconsistent sort of bounds.");
}
if (cur.isLowerBound()) {
if (candidate == null) {
stack.push(cur);
} else {
if (Bound.adOrOver(candidate.upperBound, cur)) {
stack.push(candidate.lowerBound);
candidate = null;
} else {
results.add(candidate);
stack.push(cur);
}
}
} else if (cur.isUpperBound()) {
Bound pop = stack.pop();
if (stack.isEmpty()) {
candidate = Interval.newFromBounds(pop, cur);
}
} else {
throw new RuntimeException("Inconsistent value for bounds.");
}
}
if (candidate != null) {
results.add(candidate);
}
LOG.debug("results {}", results);
return results;
}
public static List invertOverDomain(Interval interval, Interval domain) {
List results = new ArrayList<>();
if (!domain.lowerBound.equals(interval.lowerBound)) {
Interval left = new Interval(domain.lowerBound.getBoundaryType(),
domain.lowerBound.getValue(),
interval.lowerBound.getValue(),
invertBoundary(interval.lowerBound.getBoundaryType()),
interval.rule,
interval.col);
results.add(left);
}
if (!domain.upperBound.equals(interval.upperBound)) {
Interval right = new Interval(invertBoundary(interval.upperBound.getBoundaryType()),
interval.upperBound.getValue(),
domain.upperBound.getValue(),
domain.upperBound.getBoundaryType(),
interval.rule,
interval.col);
results.add(right);
}
LOG.debug("results {}", results);
return results;
}
public static List invertOverDomain(List intervals, Interval domain) {
List results = new ArrayList<>();
final List is = flatten(intervals);
Iterator iterator = is.iterator();
if (!iterator.hasNext()) {
return Collections.singletonList(domain); // if none, inversion is the domain.
}
Interval firstInterval = iterator.next();
if (!domain.lowerBound.equals(firstInterval.lowerBound)) {
Interval left = new Interval(domain.lowerBound.getBoundaryType(),
domain.lowerBound.getValue(),
firstInterval.lowerBound.getValue(),
invertBoundary(firstInterval.lowerBound.getBoundaryType()),
firstInterval.rule,
firstInterval.col);
results.add(left);
}
Interval previousInterval = firstInterval;
while (iterator.hasNext()) {
Interval nextInterval = iterator.next();
if ((!previousInterval.upperBound.getValue().equals(nextInterval.lowerBound.getValue()))
|| (previousInterval.upperBound.getBoundaryType() == RangeBoundary.OPEN && nextInterval.lowerBound.getBoundaryType() == RangeBoundary.OPEN)) {
Interval iNew = new Interval(invertBoundary(previousInterval.upperBound.getBoundaryType()),
previousInterval.upperBound.getValue(),
nextInterval.lowerBound.getValue(),
invertBoundary(nextInterval.lowerBound.getBoundaryType()),
previousInterval.rule,
previousInterval.col);
results.add(iNew);
}
previousInterval = nextInterval;
}
if (!domain.upperBound.equals(previousInterval.upperBound)) {
Interval right = new Interval(invertBoundary(previousInterval.upperBound.getBoundaryType()),
previousInterval.upperBound.getValue(),
domain.upperBound.getValue(),
domain.upperBound.getBoundaryType(),
previousInterval.rule,
previousInterval.col);
results.add(right);
}
LOG.debug("results {}", results);
return results;
}
public String asHumanFriendly(Domain domain) {
if (lowerBound.getValue().equals(upperBound.getValue())
&& lowerBound.getBoundaryType() == RangeBoundary.CLOSED
&& upperBound.getBoundaryType() == RangeBoundary.CLOSED) {
return Bound.boundValueToString(lowerBound.getValue());
} else if (domain.isDiscreteDomain()) {
List> dValues = domain.getDiscreteValues();
int posL = dValues.indexOf(lowerBound.getValue());
if (posL < dValues.size() - 1
&& dValues.get(posL + 1).equals(upperBound.getValue())
&& lowerBound.getBoundaryType() == RangeBoundary.CLOSED
&& upperBound.getBoundaryType() == RangeBoundary.OPEN) {
return Bound.boundValueToString(lowerBound.getValue());
} else if (posL == dValues.size() - 1
&& lowerBound.getBoundaryType() == RangeBoundary.CLOSED
&& upperBound.getBoundaryType() == RangeBoundary.CLOSED) {
return Bound.boundValueToString(lowerBound.getValue());
} else {
return this.toString();
}
} else if (this.equals(domain.getDomainMinMax())) {
return "-";
} else if (upperBound.equals(domain.getMax()) && upperBound.getBoundaryType() == RangeBoundary.CLOSED) {
if (lowerBound.getBoundaryType() == RangeBoundary.CLOSED) {
return ">=" + Bound.boundValueToString(lowerBound.getValue());
} else if (lowerBound.getBoundaryType() == RangeBoundary.OPEN) {
return ">" + Bound.boundValueToString(lowerBound.getValue());
}
} else if (lowerBound.equals(domain.getMin()) && lowerBound.getBoundaryType() == RangeBoundary.CLOSED) {
if (upperBound.getBoundaryType() == RangeBoundary.CLOSED) {
return "<=" + Bound.boundValueToString(upperBound.getValue());
} else if (upperBound.getBoundaryType() == RangeBoundary.OPEN) {
return "<" + Bound.boundValueToString(upperBound.getValue());
}
}
return this.toString();
}
public static List normalizeDiscrete(List intervals, List discreteValues) {
List results = new ArrayList<>();
for (Interval curInterval : intervals) {
if (curInterval.lowerBound.getBoundaryType() == RangeBoundary.CLOSED && curInterval.upperBound.getBoundaryType() == RangeBoundary.OPEN) {
int lowerIdx = discreteValues.indexOf(curInterval.lowerBound.getValue());
int upperIdx = discreteValues.indexOf(curInterval.upperBound.getValue());
if (upperIdx - lowerIdx >= 2 && lowerIdx >= 0 && upperIdx >= 0) {
Comparable> previousOfUpper = (Comparable>) discreteValues.get(upperIdx - 1);
Interval newInterval = new Interval(RangeBoundary.CLOSED, curInterval.lowerBound.getValue(), previousOfUpper, RangeBoundary.CLOSED, 0, 0);
results.add(newInterval);
} else {
results.add(curInterval); // add as-is.
}
} else {
results.add(curInterval); // add as-is.
}
}
return results;
}
public boolean isSingularity() {
return lowerBound.getBoundaryType() == RangeBoundary.CLOSED &&
upperBound.getBoundaryType() == RangeBoundary.CLOSED &&
BoundValueComparator.compareValueDispatchingToInf(lowerBound, upperBound) == 0;
}
public static boolean adjOrOverlap(List intervalsA, List intervalsB) {
List otherIntervals = new ArrayList<>(intervalsB);
for (Interval i : intervalsA) {
List adjOrOverlapWithI = new ArrayList<>();
for (Interval o : otherIntervals) {
if (i.leftAdjOrOverlap(o) || o.leftAdjOrOverlap(i)) {
adjOrOverlapWithI.add(o);
}
}
otherIntervals.removeAll(adjOrOverlapWithI);
}
return otherIntervals.isEmpty();
}
}