package org.limewire.promotion.impressions; import java.util.Calendar; import java.util.GregorianCalendar; import java.util.List; import java.util.concurrent.atomic.AtomicInteger; import org.limewire.util.ByteUtils; import org.limewire.util.StringUtils; /** * This is the data sent to the server. It includes a String query, and binary * data for the time and impressions. */ public class UserQueryEventData { private final UserQueryEvent event; private final long millisSinceToday; public UserQueryEventData(UserQueryEvent event, long millisSinceToday) { this.event = event; this.millisSinceToday = millisSinceToday; } public UserQueryEventData(UserQueryEvent event) { this(event, millisecondsSinceTheStartOfToday()); } public String getQuery() { return event.getOriginalQuery(); } // TODO: Improve to not include all the array creation public byte[] getData() { List<Impression> impressions = event.getImpressions(); /* * Format: * * number of impressions : 1 byte * milliseconds since start of the day : 4 bytes * original query time : 8 bytes * List of n=length of * n=binder name length : 1 byte * binder name : n bytes * promo ID : 8 bytes * impression time : 8 bytes */ int length = 1 + 4 + 8; for (Impression imp : impressions) { length += 1; length += StringUtils.toAsciiBytes(imp.getBinderUniqueName()).length; length += 8; length += 8; } byte[] bytes = new byte[length]; AtomicInteger inc = new AtomicInteger(0); bytes[inc.getAndAdd(1)] = (byte) (0xff & impressions.size()); System.arraycopy(ByteUtils.long2bytes(millisSinceToday, 4), 0, bytes, inc.getAndAdd(4), 4); System.arraycopy(ByteUtils.long2bytes(event.getOriginalQueryTime().getTime(), 8), 0, bytes, inc.getAndAdd(8), 8); for (int i = 0; i < impressions.size(); i++) { Impression imp = impressions.get(i); byte[] binderName = StringUtils.toAsciiBytes(imp.getBinderUniqueName()); bytes[inc.getAndAdd(1)] = (byte) (0xff & binderName.length); System.arraycopy(binderName, 0, bytes, inc.getAndAdd(binderName.length), binderName.length); System.arraycopy(ByteUtils.long2bytes(imp.getPromoUniqueID(), 8), 0, bytes, inc.getAndAdd(8), 8); System.arraycopy(ByteUtils.long2bytes(imp.getTimeShown().getTime(), 8), 0, bytes, inc.getAndAdd(8), 8); } return bytes; } /** * Returns the number of milliseconds since the start of the today. This is * exposed, so we can get it during testing. * * @return the number of milliseconds since the start of the today. */ long getMillisSinceToday() { return millisSinceToday; } /** * Returns the milliseconds since the start of today. * * @return */ static int millisecondsSinceTheStartOfToday() { return (int) (System.currentTimeMillis() - getFirstMillisecond()); } static long getFirstMillisecond() { int year = Calendar.getInstance().get(Calendar.YEAR); Calendar cal = new GregorianCalendar(year, 0, 1, 0, 0, 0); return cal.getTime().getTime(); } }