[josm-dev] Jumbo Patch

Gabriel Ebner ge at gabrielebner.at
Sun Dec 16 23:07:16 GMT 2007


On Sun, Dec 16, 2007 at 09:33:14PM +0000, Gervase Markham wrote:
> Gabriel Ebner wrote:
> > You'll end up having to change the callers anyhow, as they assume a certain
> > behavior of how primitives work.
> 
> Then that's your mistake; those assumptions should be documented, or 
> unnecessary :-)

*My* mistake?  I wasn't even around yet when these decisions were made. :-)

But you're right.  There should be a JOSM internals manual somewhere, but I
guess it'll share the fate of the javadocs:  Someone will change the code but
not the documentation.  In fact I'd take the comments and even the javadocs as
nothing more than a starting point, we've got some pretty scary and misleading
stuff in JOSM:

    /**
     * Split a way into two or more parts, starting at a selected node.
     * 
     * FIXME: what do the following "arguments" refer to?
     * @param way the way to split
     * @param nodes the node(s) to split the way at; must be part of the way.
     */
    private void splitWay() {

> Right. So the correct answer is to make adding nodes to a Way and to the 
> undo/redo list an atomic operation, if the two must be coupled together.
> 
> Ignoring for the moment the fact that undoRedo is a "global", it might 
> go something like this:
> 
> Way wnew = new Way(w);
> wnew.replaceNodes(newNodes);
> 
> class Way {
>    ...
> 
>    function replaceNodes(nodeList newNodes) {
>      Way oldway = this.clone();
>      this.nodes = newNodes;
>      Main.main.undoRedo.add(new ChangeCommand(oldway, this));
>      ...
>    }
> }

I didn't tell you the whole story.  If you want to have two modifications as a
single undo item, you've got to put them into a SequenceCommand:

  Command a = ...;
  Command b = ...;
  Main.main.undoRedo.add(new SequenceCommand(a, b));

The catch is that if you change a way twice, the second change will overwrite
the first one.  (So you've got to remember what you've changed -- and that's
the main reason we don't have helper functions like replaceNodes() already.)

> [ concurrent modification & shared mutable state ]

User code isn't supposed to modify the primitives from the data set anyhow.
Unfortunately we are mutation to generate partially different primitives:

  // Create a clone of the way with a node appended.
  Way wnew = new Way(w);
  w.nodes.add(n);

That's it.  From then on, user code shouldn't (and does not) modify the Way
anymore.  It will only be modified by *Command after that.

So we actually have quasi readonly objects; in that sense we already have de
facto private data with accessors.

  Gabriel.




More information about the josm-dev mailing list