Mercurial > pub > Impl
annotate Lib/IMPL/Config.pm @ 175:9057e4b95d10
corrected cloning method
author | sourcer |
---|---|
date | Wed, 05 Oct 2011 00:48:43 +0300 |
parents | b88b7fe60aa3 |
children | b3d91ff7aea9 |
rev | line source |
---|---|
49 | 1 package IMPL::Config; |
2 use strict; | |
3 use warnings; | |
4 | |
165 | 5 use parent qw(IMPL::Object::Accessor IMPL::Object::Serializable IMPL::Object::Autofill); |
49 | 6 |
7 __PACKAGE__->PassThroughArgs; | |
8 | |
170 | 9 use File::Spec(); |
10 | |
49 | 11 use IMPL::Class::Member; |
12 use IMPL::Class::PropertyInfo; | |
13 use IMPL::Exception; | |
14 | |
15 use IMPL::Serialization; | |
16 use IMPL::Serialization::XmlFormatter; | |
17 | |
170 | 18 our $ConfigBase ||= ''; |
60
b0c068da93ac
Lazy activation for the configuration objects (final concept)
wizard
parents:
58
diff
changeset
|
19 |
49 | 20 sub LoadXMLFile { |
21 my ($self,$file) = @_; | |
22 | |
23 my $class = ref $self || $self; | |
24 | |
25 my $serializer = new IMPL::Serializer( | |
26 Formatter => new IMPL::Serialization::XmlFormatter( | |
27 IdentOutput => 1, | |
28 SkipWhitespace => 1 | |
29 ) | |
30 ); | |
31 | |
32 open my $hFile,'<',$file or die new IMPL::Exception("Failed to open file",$file,$!); | |
33 | |
34 my $obj; | |
35 eval { | |
36 $obj = $serializer->Deserialize($hFile); | |
37 }; | |
38 | |
39 if ($@) { | |
40 my $e=$@; | |
41 die new IMPL::Exception("Can't load the configuration file",$file,$e); | |
42 } | |
43 return $obj; | |
44 } | |
45 | |
46 sub SaveXMLFile { | |
47 my ($this,$file) = @_; | |
48 | |
49 my $serializer = new IMPL::Serializer( | |
50 Formatter => new IMPL::Serialization::XmlFormatter( | |
51 IdentOutput => 1, | |
52 SkipWhitespace => 1 | |
53 ) | |
54 ); | |
55 | |
56 open my $hFile,'>',$file or die new IMPL::Exception("Failed to open file",$file,$!); | |
57 | |
58 $serializer->Serialize($hFile, $this); | |
59 } | |
60 | |
61 sub xml { | |
62 my $this = shift; | |
63 my $serializer = new IMPL::Serializer( | |
64 Formatter => new IMPL::Serialization::XmlFormatter( | |
65 IdentOutput => 1, | |
66 SkipWhitespace => 1 | |
67 ) | |
68 ); | |
69 my $str = ''; | |
70 open my $hFile,'>',\$str or die new IMPL::Exception("Failed to open stream",$!); | |
71 | |
72 $serializer->Serialize($hFile, $this); | |
73 | |
74 undef $hFile; | |
75 | |
76 return $str; | |
77 } | |
78 | |
79 sub save { | |
80 my ($this,$ctx) = @_; | |
63
76b878ad6596
Added serialization support for the IMPL::Object::List
wizard
parents:
60
diff
changeset
|
81 |
76b878ad6596
Added serialization support for the IMPL::Object::List
wizard
parents:
60
diff
changeset
|
82 my $val; |
49 | 83 |
63
76b878ad6596
Added serialization support for the IMPL::Object::List
wizard
parents:
60
diff
changeset
|
84 $val = $this->rawGet($_) and $ctx->AddVar($_ => $val) foreach map $_->Name, $this->get_meta( |
76b878ad6596
Added serialization support for the IMPL::Object::List
wizard
parents:
60
diff
changeset
|
85 'IMPL::Class::PropertyInfo', |
76b878ad6596
Added serialization support for the IMPL::Object::List
wizard
parents:
60
diff
changeset
|
86 sub { |
76b878ad6596
Added serialization support for the IMPL::Object::List
wizard
parents:
60
diff
changeset
|
87 $_->Access == IMPL::Class::Member::MOD_PUBLIC and |
76b878ad6596
Added serialization support for the IMPL::Object::List
wizard
parents:
60
diff
changeset
|
88 $_->canGet; |
76b878ad6596
Added serialization support for the IMPL::Object::List
wizard
parents:
60
diff
changeset
|
89 }, |
76b878ad6596
Added serialization support for the IMPL::Object::List
wizard
parents:
60
diff
changeset
|
90 1); |
49 | 91 } |
92 | |
58 | 93 sub spawn { |
170 | 94 my ($this,$file) = @_; |
95 return $this->LoadXMLFile( File::Spec->catfile($ConfigBase,$file) ); | |
58 | 96 } |
97 | |
60
b0c068da93ac
Lazy activation for the configuration objects (final concept)
wizard
parents:
58
diff
changeset
|
98 sub get { |
b0c068da93ac
Lazy activation for the configuration objects (final concept)
wizard
parents:
58
diff
changeset
|
99 my $this = shift; |
b0c068da93ac
Lazy activation for the configuration objects (final concept)
wizard
parents:
58
diff
changeset
|
100 |
b0c068da93ac
Lazy activation for the configuration objects (final concept)
wizard
parents:
58
diff
changeset
|
101 if (@_ == 1) { |
b0c068da93ac
Lazy activation for the configuration objects (final concept)
wizard
parents:
58
diff
changeset
|
102 my $obj = $this->SUPER::get(@_); |
b0c068da93ac
Lazy activation for the configuration objects (final concept)
wizard
parents:
58
diff
changeset
|
103 return UNIVERSAL::isa($obj,'IMPL::Config::Activator') ? $obj->activate : $obj; |
b0c068da93ac
Lazy activation for the configuration objects (final concept)
wizard
parents:
58
diff
changeset
|
104 } else { |
b0c068da93ac
Lazy activation for the configuration objects (final concept)
wizard
parents:
58
diff
changeset
|
105 my @objs = $this->SUPER::get(@_); |
b0c068da93ac
Lazy activation for the configuration objects (final concept)
wizard
parents:
58
diff
changeset
|
106 return map UNIVERSAL::isa($_,'IMPL::Config::Activator') ? $_->activate : $_, @objs ; |
b0c068da93ac
Lazy activation for the configuration objects (final concept)
wizard
parents:
58
diff
changeset
|
107 } |
b0c068da93ac
Lazy activation for the configuration objects (final concept)
wizard
parents:
58
diff
changeset
|
108 } |
b0c068da93ac
Lazy activation for the configuration objects (final concept)
wizard
parents:
58
diff
changeset
|
109 |
b0c068da93ac
Lazy activation for the configuration objects (final concept)
wizard
parents:
58
diff
changeset
|
110 sub rawGet { |
b0c068da93ac
Lazy activation for the configuration objects (final concept)
wizard
parents:
58
diff
changeset
|
111 my $this = shift; |
b0c068da93ac
Lazy activation for the configuration objects (final concept)
wizard
parents:
58
diff
changeset
|
112 return $this->SUPER::get(@_); |
b0c068da93ac
Lazy activation for the configuration objects (final concept)
wizard
parents:
58
diff
changeset
|
113 } |
b0c068da93ac
Lazy activation for the configuration objects (final concept)
wizard
parents:
58
diff
changeset
|
114 |
b0c068da93ac
Lazy activation for the configuration objects (final concept)
wizard
parents:
58
diff
changeset
|
115 sub Exists { |
b0c068da93ac
Lazy activation for the configuration objects (final concept)
wizard
parents:
58
diff
changeset
|
116 $_[0]->SUPER::get($_[1]) ? 1 : 0; |
b0c068da93ac
Lazy activation for the configuration objects (final concept)
wizard
parents:
58
diff
changeset
|
117 } |
b0c068da93ac
Lazy activation for the configuration objects (final concept)
wizard
parents:
58
diff
changeset
|
118 |
49 | 119 1; |
120 __END__ | |
121 | |
122 =pod | |
123 | |
73 | 124 =head1 NAME |
125 | |
126 C<IMPL::Config> - базовый класс для настраиваемого приложения. | |
127 | |
128 =head1 SYNOPSIS | |
49 | 129 |
73 | 130 =begin code |
131 | |
132 # define application | |
133 | |
134 package MyApp; | |
165 | 135 use parent qw(IMPL::Config); |
49 | 136 |
137 use IMPL::Class::Property; | |
138 use IMPL::Config::Class; | |
139 | |
140 BEGIN { | |
141 public property SimpleString => prop_all; | |
60
b0c068da93ac
Lazy activation for the configuration objects (final concept)
wizard
parents:
58
diff
changeset
|
142 public property DataSource => prop_all; |
49 | 143 } |
144 | |
145 sub CTOR { | |
146 my $this = shift; | |
73 | 147 |
60
b0c068da93ac
Lazy activation for the configuration objects (final concept)
wizard
parents:
58
diff
changeset
|
148 $this->DataSource( |
b0c068da93ac
Lazy activation for the configuration objects (final concept)
wizard
parents:
58
diff
changeset
|
149 new IMPL::Config::Activator( |
73 | 150 factory => 'MyDataSource', |
151 parameters=>{ | |
60
b0c068da93ac
Lazy activation for the configuration objects (final concept)
wizard
parents:
58
diff
changeset
|
152 host => 'localhost', |
b0c068da93ac
Lazy activation for the configuration objects (final concept)
wizard
parents:
58
diff
changeset
|
153 user => 'dbuser' |
b0c068da93ac
Lazy activation for the configuration objects (final concept)
wizard
parents:
58
diff
changeset
|
154 } |
b0c068da93ac
Lazy activation for the configuration objects (final concept)
wizard
parents:
58
diff
changeset
|
155 ) |
b0c068da93ac
Lazy activation for the configuration objects (final concept)
wizard
parents:
58
diff
changeset
|
156 ) unless $this->Exists('DataSource'); |
49 | 157 } |
158 | |
73 | 159 # using application object |
58 | 160 |
73 | 161 my $app = spawn MyApp('default.xml'); |
58 | 162 |
163 $app->Run(); | |
164 | |
73 | 165 =end code |
166 | |
167 Ниже приведен пример файла C<default.xml> содержащего настройки приложения | |
168 | |
169 =begin code xml | |
170 | |
171 <app type='MyApp'> | |
172 <SimpleString>The application</SimpleString> | |
173 <DataSource type='IMPL::Config::Activator'> | |
174 <factory>MyDataSourceClass</factory> | |
175 <parameters type='HASH'> | |
176 <host>localhost</host> | |
177 <user>dbuser</user> | |
178 </parameters> | |
179 </DataSource> | |
180 </app> | |
181 | |
182 =end code xml | |
183 | |
49 | 184 =head1 DESCRIPTION |
185 | |
73 | 186 C<[Serializable]> |
187 | |
188 C<[Autofill]> | |
189 | |
165 | 190 C<use parent IMPL::Object::Accessor> |
73 | 191 |
192 Базовый класс для приложений. Использует подход, что приложение | |
193 является объектом, состояние которого предтавляет собой конфигурацию, | |
194 а методы - логику. | |
195 | |
196 Данный класс реализует функционал десериализации (и сериализации) экземпляра | |
197 приложения из XML документа. Для этого используется механизм C<IMPL::Serialization>. | |
198 При этом используются опции C<IMPL::Serialization::XmlFormatter> C<IdentOutput> и | |
199 C<SkipWhitespace> для записи документа в легко читаемом виде. | |
200 | |
201 Поскольку в результате восстановления приложения восстанавливаются все элементы | |
202 из файла конфигурации, то это может потребовать значительных ресурсов для | |
203 создания частей, которые могут никогда не понадобиться. Например, не требуется инициализация | |
204 источника данных для передачи пользователю статических данных, сохраненных на диске. | |
205 | |
206 Для решения этой проблемы используются специальные объекты C<IMPL::Config::Activator>. | |
207 | |
208 Если у приложения описано свойство, в котором хранится C<IMPL::Config::Activator>, то | |
209 при первом обращении к такому свойству, будет создан объект вызовом метода | |
210 C<< IMPL::Config::Activator->activate() >> и возвращен как значение этого свойства. | |
211 Таким образом реализуется прозрачная отложенная активация объектов, что позволяет | |
212 экономить ресурсы. | |
49 | 213 |
214 =head1 MEMBERS | |
215 | |
216 =over | |
217 | |
73 | 218 =item C<[static] LoadXMLFile($fileName) > |
60
b0c068da93ac
Lazy activation for the configuration objects (final concept)
wizard
parents:
58
diff
changeset
|
219 |
73 | 220 Создает из XML файла C<$fileName> экземпляр приложения |
49 | 221 |
73 | 222 =item C<SaveXMLFile($fileName)> |
60
b0c068da93ac
Lazy activation for the configuration objects (final concept)
wizard
parents:
58
diff
changeset
|
223 |
73 | 224 Сохраняет приложение в файл C<$fileName> |
225 | |
226 =item C<[get] xml > | |
49 | 227 |
73 | 228 Сохраняет конфигурацию приложения в XML строку. |
60
b0c068da93ac
Lazy activation for the configuration objects (final concept)
wizard
parents:
58
diff
changeset
|
229 |
73 | 230 =item C<[static,operator] spawn($file)> |
49 | 231 |
73 | 232 Синоним для C<LoadXMLFile>, предполагается использование как оператора. |
60
b0c068da93ac
Lazy activation for the configuration objects (final concept)
wizard
parents:
58
diff
changeset
|
233 |
73 | 234 =item C<rawGet($propname,...)> |
235 | |
236 Метод для получения значений свойств приложения. Данный метод позволяет избежать | |
237 использование активации объектов через C<IMPL::Config::Activator>. | |
60
b0c068da93ac
Lazy activation for the configuration objects (final concept)
wizard
parents:
58
diff
changeset
|
238 |
49 | 239 =back |
240 | |
241 =cut |