Mercurial > pub > Impl
annotate Lib/IMPL/Config.pm @ 245:7c517134c42f
Added Unsupported media type Web exception
corrected resourceLocation setting in the resource
Implemented localizable resources for text messages
fixed TT view scopings, INIT block in controls now sets globals correctly.
author | sergey |
---|---|
date | Mon, 29 Oct 2012 03:15:22 +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 |