This Bugzilla instance is a read-only archive of historic NetBeans bug reports. To report a bug in NetBeans please follow the project's instructions for reporting issues.

Bug 56338 - viewmodel: Model ordering gets randomized because of HasSet to List conversion
Summary: viewmodel: Model ordering gets randomized because of HasSet to List conversion
Status: CLOSED WONTFIX
Alias: None
Product: debugger
Classification: Unclassified
Component: Code (show other bugs)
Version: 4.x
Hardware: All All
: P1 blocker (vote)
Assignee: issues@debugger
URL:
Keywords:
Depends on:
Blocks:
 
Reported: 2005-03-13 21:34 UTC by ivan
Modified: 2010-04-29 09:21 UTC (History)
0 users

See Also:
Issue Type: DEFECT
Exception Reporter:


Attachments

Note You need to log in before you can comment on or make changes to this bug.
Description ivan 2005-03-13 21:34:41 UTC
Suddenly my breakpoints don't appear in the breakpoints view.

I stepped through some of the code, following treeChanged().
I ended up here:

=>[1] org.netbeans.spi.viewmodel.Models.DelegatingTreeModel.getRoot(this =
<OBJECT>)  "Models.java":822
  [2] org.netbeans.spi.viewmodel.Models.CompoundModel.getRoot(this = <OBJECT>) 
"Models.java":2036

Where getRoot() returns models[0].getRoot().
But models.length is 2 and 

models[0] is a org.netbeans.modules.debugger.ui.models.BreakpointsTreeModel
models[1] is a com.sun.tools.debugger.dbxgui.debugger.breakpoints.BreakpointModel

For one thing anyone looking at the class DelegatingTreeModel and
it having an array of models and yet getRoot() returning models[0]
will raise their eyebrow. 

Anyway ...

These models get registered from a call in ViewModelListener.updateModel()
which does two sets of lookup. This explain why models is of length 2.
It also puts the result of the lookups into a HashSet.
This HashSet is then converted to a List and passed on to 
Models.createCompoundModel().

createCompoundModel() attempts to "sort" models but about the only
aspect governing the sorting is whether the name of the model ends in
"First" otherwise the conversion from hashset to a list and thence to
an array is random and depends on how things hash!
I think this might explain why sometimes I get the bpts and sometimes 
I don't. 
It looks as if the looking for First was an experiment to
deal with this random behaviour.
It would see that a LinkedHashSet, with predictable iteration behaviour is
the right thing to use here, but when I tried it here's what happennes.
My Model ends up first in LinkedHashSet but the sorting in createCompoundModel
makes it go to the end of the list. So I changed the addFirst to addLast.
	For that matter, why is it that if the model ends with First
	it end up going last?
This seems to make it work for me.
But this is going beyond a simple spot fix. The getRoot() only favoring the
first model is a bit weird. Maybe there's sound reason for it but
it should be explained in the code. As it is I don't know whether or
ahy should lookups of models from debugger manager take or not take
precedence over lookup from engines.
I also can't tell where and what else might be affected by this.

We automatically pull NB code so my spot fixes won't last long.
Comment 1 Jan Jancura 2005-03-29 14:12:04 UTC
Generally said - you should not register two TreeModels for one view. There
should be one original TreeModel. If you need to modify content of view defined
by original TreeModel, you should use TreeModelFilter. We use the same approach
in JPDADebugger - see
org.netbeans.modules.debugger.jpda.ui.models.BreakpointsTreeModelFilter.

If you have two TreeModels registerred for one view, result behaviour is simply
random - its your case. It depends on some ordering, and ordering is not well
defined, as you have discoverred.

So, why having two TreeModels is not prohibited? 
There are some minor reasons for that, I do not remember exactly.
But in this case you should keep two rules:
1) Both TreeModels should return same root node
2) All methods of models should return some results for distinct set of node
types. It means that if treeModel1.isLeaf (node) returns some boolean for given
node, treeModel2 have to throw UnknownTypeException for the same node.
I am mnot sure if its your case, probably not.
Anyway, possibility to have two TreeModels for one view is not "public" and
supported.

Is it OK for you? Can you rewrite your TreeModel to TreeModelFilter?
Comment 2 ivan 2005-03-29 23:16:47 UTC
Ok, this is making a bit more sense.

AFAIK I'm using the same TreeModel.ROOT everywhere so that condition
is satisfied, although if an API requires a contract to be fulfilled it should
test for it. I.e. I expect getRoot() to assert that the roots of all
models are identical and that all loops over models to assert
that only one returns a value. Since you cache the model in classNameToModel
these additional assertions should not slow things down?

But then let's consider Delegating....getChildren(). When it
gets the ROOT node the first time the classNameToModel should
fail so it falls through to the model loop. If my model isn't first 
and the regular model returns an empty array instead of UnknownTypeException
for ROOT things will go bad.
It seems that rule 2 is not really satisfiable for ROOT nodes and ordering
does become important for them.

Also considering that you do sort the models I find it odd that you claim
that models should be equivalent within rules 1 and 2. Why sort
them then?

Comment 3 Quality Engineering 2010-04-29 09:21:35 UTC
Verified ... and Closing all issues resolved into NetBeans 6.7 and earlier.