/////
// Now we need to loop over batches of the resource ID list - asking the server for their resource representations.
// When we get the resources from the server, we put them in our resourceMap, keyed on ID.
final boolean isDebugEnabled = log.isDebugEnabled();
final StopWatch stopWatch = new StopWatch();
String marker = null;
Map<Integer, Resource> resourceMap = new HashMap<Integer, Resource>(resourceIdList.size());
int batchNumber = 0;
while (!resourceIdList.isEmpty()) {
// Our current batch starts at the head of the list, but
// we need to determine how big our current batch should be and where in the list of IDs that batch ends
int size = resourceIdList.size();
int end = (SYNC_BATCH_SIZE < size) ? SYNC_BATCH_SIZE : size;
batchNumber++;
// Determine the content of our current batch - this is simply a sublist of our IDs list.
// Note that we use .clear() once we get the batch array in order to advance our progress and help GC.
// This usage of .clear() will remove the processed resources from the backing list.
String markerPrefix = null;
if (isDebugEnabled) {
markerPrefix = String.format("a. Batch [%03d] (%d): ", batchNumber, syncInfos.size());
marker = String.format("%sGet resource ID sublist - %d of %d remaining", markerPrefix, end, size);
stopWatch.markTimeBegin(marker);
}
List<Integer> resourceIdBatch = resourceIdList.subList(0, end);
Integer[] resourceIdArray = resourceIdBatch.toArray(new Integer[resourceIdBatch.size()]);
resourceIdBatch.clear();
if (isDebugEnabled) {
stopWatch.markTimeEnd(marker);
marker = markerPrefix + "Get sublist of resources from server";
stopWatch.markTimeBegin(marker);
}
// Ask the server for the resource representation of all resource IDs in our batch.
// This is a potentially expensive operation depending on the size of the batch and the content of the resources.
List<Resource> resourceBatch = configuration.getServerServices().getDiscoveryServerService()
.getResourcesAsList(resourceIdArray);
if (isDebugEnabled) {
stopWatch.markTimeEnd(marker);
marker = markerPrefix + "Store sublist of resources to map";
stopWatch.markTimeBegin(marker);
}
// Now that the server told us the resources in our batch, we add them to our master map.
// Note our usage of clear on the batch - this is to help GC.
for (Resource r : resourceBatch) {
// protect against childResources notNull assumptions downstream
if (null == r.getChildResources()) {
r.setChildResources(new CopyOnWriteArraySet()); // this will actually initialize to an empty Set
}
compactResource(r);
resourceMap.put(r.getId(), r);
}
resourceBatch.clear();
if (isDebugEnabled) {
stopWatch.markTimeEnd(marker);
}
}
if (syncInfos.size() != resourceMap.size()) {
log.warn("Expected [" + syncInfos.size() + "] but found [" + resourceMap.size()
+ "] resources when fetching from server");
}
/////
// We now have all the resources associated with all sync infos in a map.
// We need to build the full resource tree using the resource parent info as the blueprint for how to
// link the resources in the tree.
if (isDebugEnabled) {
marker = "b. Build the resource hierarchies";
stopWatch.markTimeBegin(marker);
}
// The root resources to be merged (i.e. the resources whose parents are not in the map)
Set<Resource> result = new HashSet<Resource>();
for (Resource resource : resourceMap.values()) {
if (null == resource.getParentResource()) {
result.add(resource); // the platform, make sure we have this
continue;
}
Resource parent = resourceMap.get(resource.getParentResource().getId());
if (null != parent) {
parent.addChildResource(resource);
} else {
result.add(resource);
}
}
if (isDebugEnabled) {
stopWatch.markTimeEnd(marker);
log.debug("Resource trees built from map - performance: " + stopWatch);
}
return result;