Diff for /loncom/interface/lonnavmaps.pm between versions 1.99 and 1.100

version 1.99, 2002/11/08 18:44:02 version 1.100, 2002/11/08 19:10:58
Line 1371  sub new { Line 1371  sub new {
                     }                      }
                 }                  }
             }              }
             if (ref($curRes) && $curRes->is_map() && $direction == FORWARD()) {  
                 my $firstResource = $curRes->map_start();  
                 my $finishResource = $curRes->map_finish();  
                 my $newIterator = Apache::lonnavmaps::iterator->new($self->{NAV_MAP},  
                                                                     $firstResource,  
                                                                     $finishResource,  
                                                                     $self->{FILTER},  
                                                                     $self->{ALREADY_SEEN},  
                                                                     $self->{CONDITION});  
             }  
                           
             # Assign the final val              # Assign the final val
             if (ref($curRes) && $direction == BACKWARD()) {              if (ref($curRes) && $direction == BACKWARD()) {
Line 1549  sub populateStack { Line 1539  sub populateStack {
   
 package Apache::lonnavmaps::DFSiterator;  package Apache::lonnavmaps::DFSiterator;
   
 # UNDOCUMENTED: This is a private library, it should not generally be used  # Not documented in the perldoc: This is a simple iterator that just walks
 # by the outside world. What it does is walk through the nav map in a   #  through the nav map and presents the resources in a depth-first search
 # depth-first fashion. This is not appropriate for most uses, but it is  #  fashion, ignorant of conditionals, randomized resources, etc. It presents
 # used by the main iterator for pre-processing. It also is able to isolate  #  BEGIN_MAP and END_MAP, but does not understand branches at all. It is
 # much of the complexity of the main iterator, so the main iterator is much  #  useful for pre-processing of some kind, and is in fact used by the main
 # simpler.  #  iterator that way, but that's about it.
 # There is no real benefit in merging the main iterator and this one into one class...  # One could imagine merging this into the init routine of the main iterator,
 # all the logic in DFSiterator would need to be replicated, you gain no performance,  #  but this might as well be left seperate, since it is possible some other
 # at best, you just make one massively complicated iterator in place of two   #  use might be found for it. - Jeremy
 # somewhat complicated ones. ;-) - Jeremy  
   
 # Here are the tokens for the iterator, replicated from iterator for convenience:  
   
 sub BEGIN_MAP { return 1; }    # begining of a new map  sub BEGIN_MAP { return 1; }    # begining of a new map
 sub END_MAP { return 2; }      # end of the map  sub END_MAP { return 2; }      # end of the map
 sub BEGIN_BRANCH { return 3; } # beginning of a branch  
 sub END_BRANCH { return 4; }   # end of a branch  
 sub FORWARD { return 1; }      # go forward  sub FORWARD { return 1; }      # go forward
 sub BACKWARD { return 2; }  sub BACKWARD { return 2; }
   
 # Params: nav map, start resource, end resource, filter, condition,   # Params: Nav map ref, first resource id/ref, finish resource id/ref,
 # already seen hash ref  #         filter hash ref (or undef), already seen hash or undef, condition
   #         (as in main iterator), direction FORWARD or BACKWARD (undef->forward).
 sub new {  sub new {
     # magic invocation to create a class instance      # magic invocation to create a class instance
     my $proto = shift;      my $proto = shift;
Line 1581  sub new { Line 1566  sub new {
     $self->{NAV_MAP} = shift;      $self->{NAV_MAP} = shift;
     return undef unless ($self->{NAV_MAP});      return undef unless ($self->{NAV_MAP});
   
     # Handle the parameters  
     $self->{FIRST_RESOURCE} = shift || $self->{NAV_MAP}->firstResource();      $self->{FIRST_RESOURCE} = shift || $self->{NAV_MAP}->firstResource();
     $self->{FINISH_RESOURCE} = shift || $self->{NAV_MAP}->finishResource();      $self->{FINISH_RESOURCE} = shift || $self->{NAV_MAP}->finishResource();
   
Line 1600  sub new { Line 1584  sub new {
     $self->{CONDITION} = shift;      $self->{CONDITION} = shift;
     $self->{DIRECTION} = shift || FORWARD();      $self->{DIRECTION} = shift || FORWARD();
   
     # Flag: Have we started yet? If not, the first action is to return BEGIN_MAP.      # Flag: Have we started yet?
     $self->{STARTED} = 0;      $self->{STARTED} = 0;
   
     # Should we continue calling the recursive iterator, if any?      # Should we continue calling the recursive iterator, if any?
Line 1614  sub new { Line 1598  sub new {
     $self->{RECURSIVE_DEPTH} = 0;      $self->{RECURSIVE_DEPTH} = 0;
   
     # For keeping track of our branches, we maintain our own stack      # For keeping track of our branches, we maintain our own stack
     $self->{BRANCH_STACK} = [];      $self->{STACK} = [];
     # If the size shrinks, we exhausted a branch  
     $self->{BRANCH_STACK_SIZE} = 0;  
     $self->{BRANCH_DEPTH} = 0;  
   
     # For returning two things in a forced sequence  
     $self->{FORCE_NEXT} = undef;  
   
     # Start with the first resource      # Start with the first resource
     if ($self->{DIRECTION} == FORWARD) {      if ($self->{DIRECTION} == FORWARD) {
         push @{$self->{BRANCH_STACK}}, $self->{FIRST_RESOURCE};          push @{$self->{STACK}}, $self->{FIRST_RESOURCE};
     } else {      } else {
         push @{$self->{BRANCH_STACK}}, $self->{FINISH_RESOURCE};          push @{$self->{STACK}}, $self->{FINISH_RESOURCE};
     }      }
     $self->{BRANCH_STACK_SIZE} = 1;  
   
     bless($self);      bless($self);
     return $self;      return $self;
 }  }
   
 # Note... this function is *touchy*. I strongly recommend tracing  
 # through it with the debugger a few times on a non-trivial map before  
 # modifying it. Order is *everything*.  
 sub next {  sub next {
     my $self = shift;      my $self = shift;
           
     # Iterator logic goes here  
   
     # Are we using a recursive iterator? If so, pull from that and      # Are we using a recursive iterator? If so, pull from that and
     # watch the depth; we want to resume our level at the correct time.      # watch the depth; we want to resume our level at the correct time.
     if ($self->{RECURSIVE_ITERATOR_FLAG}) {      if ($self->{RECURSIVE_ITERATOR_FLAG}) {
Line 1660  sub next { Line 1632  sub next {
         return $next;          return $next;
     }      }
   
     # Is this return value pre-determined?  
     if (defined($self->{FORCE_NEXT})) {  
         my $tmp = $self->{FORCE_NEXT};  
         $self->{FORCE_NEXT} = undef;  
         return $tmp;  
     }  
   
     # Is there a current resource to grab? If not, then return      # Is there a current resource to grab? If not, then return
     # END_BRANCH and END_MAP in succession.      # END_MAP, which will end the iterator.
     if (scalar(@{$self->{BRANCH_STACK}}) == 0) {      if (scalar(@{$self->{STACK}}) == 0) {
         if ($self->{BRANCH_DEPTH} > 0) {          return $self->END_MAP();
             $self->{FORCE_NEXT} = $self->END_MAP();  
             $self->{BRANCH_DEPTH}--;  
             return $self->END_BRANCH();  
         } else {  
             return $self->END_MAP();  
         }  
     }      }
   
     # Have we not yet begun? If not, return BEGIN_MAP and       # Have we not yet begun? If not, return BEGIN_MAP and 
Line 1686  sub next { Line 1645  sub next {
         return $self->BEGIN_MAP;          return $self->BEGIN_MAP;
     }      }
   
     # Did the branch stack shrink since last run? If so,  
     # we exhausted a branch last time, therefore, we're about  
     # to start a new one. (We know because we already checked to see  
     # if the stack was empty.)  
     if ( scalar (@{$self->{BRANCH_STACK}}) < $self->{BRANCH_STACK_SIZE}) {  
         $self->{BRANCH_STACK_SIZE} = scalar(@{$self->{BRANCH_STACK}});  
         $self->{BRANCH_DEPTH}++;  
         return $self->BEGIN_BRANCH();  
     }  
   
     # Remember the size for comparision next time.  
     $self->{BRANCH_STACK_SIZE} = scalar(@{$self->{BRANCH_STACK}});  
   
     # If the next resource we mean to return is going to need  
     # a lower branch level, terminate branches until we get   
     # there.  
   
     # Get the next resource in the branch      # Get the next resource in the branch
     $self->{HERE} = pop @{$self->{BRANCH_STACK}};      $self->{HERE} = pop @{$self->{STACK}};
   
     # Are we at the right depth? If not, close a branch and return      # remember that we've seen this, so we don't return it again later
     # the current resource onto the branch stack  
     # Note: There seems to be some bugs here, so don't rely  
     # on this, use the real iterator instead.  
     if (defined($self->{HERE}->{DATA}->{ITERATOR_DEPTH})  
         && $self->{HERE}->{DATA}->{ITERATOR_DEPTH} <  
         $self->{BRANCH_DEPTH} ) {  
         $self->{BRANCH_DEPTH}--;  
         # return it so we can pick it up eventually  
         push @{$self->{BRANCH_STACK}}, $self->{HERE};  
         return $self->END_BRANCH();  
     }  
   
     # We always return it after this point and never before  
     # (proof: look at just the return statements), so we  
     # remember that we've seen this.  
     $self->{ALREADY_SEEN}->{$self->{HERE}->{ID}} = 1;      $self->{ALREADY_SEEN}->{$self->{HERE}->{ID}} = 1;
           
     # Get the next possible resources      # Get the next possible resources
Line 1734  sub next { Line 1661  sub next {
     my $next = [];      my $next = [];
   
     # filter the next possibilities to remove things we've       # filter the next possibilities to remove things we've 
     # already seen. Also, remember what branch depth they should      # already seen.
     # be displayed at, since there's no other reliable way to tell.  
     foreach (@$nextUnfiltered) {      foreach (@$nextUnfiltered) {
         if (!defined($self->{ALREADY_SEEN}->{$_->{ID}})) {          if (!defined($self->{ALREADY_SEEN}->{$_->{ID}})) {
             push @$next, $_;              push @$next, $_;
             $_->{DATA}->{ITERATOR_DEPTH} =   
                 $self->{BRANCH_DEPTH} + 1;  
         }          }
     }      }
   
     # Handle branch cases:  
     # Nothing is available next: BRANCH_END  
     # 1 thing next: standard non-branch  
     # 2+ things next: have some branches  
     my $nextCount = scalar(@$next);  
     if ($nextCount == 0) {  
         # Return this and on the next run, close the branch up if we're   
         # in a branch  
         if ($self->{BRANCH_DEPTH} > 0 ) {  
             $self->{FORCE_NEXT} = $self->END_BRANCH();  
             $self->{BRANCH_DEPTH}--;  
         }  
     }  
       
     while (@$next) {      while (@$next) {
         # copy the next possibilities over to the branch stack          # copy the next possibilities over to the stack
         # in the right order          push @{$self->{STACK}}, shift @$next;
         push @{$self->{BRANCH_STACK}}, shift @$next;  
     }  
   
     if ($nextCount >= 2) {  
         $self->{FORCE_NEXT} = $self->BEGIN_BRANCH();  
         $self->{BRANCH_DEPTH}++;  
         return $self->{HERE};   
     }      }
   
     # If this is a map and we want to recurse down it... (not filtered out)      # If this is a map and we want to recurse down it... (not filtered out)
Line 1786  sub next { Line 1689  sub next {
     return $self->{HERE};      return $self->{HERE};
 }  }
   
 sub getStack {  
     my $self=shift;  
   
     my @stack;  
   
     $self->populateStack(\@stack);  
   
     return \@stack;  
 }  
   
 # Private method: Calls the iterators recursively to populate the stack.  
 sub populateStack {  
     my $self=shift;  
     my $stack = shift;  
   
     push @$stack, $self->{HERE} if ($self->{HERE});  
   
     if ($self->{RECURSIVE_ITERATOR_FLAG}) {  
         $self->{RECURSIVE_ITERATOR}->populateStack($stack);  
     }  
 }  
   
 1;  1;
   
 package Apache::lonnavmaps::resource;  package Apache::lonnavmaps::resource;

Removed from v.1.99  
changed lines
  Added in v.1.100


FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>