Az alábbiakban látható, hogy mit tehetnek a modellszolgáltatók a Csapat logikai modelltámogatás előnyeinek kihasználása érdekében:
Az alábbi szakaszok részletesen tárgyalják az előzőekben ismertetett pontok mindegyikét. Számos pont működésének bemutatására az org.eclipse.team.examples.filesystem bedolgozó tartalmaz példákat. A projektet ki lehet iktatni a CVS lerakatból, és használható hivatkozásként az ismertető olvasása közben. Jogkizárási nyilatkozat: A példabedolgozókban lévő forráskód változhat. A példában használtnak megfelelő másolat megszerzéséhez a 3.2 verzióhoz tartozó címke (általában R3_2) vagy a 2006. június 28. dátum címke segítségével ellenőrizheti a projektet.
Az erőforrás-leképező API szándékosan egyszerű, ki vannak belőle hagyva a logikai modellkezelések. Az ügyfél az adott felület segítségével nem tudja megjeleníteni a logikai modelleket illetve nem tudja lekérdezni a velük kapcsolatos további ismereteket. Célja csupán néhány modellelem leképezése munkaterület-erőforrásokra.
Az API az alábbi osztályokból áll:
Object getModelObject()
: A modellobjektum, amelyből a
leképezés származtatva (vagy adaptálva) lett. ResourceTraversal[] getTraversals(ResourceMappingContext,
IProgressMonitor)
: Az erőforrás bejárási útja a modellobjektumot
alkotó erőforrásokat foglalja magában.
ResourceTraversal
erőforrások egy halmazát illetve egy
mélységjelzőt tartalmaz, amely azt jelöli, hogy a bejárási út erőforrásai milyen
mélységben tartoznak az eredeti modellobjektumhoz. Az erőforrás bejárási utakat az ügyfelek számára az
erőforrás-leképezések biztosítják. Céljuk, hogy a modellek tartalmát olyan
módon írják le, hogy az ügyfél (pl. egy lerakatszolgáltató) műveleteit a
lehető leghatékonyabb módon végezhesse. A fontosabb metódusok az alábbiak:
getResources()
getDepth()
ResourceMappingContext
és a
RemoteResourceMappingContext
használata egy kicsit bonyolultabb és az
Erőforrás-leképezés környezet
részben vannak leírva. Kétféle bedolgozótípus jöhet számításba az erőforrás-leképezésekkor. A első típus olyan modellt biztosít, amely tartalmazza vagy tárolja a munkaterület erőforrásait, a másik pedig olyat, amely a műveleteket akarja végrehajtani az erőforrásokon. Az első típusról a következő fejezetben olvashat, a másodikról pedig a Lerakat eligazító a logikai modell integrációhoz című fejezetben.
A bedolgozók, amelyek modellobjektumait az IResource
elemhez adaptálták a helyzetérzékeny menüben megjelenített
erőforrás-specifikus tevékenységek kihasználása érdekében, most
adaptálódhatnak a ResourceMapping
elemhez, amennyiben az
objektum erőforrásokhoz adaptálásának részletesebb leírása előnyösebb. Ha
nem származik belőle előny, akkor nem szükséges végrehajtani. Egy Java
fordítási egységnek (például egy JDT nézetben megjelenített *.java fájl)
például, amely jelenleg az IFile
elemhez adaptálódik, nem
kell az ResourceMapping
elemhez adaptálódnia, mivel semmi
előnye. A Java csomagnak azonban adaptálódnia kell a
ResourceMapping
elemhez annak jelzése érdekében, hogy a
csomag csak a megfelelő mappában lévő fájlokból áll, az almappákban lévőket nem tartalmazza.
A preferált módja egy modellelem adaptálásának az erőforrás-leképezéshez, egy illesztőgyár használata. A következő egy adaptergyár bedolgozó leírófájlban közreadására szolgáló XML leírónyelv.
<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>
Az illesztőgyár megvalósítása valahogy így nézne ki:
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};
}
}
A modellobjektumok meg tudják valósítani az IAdaptable
felületet. Ekkor meg kell róla győződniük, hogy a Platform adapterkezelőt
a rendszer figyelembe veszi. Ezt vagy a PlatformObject
továbbszármaztatásával vagy a következő kódsor használatával lehet
megtenni:
Platform.getAdapterManager().getAdapter(Object, Class)
A fenti megközelítés a kedvezőbb. Bár a modell objektum megvalósíthatja az
IAdaptable felületet és biztosíthatja a getAdapter(Class)
megvalósítást, amely létrehoz egy ResourceMapping
példányt,
ha ezt kérik. Ez egy magától érthetődő megközelítés, de
legalább a modellnek határozott tudással kell rendelkezniük az erőforrások
adaptálásával kapcsolatban.
Bizonyos esetekben elképzelhető, hogy a logikai modell szolgáltatója
nem akarja, hogy a modellje minden környezetben adaptálódjon az
IResource
elemhez vagy azt akarja, hogy az objektum másképp
adaptálódjon az objektumkiegészítésekhez, mint más környezetekhez. A munkaterület UI erre a célra biztosít egy speciális köztes
illesztő alkalmazás programozási felületet,
IContributorResourceAdapter
. Ha az objektumkiegészítések
környezetében az objektumok az IResource
elemhez
adaptálódnak, akkor a munkaterület először megpróbálja adaptálni az
erőforrásokat az IContributorResourceAdapter
elemhez, mielőtt
közvetlenül az IResource
elemhez próbálná adaptálni őket. Ennek a
felületnek egy új alfelülete, az IContributorResourceAdapter2
hozzá lett adva, amely ugyanazt a képességet biztosítja a
ResourceMapping
számára.
Az egyetlen különbség, hogy a modellszolgáltatónak regisztrálnia kell egy
gyárat az IContributorResourceAdapter
hez, mivel a
munkaterület csinál egy instanceof ellenőrzést, hogy lássa, hogy a
hozzáadott illesztő szintén egy IContributorResourceAdapter2
példány-e.
A ResourceMapping
alosztály megvalósítása a Java csomag
számára valahogy így nézne ki:
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)
}
}
}
Ez egy viszonylag magától érthetődő leképezés, így a megvalósítás nem bonyolult. Természetesen az erőforrás-leképezés megvalósításának bonyolultsága a modelltől függ.
Az erőforrás-leképezési API egyik előnye, hogy lehetővé teszi a bedolgozók számára tetszőleges, erőforrás-leképezésekhez szükséges műveletek megvalósítását (például CVS frissítés, CVS véglegesítés, CVS címke, rendezetlen sorsú kiemelés, stb.). Bárhogy is, az eddig bemutatott API csak a modell helyi állapotával foglalkozik. Ha a fejlesztők között megosztható modellt használ, akkor olyan helyzetbe kerülhet, amelyben a modell távoli állapota (például azon modell állapota, amelyet egy másik felhasználó beiktatott a lerakatba) különbözik a munkaterület állapotától. Ha CVS frissítést hajtott végre, akkor szükség lehet arra, hogy a modell helyi állapota abban az esetben is megfeleljen a távoli állapotnak, ha ez azt jelenti, hogy további fájlokat kell felvenni vagy néhány fájlt el kell távolítani.
Ez néhány logikai modell esetében nem kérdés. Például a java csomagok 1-es mélységig vizsgált tárolók, a modell távoli állapotától függetlenül. Ezt figyelembe véve a lerakatszolgáltatók könnyen meghatározhatják, hogy a kimenő törléseket véglegesítéskor végre kell-e hajtani, illetve hogy a bejövő kiegészítéseket frissítéskor telepíteni kell-e. Azonban bizonyos esetekben a logikai modelleket alkotó erőforrások idővel változhatnak. Például egy adott modellelemet alkotó erőforrások változhatnak egy leírófájl (vagy egyéb hasonló mechanizmus) tartalmának függvényében. Annak érdekében, hogy az erőforrás-leképezés a megfelelő bejárási utat adja vissza, hozzáféréssel kell rendelkeznie a távoli leírófájl tartalmához (amennyiben az eltér a helyi fájl tartalmától). A folyamat ezáltal tudja ellenőrizni, hogy léteznek-e olyan további erőforrások, amelyeket tartalmaznia kell. Lehetséges, hogy ezen további erőforrások nem léteznek a munkaterületen, de a lerakatkezelő ebben ez esetben is tudja, hogy milyen módon győződhet meg ezek létezéséről a kijelölt művelet elvégzésekor.
Az ilyen és ehhez hasonló, összetettebb modellek támogatásához egy
RemoteResourceMappingContext
adható át a
ResourceMapping#getTraversals
metódusnak. Ha környezet
is meg van adva, akkor a leképezés ennek segítségével tud meggyőződni
arról, hogy a bejárási út az összes szükséges erőforrást tartalmazza. Ha
nincs környezet megadva, akkor a leképezés feltételezheti, hogy csak a
helyi állapot érdekes.
A ResourceMapping
elemnek csak akkor kell aggódnia a
getTraversals
metódus számára biztosított környezet miatt, ha
a modellt alkotó erőforrások az idővel változnak, illetve a modell és az
erőforrások közötti kapcsolat nem írható le egy egyszerű elérési úttal,
amelyet a modell alkotó erőforrások (és csak ezen erőforrások)
tartalmazásához biztosított. Annak ellenére például, hogy a Java csomag
erőforrásai idővel változhatnak, a csomag leírható egy egy mélységű
mappaként, így a java csomagok erőforrás-leképezésének nem kell használnia
az erőforrás-leképezési környezetet.
Sokkal összetettebb példaként vegyünk egy több képet tartalmazó HTML
fájlt. Tételezzük fel, hogy a HTML fájl képhivatkozásai az adott fájl
modelljének részét képezik. A HTML fájl tartalmának lerakatból való
frissítésekor a felhasználó azt várná, hogy új képek kerülnek hozzáadásra.
A HTM fájlmodell ResourceMapping
eleméhez tartozó
getTraversals
metódus az alábbi módon nézne ki:
public class HTMLResourceMapping extends ResourceMapping {
private HTMLFile htmlFile;
public ResourceTraversal[] getTraversals(ResourceMappingContext context,
IProgressMonitor monitor)
IResource[] resources = htmlFile.getResources();
if (context instanceof RemoteResourceMappingContext) {
// További erőforrások kezelése a kiszolgálón
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)};
}
}
Figyelje meg, hogy a modellben két erőforráshalmaz van: a munkaterületen lévő HTML fájl helyi tartalmából származtatott illetve a távoli és alap fájl tartalmából lekért. Ezen halmazokban lehet olyan erőforrás, amely a munkaterületen nem létezik. A helyi HTML fájl például tartalmazhat a munkaterületen nem létező képre mutató relatív hivatkozást. Ezt az erőforrást fel kell venni, így ha távol létezik, lehívásra kerül. Távoli fájl esetén tartalmazhat egy új példányt, amely további képekre hivatkozik. Ezeket a képeket az új távoli tartalom letöltésekor le kell hívni.
A modellszolgáltatót a kapcsolódó erőforrás-leképezések csoportosítására szolgálnak. Itt egy hivatkozás a ModelProvider osztályhoz. Az osztály három fő célt szolgál:
IResourceMappingMerger
elem a modellhez például a modellszolgáltató adaptálásával kérhető le. Az alábbiakban egy modelProvider kiterjesztés meghatározásának példája látható.
<extension
id="modelProvider"
name="könyvtár példa"
point="org.eclipse.core.resources.modelProviders">
<modelProvider
class="org.eclipse.team.examples.library.adapt.LibraryModelProvider"
name="könyvtár példa"/>
<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>
A LibraryModelProvider
a ModelProvider
alosztálya.
A felkészítési szabály azon erőforrásoknak felel meg, amelyek a
modelljükben tárolják a könyvtármodellt. A fenti példában a modellszolgáltató a projekt
minden könyvtárjelleggel rendelkező erőforrásának megfelel.
Ha a modellszolgáltató meg lett adva, akkor a
ResourceMapping#getModelProviderId()
metódust újra kell
definiálni a modellszolgáltató azonosítójának visszaadása érdekében.
public String getModelProviderId() {
return "org.eclipse.team.examples.library.adapt.modelProvider";
}
Az erőforrások szolgáltató felkészítési szabályának megfelelő
erőforrás-leképezéseinek megfelelő fordított leképezéseinek
lekéréséhez a getMapping
metódusok egyikét vagy
mindegyikét újra kell definiálnia. Az újradefiniálandó metódus attól függ, hogy a modell
rendelkezik-e több erőforrást tartalmazó elemmel. Ha a modellelemek
egyetlen erőforrásra kerülnek leképezésre, akkor az egyetlen
IResource
argumentumot fogadó metódusokat újradefiniálhatja.
Ellenkező esetben újra kell definiálni az erőforrástömböt fogadó metódust.
Az alábbiakban egy erőforrást használó esetre látható példa.
A következő példa metódus egy könyvtármodellfájlt egy megfelelő
erőforrás-leképezésbe burkol be. A modellszolgáltató számára érdekes
fájlokat tartalmazó mappákat is beburkolja.
public class LibraryModelProvider extends ModelProvider {
public ResourceMapping[] getMappings(IResource resource,
ResourceMappingContext context, IProgressMonitor monitor) {
if (isModelFile(resource)) {
// Erőforrás-leképezés visszaadása a fájlon
return new LibraryResourceMapping(resource);
} if (containsModelFiles(resource)) {
// Mély erőforrás-leképezés létrehozása a tárolón
return new LibraryContainerResourceMapping(resource);
}
// Az erőforrás a modellszolgáltató számára érdektelen
return null;
}
}
Az ügyfelek ezután hozzáférhetnek a modellszolgáltatóhoz annak meghatározása érdekében, hogy a modellszolgáltató törődik-e azon erőforrásokkal, amelyeket használni kívánnak. A következő rész azon csoportműveletek számára biztosított alkalmazás programozási felületeket írja le, amelyek a modellszolgáltató alkalmazás programozási felületet használják a használandó teljes erőforrás-leképezési halmaz meghatározásához, ha egy csoportművelet kerül végrehajtásra a kiválasztott erőforrások vagy modellelemek halmazán.
Az erőforrásokon végrehajtott műveleteket először ellenőrizni kell annak biztosítása érdekében, hogy a felhasználó tisztában legyen a lehetséges mellékhatásokkal. Az alábbiakban az erőforrás-változás ellenőrzéséhez szükséges lépések láthatók.
IResourceChangeDescriptionFactory
segítségével. A gyár előállít egy IResourceDelta
elemet,
amely tükrözi, hogy az eredményül kapott erőforrás-változás hogyan fog
kinézni a művelet végrehajtásakor. ResourceChangeValidator
segítségével. Az ellenőrző minden olyan modellszolgáltatót megtekint,
amely bejegyzett érdeklődéssel rendelkezik a befolyásolt erőforrásokra
vonatkozóan. Az eredmény néhány állapot, amely az eredeti modell
azonosítóját és a művelet modellre gyakorolt lehetséges mellékhatás
leírását tartalmazza. Amikor a csoportszolgáltató megjelenítés nélküli összefésült próbál végrehajtani, a következőt teszi:
A modellelemek megjelenítését a Csoportművelet kontextusában az Általános navigátor keretrendszer teszi lehetővé.
A fenti lépések lehetővé teszik, hogy a modellek a csoportműveletek által használt párbeszédablakokban megjelenjenek. A összefésülési előképbe integráláshoz további lépések szükségesek.
A következő továbbfejlesztések történtek a fájltörténet és a modellelem-történet területén:
A következő a távoli böngészés támogatása érdekében biztosított:
A csoportszolgáltatók a modellelemek kiemeléséhez azok könnyű kiemelését átalakíthatják úgy, hogy az erőforrás-leképezéseket kezeljék - hasonlóképpen ahhoz, ahogy az objektum-hozzájárulások az erőforrás-leképezéseket kezelik. Azonban létezik a logikai modellelemek kiemelésének egy problémásabb nézőpontja is. Ha egy modellelem nem rendelkezik kölcsönösen egyértelmű erőforrás-leképezéssel, akkor előfordulhat, hogy a modellelem az alapul szolgáló erőforrások módosításakor egy címkefrissítést nem kap meg.
A probléma kiküszöbölésére bevezetésre került az
ITeamStateProvider
,
amely a modellszolgáltatók számára hozzáférést biztosít a
csoportkiemeléseket érintő állapotváltozásokhoz. Ezen kívül a
modellnézetek a
SynchronizationStateTester
segítségével meghatározhatják, hogy a logikai modellelemek címkéit mikor
kell frissíteni. Az API az ITeamStateProvider
felület alapján határozza meg, hogy az erőforrás csoportállapota mikor
változott meg, és átadható egy csoportkiemelő számára egy
IDecorationContext
részeként.