public Iterator listChildren()

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;
    }