Modelwegwijzer voor logische modelintegratie

Hieronder vindt u een lijst met de acties die modelproviders kunnen ondernemen om te profiteren van ondersteuning voor logische modellen van teams:

  1. Modelelementen in modelviews aanpassen aan ResourceMapping om op resources gebaseerde bewerkingen in uw modelelementen te laten verschijnen.
  2. Een ModelProvider registreren om ervoor te zorgen dat uw model wordt geraadpleegd wanneer bewerkingen worden uitgevoerd aan de resources die aan uw model zijn gerelateerd.
  3. Gebruik de ResourceChangeValidator wanneer u bewerkingen op resources uitvoert om ervoor te zorgen dat mogelijke neveneffecten op de modelelementen die zijn gerelateerd aan de desbetreffende resources, aan de gebruiker bekend worden gemaakt.
  4. Implementeer een IResourceMappingMerger om deel te kunnen nemen aan naamloze samenvoegingen waarbij resources die aan uw model zijn gerelateerd betrokken zijn.
  5. Registreer een teamContentProvider om deel te kunnen nemen aan teamviewers, zoals previews van samenvoegingen.
  6. Geef een IHistoryPageSource op om de historie van het logische model weer te geven in de view Teamhistorie.
  7. Gebruik de Eclipse-bestandssysteem-API om toegang te krijgen tot de status op afstand van modelprojecten.
  8. Gebruik de SynchronizationStateTester-API om ervoor te zorgen dat de modelelementen op de juiste wijze zijn gedecoreerd en dat ze geen één-op-één toewijzing hebben met resources.

In de volgende secties worden al deze punten gedetailleerder beschreven. De plugin org.eclipse.team.examples.filesystem bevat een voorbeeld dat verschillende van deze punten illustreert. U kunt het project uit de CVS-repository reserveren en als naslag gebruiken tijdens het lezen van deze zelfstudie. Let op: de broncode in de voorbeeldplugins kan van tijd tot tijd worden gewijzigd. Als u een exemplaar wilt bemachtigen dat met dit voorbeeld overeenkomt, kunt u het project reserveren met de 3.2-versiecode (waarschijnlijk R3_2) of de datumcode 28 juni 2006.

Resourcetoewijzingen

De basisresourcetoewijzings-API

De resourcetoewijzings-API is met opzet eenvoudig en logische modelbewerkingen zijn eruit weggelaten. Deze interface kan niet door een client worden gebruikt om logische modellen weer te geven of er interessante aanvullende kennis over op te doen. Het doel ervan is eenvoudigweg om een of twee modelelementen aan werkgebiedresources toe te wijzen.

De API bestaat uit de volgende klassen:

Er zijn twee typen plugins waarvoor resourcetoewijzingen interessant zouden moeten zijn. Plugins die een model leveren dat bestaat uit resources of resources bevat in het werkgebied en plugins die bewerkingen op resources willen uitvoeren. Het eerste type plugin wordt besproken in de volgende sectie, en het tweede type in de sectie Repositorywegwijzer voor logische modelintegratie.

Een model aanpassen aan een ResourceMapping

Plugins die hun modelobjecten aan IResource hebben aangepast om resource-specifieke acties in het voorgrondmenu af te beelden, kunnen zich nu aan ResourceMapping aanpassen als een rijkere omschrijving van hoe het object zich aan resources aanpast nuttig is. Ze zijn echter niet verplicht om dit te doen als het geen voordelen oplevert. Een Java-compilatie-eenheid (dit is een *.java-bestand weergegeven in een JDT-view) dat zich momenteel aan IFile aanpast, hoeft zich bijvoorbeeld niet aan ResourceMapping aan te passen, aangezien dit geen enkel voordeel oplevert. Een Java-pakket moet zich echter aan ResourceMapping aanpassen om aan te geven dat het pakket alleen uit de bestanden in de bijbehorende map bestaat, en niet uit de submappen.

De voorkeursmethode om modelelementen aan een resourcetoewijzing aan te passen, is door een adapterfactory te gebruiken. Hieronder volgt de XML-opmaak voor het toevoegen van een adapterfactory aan een pluginmanifest.

   <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>

De adapterfactory zou er ongeveer als volgt uitzien:

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};
}
}

Modelobjecten kunnen de interface IAdaptable implementeren. Wanneer zij dit doen, moeten zij ervoor zorgen dat de Platformadaptermanager wordt geraadpleegd. Dit kan worden gedaan door een subklasse te maken van PlatformObject of door de volgende coderegel te gebruiken:

Platform.getAdapterManager().getAdapter(Object, Class)

De bovenste is de voorkeursbenadering. Het modelobject kan echter de interface IAdaptable implementeren en een implementatie van getAdapter(Class) bieden die een instance van ResourceMapping maakt indien daarom expliciet wordt gevraagd. Dit is een directere benadering, maar de minst wenselijke, aangezien het model expliciete kennis moet hebben van de aanpassing aan resources.

In sommige gevallen wil de provider van een logisch model mogelijk niet dat zijn model in elke context wordt aangepast aan IResource of wil deze het object misschien anders aanpassen voor objectbijdragen dan voor andere contexten. De workbenchgebruikersinterface biedt een speciale intermediaire adapter-API, IContributorResourceAdapter, voor dit doel. Wanneer objecten worden aangepast aan IResource in de context van objectbijdragen, probeert de workbench eerst de resource aan te passen aan IContributorResourceAdapter voordat wordt geprobeerd om IResource direct aan te passen. Er is een nieuwe subinterface van deze interface, IContributorResourceAdapter2, toegevoegd, die dezelfde voorziening biedt voor ResourceMapping. Het enige verschil is dat de modelprovider een factory moet registreren voor IContributorResourceAdapter aangezien de workbench een instanceof-controle doet om te zien of de toegevoegde adapter ook een instance van IContributorResourceAdapter2 is.

De implementatie van de subklasse ResourceMapping voor een Java-pakket zou er ongeveer als volgt uitzien.

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)
}
}
}

Dit is een vrij directe toewijzing en daarom is de implementatie niet complex. De complexiteit van de resourcetoewijzingsimplementatie zal uiteraard van model tot model variëren.

Resourcetoewijzingscontext

Een van de voordelen van een resourcetoewijzings-API is dat het plugins de mogelijkheid biedt om de gewenste bewerkingen uit te voeren in termen van resourcetoewijzingen (bijvoorbeeld CVS-update, CVS-commit, CVS-tag, gewijzigde decoratie, enzovoort). De API die tot dusverre is besproken, houdt zich echter alleen bezig met de lokale status van het model. Wanneer u werkt met een model dat tussen ontwikkelaars kan worden gedeeld, belandt u in een situatie waarin de status op afstand van het model (dit is de status van het model dat een andere ontwikkelaar in de repository heeft ingecheckt) mogelijk anders is dan de status in het werkgebied. Als u een CVS-update hebt uitgevoerd, wilt u dat de lokale status van het model overeenkomt met de status op afstand, zelfs als dit zou betekenen dat aanvullende bestanden moeten worden opgenomen of sommige bestanden moeten worden verwijderd.

Dit is geen probleem voor bepaalde logische modellen. Een Java-pakket is bijvoorbeeld een container die wordt bezocht tot een diepte van één, ongeacht de status op afstand van het model. Met dit gegeven kan een repositoryprovider eenvoudig vaststellen dat uitgaande verwijderingen moeten worden opgenomen bij het vastleggen of dat inkomende aanvullingen moeten worden opgenomen bij het bijwerken. De resources die bepaalde logische modellen vormen, kunnen echter wijzigen na verloop van tijd. De resources die een modelelement vormen, hangen bijvoorbeeld mogelijk af van de content van een manifestbestand (of een ander vergelijkbaar mechanisme). Om de resourcetoewijzng de juiste uitvoering te laten retourneren, moet deze de content op afstand van het manifestbestand openen (als dit verschilt van de lokale content) om te zien of er aanvullende resources zijn die moeten worden opgenomen. Deze aanvullende resources bestaan mogelijk niet in het werkgebied, maar de repositoryprovider weet hoe hij er zeker van kan zijn dat deze wel aanwezig waren op het moment dat de geselecteerde actie is uitgevoerd.

Voor de ondersteuning van deze complexere modellen kan een RemoteResourceMappingContext worden doorgegeven aan de methode ResourceMapping#getTraversals. Wanneer een context wordt verstrekt, kan de toewijzing deze gebruiken om te controleren of alle noodzakelijke resources in de toewijzing zijn opgenomen. Als er geen context is verstrekt, kan de toewijzing aannemen dat alleen de lokale status van belang is.

Wanneer moet een ResourceMapping zich zorgen maken over de RemoteResourceMappingContext?

Een ResourceMapping hoeft alleen rekening te houden met een context die aan de methode getTraversals is verstrekt in gevallen waarin de resources die een model vormen na verloop van tijd veranderen en de relatie tussen het model en de resources niet kan worden beschreven door een eenvoudige uitvoering waarvan zeker is dat deze die resources bevat (en alleen die resources) die het model vormen. Hoewel de resources van een Java-pakket bijvoorbeeld na verloop van tijd kunnen veranderen, kan het pakket als een map met een diepte van één worden beschreven, zodat een resourcetoewijzing voor Java-pakketten geen gebruik hoeft te maken van de resourcetoewijzingscontext.

Nu een gecompliceerder voorbeeld: een HTML-bestand met meerdere afbeeldingen. Laten we aannemen dat alle afbeeldingsverwijzingen in een HTML-bestand onderdeel vormen van het model van dat bestand. Wanneer de lokale content van het HTML-bestand wordt bijgewerkt vanuit een repository, zou de gebruiker verwachten dat alle nieuwe afbeeldingen zijn opgenomen. De methode getTraversals voor een ResourceMapping voor het HTML-bestandsmodel zou er ongeveer als volgt uitzien:

public class HTMLResourceMapping extends ResourceMapping {
private HTMLFile htmlFile;
public ResourceTraversal[] getTraversals(ResourceMappingContext context,
IProgressMonitor monitor)
IResource[] resources = htmlFile.getResources();
if (context instanceof RemoteResourceMappingContext) {
// Zoeken naar aanvullende resources op de server
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)};
}
}

Merk op dat er twee sets met resources in het model zijn opgenomen: degene die zijn afgeleid van de lokale content van het HTML-bestand in het werkgebied en degene die uit de content van het bestand op afstand en het basisbestand zijn afgeleid. In beide sets kunnen resources zijn die niet in het werkgebied aanwezig zijn. Het lokale HTML-bestand kan bijvoorbeeld een relatieve link bevatten naar een afbeelding die niet in het werkgebied aanwezig is. Deze resource moet worden opgenomen, zodat deze kan worden opgehaald als deze op afstand bestaat. Wat betreft het bestand op afstand, dit kan een nieuwe kopie bevatten die naar aanvullende afbeeldingen verwijst die moeten worden opgehaald wanneer de nieuwe content op afstand wordt gedownload.

Modelproviders

Modelproviders bieden een manier om gerelateerde resourcetoewijzingen samen te groeperen. Dit is een link naar de klasse ModelProvider. Deze klasse heeft drie belangrijke functies:

  1. Clients kunnen van een modelprovider vervolgens aanvullende stukjes API verkrijgen voor het uitvoeren van bewerkingen op een set met resourcetoewijzingen met behulp van het aanpasbare mechanisme. De IResourceMappingMerger voor het model wordt bijvoorbeeld verkregen door de modelprovider aan te passen.
  2. Met een set bestandssysteemresources kunnen clients opvragen of een modelprovider modelelementen heeft opgenomen in deze resources en, als dit het geval is, de set met resourcetoewijzingen verkrijgen die de relatie beschrijft.
  3. Voor bewerkingen op een set resources vraagt de validator voor resourcewijzigingen de modelproviders op om vast te stellen of er mogelijke neveneffecten van een bewerking zijn waar gebruikers van op de hoogte moeten zijn. Dit wordt behandeld in een aparte sectie over wijzigingen valideren.

Dit is een voorbeeld van de definitie van het extensiepunt modelProvider:

   <extension
id="modelProvider"
name="Bibliotheekvoorbeeld"
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>

De LibraryModelProvider is een subklasse van ModelProvider. De beschikbaarheidsregel wordt gebruikt om resources toe te wijzen die het bibliotheekmodel in het model ervan opneemt. In het bovenstaande voorbeeld zal de modelprovider elke resource in een project toewijzen dat van het soort bibliotheek is.

Als de modelprovider eenmaal is gedefinieerd, moet de methode ResourceMapping#getModelProviderId() worden vervangen om het ID van de modelprovider te retourneren.

   public String getModelProviderId() {
return "org.eclipse.team.examples.library.adapt.modelProvider";
}

Om de juiste omgekeerde toewijzing van resource-naar-resourcetoewijzing te verkrijgen voor de resources die overeenkomen met de beschikbaarheidsregel van de provider, moet u ook een van of beide getMapping-methoden wijzigen. Welke methode u moet wijzigen, hangt af van de vraag of uw model elementen heeft die wel of niet meerdere resources bevatten. Als uw modelelementen worden toegewezen aan een enkele resource, kunt u de methode wijzigen die een enkel IResource-argument accepteert. Anders moet u de methode vervangen die een array van resources accepteert. Hieronder volgt een voorbeeld van het geval van de enkele resource.

In de volgende voorbeeldmethode wordt een bibliotheekmodelbestand in de juiste resourcetoewijzing opgenomen. Ook worden mappen opgenomen die bestanden bevatten die van belang zijn voor de modelprovider.

public class LibraryModelProvider extends ModelProvider {
public ResourceMapping[] getMappings(IResource resource,
ResourceMappingContext context, IProgressMonitor monitor) {
if (isModelFile(resource)) {
// Een resourcetoewijzing retourneren naar het bestand
return new LibraryResourceMapping(resource);
} if (containsModelFiles(resource)) {
// Een diepe resourcetoewijzing maken in de container
return new LibraryContainerResourceMapping(resource);
}
// De resource is niet van belang voor deze modelprovider
return null;
}
}

Clients kunnen vervolgens toegang krijgen tot de modelprovider om vast te stellen of de modelprovider belang heeft bij de resources die op het punt staan om te worden bewerkt. In de volgende sectie wordt de API beschreven die wordt verstrekt voor teambewerkingen die de modelprovider-API gebruiken om de volledige set resourcetoewijzingen vast te stellen die moet worden bewerkt wanneer een teambewerking wordt uitgevoerd op een set geselecteerde resources of modelelementen.

Resourcewijzigingen valideren

Bewerkingen die op resources worden uitgevoerd, moeten eerst worden gevalideerd om er zeker van te zijn dat de gebruiker op de hoogte is van mogelijke neveneffecten. Hieronder volgen de stappen die vereist zijn om een resourcewijziging te valideren.

  1. Stel een beschrijving op van de wijziging met behulp van de IResourceChangeDescriptionFactory. De factory maakt een IResourceDelta die weerspiegelt hoe de resulterende resourcedelta eruit zal komen te zien nadat de bewerking is uitgevoerd.
  2. Valideer de wijziging met behulp van de ResourceChangeValidator. De validator consulteert alle modelproviders waarvan is geregistreerd dat deze een belang hebben bij de desbetreffende resources. Het resultaat wordt gevormd door een of meer statuswaarden met het ID van het oorspronkelijke model en een beschrijving van de mogelijke neveneffecten op het model.
  3. Stel de gebruiker op de hoogte van alle mogelijke neveneffecten van modellen die onbekend zijn bij de uitvoerder van de bewerking. Als bijvoorbeeld een Java-herstructurering een neveneffect heeft ontvangen van het Java-model, kan deze worden genegeerd, aangezien de herstructurering de semantiek van het Java-model begrijpt. Als echter een neveneffect van het bibliotheekmodel wordt geretourneerd, moet de gebruiker hiervan op de hoogte worden gesteld, aangezien Java geen kennis heeft van het bibliotheekmodel.

Samenvoegen op basis van modellen

Wanneer een teamprovider een naamloze samenvoeging probeert uit te voeren, gaat deze als volgt te werk:

  1. De resourcetoewijzingen ophalen uit de geselecteerde elementen.
  2. Vaststellen welke modelproviders betrokken zijn bij het gebruik van de methode ResourceMapping#getModelProvider().
  3. Het bereik van de bewerking uitbreiden om alle noodzakelijke resourcetoewijzingen op te nemen.
  4. Een beschrijving opstellen van de synchronisatiestatus tussen lokaal en op afstand. Deze beschrijving wordt aan de modellen verstrekt via de IMergeContext-API.
  5. De modelproviders aanpassen aan IResourceMappingMerger.
  6. De methode validateMerge oproepen voor elke samenvoeging, waarbij de synchronisatiebeschrijving wordt doorgegeven om ervoor te zorgen dat er geen voorwaarde is die de gewenste samenvoeging kan voorkomen.
  7. De samenvoeging delegeren aan de modelsamenvoegers om de samenvoeging uit te voeren.
  8. Modelproviders kunnen de samenvoeging van afzonderlijke bestanden terug naar de teamprovider delegeren als zij alleen de volgorde van de samenvoeging willen bepalen of de samenvoeging zelf willen uitvoeren en aan de teamprovider aangeven wanneer deze gereed zijn.

Modelcontent in teambewerkingsviews

De weergave van modelelementen in de context van een teambewerking wordt mogelijk gemaakt door het algemene navigatornetwerk.

De bovenstaande stappen stellen de modellen in staat om te worden afgebeeld in dialoogvensters die door teambewerkingen worden gebruikt. Voor integratie in een samenvoegingspreview zijn aanvullende stappen nodig.

Historieview

Op het gebied van bestandshistorie en modelelementhistorie zijn de volgende verbeteringen aangebracht:

Bladeren op afstand

Voor de ondersteuning van bladeren op afstand worden de volgende functies geleverd:

Modelelementen decoreren met teamstatus

Teamproviders kunnen modelelementen decoreren door hun lichtgewicht decorators te converteren om op dezelfde manier te werken met resourcetoewijzingen als objectbijdragen worden geconverteerd om voor resourcetoewijzingen te kunnen worden gebruikt. Er is echter een aspect van logische modelelementdecoratie die problematisch is. Als een model geen één-op-één toewijzing met een resource heeft, ontvangt het modelelement mogelijk geen labelupdate wanneer de onderliggende resource wijzigt.

Om dit probleem aan te pakken, is de ITeamStateProvider geïntroduceerd om modelproviders toegang te bieden tot statuswijzigingen die mogelijk van invloed zijn op teamdecoraties. Bovendien kunnen modelviews een SynchronizationStateTester gebruiken om vast te stellen wanneer de labels van logische modelelementen moeten worden bijgewerkt. Deze API is afhankelijk van de interface ITeamStateProvider om vast te stellen of de teamstatus is gewijzigd en kan worden doorgegeven aan een teamdecorator als onderdeel van IDecorationContext.