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; } }