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