All Downloads are FREE. Search and download functionalities are using the official Maven repository.

com.hazelcast.org.apache.calcite.util.RangeSets Maven / Gradle / Ivy

There is a newer version: 5.5.0
Show newest version
/*
 * 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 com.hazelcast.org.apache.calcite.util;

import com.hazelcast.com.google.common.collect.BoundType;
import com.hazelcast.com.google.common.collect.ImmutableRangeSet;
import com.hazelcast.com.google.common.collect.Range;
import com.hazelcast.com.google.common.collect.RangeSet;
import com.hazelcast.com.google.common.collect.TreeRangeSet;

import java.util.Iterator;
import java.util.Set;
import java.util.function.BiConsumer;
import java.util.function.Function;

/** Utilities for Guava {@link com.hazelcast.com.google.common.collect.RangeSet}. */
@SuppressWarnings({"BetaApi", "UnstableApiUsage"})
public class RangeSets {
  private RangeSets() {}

  @SuppressWarnings({"BetaApi", "rawtypes"})
  private static final ImmutableRangeSet ALL =
      ImmutableRangeSet.of().complement();

  /** Subtracts a range from a range set. */
  public static > RangeSet minus(RangeSet rangeSet,
      Range range) {
    final TreeRangeSet mutableRangeSet = TreeRangeSet.create(rangeSet);
    mutableRangeSet.remove(range);
    return mutableRangeSet.equals(rangeSet) ? rangeSet
        : ImmutableRangeSet.copyOf(mutableRangeSet);
  }

  /** Returns the unrestricted range set. */
  @SuppressWarnings({"rawtypes", "unchecked"})
  public static > RangeSet rangeSetAll() {
    return (RangeSet) ALL;
  }

  /** Compares two range sets. */
  public static > int compare(RangeSet s0,
      RangeSet s1) {
    final Iterator> i0 = s0.asRanges().iterator();
    final Iterator> i1 = s1.asRanges().iterator();
    for (;;) {
      final boolean h0 = i0.hasNext();
      final boolean h1 = i1.hasNext();
      if (!h0 || !h1) {
        return Boolean.compare(h0, h1);
      }
      final Range r0 = i0.next();
      final Range r1 = i1.next();
      int c = compare(r0, r1);
      if (c != 0) {
        return c;
      }
    }
  }

  /** Compares two ranges. */
  public static > int compare(Range r0,
      Range r1) {
    int c = Boolean.compare(r0.hasLowerBound(), r1.hasLowerBound());
    if (c != 0) {
      return c;
    }
    if (r0.hasLowerBound()) {
      c = r0.lowerEndpoint().compareTo(r1.lowerEndpoint());
      if (c != 0) {
        return c;
      }
      c = r0.lowerBoundType().compareTo(r1.lowerBoundType());
      if (c != 0) {
        return c;
      }
    }
    c = Boolean.compare(r0.hasUpperBound(), r1.hasUpperBound());
    if (c != 0) {
      return -c;
    }
    if (r0.hasUpperBound()) {
      c = r0.upperEndpoint().compareTo(r1.upperEndpoint());
      if (c != 0) {
        return c;
      }
      c = r0.upperBoundType().compareTo(r1.upperBoundType());
      if (c != 0) {
        return c;
      }
    }
    return 0;
  }

  /** Computes a hash code for a range set.
   *
   * 

This method does not compute the same result as * {@link RangeSet#hashCode}. That is a poor hash code because it is based * upon {@link java.util.Set#hashCode}). * *

The algorithm is based on {@link java.util.List#hashCode()}, * which is well-defined because {@link RangeSet#asRanges()} is sorted. */ public static > int hashCode(RangeSet rangeSet) { int h = 1; for (Range r : rangeSet.asRanges()) { h = 31 * h + r.hashCode(); } return h; } /** Returns whether a range is a point. */ public static > boolean isPoint(Range range) { return range.hasLowerBound() && range.hasUpperBound() && range.lowerEndpoint().equals(range.upperEndpoint()) && !range.isEmpty(); } /** Returns whether a range set is a single open interval. */ public static > boolean isOpenInterval(RangeSet rangeSet) { if (rangeSet.isEmpty()) { return false; } final Set> ranges = rangeSet.asRanges(); final Range range = ranges.iterator().next(); return ranges.size() == 1 && (!range.hasLowerBound() || !range.hasUpperBound()); } /** Returns the number of ranges in a range set that are points. * *

If every range in a range set is a point then it can be converted to a * SQL IN list. */ public static > int countPoints(RangeSet rangeSet) { int n = 0; for (Range range : rangeSet.asRanges()) { if (isPoint(range)) { ++n; } } return n; } /** Calls the appropriate handler method for each range in a range set, * creating a new range set from the results. */ public static , C2 extends Comparable> RangeSet map(RangeSet rangeSet, Handler> handler) { final ImmutableRangeSet.Builder builder = ImmutableRangeSet.builder(); rangeSet.asRanges().forEach(range -> builder.add(map(range, handler))); return builder.build(); } /** Calls the appropriate handler method for the type of range. */ public static , R> R map(Range range, Handler handler) { if (range.hasLowerBound() && range.hasUpperBound()) { final C lower = range.lowerEndpoint(); final C upper = range.upperEndpoint(); if (range.lowerBoundType() == BoundType.OPEN) { if (range.upperBoundType() == BoundType.OPEN) { return handler.open(lower, upper); } else { return handler.openClosed(lower, upper); } } else { if (range.upperBoundType() == BoundType.OPEN) { return handler.closedOpen(lower, upper); } else { if (lower.equals(upper)) { return handler.singleton(lower); } else { return handler.closed(lower, upper); } } } } else if (range.hasLowerBound()) { final C lower = range.lowerEndpoint(); if (range.lowerBoundType() == BoundType.OPEN) { return handler.greaterThan(lower); } else { return handler.atLeast(lower); } } else if (range.hasUpperBound()) { final C upper = range.upperEndpoint(); if (range.upperBoundType() == BoundType.OPEN) { return handler.lessThan(upper); } else { return handler.atMost(upper); } } else { return handler.all(); } } /** Copies a range set. */ public static , C2 extends Comparable> RangeSet copy(RangeSet rangeSet, Function map) { return map(rangeSet, new CopyingHandler() { @Override C2 convert(C c) { return map.apply(c); } }); } /** Copies a range. */ public static , C2 extends Comparable> Range copy(Range range, Function map) { return map(range, new CopyingHandler() { @Override C2 convert(C c) { return map.apply(c); } }); } public static > void forEach(RangeSet rangeSet, Consumer consumer) { rangeSet.asRanges().forEach(range -> forEach(range, consumer)); } public static > void forEach(Range range, Consumer consumer) { if (range.hasLowerBound() && range.hasUpperBound()) { final C lower = range.lowerEndpoint(); final C upper = range.upperEndpoint(); if (range.lowerBoundType() == BoundType.OPEN) { if (range.upperBoundType() == BoundType.OPEN) { consumer.open(lower, upper); } else { consumer.openClosed(lower, upper); } } else { if (range.upperBoundType() == BoundType.OPEN) { consumer.closedOpen(lower, upper); } else { if (lower.equals(upper)) { consumer.singleton(lower); } else { consumer.closed(lower, upper); } } } } else if (range.hasLowerBound()) { final C lower = range.lowerEndpoint(); if (range.lowerBoundType() == BoundType.OPEN) { consumer.greaterThan(lower); } else { consumer.atLeast(lower); } } else if (range.hasUpperBound()) { final C upper = range.upperEndpoint(); if (range.upperBoundType() == BoundType.OPEN) { consumer.lessThan(upper); } else { consumer.atMost(upper); } } else { consumer.all(); } } /** Creates a consumer that prints values to a {@link StringBuilder}. */ public static > Consumer printer(StringBuilder sb, BiConsumer valuePrinter) { return new Printer<>(sb, valuePrinter); } /** Deconstructor for {@link Range} values. * * @param Value type * @param Return type * * @see Consumer */ public interface Handler, R> { R all(); R atLeast(C lower); R atMost(C upper); R greaterThan(C lower); R lessThan(C upper); R singleton(C value); R closed(C lower, C upper); R closedOpen(C lower, C upper); R openClosed(C lower, C upper); R open(C lower, C upper); } /** Consumer of {@link Range} values. * * @param Value type * * @see Handler */ public interface Consumer> { void all(); void atLeast(C lower); void atMost(C upper); void greaterThan(C lower); void lessThan(C upper); void singleton(C value); void closed(C lower, C upper); void closedOpen(C lower, C upper); void openClosed(C lower, C upper); void open(C lower, C upper); } /** Handler that converts a Range into another Range of the same type, * applying a mapping function to the range's bound(s). * * @param Value type * @param Output value type */ private abstract static class CopyingHandler, C2 extends Comparable> implements RangeSets.Handler> { abstract C2 convert(C c); @Override public Range all() { return Range.all(); } @Override public Range atLeast(C lower) { return Range.atLeast(convert(lower)); } @Override public Range atMost(C upper) { return Range.atMost(convert(upper)); } @Override public Range greaterThan(C lower) { return Range.greaterThan(convert(lower)); } @Override public Range lessThan(C upper) { return Range.lessThan(convert(upper)); } @Override public Range singleton(C value) { return Range.singleton(convert(value)); } @Override public Range closed(C lower, C upper) { return Range.closed(convert(lower), convert(upper)); } @Override public Range closedOpen(C lower, C upper) { return Range.closedOpen(convert(lower), convert(upper)); } @Override public Range openClosed(C lower, C upper) { return Range.openClosed(convert(lower), convert(upper)); } @Override public Range open(C lower, C upper) { return Range.open(convert(lower), convert(upper)); } } /** Converts any type of range to a string, using a given value printer. * * @param Value type */ static class Printer> implements Consumer { private final StringBuilder sb; private final BiConsumer valuePrinter; Printer(StringBuilder sb, BiConsumer valuePrinter) { this.sb = sb; this.valuePrinter = valuePrinter; } @Override public void all() { sb.append("(-\u221e..+\u221e)"); } @Override public void atLeast(C lower) { sb.append('['); valuePrinter.accept(sb, lower); sb.append("..+\u221e)"); } @Override public void atMost(C upper) { sb.append("(-\u221e.."); valuePrinter.accept(sb, upper); sb.append("]"); } @Override public void greaterThan(C lower) { sb.append('('); valuePrinter.accept(sb, lower); sb.append("..+\u221e)"); } @Override public void lessThan(C upper) { sb.append("(-\u221e.."); valuePrinter.accept(sb, upper); sb.append(")"); } @Override public void singleton(C value) { valuePrinter.accept(sb, value); } @Override public void closed(C lower, C upper) { sb.append('['); valuePrinter.accept(sb, lower); sb.append(".."); valuePrinter.accept(sb, upper); sb.append(']'); } @Override public void closedOpen(C lower, C upper) { sb.append('['); valuePrinter.accept(sb, lower); sb.append(".."); valuePrinter.accept(sb, upper); sb.append(')'); } @Override public void openClosed(C lower, C upper) { sb.append('('); valuePrinter.accept(sb, lower); sb.append(".."); valuePrinter.accept(sb, upper); sb.append(']'); } @Override public void open(C lower, C upper) { sb.append('('); valuePrinter.accept(sb, lower); sb.append(".."); valuePrinter.accept(sb, upper); sb.append(')'); } } }





© 2015 - 2024 Weber Informatics LLC | Privacy Policy