Mercurial > pub > Impl
annotate Lib/IMPL/Config.pm @ 204:d63f9a92d6d4
+IMPL::Config::Include - simple way to include external config
*IMPL::Web::Handler::TTView - finished template selecting mechanism (not tested)
| author | sergey |
|---|---|
| date | Wed, 02 May 2012 17:42:47 +0400 |
| parents | 4d0e1962161c |
| children | 891c04080658 |
| 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 { |
|
d63f9a92d6d4
+IMPL::Config::Include - simple way to include external config
sergey
parents:
194
diff
changeset
|
125 $AppBase |
|
d63f9a92d6d4
+IMPL::Config::Include - simple way to include external config
sergey
parents:
194
diff
changeset
|
126 } |
|
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 sub ConfigBase { |
|
d63f9a92d6d4
+IMPL::Config::Include - simple way to include external config
sergey
parents:
194
diff
changeset
|
129 $ConfigBase |
|
d63f9a92d6d4
+IMPL::Config::Include - simple way to include external config
sergey
parents:
194
diff
changeset
|
130 } |
|
d63f9a92d6d4
+IMPL::Config::Include - simple way to include external config
sergey
parents:
194
diff
changeset
|
131 |
| 49 | 132 1; |
| 133 __END__ | |
| 134 | |
| 135 =pod | |
| 136 | |
| 73 | 137 =head1 NAME |
| 138 | |
| 180 | 139 C<IMPL::Config> - базовый класс для настраиваемого приложения. |
| 73 | 140 |
| 141 =head1 SYNOPSIS | |
| 49 | 142 |
| 73 | 143 =begin code |
| 144 | |
| 145 # define application | |
| 146 | |
| 147 package MyApp; | |
| 165 | 148 use parent qw(IMPL::Config); |
| 49 | 149 |
| 150 use IMPL::Class::Property; | |
| 151 use IMPL::Config::Class; | |
| 152 | |
| 153 BEGIN { | |
| 154 public property SimpleString => prop_all; | |
|
60
b0c068da93ac
Lazy activation for the configuration objects (final concept)
wizard
parents:
58
diff
changeset
|
155 public property DataSource => prop_all; |
| 49 | 156 } |
| 157 | |
| 158 sub CTOR { | |
| 159 my $this = shift; | |
| 73 | 160 |
|
60
b0c068da93ac
Lazy activation for the configuration objects (final concept)
wizard
parents:
58
diff
changeset
|
161 $this->DataSource( |
| 194 | 162 new IMPL::Config::Activator( |
| 163 factory => 'MyDataSource', | |
| 164 parameters=>{ | |
| 165 host => 'localhost', | |
| 166 user => 'dbuser' | |
| 167 } | |
| 168 ) | |
|
60
b0c068da93ac
Lazy activation for the configuration objects (final concept)
wizard
parents:
58
diff
changeset
|
169 ) unless $this->Exists('DataSource'); |
| 49 | 170 } |
| 171 | |
| 73 | 172 # using application object |
| 58 | 173 |
| 73 | 174 my $app = spawn MyApp('default.xml'); |
| 58 | 175 |
| 176 $app->Run(); | |
| 177 | |
| 73 | 178 =end code |
| 179 | |
| 180 | 180 Ниже приведен пример файла C<default.xml> содержащего настройки приложения |
| 73 | 181 |
| 182 =begin code xml | |
| 183 | |
| 184 <app type='MyApp'> | |
| 194 | 185 <SimpleString>The application</SimpleString> |
| 186 <DataSource type='IMPL::Config::Activator'> | |
| 187 <factory>MyDataSourceClass</factory> | |
| 188 <parameters type='HASH'> | |
| 189 <host>localhost</host> | |
| 190 <user>dbuser</user> | |
| 191 </parameters> | |
| 192 </DataSource> | |
| 73 | 193 </app> |
| 194 | |
| 195 =end code xml | |
| 196 | |
| 49 | 197 =head1 DESCRIPTION |
| 198 | |
| 73 | 199 C<[Serializable]> |
| 200 | |
| 201 C<[Autofill]> | |
| 202 | |
| 165 | 203 C<use parent IMPL::Object::Accessor> |
| 73 | 204 |
| 180 | 205 Базовый класс для приложений. Использует подход, что приложение |
| 206 является объектом, состояние которого предтавляет собой конфигурацию, | |
| 207 а методы - логику. | |
| 73 | 208 |
| 180 | 209 Данный класс реализует функционал десериализации (и сериализации) экземпляра |
| 210 приложения из XML документа. Для этого используется механизм C<IMPL::Serialization>. | |
| 211 При этом используются опции C<IMPL::Serialization::XmlFormatter> C<IdentOutput> и | |
| 212 C<SkipWhitespace> для записи документа в легко читаемом виде. | |
| 73 | 213 |
| 180 | 214 Поскольку в результате восстановления приложения восстанавливаются все элементы |
| 215 из файла конфигурации, то это может потребовать значительных ресурсов для | |
| 216 создания частей, которые могут никогда не понадобиться. Например, не требуется инициализация | |
| 217 источника данных для передачи пользователю статических данных, сохраненных на диске. | |
| 73 | 218 |
| 180 | 219 Для решения этой проблемы используются специальные объекты C<IMPL::Config::Activator>. |
| 73 | 220 |
| 180 | 221 Если у приложения описано свойство, в котором хранится C<IMPL::Config::Activator>, то |
| 222 при первом обращении к такому свойству, будет создан объект вызовом метода | |
| 223 C<< IMPL::Config::Activator->activate() >> и возвращен как значение этого свойства. | |
| 224 Таким образом реализуется прозрачная отложенная активация объектов, что позволяет | |
| 225 экономить ресурсы. | |
| 49 | 226 |
| 227 =head1 MEMBERS | |
| 228 | |
| 229 =over | |
| 230 | |
| 73 | 231 =item C<[static] LoadXMLFile($fileName) > |
|
60
b0c068da93ac
Lazy activation for the configuration objects (final concept)
wizard
parents:
58
diff
changeset
|
232 |
| 180 | 233 Создает из XML файла C<$fileName> экземпляр приложения |
| 49 | 234 |
| 73 | 235 =item C<SaveXMLFile($fileName)> |
|
60
b0c068da93ac
Lazy activation for the configuration objects (final concept)
wizard
parents:
58
diff
changeset
|
236 |
| 180 | 237 Сохраняет приложение в файл C<$fileName> |
| 73 | 238 |
| 239 =item C<[get] xml > | |
| 49 | 240 |
| 180 | 241 Сохраняет конфигурацию приложения в XML строку. |
|
60
b0c068da93ac
Lazy activation for the configuration objects (final concept)
wizard
parents:
58
diff
changeset
|
242 |
| 73 | 243 =item C<[static,operator] spawn($file)> |
| 49 | 244 |
| 180 | 245 Синоним для C<LoadXMLFile>, предполагается использование как оператора. |
|
60
b0c068da93ac
Lazy activation for the configuration objects (final concept)
wizard
parents:
58
diff
changeset
|
246 |
| 73 | 247 =item C<rawGet($propname,...)> |
| 248 | |
| 180 | 249 Метод для получения значений свойств приложения. Данный метод позволяет избежать |
| 250 использование активации объектов через C<IMPL::Config::Activator>. | |
|
60
b0c068da93ac
Lazy activation for the configuration objects (final concept)
wizard
parents:
58
diff
changeset
|
251 |
| 49 | 252 =back |
| 253 | |
| 254 =cut |
