Mercurial > pub > Impl
comparison Lib/IMPL/Web/TT/Form.pm @ 194:4d0e1962161c
Replaced tabs with spaces
IMPL::Web::View - fixed document model, new features (control classes, document constructor parameters)
| author | cin |
|---|---|
| date | Tue, 10 Apr 2012 20:08:29 +0400 |
| parents | d1676be8afcc |
| children |
comparison
equal
deleted
inserted
replaced
| 193:8e8401c0aea4 | 194:4d0e1962161c |
|---|---|
| 7 use IMPL::DOM::Navigator::SchemaNavigator(); | 7 use IMPL::DOM::Navigator::SchemaNavigator(); |
| 8 | 8 |
| 9 __PACKAGE__->PassThroughArgs; | 9 __PACKAGE__->PassThroughArgs; |
| 10 | 10 |
| 11 BEGIN { | 11 BEGIN { |
| 12 public property base => prop_all; | 12 public property base => prop_all; |
| 13 public property schema => prop_all; | 13 public property schema => prop_all; |
| 14 public property errors => prop_all; | 14 public property errors => prop_all; |
| 15 public property data => prop_all; | 15 public property data => prop_all; |
| 16 public property state => prop_all; | 16 public property state => prop_all; |
| 17 public property formResult => prop_all; | 17 public property formResult => prop_all; |
| 18 } | 18 } |
| 19 | 19 |
| 20 sub CTOR { | 20 sub CTOR { |
| 21 my ($this) = @_; | 21 my ($this) = @_; |
| 22 | 22 |
| 23 if (my $form = $this->formResult) { | 23 if (my $form = $this->formResult) { |
| 24 $this->base($form->{formName}); | 24 $this->base($form->{formName}); |
| 25 $this->errors($form->{formErrors}); | 25 $this->errors($form->{formErrors}); |
| 26 $this->data($form->{formData}); | 26 $this->data($form->{formData}); |
| 27 $this->schema($form->{formSchema}); | 27 $this->schema($form->{formSchema}); |
| 28 $this->state($form->{state}); | 28 $this->state($form->{state}); |
| 29 } else { | 29 } else { |
| 30 | 30 |
| 31 $this->base($this->nodeName) unless $this->base; | 31 $this->base($this->nodeName) unless $this->base; |
| 32 | 32 |
| 33 die new IMPL::InvalidArgumentException('A schema is required for a form',$this->nodeName) | 33 die new IMPL::InvalidArgumentException('A schema is required for a form',$this->nodeName) |
| 34 unless eval { $this->schema->isa( typeof IMPL::DOM::Schema ) }; | 34 unless eval { $this->schema->isa( typeof IMPL::DOM::Schema ) }; |
| 35 | 35 |
| 36 die new IMPL::InvalidOperationException('Can\'t find a form definition in a schema',$this->nodeName,$this->base) | 36 die new IMPL::InvalidOperationException('Can\'t find a form definition in a schema',$this->nodeName,$this->base) |
| 37 unless $this->schema->selectNodes(sub { $_->nodeName eq 'ComplexNode' and $_->name eq $this->base }); | 37 unless $this->schema->selectNodes(sub { $_->nodeName eq 'ComplexNode' and $_->name eq $this->base }); |
| 38 } | 38 } |
| 39 | 39 |
| 40 $this->errors([]) unless $this->errors; | 40 $this->errors([]) unless $this->errors; |
| 41 } | 41 } |
| 42 | 42 |
| 43 sub fillContents { | 43 sub fillContents { |
| 44 my ($this) = @_; | 44 my ($this) = @_; |
| 45 | 45 |
| 46 my $schema = $this->schema->selectSingleNode(sub { $_->nodeName eq 'ComplexNode' and $_->name eq $this->base }); | 46 my $schema = $this->schema->selectSingleNode(sub { $_->nodeName eq 'ComplexNode' and $_->name eq $this->base }); |
| 47 | 47 |
| 48 $this->buildContainer( | 48 $this->buildContainer( |
| 49 $schema, | 49 $schema, |
| 50 $schema, | 50 $schema, |
| 51 $this->data->isComplex ? $this->data : undef, | 51 $this->data->isComplex ? $this->data : undef, |
| 52 $this | 52 $this |
| 53 ); | 53 ); |
| 54 } | 54 } |
| 55 | 55 |
| 56 sub buildContainer { | 56 sub buildContainer { |
| 57 my ($this,$schemaSource,$schema,$domNode,$container,$path) = @_; | 57 my ($this,$schemaSource,$schema,$domNode,$container,$path) = @_; |
| 58 | 58 |
| 59 $path = [@{$path || []},{node => $domNode, schemaSource => $schemaSource}]; | 59 $path = [@{$path || []},{node => $domNode, schemaSource => $schemaSource}]; |
| 60 | 60 |
| 61 $container ||= $this->document->Create($schemaSource->name,'IMPL::Web::TT::Collection'); | 61 $container ||= $this->document->Create($schemaSource->name,'IMPL::Web::TT::Collection'); |
| 62 | 62 |
| 63 foreach my $schemaItem ( $schema->content->childNodes ) { | 63 foreach my $schemaItem ( $schema->content->childNodes ) { |
| 64 my $schemaItemSource = $schemaItem; | 64 my $schemaItemSource = $schemaItem; |
| 65 | 65 |
| 66 $schemaItem = $this->schema->resolveType($schemaItem->type) | 66 $schemaItem = $this->schema->resolveType($schemaItem->type) |
| 67 if typeof $schemaItem eq typeof IMPL::DOM::Schema::Node; | 67 if typeof $schemaItem eq typeof IMPL::DOM::Schema::Node; |
| 68 | 68 |
| 69 my @nodesData = $domNode->selectNodes(sub { $_->schemaSource == $schemaItemSource } ) if $domNode; | 69 my @nodesData = $domNode->selectNodes(sub { $_->schemaSource == $schemaItemSource } ) if $domNode; |
| 70 | 70 |
| 71 push @nodesData, undef unless @nodesData; | 71 push @nodesData, undef unless @nodesData; |
| 72 | 72 |
| 73 if ($schemaItem->isa(typeof IMPL::DOM::Schema::ComplexNode) ) { | 73 if ($schemaItem->isa(typeof IMPL::DOM::Schema::ComplexNode) ) { |
| 74 $this->appendChild( $this->buildContainer($schemaItemSource,$schemaItem,$_,undef,$path) ) foreach @nodesData; | 74 $this->appendChild( $this->buildContainer($schemaItemSource,$schemaItem,$_,undef,$path) ) foreach @nodesData; |
| 75 } elsif ($schemaItem->isa(typeof IMPL::DOM::Schema::SimpleNode)) { | 75 } elsif ($schemaItem->isa(typeof IMPL::DOM::Schema::SimpleNode)) { |
| 76 $this->appendChild( $this->buildControl($schemaItemSource,$schemaItem,$_,$path) ) foreach @nodesData; | 76 $this->appendChild( $this->buildControl($schemaItemSource,$schemaItem,$_,$path) ) foreach @nodesData; |
| 77 } | 77 } |
| 78 } | 78 } |
| 79 | 79 |
| 80 return $container; | 80 return $container; |
| 81 } | 81 } |
| 82 | 82 |
| 83 sub buildControl { | 83 sub buildControl { |
| 84 my ($this,$schemaSource,$schema,$node,$path) = @_; | 84 my ($this,$schemaSource,$schema,$node,$path) = @_; |
| 85 | 85 |
| 86 my @errors; | 86 my @errors; |
| 87 | 87 |
| 88 if ($node) { | 88 if ($node) { |
| 89 @errors = grep { ($_->Node || $_->Parent) == $node } @{$this->errors}; | 89 @errors = grep { ($_->Node || $_->Parent) == $node } @{$this->errors}; |
| 90 } else { | 90 } else { |
| 91 @errors = grep $_->Schema == $schemaSource, @{$this->errors}; | 91 @errors = grep $_->Schema == $schemaSource, @{$this->errors}; |
| 92 } | 92 } |
| 93 | 93 |
| 94 return $this->document->CreateControl( | 94 return $this->document->CreateControl( |
| 95 $schemaSource->name, | 95 $schemaSource->name, |
| 96 $this->mapType($schemaSource), | 96 $this->mapType($schemaSource), |
| 97 { | 97 { |
| 98 schema => $schema, | 98 schema => $schema, |
| 99 sourceSchema => $schemaSource, | 99 sourceSchema => $schemaSource, |
| 100 errors => \@errors, | 100 errors => \@errors, |
| 101 data => $node, | 101 data => $node, |
| 102 inputType => $schemaSource->nodeProperty('inputType') || $schema->nodeProperty('inputType'), | 102 inputType => $schemaSource->nodeProperty('inputType') || $schema->nodeProperty('inputType'), |
| 103 nodeValue => $node && $node->nodeValue, # small hack set a non dom class property through | 103 nodeValue => $node && $node->nodeValue, # small hack set a non dom class property through |
| 104 queryParameter => $this->makeParameterName([@$path,{ node => $node, schemaSource => $schemaSource}]) | 104 queryParameter => $this->makeParameterName([@$path,{ node => $node, schemaSource => $schemaSource}]) |
| 105 } | 105 } |
| 106 ); | 106 ); |
| 107 } | 107 } |
| 108 | 108 |
| 109 sub mapType { | 109 sub mapType { |
| 110 my ($this,$schema) = @_; | 110 my ($this,$schema) = @_; |
| 111 | 111 |
| 112 $schema->nodeProperty('control') || | 112 $schema->nodeProperty('control') || |
| 113 ( $schema->type && $this->schema->resolveType($schema->type)->nodeProperty('control') ) | 113 ( $schema->type && $this->schema->resolveType($schema->type)->nodeProperty('control') ) |
| 114 or die new IMPL::Exception("Unable to get control class for the form element",$schema->path); | 114 or die new IMPL::Exception("Unable to get control class for the form element",$schema->path); |
| 115 } | 115 } |
| 116 | 116 |
| 117 sub makeParameterName { | 117 sub makeParameterName { |
| 118 my ($this,$path) = @_; | 118 my ($this,$path) = @_; |
| 119 | 119 |
| 120 join '/', map { | 120 join '/', map { |
| 121 $_->{node} ? | 121 $_->{node} ? |
| 122 ( | 122 ( |
| 123 $_->{node}->nodeProperty('instanceId') ? | 123 $_->{node}->nodeProperty('instanceId') ? |
| 124 $_->{node}->nodeName . '['. ']' : | 124 $_->{node}->nodeName . '['. ']' : |
| 125 $_->{node}->nodeName | 125 $_->{node}->nodeName |
| 126 ) : | 126 ) : |
| 127 ( | 127 ( |
| 128 $_->{schemaSource}->maxOccur eq 'unbounded' || $_->{schemaSource}->maxOccur > 1 ? | 128 $_->{schemaSource}->maxOccur eq 'unbounded' || $_->{schemaSource}->maxOccur > 1 ? |
| 129 $_->{schemaSource}->name . '[0]' : | 129 $_->{schemaSource}->name . '[0]' : |
| 130 $_->{schemaSource}->name | 130 $_->{schemaSource}->name |
| 131 ) | 131 ) |
| 132 } @$path; | 132 } @$path; |
| 133 } | 133 } |
| 134 | 134 |
| 135 sub makeControlArgs{ | 135 sub makeControlArgs{ |
| 136 my ($this,$path) = @_; | 136 my ($this,$path) = @_; |
| 137 | 137 |
| 138 my $navi = new IMPL::DOM::Navigator::SchemaNavigator($this->schema); | 138 my $navi = new IMPL::DOM::Navigator::SchemaNavigator($this->schema); |
| 139 my @path = ($this->base, split(/\./,$path) ); | 139 my @path = ($this->base, split(/\./,$path) ); |
| 140 | 140 |
| 141 $navi->NavigateName($_) or die new IMPL::InvalidArgumentException( | 141 $navi->NavigateName($_) or die new IMPL::InvalidArgumentException( |
| 142 "Can't find a definition for an element", | 142 "Can't find a definition for an element", |
| 143 $_, | 143 $_, |
| 144 $path, | 144 $path, |
| 145 $this->element, | 145 $this->element, |
| 146 ) foreach @path; | 146 ) foreach @path; |
| 147 | 147 |
| 148 my $schema = $navi->Current; | 148 my $schema = $navi->Current; |
| 149 my $sourceSchema = $navi->SourceSchemaNode; | 149 my $sourceSchema = $navi->SourceSchemaNode; |
| 150 my $queryParameter = join '/', @path; | 150 my $queryParameter = join '/', @path; |
| 151 shift @path; | 151 shift @path; |
| 152 my $node = $this->data ? $this->data->selectSingleNode(@path) : undef; | 152 my $node = $this->data ? $this->data->selectSingleNode(@path) : undef; |
| 153 | 153 |
| 154 my @errors; | 154 my @errors; |
| 155 | 155 |
| 156 if ($node) { | 156 if ($node) { |
| 157 @errors = grep { ($_->Node || $_->Parent) == $node } @{$this->errors}; | 157 @errors = grep { ($_->Node || $_->Parent) == $node } @{$this->errors}; |
| 158 } else { | 158 } else { |
| 159 @errors = grep $_->Schema == $sourceSchema, @{$this->errors}; | 159 @errors = grep $_->Schema == $sourceSchema, @{$this->errors}; |
| 160 } | 160 } |
| 161 | 161 |
| 162 return { | 162 return { |
| 163 schema => $schema, | 163 schema => $schema, |
| 164 sourceSchema => $sourceSchema, | 164 sourceSchema => $sourceSchema, |
| 165 errors => \@errors, | 165 errors => \@errors, |
| 166 data => $node, | 166 data => $node, |
| 167 nodeValue => $node && $node->nodeValue, # small hack set a non dom class property through | 167 nodeValue => $node && $node->nodeValue, # small hack set a non dom class property through |
| 168 queryParameter => $queryParameter, | 168 queryParameter => $queryParameter, |
| 169 inputType => $sourceSchema->nodeProperty('inputType') || $schema->nodeProperty('inputType') | 169 inputType => $sourceSchema->nodeProperty('inputType') || $schema->nodeProperty('inputType') |
| 170 }; | 170 }; |
| 171 } | 171 } |
| 172 | 172 |
| 173 sub makeContent { | 173 sub makeContent { |
| 174 my ($this,$mappings) = @_; | 174 my ($this,$mappings) = @_; |
| 175 | 175 |
| 176 my $formSchema = $this->schema->selectSingleNode(sub { $_->nodeName eq 'ComplexNode' and $_->name eq $this->base } ) | 176 my $formSchema = $this->schema->selectSingleNode(sub { $_->nodeName eq 'ComplexNode' and $_->name eq $this->base } ) |
| 177 or die new Exception("Cant find a schema element for the specified form", $this->base); | 177 or die new Exception("Cant find a schema element for the specified form", $this->base); |
| 178 | 178 |
| 179 my $doc = $this->document; | 179 my $doc = $this->document; |
| 180 foreach my $itemSchema ( $formSchema->content->childNodes ) { | 180 foreach my $itemSchema ( $formSchema->content->childNodes ) { |
| 181 my $itemName = $itemSchema->name; | 181 my $itemName = $itemSchema->name; |
| 182 if (my $controlClass = $mappings->{$itemName} ) { | 182 if (my $controlClass = $mappings->{$itemName} ) { |
| 183 my $contorl = $doc->CreateControl($itemName,$controlClass,$this->makeControlArgs($itemName)); | 183 my $contorl = $doc->CreateControl($itemName,$controlClass,$this->makeControlArgs($itemName)); |
| 184 $this->appendChild($contorl); | 184 $this->appendChild($contorl); |
| 185 } | 185 } |
| 186 } | 186 } |
| 187 return; | 187 return; |
| 188 } | 188 } |
| 189 | 189 |
| 190 sub formErrors { | 190 sub formErrors { |
| 191 my ($this) = @_; | 191 my ($this) = @_; |
| 192 | 192 |
| 193 if (my $node = $this->data ) { | 193 if (my $node = $this->data ) { |
| 194 return [ | 194 return [ |
| 195 grep { | 195 grep { |
| 196 ( $_->Node || $_->Parent) == $node | 196 ( $_->Node || $_->Parent) == $node |
| 197 } @{$this->errors} | 197 } @{$this->errors} |
| 198 ]; | 198 ]; |
| 199 } else { | 199 } else { |
| 200 return []; | 200 return []; |
| 201 } | 201 } |
| 202 } | 202 } |
| 203 | 203 |
| 204 1; | 204 1; |
| 205 __END__ | 205 __END__ |
| 206 | 206 |
