Ci-dessous figure une liste des opérations que les fournisseurs de modèles peuvent faire pour tirer parti du support des modèles logiques d'équipe :
Les sections suivantes décrivent plus en détail chacun de ces points. Le plug-in org.eclipse.team.examples.filesystem contient un exemple illustrant plusieurs de ces points. Vous pouvez réserver le projet du référentiel CVS et l'utiliser comme référence lorsque vous lisez de didacticiel. Clause de protection : Le code source dans l'exemple de plug-in peut varier dans le temps. Pour obtenir une copie qui correspond à ce qui est utilisé dans cet exemple, vous pouvez réserver le projet à l'aide de la balise de version 3.2 (R3_2, le plus souvent) ou une balise en date du 28 juin 2006.
L'API de mappage des ressources est volontairement simple en ignorant les opérations de modèles logiques. Un client ne peut pas utiliser cette interface pour afficher des modèles logiques ou obtenir des informations complémentaires intéressantes sur celle-ci. Son but est simplement de mapper un ou plusieurs éléments de modèle aux ressources de l'espace de travail.
L'API comprend les classes suivantes :
Object getModelObject()
: L'objet de modèle dont découle le mappage (ou adapté).ResourceTraversal[]
getTraversals(ResourceMappingContext, IProgressMonitor)
: Le balayage de la ressource couvrant les ressources qui forment l'objet de modèle.ResourceTraversal
contient un ensemble de ressources ainsi qu'un indicateur de profondeur qui signale la profondeur à laquelle les ressources situées dans le balayage sont associées avec l'objet de modèle d'origine. Des balayages de ressource sont fournis à un client par un mappage de ressource dans le but de décrire le contenu d'un modèle pour permettre au client (un fournisseur de référentiel) d'effectuer ses opérations aussi efficacement que possible. Les méthodes conseillées sont les suivantes :
getResources()
getDepth()
ResourceMappingContext
et RemoteResourceMappingContext
est plus compliquée et fait l'objet d'une description dans la section Contexte du mappage des ressources.Deux types de plug-ins devraient s'intéresser aux mappages des ressources. Ceux qui fournissent un modèle qui comprend des ressources, ou qui est conservé dans des ressources de l'espace de travail et ceux qui souhaitent effectuer des opérations sur les ressources. Le premier est traité dans la section suivante tandis que le deuxième est abordé dans la section Organigramme des référentiels pour l'intégration des modèles logiques.
Les plug-ins ayant adapté leurs objets de modèle à IResource
pour extraire les actions spécifiques aux ressources affichées dans le menu contextuel peuvent à présent s'adapter à ResourceMapping
si une description plus détaillée de la manière dont les objets s'adaptent est utile. Toutefois, s'il n'y a aucun intérêt à le faire, cette opération n'est pas obligatoire. Par exemple, une unité de compilation Java (par exemple, un fichier *.java affiché dans une vue JDT) qui s'adapte actuellement à IFile
ne doit pas s'adapter à ResourceMapping
puisque rien n'est acquis. Toutefois, un package Java doit s'adapter à ResourceMapping
pour indiquer que le package comprend uniquement les fichiers dans le dossier correspondant et non pas les sous-dossiers.
La méthode recommandée pour adapter les modèles d'élément à un mappage des ressources consiste à utiliser une fabrique d'adaptateur. Ci-dessous figure le marquage XML permettant d'ajouter une fabrique d'adaptateur dans un manifeste de plug-in.
<extension
point="org.eclipse.core.runtime.adapters">
<factory
class="org.eclipse.example.library.logical.AdapterFactory"
adaptableType="org.eclipse.example.library.Book">
<adapter type="org.eclipse.core.resources.mapping.ResourceMapping"/>
</factory>
<factory
class="org.eclipse.example.library.logical.AdapterFactory"
adaptableType="org.eclipse.example.library.Library">
<adapter type="org.eclipse.core.resources.mapping.ResourceMapping"/>
</factory>
...
</extension>
L'implémentation de la fabrique d'adaptateur doit ressembler à ceci :
public class AdapterFactory implements IAdapterFactory {
public Object getAdapter(Object adaptableObject, Class adapterType) {
if((adaptableObject instanceof EObject) && adapterType == ResourceMapping.class) {
return new EObjectResourceMapping((EObject)adaptableObject);
}
return null;
}
public Class[] getAdapterList() {
return new Class[] {ResourceMapping.class};
}
}
Les objets de modèle peuvent implémenter l'interface IAdaptable
. Si tel est le cas, ils doivent s'assurer que le gestionnaire de l'adaptateur de la plateforme est consulté. Il peut le faire en sous-classant PlatformObject
ou en utilisant la ligne de code suivante :
Platform.getAdapterManager().getAdapter(Object, Class)
Cette méthode est préférable. Cependant, l'objet de modèle peut implémenter l'interface IAdaptable et fournir une implémentation getAdapter(Class)
qui crée des renvois d'une instance de ResourceMapping
de manière explicite, si besoin est. Cette méthode est plus directe, mais est moins conseillée, dans la mesure où le modèle doit disposer d'une connaissance explicite de l'adaptation aux ressources.
Dans certains cas, le fournisseur d'un modèle logique peut ne pas souhaiter que son modèle s'adapte à IResource
dans chaque contexte ou peut vouloir que son objet s'adapte différemment pour les contributions d'objet que pour les autres contextes. L'interface utilisateur du plan de travail fournit une API d'adaptateur intermédiaire spécial, IContributorResourceAdapter
, à cette fin. Lorsque des objets sont adaptés à IResource
dans le contexte de contributions d'objet, le plan de travail tente premièrement d'adapter la ressource à IContributorResourceAdapter
avant de tenter de s'adapter à IResource
directement. Une sous-interface de cette interface, IContributorResourceAdapter2
, qui offre la même fonctionnalité pour ResourceMapping
, a été ajoutée.
La seule différence réside dans le fait que le fournisseur de modèles doit enregistrer une fabrique pour IContributorResourceAdapter
car le plan de travail effectue une vérification de instanceof afin de déterminer si l'adaptateur ajouté est également une instance de IContributorResourceAdapter2
.
L'implémentation de la sous-classe ResourceMapping
d'un package Java ressemblerait à ceci.
public class JavaPackageResourceMapping extends ResourceMapping {
IPackageFragment package;
...
public getModelObject() {
return package;
}
public ResourceTraversals[] getTraversals(
ResourceMappingContext context,
IProgressMonitor monitor) {
return new ResourceTraversal[] {
new ResourceTraversal(
new IResource[] { package.getCorrespondingResource() },
IResource.DEPTH_ONE, IResource.NONE)
}
}
}
Ce mappage est relativement direct. Par conséquent, l'implémentation n'est pas complexe. La complexité de l'implémentation du mappage des ressources varie, bien entendu, d'un modèle à un autre.
Un des avantages d'une API de mappage des ressources est de permettre aux plug-ins de mettre en oeuvre toutes les opérations qu'ils désirent en termes de mappage des ressources (par exemple, mise à jour CVS, validation CVS, balise CVS, décoration modifiée, etc.). Toutefois, l'API qui a été introduite jusqu'à présent ne concerne que l'état local du modèle. Lorsque vous utilisez un modèle susceptible d'être partagé entre les développeurs, vous vous retrouvez dans une situation dans laquelle l'état distant du modèle (à savoir, l'état du modèle qu'un utilisateur a libéré dans le référentiel) peut différer de l'état indiqué dans l'espace de travail. Si vous avez effectué une mise à jour CVS, vous voudrez que l'état local du modèle corresponde à l'état distant même si cela implique que des fichiers supplémentaires soient inclus ou que certains fichiers doivent être supprimés.
Ce n'est pas un problème pour certains modèles logiques. Par exemple, un package java est un conteneur visité à une profondeur de une, quel que soit l'état distant du modèle. En dépit de ceci, un fournisseur de référentiels peut aisément déterminer si des suppressions sortantes doivent être incluses lors de la validation ou si des ajouts entrants doivent être inclus lors de la mise à jour. Toutefois, les ressources qui constituent certains modèles logiques sont susceptibles de changer. Par exemple, les ressources qui constituent un élément de modèle peuvent dépendre du contenu d'un fichier manifeste (ou d'autres mécanismes similaires). Pour que le mappage des ressources renvoie le balayage correspondant, il doit accéder au contenu distant du fichier manifeste (s'il diffère du contenu local) afin de voir si des ressources supplémentaires doivent être incluses. Ces ressources supplémentaires peuvent ne pas exister dans l'espace de travail, mais le fournisseur de référentiels saurait le vérifier lors de l'exécution de l'action sélectionnée.
Pour prendre en charge ces modèles plus complexes, un élément RemoteResourceMappingContext
peut être transmis à la méthode ResourceMapping#getTraversals
.
Lorsqu'un contexte est fourni, le mappage peut l'utiliser pour vérifier que toutes les ressources nécessaires sont incluses dans le balayage. Dans le cas contraire, le mappage peut présumer que seul l'état local est utile.
Un élément ResourceMapping
doit seulement se préoccuper d'un contexte fourni à la méthode getTraversals
dans les cas où les ressources qui composent un modèle changent et que la relation entre le modèle et les ressources ne peut pas être décrite par un simple balayage garanti pour englober les ressources qui composent ce modèle (et seulement celles-ci). Par exemple, bien que les ressources d'un package Java puissent varier, le package peut être décrit en tant que dossier d'une profondeur de un de sorte qu'un mappage de ressources pour les packages java n'ait pas besoin de recourir au contexte du mappage des ressources.
A titre d'exemple plus complexe, imaginons un fichier HTML contenant plusieurs images. Supposons que toutes les références d'images du fichier HTML fassent partie du modèle de ce fichier. Lors de la mise à jour du contenu local du fichier HTML à partir d'un référentiel, l'utilisateur s'attend à ce que toutes les nouvelles images soient incluses. La méthode getTraversals
d'un ResourceMapping
correspondant au modèle de fichier HTML ressemblerait à ceci :
public class HTMLResourceMapping extends ResourceMapping {
private HTMLFile htmlFile;
public ResourceTraversal[] getTraversals(ResourceMappingContext context,
IProgressMonitor monitor)
IResource[] resources = htmlFile.getResources();
if (context instanceof RemoteResourceMappingContext) {
// Rechercher les ressources supplémentaires sur le serveur
RemoteResourceMappingContext remoteContext = (RemoteResourceMappingContext)context;
IFile file = htmlFile.getFile();
if (remoteContext.hasRemoteChange(file, monitor)) {
IStorage storage = remoteContext.fetchRemoteContents(file, monitor);
IResource[] additionalResources = getReferences(storage.getContents());
resources = combine(resources, additionalResources);
}
if (remoteContext.isThreeWay() && remoteContext.hasLocalChange(file, monitor)) {
IStorage storage = remoteContext.fetchBaseContents(file, monitor);
IResource[] additionalResources = getReferences(storage.getContents());
resources = combine(resources, additionalResources);
}
}
return new ResourceTraversal[] {
new ResourceTraversal(resources, IResource.DEPTH_ZERO, IResource.NONE)};
}
}
Notez qu'il existe deux ensembles de ressources inclus dans le modèle : celles issues du contenu local du fichier HTML dans l'espace de travail et celles extraites du contenu du fichier distant et du fichier de base. Quel que soit l'ensemble, des ressources peuvent ne pas résider dans l'espace de travail. Par exemple, le fichier HTML local peut contenir un lien relatif à une image qui n'existe pas dans l'espace de travail. Cette ressource doit être incluse afin qu'elle puisse être extraite si elle existe à distance. Comme pour le fichier distant, elle peut contenir une nouvelle copie qui référence les images supplémentaires devant être extraites lorsque le nouveau contenu distant est téléchargé.
Les fournisseurs de modèle permettent de regrouper les mappages de ressources associés. Voici un lien vers la classe ModelProvider. Cette classe a trois objectifs :
IResourceMappingMerger
du modèle est obtenu grâce à l'adaptation du fournisseur de modèles.L'exemple ci-dessous illustre la définition d'une extension modelProvider.
<extension
id="modelProvider"
name="Library Example"
point="org.eclipse.core.resources.modelProviders">
<modelProvider
class="org.eclipse.team.examples.library.adapt.LibraryModelProvider"
name="Library Example"/>
<extends-model id="org.eclipse.core.resources.modelProvider"/>
<enablement> <test property="org.eclipse.core.resources.projectNature" value="org.eclipse.team.examples.library.view.nature" />
</enablement>
</extension>
LibraryModelProvider
est une sous-classe de ModelProvider
.
La règle d'activation sert à mettre en correspondance les ressources dans lesquelles le modèle Library conserve son modèle. Dans l'exemple précédent, le fournisseur de modèles met en correspondance toutes les ressources présentes dans un projet qui ont la nature de bibliothèque.
Une fois le fournisseur de modèles fourni, la méthode ResourceMapping#getModelProviderId()
doit être remplacée pour renvoyer l'ID du fournisseur de modèles.
public String getModelProviderId() {
return "org.eclipse.team.examples.library.adapt.modelProvider";
}
Pour obtenir le mappage de ressources inverse au mappage des ressources des ressources qui correspondent à la règle d'activation de votre fournisseur, vous devez également remplacer l'une des méthodes getMapping
ou les deux. La méthode que vous devez remplacer dépend si le modèle possède des éléments qui contiennent plusieurs ressources ou non. Si les éléments de votre modèle sont associés à une seule ressource, vous pouvez remplacer la méthode qui accepte un seul argument IResource
. Dans le cas contraire, vous devez remplacer la méthode qui accepte une grappe de ressources. L'exemple ci-dessous illustre l'utilisation du cas de la ressource unique.
Dans l'exemple suivant, la méthode englobe un fichier de modèle de bibliothèque dans un mappage de ressources. Elle englobe également les dossiers qui contiennent des fichiers utiles pour le fournisseur de modèles.
public class LibraryModelProvider extends ModelProvider {
public ResourceMapping[] getMappings(IResource resource,
ResourceMappingContext context, IProgressMonitor monitor) {
if (isModelFile(resource)) {
// Renvoie un mappage de ressources sur le fichier
return new LibraryResourceMapping(resource);
} if (containsModelFiles(resource)) {
// Crée un mappage de ressources profond sur le conteneur
return new LibraryContainerResourceMapping(resource);
}
// La ressource n'est pas utile pour ce fournisseur de modèles
return null;
}
}
Les clients peuvent ensuite accéder au fournisseur de modèles afin de déterminer si celui-ci se préoccupe des ressources sur lesquelles des opérations sont sur le point d'être réalisées. La section suivante décrit l'API qui sera fournie aux opérations d'équipe qui utilisent l'API du fournisseur de modèles pour déterminer l'ensemble complet de mappages de ressources à utiliser lorsqu'une opération d'équipe est réalisée sur un ensemble de ressources sélectionnées ou des éléments de modèle.
Les opérations effectuées sur les ressources doivent au préalable être validées afin de s'assurer que l'utilisateur est informé des effets secondaires possibles. Ci-dessous figurent les étapes requises pour valider une modification apportée à une ressource.
IResourceChangeDescriptionFactory
.
La fabrique produit un élément IResourceDelta
qui duplique l'aspect du delta de la ressource résultante une fois l'opération effectuée.ResourceChangeValidator
.
Le valideur consulte tous les fournisseurs de modèle ayant montré un intérêt pour les ressources concernées. Le résultat renvoyé correspond à un ou plusieurs états contenant l'ID du modèle d'origine et une description des effets secondaires potentiels d'une opération sur le modèle.Lorsqu'un fournisseur d'équipe tente une fusion en arrière-plan, il effectue les opérations suivantes :
L'affichage des éléments de modèle dans le contexte d'une opération d'équipe est rendu possible grâce à l'infrastructure du navigateur commun.
Les étapes précédentes permettront aux modèles d'apparaître dans les boîtes de dialogue utilisées par les opérations d'équipe. Il existe d'autres étapes obligatoires pour l'intégration dans un aperçu de fusion.
Les améliorations suivantes ont été apportées dans le domaine de l'historique des fichiers et des éléments de modèle :
Les éléments suivants ont été fournis pour prendre en charge la navigation à distance :
Les fournisseurs d'équipe peuvent décorer les éléments de modèle en convertissant leurs décorateurs simples de façon à ce qu'ils fonctionnent pour les mappages de ressources exactement comme les contributions d'objets sont converties pour fonctionner pour les mappages de ressources. Toutefois, un aspect de la décoration d'éléments de modèle logique pose problème. Si un élément de modèle ne possède pas un mappage un à un sur une ressource, l'élément de modèle risque de ne pas recevoir de mise à jour de modèle lorsque les ressources sous-jacentes seront modifiées.
Pour résoudre cet incident, l'élément ITeamStateProvider
a été introduit afin de permettre aux fournisseurs de modèle d'accéder aux modifications d'état susceptibles d'affecter les décorations d'équipe. Par ailleurs, les vues de modèle peuvent utiliser un élément SynchronizationStateTester
pour déterminer lorsque les libellés des éléments de modèle logique doivent être mis à jour. Cette API recourt à l'interface ITeamStateProvider
afin de déterminer lorsque l'état d'équipe de la ressource a changé et lorsqu'il peut être transmis à un décorateur d'équipe dans le cadre d'un IDecorationContext
.