in src/main/java/org/apache/sling/resourcemerger/impl/MergingResourceProvider.java [248:372]
public Iterator<Resource> listChildren(final ResolveContext<Void> ctx, final Resource parent) {
final ResourceResolver resolver = parent.getResourceResolver();
final String relativePath = getRelativePath(parent.getPath());
if (relativePath != null) {
// candidates is the list of holders from which the children are being constructed!
final List<ResourceHolder> candidates = new ArrayList<ResourceHolder>();
final Iterator<Resource> resources = picker.pickResources(resolver, relativePath, parent).iterator();
// start with the base resource
boolean isUnderlying = true;
while (resources.hasNext()) {
Resource parentResource = resources.next();
final ResourceHidingHandler handler = !isUnderlying ? new ResourceHidingHandler(parentResource, this.traverseHierarchie) : null;
isUnderlying = false;
// remove the hidden child resources from the underlying resource
if (handler != null) {
final Iterator<ResourceHolder> iter = candidates.iterator();
while (iter.hasNext()) {
final ResourceHolder holder = iter.next();
if (handler.isHidden(holder.name, false)) {
iter.remove(); // remove from the candidates list
}
}
}
int previousChildPositionInCandidateList = -1;
// get children of current resource (might be overlaid resource)
for (final Resource child : parentResource.getChildren()) {
final String rsrcName = child.getName();
// the holder which should end up in the children list
ResourceHolder holder = null;
int childPositionInCandidateList = -1;
// check if this an overlaid resource (i.e. has the resource with the same name already be exposed through the underlying resource)
for (int index=0; index < candidates.size(); index++) {
ResourceHolder current = candidates.get(index);
if (current.name.equals(rsrcName)) {
holder = current;
childPositionInCandidateList = index;
break;
}
}
// for new resources, i.e. no underlying resource found...
if (holder == null) {
// remove the hidden child resources from the local resource
if (handler != null && handler.isHidden(rsrcName, true)) {
continue; // skip this child
}
holder = new ResourceHolder(rsrcName);
if (previousChildPositionInCandidateList != -1) {
// either add after the previous child position
candidates.add(previousChildPositionInCandidateList+1, holder);
previousChildPositionInCandidateList++;
} else {
// or add to the end of the list
candidates.add(holder);
previousChildPositionInCandidateList = candidates.size() - 1;
}
}
// in all cases the holder should get the current child!
holder.resources.add(child);
// Check if children need reordering
int orderBeforeIndex = -1;
final ValueMap vm = child.getValueMap();
final String orderBefore = vm.get(MergedResourceConstants.PN_ORDER_BEFORE, String.class);
if (orderBefore != null && !orderBefore.equals(rsrcName)) {
// search entry
int index = 0;
while (index < candidates.size()) {
final ResourceHolder current = candidates.get(index);
if (current.name.equals(orderBefore)) {
orderBeforeIndex = index;
break;
}
index++;
}
}
// either reorder because of explicit reording property
if (orderBeforeIndex > -1) {
candidates.add(orderBeforeIndex, holder);
if (childPositionInCandidateList == -1) {
candidates.remove(candidates.size() - 1);
} else {
if (childPositionInCandidateList > orderBeforeIndex) {
childPositionInCandidateList++;
}
candidates.remove(childPositionInCandidateList);
}
} else {
// or reorder because overlaid resource has a different order
if (childPositionInCandidateList != -1 && previousChildPositionInCandidateList != -1) {
candidates.remove(childPositionInCandidateList);
if (childPositionInCandidateList < previousChildPositionInCandidateList) {
previousChildPositionInCandidateList--;
}
if(previousChildPositionInCandidateList+1 > candidates.size()){
candidates.add(holder);
} else {
candidates.add(previousChildPositionInCandidateList + 1, holder);
}
previousChildPositionInCandidateList++;
}
}
}
}
final List<Resource> children = new ArrayList<Resource>();
for (final ResourceHolder holder : candidates) {
final Resource mergedResource = this.createMergedResource(resolver,
(relativePath.length() == 0 ? holder.name : relativePath + '/' + holder.name), holder);
if (mergedResource != null) {
children.add(mergedResource);
}
}
return children.iterator();
}
return null;
}