Documentation:Présentation du modèle de données
Un article de AlfrescoWiki.
Sommaire |
[modifier] Introduction
Les documents à stocker dans le repository n'étant pas tous de même nature (factures, extraits de naissance, images), il est primordial de leur attribuer des méta-données spécifiques. Par exemple il sera intéressant de faire remonter la taille d'une image, l'auteur d'un document ou la date d'un événement. Le modèle de base d'Alfresco fournit un ensemble de documents-types parmis les plus courants, de même que la manière de les organiser ou les relier. On trouvera ainsi des notions de répertoires, de document, de traduction, de pièce jointe, de forum, de commentaire, etc. Ces types suffisent à modéliser les cas les plus généraux mais il est pratique d'aller plus loin afin de permettre de décrire n'importe quel document spécifique. C'est pourquoi Alfresco permet d'étendre le modèle de données initial afin d'introduire ses propres types. Cette page présentera tout d'abord les concepts régissant le modèle de données puis dans une deuxième partie le modèle de données de base. L'enrichissement du modèle de données et traité dans une page à part : Documentation:Enrichir_le_modèle_de_données
[modifier] Le dictionnaire de données
Les types du modèle de base doivent être exprimés dans un certain formalisme afin d'être compris par le dictionnaire de données. Ce formalisme, qui dispose donc lui aussi de son modèle de données, est appelé méta-modèle (c'est-à-dire un modèle qui sert à décrire un modèle). Ce méta-modèle sera appelé par la suite modèle M2 alors que le modèle des documents Alfresco sera appelé M1 ou tout simplement "modèle". Le modèle M2 définit principalement deux entités : les types et les aspects. Tous deux servent à décrire une structure de données ayant des propriétés (voir types de données ci-dessous) et des associations vers d'autres entités. L'héritage de ces entités est aussi modélisé de manière à permettre la définition d'une nouvelle entité en repartant d'une entité existante que l'on enrichit.
Les types comme les aspects permettant de définir des propriétés et des associations, il faut se pencher un peu plus sur leurs différences. Un type est nécessaire (tout document a un type) et sert à définir une structure de base. Les aspects décrivent des jeux de propriétés et d'associations qu'on peut greffer sur n'importe quel type. Au contraire du type, unique, plusieurs aspects peuvent être ajoutés à un noeud. Le type peut donc être vu comme le coeur et les aspects comme des surcouches. La frontière entre le bon et le mauvais usage des types et des aspects est difficile à tracer mais globalement disons qu'un aspect est plus souple et plus réutilisable alors qu'un type est plus structurant et figé. On utilisera souvent l'un ou l'autre selon qu'on veut garder un modèle ouvert ou au contraire structuré. Les aspects peuvent aussi servir à ajouter des comportement mais on sort là du cadre du simple modèle de données. Outre la notion d'héritage, les associations entre les entités sont modélisées dans le modèle M2 sous deux formes : les associations de base ou paritaires, et les associations parent/enfant (ou conteneur/contenu). Ces dernières jouent un rôle primordial car chaque document, et chaque noeud du repository d'une manière générale, doit avoir un parent, au sens conteneur, pour exister.
[modifier] Types de données
Les propriétés des types de documents ou des aspects sont typées afin de garantir au modèle un minimum d'intégrité. Les types de données autorisés (à défaut de tout autre) sont définis au sein du fichier alfresco/model/dictionaryModel.xml au sein de l'espace de noms http://www.alfresco.org/model/dictionary/1.0/ (préfixe d). Ce fichier définit les types de donnée suivants :
| Nom du type | Description | Equivalent en Java |
|---|---|---|
| d:text | texte | java.lang.String |
| d:mltext | texte multilingue (chaque utilisateur le voit dans sa langue) | java.lang.String |
| d:content | Contenu d'un fichier | org.alfresco.service.cmr.repository.ContentData |
| d:int | entier | java.lang.Integer |
| d:long | entier long | java.lang.Long |
| d:float | décimal | java.lang.Float |
| d:double | décimal | java.lang.Double |
| d:date | date | java.util.Date |
| d:datetime | date et heure | java.util.Date |
| d:boolean | booléen | java.lang.Boolean |
| d:qname | Nom qualifié (i.e. dans un espace de noms) | org.alfresco.service.namespace.QName |
| d:category | Lien vers une catégorie | java.lang.String |
| d:noderef | Référence d'un noeud | org.alfresco.service.cmr.repository.NodeRef |
| d:path | Chemin | org.alfresco.service.cmr.repository.Path |
| d:locale | Langue | java.util.Locale |
| d:any | N'importe quel type (ouverture au polymorphisme) | java.lang.Object |
[modifier] Les modèles de base
Outre le dictionaryModel.xml présenté ci-dessus qui définit les types de données et pas des types de documents, Alfresco fournit un jeu de modèles de base dont les plus importants sont :
- systemModel.xml : décrit les concepts fondamentaux (identification d'un noeud, notion de racine) et les types de base qui ne sont pas encore vraiment des documents
- contentModel.xml : modèle principal qui introduit la notion de document, de répertoire (ou espace), de classifiation ainsi que les principaux aspects (titre, mail, Dublin Core, traduction, pièces jointes)
- applicationModel.xml : ajoute quelques notions utilisées par l'application Web, dont la présentation graphique (icône)
- forumsModel.xml : définit les types de documents et l'organisation des forums (aussi utilisé comme système de commentaire sur les documents)
Tous ces modèles respectent la même syntaxe décrite par un schéma XML dédié.
--Philippe DE RIVAROLA/Knowings 20 juillet 2007 à 08:25 (BST)
[modifier] Explications sur les modèles de contenu
Tous les modèles de contenu doivent être conforme au schema modelSchema.xsd. Ce fichier est présent dans le dossier "model" où sont situés les principaux modèles de base d'Alfresco (contentModel.xml, dictionaryModel.xml etc.).
<model name="cm:contentmodel" xmlns="http://www.alfresco.org/model/dictionary/1.0"> <description>Alfresco Content Model</description> <author>Alfresco</author> <published>2005-06-03</published> <version>0.1</version> ...
Chaque modèle commence par se déclarer lui même. Dans l'exemple ci-dessus, on peut voir le nom du modèle "cm:contentModel". Le préfixe "cm" est défini de la façon suivante par la balise <namespaces> (espaces de noms) :
<namespaces>
<namespace uri="http://www.alfresco.org/model/content/1.0" prefix="cm"/>
</namespaces>
<imports>
<import uri="http://www.alfresco.org/model/dictionary/1.0" prefix="d"/>
</imports>
Un modèle peut définir plusieurs "namespaces". Il peut aussi faire référence à d'autres modèles en important leur "namespaces". Dans l'exemple, on peut voir qu'un import du dictionaryModel est fait (préfixe "d"). Dans ce cas, ceci permet de faire référence à des types de données (data types) qui sont définies dans le fichier dictionaryModel.xml.
Une fois ce contexte mis en place, un type de contenu peut être défini.
<types>
<type name="cm:cmobject">
<title>Object</title>
<parent>sys:base</parent>
<properties>
<property name="cm:name">
<type>d:text</type>
</property>
</properties>
<mandatory-aspects>
<aspect>cm:auditable</aspect>
</mandatory-aspects>
</type>
...
Ci-dessus, un type de contenu "cm:cmobject" a été défini. Ce type supporte une propriété appelée "cm:name" avec un type de données "d:text" (soit du texte simple). La balise <parent> permet de définir l'héritage éventuel. Ici, le type "cm:object" hérite du type "sys:base" et donc de toutes ses définitions. Notez la balise <mandatory-aspects> qui oblige l'aspect "cm;auditable" à être appliqué automatiquement quand un type de contenu "cm:object" est créé.
Description d'un aspect. Prenons comme exemple "cm:auditable" :
<aspects>
<aspect name="cm:auditable">
<title>Auditable</title>
<properties>
<property name="cm:created">
<type>d:datetime</type>
</property>
<property name="cm:creator">
<type>d:text</type>
</property>
<property name="cm:modified">
<type>d:datetime</type>
</property>
<property name="cm:modifier">
<type>d:text</type>
</property>
<property name="cm:accessed">
<type>d:datetime</type>
</property>
</properties>
</aspect>
...
Cet aspect est appliqué à n'importe quel contenu. Ainsi les différentes propriétés (date de création, créateur...) sont appliquées.
Les propriétés supportent différentes configurations :
- <mandatory>true-false</mandatory> - la propriété est obligatoire ou non. Si obligatoire, la valeur de la propriété doit être fourni avant que le noeud soit sauvegardé.
- <default>(valeur)</default> - assigne automatiquement une valeur quand le noeud est créé.
<property name="my:property">
<type>d:text</type>
<mandatory>true</mandatory>
<default>my default value</default>
</property>
Une balise "<protected>true|false</protected>" peut aussi être utilisée pour rendre la propriété verrouillée. L'utilisateur ne peut pas la modifier.
Il est possible de préciser de quelle façon la propriété doit être indexée. Par défaut chaque propriété est indéxée de façon atomique(notion d'atomicité).
<property name="cm:example">
<type>d:text</type>
<mandatory>false</mandatory>
<index enabled="true">
<atomic>false</atomic> <!-- indexation en arrière plan ou non -->
<stored>false</stored> <!-- stocke ou ne stocke pas la valeur de la propriété dans l'index -->
<tokenised>true</tokenised>
</index>
</property>
Regardons à présent un exemple d'association.
<type name="cm:folder">
<title>Folder</title>
<parent>cm:cmobject</parent>
<associations>
<child-association name="cm:contains">
<source>
<mandatory>false</mandatory>
<many>false</many>
</source>
<target>
<class>sys:base</class>
<mandatory>false</mandatory>
<many>true</many>
</target>
<duplicate>false</duplicate>
</child-association>
</associations>
</type>
Une association appelée "cm:contains" est définie. Le rôle de la source et la cible est de suivre des contraintes telles que des cardinalités et des classes cible (type de contenu ou aspect). Dans le cas ci-dessus est autorisé plusieurs cibles (<manu>true>/many>) et n'importe quel type de contenu (puisque cm:folder et cm:content héritent de cm:cmobject qui hérite de sys:base).
Les associations de type "child-association" permettent des relations "parents/enfants". Ainsi un noeud X ayant une child-asociation avec un noeud Y, X est le prent de Y. Cela implique une notion de récursivité. Si on supprime X alors Y, étant l'enfant de X, est supprimé aussi. Ce n'est pas le cas avec les associations simple "association". Les "child-association" permettent facilement une navigation en utilisant des recherches XPath ou Lucene.
Voici un exemple d'association simple :
<aspect name="cm:subscribable">
<associations>
<association name="cm:subscribedBy">
<source>
<mandatory>false</mandatory>
<many>true</many>
</source>
<target>
<class>cm:person</class>
<mandatory>false</mandatory>
<many>true</many>
</target>
</association>
</associations>
</aspect>
dans ce cas la propagation de la suppression ne se fera pas. Dans le cas d'associations simples, on ne peut pas utiliser les langages de recherches XPath et Lucene pour naviguer d'un noeud vers un autre puisqu'il n'y a pas de ralation parent/enfant.

