package com.mongodb.hvdf.util; import java.util.ArrayList; import java.util.Collections; import java.util.Comparator; import java.util.List; import org.bson.types.ObjectId; import com.mongodb.DBObject; import com.mongodb.hvdf.api.Sample; public class ContentListHelper { private static Comparator<Sample> backwardTimeComparator = new Comparator<Sample>() { @Override public int compare(Sample o1, Sample o2) { final ObjectId oid2 = (ObjectId)o2.getId(); final ObjectId oid1 = (ObjectId)o1.getId(); final int compare = oid2.compareTo(oid1); return compare; }}; private static Comparator<Sample> timeOrderComparator = new Comparator<Sample>() { @Override public int compare(Sample o1, Sample o2) { final ObjectId oid2 = (ObjectId)o2.getId(); final ObjectId oid1 = (ObjectId)o1.getId(); final int compare = oid1.compareTo(oid2); return compare; }}; public static List<Sample> extractContent( final List<Sample> source, final DBObject anchor, final int limit, final boolean allowFutureAnchor){ int count = Math.abs(limit); final boolean forward = limit > 0; List<Sample> results = new ArrayList<Sample>(count); if(anchor != null){ // find the anchor object, then walk backward or forward in time Sample markerObject = new Sample(anchor); int index = Collections.binarySearch(source, markerObject, timeOrderComparator); // if the anchor is past all values, it needs to be allowed if(Math.abs(index) < source.size() || allowFutureAnchor){ if(forward == true){ index = index < 0 ? Math.abs(index) - 2 : Math.abs(index) - 1; for(int i = index; i >= 0 && count-- > 0; --i){ results.add(source.get(i)); } } else { index = index < 0 ? Math.abs(index) - 1 : Math.abs(index) + 1; for(int i = index; i < source.size() && count-- > 0; ++i){ results.add(source.get(i)); } Collections.reverse(results); } } } else if(forward == true) { // just read from the end of the user content list for(int i = source.size() - 1; i >= 0 && count-- > 0; --i) results.add(source.get(i)); } return results; } public static ListWalker<Sample> getContentWalker( final List<Sample> source, final DBObject anchor, final int limit) { ListWalker<Sample> walker = null; if(anchor == null){ // Use reverse list walker for each user content list return new ReverseListWalker<Sample>(source); } else { Sample markerObject = new Sample(anchor); int index = Collections.binarySearch(source, markerObject, timeOrderComparator); if(limit > 0){ // Use reverse list walker anchored in each user content list index = index < 0 ? Math.abs(index) - 2 : Math.abs(index) - 1; walker = new ReverseListWalker<Sample>(source, index); } else { // Use forward list walker anchored in each user content list index = index < 0 ? Math.abs(index) - 1 : Math.abs(index) + 1; walker = new ListWalker<Sample>(source, index); } } return walker; } public static List<Sample> merge(final List<ListWalker<Sample>> walkers, final int limit) { int count = Math.abs(limit); boolean forward = limit > 0; Comparator<Sample> comparator = forward == true ? backwardTimeComparator : timeOrderComparator; List<Sample> result = new ArrayList<Sample>(count); ListWalker<Sample> lowest; while (result.size() < count) { lowest = null; for (ListWalker<Sample> l : walkers) { if (! l.atEnd()) { if (lowest == null) { lowest = l; } else if (l.get() != null && comparator.compare(l.get(), lowest.get()) <= 0) { lowest = l; } } } // Add the lowest value to the result or break if // all lists have been exhausted if(lowest != null) result.add(lowest.step()); else break; } if(forward == false) Collections.reverse(result); return result; } }