Hi Jörg,

I think this is, in part, a matter of personal experience. My team and I have 
found traversing a sub tree traversal so useful that I've created libraries of 
predicates and an expression language to ease the creation of predicates for 
those traversals. I would estimate that we use a traversal about 2 - 3 times  a 
month, sometimes as part of a new component, or when pulling reports and 
operational queries.

We use it, when writing code, more then get/list children of a resource.

I do think the ability to do a traversal should be part of a core library, the 
reasoning for that is that there are currently multiple instances of a some 
sort of tree traversal in multiple bundles now. From Sling Query to the default 
GET servlets. When I start seeing the same thing over and over again that tells 
me it should be centralized.

I did just commit one change based on this conversation, since their tends to 
be a focus on "whole subtree" which is something I don't actually use, I 
removed the method

- stream();

leaving just

- stream(Predicate<Resource>)

That leaves open the possibility of static predicates to do things like

stream(CHILDREN);
stream(ALL_DESCENDANTS)
stream(PAGES)

As for extensions of existing methods, I think there would be an interest in 
that. maybe something like

Stream<Resource> listChildren(Predicate<Resource> childSelector);

which I think would make a great patch.

 I appreciate the feedback.

Thanks!
- Jason

On Tue, Jun 5, 2018, at 6:30 PM, Jörg Hoh wrote:
> Hi,
> 
> sorry for joining the game a bit late ... At the moment it's not clear to
> me, why we actually want to extend the API with this functionality; while I
> totally understand the value and beauty of streams, I wonder if the usecase
> "traverse the whole subtree" happens really that often that it qualifies
> for an extension of the API. Personally I implemented it once or twice over
> the course of some years, but that's not something I need to have in the
> public API. I consider it as a convenience function I can easily implement
> on top of the already existing Resource API.
> 
> I would rather provide versions of the listChildren method which return
> streams (or any other method of the Resource API which returns a list  or
> an iterator over resources).
> 
> Jörg
> 
> 
> 2018-06-04 20:24 GMT+02:00 Jason E Bailey <j...@apache.org>:
> 
> > At this point I'm looking for feedback to say whether there is a consensus
> > that the proposed API
> >
> > - stream()
> > - stream(Predicate<Resource>)
> >
> > where each one attempts to iterate through the tree is *sufficient enough
> > for the initial release*. I believe Stefan's concern was that he believed
> > someone encountering stream() on a resource would believe that it's only a
> > stream of the immediate children.
> >
> > I believe, he would prefer something like
> >
> > - treeStream()
> >
> > I'm inclined to see just stream() as the base method, as that's the
> > standard convention for a method that generates a stream.
> >
> > feedback appreciated.
> > Also there is a new pull request now that I've rolled everything back
> > https://github.com/apache/sling-org-apache-sling-api/pull/5
> >
> >
> >
> > - Jason
> >
> > On Mon, Jun 4, 2018, at 2:02 PM, Jason E Bailey wrote:
> > > You got it. Thats's what I was attempting to describe and that's the
> > > type of filtering we do a lot of.
> > >
> > > - Jason
> > >
> > > On Mon, Jun 4, 2018, at 1:58 PM, Daniel Klco wrote:
> > > > It seems redundant, but I think they're somewhat different concepts.
> > The
> > > > Predicate passed into the stream method is for evaluating the Resources
> > > > relevant for traversal, whereas (at least I'm assuming) that any
> > subsequent
> > > > filters would filter the subsequent stream of resources. Having that
> > sort
> > > > of redundancy would allow you to traverse a structure like the
> > following:
> > > >
> > > > - myasset.jpg (dam:Asset)
> > > >   - renditions (nt:folder)
> > > >     - original (nt:file)
> > > >     - rendition1.jpg (nt:file)
> > > >
> > > > so if you wanted to get just a stream of the nt:file resources you
> > could do:
> > > >
> > > > myassetResource.stream(maxDepth(2)).filter(isResourceType("nt:file")).
> > forEach(e
> > > > -> {DO_SOMETHING});
> > > >
> > > > I like the idea of adding the predicates either in the API or as a
> > separate
> > > > dependency as there are likely a few common patterns that would be used
> > > > quite a bit.
> > > >
> > > > -Dan
> > > >
> > > > On Mon, Jun 4, 2018 at 1:31 PM, Jason E Bailey <j...@apache.org> wrote:
> > > >
> > > > >
> > > > >
> > > > > - Jason
> > > > >
> > > > > On Mon, Jun 4, 2018, at 12:35 PM, Daniel Klco wrote:
> > > > >
> > > > > >
> > > > > > Rather than having another parameter, what about providing a
> > > > > > ResourceChildrenPredicate? Based on the current API it looks like
> > you'd
> > > > > > have to provide the current resource to make this work, but it
> > seems like
> > > > > > it would be very useful to have a predicate which would only allow
> > for
> > > > > both
> > > > > > direct children or children up to a particular depth. I'd see it
> > useful
> > > > > to
> > > > > > provide 2-3 different default predicates to help with common
> > activities:
> > > > > >
> > > > > > ResourceChildrenPredicate - filter the stream of resources based
> > on their
> > > > > > child status
> > > > > > ResourceTypePredicate - filter the stream of resource based on
> > their
> > > > > > resource type
> > > > > > ValuePredicate - filter the stream of resources based on a value
> > in the
> > > > > > resource's ValueMap
> > > > > >
> > > > > >
> > > > >
> > > > > Funny you should mention this. The original ResourceStream object
> > came
> > > > > from the whiteboard streams project. Which has a whole package
> > dedicated
> > > > > to defining static predicates. There's even an expression languages
> > in
> > > > > their as well. However, for filtering, there's already a filter
> > method that
> > > > > a Stream provides. It's redundant to have a pre-filtered stream.
> > > > >
> > > > > However, as a limitation on the stream, you can do the same thing. It
> > > > > would something like
> > > > >
> > > > > - resource.stream(CHILD_RESOURCES);
> > > > >
> > > > > or
> > > > >
> > > > > - resource.stream(maxDepth(1));
> > > > >
> > > > > maxDepth being a static method that you've imported from the
> > appropriate
> > > > > library that provides a Predicate
> > > > >
> >
> 
> 
> 
> -- 
> Cheers,
> Jörg Hoh,
> 
> http://cqdump.wordpress.com
> Twitter: @joerghoh

Reply via email to