Sean,

you do not accept my argument that the wrapper objects I would need following your programming model waste memory. That's fine for me. But tell you what: I do not accept your argument that implementing TreeModel is a special case nobody else is using. My colleagues and I have implemented TreeModel variants for dozens of Swing applications to save memory resources. Of course you can do without your own implementation by using DefaultTreeModel. But - accept it or not - memory consumption matters for some people out there. So don't wipe this argument from the table like it's not there.

I'll tell you how we are going to resolve this: when you came along with the idea for an improved tree component I told you we can get all the requirements you are looking for by refactoring the existing tree component. You choose the revolutionary approach and started your own component from scratch. That's just fine for me but now I'm going to try the evolutionary approach by refactoring the existing tree and incorporating new functionality from tree2. I'm quite sure this can be done without breaking existing code. As I have other stuff to work on, too, this will not be finished within the next few days. Anyway it should be worth the time as we'll end up with one tree component and without the need for a legacy package.

In the meantime if there will be a MyFaces release we should mark tree2 as experimental and tell anybody that he's using this component at his own risk.

Oliver


Sean Schofield wrote:

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






--
Oliver Rossmueller
Software Engineer and IT-Consultant
Hamburg, Germany
http://www.rossmueller.com



Reply via email to