package com.browseengine.bobo.facets.impl;
import java.io.IOException;
import java.util.HashMap;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;
import java.util.Properties;
import java.util.Set;
import java.util.StringTokenizer;
import com.browseengine.bobo.api.BoboSegmentReader;
import com.browseengine.bobo.api.BrowseSelection;
import com.browseengine.bobo.api.FacetSpec;
import com.browseengine.bobo.facets.FacetCountCollectorSource;
import com.browseengine.bobo.facets.FacetHandler;
import com.browseengine.bobo.facets.FacetHandler.FacetDataNone;
import com.browseengine.bobo.facets.filter.EmptyFilter;
import com.browseengine.bobo.facets.filter.RandomAccessAndFilter;
import com.browseengine.bobo.facets.filter.RandomAccessFilter;
import com.browseengine.bobo.facets.filter.RandomAccessOrFilter;
import com.browseengine.bobo.sort.DocComparatorSource;
public class ComboFacetHandler extends FacetHandler<FacetDataNone> {
private static final String DFEAULT_SEPARATOR = ":";
private final String _separator;
public ComboFacetHandler(String name, Set<String> dependsOn) {
this(name, DFEAULT_SEPARATOR, dependsOn);
}
public ComboFacetHandler(String name, String seperator, Set<String> dependsOn) {
super(name, dependsOn);
_separator = seperator;
}
public String getSeparator() {
return _separator;
}
private static class ComboSelection {
final String name;
final String val;
private ComboSelection(String name, String val) {
this.name = name;
this.val = val;
}
static ComboSelection parse(String value, String sep) {
StringTokenizer strtok = new StringTokenizer(value, sep);
if (strtok.hasMoreTokens()) {
String name = strtok.nextToken();
if (strtok.hasMoreTokens()) {
String val = strtok.nextToken();
return new ComboSelection(name, val);
}
}
return null;
}
}
@Override
public RandomAccessFilter buildRandomAccessFilter(String value, Properties selectionProperty)
throws IOException {
RandomAccessFilter retFilter = EmptyFilter.getInstance();
ComboSelection comboSel = ComboSelection.parse(value, _separator);
if (comboSel != null) {
FacetHandler<?> handler = getDependedFacetHandler(comboSel.name);
if (handler != null) {
retFilter = handler.buildRandomAccessFilter(comboSel.val, selectionProperty);
}
}
return retFilter;
}
private static Map<String, List<String>> convertMap(String[] vals, String sep) {
Map<String, List<String>> retmap = new HashMap<String, List<String>>();
for (String val : vals) {
ComboSelection sel = ComboSelection.parse(val, sep);
if (sel != null) {
List<String> valList = retmap.get(sel.name);
if (valList == null) {
valList = new LinkedList<String>();
retmap.put(sel.name, valList);
}
valList.add(sel.val);
}
}
return retmap;
}
@Override
public RandomAccessFilter buildRandomAccessAndFilter(String[] vals, Properties prop)
throws IOException {
Map<String, List<String>> valMap = convertMap(vals, _separator);
Set<Entry<String, List<String>>> entries = valMap.entrySet();
List<RandomAccessFilter> filterList = new LinkedList<RandomAccessFilter>();
for (Entry<String, List<String>> entry : entries) {
String name = entry.getKey();
FacetHandler<?> facetHandler = getDependedFacetHandler(name);
if (facetHandler == null) {
return EmptyFilter.getInstance();
}
List<String> selVals = entry.getValue();
if (selVals == null || selVals.size() == 0) return EmptyFilter.getInstance();
RandomAccessFilter f = facetHandler.buildRandomAccessAndFilter(
selVals.toArray(new String[0]), prop);
if (f == EmptyFilter.getInstance()) return f;
filterList.add(f);
}
if (filterList.size() == 0) {
return EmptyFilter.getInstance();
}
if (filterList.size() == 1) {
return filterList.get(0);
}
return new RandomAccessAndFilter(filterList);
}
@Override
public RandomAccessFilter buildRandomAccessOrFilter(String[] vals, Properties prop, boolean isNot)
throws IOException {
Map<String, List<String>> valMap = convertMap(vals, _separator);
Set<Entry<String, List<String>>> entries = valMap.entrySet();
List<RandomAccessFilter> filterList = new LinkedList<RandomAccessFilter>();
for (Entry<String, List<String>> entry : entries) {
String name = entry.getKey();
FacetHandler<?> facetHandler = getDependedFacetHandler(name);
if (facetHandler == null) {
continue;
}
List<String> selVals = entry.getValue();
if (selVals == null || selVals.size() == 0) {
continue;
}
RandomAccessFilter f = facetHandler.buildRandomAccessOrFilter(selVals.toArray(new String[0]),
prop, isNot);
if (f == EmptyFilter.getInstance()) continue;
filterList.add(f);
}
if (filterList.size() == 0) {
return EmptyFilter.getInstance();
}
if (filterList.size() == 1) {
return filterList.get(0);
}
if (isNot) {
return new RandomAccessAndFilter(filterList);
} else {
return new RandomAccessOrFilter(filterList);
}
}
@Override
public DocComparatorSource getDocComparatorSource() {
throw new UnsupportedOperationException("sorting not supported for " + ComboFacetHandler.class);
}
@Override
public FacetCountCollectorSource getFacetCountCollectorSource(BrowseSelection sel, FacetSpec fspec) {
throw new UnsupportedOperationException("facet counting not supported for "
+ ComboFacetHandler.class);
}
@Override
public String[] getFieldValues(BoboSegmentReader reader, int id) {
Set<String> dependsOn = this.getDependsOn();
List<String> valueList = new LinkedList<String>();
for (String depends : dependsOn) {
FacetHandler<?> facetHandler = getDependedFacetHandler(depends);
String[] fieldValues = facetHandler.getFieldValues(reader, id);
for (String fieldVal : fieldValues) {
StringBuilder buf = new StringBuilder();
buf.append(depends).append(_separator).append(fieldVal);
valueList.add(buf.toString());
}
}
return valueList.toArray(new String[0]);
}
@Override
public int getNumItems(BoboSegmentReader reader, int id) {
Set<String> dependsOn = this.getDependsOn();
int count = 0;
for (String depends : dependsOn) {
FacetHandler<?> facetHandler = getDependedFacetHandler(depends);
String[] fieldValues = facetHandler.getFieldValues(reader, id);
if (fieldValues != null) {
count++;
}
}
return count;
}
@Override
public FacetDataNone load(BoboSegmentReader reader) throws IOException {
return FacetDataNone.instance;
}
}