# Observers in cobjects

Generic observer mechanism described in is used in our cobject implementation. `IProperty` base class implements `IObserverHandler` interface and so all its descendants are responsible for notifying about changes (see .

All cobjects provides `BasicChangeContext` which contains previous value of changed one. Because complex types can add and remove its elements, special behaviour is specified. New value given as mandatory parameter of notify method may be `CNull` if element is deleted from comlex type. Old value in the context may also `CNull` if element was added. It is imposible to have both of them `CNull`.

# Observers in CPdf

CPdf class as PDF file maintainer uses observers for synchronization of structures which may be changed in two ways. This may occure because all attributes can be accesible through properties (cobjects) and also special objects provided by CPdf - CPage for page manipulation, COutline for outlines manipulation and so on. Special objects keeps logic of concrete entities and manipulates with cobject in that way. Property part is without any logic and enables making changes which are not covered by special objects. This advantage and extensibility is payed by additional synchronization.

Property tree doesn't know the way how it was changed.

## Page tree synchronization

Page tree, as mentiont above, can be changed from property site of view by making changes directly to the or by CPdf using

    	CPdf::insertPage
    	Cpdf::removePage

methods. Second way is safer, because all necessary workaround are done correctly here which is not guaranteed by property site, where any kind of data can be supplied.

Synchronization is guarantied by 3 internal Classes are internal because they need access to CPdf internals, such as pageList and protected methods for page tree and page list consolidation. classes which implements `IObserver` interface. To make their logic easier, each observer is specialized for one type of change. So that we have

- `PageTreeRootObserver` - which is registered on Pages entry in . If this value changes, we have to throw away and invalidate all pages which were returned until now.
- `PageTreeNodeObserver` - which is registered on all intermediate nodes. If any of node's dictionary is changed, checks whether it is entry which may affect page tree (Kids, Count or Parent properties are added, removed, or their value is changed). it has to invalidate all subtree of this node.
- `PageTreeKidsObserver` - which is registered on all elements of intermediate node's Kids array. If any of this element changes its value (they all should be referencies to Pages or Page dictionary), original node has to be invalidated and also its children if it is intermediate node.

Whenever Kids array changes and as a result subtree of intermediate node is changed, Count entry in node's dictionary has to be changed too and propagated to the page tree root.

All this stuff is implemented by `consolidatePageTree` and `consolidatePageList` methods in CPdf. For more implementation details, please see doxygen documentation.

# Observers in CPage

## Observer for annotation

CPage stores all CAnnotation instance from its Annots array in internal `annotStorage`. User can change annotatations with `addAnnotation` or `delAnnotation` methods but also by changing Annots array directly.

To prevent from problems with inconsistency, CPage instance registers `AnnotsArrayWatchDog` observer implementation on Annots array and all its members (because they are referencies and someone may change reference value to target which is not annotation dictionary). Whenever this array changes, observer will force to reload annotStorage (see doxygen documentation for more precise information because they are out of scope of this documentation).