Constructor section
===================

A constructor pipeline section is the heart of a transmogrifier content import
pipeline. It constructs Plone content based on the items it processes. The
constructor section blueprint name is
``collective.transmogrifier.sections.constructor``. Constructor sections do
only one thing, they construct *new* content. No schema changes are made.
Also, constructors create content without restrictions, no security checks or
containment constraints are checked.

Construction needs 2 pieces of information: the path to the item (including
the id for the new item itself) and it's portal type. To determine both of
these, the constructor section inspects each item and looks for 2 keys, as
described below. Any item missing any of these 2 pieces will be skipped.
Similarly, items with a path for a container or type that doesn't exist will
be skipped as well; make sure that these containers are constructed
beforehand. Because a constructor section will only construct new objects, if
an object with the same path already exists, the item will also be skipped.

For the object path, it'll look (in order) for
``_collective.transmogrifier.sections.constructor_[sectionname]_path``,
``_collective.transmogrifier.sections.constructor_path``,
``_[sectionname]_path``, and ``_path``, where ``[sectionname]`` is replaced
with the name given to the current section. This allows you to target the
right section precisely if needed. Alternatively, you can specify what key to
use for the path by specifying the ``path-key`` option, which should be a list
of keys to try (one key per line, use a ``re:`` or ``regexp:`` prefix to
specify regular expressions).

For the portal type, use the ``type-key`` option to specify a set of keys just
like ``path-key``. If omitted, the constructor will look for
``_collective.transmogrifier.sections.constructor_[sectionname]_type``,
``_collective.transmogrifier.sections.constructor_type``,
``_[sectionname]_type``, ``_type``, ``portal_type`` and ``Type`` (in that
order, with ``[sectionname]`` replaced).

Unicode paths will be encoded to ASCII. Using the path and type, a new object
will be constructed using invokeFactory; nothing else is done. Paths are
always interpreted as relative to the context object, with the last path
segment being the id of the object to create.

>>> import pprint
>>> constructor = """
... [transmogrifier]
... pipeline =
...     contentsource
...     constructor
...     printer
...     
... [contentsource]
... blueprint = collective.transmogrifier.sections.tests.contentsource
... 
... [constructor]
... blueprint = collective.transmogrifier.sections.constructor
... 
... [printer]
... blueprint = collective.transmogrifier.sections.tests.pprinter
... """
>>> registerConfig(u'collective.transmogrifier.sections.tests.constructor',
...                constructor)
>>> transmogrifier(u'collective.transmogrifier.sections.tests.constructor')
{'_type': 'FooType', '_path': '/spam/eggs/foo'}
{'_type': 'FooType', '_path': '/foo'}
{'_path': 'not/existing/bar',
 '_type': 'BarType',
 'title': 'Should not be constructed, not an existing path'}
{'_path': '/spam/eggs/existing',
 '_type': 'FooType',
 'title': 'Should not be constructed, an existing object'}
{'_path': '/spam/eggs/incomplete',
 'title': 'Should not be constructed, no type'}
{'_path': '/spam/eggs/nosuchtype',
 '_type': 'NonExisting',
 'title': 'Should not be constructed, not an existing type'}
{'_path': 'spam/eggs/changedByFactory',
 '_type': 'FooType',
 'title': 'Factories are allowed to change the id'}
>>> pprint.pprint(plone.constructed)
(('spam/eggs', 'foo', 'FooType'),
 ('', 'foo', 'FooType'),
 ('spam/eggs', 'changedByFactory', 'FooType'))
