package org.styloot.hobo.hoboindex;
import java.util.*;
import java.io.*;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.styloot.hobo.*;
import org.styloot.hobo.itemfinders.ItemFinder;
import org.styloot.hobo.itemfinders.SubsetIndexItemFinder;
import org.styloot.hobo.itemfinders.*;
import org.styloot.hobo.iterators.*;
import org.styloot.hobo.hoboindex.HoboIndex;
public class SimpleHoboIndex implements HoboIndex {
private static final Logger log = LoggerFactory.getLogger(SimpleHoboIndex.class);
public SimpleHoboIndex(Collection<Item> items) {
this(items.iterator());
}
public SimpleHoboIndex(Item[] items) {
this(Util.collectionFromArray(items));
}
public SimpleHoboIndex(Iterator<Item> items) {
Map<String,List<Item>> catToItems = categoriesToItems(items);
log.info("Initializing HoboIndex with " + catToItems.size() + " categories.");
//Now we need to build ItemFinders
for (String cat : catToItems.keySet()) {
categoryMap.put(cat, new SubsetIndexItemFinder(catToItems.get(cat), cat));
}
log.info("ItemFinders built.");
}
public Iterator<Item> find(String cat, Collection<String> features, CIELabColor color, double dist, int minPrice, int maxPrice) {
if (dist < 0) { //Negative color distance implies no color query
color = null;
}
Vector<Iterator<Item>> iters = new Vector<Iterator<Item>>();
Collection<ItemFinder> categories;
if ((cat != "") && (cat != null)) {
categories = categoryMap.itemFinders(cat);
} else {
categories = categoryMap.values(); //Small performance improvement in case of no category
}
for (ItemFinder finder : categories) {
iters.add(finder.find(features, color, dist, minPrice, maxPrice));
}
return new CombinedIterator(iters);
}
private CategoryMap categoryMap = new CategoryMap();
protected Map<String,List<Item>> categoriesToItems(Iterator<Item> items) {
Map<String,List<Item>> result = new HashMap<String,List<Item>>();
for (Iterator<Item> iter = items; iter.hasNext();) {
Item item = iter.next();
if (!result.containsKey(item.category.name)) {
result.put(item.category.name, new LinkedList<Item>());
}
result.get(item.category.name).add(item);
}
return result;
}
private static class CategoryMap extends TreeMap<String,ItemFinder> {
public NavigableMap<String,ItemFinder> findSubCategoriesMap(String key) {
return subMap(key, true, key+Character.MAX_VALUE, true);
}
public Collection<ItemFinder> itemFinders(String key) {
return findSubCategoriesMap(key).values();
}
public Set<String> subcategories(String key) {
return findSubCategoriesMap(key).keySet();
}
}
public static void main(String[] args) {
Vector<Item> items = new Vector<Item>();
for (int i=0;i<10;i++) {
Vector<String> f = new Vector<String>();
f.add("foo");
if (i % 2 == 0)
f.add("bar");
if (i % 3 == 0)
items.add(new Item("id" + i, "/dress", f, i, null, i));
if (i % 3 == 1)
items.add(new Item("id" + i, "/dress/short", f, i, null, i));
if (i % 3 == 2)
items.add(new Item("id" + i, "/skirt", f, i, null, i));
}
HoboIndex idx = new SimpleHoboIndex(items);
Vector<String> f = new Vector<String>();
f.add("foo");
f.add("bar");
for (Iterator<Item> i = idx.find("/dress", f, null, 0, 2, Integer.MAX_VALUE); i.hasNext(); ) {
Item item = (Item)i.next();
System.out.println(item.id + " -> " + item.category + " , " + item.quality + " , " + item.cost);
}
}
}