com.hazelcast.org.apache.calcite.sql.validate.SqlNameMatchers 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 com.hazelcast.org.apache.calcite.sql.validate;
import com.hazelcast.org.apache.calcite.rel.type.RelDataType;
import com.hazelcast.org.apache.calcite.rel.type.RelDataTypeField;
import com.hazelcast.org.apache.calcite.sql.SqlIdentifier;
import com.hazelcast.org.apache.calcite.util.Util;
import com.hazelcast.com.google.common.collect.ImmutableList;
import com.hazelcast.org.checkerframework.checker.nullness.qual.Nullable;
import java.util.LinkedHashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.TreeSet;
import static java.util.Objects.requireNonNull;
/**
* Helpers for {@link SqlNameMatcher}.
*/
public class SqlNameMatchers {
private static final BaseMatcher CASE_SENSITIVE = new BaseMatcher(true);
private static final BaseMatcher CASE_INSENSITIVE = new BaseMatcher(false);
private SqlNameMatchers() {}
/** Returns a name matcher with the given case sensitivity. */
public static SqlNameMatcher withCaseSensitive(final boolean caseSensitive) {
return caseSensitive ? CASE_SENSITIVE : CASE_INSENSITIVE;
}
/** Creates a name matcher that can suggest corrections to what the user
* typed. It matches liberally (case-insensitively) and also records the last
* match. */
public static SqlNameMatcher liberal() {
return new LiberalNameMatcher();
}
/** Partial implementation of {@link SqlNameMatcher}. */
private static class BaseMatcher implements SqlNameMatcher {
private final boolean caseSensitive;
BaseMatcher(boolean caseSensitive) {
this.caseSensitive = caseSensitive;
}
@Override public boolean isCaseSensitive() {
return caseSensitive;
}
@Override public boolean matches(String string, String name) {
return caseSensitive ? string.equals(name)
: string.equalsIgnoreCase(name);
}
protected boolean listMatches(List list0, List list1) {
if (list0.size() != list1.size()) {
return false;
}
for (int i = 0; i < list0.size(); i++) {
String s0 = list0.get(i);
String s1 = list1.get(i);
if (!matches(s0, s1)) {
return false;
}
}
return true;
}
@Override public , V> @Nullable V get(Map map,
List prefixNames, List names) {
final List key = concat(prefixNames, names);
if (caseSensitive) {
//noinspection SuspiciousMethodCalls
return map.get(key);
}
for (Map.Entry entry : map.entrySet()) {
if (listMatches(key, entry.getKey())) {
matched(prefixNames, entry.getKey());
return entry.getValue();
}
}
return null;
}
private static List concat(List prefixNames, List names) {
if (prefixNames.isEmpty()) {
return names;
} else {
return ImmutableList.builder().addAll(prefixNames).addAll(names)
.build();
}
}
protected void matched(List prefixNames, List names) {
}
protected List bestMatch() {
throw new UnsupportedOperationException();
}
@Override public String bestString() {
return SqlIdentifier.getString(bestMatch());
}
@Override public @Nullable RelDataTypeField field(RelDataType rowType, String fieldName) {
return rowType.getField(fieldName, caseSensitive, false);
}
@Override public int frequency(Iterable names, String name) {
int n = 0;
for (String s : names) {
if (matches(s, name)) {
++n;
}
}
return n;
}
@Override public Set createSet() {
return isCaseSensitive()
? new LinkedHashSet<>()
: new TreeSet<>(String.CASE_INSENSITIVE_ORDER);
}
}
/** Matcher that remembers the requests that were made of it. */
private static class LiberalNameMatcher extends BaseMatcher {
@Nullable List matchedNames;
LiberalNameMatcher() {
super(false);
}
@Override protected boolean listMatches(List list0,
List list1) {
final boolean b = super.listMatches(list0, list1);
if (b) {
matchedNames = ImmutableList.copyOf(list1);
}
return b;
}
@Override protected void matched(List prefixNames,
List names) {
matchedNames = ImmutableList.copyOf(
Util.startsWith(names, prefixNames)
? Util.skip(names, prefixNames.size())
: names);
}
@Override public List bestMatch() {
return requireNonNull(matchedNames, "matchedNames");
}
}
}
© 2015 - 2024 Weber Informatics LLC | Privacy Policy