Oliver,
You are correct that option 3 is missing in the new tree and that its
present in JTree and the current tree. This was not designed to
intentionally deprive you of functionality that you need in your
application. It didn't really occur to me that tree should support
this kind of functionality.
You must admit that your situation is a pretty specialized case. How
many MyFaces users are using third party components that provide tree
data via a model? My guess is that most are pulling the data
themselves from LDAP or a database and they are using either options 1
or 2 which tree2 can handle.
You are basically asking for the ability to plug a third party data
model directly into the tree without wrapping the objects with an
adapter, etc. to conform to TreeNode interface. I definitely think
that it is acceptable to wrap your data with a very *light* object
that can provide this functionality. I do not accept your argument
that this wastes precious memory. The adapter pattern is a standard
practice and is done all the time without crashing servers. I agree
that in your case it would be a hassle to change the code but lets not
overstate the ramifications of this solution.
Your code sample where you show how you could use tree2 right now
seems perfectly fine to me. I recall that you are using the
server-side expansion control now because you have too much data to
push to the client at once. This makes the wrapping of your
components even less burdensome.
Since there seems to be some concern about losing this functionality,
I would propose that we consider keeping the original tree but moving
it to a legacy package name and give it a tag like <treeLegacy>. Also
we should deprecate the current tree classes. Since it looks like a
release will be coming soon I think this is the best short-term
solution.
Then you and I can explore the possibility of providing option 3
functionality in a future release.
What do you think about that? I take it you have no other concerns at
this point other than option 3 functionality. Is that correct?
sean
On Sat, 12 Mar 2005 14:22:55 +0100, Oliver Rossmueller
<[EMAIL PROTECTED]> wrote:
> Sean Schofield wrote:
>
> > <snip>
> >
> >Yes you are repeating yourself over and over on this point. I do not
> >see how tree2 has changed the basic requirments of the user. You keep
> >saying that I am against TreeModel and for TreeNode. That is not the
> >case. Let me try to phrase my argument differently ...
> >
> >You are correct that JTree operates on a TreeModel instance. It also
> >has TreeNode interface. Data is first wrapped in TreeNode instance
> >before being added to the model. See this example from Sun's JTree
> >example:
> >
> >rootNode = new DefaultMutableTreeNode("Root Node");
> >treeModel = new DefaultTreeModel(rootNode);
> >treeModel.addTreeModelListener(new MyTreeModelListener());
> >tree = new JTree(treeModel);
> >
> >You are correct that JTree does not require a TreeNode interface. I
> >agree with you there. JTree does require a *different* interface,
> >however, and that interface is TreeModel. You cannot just add some
> >arbitrary String "Foo" to a JTree. How would the tree know what to do
> >with it? Is this string a leaf or not? How can you add children to a
> >String? You have two choices. First choice is to use
> >DefaultMutableTreeNode and DefaultTreeModel (as shown above.) That
> >option *requires* TreeNode. Second choice is to write your own class
> >that implements TreeModel. Either way, you cannot just add an
> >arbitrary String to a JTree.
> >
> >Again, I urge us not to think in terms of JTree. Lets leave JTree out
> >of this for now. Lets just talk about the shortcomings of tree2. If
> >we can address those then we can move forward. IMO discussing JTree
> >is not helpful in reaching consensus on this.
> >
> >
> The point is not JTree but the options the user has in providing data:
>
> Option 1: Use DefaultTreeModel and wrap your node objects using
> DefaultMutableTreeNode
>
> Option 2: Use DefaultTreeModel and have your node objects implement
> interface TreeNode
>
> Option 3: Implement interface TreeModel on your own
>
> As the current tree component's design closely follows JTree you have
> the same three options:
>
> Option 1: Use DefaultTreeModel and wrap your node objects using
> DefaultMutableTreeNode
>
> Option 2: Use DefaultTreeModel and have your node objects implement
> interface TreeNode
>
> Option 3: Implement interface TreeModel on your own
>
> Now you say we do not need option 3 anymore, so tree2 only has
>
> Option 1: Use TreeNodeBase to wrap your node objects
>
> Option 2: Have your node objects implement interface tree2.TreeNode
>
> As you kicked away the TreeModel interface (your TreeModel class is just
> an implementation-specific internal helper for HtmlTree as I see it) I
> no longer have the option to implement TreeModel on my own. But named
> option 3 is a crucial option and it's absence is an absolute show
> stopper for me. As words seem not to work out in explaining my argument
> I'll try it with an example this time. It follows the scenario using the
> 3rd party library already mentioned before.
>
> So at the moment I have an implementation of interface TreeModel which
> looks somewhat like the following:
>
> public class MyTreeModel implements TreeModel
> {
>
> private ExternalLib externalLib = new ExternalLib();
>
> public Object getRoot()
> {
> return externalLib.top();
> }
>
> public Object getChild(Object parent, int index)
> {
> ExternalObject[] children = externalLib.subnodes(parent);
> return children[index];
> }
>
> public int getChildCount(Object parent)
> {
> return externalLib.countSubnodes(parent);
> }
>
> public boolean isLeaf(Object node)
> {
> return externalLib.testLeaf(node);
> }
>
> public int getIndexOfChild(Object parent, Object child)
> {
> ExternalObject[] children = externalLib.subnodes(parent);
> for (int i = 0; i < children.length; i++)
> {
> if (children[i].equals(child)) {
> return i;
> };
>
> }
> return -1;
> }
>
> public void valueForPathChanged(TreePath path, Object newValue)
> {
> ...
> }
>
> public Collection getTreeModelListeners()
> {
> ...
> }
> }
>
> Simple enough, isn't it? But you tell me I can't use TreeModel anymore
> when using tree2. So any node object has to implement tree2.TreeNode. As
> I have no access to the sorces of ExternalLib and ExternalObject and
> therefore can not implement interface tree2.TreeNode in the library I
> have to use a wrapper. Unfortunatelly I cannot use option 1 ans
> TreeNodeBase just operates on strings. Ok, so I have to implement
> tree2.TreeNode on my own:
>
> public class TreeNodeWrapper implements TreeNode
> {
> private String identifier;
> private ExternalObject node;
> ExternalLib externalLib;
>
> public TreeNodeWrapper(ExternalObject node, ExternalLib externalLib)
> {
> this.node = node;
> this.externalLib = externalLib;
> }
>
> public boolean isLeaf()
> {
> return externalLib.testLeaf(node);
> }
>
> public void setLeaf(boolean leaf)
> {
> // don't know why this is in the interface
> throw new UnsupportedOperationException();
> }
>
> public List getChildren()
> {
> ExternalObject[] children = externalLib.subnodes(parent);
> ArrayList answer = new ArrayList(children.length);
>
> for (int i = 0; i < children.length; i++)
> {
> answer.add(new TreeNodeWrapper(children[i], externalLib));
> // <= EXTRA OBJECT HERE ###############
> }
>
> return answer;
> }
>
> public String getType()
> {
> return node.getTypeName();
> }
>
> public void setType(String type)
> {
> // don't know why this is in the interface
> throw new UnsupportedOperationException();
> }
>
> public void setDescription(String description)
> {
> // don't know why this is in the interface
> throw new UnsupportedOperationException();
> }
>
> public String getDescription()
> {
> return node.getLabel();
> }
>
> public void setIdentifier(String identifier)
> {
> this.identifier = identifier;
> }
>
> public String getIdentifier()
> {
> return identifier;
> }
>
> public int getChildCount()
> {
> return externalLib.countSubnodes(node);
> }
> }
>
> All right, complexity of this implementation is similar to the TreeModel
> implementation. But my main argument against your decistion to drop
> option 3 is the need for extra wrapper objects to fulfill the conctract
> (see method getChildren() above where any ExternalObject has to be put
> inside another wrapper object). Maybe you do not care about resource
> consumption but I do and I have to because the machines I have at hand
> are kind of limited in that aspect. So I don't like to be forced to
> waste memory just because you do not like the TreeModel interface and
> the programming model behind it. You say it's just an interface but you
> have to see the implications on possible implementations this change in
> interfaces has. That's what I'm talking about all the time.
>
> So please give option 3 back to users and change tree2 to take
> tree.model.TreeModel instances as it's value instead of tree2.TreeNode.
> Or show me a way to fulfill the tree2.TreeNode contract without the need
> for extra objects in the example above.
>
> Oliver
>
> >
> >
> >
> >>Exactly that's my argument: the TreeNodeBase instance is the extra
> >>object you force me to create!!! When implementing TreeModel there is no
> >>need for this extra object, I'm able to use just the 3rd party data
> >>objects, naked and unwrapped as I get the from the external library. I
> >>don't have to wrap them with DefaultMutableTreeNode or any other object.
> >>
> >>
> >
> >I guarantee that your third party component is not returing objects
> >that implement TreeModel. That is my point. I think you are getting
> >hung up on the wording of TreeModel vs. TreeNode. The current tree
> >needs to make the raw data compliant with what the component expects
> >(TreeModel). The new tree does the same thing but calls it something
> >different (TreeNode.) The current tree also has a TreeNode interface
> >and you say that its not required to use the tree. That's fine. I
> >won't argue that point.
> >
> >To summarize, the current tree requires that data be adapted to the
> >TreeModel interface. The new tree requires that data be adapted to
> >the TreeNode interface. The fact that I am calling it TreeNode
> >instead of TreeModel does not make it any more difficult for the user
> >to implement. The new tree also has a TreeModel class. A difference
> >in the new implementation is that the model stuff is handled behind
> >the scenes. There is no need for the user to provide their own model.
> > We could look at changing that but basically its already possible to
> >provide your own models by extending the TreeModel class.
> >
> >Please take another look at how I am using TreeNode and TreeModel. If
> >you think its important that the user can provide their own models
> >then lets explore that! Maybe this is the nature of your objection.
> >If so, I'm happy to work with you on that.
> >
> >I think some of the confusion is over the changes in implementation.
> >This is primarily a difference of opinion between the two of us. It
> >doesn't affect the users. Most users are going to use
> >DefaultMutableTreeNode as you do in your example or TreeNodeBase as I
> >do in my example.
> >
> >
> >
> >>Again you seem to ignore my argument. I'm not talking about
> >>expanded/collapsed state but about SELECTED nodes. Take the tree example
> >>in the examples webapp. When you click the text of the root node it will
> >>get bold as the root node is the selected node now. Go on and expand
> >>some of the children and click the text of one of the child nodes: again
> >>the text will get bold to mark the selected node. At any time it is
> >>possible to ask the current tree for the path to the node currently
> >>selected. In tree2 the component itself does not care about that so I
> >>have to implement that feature on my own. It can be done using some
> >>specific command links and actions but I think to keep track of a
> >>selected node is a feature so common to tree components that is should
> >>be implemented there.
> >>
> >>
> >
> >This is the kind of specific use case that I have been asking you to
> >provide. Until now you just kept telling me that the new tree could
> >not handle selection. Now I see what you mean by selection. Let me
> >see if I can't address it in the new tree. I will get back to you on
> >this one.
> >
> >
> >
> >>Actually that's what I'm doing I suppose: to talk about features that
> >>are missing for tree2. But you have to be open for the fact that there
> >>are other scenarios and applications than the one you have in mind. I
> >>understand that your effort is driven by the requirements of the project
> >>you are currently working on. The current tree component has it's origin
> >>in a similar effort. To get a general-purpose tree component we have to
> >>address the issues I brought on the table. Otherwise we end up with two
> >>tree implementations which have something in common but miss some
> >>feature the other implementation has and vice versa. This can not be the
> >>goal if you ask me.
> >>
> >>
> >
> >I agree we need to address these issues. In order to do that, I need
> >specifics. I will look into the selection issue as you have asked. I
> >think I can work something out on that one. As for the interface
> >issue, please take another look at my reasoning on that. If you want
> >the ability to provide your own TreeModel then maybe that's something
> >we can do (although I don't think its necessary.)
> >
> >Believe it or not I think we are making progress. I now know what you
> >mean by the selection problem. So we are 50% there. Lets see if we
> >can't reach an understanding on the inteface issue.
> >
> >
> >
> >>Oliver
> >>
> >>
> >
> >sean
> >
> >
>
> --
> Oliver Rossmueller
> Software Engineer and IT-Consultant
> Hamburg, Germany
> http://www.rossmueller.com
>
>