/*****************************************************************************
* Copyright (C) Codehaus.org *
* ------------------------------------------------------------------------- *
* Licensed 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 net.ion.rosetta;
import java.util.Arrays;
import java.util.Comparator;
import java.util.HashMap;
import java.util.TreeSet;
import net.ion.rosetta.annotations.Private;
import net.ion.rosetta.functors.Map;
import net.ion.rosetta.functors.Maps;
/**
* Helper class for creating lexers and parsers for keywords.
*
* @author Ben Yu
*/
final class Keywords {
private interface StringCase {
Comparator<String> comparator();
String toKey(String k);
<T> net.ion.rosetta.functors.Map<String, T> toMap(java.util.Map<String, T> m);
}
private static final StringCase CASE_SENSITIVE = new CaseSensitive();
private static final StringCase CASE_INSENSITIVE = new CaseInsensitive();
private static class CaseSensitive implements StringCase {
private static Comparator<String> COMPARATOR = new Comparator<String>() {
public int compare(String a, String b) {
if (a == b)
return 0;
else if (a == null)
return -1;
else if (b == null)
return 1;
else
return a.compareTo(b);
}
};
public Comparator<String> comparator() {
return COMPARATOR;
}
public String toKey(String k) {
return k;
}
public <T> net.ion.rosetta.functors.Map<String, T> toMap(java.util.Map<String, T> m) {
return Maps.map(m);
}
}
private static class CaseInsensitive implements StringCase {
private static Comparator<String> COMPARATOR = new Comparator<String>() {
public int compare(String a, String b) {
if (a == b)
return 0;
else if (a == null)
return -1;
else if (b == null)
return 1;
else
return a.compareToIgnoreCase(b);
}
};
public Comparator<String> comparator() {
return COMPARATOR;
}
public String toKey(String k) {
return k.toLowerCase();
}
public <T> net.ion.rosetta.functors.Map<String, T> toMap(final java.util.Map<String, T> m) {
return new net.ion.rosetta.functors.Map<String, T>() {
public T map(String key) {
return m.get(key.toLowerCase());
}
};
}
}
private static StringCase getStringCase(boolean caseSensitive) {
return caseSensitive ? CASE_SENSITIVE : CASE_INSENSITIVE;
}
@Private
static String[] unique(Comparator<String> c, String... names) {
TreeSet<String> set = new TreeSet<String>(c);
set.addAll(Arrays.asList(names));
return set.toArray(new String[set.size()]);
}
@SuppressWarnings("unchecked")
static <T> Lexicon lexicon(Parser<String> wordScanner, String[] keywordNames, boolean caseSensitive, final Map<String, ?> defaultMap) {
StringCase scase = getStringCase(caseSensitive);
HashMap<String, Object> map = new HashMap<String, Object>();
for (String n : unique(scase.comparator(), keywordNames)) {
Object value = Tokens.reserved(n);
map.put(scase.toKey(n), value);
}
final Map<String, Object> fmap = scase.toMap(map);
Map<String, Object> tokenizerMap = new Map<String, Object>() {
public Object map(String text) {
Object val = fmap.map(text);
if (val != null)
return val;
else
return defaultMap.map(text);
}
};
return new Lexicon(fmap, wordScanner.map(tokenizerMap));
}
}