// all avails for all explicit resources for the time range, ordered by asc startTime
List<Availability> allAvailabilities = findResourceGroupAvailabilityWithinInterval(groupId, startDate, endDate);
// If we have no availabilities we need to return a single group avail, either EMPTY or WARN (all UNKNOWN)
if (allAvailabilities.isEmpty()) {
ResourceGroupAvailability groupAvail = new ResourceGroupAvailability(groupId);
groupAvail.setStartTime(startTime);
groupAvail.setEndTime(endTime);
int explicitMemberCount = resourceGroupManager.getExplicitGroupMemberCount(groupId);
groupAvail.setGroupAvailabilityType((0 == explicitMemberCount) ? GroupAvailabilityType.EMPTY
: GroupAvailabilityType.WARN);
result.add(groupAvail);
return result;
}
// OK, let's try and explain explain what we are doing here. The goal is to have a continuous set of intervals
// extending from startTime to endTime showing all changes in group avail. Each avail change for any member
// could signify a change in the overall group avail. We must first establish the initial group avail and
// then walk forward, checking for changes at each resource avail startTime for a group member.
// One subtlety is that group membership can change over time. We don't track when resources come and go, we
// are dealing with the avails for the *current* explicit members. So, we'll only work with the avails we have
// and not worry about missing avails at any given time. In other words, no "surrogate" UNKNOWN avail insertion.
// OK, calculate the initial group avail
Long atTime = startTime;
int atTimeIndex = 0;
ResourceGroupAvailability currentGroupAvail = null;
int size = allAvailabilities.size();
do {
GroupAvailabilityType groupAvailTypeAtTime = getGroupAvailabilityType(atTime, allAvailabilities);
// if this is a change in group avail type then add it to the result
if (null == currentGroupAvail || currentGroupAvail.getGroupAvailabilityType() != groupAvailTypeAtTime) {
if (null != currentGroupAvail) {
currentGroupAvail.setEndTime(atTime);
}
// leave endTime unset, we don't know endTime until we know the next startTime, or are done
currentGroupAvail = new ResourceGroupAvailability(groupId);
currentGroupAvail.setStartTime(atTime);
currentGroupAvail.setGroupAvailabilityType(groupAvailTypeAtTime);
result.add(currentGroupAvail);
}
// move atTime to the next possible startTime
while (atTimeIndex < size && allAvailabilities.get(atTimeIndex).getStartTime() <= atTime) {
++atTimeIndex;
}
if (atTimeIndex < size) {
atTime = allAvailabilities.get(atTimeIndex).getStartTime();
}
} while (atTimeIndex < size);
currentGroupAvail.setEndTime(endTime);
return result;
}