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:
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.
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:
Object getModelObject()
: O objecto do modelo a partir do
qual a correlação derivou (ou foi adaptada).ResourceTraversal[] getTraversals(ResourceMappingContext,
IProgressMonitor)
: A travessia dos recursos que abrange os recursos
que constituem o objecto do modelo. ResourceTraversal
contém um conjunto de recursos e um sinalizador de profundidade que indica a
profundidade à qual estão associados os recursos na travessia com o objecto do modelo de origem. As travessias dos recursos são facultadas ao cliente pela
correlação de recursos para descrever os conteúdos de um modelo de modo a que o
cliente (por exemplo, um fornecedor de repositórios) possa executar operações da forma mais eficiente possível.
Os métodos de interesse são: getResources()
getDepth()
ResourceMappingContext
e
RemoteResourceMappingContext
é um pouco mais complicada e é descrita na secção
Contexto de Correlação de Recursos.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.
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.
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.
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.
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:
IResourceMappingMerger
para o modelo é obtida ao adaptar o fornecedor de modelos. 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.
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.
IResourceChangeDescriptionFactory
.
O fornecedor produz um IResourceDelta
que reflecte o aspecto do
delta do recurso resultante após a execução da operação. 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. Quando um fornecedor de Equipas tentar efectuar uma intercalação sem cabeçalho, este irá efectuar os seguintes passos:
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.
As seguintes melhorias foram efectuadas na área do histórico de ficheiros e do histórico de elementos de modelos:
O que segue foi facultado para suportar a procura remota:
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
.