package org.archive.cdxserver.processor; import java.util.Date; import java.util.TreeMap; import org.archive.format.cdx.CDXLine; import org.archive.util.ArchiveUtils; public class ClosestTimestampSorted extends WrappedProcessor { enum Dir { ANY, PREV, NEXT, }; Dir dir; TreeMap<Long, CDXLine> closestLines; Long target; int limit; boolean done = false; protected Long convTimestamp(String timestamp) { return ArchiveUtils.getDate(timestamp, new Date()).getTime(); } public ClosestTimestampSorted(BaseProcessor output, String target, int limit) { super(output); if (target.startsWith("-")) { target = target.substring(1); dir = Dir.PREV; } else if (target.startsWith("^")) { target = target.substring(1); dir = Dir.NEXT; } else { dir = Dir.ANY; } this.target = convTimestamp(target); this.limit = (limit > 0 ? limit : Integer.MAX_VALUE); closestLines = new TreeMap<Long, CDXLine>(); } @Override public int writeLine(CDXLine line) { if (done) { return Integer.MAX_VALUE; } Long curr = convTimestamp(line.getTimestamp()); Long diff; switch (dir) { case PREV: if (curr < target) { diff = target - curr; } else { diff = target + curr; } break; case NEXT: if (curr > target) { diff = curr - target; } else { diff = (target - curr) + target * 2; } break; case ANY: default: diff = Math.abs(curr - target); break; } if (closestLines.size() == limit) { // Assumes ascending timestamp input if (diff > closestLines.lastKey()) { done = true; return writeSorted(); } } closestLines.put(diff, line); if (closestLines.size() > limit) { closestLines.remove(closestLines.lastKey()); } return 0; } protected int writeSorted() { int count = 0; for (CDXLine line : closestLines.values()) { super.writeLine(line); ++count; } closestLines.clear(); return count; } @Override public void writeResumeKey(String resumeKey) { writeSorted(); super.writeResumeKey(resumeKey); } @Override public void end() { writeSorted(); super.end(); } }