Third Party Product Integration
Plone Developer Manual is a comprehensive guide to Plone programming.
1. ATVocabularyManager
ATVocabularyManager is a product for letting site managers define vocabularies for fields through-the-web or by import from XML files. ArchGenXML can generate the necessary code to use this product.
ATVM manages dynamic vocabularies. It installs a tool, where a site Manager can add, change and delete vocabularies. These vocabularies can then be used anywhere on the site.
You can download ATVocabularyManager from the Plone.org products area: "http://plone.org/products/atvocabularymanager":/products/atvocabularymanager
Using simple flat vocabularies
Adding ATVM-vocabs to your UML model is quite easy.
1. Add a selection or multiselection field to your type.
2. Add a tag 'vocabulary:name' and give it a name, let's say 'countries'
3. Add a tag 'vocabulary:type' with the value 'ATVocabularyManager'
We are now finished with the UML. Save it and let AGX do the work. What still is missing, is to install the countries vocabulary. Therefore:
* Add a function called 'setupVocabularies' to the protected code section in 'setuphandlers.py' in your product and register it as an import step in '/profiles/default/import_steps.xml' in a code section (make it dependend from you '*QI-Dependencies' step.
* Add the following code to your setuphandler.yp (this sets up a vocabulary 'countries' with the given values, and registers it with ATVocabularyManager)::
from Products.ATVocabularyManager.config import TOOL_NAME as ATVOCABULARYTOOL
from Products.CMFCore.utils import getToolByName
from Products.ATVocabularyManager.utils.vocabs import createSimpleVocabs
def setupVocabularies(context):
"""let's install the countries vocab"""
vocabs = {}
vocabs['countries'] = (
('ice', u'Iceland'),
('nor', u'Norway'),
('fin', u'Finland'),
('tyr', u'Tyrol'),
('auf', u'Ausserfern'),
)
site = context.getSite()
atvm = getToolByName(site, ATVOCABULARYTOOL)
createSimpleVocabs(atvm, vocabs)
Using simple tree vocabularies
If youre interested in using and creating hierachical vocab:
* use additional tag 'vocabulary:vocabulary_type' with value 'TreeVocabulary',
* have a look at the doc-string of 'Products.ATVocabularyManager.utils.createHierarchicalVocabs'.
Using vocabularies based on the **IMS Vocabulary Definition Exchange** (VDEX) format.
"VDEX":http://www.imsglobal.org/vdex/index.html is a simple XML based format to define flat or hierachical multilingual vocabularies. ATVocabularyManager supports VDEX in most of its dialects.
To tell Archetypes to use them in your UML first take Steps 1 to 3 of the first section and skip the import part. Then add a tag 'vocabulary:vocabulary_type' and give it the value 'VdexVocabulary'.
Now add a folder called 'data' in your products folder. Inside the '/data' folder create a new file called 'countries.vdex' ("example":countries.vdex). It will be imported automatically on install or reinstall, but only if a vocabulary named countries does not exist.
2. Relations
Create relations between portal-types model-driven. Support for Relations Product (complex references). Define sets of rules for validation, creation and lifetime of Archetypes references. ArchGenXML can generate the necessary code and XML-configuration data to use this product.
Prerequisites
To enable Relations install the Product ("code-location":http://plone.org/products/relations/).
Basics
As an option on command line, up to a tagged-value on model-level or on a single UML-Association you just define the
'relation_implementation' and set it to 'relations'. A directed Assoziation results in one Relation.
**Give the association and its assoziation ends names.** They'll be used as the names for the RelationField. If you dont want a field turn it off by setting a tagged value 'generate_reference_fields' on class (or package, model) level to '0'.
Inverse Relation
If the association is not directed (navigable on both association ends) an inverse relation will be created.
The tagged-value 'inverse_relation_name' will be used for the back-relation on undirected associations. It defaults to a relation named 'toend_fromend', where these are the lowercased versions of the association ends. If the two ends are named the same, then the relation will be named 'association_inv', where 'association' is the name of the association. (Finally, if the option 'old_inverse_relation_name' is set, then it defaults to the association name postfixed by '_inverse'.)
Cardinality
You can use the Multiplicity on in UML to define the cardinality of an Relation.
You can use the minimum and maximun value here using the syntax '1..5' which means at least one relationrelated objects but not more than five.
Constraints
type-constraint -- as described above an association between two portal-types will be created.
interface-constraint -- an association between an archetypes class and an interface will create an interface-constraint. the relation is allowed to all classes implementing this interface.
Association classes
Association classes can be used to store data on the relation as an object. You can model it using the UML association class or using a tagged value 'association_class' on the association.
3. Remember
Generate 'Remember' based Member-Types. Its the successor of CMFMember.
Prerequisites
You must install to additional Products:
* "membrane":http://plone.org/products/membrane
* "remember":http://plone.org/products/remember
(using "Five 1.4.3+":http://codespeak.net/z3/five/)
You should also read the documentation of both and understand how they work!
A Content-Type based on remember
* Create a class in your class diagram and give it a a stereotype '<<remember>>'
* add the tagged value 'use_workflow' and set it to one of
'member_approval_workflow' or 'member_auto_workflow'. You can create also your
own workflow if you know what remember needs (look at the workflows shipped
with remember).
* set the 'active_workflow_states' tagged value to the class and declare which
states of the used workflow are the ones, where the user can log in with.
It expects a list of values, e.g. 'python:["private", "public"]'
* Add attributes (fields) as you need. Attention here, only override fields
of remembers BaseMember schema if you know what youre doing.
* Generate & Done
4. CompoundField and ArrayField
How to make custom fields: a list of some default field type, a compound of a two or more default fields.
Prerequisites
Install the "CompoundField":http://plone.org/products/compoundfield extension
into you Products folder.
List of fields - ArrayField
Assume you want to have content type where the user can provide one or more files.
Its easy by making the type folderish. But for some use-cases this is to heavy or to
difficult, you want the user to use a form for those files.
You could say, ok, up to 5 files is enough and model 5 file fields into your class.
Not very elegant, huh?
The easiest way is to to use the UML 'multiplicity' feature on your attribute aka field of the
class. If you want to enable unlimited attachments use multiplicity '*'.
Or choose a number like '5', as in our above example.
You can set the initial size of the array by using the tagged value 'array:size' to 'python:10' for example.
Prefixed with 'array:' you can access also the label 'array:widget:label' of it and so on.
If you prefer the EnhancedArrayWidget you need to add an tagged value 'imports'
'from Products.Compoundfield.EnhancedArrayWidget import EnhancedArrayWidget' to your class
and set on the attribute the tagged value 'array:widget:type' to 'EnhanceArrayWidget'.
Custom Fields compounds - CompoundField
With ArchGenXML you can create compounds of fields from existing fields.
Such a set of fields behaves almost like a normal field.
To create such a compounded field create a new class and give it the
stereotype '<<field>>'
Now add attributes to it like you would do on a content type class.
You can use almost every field type, just some special fields, mostyl those
acting as a proxy without own storage, wont work (such as ReferenceField or AttachementField).
For example we create a 'PointField' consisting out of two 'FloatFields' by
just adding a 'x' and 'y' attribute of type 'float'.
To use the new field create a fresh content class and name it 'Polygon'.
Take a dependency arrow pointing from your Polygon class to the field class.
This ensures it gets imported!
Next add an attribute 'points' to the class. The type of the new points attribute
is 'PointsField'. Now to make it a polygon give it a multiplicity of *and
your done: You have a list of Points as one field.
5. Content Flavors
When you want to add a couple of fields to an existing content type (including reference fields), you may decide to create a whole new product that subclasses that type. You then have a whole bunch of code to maintain and you are dependent on changes that may occur in your parent class. Or you let ArchGenXML use the Content Flavors product and your day gets brighter. Note that the use of the experimental content flavors product is now deprecated in favor of the more reliable and feature-rich archetypes.schemaextender.
Prerequisites
You must install the Content Flavors product.
Adding a field to an existing content typ
- Let an existing content type, e.g. "ExistingType", be present in your diagram (as a class with stereotypes <<archetype>> and <<stub>>)
- Create a class, e.g. "MyCoolFlavor", in your diagram and give it the <<flavor>> stereotype
- Add any field(s), e.g. "MyAdditionalField", to this flavor class
- Create a realization arrow from "ExistingType" to "MyCoolFlavor"
- Generate & Done
Now every new instance of ExistingType will have the MyAdditionalField field in its schema, default view and default edit form.
Limits
-
The use of the experimental content flavors product is now deprecated in favor of the more reliable and feature-rich archetypes.schemaextender.
- Content Flavors also allows custom views to be used by existing types but this feature is not supported by ArchGenXML yet.
- You may not be able to see the additional field(s) if the ExistingType uses some non-default view. You then have to manually manage this by overriding these existing views with some of your own, with or without the help of the Content Flavors product.
- The existing content type may have to be based on ATCT (to be tested)?
- Several flavors can be applied to a given type. The order of precedence can be managed through the web if the existing type follows some requirements detailed in the Content Flavors documentation.
- There are possible issues with indexing the additional fields, see CF documentation for details.
- Content Flavors was an experiment and is now deprecated in favour of the archetypes.schemaextender, which is also supported by AGX.
6. archetypes.schemaextender
When you want to add a couple of fields to an existing content type (including reference fields), you may decide to create a whole new product that subclasses that type. You then have a whole bunch of code to maintain and you are dependent on changes that may occur in your parent class. Or you let ArchGenXML make your product use archetypes.schemaextender and your day gets brighter.
Prerequisites
You must install the archetypes.schemaextender product.
Adding a field to an existing content type
Let's say you want to add superPower (a field) to HumanBeing
(a class).
- Let the content type to extend, e.g. "HumanBeing", be present in your diagram (as a class, possibly with the <<stub>> stereotype)
- Create an interface, e.g. "ISuperHero" (the "I" helps remembering this is an interface), in your diagram ; it has the <<interface>> stereotype
- Draw a realization arrow from "HumanBeing" to "ISuperHero"
- Create a class, e.g. "SuperHero", in your diagram and give it the <<extender>> stereotype
- Add any field(s), e.g. "superPower", to this extender
- Create a realization arrow from the extender class to the interface, e.g. from "SuperHero" to "ISuperHero", remove its <<realize>> stereotype and replace it with a <<adapts>> stereotype
- Generate & Done
Now every new instance of HumanBeing will have the superPower field in its schema, default view and default edit form. And even if the developer of the HumanBeing content type decides to remove its arms or legs, human beings (all of them) will still have super powers because you declared they are super heros (they implement ISuperHero).
Note that, in order to add these stereotypes (<<extender>>, <<adapts>>) to your (Argo)UML model, you have to create a stereotype, give it the proper name (extender, adapts) and select its proper "Super-class" in the properties tab (you either select class for class stereotypes, or abstraction for the "adapts" stereotype).
Example model and additional features
AGX support of archetypes schemaextender is illustrated by the example model in the screenshot below :

You may note from this example model that AGX support of archetypes.schemaextender comes with a bunch of funny features :
- support for adapters and named adapters
- adapted interfaces (or classes) can be external to your model (using the <<stub>> stereotype)
- you can even let a stub class implement a
stub interface : in the example above, the HumanBeing stub class has a realization arrow to IAStubInterfaceFromYetAnotherProduct, which will be turned by AGX into a
five:implement ZCML declaration. This is useful when you want to integrate 2 distinct third party products via your own product. Your model is then nothing more than a "glue" model, which is a good thing in many cases.
