Preface: I am a long-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)
- Item : Object (can be a String or another Collection)
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