492 /*dynamic markup from execution*/ |
492 /*dynamic markup from execution*/ |
493 val execs: Map[Document_ID.Exec, Command.State] = Map.empty, |
493 val execs: Map[Document_ID.Exec, Command.State] = Map.empty, |
494 /*command-exec assignment for each version*/ |
494 /*command-exec assignment for each version*/ |
495 val assignments: Map[Document_ID.Version, State.Assignment] = Map.empty, |
495 val assignments: Map[Document_ID.Version, State.Assignment] = Map.empty, |
496 /*commands with markup produced by other commands (imm_succs)*/ |
496 /*commands with markup produced by other commands (imm_succs)*/ |
497 val augmented_commands: Graph[Document_ID.Command, Unit] = Graph.long, |
497 val commands_redirection: Graph[Document_ID.Command, Unit] = Graph.long, |
498 /*explicit (linear) history*/ |
498 /*explicit (linear) history*/ |
499 val history: History = History.init) |
499 val history: History = History.init) |
500 { |
500 { |
501 private def fail[A]: A = throw new State.Fail(this) |
501 private def fail[A]: A = throw new State.Fail(this) |
502 |
502 |
538 |
538 |
539 private def other_id(id: Document_ID.Generic): Option[(Text.Chunk.Id, Text.Chunk)] = |
539 private def other_id(id: Document_ID.Generic): Option[(Text.Chunk.Id, Text.Chunk)] = |
540 (execs.get(id) orElse commands.get(id)).map(st => |
540 (execs.get(id) orElse commands.get(id)).map(st => |
541 ((Text.Chunk.Id(st.command.id), st.command.chunk))) |
541 ((Text.Chunk.Id(st.command.id), st.command.chunk))) |
542 |
542 |
543 private def augmented(st: Command.State): Graph[Document_ID.Command, Unit] = |
543 private def redirection(st: Command.State): Graph[Document_ID.Command, Unit] = |
544 (augmented_commands /: st.markups.other_id_iterator)({ case (graph, id) => |
544 (commands_redirection /: st.markups.redirection_iterator)({ case (graph, id) => |
545 graph.default_node(id, ()).default_node(st.command.id, ()).add_edge(id, st.command.id) }) |
545 graph.default_node(id, ()).default_node(st.command.id, ()).add_edge(id, st.command.id) }) |
546 |
546 |
547 def accumulate(id: Document_ID.Generic, message: XML.Elem): (Command.State, State) = |
547 def accumulate(id: Document_ID.Generic, message: XML.Elem): (Command.State, State) = |
548 { |
548 { |
549 execs.get(id) match { |
549 execs.get(id) match { |
550 case Some(st) => |
550 case Some(st) => |
551 val new_st = st.accumulate(self_id(st), other_id _, message) |
551 val new_st = st.accumulate(self_id(st), other_id _, message) |
552 val execs1 = execs + (id -> new_st) |
552 val execs1 = execs + (id -> new_st) |
553 (new_st, copy(execs = execs1, augmented_commands = augmented(new_st))) |
553 (new_st, copy(execs = execs1, commands_redirection = redirection(new_st))) |
554 case None => |
554 case None => |
555 commands.get(id) match { |
555 commands.get(id) match { |
556 case Some(st) => |
556 case Some(st) => |
557 val new_st = st.accumulate(self_id(st), other_id _, message) |
557 val new_st = st.accumulate(self_id(st), other_id _, message) |
558 val commands1 = commands + (id -> new_st) |
558 val commands1 = commands + (id -> new_st) |
559 (new_st, copy(commands = commands1, augmented_commands = augmented(new_st))) |
559 (new_st, copy(commands = commands1, commands_redirection = redirection(new_st))) |
560 case None => fail |
560 case None => fail |
561 } |
561 } |
562 } |
562 } |
563 } |
563 } |
564 |
564 |
652 copy( |
652 copy( |
653 versions = versions1, |
653 versions = versions1, |
654 blobs = blobs1, |
654 blobs = blobs1, |
655 commands = commands1, |
655 commands = commands1, |
656 execs = execs1, |
656 execs = execs1, |
657 augmented_commands = augmented_commands.restrict(commands1.isDefinedAt(_)), |
657 commands_redirection = commands_redirection.restrict(commands1.isDefinedAt(_)), |
658 assignments = assignments1) |
658 assignments = assignments1) |
659 } |
659 } |
660 |
660 |
661 private def command_states_self(version: Version, command: Command) |
661 private def command_states_self(version: Version, command: Command) |
662 : List[(Document_ID.Generic, Command.State)] = |
662 : List[(Document_ID.Generic, Command.State)] = |
678 |
678 |
679 def command_states(version: Version, command: Command): List[Command.State] = |
679 def command_states(version: Version, command: Command): List[Command.State] = |
680 { |
680 { |
681 val self = command_states_self(version, command) |
681 val self = command_states_self(version, command) |
682 val others = |
682 val others = |
683 if (augmented_commands.defined(command.id)) { |
683 if (commands_redirection.defined(command.id)) { |
684 (for { |
684 (for { |
685 command_id <- augmented_commands.imm_succs(command.id).iterator |
685 command_id <- commands_redirection.imm_succs(command.id).iterator |
686 (id, st) <- command_states_self(version, the_static_state(command_id).command) |
686 (id, st) <- command_states_self(version, the_static_state(command_id).command) |
687 if !self.exists(_._1 == id) |
687 if !self.exists(_._1 == id) |
688 } yield (id, st)).toMap.valuesIterator.toList |
688 } yield (id, st)).toMap.valuesIterator.toList |
689 } |
689 } |
690 else Nil |
690 else Nil |
691 self.map(_._2) ::: others.map(_.retarget(command)) |
691 self.map(_._2) ::: others.map(_.redirect(command)) |
692 } |
692 } |
693 |
693 |
694 def command_results(version: Version, command: Command): Command.Results = |
694 def command_results(version: Version, command: Command): Command.Results = |
695 Command.State.merge_results(command_states(version, command)) |
695 Command.State.merge_results(command_states(version, command)) |
696 |
696 |