| /******************************************************************************* |
| * Copyright (c) 2010, 2011 Obeo. |
| * All rights reserved. This program and the accompanying materials |
| * are made available under the terms of the Eclipse Public License v1.0 |
| * which accompanies this distribution, and is available at |
| * http://www.eclipse.org/legal/epl-v10.html |
| * |
| * Contributors: |
| * Obeo - initial API and implementation |
| *******************************************************************************/ |
| package org.eclipse.mylyn.docs.intent.collab.ide.repository; |
| |
| import com.google.common.base.Predicate; |
| |
| import org.eclipse.core.resources.IFolder; |
| import org.eclipse.core.resources.IProject; |
| import org.eclipse.core.resources.IResource; |
| import org.eclipse.core.resources.IWorkspace; |
| import org.eclipse.core.resources.ResourcesPlugin; |
| import org.eclipse.core.runtime.CoreException; |
| import org.eclipse.core.runtime.Status; |
| import org.eclipse.emf.common.util.URI; |
| import org.eclipse.emf.ecore.EClass; |
| import org.eclipse.emf.ecore.EObject; |
| import org.eclipse.emf.ecore.EPackage.Registry; |
| import org.eclipse.emf.ecore.resource.Resource; |
| import org.eclipse.emf.ecore.resource.ResourceSet; |
| import org.eclipse.emf.transaction.TransactionalEditingDomain; |
| import org.eclipse.emf.transaction.impl.InternalTransactionalEditingDomain; |
| import org.eclipse.mylyn.docs.intent.collab.handlers.RepositoryClient; |
| import org.eclipse.mylyn.docs.intent.collab.handlers.adapters.RepositoryAdapter; |
| import org.eclipse.mylyn.docs.intent.collab.handlers.adapters.RepositoryStructurer; |
| import org.eclipse.mylyn.docs.intent.collab.ide.adapters.WorkspaceAdapter; |
| import org.eclipse.mylyn.docs.intent.collab.repository.Repository; |
| import org.eclipse.mylyn.docs.intent.collab.repository.RepositoryConnectionException; |
| |
| /** |
| * Representation of a Workspace as a repository. |
| * |
| * @author <a href="mailto:alex.lagarde@obeo.fr">Alex Lagarde</a> |
| */ |
| public class WorkspaceRepository implements Repository { |
| |
| /** |
| * The default extension for any element stored on the repository. |
| */ |
| private static final String WORKSPACE_RESOURCE_EXTENSION = "repomodel"; |
| |
| /** |
| * Represents this repository configuration. |
| */ |
| private WorkspaceConfig workspaceConfig; |
| |
| /** |
| * Session that will notify any listening entities about changes on Workspace resources corresponding to |
| * repository resources. |
| */ |
| private WorkspaceSession session; |
| |
| /** |
| * Indicates if the repository resource set has been initialized. |
| */ |
| private boolean isResourceSetLoaded; |
| |
| /** |
| * The repository editing domain. |
| */ |
| private TransactionalEditingDomain editingDomain; |
| |
| /** |
| * The repository structurer. |
| */ |
| private RepositoryStructurer repositoryStructurer; |
| |
| /** |
| * Used to determine if a resource can be unloaded: if the root has one of this unloadableTypes, then it |
| * will be unloaded. |
| */ |
| private EClass[] unloadableTypes; |
| |
| /** |
| * WorkspaceRepository constructor. |
| * |
| * @param workspaceConfig |
| * this repository configuration |
| * @param unloadableTypes |
| * the list of types which cannot be unloaded |
| */ |
| public WorkspaceRepository(WorkspaceConfig workspaceConfig, EClass... unloadableTypes) { |
| this.unloadableTypes = unloadableTypes; |
| this.workspaceConfig = workspaceConfig; |
| this.editingDomain = TransactionalEditingDomain.Factory.INSTANCE.createEditingDomain(); |
| isResourceSetLoaded = false; |
| } |
| |
| /** |
| * Initializes the resource set using the repository content ; if the repository content is empty, creates |
| * all the declared indexes. |
| * |
| * @throws CoreException |
| * it the resourceSet cannot be initialized |
| */ |
| private void initializeResourceSet() throws CoreException { |
| |
| // We first get the project on which the repository is defined |
| IProject project = workspaceConfig.getProject(); |
| if (!project.exists()) { |
| project.create(null); |
| } |
| if (!project.isOpen()) { |
| project.open(null); |
| } |
| IFolder folder = project.getFolder(workspaceConfig.getRepositoryRelativePath()); |
| // We created a WorkspaceRepositoryLoader using the indexPathList |
| WorkspaceRepositoryLoader loader = new WorkspaceRepositoryLoader(this, this.getWorkspaceConfig() |
| .getIndexesPathList()); |
| // If the repository folder exists |
| if (folder.exists()) { |
| // We load the resourceSet |
| loader.loadResourceSet(); |
| } else { |
| // If the repository folder doesn't exist |
| // We create it |
| folder.create(IResource.NONE, true, null); |
| // And use the RepositoryLoader to initialize the resource set with empty content |
| loader.loadResourceSet(); |
| |
| } |
| isResourceSetLoaded = true; |
| |
| } |
| |
| /** |
| * {@inheritDoc} |
| * |
| * @see org.eclipse.mylyn.docs.intent.collab.repository.Repository#register(org.eclipse.mylyn.docs.intent.collab.handlers.RepositoryClient) |
| */ |
| public void register(RepositoryClient client) { |
| // No need to register |
| } |
| |
| /** |
| * {@inheritDoc} |
| * |
| * @see org.eclipse.mylyn.docs.intent.collab.repository.Repository#unregister(org.eclipse.mylyn.docs.intent.collab.handlers.RepositoryClient) |
| */ |
| public void unregister(RepositoryClient client) { |
| // No need to unregister |
| |
| } |
| |
| /** |
| * {@inheritDoc} |
| * |
| * @see org.eclipse.mylyn.docs.intent.collab.repository.Repository#getOrCreateSession() |
| */ |
| public synchronized Object getOrCreateSession() throws RepositoryConnectionException { |
| |
| // We first initialize the resource set if needed |
| if (!isResourceSetLoaded) { |
| try { |
| initializeResourceSet(); |
| } catch (CoreException e) { |
| throw new RepositoryConnectionException(e.getMessage()); |
| } |
| } |
| if (this.session == null) { |
| // Creation of a Workspace session that will send notifications when the workspace's resources |
| // corresponding to repository resources change |
| this.session = new WorkspaceSession(this); |
| IWorkspace workspace = ResourcesPlugin.getWorkspace(); |
| workspace.addResourceChangeListener(session); |
| } |
| return this.session; |
| } |
| |
| /** |
| * {@inheritDoc} |
| * |
| * @see org.eclipse.mylyn.docs.intent.collab.repository.Repository#closeSession() |
| */ |
| public synchronized void closeSession() throws RepositoryConnectionException { |
| if (this.session != null) { |
| ResourcesPlugin.getWorkspace().removeResourceChangeListener(session); |
| this.session.close(); |
| this.session = null; |
| } |
| |
| // If a transaction is being executed, we abort it |
| if (((InternalTransactionalEditingDomain)this.editingDomain).getActiveTransaction() != null) { |
| ((InternalTransactionalEditingDomain)this.editingDomain).getActiveTransaction().abort( |
| Status.CANCEL_STATUS); |
| } |
| this.editingDomain.dispose(); |
| } |
| |
| /** |
| * {@inheritDoc} |
| * |
| * @see org.eclipse.mylyn.docs.intent.collab.repository.Repository#getPackageRegistry() |
| */ |
| public Registry getPackageRegistry() throws RepositoryConnectionException { |
| // Return the resourceset's package registry |
| return getResourceSet().getPackageRegistry(); |
| } |
| |
| // ---- SPECIFIC BEHAVIORS |
| /** |
| * Indicates if the given path represents a location in the repository. |
| * |
| * @param path |
| * the path to study |
| * @return true if the given path represents a location in the repository, false otherwise |
| */ |
| public boolean isInRepositoryPath(String path) { |
| return path.startsWith(this.workspaceConfig.getRepositoryRelativePath()); |
| } |
| |
| /** |
| * Indicates if the given resource is included in the given path. |
| * |
| * @param path |
| * is the path |
| * @param resource |
| * the resource to determine if it's included in the given path |
| * @return true if the resource's associated path starts with or is equals to the given path, false |
| * otherwise |
| */ |
| public boolean isIncludedInPath(String path, Resource resource) { |
| // We first get the complete URI of the given path |
| URI uriPath = getURIMatchingPath(path); |
| // We compare the two URI |
| return resource.getURI().toString().startsWith(uriPath.toString()); |
| } |
| |
| /** |
| * Returns the Repository URI corresponding to the given path. |
| * <p> |
| * The complete path is calculated by prefixing the given path by this repository path and postfixing it |
| * by the default file extension. |
| * </p> |
| * |
| * @param path |
| * is the path |
| * @return the Repository URI corresponding to the given path |
| */ |
| public URI getURIMatchingPath(String path) { |
| String completePath = this.getWorkspaceConfig().getRepositoryAbsolutePath() + path; |
| // If the path don't ends with '/' (i.e isn't a folder), we add the file extension |
| if (shouldHaveWorkspaceResourceExtension(completePath)) { |
| completePath += "." + WORKSPACE_RESOURCE_EXTENSION; |
| } |
| completePath = completePath.trim(); |
| URI uri = URI.createPlatformResourceURI(completePath, false); |
| return uri; |
| } |
| |
| /** |
| * Indicates if the Repository resource located at the given path should be association with the |
| * {@link WorkspaceRepository#WORKSPACE_RESOURCE_EXTENSION} extension. |
| * |
| * @param path |
| * the path of the Repository resource |
| * @return true if the Repository resource located at the given path should be association with the |
| * {@link WorkspaceRepository#WORKSPACE_RESOURCE_EXTENSION} extension, false otherwise |
| */ |
| public boolean shouldHaveWorkspaceResourceExtension(String path) { |
| return !path.endsWith("/"); |
| } |
| |
| /** |
| * Returns the EMF ResourceSet of this Workspace repository. |
| * <p> |
| * It will handle resource creation, package registry management... |
| * </p> |
| * |
| * @return the resourceSet the EMF ResourceSet of this Workspace repository |
| */ |
| public ResourceSet getResourceSet() { |
| return editingDomain.getResourceSet(); |
| } |
| |
| /** |
| * Returns this repository configuration. |
| * |
| * @return this repository configuration |
| */ |
| public WorkspaceConfig getWorkspaceConfig() { |
| return workspaceConfig; |
| } |
| |
| /** |
| * Returns the default extension for any element stored on the repository. |
| * |
| * @return the default extension for any element stored on the repository |
| */ |
| public static String getWorkspaceResourceExtension() { |
| return WORKSPACE_RESOURCE_EXTENSION; |
| } |
| |
| public TransactionalEditingDomain getEditingDomain() { |
| return editingDomain; |
| } |
| |
| /** |
| * {@inheritDoc} |
| * |
| * @see org.eclipse.mylyn.docs.intent.collab.repository.Repository#setRepositoryStructurer(org.eclipse.mylyn.docs.intent.collab.handlers.adapters.RepositoryStructurer) |
| */ |
| public void setRepositoryStructurer(RepositoryStructurer structurer) { |
| this.repositoryStructurer = structurer; |
| |
| } |
| |
| /** |
| * {@inheritDoc} |
| * |
| * @see org.eclipse.mylyn.docs.intent.collab.repository.Repository#createRepositoryAdapter() |
| */ |
| public RepositoryAdapter createRepositoryAdapter() { |
| WorkspaceAdapter workspaceAdapter = new WorkspaceAdapter(this); |
| if (this.repositoryStructurer != null) { |
| workspaceAdapter.attachRepositoryStructurer(this.repositoryStructurer); |
| } |
| // We set a new unloadable Resource Predicate |
| workspaceAdapter.setUnloadableResourcePredicate(new Predicate<Resource>() { |
| |
| public boolean apply(Resource resource) { |
| // The Intent index should never be unloaded |
| if (!resource.getContents().isEmpty()) { |
| boolean res = false; |
| EObject root = resource.getContents().iterator().next(); |
| for (EClass unloadableType : unloadableTypes) { |
| if (root.eClass().equals(unloadableType)) { |
| res = true; |
| } |
| } |
| return res; |
| } |
| return false; |
| } |
| }); |
| return workspaceAdapter; |
| } |
| |
| /** |
| * {@inheritDoc} |
| * |
| * @see org.eclipse.mylyn.docs.intent.collab.repository.Repository#getIdentifier() |
| */ |
| public String getIdentifier() { |
| return workspaceConfig.getProject().getName(); |
| } |
| |
| /** |
| * {@inheritDoc} |
| * |
| * @see org.eclipse.mylyn.docs.intent.collab.repository.Repository#getRepositoryLocation() |
| */ |
| public String getRepositoryLocation() { |
| return ResourcesPlugin.getWorkspace().getRoot().getLocation().toPortableString() |
| + getWorkspaceConfig().getRepositoryAbsolutePath().replace(".repository", ""); |
| } |
| |
| /** |
| * {@inheritDoc} |
| * |
| * @see org.eclipse.mylyn.docs.intent.collab.repository.Repository#getRepositoryURI() |
| */ |
| public URI getRepositoryURI() { |
| return URI.createPlatformResourceURI(getIdentifier(), true); |
| } |
| } |