How iterate over a potentially infinite collection of collections using JSTL
Preface: I am a l开发者_如何学Pythonong-time fan of SO, read stuff here almost everyday -- but this is my first question -- thank you to everyone who has made SO such a fantastic resource!
Environment: Spring/JSTL/Java ; the constraints of this project are such that I cannot accept a solution which requires abandoning Spring/Java, though I could probably implement any standard view in place of JSTL.
Note: This question is not about how to iterate over a simple collection in JSTL; I know how to do that. Additionally, I have searched SO and Google for an answer to this problem and have yet to find an answer. I am willing to admit that maybe that indicates that I am approaching the problem incorrectly -- if so, I would appreciate an explanation of a better way to approach it.
Problem: I have a data-service from which I obtain a collection of collections. I do not control this service, nor am I able to define it -- someone else is in charge of that, and it can change at any time. Each item in the collection can be another collection (which I must parse), so the entire collection is theoretically unbounded. The collection is basically like this:
- Item name : String
- Item : Object (can be a String or another Collection) (this sequence is potentially infinite)
Essentially each item is a "service" that my client offers to their customers -- for example: "Configure your institutional-email", and each collection is a "category" of related services -- for example: "Email Services Offered". But the category of "Email Services Offered" could actually be an item/object/collection of a larger item/object/collection that is more general -- for example: "Communication Services Offered".
Current Solution: In my Spring Controller I currently get this collection as a Map and place it onto my Model. In my View (JSTL) I (currently) iterate through 2-levels of the collection, where I assume (the one thing I can assume about this) that the first level is all going to be sub-collections (ie: 'categories'), and where I also assume (incorrectly) that the second level is all going to be items (ie: 'services').
<ul>
<c:forEach items="${serviceCategories} var="category"> // iterate through each collection
<li>${category.key} //the user-displayable title of the 'category' ('collection')
<ul>
<c:forEach items="${category.value}" var="service"> // iterate through each item
<li>${service.key}</li> //the user-displayable title of the 'service' ('item')
</c:if>
</ul>
</li>
</c:if>
</ul>
So I guess my question is that, given such a data-structure, how do I represent it in a view that can manage this??? I am bound by the client's desire to have this structure represented in a tree-like structure.
If I could manipulate the view using pure-java then I would expect one way to achieve this would be to use recursion... something like this, I guess:
/** NOTE: I am not suggesting this is a great example of recursion, nor that it even
* would result in correct output; it was one-off'd just to provide something of an
* example of how I imagine this could be done in Java if I had to do it this way.
*/
private StringBuilder buildString( Map<String, Object> dataStruct ) {
StringBuilder view = new StringBuilder();
Set<String> keys = dataStruct.getKeys();
for( String key : keys ) {
Object value = dataStruct.get( key );
if( value instanceof String ) {
view = key + "[" + value + "]";
return;
}
String subView = buildString( value );
view = key + "[" + subView + "]";
}
Gosh, I hope that is all clear-as-mud and not overwhelming. I also hope I am simply overlooking (or ignorant of) a more elegant-solution that is readily recognized by someone who can help me out.
Thank you for your time! :D
Anytime you have hierarchical data that has unknown depth, and you want to display it, I think a good option is to turn it into XML and bind the XML to some type of tree display. For example, in a similar situation in one of my applications (also Java/Spring) I use XStream to turn the collection into XML (you simply point XStream at the root object and it follows all of the paths for you), and then I display the results using the jQuery plugin jsTree.
If you don't want to use javascript, an alternate approach would be to use something like Jakob Jenkov's Tree Tag.
Another option is to create a JSP simple tag (.tag
file) that calls itself recursively.
精彩评论