Uploaded image for project: 'Calcite'
  1. Calcite
  2. CALCITE-2491

Simplify NameSet, NameMap, NameMultimap implementation

    XMLWordPrintableJSON

    Details

    • Type: Bug
    • Status: Closed
    • Priority: Major
    • Resolution: Fixed
    • Affects Version/s: 1.17.0
    • Fix Version/s: 1.18.0
    • Component/s: core
    • Labels:
      None

      Description

      The following implementation sketch of NameSet and friends is simpler in terms of code readability:

      public abstract class CaseInsensitiveKey {
        public final String value;
      
        public CaseInsensitiveKey(String value) {
          this.value = value;
        }
      
        @Override public String toString() {
          return value;
        }
      
        public abstract int compareResult();
      }
      
      public final class CaseInsensitiveLowerKey extends CaseInsensitiveKey {
        public CaseInsensitiveLowerKey(String value) {
          super(value);
        }
      
        @Override public int compareResult() {
          return -1;
        }
      }
      public final class CaseInsensitiveUpperKey extends CaseInsensitiveKey {
        public CaseInsensitiveUpperKey(String value) {
          super(value);
        }
      
        @Override public int compareResult() {
          return 1;
        }
      }
      public class NameMap2<V> {
        /**
         * Comparator that compares all strings differently, but if two strings are
         * equal in case-insensitive match they are right next to each other. In a
         * collection sorted on this comparator, we can find case-insensitive matches
         * for a given string using a range scan between the upper-case string and
         * the lower-case string.
         */
        public static final Comparator<Object> COMPARATOR = (o1, o2) -> {
          String s1 = o1.toString();
          String s2 = o2.toString();
          int c = s1.compareToIgnoreCase(s2);
          if (c != 0) {
            return c;
          }
          if (o1 instanceof CaseInsensitiveKey) {
            return ((CaseInsensitiveKey) o1).compareResult();
          }
          if (o2 instanceof CaseInsensitiveKey) {
            return -((CaseInsensitiveKey) o2).compareResult();
          }
          return s1.compareTo(s2);
        };
      
        private final NavigableMap<String, V> map = new TreeMap<>(COMPARATOR);
      
        public void put(String name, V v) {
          map.put(name, v);
        }
      
        public NavigableMap<String, V> map() {
          return map;
        }
      
        private NavigableMap<Object, V> rawMap() {
          return (NavigableMap<Object, V>) (NavigableMap) map;
        }
      
        /**
         * Returns a map containing all the entries in the map that match the given
         * name. If case-sensitive, that map will have 0 or 1 elements; if
         * case-insensitive, it may have 0 or more.
         */
        public NavigableMap<String, V> range(String name, boolean caseSensitive) {
          if (caseSensitive) {
            return map.subMap(name, true, name, true);
          } else {
            return (NavigableMap<String, V>) (NavigableMap) rawMap()
                .subMap(new CaseInsensitiveLowerKey(name), new CaseInsensitiveUpperKey(name));
          }
        }
      
        /**
         * Returns whether this map contains a given key, with a given
         * case-sensitivity.
         */
        public boolean containsKey(String name, boolean caseSensitive) {
          if (caseSensitive) {
            return map.subMap(name, true, name, true);
          }
          return (NavigableMap<String, V>) (NavigableMap) rawMap()
              .subMap(new CaseInsensitiveLowerKey(name), new CaseInsensitiveUpperKey(name));
        }
      
        public Set<String> keySet() {
          return map.keySet();
        }
      }
      
      public class NameSet2 {
        NameMap2<Boolean> map = new NameMap2<>();
      
        public void add(String s) {
          map.put(s, true);
        }
      
        public boolean contains(String name, boolean caseSensitive) {
          return map.containsKey(name, caseSensitive);
        }
      
        public Collection<String> range(String name, boolean caseSensitive) {
          return map.range(name, caseSensitive).keySet();
        }
      
        public Iterable<String> iterable() {
          return Collections.unmodifiableSet(map.keySet());
        }
      
        @Override public String toString() {
          return map.keySet().toString();
        }
      }
      

        Attachments

          Issue Links

            Activity

              People

              • Assignee:
                vladimirsitnikov Vladimir Sitnikov
                Reporter:
                vladimirsitnikov Vladimir Sitnikov
              • Votes:
                0 Vote for this issue
                Watchers:
                2 Start watching this issue

                Dates

                • Created:
                  Updated:
                  Resolved: