changeset 67:9f5795a10939

Documentation, minor fixes
author wizard
date Fri, 19 Mar 2010 20:06:12 +0300
parents f47f93534005
children 739f1288ca84
files Lib/IMPL/Object/Factory.pm Lib/IMPL/Web/Application.pm Lib/IMPL/Web/Application/Action.pm Lib/IMPL/Web/Application/Response.pm _test/Resources/app.xml
diffstat 5 files changed, 334 insertions(+), 60 deletions(-) [+]
line wrap: on
line diff
--- a/Lib/IMPL/Object/Factory.pm	Thu Mar 18 17:58:33 2010 +0300
+++ b/Lib/IMPL/Object/Factory.pm	Fri Mar 19 20:06:12 2010 +0300
@@ -70,14 +70,6 @@
 
 =begin code
 
-sub ProcessItems {
-	my ($factory,$items);
-	
-	return map $factory->new($_), @$items;
-}
-
-my @users = ProcessItems('MyApp::User',$db->selectUsers);
-
 my $factory = new IMPL::Object::Factory(
 	'MyApp::User',
 	{
@@ -85,13 +77,35 @@
 	}
 );
 
+my $class = 'MyApp::User';
+
+my $user;
+
+$user = $class->new(name => 'nobody'); # will create object MyApp::User
+                                       # and pass parameters (name=>'nobody')
+											
+$user = $factory->new(name => 'root'); # will create object MyApp::User
+                                       # and pass paremeters (isAdmin => 1, name => 'root')
+
 =end code
 
-my @admins = ProcessItems($factory,$db->selectAdmins);
+Или сериализованная форма в XML.
+
+=begin code xml
 
+<factory type="IMPL::Object::Factory">
+	<factory>MyApp::User</factory>,
+	<parameters type="HASH">
+		<isAdmin>1</isAdmin>
+	</parameters>
+</factory>
+
+=end code xml
 
 =head1 DESCRIPTION
 
+C<[Serializable]>
+
 Класс, реализующий фабрику классов.
 
 Фабрика классов это любой объект, который имеет метод C< new > вызов которого приводит к созданию нового
@@ -108,16 +122,56 @@
 
 =over
 
-=item C< factory >
+=item C< CTOR($factory,$parameters) >
+
+Создает новый экземпляр
+
+=over
+
+=item C<$factory>
+
+Либо имя класса, либо другая фабрика.
+
+=item C<$parameters>
+
+Ссылка на параметры для создания объектов, может быть ссылкой на хеш, массив и т.д.
+
+Если является ссылкой на хеш, то при создании объектов данной фабрикой этот хеш
+будет развернут в список и передан параметрами методу C<new>.
+
+Если является ссылкой на массив, то при создании объектов данной фабрикой этот массив
+будет передан в списк и передан параметрами методу C<new>.
+
+Если является любым другим объектом или скаляром, то будет передан параметром методу
+C<new> как есть.
+
+=back
+
+=item C< [get] factory >
 
 Свойство, содержащее фабрику для создание новых объектов текущей фабрикой. Чаще всего оно содержит
 имя класса.
 
-=item C< parameters >
+=item C< [get] parameters >
 
 Свойство, содержит ссылку на параметры для создания объектов, при создании объекта эти параметры будут
 развернуты в список и переданы оператору C< new > фабрике из свойства C< factory >, за ними будут
-следовать параметры непосредственно текущей фабрики. 
+следовать параметры непосредственно текущей фабрики.
+
+=item C<new(@params)>
+
+Создает новый объект, используя свйство C<factory> как фабрику и передавая туда параметры
+из свойства C<parameters> и списка C<@params>. Ниже приведен упрощенный пример, как это происходит.
+
+=begin code
+
+sub new {
+	my ($this,@params) = @_;
+	
+	return $this->factory->new(_as_list($this->parameters), @params);
+}
+
+=end code
 
 =back
 
--- a/Lib/IMPL/Web/Application.pm	Thu Mar 18 17:58:33 2010 +0300
+++ b/Lib/IMPL/Web/Application.pm	Fri Mar 19 20:06:12 2010 +0300
@@ -14,7 +14,7 @@
 
 BEGIN {
     public property handlerError => prop_all;
-    public property factoryAction => prop_all;
+    public property actionFactory => prop_all;
     public property handlersQuery => prop_all | prop_list;
     public property responseCharset => prop_all;
     public property options => prop_all;
@@ -30,7 +30,7 @@
 sub CTOR {
 	my ($this) = @_;
 	
-	$this->factoryAction('IMPL::Web::Application::Action') unless $this->factoryAction;
+	$this->actionFactory('IMPL::Web::Application::Action') unless $this->actionFactory;
 	$this->responseCharset('utf-8') unless $this->responseCharset;
 }
 
@@ -39,7 +39,7 @@
     
     while (my $query = $this->FetchRequest()) {
         
-        my $action = $this->factoryAction->new(
+        my $action = $this->actionFactory->new(
         	query => $query,
         	application => $this, 
         );
@@ -72,8 +72,15 @@
 
 =head1 SYNOPSIS
 
+=begin code
+
 require MyApp;
-MyApp->spawn('app.config')->Run();
+
+my $instance = spawn MyApp('app.config');
+
+$instance->Run();
+
+=end code
 
 =head1 DESCRIPTION
 
@@ -82,13 +89,94 @@
 
 Процесс обработки запроса состоит из следующих частей
 
-1. Получение cgi запроса
-2. Вызов модуля для инициализации объекта действия
-3. Инициализация контекста выполнения 
-4. Выполнение запроса
-5. Преобразование полученных данных в тело ответа
+=over
+
+=item 1
+
+Получение cgi запроса
+
+=item 2
 
+Создание объекта C<IMPL::Web::Application::Action>
 
+=item 3
 
+Формирование цепочки вызовов при помощи C<< IMPL::Web::Application::Action->ChainHandler >>
+
+=item 4
+
+Выполнение запроса C<< IMPL::Web::Application::Action->Invoke >>
 
 =cut
+
+Также приложение поддерживает отложенное создание объектов, которые по первому обращению
+к свойствам. Это реализовано в базовом классе C< IMPL::Configuration >. Для настройки
+активаторов можно использовать свойство C<options>, в которое должен быть помещен хеш
+со ссылками на активаторы, см. пример ниже C<CONFIGURATION>. 
+
+=head2 CONFIGURATION
+
+Ниже приведен пример конфигурации приложения
+
+=begin code xml
+
+<?xml version="1.0" encoding="UTF-8"?>
+<Application id='app' type="Test::Web::Application::Instance">
+	
+	<!-- Begin custom properties -->
+	<name>Sample application</name>
+	<dataSource type='IMPL::Config::Activator' id='ds'>
+		<factory>IMPL::Object</factory>
+		<parameters type='HASH'>
+			<db>data</db>
+			<user>nobody</user>
+		</parameters>
+	</dataSource>
+	<securityMod type='IMPL::Config::Activator'>
+		<factory>IMPL::Object</factory>
+		<parameters type='HASH'>
+			<ds refid='ds'/>
+		</parameters>
+	</securityMod>	
+	<!-- End custom properties -->
+	
+	<!-- direct access to the activators -->
+	<options type="HASH">
+		<dataSource refid='ds'/>
+	</options>
+	
+	<!-- Set default output encoding, can be changed due query handling -->
+	<responseCharset>utf-8</responseCharset>
+	
+	<!-- Actions creation configuration -->
+	<actionFactory type="IMPL::Object::Factory">
+		
+		<!-- Construct actions -->		
+		<factory>IMPL::Web::Application::Action</factory>
+		<parameters type='HASH'>
+			
+			<!-- with special responseFactory -->
+			<responseFactory type='IMPL::Object::Factory'>
+			
+				<!-- Where resopnses have a special streamOut -->
+				<factory>IMPL::Web::Application::Response</factory>
+				<parameters type='HASH'>
+				
+					<!-- in memory dummy output instead of STDOUT -->
+					<streamOut>memory</streamOut>
+					
+				</parameters>
+			</responseFactory>
+		</parameters>
+	</actionFactory>
+	
+	<!-- Query processing chain -->
+	<handlersQuery type="IMPL::Object::List">
+		<item type="IMPL::Web::QueryHandler::PageFormat">
+			<templatesCharset>cp1251</templatesCharset>
+		</item>
+	</handlersQuery>
+</Application>
+
+=end code xml
+
--- a/Lib/IMPL/Web/Application/Action.pm	Thu Mar 18 17:58:33 2010 +0300
+++ b/Lib/IMPL/Web/Application/Action.pm	Fri Mar 19 20:06:12 2010 +0300
@@ -87,49 +87,159 @@
 
 =pod
 
+=head1 NAME
+
+C<IMPL::Web::Application::Action> - Обертка вокруг C<CGI> запроса.
+
 =head1 DESCRIPTION
 
-Определяет порядок выполнения запроса.
+C<[Infrastructure]>
 
-Запрос выполняется последовательным вызовом цепочки обработчиков, при этом обработчики
-сами вызывают следующие.
+Определяет порядок выполнения запроса. Запрос выполняется последовательным вызовом
+цепочки обработчиков, при этом обработчики сами вызывают следующие.
+Обработчики выполняются в порядке, обратном их добавлению.
 
 Типичная цепочка может быть такой, в порядке добавления
 
-SecCallToMethod($target,$method)
-AuthenticateMethod
-TDocumentOut($file)
+=begin code
+
+IMPL::Web::QueryHandler::SecCallToMethod
+IMPL::Web::QueryHandler::AuthenticateCookie
+IMPL::Web::QueryHandler::PageFormat
+
+=end code
 
 что приведет к следующей последовательности
 
-Action->Invoke() {
-	TDocumentOut->Invoke($Action,$nextHandler) {
-		my $result = $nextHandler() {
-			$AuthenticateMethod($Action,$nextHandler) {
-				my $context = $Action->application->security->Authenticate($Action->query,$Action->response);
-				return $context->Impersonate($nextHandler) {
-					$objSecCallToMethod->Invoke($Action,undef) {
+=begin code
+
+# the application creates a new Action object 
+
+my $action = $application->actionFactory->new(
+	action => $application, # the application passes self
+	query => $query # current CGI query
+);
+
+# forms query handlers stack
+
+$action->ChainHandler($_) foreach qw (
+	IMPL::Web::QueryHandler::SecCallToMethod
+	IMPL::Web::QueryHandler::AuthenticateCookie
+	IMPL::Web::QueryHandler::PageFormat
+);
+
+# and finally invokes the action
+
+$action->Invoke() {
+	
+	# some internals
+	
+	IMPL::Web::QueryHandler::PageFormat->Invoke($action,$nextHandlerIsAuthHandler) {
+		
+		#some internals
+		
+		my $result = $nextHandlerIsAuthHandler() {
+			
+			# some internals
+
+			IMPL::Web::QueryHandler::AuthenticateCookie->Invoke($action,$nextHandlerIsSecCall) {
+				
+				# some internals
+				# do auth and generate security $context 
+				
+				# impersonate $context and call the next handler				
+				return $context->Impersonate($nextHandlerIsSecCall) {
+					
+					# some internals 
+					
+					IMPL::Web::QueryHandler::SecCallToMethod->Invoke($action,undef) {
+						
+						# next handler isn't present as it is the last hanler
+						
+						# some internals
+						# calculate the $method and the $target from CGI request
+												
 						IMPL::Security->AccessCheck($target,$method);
 						return $target->$method();
+						
 					}
+					
 				}
+				
 			}
 		}
-		$this->format($result,$Action->response->streamBody);
+		
+		# some intenals
+		# formatted output to $action->response->streamBody		
 	}		
 }
 
+=end code
+
 или как альтернатива может быть еще
 
-$objSecCallToMethod($target,$method)
-$AuthenticateMethod
-$TransfromToSimpleData
-$JSONOut
+=begin code
+
+IMPL::Web::QueryHandler::SecCallToMethod
+IMPL::Web::QueryHandler::AuthenticateCookie
+IMPL::Web::QueryHandler::Filter->new( target => IMPL::Transform::ObjectToJSON->new() , method => 'Transform')
+IMLP::Web::QueryHandler::JSONFormat
+
+
+=end code
 
 В данной цепочке также происходит вызов метода, но его результат потом преобразуется
 в простые структуры и передается JSON преобразователю. Таким образом модулю логики
 не требуется знать о выходном формате, всю работу проделают дополнительные фильтры.
 
+=head1 MEMBERS
+
+=head2 PROPERTIES
+
+=over
+
+=item C< [get] application>
+
+Экземпляр приложения создавшего текущий объект
+
+=item C< [get] query >
+
+Экземпляр C<CGI> запроса
+
+=item C< [get] response >
+
+Ответ на C<CGI> заспрос C<IMPL::Web::Application::Response>
+
+=item C< [get] responseFactory >
+
+Фабрика ответов на запрос, используется для создания нового ответа
+либо при конструировании текущего объекта C<IMPL::Web::Application::Action>,
+либо при вызове метода C<ReinitResponse> у текущего объекта.
+
+По умолчанию имеет значение C<IMPL::Web::Application::Response>
+
+=back
+
+=head2 METHODS
+
+=over
+
+=item C< ReinitResponse() >
+
+Отмена старого ответа C<response> и создание вместо него нового.
+
+Данная операция обычно проводится при обработке ошибок, когда
+уже сформированный ответ требуется отменить. Следует заметить,
+что эта операция не возможна, если ответ частично или полностью
+отправлен клиенту. Тогда возникает исключение C<IMPL::InvalidOperationException>.
+
+=item C< ChainHandler($handler) >
+
+Добавляет новый обработчик в цепочку. Выполнение цепочки начинается с конца,
+тоесть последний добавленный будет выполнен первым. 
+
+=back
+
 =head1 HANDLERS
 
 =head2 subroutines
@@ -151,9 +261,9 @@
 
 =back 
 
-=head2 C< IMPL::Web::Application::QueryHandler >
+=head2 C< IMPL::Web::QueryHandler >
 
-Любой объект наследованный от C< IMPL::Web::Application::QueryHandler > может быть
+Любой объект наследованный от C< IMPL::Web::QueryHandler > может быть
 использован в качестве обработчика запроса
 
 =cut
\ No newline at end of file
--- a/Lib/IMPL/Web/Application/Response.pm	Thu Mar 18 17:58:33 2010 +0300
+++ b/Lib/IMPL/Web/Application/Response.pm	Fri Mar 19 20:06:12 2010 +0300
@@ -14,6 +14,7 @@
 #todo: add binary method to set a binary encoding, set it automatic when type isn't a text 
 
 BEGIN {
+	# автозаполнение буде происходить в порядке объявления
 	public property query => prop_get | owner_set; # cgi query
 	public property status => prop_all, { validator => \&_checkHeaderPrinted };
 	public property contentType => prop_all, { validator => \&_checkHeaderPrinted }; # String
@@ -32,11 +33,19 @@
 
 __PACKAGE__->PassThroughArgs;
 
+our %CTOR = (
+	'IMPL::Object::Autofill' => sub {
+		my %args = @_;
+		
+		$args{query} = CGI->new($args{query} || {});
+		
+		%args;
+	}
+);
+
 sub CTOR {
 	my ($this,%args) = @_;
 	
-	$this->query(CGI->new($this->query() | {})) unless $this->query;
-	
 	if (lc $this->streamOut eq 'memory') {
 		my $dummy = '';
 		open my $hout, '>:encoding(utf8)', \$dummy or die new IMPL::Exception("Failed to create memory stream",$!);
@@ -165,15 +174,23 @@
 
 =pod
 
+=head1 NAME
+
+C<IMPL::Web::Application::Response> - Ответ веб сервера непосредственно клиенту.
+
 =head1 DESCRIPTION
 
-Ответ сервера на CGI запрос, позволяет сформировать основные свойства заголовка и тело запроса.
+C<[Infrastructure]>
+
+Позволяет сформировать основные свойства заголовка и тело ответа.
+
+Создается объектом C<IMPL::Web::Application::Action> в процессе обработки запроса.
+
+Может использоваться обработчиками C<IMPL::Web::QueryHandler> в процессе выполнения запроса.
 
 Объект позволяет буфферизировать вывод в тело ответа, что позволяет отменить или изменить
-ответ в последний момент.
-
-Свойство C< isHeaderPrinted > можно использовать для определения были ли отправлены какие-нибудь
-данные клиенту. 
+ответ в последний момент. Свойство C< isHeaderPrinted >  используется для определения факта
+отправлки данных клиенту. 
 
 =head1 PROPERTIES
 
@@ -184,27 +201,27 @@
 
 =over
 
-=item C< query >
+=item C< [get] query >
 
 CGI запрос, который используется для вывода данных, заголовка и пр. Существует всегда.
 
-=item C< status >
+=item C< [get,set] status >
 
 Код ошибки HTTP. Например, '200 OK'. По умолчанию не установлен, при отправке клиенту бедт отправлен '200 ОК'.
 
-=item C< contentType >
+=item C< [get,set] contentType >
 
 Тип MIME. По умолчанию не установлен, подразумивается 'text/html'.
 
-=item C< charset >
+=item C< [get,set] charset >
 
 Кодировка, синоним свойства query->charset.
 
-=item C< expires >
+=item C< [get,set] expires >
 
 Определяет время жизни контента, например '+10m'. По умолчанию не задано и не передается.
 
-=item C< cookies >
+=item C< [get,set] cookies >
 
 Хеш массив с cookies, например C< { cart => ['foo','bar'], display => 'list' } >.
 
@@ -216,7 +233,7 @@
 
 =over
 
-=item C< buffered >
+=item C< [get,set] buffered >
 
 C< True > - то тело ответа пишется в буффер и будет отправлено при вызове метода C< Complete >,
 заголовок также будет отправлен после вызова метода C< Complete >. 
@@ -226,15 +243,15 @@
 
 Это свойство можно менять до первого обращения к потоку для записи в тело ответа.
 
-=item C< streamOut >
+=item C< [get] streamOut >
 
 Стандартный вывод CGI приложения.
 
-=item C< streamBody >
+=item C< [get] streamBody >
 
 Поток для записи в тело ответа.
 
-=item C< isHeadPrinted >
+=item C< [get] isHeadPrinted >
 
 Признак того, что заголовок уже был отправлен клиенту.
 
@@ -255,4 +272,9 @@
 
 =back
 
+=head1 REMARKS
+
+Данный объект является автозаполняемым, т.е. все его свойства можно задать через
+именованные параметры конструктора.
+
 =cut
\ No newline at end of file
--- a/_test/Resources/app.xml	Thu Mar 18 17:58:33 2010 +0300
+++ b/_test/Resources/app.xml	Fri Mar 19 20:06:12 2010 +0300
@@ -27,7 +27,7 @@
 	<responseCharset>utf-8</responseCharset>
 	
 	<!-- Actions creation configuration -->
-	<factoryAction type="IMPL::Object::Factory">
+	<actionFactory type="IMPL::Object::Factory">
 		<factory>IMPL::Web::Application::Action</factory>
 		<parameters type='HASH'>
 			<responseFactory type='IMPL::Object::Factory'>
@@ -37,7 +37,7 @@
 				</parameters>
 			</responseFactory>
 		</parameters>
-	</factoryAction>
+	</actionFactory>
 	
 	<!-- Query processing  -->
 	<handlersQuery type="IMPL::Object::List">