Master.pm 2.8KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116
  1. package SugarTrail::Template::Master;
  2. # Master template holder
  3. # new()
  4. # parse()
  5. # _parse_headers()
  6. # _parse_body()
  7. use strict;
  8. use warnings;
  9. use Carp;
  10. use SugarTrail::Template::Slave;
  11. use SugarTrail::Template::Condition;
  12. sub new {
  13. my $class = shift;
  14. my $args = { @_ };
  15. my $self = {};
  16. $self->{args} = $args;
  17. return bless $self, $class;
  18. }
  19. sub parse {
  20. my $self = shift;
  21. my ($head, $body) = split "\n\n", $self->{text}, 2;
  22. $self->{head} = $head;
  23. $self->{body} = $body;
  24. return (
  25. $self->_parse_headers(),
  26. $self->_parse_body()
  27. );
  28. }
  29. sub _parse_headers {
  30. my $self = shift;
  31. foreach (split "\n", $self->{head}) {
  32. my ($n, $v) = split ": ", $_, 2;
  33. $self->{meta}->{$n} = $v;
  34. }
  35. return scalar keys %{ $self->{meta} };
  36. }
  37. sub _parse_body {
  38. my $self = shift;
  39. $self->{steps} = [];
  40. foreach (split "\n", $self->{body}) {
  41. chomp; s/ *$//;
  42. my @conds;
  43. my ($line, $cond_block) = $_ =~ m/^(.*?)(\{(.*)\})?$/;
  44. $line =~ s/ *$//;
  45. if ($cond_block) {
  46. $cond_block =~ s/\}$//;
  47. $cond_block =~ s/^\{//;
  48. @conds = split m/\s*;\s*/, $cond_block;
  49. }
  50. push @{ $self->{steps} }, { line => $line, conds => \@conds };
  51. }
  52. return scalar @{ $self->{steps} };
  53. }
  54. sub generate_slave {
  55. my $self = shift;
  56. my $args = shift;
  57. my $slave = SugarTrail::Template::Slave->new($args);
  58. my @slave_steps;
  59. STEP: foreach my $master_step (@{ $self->{steps} }) {
  60. my $accept = 1;
  61. my $slave_step = {
  62. line => $master_step->{line},
  63. warnings => []
  64. };
  65. COND: foreach my $condstr (@{ $master_step->{conds} }) {
  66. my $c = SugarTrail::Template::Condition->new($condstr);
  67. my ($r, $w) = $c->match($args);
  68. # if warnings, store them, prepare to accept and ignore result
  69. if (scalar @$w) {
  70. $accept = 1;
  71. push @{$slave_step->{warnings}}, @$w;
  72. next COND;
  73. } else {
  74. # point of no warnings -- refusal should be valid here
  75. $accept = 0 unless $r;
  76. }
  77. }
  78. push @slave_steps, $slave_step
  79. if ($accept || scalar @{$slave_step->{warnings}});
  80. }
  81. $slave->{meta}->{'Stm'} = $self->{stm};
  82. $slave->{meta}->{'Stm Revision'} = $self->get_current_revision();
  83. $slave->{meta}->{'Params'} = mkmymime($args);
  84. $slave->{steps} = \@slave_steps;
  85. return $slave;
  86. }
  87. # skel: returns time (might be useful in absence of VCS)
  88. sub get_current_revision {
  89. return time;
  90. }
  91. sub mkmymime {
  92. my $d = shift;
  93. my $d1 = "; "; my $d2 = "=";
  94. my @t;
  95. foreach (sort keys %$d) {
  96. push @t, $_ . $d2 . $d->{$_};
  97. }
  98. return join $d1, @t;
  99. }
  100. 1;