邏輯模型整合的模型導覽圖

以下是模型提供者能夠執行哪些動作來利用團隊邏輯模型支援的清單:

  1. 配合 ResourceMapping 來改寫模型視圖中的模型元素,讓基於資源的作業能夠出現在模型元素上。
  2. 登錄 ModelProvider 來確保在模型的相關資源上執行作業時,會顧及您的模型。
  3. 在資源上執行作業時使用 ResourceChangeValidator,以確保使用者能得知這些資源的相關模型元素所可能受到的任何負面影響。
  4. 實作 IResourceMappingMerger 來參與涉及模型相關資源的無監視器型合併。
  5. 登錄 teamContentProvider 來參與「團隊」檢視器(如合併預覽)。
  6. 提供 IHistoryPageSource 來將邏輯模型歷程顯示在「團隊歷程」視圖中。
  7. 利用 Eclipse 檔案系統 API 來存取模型專案的遠端狀態。
  8. 利用 SynchronizationStateTester API 來確保與資源沒有 1:1 對映的模型元素會有適當的裝飾。

下列各節會分別詳細說明這幾點。 org.eclipse.team.examples.filesystem 外掛程式含有一個範例,可以說明若干這些要點。 您可以從 CVS 儲存庫移出專案,用它來作為閱讀這份教學指導時的參考資料。免責聲明:這個範例外掛程式中的程式碼可能會在一段時間之後有所改變。 如果要取得符合這個範例所用內容的副本,您可以利用 3.2 版標示(很可能是 R3_2)或 2006 年 6 月 28 日的日期標示來移出專案。

資源對映

基本資源對映 API

資源對映 API 有意簡化,省略了邏輯模型的操作。 用戶端無法利用這個介面來顯示邏輯模型,或取得任何其他有用的相關知識。 它的目的是簡化成將一或多個模型元素對映至工作區資源。

這個 API 由下列類別組成:

在資源對映中,有兩類應該有用的外掛程式。 一種是提供模型的外掛程式,且所提供的模型由工作區資源組成或持續保存在工作區資源中,一種是想要在資源上執行作業的外掛程式。 下一節討論前面一種,邏輯模型整合的儲存庫導覽圖會討論後面一種。

改寫模型來配合 ResourceMapping

如果物件如何改寫來配合資源的說明越豐富越好,改寫模式物件來配合 IResource,以便將特定資源專用動作顯示在快速功能表的外掛程式,現在可以配合 ResourceMapping 來改寫。 不過,如果沒有好處,便不需要如此。 例如,目前配合 IFile 的 Java 編譯單元(也就是 JDT 視圖所顯示的 *.java 檔)不需要改成配合 ResourceMapping,因為沒有好處。 不過,Java 套件應該配合 ResourceMapping,以便指出套件只由對應資料夾中的檔案組成,子資料夾不包括在內。

使用配接器 Factory 是配合資源對映來改寫模型元素的偏好方式。 以下是在外掛程式 Manifest 中提供配接器 Factory 的 XML 標記。

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

配接器 Factory 實作看起來會如下:

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

模型物件可以實作 IAdaptable 介面。 當它們實作這個介面時,它們必須確定咨詢了平台配接器管理者。 繼承 PlatformObject 或使用下列程式碼行,便可以完成這項作業:

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

以上是偏好的方法。 不過,模型物件可以實作 IAdaptable 介面及提供所建立的 getAdapter(Class) 實作,當要求 ResourceMapping 實例時,它會明確傳回一個。 這是比較直接而明確的方法,但卻最不好,因為模型必須明確瞭解配合資源來進行的改寫作業。

在某些情況下,邏輯模型的提供者可能不想讓它們的模型在每個環境定義中都配合 IResource,或者關於提供物件,相對於其他環境定義,邏輯模型提供者也可能會想讓物件以不同的方式來配合。 工作台使用者介面為了這個目的,提供了特殊的中間配接器 API IContributorResourceAdapter。 當在提供物件的環境定義中,正在配合 IResource 來改寫物件之時,工作台會先嘗試配合 IContributorResourceAdapter 來改寫資源,之後,才會嘗試直接配合 IResource 來改寫。 IContributorResourceAdapter2 是這個介面的新的子介面,它提供了與 ResourceMapping 相同的功能。 不同之處,只有模型提供者應該登錄 IContributorResourceAdapter 的 Factory,因為工作台會執行 instanceof 檢查,以瞭解所提供的配接器是否也是 IContributorResourceAdapter2 的實例。

Java 套件 ResourceMapping 子類別的實作看起來應該如下。

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

這是一項直接而明確的對映,因此,實作並不複雜。 當然,不同模型的資源對映實作,會有各不相同的複雜度。

資源對映環境定義

「資源對映 API」的好處之一,是它容許外掛程式在資源對映方面,實作它們所需要的任何作業(如 CVS 更新、CVS 確定、CVS 標示、用過的裝飾等)。不過,目前所引進的 API 只會處理模型的本端狀態。 當使用可能有開發人員在共用的模型時,您會進入模型的遠端狀態(也就是另一位使用者已移入儲存庫之模型的狀態)不同於工作區狀態的情況。 如果您執行 CVS 更新,您會想要模型的本端狀態符合遠端狀態,即使這代表了必須併入或刪除一些檔案,也是如此。

對某些邏輯模型而言,這不是問題。 比方說,Java 套件便是被造訪到某個深度的儲存檔案,不論模型的遠端狀態為何,都是如此。 在這個情況下,儲存庫提供者可以輕易判斷在確定時應該併入送出刪除,在更新時應該併入送入新增。 不過,構成某些邏輯模型的資源可能會隨著時間而改變。 例如,構成模型元素的資源可能會相依於 Manifest 檔(或其他類似機制)的內容。 為了使資源對映傳回適當的遍訪,它必須存取 Manifest 檔的遠端內容(如果不同於本端內容的話),以便瞭解是否需要併入其他資源。 這些其他資源不一定會在工作區中,但儲存庫提供者會知道在執行所選取動作時,如何確定它們在工作區中。

如果要支援這些比較複雜的模型,您可以將 RemoteResourceMappingContext 傳給 ResourceMapping#getTraversals 方法。 當提供環境定義時,對映可以利用它來確定遍訪併入了所有必要的資源。 如果未提供環境定義,對映可能假設只有本端狀態有用。

ResourceMapping 何時需要考量 RemoteResourceMappingContext?

ResourceMapping 只需要擔心提供給 getTraversals 方法的環境定義,以防組成模型的資源隨著時間而改變,而保證將組成模型的這些資源(也只有這些資源)封裝起來的簡式遍訪卻無法說明模型和資源之間的關係。 例如,雖然 Java 套件的資源可能隨著時間而改變,套件仍可以被說明為深度為 1 的資料夾,因此,Java 套件的資源對映仍可以使用資源對映的環境定義。

我們設想一個比較複雜的範例:含有若干影像的 HTML 檔。 我們假設 HTML 檔所參照的任何影像都屬於這個檔案的模型。 當從儲存庫更新 HTML 檔的本端內容時,使用者會預期任何新的影像都包括在內。HTML 檔案模型 ResourceMappinggetTraversals 方法看起來會類似於:

public class HTMLResourceMapping extends ResourceMapping {
private HTMLFile htmlFile;
public ResourceTraversal[] getTraversals(ResourceMappingContext context,
IProgressMonitor monitor)
IResource[] resources = htmlFile.getResources();
if (context instanceof RemoteResourceMappingContext) {
// Look for any additional resources on the 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);
}
}
y return new ResourceTraversal[] {
new ResourceTraversal(resources, IResource.DEPTH_ZERO, IResource.NONE)};
}
}

請注意,模型包括兩組資源:在工作區中從 HTML 檔本端內容衍生而來的資源,以及取自遠端檔案和基本檔案內容的資源。 這兩組資源都可能有不在工作區中的資源。 例如,本端 HTML 檔可能含有相對鏈結,通往不在工作區中的影像。 您應該併入這項資源,以便當它在遠端時,能夠提取它。 至於遠端檔案,它可能含有新副本,參照下載新遠端內容時所應提取的其他影像。

模型提供者

模型提供者用來將相關資源對映分成一組的方法。 以下是通往 ModelProvider 類別的鏈結。 這個類別有三個主要用途:

  1. 從模型提供者中,用戶端可以利用適應性機制來取得其他 API 片段,以便在一組資源對映上執行作業。 例如,模型的 IResourceMappingMerger 便是改寫模型提供者而取得。
  2. 在取得一組檔案系統資源之後,用戶端可以查詢模型提供者是否有模型元素持續保存在這些資源中,如果有,便取得一組說明關係的資源對映。
  3. 對於在一組資源上執行的作業,資源變更驗證器會查詢模型提供者,以判斷作業是否可能有任何使用者應該知道的負面影響。 變更驗證一節有這方面的討論。

以下是 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>

LibraryModelProviderModelProvider 的子類別。 啟用規則用來比對「程式庫」模型將它的模型持續保存在其中的資源。 在上述範例中,模型提供者會比對含程式庫本質之專案中的任何資源。

定義好模型提供者之後,應該置換 ResourceMapping#getModelProviderId() 方法來傳回模型提供者的 ID。

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

對於符合提供者啟用規則的資源,如果要取得資源對資源的對映之適當倒轉對映,您也應該置換兩個 getMapping 方法或其中之一。 您必須置換的方法會隨著模型是否有元素含有多項資源而不同。 如果您的模型元素對映至單一資源,您可以置換接受單一 IResource 引數的方法。 否則,您必須置換接受資源陣列的方法。 以下是使用單一資源案例的範例。

下列範例方法將程式庫模型檔包裝在適當的資源對映中。 另外,它也包裝了一些資料夾,其中含有對模型提供者有用的檔案。

public class LibraryModelProvider extends ModelProvider {
public ResourceMapping[] getMappings(IResource resource,
ResourceMappingContext context, IProgressMonitor monitor) {
if (isModelFile(resource)) {
// Return a resource mapping on the file
return new LibraryResourceMapping(resource);
} if (containsModelFiles(resource)) {
// Create a deep resource mapping on the container
return new LibraryContainerResourceMapping(resource);
}
// The resource is not of interest to this model provider
return null;
}
}

之後,用戶端便可以存取模型提供者來判斷模型提供者是否在意即將處理的資源。 下一節說明將提供給團隊作業的 API,這些團隊作業利用模型提供者 API 來判斷在一組所選資源或模型元素上執行團隊作業時,所要處理的整組資源對映。

資源變更驗證

在資源上執行的作業,應該先進行驗證,以確保使用者會得知任何可能的負面影響。 以下是驗證資源變更所需要的步驟。

  1. 利用 IResourceChangeDescriptionFactory 來建置變更的說明。 Factory 會產生一個 IResourceDelta 來鏡映作業執行之後,所產生的資源差異外觀。
  2. 利用 ResourceChangeValidator 來驗證變更。 驗證器會咨詢所有登錄為對受影響的資源有興趣的模型提供者。 結果是一或多個狀態,這些狀態含有起源模型的 ID 及作業對模型所可能造成之負面影響的說明。
  3. 讓使用者知道作業起始者所不知道的模型所可能帶來的負面影響。 比方說,如果 Java 重構收到 Java 模型的負面影響,可能會忽略它,因為重構瞭解 Java 模型的語意。 不過,如果傳回來自「程式庫」模型的負面影響,使用者應該要知道它,因為 Java 對於「程式庫」模型一無所知。

基於模型的合併

當團隊提供者嘗試無監視器型合併時,它會執行下列動作:

  1. 從所選元素取得資源對映
  2. 利用 ResourceMapping#getModelProvider() 方法來判斷所涉及的模型提供者。
  3. 展開作業範圍來併入所有必要的資源對映。
  4. 建置本端和遠端之間同步化狀態的說明。這個說明是透過 IMergeContext API 來提供給模型。
  5. 配合 IResourceMappingMerger 來改寫模型提供者。
  6. 在每個合併者上呼叫 validateMerge 方法,傳入 synchronization 說明,以確保不會有可能造成無法嘗試合併的情況。
  7. 將合併委派給模型合併者來執行合併。
  8. 如果「模型提供者」只要控制合併的順序,或可能自己執行合併,並在完成時將信號傳給團隊提供者,「模型提供者」可以將個別檔案的合併重新委派給「團隊提供者」。

團隊作業視圖中的模型內容

在「團隊作業」的環境定義中,模型元素的顯示是因「共用導覽器」架構而成為可能。

上述步驟可讓模型出現在團隊作業所用的對話框中。整合到合併預覽中,還需要一些其他步驟。

「歷程」視圖

在檔案歷程和模型元素歷程的區域中,已進行了下列改進:

遠端瀏覽

已提供下列項目來支援遠端瀏覽:

利用團隊狀態裝飾模型元素

「團隊提供者」可以依照將提供物件轉換成適用於資源對映的相同方式,將它們的小型裝飾元轉換成適用於資源對映,以裝飾模型元素。 不過,邏輯模型元素裝飾有一個方面有問題。 如果模型元素與資源沒有 1:1 的對映,當基礎資源變更時,模型元素可能不會收到標籤更新。

為了處理這個問題,引進了 ITeamStateProvider,使模型提供者能夠存取可能會影響到團隊裝飾的狀態變更。 另外,模型視圖也可以利用 SynchronizationStateTester 來判斷何時需要更新邏輯模型元素的標籤。 這個 API 依賴 ITeamStateProvider 介面來判斷資源團隊狀態的變更時間,它可以傳遞給團隊裝飾元,而成為 IDecorationContext 的一部分。