gt: 			StringBuilder sb_asLongs = new StringBuilder();
context: /*
   * Part of the NDNx Java Library.
   *
   * Portions Copyright (C) 2013 Regents of the University of California.
   * 
   * Based on the CCNx C Library by PARC.
   * Copyright (C) 2011-2012 Palo Alto Research Center, Inc.
   *
   * This library is free software; you can redistribute it and/or modify it
   * under the terms of the GNU Lesser General Public License version 2.1
   * as published by the Free Software Foundation. 
   * This library is distributed in the hope that it will be useful,
   * but WITHOUT ANY WARRANTY; without even the implied warranty of
   * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
   * Lesser General Public License for more details. You should have received
   * a copy of the GNU Lesser General Public License along with this library;
   * if not, write to the Free Software Foundation, Inc., 51 Franklin Street,
   * Fifth Floor, Boston, MA 02110-1301 USA.
   */
  
  package org.ndnx.ndn.profiles.versioning;
  
  import java.io.Serializable;
  import java.security.InvalidParameterException;
  import java.util.ArrayList;
  import java.util.Comparator;
  import java.util.Iterator;
  import java.util.logging.Level;
  
  import org.ndnx.ndn.impl.support.Log;
  import org.ndnx.ndn.impl.support.TreeSet6;
  import org.ndnx.ndn.profiles.VersioningProfile;
  import org.ndnx.ndn.protocol.Component;
  import org.ndnx.ndn.protocol.ContentName;
  import org.ndnx.ndn.protocol.Exclude;
  import org.ndnx.ndn.protocol.ExcludeAny;
  import org.ndnx.ndn.protocol.ExcludeComponent;
  import org.ndnx.ndn.protocol.Interest;
  
  
  /**
   * Stores state about a specific Interest on the wire.  This class does not
   * do any network transactions, it only stores state about a specific interest
   * and will generate a new Interest message based on its current start, stop,
   * and exclusion list.
   * 
   */
  public class InterestData {
  
  	// VersioningInterestManager uses an ordering by _startTime.
  	// For a data structure like TreeSet to be serializable, its comparator must be serializable
  	public static class StartTimeComparator implements Comparator<InterestData>, Serializable {
  		private static final long serialVersionUID = -1033458449981547213L;
  
  		/**
  		 * Order by startTime using UNSIGNED COMPARISON
  		 */
  		public int compare(InterestData arg0, InterestData arg1) {
  			synchronized(arg0) {
  				synchronized(arg1) {
  					return(arg0._startTime.compareTo(arg1._startTime));
  				}
  			}
  		}
  	}
  	
  	/**
  	 * An Interest with unbounded timespan
  	 * @param basename
  	 */
  	public InterestData(ContentName basename) {
  		this(basename, VersionNumber.getMinimumVersion(), VersionNumber.getMaximumVersion());
  	}
  
  	/**
  	 * An Interest with only a lower bound
  	 * @param basename
  	 * @param startTime
  	 */
  	public InterestData(ContentName basename, VersionNumber startTime) {
  		this(basename, startTime, VersionNumber.getMaximumVersion());
  	}
  
  	/**
  	 * @param startTime minimum version to include.
  	 * @param stopTime maximum version to include.
  	 */
  	public InterestData(ContentName basename, VersionNumber startTime, VersionNumber stopTime) {
  		_name = basename;
  
  		setStartTime(startTime);
  		setStopTime(stopTime);
  	}
  
  	public synchronized int size() {
  		return _excludedVersions.size();
  	}
  
  	/**
  	 * Implement equals based on name, startTime, stopTime, and the excluded version numbers
  	 */
  	@Override
  	public synchronized boolean equals(Object obj) throws ClassCastException {
  		if( null == obj )
  			throw new ClassCastException("Null value");
  
  		if( !(obj instanceof InterestData) )
  			throw new ClassCastException("Not a InterestData");
  
  		synchronized(obj) {
  			InterestData other = (InterestData) obj;
  
  			if( _name.equals(other._name) ) {
  				if(_startTime.equals(other._startTime) && _stopTime.equals(other._stopTime) ) {
  					if( _excludedVersions.equals(other._excludedVersions) ) {
  						return true;
  					}
  				}
  			}
  			return false;
  		}
  	}
  
  	/**
  	 * Implement hashCode() so we can ensure consistency with equals
  	 */
  	@Override
  	public synchronized int hashCode() {
  		final int prime = 31;
  		int result = 1;
  
  		result = prime * result + _name.hashCode();
  		result = prime * result + _startTime.hashCode();
  		result = prime * result + _stopTime.hashCode();
  
  		// this is the cumulative hashcode of everything in the set
  		result = prime * result + _excludedVersions.hashCode();
  
  		return result;
  	}
  
  
  	/**
  	 * Dont do this while in a sorted set, as the sort order will break.
  	 * Start time is the minimum version to include.
  	 * in milliseconds (not binarytime)
  	 * 
  	 @param startTime minimum version to include (milliseconds).  The earliest time is NO_START_TIME.
  	 *                  if a startTime < NO_START_TIME is given (e.g. 0), NO_START_TIME is used.
  	 */
  	public synchronized void setStartTime(VersionNumber startTime) {
  		if( VersionNumber.getMinimumVersion().after(startTime) )
  			startTime = VersionNumber.getMinimumVersion();
  
  		_startTime = startTime;
  		_dirty = true;
  	}
  
  	/**
  	 * stopTime is the maximum version to include.
  	 * use NO_STOP_TIME for infinity. If a greater value (unsigned comparison) is
  	 * given, NO_STOP_TIME is used.
  	 * in milliseconds (not binarytime)
  	 */
  	public synchronized void setStopTime(VersionNumber stopTime) {
  		if( VersionNumber.getMaximumVersion().before(stopTime) )
  			stopTime = VersionNumber.getMaximumVersion();
  
  		_stopTime = stopTime;
  		_dirty = true;
  	}
  
  	/**
  	 * Returns false if too many excludes in this Interest
  	 * @param version
  	 * @return
  	 */
  	public synchronized boolean addExclude(VersionNumber version) {
  		if( _excludedVersions.size() >= VersioningInterestManager.MAX_FILL ) {
  			if( Log.isLoggable(Log.FAC_ENCODING, Level.FINE) )
  				Log.fine(Log.FAC_ENCODING, "addExclude full, not adding {0}", version);
  			return false;
  		}
  		addExcludeUnbounded(version);
  		return true;
  	}
  
  	public synchronized Interest buildInterest() {
  		if( !_dirty )
  			return _interest;
  
  		ArrayList<Exclude.Element> components = new ArrayList<Exclude.Element>();
  
  		byte [] startTimeMinusOneComponent;
  
  		if( VersionNumber.getMinimumVersion().before(_startTime) ) {
  			VersionNumber startTimeMinusOne = _startTime.addAndReturn(-1);
  			startTimeMinusOneComponent = startTimeMinusOne.getVersionBytes();
  		} else {
  			// if we're starring at 0, exclude below that.  We actually cannot
  			// express this as a NDNTime
  			startTimeMinusOneComponent = VersioningProfile.BOTTOM_EXCLUDE_VERSION_MARKER;
  		}
  
  		components.add(new ExcludeAny());
  		components.add(new ExcludeComponent(startTimeMinusOneComponent));
  		if( Log.isLoggable(Log.FAC_ENCODING, Level.FINEST) )
  			Log.finest(Log.FAC_ENCODING, "Exclusion: start version {0}", 
  					Component.printURI(startTimeMinusOneComponent));
  
  		// Now add the specific exclusions
  
  		ExcludeComponent lastComponentExcluded = null;
  		// TreeSet is sorted, so this is in right order for the exclusion filter
  		Iterator<VersionNumber> i = _excludedVersions.iterator();
  		while( i.hasNext() ) {
  			VersionNumber elem = i.next();
  			lastComponentExcluded = new ExcludeComponent(elem.getVersionBytes());
  			components.add(lastComponentExcluded);
  		}
  
  		// Now exclude everything after stop time
  		ExcludeComponent exStop = null;
  		byte [] stopTimePlusOneComponent;
  
  		if( VersionNumber.getMaximumVersion().after(_stopTime))
  			stopTimePlusOneComponent = _stopTime.addAndReturn(1).getVersionBytes();
  		else
  			stopTimePlusOneComponent = VersioningProfile.TOP_EXCLUDE_VERSION_MARKER;
  
  		exStop = new ExcludeComponent(stopTimePlusOneComponent);
  
  		// It could happen that our stop time is exactly equal to the version of an
  		// exclusion we already made.  if that's the case, don't add a duplicate
  		if( null == lastComponentExcluded || ! lastComponentExcluded.equals(exStop) )
  			components.add(exStop);
  
  		components.add(new ExcludeAny());
  
  		if( Log.isLoggable(Log.FAC_ENCODING, Level.FINEST) )
  			Log.finest(Log.FAC_ENCODING, "Exclusion: stop  version {0}", exStop.toString());
  
  		Exclude exclude;
  
  		try {
  			exclude = new Exclude(components);
  		} catch(InvalidParameterException ipe) {
  			// all of this verbosity was to catch a bug in the startTime component.
  			// That's fixed now, but if this ever comes up, its something serious.
  			ipe.printStackTrace();
  			Log.severe(Log.FAC_ENCODING, this.toString());
  			StringBuilder sb_asVersion = new StringBuilder();
  