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