Guia de Consulta de Modelos para a Integração de Modelos Lógicos

Em seguida é apresentada uma lista dos procedimentos que os fornecedores de modelos poderão efectuar de modo a tirar partido do Suporte de modelos lógicos da equipa:

  1. Adaptar elementos de modelos nas vistas de modelos à ResourceMapping de modo a permitir que as operações baseadas em recursos sejam apresentadas nos elementos de modelos.
  2. Registar um ModelProvider para se certificar que o modelo é consultado quando as operações forem executadas em recursos relacionados com o modelo.
  3. Utilizar o ResourceChangeValidator ao executar operações em recursos de modo a assegurar que quaisquer potenciais efeitos secundários nos elementos de modelos relacionados com esse recursos são do conhecimento do utilizador.
  4. Implementar um IResourceMappingMerger de modo a participar em intercalações sem cabeçalho que envolvam os recursos relacionados com o modelo.
  5. Registar um teamContentProvider de modo a participar nos visualizadores Equipa, tais como as pré-visualizações de intercalação.
  6. Facultar um IHistoryPageSource para apresentar o histórico de modelos lógicos na vista do histórico Equipa.
  7. Utilizar a API Eclipse File System para aceder ao estado remoto dos projectos de modelos.
  8. Utilizar a API SynchronizationStateTester para assegurar a decoração adequada dos elementos de modelos que não contêm uma correlação de um-para-um com os recursos.

As secções seguintes descrevem mais detalhadamente cada um destes pontos. O plug-in org.eclipse.team.examples.filesystem contém um exemplo que ilustra vários pontos. Poderá dar saída ao projecto do repositório CVS e utilizá-lo como referência para ler este guia de iniciação. Renúncia de Responsabilidade: O código fonte nos plug-ins exemplo poderá ser alterado com o tempo. Para obter uma cópia que corresponde ao que é utilizado neste exemplo, pode verificar o projecto utilizando o identificador da versão 3.2 (provavelmente o R3_2) ou um identificador da data de 28 de Junho de 2006.

Correlações de Recursos

A API Básica de Correlações de Recursos

A API de correlações de recursos é propositadamente simples, estando omitidas as manipulações de modelos lógicos. Um cliente não pode utilizar esta interface para apresentar modelos lógicos ou para obter qualquer conhecimento adicional interessante sobre a mesma. O seu objectivo é simplesmente correlacionar um ou mais elementos de modelos com os recursos do espaço de trabalho.

A API consiste nas seguintes classes:

Existem dois tipos de plug-ins que deverão ter algum interesse nas correlações de recursos. Os plug-ins que facultam um modelo que consiste ou persiste nos recursos do espaço de trabalho e os plug-ins que pretendem executar operações nos recursos. O primeiro é abordado na secção seguinte, enquanto que o segundo é abordado no Guia de Consulta de Repositórios para a Integração de Modelos Lógicos.

Adaptar um Modelo a uma ResourceMapping

Os plug-ins que adaptaram os respectivos objectos de modelos a IResource de modo a obter acções específicas dos recursos apresentadas no menu contextual podem agora ser adaptados a ResourceMapping se uma descrição mais completa de como o objecto de adapta aos recursos for vantajosa. Contudo, se não houver qualquer vantagem, não terão de o efectuar. Por exemplo, uma unidade de compilação Java (ou seja, um ficheiro *.java apresentado numa vista JDT) que actualmente se adapta ao IFile não necessita de se adaptar à ResourceMapping, uma vez que não há vantagens. Contudo, um pacote Java deverá adaptar-se à ResourceMapping de modo a indicar que o pacote consiste apenas em ficheiros contidos na pasta correspondente e não nas sub-pastas.

A forma recomendada para adaptar os elementos de modelos a uma correlação de recursos é através da utilização de um fornecedor de adaptadores. Em seguida é apresentada uma marcação XML para a contribuição de um fornecedor de adaptadores num manifesto de plug-ins.

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

A implementação do fornecedor de adaptadores deverá ser semelhante ao seguinte:

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

Os objectos de modelos podem implementar a interface IAdaptable. Nesse caso, terão de assegurar que o gestor do adaptador da Plataforma é consultado. Este procedimento pode ser efectuado ao criar uma subclasse PlatformObject ou ao utilizar a seguinte linha de código:

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

Em cima está apresentada a abordagem recomendada. Contudo, o objecto de modelo pode implementar a interface IAdaptable e facultar uma implementação getAdapter(Class) que cria e devolve uma instância de ResourceMapping explicitamente quando esta for requerida. Isto consiste numa abordagem mais directa, sendo, porém, a menos recomendada, uma vez que o modelo tem de ter um conhecimento explícito da adaptação aos recursos.

Em alguns casos, o fornecedor de um modelo lógico poderá não pretender que o modelo se adapte ao IResource em todos os contextos ou poderá pretender que o objecto de adapte às contribuições de objectos de modo diferente do que a outros contextos. O UI da área de trabalho faculta uma API adaptadora intermédia especial, a IContributorResourceAdapter, para este fim. Quando os objectos estão a ser adaptados a IResource no contexto das contribuições de objectos, a área de trabalho tenta adaptar o recurso a IContributorResourceAdapter antes de o tentar adaptar directamente a IResource. Foi adicionada uma nova sub-interface a esta interface, a IContributorResourceAdapter2, que faculta a mesma capacidade para a ResourceMapping. A única diferença é que o fornecedor de modelos deverá registar um fornecedor para o IContributorResourceAdapter, uma vez que a Área de Trabalho verifica a instanceof para ver se o adaptador contribuído consiste também numa instância de IContributorResourceAdapter2.

A implementação da subclasse ResourceMapping para um pacote Java deverá ser semelhante ao seguinte.

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

Esta é uma correlação bastante directa, fazendo com que a implementação não seja complexa. A complexidade da implementação da correlação de recursos irá obviamente variar de modelo para modelo.

Contexto de Correlação de Recursos

Uma das vantagens da API de Correlações de Recursos é o facto de permitir que os plug-ins implementem qualquer operação desejada em termos de correlações de recursos (por exemplo, actualização de CVS, consolidação de CVS, separador de CVS, decoração com defeitos, etc.). Contudo, a API introduzida lida apenas com o estado local do modelo. Ao trabalhar com um modelo que pode ser partilhado pelos programadores, levará a uma situação em que o estado remoto do modelo (ou seja, o estado do modelo que outro utilizador deu entrada no repositório) poderá ser diferente do estado do espaço de trabalho. Se efectuar uma actualização de CVS, recomenda-se que o estado local do modelo corresponda ao estado remoto, mesmo que isso implique que ficheiros adicionais necessitem de ser incluídos ou que alguns ficheiros necessitem de ser removidos.

Esta questão não se aplica a alguns modelos lógicos. Por exemplo, um pacote java consiste num contentor visitado numa profundidade de um, independentemente do estado remoto do modelo. Dado isto, um fornecedor de repositórios pode facilmente determinar que as eliminações de saída deverão ser incluídas durante a consolidação ou que as adições de entrada deverão ser incluídas durante a actualização. Contudo, os recursos que constituem alguns modelos lógicos poderão ser alteradas com o decorrer do tempo. Por exemplo, os recursos que constituem um elemento de modelos pode depender dos conteúdos de um ficheiro de manifesto (ou de outro mecanismo semelhante). Para que a correlação de recursos resulte na travessia adequada, terá de aceder aos conteúdos remotos do ficheiro de manifesto (caso estes sejam diferentes dos conteúdos locais) para que possa verificar se é necessário incluir recursos adicionais. Estes recursos adicionais poderão não existir no espaço de trabalho, mas o fornecedor de repositórios saberá assegurar que existem quando a acção seleccionada for executada.

Para suportar estes modelos mais complexos, poderá ser transmitido um RemoteResourceMappingContext para o método ResourceMapping#getTraversals. Quando é facultado um contexto, a correlação pode utilizá-lo para assegurar que todos os recursos necessários estão incluídos na travessia. Se um contexto não for facultado, a correlação pode pressupor que apenas o estado local é de interesse.

Quando é que uma ResourceMapping necessita de se preocupar com o RemoteResourceMappingContext?

Uma ResourceMapping necessita apenas de se preocupar com um contexto fornecido ao método getTraversals nos casos em que os recursos que constituem um modelo alteram com o tempo e a relação entre o modelo e os recursos não pode ser descrita por uma simples travessia que abrange certamente esses recursos (e apenas esses recursos) que constituem o modelo. Por exemplo, apesar de os recursos de um pacote Java poderem alterar com o decorrer do tempo, o pacote pode ser descrito como uma pasta de profundidade de um para que uma correlação de recursos para pacotes java não necessite de utilizar o contexto de correlação de recursos.

Como exemplo mais complicado, considere um ficheiro de HTML que contém várias imagens. vamos assumir o pressuposto que qualquer referência a imagens de um ficheiro de HTML pertencem ao modelo desse ficheiro. Ao actualizar os conteúdos locais do ficheiro de HTML a partir de um repositório, o utilizador espera que as imagens novas estejam incluídas. O método getTraversals para uma ResourceMapping do modelo do ficheiro de HTML será semelhante ao seguinte:

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);
}
}
return new ResourceTraversal[] {
new ResourceTraversal(resources, IResource.DEPTH_ZERO, IResource.NONE)};
}
}

Repare que existem dois conjuntos de recursos incluídos no modelo: os que derivam dos conteúdos locais do ficheiro de HTML no espaço de trabalho e os que são obtidos a partir de conteúdos do ficheiro remoto e do ficheiro de base. Em ambos os conjuntos, poderão haver recursos que não existem no espaço de trabalho. Por exemplo, o ficheiro de HTML local poderá conter uma ligação relativa a uma imagem que não existe no espaço de trabalho. Este recurso deverá ser incluído para que seja buscado, caso exista remotamente. Em relação ao ficheiro remoto, este poderá conter uma nova cópia que referencia imagens adicionais que deverão ser buscadas quando os novos conteúdos remotos forem descarregados.

Fornecedores de Modelos

Os fornecedores de modelos consistem num meio de agrupar correlações de recursos relacionadas. Em seguida é apresentada uma ligação para a classe ModelProvider. Esta classe têm três objectivos principais:

  1. A partir de um fornecedor de modelos, os clientes podem obter partes adicionais da API que permitem executar operações num conjunto de correlações de recursos através da utilização do mecanismo adaptável. Por exemplo, a IResourceMappingMerger para o modelo é obtida ao adaptar o fornecedor de modelos.
  2. Considerando um conjunto de recursos de sistemas de ficheiros, os clientes podem consultar se um fornecedor de modelos contém elementos de modelos que persistiram nesses recursos e, caso contrário, podem obter um conjunto de correlações de recursos que descrevem a relação.
  3. Em caso de operações num conjunto de recursos, o validador de alteração de recursos irá consultar os fornecedores de modelos de modo a determinar se existem potenciais efeitos secundários de uma operação sobre os quais os utilizadores deverão ser informados. Esta situação é abordada numa outra secção, na validação de alterações.

De seguida é apresentado um exemplo de uma definição da extensão 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>

O LibraryModelProvider é uma subclasse se ModelProvider. A regra de activação é utilizada para fazer corresponder recursos nos quais o modelo Biblioteca mantém o respectivo modelo. No exemplo apresentado acima, o fornecedor de modelos irá corresponder a qualquer recurso num projecto que contenha a natureza da biblioteca.

Uma vez definido o fornecedor de modelos, o método ResourceMapping#getModelProviderId() deverá ser substituído de modo a devolver o id do fornecedor de modelos.

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

Para obter a correlação inversa adequada de recursos para correlacionar esses recursos que correspondem à regra de activação do fornecedor, deverá substituir um ou ambos os métodos getMapping. O método que necessita de substituir depende do facto de o modelo ter elementos que contêm ou não vários recursos. Se os elementos do modelo correlacionarem um único recurso, pode substituir o método que aceita um único argumento IResource. Caso contrário, será necessário substituir o método que aceita uma matriz de recursos. Em seguida, é apresentado um exemplo em que é utilizado um único caso de recurso.

O método de exemplo seguinte translineia um ficheiro de modelo de biblioteca na correlação de recursos adequada. Este exemplo translineia também as pastas que contêm ficheiros que podem ter interesse para o fornecedor de modelos.

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

Os clientes podem então aceder ao fornecedor de modelos para determinar se estes têm algum interesse nos recursos nos quais será efectuada uma operação. A secção seguinte descreve a API que será facultada às operações da equipa que utilizam a API de fornecedor de modelos para determinar o conjunto completo de correlações de recursos nas quais será efectuada uma operação quando a operação da equipa for executada num conjunto de recursos ou elementos de modelos seleccionados.

Validação de Alteração de Recursos

As operações executadas nos recursos deverão ser validadas primeiro, de modo a assegurar que o utilizador tem conhecimento de quaisquer potenciais efeitos secundários. Em seguida, são apresentados os passo necessários para validar uma alteração de recursos.

  1. Construir uma descrição da alteração através da utilização de IResourceChangeDescriptionFactory. O fornecedor produz um IResourceDelta que reflecte o aspecto do delta do recurso resultante após a execução da operação.
  2. Validar a alteração através da utilização de ResourceChangeValidator. O validador consulta todos os fornecedores de modelos que registaram algum interesse nos recursos afectados. O resultado é um ou mais estados que contêm o id do modelo de origem e uma descrição dos potenciais efeitos secundários da operação efectuada no modelo.
  3. Informe o utilizador dos potenciais efeitos secundários dos modelos que não são do conhecimento do originador da operação. Por exemplo, se uma refactorização Java tiver recebido um efeito secundário de um modelo Java, este poderá ser ignorado uma vez que a refactorização entende a semântica do modelo Java. Contudo, se for devolvido um efeito secundário do modelo Biblioteca, este deverá ser do conhecimento do utilizador uma vez que o Java não tem conhecimento do modelo Biblioteca.

Intercalação baseada em Modelos

Quando um fornecedor de Equipas tentar efectuar uma intercalação sem cabeçalho, este irá efectuar os seguintes passos:

  1. Obter as correlações de recursos a partir dos elementos seleccionados
  2. Determinar os fornecedores de modelos envolvidos através da utilização do método ResourceMapping#getModelProvider().
  3. Expandir o âmbito da operação de modo a incluir todas as correlações de recursos necessárias.
  4. Construir uma descrição do estado de sincronização entre o local e o remoto. Esta descrição é facultada aos modelos através da API IMergeContext.
  5. Adaptar os fornecedores de modelos a IResourceMappingMerger.
  6. Invocar o método validateMerge em cada intercalação, passando pela descrição de sincronização, de modo a assegurar que não existe nenhuma condição que evite uma tentativa de intercalação.
  7. Delegar a intercalação para as intercalações de modelos de modo a executar a mesma.
  8. Os fornecedores de modelos podem delegar a intercalação de ficheiros individuais para o fornecedor de Equipas, caso apenas pretendam controlar a ordem da intercalação, ou podem executar a intercalação eles próprios e indicar ao fornecedor de equipas quando tiverem terminado.

Conteúdo do Modelo nas Vistas de Operações da Equipa

A apresentação de elementos de modelos no contexto de uma operação da Equipa é possível graças ao enquadramento do Navegador Comum.

Os passos acima apresentados irão permitir que os modelos apareçam nas caixas de diálogo utilizadas pelas operações da equipa. Existem passos adicionais necessários para integrar numa pré-visualização de intercalação.

Vista Histórico

As seguintes melhorias foram efectuadas na área do histórico de ficheiros e do histórico de elementos de modelos:

Procura Remota

O que segue foi facultado para suportar a procura remota:

Decorar Elementos de Modelos com o Estado da Equipa

Os fornecedores de equipas podem decorar elementos de modelos ao converter os respectivos decoradores leves para que funcionem para as correlações de recursos do mesmo modo que as contribuições de objectos são convertidas para funcionarem para as correlações de recursos. Contudo, existe um aspecto de decoração de elementos de modelos lógicos que é problemático. Se um elemento de modelos não contiver uma correlação de um-para-um com um recursos, o elemento de modelos poderá não receber uma actualização de etiquetas quando os recursos subjacentes forem alterados.

Para abordar esta questão, o ITeamStateProvider foi introduzido de modo a facultar aos fornecedores de modelos acesso às alterações de estado que poderão afectar as decorações da equipa. Para além disso, as vistas de modelos podem utilizar um SynchronizationStateTester para determinar quando as etiquetas dos elementos de modelos necessitam de ser actualizadas. Esta API depende da interface ITeamStateProvider para determinar quando o estado da equipa de um recurso foi alterada e pode ser transmitida para o decorador da equipa como sendo parte de um IDecorationContext.