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