diff Lib/IMPL/Web/Application/Resource.pm @ 268:4abda21186cd

*refactoring IMPL::Web: added 'application' property to resources
author cin
date Mon, 21 Jan 2013 02:08:17 +0400
parents 32aceba4ee6d
children 546957c50a36
line wrap: on
line diff
--- a/Lib/IMPL/Web/Application/Resource.pm	Thu Jan 17 02:39:44 2013 +0400
+++ b/Lib/IMPL/Web/Application/Resource.pm	Mon Jan 21 02:08:17 2013 +0400
@@ -17,11 +17,12 @@
         'IMPL::Web::Application::ResourceInterface' => undef
       ],
       props => [
-        parent   => PROP_RO,
-        model    => PROP_RO,
-        id       => PROP_RO,
-        contract => PROP_RO,
-        location => PROP_RO,
+        application => PROP_RO,
+        parent      => PROP_RO,
+        model       => PROP_RO,
+        id          => PROP_RO,
+        contract    => PROP_RO,
+        location    => PROP_RO,
       ]
 };
 
@@ -37,64 +38,67 @@
     $this->model( $args{model} );
     $this->id( $args{id} );
     $this->contract( $args{contract} );
+    $this->application( $args{application} || ($args{parent} && $args{parent}->application) );
 
-    # если расположение явно не указано, то оно вычисляется автоматически,
-    # либо остается не заданным
-    $this->location( $args{location} || eval { $this->parent->location->Child( $this->id ) } );
+# если расположение явно не указано, то оно вычисляется автоматически,
+# либо остается не заданным
+    $this->location( $args{location}
+          || eval { $this->parent->location->Child( $this->id ) } );
 }
 
 sub InvokeHttpVerb {
-      my ( $this, $verb, $action ) = @_;
+    my ( $this, $verb, $action ) = @_;
+
+    my $operation = $this->contract->verbs->{ lc($verb) };
 
-      my $operation = $this->contract->verbs->{ lc($verb) };
-      
-      die NotAllowedException->new(
-          allow => join( ',', map( uc, keys %{ $this->contract->verbs } ) )
-      )
-        unless $operation;
-      
-      # в случае, когда один ресурс вызывает HTTP метод другого ресурса, нужно
-      # сохранить оригинальный resourceLocation  
-      $action->context->{resourceLocation} ||= $this->location; 
+    die NotAllowedException->new(
+        allow => join( ',', map( uc, keys %{ $this->contract->verbs } ) ) )
+      unless $operation;
 
-      return $operation->Invoke( $this, $action );
+# в случае, когда один ресурс вызывает HTTP метод другого ресурса, нужно
+# сохранить оригинальный resourceLocation
+    $action->context->{resourceLocation} ||= $this->location;
+
+    return _InvokeDelegate($operation, $this, $action );
 }
 
 # это реализация по умолчанию, базируется информации о ресурсах, содержащийся
 # в контракте.
 sub FetchChildResource {
-      my ( $this, $childId ) = @_;
-      
-      my ($info,$childIdParts) = $this->contract->FindChildResourceInfo($childId);
-      
-      die NotFoundException->new($this->location->url,$childId) unless $info;
-      
-      my $binding = $info->{binding};
-      my $contract = $info->{contract};
-        
-      if (ref $contract eq 'CODE') {
-          $contract = $contract->();
-          $info->{contract} = $contract;
-      }
-      
-      die OperationException->new("Can't fetch a contract for the resource", $childId)
-        unless $contract;
-        
-      my %args = (
-            parent => $this,
-            id     => $childId
-      );
-      
-      $args{model} = _InvokeDelegate($binding,$this,@$childIdParts);
+    my ( $this, $childId ) = @_;
+
+    my ( $info, $childIdParts ) =
+      $this->contract->FindChildResourceInfo($childId);
+
+    die NotFoundException->new( $this->location->url, $childId ) unless $info;
+
+    my $binding  = $info->{binding};
+    my $contract = $info->{contract};
+    my $model    = _InvokeDelegate( $binding, $this, @$childIdParts );
 
-      return $contract->CreateResource(%args);
+    if ( ref $contract eq 'CODE' || $contract->can('Invoke')) {
+        $contract = _InvokeDelegate($contract,$this,$model);
+        $info->{contract} = $contract;
+    }
+
+    die OperationException->new( "Can't fetch a contract for the resource",
+        $childId )
+      unless $contract;
+
+    my %args = (
+        parent => $this,
+        id     => $childId,
+        model  => $model
+    );
+
+    return $contract->CreateResource(%args);
 }
 
 sub _InvokeDelegate {
     my $delegate = shift;
-    
+
     return $delegate->(@_) if ref $delegate eq 'CODE';
-    return $delegate->Invoke(@_) if eval { $delegate->can('Invoke')};
+    return $delegate->Invoke(@_) if eval { $delegate->can('Invoke') };
 }
 
 1;
@@ -158,6 +162,12 @@
 
 =head1 MEMBERS
 
+=head2 C<[get]application>
+
+Ссылка на приложение, к которому относится данный ресурс. Его следует задавать
+только для коренвых ресурсов, дочерние ресурсы получают это свойство от
+родителей.
+
 =head2 C<[get]contract>
 
 Обязательное свойство для ресурса, ссылается, на контракт, соответствующий
@@ -185,4 +195,16 @@
 автоматически (только для ресурсов имеющих родителя). Следует заметить, что
 адрес ресурса не содержит параметров запроса, а только путь.
 
+=head2 C<[get]FetchChildResource($id)>
+
+Возвращает дочерний ресурс, по его идентификатору.
+
+Данная реализация использует контракт текущего ресурса для поиска информации о
+дочернем ресурсе C<< $this->contract->FindChildResourceInfo($id) >>.
+
+Затем осуществляется привязка к моделе, тоесть, выполняется делегат, для
+получения модели дочернего ресурса, а затем осуществляется привязка к контракту,
+при этом в делегат, который должен вернуть контракт дочернего ресурса передаются
+текущий ресурc и модель дочернего ресурса.
+
 =cut