On Monday, January 6, 2014 3:05:57 PM UTC-6, Edward K. Ream wrote:
 

> [There remains one last complication, which I have been working on all 
> day, namely properly creating all organizer nodes, especially nested 
> organizer nodes.  Clearly, this is doable: the @organizers tree contains 
> all necessary data.
>
> Doable, but very tricky.  The problem is that the @organizer: nodes 
> contain full unl's of child nodes, but those unl's are invalid until we 
> create the organizer nodes, which is what we are trying to do!
>

I believe I see the way forward: create an OrganizerInfo class to 
encapsulate various details about each organizer node. 

There are at least two new distinctions to be handled:

1. The "raw" unl, which is the unl of the imported node, before the node is 
moved to any organizer node.  This is the unl stripped of all references to 
organizer nodes.  Here is the relevant code::

def drop_unl_tail(self,unl):
    '''Drop the last part of the unl.'''
    return '-->'.join(unl.split('-->')[:-1])

def drop_all_organizers_in_unl(self,organizer_unls,unl):
    '''Drop all organizer unl's in unl, recreating the imported url.'''
    def key(s):
        return s.count('-->')
    for s in reversed(sorted(organizer_unls,key=key)):
        if unl.startswith(s):
            s2 = self.drop_unl_tail(s)
            unl = s2 + unl[len(s):]
    return unl

2. The **source node** of an organizer node.  This is the imported node 
that:

a) will become the parent of the organizer node and

b) presently contains all the nodes that will become children of the 
organizer node.

Computing the source unl is similar to computing the raw unl, but the 
computation drops the tail of the unl only until a non-organizer part is 
seen.  Probably something like this (untested!):

def source_unl(self,organizer_unls,unl):
    '''Return the source_unl of an organizer unl.'''
    def key(s):
        return s.count('-->')
    assert unl in organizer_unls
    for s in reversed(sorted(organizer_unls,key=key)):
        if unl.startswith(s):
            s2 = self.drop_unl_tail(s)
            unl = s2 + unl[len(s):]
        else: break
    return unl

There is also an ever-present complication: moving nodes into an organizer 
node has the potential to invalidate previously-computed positions.  The 
present version of vc.create_organizer_nodes_helper handles this by in 
three steps:

- Create the organizer node at the last child of the (source) node
- Demote demoting children in reverse. (They become children of the 
organizer node).
- Move the organizer node to the n'th child of the source node.
  (n previously computed as the childIndex of the first demoted node).

However, this is not a complete solution to the problem, because nested 
organizer nodes may (and usually will) have the same source nodes.  I plan 
to handle this complication as follows:

- A prepass will create all organizer nodes in a safe place, as children of 
a temporary node inserted as the last top-level node.
- Another pass will demote all organized nodes into the proper organizer 
node.
- A final pass will move all organizer nodes into *previously computed* 
final positions, presumably in reverse outline order.  This pass will also 
remove the temporary node.

Finally, create_organizer_nodes_helper, the code that actually assigns 
nodes to organizer nodes, must handle the potential nesting of organizer 
nodes.  The general rules:

-  Nodes must be assigned to an organizer node from the first node 
appearing in the organizer node to the last node appearing in the organizer 
node.  In other words, extra nodes must be assigned to the organizer node 
that is presently accumulating nodes.

- However, if, while accumulating nodes for an organizer node, we see a 
node assigned to another (more deeply nested) organizer node, we must start 
accumulating nodes for that more deeply nested node.

As a result, create_organizer_nodes_helper is likely to be a recursion on 
the length of the unls of all organizer nodes having a particular node as 
its source.

Clearly, this is a complex process.  However, the new programming freedom 
created by the OrganizerInfo instances, and the new clarity created by the 
distinctions discussed above promise to solve the puzzle in a *relatively* 
straightforward fashion.  Furthermore, substantial unit tests are already 
in place (they fail at present) that will convincingly demonstrate when the 
full solution is at hand.

Maybe today.

Edward

-- 
You received this message because you are subscribed to the Google Groups 
"leo-editor" group.
To unsubscribe from this group and stop receiving emails from it, send an email 
to [email protected].
To post to this group, send email to [email protected].
Visit this group at http://groups.google.com/group/leo-editor.
For more options, visit https://groups.google.com/groups/opt_out.

Reply via email to