Hieronder vindt u een lijst met de acties die modelproviders kunnen ondernemen om te profiteren van ondersteuning voor logische modellen van teams:
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.
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:
Object getModelObject()
: het modelobject waarvan de toewijzing is afgeleid (of aangepast).ResourceTraversal[]
getTraversals(ResourceMappingContext, IProgressMonitor)
: de resource-uitvoering die de resources beslaat die het modelobject vormen.ResourceTraversal
bevat een set met resources en een dieptevlag die de diepte aangeeft waarop de resources in de uitvoering aan het oorspronkelijke modelobject zijn gekoppeld. Resource-uitvoeringen worden door een resourcetoewijzing aan een client verstrekt om de content van een model op zo'n manier te beschrijven dat de client (bijvoorbeeld een repositoryprovider) zijn bewerkingen zo efficiënt mogelijk kan uitvoeren. De volgende methoden zijn van belang:
getResources()
getDepth()
ResourceMappingContext
en RemoteResourceMappingContext
is iets gecompliceerder en wordt beschreven in de sectie Resourcetoewijzingscontext.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.
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.
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.
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 bieden een manier om gerelateerde resourcetoewijzingen samen te groeperen. Dit is een link naar de klasse ModelProvider. Deze klasse heeft drie belangrijke functies:
IResourceMappingMerger
voor het model wordt bijvoorbeeld verkregen door de modelprovider aan te passen.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.
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.
IResourceChangeDescriptionFactory
.
De factory maakt een IResourceDelta
die weerspiegelt hoe de resulterende resourcedelta eruit zal komen te zien nadat de bewerking is uitgevoerd.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.Wanneer een teamprovider een naamloze samenvoeging probeert uit te voeren, gaat deze als volgt te werk:
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.
Op het gebied van bestandshistorie en modelelementhistorie zijn de volgende verbeteringen aangebracht:
Voor de ondersteuning van bladeren op afstand worden de volgende functies geleverd:
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
.