package org.styloot.hobo.itemfinders;
import java.util.*;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.styloot.hobo.*;
import org.styloot.hobo.itemfinders.*;
import org.styloot.hobo.iterators.*;
public class ShallowIndexItemFinder implements ItemFinder {
private static final Logger log = LoggerFactory.getLogger(ShallowIndexItemFinder.class);
public ShallowIndexItemFinder(Collection<Item> myItems, String cat) {
items = new Vector<Item>(myItems);
Collections.sort(items);
category = cat;
Set<Feature> features = new HashSet<Feature>();
for (Item item : items) {
if (item.getFeatures() != null) {
for (Feature feature : item.getFeatures()) {
features.add(feature);
}
}
}
featureIndex = new HashMap<Feature,ItemFinder>();
for (Feature feature : features) {
Vector<Item> indexItems = new Vector<Item>();
int itemsAdded = 0;
for (Item i : items) {
if (i.hasFeature(feature)) {
indexItems.add(i);
itemsAdded += 1;
}
}
if (itemsAdded > 0) {
featureIndex.put(feature, new VectorItemFinder(indexItems, category));
}
}
}
private final Map<Feature,ItemFinder> featureIndex;
private final Vector<Item> items;
private final String category;
public int size() {
return items.size();
}
public Iterator<Item> getItems() {
return items.iterator();
}
public Iterator<Item> find(Collection<String> features, CIELabColor color, double distance, int minPrice, int maxPrice) {
//If we have a best feature, just defer to that one's ItemFinder
Feature bff = bestFinderFeature(features);
if (bff != null) {
Vector<String> searchFeatures = new Vector<String>(features);
searchFeatures.remove(bff.name);
return featureIndex.get(bff).find(searchFeatures, color, distance, minPrice, maxPrice);
}
//Otherwise, we just iterate over our own items.
Iterator<Item> iterator = items.iterator();
iterator = CostFilterIterator.wrap(iterator, minPrice, maxPrice);
iterator = FeaturesFilterIterator.wrap(iterator, features);
iterator = ColorFilterIterator.wrap(iterator, color, distance);
return iterator;
}
private Feature bestFinderFeature(Collection<String> features) {
// Finds the feature corresponding to the ItemFinder with the fewest items.
if (features == null || features.size() == 0) {
return null;
}
int minSize = Integer.MAX_VALUE;
ItemFinder bestFinder = null;
Feature bestFeature = null;
for (String f : features) {
Feature feature = Feature.getFeature(f);
ItemFinder finder = featureIndex.get(feature);
if ((finder != null) && (finder.size() < minSize)) {
bestFinder = finder;
minSize = bestFinder.size();
bestFeature = feature;
}
}
return bestFeature;
}
}