001: /*
002: * Copyright 2004 Outerthought bvba and Schaubroeck nv
003: *
004: * Licensed under the Apache License, Version 2.0 (the "License"); you may not
005: * use this file except in compliance with the License. You may obtain a copy of
006: * the License at
007: *
008: * http://www.apache.org/licenses/LICENSE-2.0
009: *
010: * Unless required by applicable law or agreed to in writing, software
011: * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
012: * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
013: * License for the specific language governing permissions and limitations under
014: * the License.
015: */
016: package org.outerj.daisy.repository.serverimpl.query.facets;
017:
018: import java.util.Comparator;
019: import java.util.Locale;
020: import java.util.Map;
021: import java.util.SortedMap;
022:
023: import org.apache.commons.logging.Log;
024: import org.outerj.daisy.query.model.ValueExpr;
025: import org.outerj.daisy.repository.ValueComparator;
026: import org.outerj.daisy.repository.query.FacetConf;
027: import org.outerj.daisy.repository.serverimpl.query.Formatter;
028:
029: class StringFacetSampler extends AbstractFacetSampler {
030: public StringFacetSampler(FacetConf facetConf, Locale locale,
031: Log logger) {
032: super (facetConf, locale, logger);
033: comparator = new CaseInsensitiveStringComparator(facetConf
034: .getSortAscending(), locale);
035: Map<String, String> facetProperties = facetConf.getProperties();
036: if (facetProperties.containsKey("threshold"))
037: threshold = Integer.parseInt(facetProperties
038: .get("threshold"));
039: else {
040: logger
041: .warn("Could not find facet property with name 'threshold'. Falling back to default value MAX_VALUE");
042: threshold = Integer.MAX_VALUE;
043: }
044: }
045:
046: public String createUserFormat(CountGroup group,
047: ValueExpr valueExpr, Formatter valueFormatter) {
048: String format;
049: if (group.getMin().equals(group.getMax())) {
050: format = valueFormatter.format(valueExpr, group.getMin());
051: } else {
052: String s1 = valueFormatter
053: .format(valueExpr, group.getMin());
054: String s2 = valueFormatter
055: .format(valueExpr, group.getMax());
056: int end = s1.length() > s2.length() ? s2.length() : s1
057: .length();
058: int endPos = 0;
059: String si1 = s1.toLowerCase(locale);
060: String si2 = s2.toLowerCase(locale);
061: while (si1.startsWith(si2.substring(0, endPos))
062: && endPos < end)
063: endPos++;
064:
065: format = s1.substring(0, endPos) + " - "
066: + s2.substring(0, endPos);
067: }
068: return format;
069: }
070:
071: public void regroup(SortedMap<Object, CountGroup> groups) {
072: int minsize = threshold / 2 + 1;
073: int maxsize = threshold;
074: while (groups.size() < minsize || groups.size() > maxsize) {
075: if (groups.size() < minsize) {
076: // we shouldn't be able to go in here
077: } else if (groups.size() > maxsize) {
078: int mergeCount = groups.size() / minsize;
079: CountGroup g = null;
080: if (mergeCount > 1) {
081: Map.Entry<Object, CountGroup>[] entries = (Map.Entry<Object, CountGroup>[]) groups
082: .entrySet().toArray(
083: new Map.Entry[groups.size()]);
084: for (int i = 0; i < entries.length; i++) {
085: if (i % mergeCount == 0) {
086: g = entries[i].getValue();
087: } else {
088: g.merge(entries[i].getValue());
089: groups.remove(entries[i].getKey());
090: }
091: }
092: } else {
093: Object secondToLastKey = groups.headMap(
094: groups.lastKey()).lastKey();
095: g = groups.get(secondToLastKey);
096: g.merge(groups.get(groups.lastKey()));
097: groups.remove(groups.lastKey());
098: }
099: }
100: }
101: }
102:
103: @Override
104: protected String createQueryFormat(CountGroup g,
105: ValueExpr valueExpr, Formatter formatter) {
106: if (g.getMin().equals(g.getMax())) {
107: return formatter.format(valueExpr, g.getMin());
108: } else {
109: Object realmin = g.getMin(), realmax = g.getMax();
110: if (!facetConf.getSortAscending()) {
111: realmin = g.getMax();
112: realmax = g.getMin();
113: }
114:
115: return formatter.format(valueExpr, realmin) + " AND "
116: + formatter.format(valueExpr, realmax);
117: }
118: }
119:
120: private class CaseInsensitiveStringComparator<T extends Object>
121: implements Comparator<String> {
122: private final ValueComparator<String> delegate;
123:
124: private final Locale locale;
125:
126: public CaseInsensitiveStringComparator(boolean ascending,
127: Locale locale) {
128: delegate = new ValueComparator<String>(ascending, locale);
129: this .locale = locale;
130: }
131:
132: public int compare(String o1, String o2) {
133: return delegate.compare(o1.toUpperCase(locale), o2
134: .toUpperCase(locale));
135: }
136: }
137: }
|