| line | stmt | bran | cond | sub | pod | time | code | 
| 1 |  |  |  |  |  |  | package Badger::Config::Schema; | 
| 2 |  |  |  |  |  |  |  | 
| 3 | 7 |  |  | 7 |  | 45 | use Badger::Debug ':dump'; | 
|  | 7 |  |  |  |  | 10 |  | 
|  | 7 |  |  |  |  | 37 |  | 
| 4 | 7 |  |  | 7 |  | 2343 | use Badger::Config::Item; | 
|  | 7 |  |  |  |  | 12 |  | 
|  | 7 |  |  |  |  | 410 |  | 
| 5 |  |  |  |  |  |  | use Badger::Class | 
| 6 | 7 |  |  |  |  | 53 | version   => 0.01, | 
| 7 |  |  |  |  |  |  | debug     => 0, | 
| 8 |  |  |  |  |  |  | base      => 'Badger::Base', | 
| 9 |  |  |  |  |  |  | import    => 'class CLASS', | 
| 10 |  |  |  |  |  |  | words     => 'CONFIG_SCHEMA', | 
| 11 |  |  |  |  |  |  | utils     => 'is_object', | 
| 12 |  |  |  |  |  |  | #    accessors => 'items', | 
| 13 |  |  |  |  |  |  | constants => 'HASH ARRAY DELIMITER', | 
| 14 |  |  |  |  |  |  | constant  => { | 
| 15 |  |  |  |  |  |  | CONFIG_METHOD => 'configure', | 
| 16 |  |  |  |  |  |  | CONFIG_ITEM   => 'Badger::Config::Item', | 
| 17 |  |  |  |  |  |  | VALUE         => 1, | 
| 18 |  |  |  |  |  |  | NOTHING       => 0, | 
| 19 |  |  |  |  |  |  | }, | 
| 20 |  |  |  |  |  |  | messages => { | 
| 21 |  |  |  |  |  |  | bad_type     => 'Invalid type prefix specified for %s: %s', | 
| 22 |  |  |  |  |  |  | bad_method   => 'Missing method for the %s %s configuration item: %s', | 
| 23 |  |  |  |  |  |  | dup_item     => 'Duplicate specification for scheme item: %s', | 
| 24 |  |  |  |  |  |  | bad_fallback => 'Invalid fallback item specified for %s: %s', | 
| 25 | 7 |  |  | 7 |  | 45 | }; | 
|  | 7 |  |  |  |  | 9 |  | 
| 26 |  |  |  |  |  |  |  | 
| 27 |  |  |  |  |  |  | sub init { | 
| 28 | 21 |  |  | 21 | 1 | 37 | my ($self, $config) = @_; | 
| 29 | 21 |  |  |  |  | 45 | $self->init_schema($config); | 
| 30 | 21 |  |  |  |  | 34 | return $self; | 
| 31 |  |  |  |  |  |  | } | 
| 32 |  |  |  |  |  |  |  | 
| 33 |  |  |  |  |  |  | sub init_schema { | 
| 34 | 21 |  |  | 21 | 0 | 28 | my ($self, $config) = @_; | 
| 35 | 21 |  |  |  |  | 39 | my $iclass = $self->CONFIG_ITEM; | 
| 36 | 21 |  |  |  |  | 25 | my ($name, $info, @aka, $fallback, $test, $item); | 
| 37 |  |  |  |  |  |  |  | 
| 38 | 21 |  | 66 |  |  | 49 | my $fall = $config->{ fallback } || $self; | 
| 39 | 21 |  |  |  |  | 65 | my $list = $self->{ items } = [ ]; | 
| 40 | 21 |  |  |  |  | 36 | my $hash = $self->{ item  } = { }; | 
| 41 |  |  |  |  |  |  |  | 
| 42 | 21 |  |  |  |  | 27 | my $schema = $config->{ schema }; | 
| 43 | 21 |  |  |  |  | 24 | my $extend = $config->{ extend }; | 
| 44 |  |  |  |  |  |  |  | 
| 45 | 21 |  |  |  |  | 21 | $self->debug("fallback is $fall") if DEBUG; | 
| 46 |  |  |  |  |  |  | # allow target class to be specified so we can resolve things like | 
| 47 |  |  |  |  |  |  | # package variables later | 
| 48 |  |  |  |  |  |  | #    $self->{ class } = $config->{ class } || $config->{ target }; | 
| 49 |  |  |  |  |  |  |  | 
| 50 |  |  |  |  |  |  | #    $self->debug("extending on from ", $self->dump_data($extend)); | 
| 51 |  |  |  |  |  |  |  | 
| 52 | 21 |  |  |  |  | 19 | $self->debug("Generating schema from config: ", $self->dump_data($config)) | 
| 53 |  |  |  |  |  |  | if DEBUG; | 
| 54 |  |  |  |  |  |  |  | 
| 55 |  |  |  |  |  |  | # We allow a scheme to be specified as a list reference in case the | 
| 56 |  |  |  |  |  |  | # order of evaluation is important.  For convenience, we also accept | 
| 57 |  |  |  |  |  |  | # a hash ref for a schema specification where the order isn't important. | 
| 58 |  |  |  |  |  |  | # The values in the hash array can themselves be hash references or | 
| 59 |  |  |  |  |  |  | # simple values which we assume is the default value. | 
| 60 |  |  |  |  |  |  | $schema = [ | 
| 61 |  |  |  |  |  |  | map { | 
| 62 | 21 | 100 |  |  |  | 54 | my $k = $_; | 
|  | 6 |  |  |  |  | 8 |  | 
| 63 | 6 |  |  |  |  | 6 | my $v = $schema->{ $k }; | 
| 64 | 6 | 50 |  |  |  | 29 | ref $v eq HASH | 
| 65 |  |  |  |  |  |  | ? { name => $k, %$v } | 
| 66 |  |  |  |  |  |  | : { name => $k, default => $v } | 
| 67 |  |  |  |  |  |  | } | 
| 68 |  |  |  |  |  |  | keys %$schema | 
| 69 |  |  |  |  |  |  | ] if ref $schema eq HASH; | 
| 70 |  |  |  |  |  |  |  | 
| 71 | 21 | 100 |  |  |  | 86 | $schema = [ @$schema, $extend ? @$extend : () ]; | 
| 72 |  |  |  |  |  |  |  | 
| 73 | 21 |  |  |  |  | 26 | $self->debug("Canonical schema config: ", $self->dump_data($schema)) | 
| 74 |  |  |  |  |  |  | if DEBUG; | 
| 75 |  |  |  |  |  |  |  | 
| 76 | 21 |  |  |  |  | 43 | while (@$schema) { | 
| 77 | 74 |  |  |  |  | 96 | $name = shift @$schema; | 
| 78 | 74 |  |  |  |  | 78 | $item = undef; | 
| 79 | 74 |  |  |  |  | 87 | $info = undef; | 
| 80 |  |  |  |  |  |  |  | 
| 81 |  |  |  |  |  |  | # TODO: not sure about this - we change the name.... | 
| 82 |  |  |  |  |  |  | # skip anything we've already done | 
| 83 |  |  |  |  |  |  |  | 
| 84 | 74 |  |  |  |  | 67 | $self->debug("schema item: $name\n") if DEBUG; | 
| 85 |  |  |  |  |  |  |  | 
| 86 | 74 | 100 |  |  |  | 178 | if (ref $name eq HASH) { | 
|  |  | 100 |  |  |  |  |  | 
| 87 | 7 |  |  |  |  | 8 | $info = $name; | 
| 88 |  |  |  |  |  |  | $name = $info->{ name } | 
| 89 | 7 |  | 50 |  |  | 14 | || return $self->error("Invalid hash (no name): ", $self->dump_data($info)); | 
| 90 |  |  |  |  |  |  | } | 
| 91 |  |  |  |  |  |  | elsif (is_object(CONFIG_ITEM, $name)) { | 
| 92 | 15 |  |  |  |  | 20 | $item = $name; | 
| 93 | 15 |  |  |  |  | 23 | $name = $item->name; | 
| 94 |  |  |  |  |  |  | } | 
| 95 |  |  |  |  |  |  | else { | 
| 96 | 52 |  |  |  |  | 93 | $info = { name => $name }; | 
| 97 |  |  |  |  |  |  | } | 
| 98 | 74 |  |  |  |  | 74 | $self->debug("name: $name   info: $info") if DEBUG; | 
| 99 |  |  |  |  |  |  |  | 
| 100 | 74 |  | 33 |  |  | 229 | $info->{ fallback_provider } ||= $fall; | 
| 101 |  |  |  |  |  |  |  | 
| 102 | 74 |  | 66 |  |  | 262 | $item ||= $self->CONFIG_ITEM->new($info); | 
| 103 | 74 |  |  |  |  | 130 | $name = $item->name; | 
| 104 |  |  |  |  |  |  |  | 
| 105 | 74 | 100 |  |  |  | 131 | next if $hash->{ $name }; | 
| 106 |  |  |  |  |  |  |  | 
| 107 | 71 |  |  |  |  | 65 | $self->debug("generated item: $item") if DEBUG; | 
| 108 |  |  |  |  |  |  |  | 
| 109 | 71 |  |  |  |  | 129 | foreach my $alias ($item->names) { | 
| 110 |  |  |  |  |  |  | #            return $self->error_msg( dup_item => $name ) | 
| 111 |  |  |  |  |  |  | #                if $hash->{ $name }; | 
| 112 | 97 |  |  |  |  | 174 | $hash->{ $alias } = $item; | 
| 113 |  |  |  |  |  |  | } | 
| 114 | 71 |  |  |  |  | 67 | $self->debug("adding $name => $item to schema") if DEBUG; | 
| 115 | 71 |  |  |  |  | 146 | push(@$list, $item); | 
| 116 |  |  |  |  |  |  | } | 
| 117 |  |  |  |  |  |  |  | 
| 118 | 21 |  |  |  |  | 22 | $self->debug("created schema: ", $self->dump_data($self->{ items })) | 
| 119 |  |  |  |  |  |  | if DEBUG; | 
| 120 |  |  |  |  |  |  |  | 
| 121 | 21 |  |  |  |  | 42 | return $self; | 
| 122 |  |  |  |  |  |  | } | 
| 123 |  |  |  |  |  |  |  | 
| 124 |  |  |  |  |  |  |  | 
| 125 |  |  |  |  |  |  | sub fallback { | 
| 126 | 0 |  |  | 0 | 0 | 0 | my ($self, $name, $type, $data) = @_; | 
| 127 | 0 |  |  |  |  | 0 | return $self->error_msg( bad_fallback => $name, $type ); | 
| 128 |  |  |  |  |  |  | } | 
| 129 |  |  |  |  |  |  |  | 
| 130 |  |  |  |  |  |  |  | 
| 131 |  |  |  |  |  |  | sub configure { | 
| 132 | 37 |  |  | 37 | 0 | 69 | my ($self, $config, $target, $class) = @_; | 
| 133 | 37 |  |  |  |  | 85 | my $items = $self->{ items }; | 
| 134 | 37 |  |  |  |  | 52 | my ($element, $name, $alias, $code, @args, $ok, $value); | 
| 135 |  |  |  |  |  |  |  | 
| 136 | 37 |  | 33 |  |  | 63 | $class ||= $target; | 
| 137 |  |  |  |  |  |  |  | 
| 138 | 37 |  |  |  |  | 39 | $self->debug("configure(", CLASS->dump_data_inline($config), ')') if DEBUG; | 
| 139 | 37 |  |  |  |  | 37 | $self->debug("configure element: ", CLASS->dump_data($items)) if DEBUG; | 
| 140 |  |  |  |  |  |  |  | 
| 141 | 37 |  |  |  |  | 67 | ELEMENT: foreach $element (@$items) { | 
| 142 | 267 | 100 |  |  |  | 481 | $element->try->configure($config, $target, $class) | 
| 143 |  |  |  |  |  |  | || return $self->decline($element->reason); | 
| 144 |  |  |  |  |  |  | } | 
| 145 |  |  |  |  |  |  |  | 
| 146 | 36 |  |  |  |  | 99 | return $self; | 
| 147 |  |  |  |  |  |  | } | 
| 148 |  |  |  |  |  |  |  | 
| 149 |  |  |  |  |  |  |  | 
| 150 |  |  |  |  |  |  | sub item { | 
| 151 | 0 |  |  | 0 | 0 | 0 | my $self = shift; | 
| 152 | 0 |  |  |  |  | 0 | my $item = $self->{ item }; | 
| 153 |  |  |  |  |  |  | return @_ | 
| 154 | 0 | 0 |  |  |  | 0 | ? $item->{ $_[0] } | 
| 155 |  |  |  |  |  |  | : $item; | 
| 156 |  |  |  |  |  |  | } | 
| 157 |  |  |  |  |  |  |  | 
| 158 |  |  |  |  |  |  | sub items { | 
| 159 | 20 |  |  | 20 | 0 | 21 | my $self  = shift; | 
| 160 | 20 |  |  |  |  | 58 | my $items = $self->{ items }; | 
| 161 |  |  |  |  |  |  | return wantarray | 
| 162 | 20 | 50 |  |  |  | 65 | ? @$items | 
| 163 |  |  |  |  |  |  | :  $items; | 
| 164 |  |  |  |  |  |  |  | 
| 165 |  |  |  |  |  |  |  | 
| 166 |  |  |  |  |  |  | } | 
| 167 |  |  |  |  |  |  |  | 
| 168 |  |  |  |  |  |  | 1; |