persistence.doxy
1 /*!
2 \page persistence Persistence
3 <div class="has-toc"></div>
4 
5 # Persistence # {#pers_main}
6 
7 Persistence refers to that part of the domain model, which we could call the data model.
8 
9 ## Data model ## {#pers_datamodel}
10 
11 The data model consists of domain classes whose instances are saved in the storage.
12 The following steps need to be accomplished to make domain class instances
13 persistent.
14 
15 - Definition and creation of the database tables, if using a database storage.
16 - Implementation of the \link wcmf::lib::persistence::PersistenceMapper `PersistenceMapper`\endlink
17  classes, which map the domain classes to these tables, or anything else that is used as storage.
18 - Implementation of the domain classes as subclasses of \link wcmf::lib::model::Node `Node`\endlink.
19 - Configuration of the persistence layer.
20 
21 @note If you are using the generator to create the application from a model
22 (see \ref model), all necessary code will be generated automatically.
23 
24 ### Database tables ### {#pers_tables}
25 
26 Still the most common storage for web applications is a _SQL_ database (e.g.
27 [MySQL](http://www.mysql.com/)). It is also wCMF's default storage. Although not
28 strictly necessary it is recommended to use one database table for each persistent
29 class, where each class property maps to one table column and each row stores one
30 instance. The object identity is stored in the primary key column, which is named
31 _id_ by default.
32 
33 @note wCMF uses a table called `DBSequence` for retrieving the next id value used for
34 insertion, since _autoincrement_ columns are not supported on all database servers.
35 
36 #### Primary keys #### {#pers_id}
37 
38 Primary keys are used to clearly identify an object in the database. They can consist
39 of one (_simple_) or more (_compound_) columns. The default name for a primary
40 key column is _id_. wCMF stores the primary key of an object together with it's type
41 name in an \link wcmf::lib::persistence::ObjectId `ObjectId`\endlink instance.
42 
43 #### Relations #### {#pers_relations}
44 
45 The following two relations types must be considered, when modeling the data
46 tables:
47 
48 - __One-To-Many__ relations are realized by adding a foreign key column to the
49 child table (_many_-side), which points to the parent table (_one_-side). This
50 column is named _fk_ _ + parent table name + _ _id_ by default (e.g. _fk_author_id_).
51 
52 - __Many-To-Many__ relations between two domain classes, are established by defining
53 a connection table. This table contains two primary keys, which point to the two
54 connected tables.
55 
56 ### Persistence Mappers ### {#pers_mappers}
57 
58 wCMF uses persistence mapper classes to communicate between the application and
59 the persistent storage (see \ref arch_main). These classes implement the
60 \link wcmf::lib::persistence::PersistenceMapper `PersistenceMapper`\endlink interface,
61 which defines methods for all persistence actions. By using this pattern wCMF
62 does not make any assumptions about the actual storage, which can be flat files,
63 a database, a remote service or anything else a mapper is able to handle. This approach
64 also makes it easy to connect an existing storage to a newly created wCMF application.
65 
66 To simplify the implementation of mapper classes, wCMF already contains
67 a class hierarchy for a common mapping approach, which maps each concrete class
68 to one database table ([Concrete Table Inheritance]
69 (http://martinfowler.com/eaaCatalog/concreteTableInheritance.html)). In this
70 hierarchy \link wcmf::lib::model::mapper::impl::AbstractRDBMapper `AbstractRDBMapper`\endlink handles
71 the communication with the relational database, while
72 \link wcmf::lib::model::mapper::NodeUnifiedRDBMapper `NodeUnifiedRDBMapper`\endlink
73 defines the actual mapping rules. Application developers simply need to implement
74 one subclass of \link wcmf::lib::model::mapper::NodeUnifiedRDBMapper `NodeUnifiedRDBMapper`\endlink
75 for each persistent domain class, which declares the mapping of the attributes and
76 relations of that class.
77 
78 @note All mapper classes, that are created by the generator are
79 \link wcmf::lib::model::mapper::NodeUnifiedRDBMapper `NodeUnifiedRDBMapper`\endlink
80 subclasses.
81 
82 ### Domain Classes ### {#pers_classes}
83 
84 Domain class instances hold the data that are used in the application and persisted
85 in the storage.
86 
87 Persistent domain classes either inherit from
88 - \link wcmf::lib::persistence::PersistentObject `PersistentObject`\endlink, which
89 is a container with value getter and setter methods, or from
90 - \link wcmf::lib::model::Node `Node`\endlink, which adds methods for managing
91 relations.
92 
93 These two classes are completely generic, the actual identity of the domain class -
94 that is the _properties_ and the _relations_ - are defined by the related
95 \link wcmf::lib::persistence::PersistenceMapper `PersistenceMapper`\endlink.
96 
97 So if no additional domain logic is required in the domain class, it would be
98 sufficient to use \link wcmf::lib::model::Node `Node`\endlink as domain class.
99 But in many cases you will want to execute custom code for \ref pers_hooks,
100 \ref pers_validation and other business logic and therefor create a custom subclass of
101 \link wcmf::lib::model::Node `Node`\endlink.
102 
103 @note All domain classes, that are created by the generator are
104 \link wcmf::lib::model::Node `Node`\endlink subclasses.
105 
106 #### Persistence Hooks #### {#pers_hooks}
107 
108 Persistence hooks are methods that are called at certain points of the lifecycle of
109 an instance. The default implementation of these methods is empty - in fact their
110 sole purpose is to be overwritten in subclasses on order to implement special
111 functionality that should be executed at those points.
112 \link wcmf::lib::persistence::PersistentObject `PersistentObject`\endlink defines
113 the following persistence hooks:
114 
115 - \link wcmf::lib::persistence::PersistentObject::afterCreate `afterCreate`\endlink
116 - \link wcmf::lib::persistence::PersistentObject::beforeInsert `beforeInsert`\endlink
117 - \link wcmf::lib::persistence::PersistentObject::afterInsert `afterInsert`\endlink
118 - \link wcmf::lib::persistence::PersistentObject::afterLoad `afterLoad`\endlink
119 - \link wcmf::lib::persistence::PersistentObject::beforeUpdate `beforeUpdate`\endlink
120 - \link wcmf::lib::persistence::PersistentObject::afterUpdate `afterUpdate`\endlink
121 - \link wcmf::lib::persistence::PersistentObject::beforeDelete `beforeDelete`\endlink
122 - \link wcmf::lib::persistence::PersistentObject::afterDelete `afterDelete`\endlink
123 
124 #### Values, Properties and Tags #### {#pers_values}
125 
126 The following terms are important to know when working with wCMF's domain classes:
127 
128 - __Values__ are the persistent attributes of a domain class. You can think
129  of them as class members. Values are accessed using the methods
130  \link wcmf::lib::persistence::PersistentObject::getValue `getValue`\endlink
131  and \link wcmf::lib::persistence::PersistentObject::setValue `setValue`\endlink.
132 - __Properties__ apply to domain classes and domain class values. They describe
133  static features like the `displayValues` of the class or the `inputType`
134  of a value. Properties are defined in the model as _tags_ (see \ref model_profile)
135  and are accessed using the methods
136  \link wcmf::lib::persistence::PersistentObject::getProperty `getProperty`\endlink/
137  \link wcmf::lib::persistence::PersistentObject::setProperty `setProperty`\endlink
138  and
139  \link wcmf::lib::persistence::PersistentObject::getValueProperty `getValueProperty`\endlink/
140  \link wcmf::lib::persistence::PersistentObject::setValueProperty `setValueProperty`\endlink
141 - __Tags__ are a special property used on values to group them by certain
142  aspects. For example the edit forms in the \ref app "default application" only
143  display domain class values that are tagged with `DATATYPE_ATTRIBUTE` and only those
144  attributes are editable in the translation form that are tagged with `TRANSLATABLE`.
145  The `SEARCHABLE` tag defines that an entity type should be included in the search index.
146  Tags are defined in the model using the _tag_ `app_data_type` (see \ref model_chivalue).
147 
148 ### Configuration ### {#pers_config}
149 
150 Entry point of configuring the persistence layer is
151 \link wcmf::lib::persistence::PersistenceFacade `PersistenceFacade`\endlink
152 (see \ref pers_usage).
153 The configuration mainly tells the facade which mapper classes are responsible
154 for which domain classes. This assignment is defined in the `TypeMapping`
155 configuration section. The following example shows the appropriate entries
156 for the `Author` domain class:
157 
158 <div class="ini">
159 ```
160 [PersistenceFacade]
161 __class = wcmf\lib\persistence\impl\DefaultPersistenceFacade
162 mappers = $typeMapping
163 logging = false
164 logStrategy = $auditingLogStragegy
165 
166 [AuditingLogStragegy]
167 __class = wcmf\lib\persistence\output\impl\AuditingOutputStrategy
168 
169 [TypeMapping]
170 app.src.model.Author = $app_src_model_AuthorRDBMapper
171 
172 [app_src_model_AuthorRDBMapper]
173 __class = app\src\model\AuthorRDBMapper
174 connectionParams = $database
175 
176 [Database]
177 dbType = sqlite
178 dbHostName = 127.0.0.1
179 dbName = app/test-db.sq3
180 dbUserName =
181 dbPassword =
182 dbCharSet = utf8
183 ```
184 </div>
185 
186 ## Usage ## {#pers_usage}
187 
188 \link wcmf::lib::persistence::PersistenceFacade `PersistenceFacade`\endlink is
189 the main entry point to the persistence layer. It is used to create and retrieve
190 \link wcmf::lib::persistence::PersistentObject `PersistentObject`\endlink instances.
191 The following sections show some basic examples for using the persistence layer.
192 
193 ### Loading objects ### {#pers_load}
194 
195 To load a __single object__, the
196 \link wcmf::lib::persistence::PersistenceFacade::load `PersistenceFacade::load`\endlink
197 method is used:
198 
199 <div class="php">
200 ```
201 $oid = new ObjectId('Author', 1);
202 
203 // load the Author instance with id 1
204 $author = ObjectFactory::getInstance('persistenceFacade')->load($oid);
205 
206 // PersistenceFacade will return null, if an instance does not exist
207 if($author == null) {
208  echo("An Author with object id ".$oid." does not exist.");
209 }
210 ```
211 </div>
212 
213 In the example the `Author` instance with id _1_ is loaded.
214 
215 A __list of objects__ is loaded using the
216 \link wcmf::lib::persistence::PersistenceFacade::loadObjects `PersistenceFacade::loadObjects`\endlink
217 method:
218 
219 <div class="php">
220 ```
221 // load all Author instances
222 $authors = ObjectFactory::getInstance('persistenceFacade')->loadObjects('Author');
223 ```
224 </div>
225 
226 This \link wcmf::lib::persistence::PersistenceFacade::loadObjects `PersistenceFacade::loadObjects`\endlink
227 method provides several parameters that allow to specify which instances should
228 be loaded and how the list should be ordered. The next sections explain these
229 parameters.
230 
231 #### Eager relation loading #### {#pers_builddepth}
232 
233 When loading objects we generally distinguish between __eager__ and __lazy__ loading
234 (see [Lazy loading](http://en.wikipedia.org/wiki/Lazy_loading)).
235 By default \link wcmf::lib::persistence::PersistenceFacade `PersistenceFacade`\endlink
236 performs _lazy loading_ by using _virtual proxies_ (instances of
237 \link wcmf::lib::persistence::PersistentObjectProxy `PersistentObjectProxy`\endlink).
238 That means that related objects are retrieved from the store, only when they are
239 actually accessed. To perform _eager loading_, a
240 \link wcmf::lib::persistence::BuildDepth `BuildDepth`\endlink
241 value is passed in the method calls:
242 
243 <div class="php">
244 ```
245 $oid = new ObjectId('Author', 1);
246 
247 // load the Author instance with id 1 together with all related objects
248 $author = ObjectFactory::getInstance('persistenceFacade')->load($oid, BuildDepth::INFINITE);
249 ```
250 </div>
251 
252 In this example the `Author` instance with id _1_ is loaded together with all related
253 objects recursively.
254 
255 Instead of a \link wcmf::lib::persistence::BuildDepth `BuildDepth`\endlink
256 value, an integer number could be passed indicating the depth of relations to load.
257 The following image illustrates the _build depth_ parameter for a simple model.
258 
259 \image html builddepth.png "Build depth"
260 
261 If using a build depth value of _1_ the `Author` instance _Author A_ will be loaded together
262 with it's related `Articles` instances (_Article A_, _Article B_). A value of _2_ will also load
263 the `Chapter` instances (_Chapter A1_, _Chapter A2_). The default value is
264 \link wcmf::lib::persistence::BuildDepth::SINGLE `BuildDepth::SINGLE`\endlink,
265 which means that only the _Author A_ instance is loaded. In the above illustration
266 the value of _2_ is equal to passing
267 \link wcmf::lib::persistence::BuildDepth::INFINITE `BuildDepth::INFINITE`\endlink.
268 
269 #### Sorting #### {#pers_sorting}
270 
271 When loading a list of objects, the default order of the
272 \link wcmf::lib::persistence::PersistenceMapper `PersistenceMapper`\endlink
273 class is used for sorting. This default order is defined in the model (_orderby_ tag
274 of _ChiNode_, see \ref model_chinode). Besides this, all loading methods (e.g.
275 \link wcmf::lib::persistence::PersistenceFacade::loadObjects `PersistenceFacade::loadObjects`\endlink)
276 accept an `orderby` parameter for explicitly setting a different order.
277 
278 A list of already loaded \link wcmf::lib::model::Node `Node`\endlink
279 instances is sorted by using \link wcmf::lib::model::NodeComparator `NodeComparator`\endlink
280 in the following way:
281 
282 <div class="php">
283 ```
284 $nodeList = [...];
285 
286 // set up a comparator for node type and created date
287 $sortCriteria = [
288  NodeComparator::ATTRIB_TYPE => NodeComparator::SORTTYPE_ASC,
289  'created' => NodeComparator::SORTTYPE_DESC
290 ];
291 $comparator = new NodeComparator($sortCriteria);
292 
293 // sort node list
294 usort($nodeList, [$comparator, 'compare']);
295 ```
296 </div>
297 
298 #### Pagination #### {#pers_pagination}
299 
300 A common pattern for reducing the response time of an application when displaying large lists
301 of objects is [pagination](http://en.wikipedia.org/wiki/Pagination#Pagination_in_web_content).
302 This technique splits the list into smaller parts (_pages_) that are displayed
303 one by one. In wCMF the class \link wcmf::lib::persistence::PagingInfo `PagingInfo`\endlink
304 implements the concept.
305 
306 The following code shows how to load _25_ `Author` instances starting from
307 position _50_:
308 
309 <div class="php">
310 ```
311 // setup paging
312 $pagingInfo = new PagingInfo(25);
313 $pagingInfo->setOffset(50);
314 
315 // load Author instances
316 $authors = ObjectFactory::getInstance('persistenceFacade')->loadObjects('Author', BuildDepth::SINGLE, null, null, $pagingInfo);
317 ```
318 </div>
319 
320 Pagination is also possible over __multiple entity types__:
321 
322 <div class="php">
323 ```
324 // setup paging
325 $pagingInfo = new PagingInfo(25);
326 $pagingInfo->setOffset(50);
327 
328 // load Author and Publisher instances ordered by creation date
329 $types = ['Author', 'Publisher'];
330 $order = ['created'];
331 $objects = ObjectFactory::getInstance('persistenceFacade')->loadObjects($types, BuildDepth::SINGLE, null, $order, $pagingInfo);
332 ```
333 </div>
334 
335 ### Searching objects ### {#pers_search}
336 
337 To search objects in the store the
338 \link wcmf::lib::persistence::PersistenceFacade::loadObjects `PersistenceFacade::loadObjects`\endlink
339 method is used. It allows to set the conditions that loaded objects should match.
340 
341 <div class="php">
342 ```
343 $criteria = [
344  new Criteria("Article", "title", "LIKE", "A%"),
345  new Criteria("Article", "year", ">=", "2014")
346 ]
347 
348 // load all Article instances with titles starting with A and release date 2014 or later
349 $articles = ObjectFactory::getInstance('persistenceFacade')->loadObjects("Article", BuildDepth::SINGLE, $criteria);
350 ```
351 </div>
352 
353 In this example all `Article` instances with titles starting with _A_ and release date
354 _2014 or later_ are loaded.
355 
356 #### Null values #### {#pers_search_null}
357 
358 Null values are matched/not matched using the following criteria:
359 
360 <div class="php">
361 ```
362 new Criteria("Article", "title", "=", null); // translates to Article.title IS NULL
363 new Criteria("Article", "title", "!=", null); // translates to Article.title IS NOT NULL
364 ```
365 </div>
366 
367 #### Object queries #### {#pers_search_object_queries}
368 
369 More complex use cases are supported by the \link wcmf::lib::model::ObjectQuery `ObjectQuery`\endlink
370 class. For example it allows to set search constraints on connected objects as
371 shown in the following example:
372 
373 <div class="php">
374 ```
375 // create a Author query
376 $query = new ObjectQuery('Author');
377 
378 // query part: Author.name LIKE 'A%' OR Author.name LIKE 'B%'
379 $authorTpl1 = $query->getObjectTemplate("Author");
380 $authorTpl1->setValue("name", Criteria::asValue("LIKE", "A%"));
381 $authorTpl2 = $query->getObjectTemplate("Author", null, Criteria::OPERATOR_OR);
382 $authorTpl2->setValue("name", Criteria::asValue("LIKE", "B%"));
383 
384 // query part: Article.created >= '2004-01-01' AND Article.created < '2005-01-01'
385 $articleTpl1 = $query->getObjectTemplate("Article");
386 $articleTpl1->setValue("created", Criteria::asValue(">=", "2004-01-01"));
387 $articleTpl2 = $query->getObjectTemplate("Article");
388 $articleTpl2->setValue("created", Criteria::asValue("<", "2005-01-01"));
389 
390 // connect query nodes
391 $authorTpl1->addNode($articleTpl1);
392 $authorTpl1->addNode($articleTpl2);
393 
394 // load result
395 $authorList = $query->execute(BuildDepth::SINGLE);
396 ```
397 </div>
398 
399 In this example all `Author` instances are loaded which have names starting with
400 _A_ or _B_ and which have `Article` instances connected that are created in the
401 year _2014_.
402 
403 It is possible to combine several object queries to apply pagination over __multiple entity types__
404 using the \link wcmf::lib::persistence::UnionQuery `UnionQuery`\endlink class:
405 
406 <div class="php">
407 ```
408 // create a Author query
409 $authorQuery = new ObjectQuery('Author');
410 // ... define query
411 
412 // create a Publisher query
413 $publisherQuery = new ObjectQuery('Publisher');
414 // ... define query
415 
416 // setup paging
417 $pagingInfo = new PagingInfo(25);
418 $pagingInfo->setOffset(50);
419 
420 // load Author and Publisher instances ordered by creation date
421 $queryProvider = new ObjectQueryUnionQueryProvider([$authorQuery, $publisherQuery]);
422 $order = ['created'];
423 $objects = UnionQuery::execute($queryProvider, BuildDepth::SINGLE, $order, $pagingInfo);
424 ```
425 </div>
426 
427 Besides this, wCMF integrates the
428 [Lucene](http://framework.zend.com/manual/1.12/en/zend.search.lucene.overview.html)
429 search engine in the class \link wcmf::lib::search::impl::LuceneSearch `LuceneSearch`\endlink.
430 
431 ### Iterating objects ### {#pers_iter}
432 
433 wCMF provides several [iterator](http://php.net/manual/en/class.iterator.php)
434 classes for traversing objects and values.
435 
436 \link wcmf::lib::model::NodeIterator `NodeIterator`\endlink allows to traverse
437 object graphs starting from a root \link wcmf::lib::model::Node `Node`\endlink.
438 The algorithm used is [depth-first search](http://en.wikipedia.org/wiki/Depth-first_search).
439 
440 <div class="php">
441 ```
442 // traverse $root and all descendents
443 $it = new NodeIterator($root);
444 foreach($it as $oid => $obj) {
445  echo "current object id: $oid";
446  echo "current object: $obj";
447 }
448 ```
449 </div>
450 
451 \link wcmf::lib::model::NodeValueIterator `NodeValueIterator`\endlink is used
452 to iterate over all persistent values of a \link wcmf::lib::model::Node `Node`\endlink.
453 
454 <div class="php">
455 ```
456 // traverse all values of $object
457 $it = new NodeValueIterator($object);
458 for($it->rewind(); $it->valid(); $it->next()) {
459  echo "current object: ".$it->currentNode();
460  echo "current attribute name: ".$it->key();
461  echo "current attribute value: ".$it->current();
462 }
463 ```
464 </div>
465 
466 \link wcmf::lib::model::PersistentIterator `PersistentIterator`\endlink allows
467 to traverse object graphs as well, but it's state could be persisted to split the
468 iteration of large lists into smaller parts.
469 
470 <div class="php">
471 ```
472 // traverse 10 nodes starting from $oid
473 $counter = 0;
474 $it = new PersistentIterator($oid);
475 while($it->valid() && $counter < 10) {
476  echo "current object: ".$it->currentNode();
477  $it->next();
478  $counter++;
479 }
480 
481 // save iterator state in the session
482 $iterId = $it->save();
483 
484 // load the iterator state later and traverse the remaining nodes
485 $it = PersistentIterator::load($iterId);
486 while($it->valid()) {
487  echo "current object: ".$it->currentNode();
488  $it->next();
489 }
490 ```
491 </div>
492 
493 ### Creating / Modifying objects ### {#pers_create_modify}
494 
495 Domain class instances are created by calling the
496 \link wcmf::lib::persistence::PersistenceFacade::create `PersistenceFacade::create`\endlink
497 method or simply the class constructor, where the first approach is preferred
498 over the second because it also sets the default values on attributes.
499 
500 Changes on instances are persisted automatically, when the current transaction
501 is committed (see \ref pers_tx). Objects are removed from the store by calling the
502 \link wcmf::lib::persistence::PersistentObject::delete `PersistentObject::delete`\endlink
503 method.
504 
505 <div class="php">
506 ```
507 $persistenceFacade = ObjectFactory::getInstance('persistenceFacade');
508 $tx = $persistenceFacade->getTransaction();
509 
510 // create an Author instance
511 $author = $persistenceFacade->create('Author');
512 $author->setValue('name', 'Author A');
513 
514 // create an Article instance and attach it to the author
515 $article = $persistenceFacade->create('Article');
516 $article->setValue('title', 'Article A');
517 $author->addNode($article);
518 
519 // save everything
520 $tx->commit();
521 
522 // get the author's object id
523 $oid = $author->getOID()
524 
525 // delete the author instance
526 $author = $persistenceFacade->load($oid);
527 $author->delete();
528 
529 // save everything
530 $tx->commit();
531 ```
532 </div>
533 
534 ## Validation ## {#pers_validation}
535 
536 Before persisting objects, their content has to be validated according to the
537 application requirements. Validation is handled in
538 \link wcmf::lib::persistence::PersistentObject::validateValue `PersistentObject::validateValue`\endlink
539 (for a single attribute) or
540 \link wcmf::lib::persistence::PersistentObject::validateValues `PersistentObject::validateValues`\endlink
541 (for the complete instance). These methods are called when values are changed via
542 \link wcmf::lib::persistence::PersistentObject::setValue `PersistentObject::setValue`\endlink
543 or right before persisting the object in
544 \link wcmf::lib::persistence::impl::AbstractMapper::save `AbstractMapper::save`\endlink.
545 Both validation methods throw a
546 \link wcmf::lib::persistence::ValidationException `ValidationException`\endlink, if
547 validation fails.
548 
549 ### Validation types ### {#pers_validation_types}
550 
551 The actual validation is delegated to the
552 \link wcmf::lib::validation::Validator::validate `Validator::validate`\endlink
553 method, which gets a __validation description string__ passed. This string defines
554 a single \link wcmf::lib::validation::ValidateType `ValidateType`\endlink or a
555 combination of those. The
556 \link wcmf::lib::validation::ValidateType::validate `ValidateType::validate`\endlink
557 method accepts an associative array of configuration options, that is encoded into
558 a JSON string when being used in the validation description string. An additional
559 __validation context__ might be passed to the method (e.g. the entity instance and
560 the currently validated entity attribute), when validation entity values.
561 
562 To define which validation should be applied to a domain class attribute, the
563 _tag_ `restrictions_match` is used in the model (see \ref model_chivalue).
564 
565 Currently the following validation types exist (the examples show their usage
566 in a validation description string):
567 
568 \link wcmf::lib::validation::impl::Date `Date`\endlink
569 validates against a date format, e.g.
570 
571 <div class="php">
572 ```
573 // validate against the default date format ('Y-m-d')
574 date
575 
576 // validate against a custom date format ('Y-m-d')
577 date:{"format":"j-M-Y"}
578 ```
579 </div>
580 
581 \link wcmf::lib::validation::impl::Filter `Filter`\endlink
582 validates against a PHP filter (see [filter_var](http://php.net/manual/en/function.filter-var.php)), e.g.
583 
584 <div class="php">
585 ```
586 // FILTER_VALIDATE_INT with min_range option and FILTER_FLAG_ALLOW_HEX flag
587 filter:{"type":"int","options":{"options":{"min_range":0},"flags":2}}
588 ```
589 </div>
590 
591 \link wcmf::lib::validation::impl::Image `Image`\endlink
592 checks _width_ and _height_ of the referred image file e.g.
593 
594 <div class="php">
595 ```
596 // image width exactly 200px, height less than 100px
597 image:{"width":[200,1],"height":[100,0]}
598 ```
599 </div>
600 
601 \link wcmf::lib::validation::impl::RegExp `RegExp`\endlink
602 validates against a regular expression (see [preg_match](http://php.net/manual/en/function.preg-match.php)) e.g.
603 
604 <div class="php">
605 ```
606 // integer or empty
607 regexp:{"pattern":"/^[0-9]*$/"}
608 ```
609 </div>
610 
611 \link wcmf::lib::validation::impl::Required `Required`\endlink
612 checks if the value is not empty e.g.
613 
614 <div class="php">
615 ```
616 required
617 ```
618 </div>
619 
620 \link wcmf::lib::validation::impl::Unique `Unique`\endlink
621 checks if the value is unique regarding the given entity attribute e.g.
622 
623 <div class="php">
624 ```
625 // explicitly define Keyword.name as being unique ...
626 unique:{"type":"Keyword","value":"name"}
627 
628 // ... or implicitly when used in the entity validation context of the Keyword.name
629 unique
630 ```
631 </div>
632 
633 \note The validation type is derived from the part of the configuration string,
634 that precedes the first colon.
635 
636 Custom validation types can be added in the configuration. For example
637 after adding `myValidator` (implemented in `MyValidator` class):
638 
639 <div class="ini">
640 ```
641 [Validators]
642 regexp = $regexpValidator
643 filter = $filterValidator
644 image = $imageValidator
645 myValidator = $myValidator
646 
647 [MyValidator]
648 __class = path\to\MyValidator
649 ```
650 </div>
651 
652 it is used in the following way:
653 
654 <div class="php">
655 ```
656 myValidator:custom_configuration_string_passed_by_MyValidator
657 ```
658 </div>
659 
660 ### Complex validation ### {#pers_validation_custom}
661 
662 The described validation types only operate on one attribute. If more complex
663 validation is required, e.g. if dependencies between several attributes exist, the method
664 \link wcmf::lib::persistence::PersistentObject::validateValue `PersistentObject::validateValue`\endlink
665 could be overriden in the appropriate domain class.
666 
667 ## Concurrency ## {#pers_concurrency}
668 
669 When two or more users try to access the same object at the same time problems
670 like _lost updates_ might occur. These issues are avoided by _concurrency control_
671 mechanisms, typically _object locking_.
672 
673 ### Locking ### {#pers_locking}
674 
675 wCMF provides two locking strategies:
676 
677 - __Pessimistic locking__: An explicit lock is obtained by one user, that blocks
678  write access to the object for other users until the lock is released.
679 - __Optimistic locking__: A copy of the initial object data is stored for each user
680  and checked against later, when the user tries to store the object. The operation
681  fails, if another user has updated the object data in the meantime.
682 
683 For more detailed information see
684 [database locks](http://en.wikipedia.org/wiki/Lock_%28computer_science%29#Database_locks).
685 
686 \link wcmf::lib::persistence::concurrency::Lock `Lock`\endlink instances are
687 obtained by calling
688 \link wcmf::lib::persistence::concurrency::ConcurrencyManager::aquireLock `ConcurrencyManager::aquireLock`\endlink
689 and released using
690 \link wcmf::lib::persistence::concurrency::ConcurrencyManager::releaseLock `ConcurrencyManager::releaseLock`\endlink
691 like shown in the following example:
692 
693 <div class="php">
694 ```
695 // object id of the object to lock
696 $oid = new ObjectId('Author', 1);
697 
698 // aquire an optimistic lock for the object
699 $lockType = Lock::TYPE_OPTIMISTIC;
700 $concurrencyManager = ObjectFactory::getInstance('concurrencyManager');
701 try {
702  $concurrencyManager->aquireLock($oid, $lockType);
703 }
704 catch(PessimisticLockException $ex) {
705  // another user already holds a lock on this object
706  echo $ex->getMessage();
707 }
708 
709 // release lock later
710 $concurrencyManager->releaseLock($oid, $lockType);
711 ```
712 </div>
713 
714 The actual storage and retrieval of
715 \link wcmf::lib::persistence::concurrency::Lock `Lock`\endlink instances is
716 delegated to
717 \link wcmf::lib::persistence::concurrency::LockHandler `LockHandler`\endlink.
718 The following lines show the concurrency configuration in the \ref app "default application":
719 
720 <div class="ini">
721 ```
722 [ConcurrencyManager]
723 __class = wcmf\lib\persistence\concurrency\impl\DefaultConcurrencyManager
724 lockHandler = $lockHandler
725 
726 [LockHandler]
727 __class = wcmf\lib\persistence\concurrency\impl\DefaultLockHandler
728 lockType = app.src.model.wcmf.Lock
729 ```
730 </div>
731 
732 As you can see the
733 \link wcmf::lib::persistence::concurrency::LockHandler `LockHandler`\endlink
734 implementation is exchangeable.
735 
736 ## Transactions ## {#pers_tx}
737 
738 wCMF supports [database transactions](http://en.wikipedia.org/wiki/Database_transaction).
739 There is only __one transaction at the same time__ and it is be obtained using the
740 \link wcmf::lib::persistence::PersistenceFacade::getTransaction `PersistenceFacade::getTransaction`\endlink
741 method. The transaction has an _active_ state, which is set in the
742 \link wcmf::lib::persistence::Transaction::begin `Transaction::begin`\endlink
743 method and reset on commit or rollback.
744 
745 The following example shows, how to use transactions:
746 
747 <div class="php">
748 ```
749 $persistenceFacade = ObjectFactory::getInstance('persistenceFacade');
750 
751 // get the current transaction and start it
752 $transaction = $persistenceFacade->getTransaction();
753 $transaction->begin();
754 try {
755  // load the the Author instance with id 1 and make changes to it
756  $author = $persistenceFacade->load(new ObjectId('Author', 1));
757  $author->setValue("name", "Author B");
758 
759  // save the changes
760  $transaction->commit();
761 }
762 catch(Exception $ex) {
763  // rollback the transaction if the commit fails
764  echo $ex->getMessage();
765  $transaction->rollback();
766 }
767 ```
768 </div>
769 
770 \note Even if not obtained explicitely, there is always a transaction existing
771 in the background, to which objects loaded from the store are attached. But to
772 persist changes when doing a commit, the transaction has to be set _active_
773 _before_ loading or creating the object.
774 
775 There are situations where you want to let the current transaction __ignore changes__
776 made to newly created objects or objects loaded from the store. In these cases you
777 can use the method
778 \link wcmf::lib::persistence::Transaction::detach `Transaction::detach`\endlink
779 to disconnect the object from the transaction.
780 
781 ### Dry runs ### {#pers_tx_dry}
782 
783 wCMF applies all database changes directly when committing the database transaction.
784 
785 But there are situations where this is not desirable or just not possible. For example you might want
786 to review the changes bevor applying them finally. Or the work to be done inside the transaction
787 would exceed the provided resources (time and/or memory) and therefor must be split into smaller
788 pieces but still need to be carried out in a one fails, all fail manner. A typical use case for the
789 latter would be a large data import from external sources.
790 
791 For these cases wCMF transactions offer the \link wcmf::lib::persistence::Transaction::commitCollect `Transaction::commitCollect`\endlink
792 method, which returns all statements that would be executed, if the transaction would be
793 commited regularly.
794 
795 The following script shows how to do a dry run first and commit the collected statements later:
796 
797 <div class="php">
798 ```
799 $persistenceFacade = ObjectFactory::getInstance('persistenceFacade');
800 $transaction = $this->persistenceFacade->getTransaction();
801 
802 // create/modify/delete objects inside transaction
803 $transaction->begin();
804 // ...
805 // dry run after finish
806 $statements = $transaction->commitCollect();
807 
808 // apply collected statements to the database
809 try {
810  $transaction->begin();
811  $conn = $this->persistenceFacade->getMapper('Project')->getConnection();
812  foreach ($statements as $statement) {
813  list($stmt, $params) = $statement;
814  $conn->prepare($stmt)->execute($params);
815  }
816  $transaction->commit();
817 }
818 catch (\Exception $ex) {
819  $transaction->rollback();
820 }
821 ```
822 </div>
823 */