}
}
}
private void rebuildMetadata(final String username, long apiKeyId) {
final Guest guest = guestService.getGuest(username);
String entityName = JPAUtils.getEntityName(LocationFacet.class);
int i=0;
final Query facetsQuery = em.createQuery(String.format("SELECT facet FROM %s facet WHERE facet.apiKeyId=? ORDER BY facet.start ASC", entityName));
facetsQuery.setParameter(1, apiKeyId);
while(true) {
facetsQuery.setFirstResult(i);
facetsQuery.setMaxResults(1000);
final List<LocationFacet> rawLocations = facetsQuery.getResultList();
//System.out.println(username + ": retrieved " + rawLocations.size() + " location datapoints (offset is " + i + ")");
if (rawLocations.size()==0)
break;
//System.out.println(username + ": " + AbstractLocalTimeFacet.timeStorageFormat.withZoneUTC().print(rawLocations.get(0).start));
long then = System.currentTimeMillis();
// Loop over the points to see if they're already included in visited cities entries
// it's important that the location points in the locations list are for a single apiKeyId
// and are in forward chronological order. Only add locations that aren't already contained
// within a VisitedCity item to the newLocations list
List<LocationFacet> newLocations=new ArrayList<LocationFacet>();
VisitedCity existingVisitedCityRecord = null;
for (LocationFacet locationFacet : rawLocations) {
// Check to see if this location is in the current existingVisitedCityRecord (if any)
if(existingVisitedCityRecord !=null && locationFacet.start <=existingVisitedCityRecord.end) {
// This location falls within the last fetched visited cities record, skip it
continue;
}
// This location doesn't fall within the last fetched visited cities record (if any).
// See if it fits in a new one. Note that this really assumes that locationFacet.start
// and locationFacet.end are the same and VisitedCity records are non-overlapping.
// It returns null if there are no visited city
// records overlapping the current point and non-null if there is one.
existingVisitedCityRecord = JPAUtils.findUnique(em, VisitedCity.class,
"visitedCities.byApiAndTime",
locationFacet.apiKeyId,
locationFacet.start,
locationFacet.end);
if(existingVisitedCityRecord == null) {
// This is a new point, add it
newLocations.add(locationFacet);
}
else {
// This point is already covered, skip it
}
}
if(newLocations.size()>0) {
long start = newLocations.get(0).start;
System.out.println(username + ": processing " + newLocations.size() + " new " + entityName +
" datapoints (offset is " + i + ", start is " + start +
" = " + AbstractLocalTimeFacet.timeStorageFormat.withZoneUTC().print(start) + " UTC)");
updateLocationMetadata(guest.getId(), newLocations);
}
else {
System.out.println(username + ": no new " + entityName + " location datapoints (offset is " + i + ")");
}