blob: f7f288af1b87c1108226745427339f71e321c47a [file] [log] [blame]
/*******************************************************************************
* Copyright (c) 2005 IBM Corporation and others.
* 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:
* IBM Corporation - initial API and implementation
*******************************************************************************/
/*
* $$RCSfile: EMFNature.java,v $$
* $$Revision: 1.4 $$ $$Date: 2005/02/15 23:04:14 $$
*/
package org.eclipse.jem.util.emf.workbench.nature;
import java.util.*;
import org.eclipse.core.resources.*;
import org.eclipse.core.runtime.*;
import org.eclipse.emf.common.util.*;
import org.eclipse.emf.ecore.resource.Resource;
import org.eclipse.emf.ecore.resource.ResourceSet;
import org.eclipse.emf.ecore.xmi.XMLParserPool;
import org.eclipse.emf.ecore.xmi.impl.XMLParserPoolImpl;
import org.eclipse.jem.internal.util.emf.workbench.nature.EMFNatureRegistry;
import org.eclipse.jem.util.emf.workbench.*;
import org.eclipse.jem.util.logger.proxy.Logger;
/**
* The base EMFNature.
* <p>
* This is expected to be subclassed by clients, but there are default subclasses available.
* </p>
*
* @since 1.0.0
*/
public abstract class EMFNature implements IProjectNature, IEMFContextContributor {
protected IProject project;
protected EMFWorkbenchContextBase emfContext;
protected boolean hasConfigured = false;
public static XMLParserPool SHARED_PARSER_POOL = new XMLParserPoolImpl();
public EMFNature() {
super();
}
/**
* Add the nature id to the project.
*
* @param proj
* @param natureId
* @throws CoreException
*
* @since 1.0.0
*/
protected static void addNatureToProject(IProject proj, String natureId) throws CoreException {
ProjectUtilities.addNatureToProject(proj, natureId);
}
/**
* Configures the project with this nature. This is called by <code>IProject.addNature</code> and should not be called directly by clients. The
* nature extension id is added to the list of natures on the project by <code>IProject.addNature</code>, and need not be added here.
*
* <p>
* All subtypes must call super. The better way for subtypes is to override primConfigure instead.
* </p>
*
* @throws CoreException
* @since 1.0.0
*/
public void configure() throws org.eclipse.core.runtime.CoreException {
if (!hasConfigured) {
hasConfigured = true;
primConfigure();
}
}
/**
* Called from configure the first time configure is called on the nature. Default is do nothing. Subclasses should override and add in their own
* configuration.
*
* @throws org.eclipse.core.runtime.CoreException
*
* @since 1.0.0
*/
protected void primConfigure() throws org.eclipse.core.runtime.CoreException {
}
/**
* Create an EMF context for the project.
*
* @throws CoreException
*
* @since 1.0.0
*/
protected void createEmfContext() throws CoreException {
WorkbenchResourceHelperBase.createEMFContext(getProject(), this);
}
/**
* Create a folder relative to the project based on aProjectRelativePathString.
*
* @param aProjectRelativePathString
* @return
* @throws CoreException
*
* @since 1.0.0
*/
public IFolder createFolder(String aProjectRelativePathString) throws CoreException {
if (aProjectRelativePathString != null && aProjectRelativePathString.length() > 0)
return createFolder(new Path(aProjectRelativePathString));
return null;
}
/**
* Create a folder relative to the project based on aProjectRelativePathString.
*
* @param aProjectRelativePath
* @return
* @throws CoreException
*
* @since 1.0.0
*/
public IFolder createFolder(IPath aProjectRelativePath) throws CoreException {
if (aProjectRelativePath != null && !aProjectRelativePath.isEmpty()) {
IFolder folder = getWorkspace().getRoot().getFolder(getProjectPath().append(aProjectRelativePath));
if (!folder.exists()) {
ProjectUtilities.ensureContainerNotReadOnly(folder);
folder.create(true, true, null);
}
return folder;
}
return null;
}
/**
* Removes this nature from the project, performing any required deconfiguration. This is called by <code>IProject.removeNature</code> and
* should not be called directly by clients. The nature id is removed from the list of natures on the project by
* <code>IProject.removeNature</code>, and need not be removed here.
*
* @throws CoreException
* @since 1.0.0
*/
public void deconfigure() throws org.eclipse.core.runtime.CoreException {
emfContext = null;
}
/**
* Return true if the IFile with the given name exists in this project.
*
* @param aFileName
* filename can be relative to one of the input file paths for the WorkbenchURIConverter.
* @return <code>true</code> if filename exists in this project
*
* @since 1.0.0
*/
public boolean fileExists(String aFileName) {
if (aFileName == null)
return false;
IPath path = new Path(aFileName);
if (path.isAbsolute())
return ResourcesPlugin.getWorkspace().getRoot().getFile(path).exists();
else
return getWorkbenchURIConverter().canGetUnderlyingResource(aFileName);
}
/**
* Get the resource set for the project
*
* @return
*
* @since 1.0.0
*/
public ResourceSet getResourceSet() {
return getEmfContextBase().getResourceSet();
}
/**
* Returns the EMF root folder for the project. Defaults to the project. Subclasses can override.
*
* @return EMF root folder for the project.
*
* @since 1.0.0
*/
public IContainer getEMFRoot() {
return getProject();
}
/**
* Used for optimizations; answers whether a mof context for this nature has exists yet
*
* @deprecated use hasResourceSet();
* @since 1.0.0
*/
public boolean hasContext() {
return hasResourceSet();
}
/**
* Is there a resource set yet for the project.
*
* @return <code>true</code> if there is a resource set for the project.
*
* @since 1.0.0
*/
public boolean hasResourceSet() {
return emfContext != null && emfContext.hasResourceSet();
}
/**
* Lazy initializer; for migration of existing workspaces where configure will never get called.
*
* @return context base for the project.
*
* @since 1.0.0
*/
protected EMFWorkbenchContextBase getEmfContextBase() {
if (emfContext == null) {
try {
createEmfContext();
} catch (CoreException ex) {
Logger.getLogger().logError(ex);
}
}
return emfContext;
}
/**
* Get the IFile with the given name if it is in this project.
*
* @param aFileName
* filename can be relative to one of the input file paths for the WorkbenchURIConverter.
* @return file it it is in this project, or <code>null</code> if it doesn't.
*
* @since 1.0.0
*/
public IFile getFile(String aFileName) {
return getWorkbenchURIConverter().getFile(aFileName);
}
/**
* Return the nature's ID.
*
* @return nature id
*
* @since 1.0.0
*/
public abstract String getNatureID();
/**
* Return the ID of the plugin that this nature is contained within.
*
* @return
*
* @since 1.0.0
*/
protected abstract String getPluginID();
/**
* Returns the project to which this project nature applies.
*
* @return the project handle
* @since 1.0.0
*/
public org.eclipse.core.resources.IProject getProject() {
return project;
}
/**
* Return the full path of the project.
*
* @return full project path (relative to workspace)
* @since 1.0.0
*/
public IPath getProjectPath() {
return getProject().getFullPath();
}
/**
* Get the server property of the project from the supplied key
*
* @param key
* java.lang.String
* @deprecated we cannont use persistent properties because they are not stored in the repository
* @since 1.0.0
*/
protected String getProjectServerValue(String key) {
if (key == null)
return null;
try {
QualifiedName wholeName = qualifiedKey(key);
return getProject().getPersistentProperty(wholeName);
} catch (CoreException exception) {
//If we can't find it assume it is null
exception.printStackTrace();
return null;
}
}
/**
* Get WorkbenchURIConverter for this project.
* <p>
* This method assumes the URIConverter on the ResourceSet is the one that was created for the ResourceSet on behalf of this nature runtime.
* </p>
*
* @return
*
* @since 1.0.0
*/
protected WorkbenchURIConverter getWorkbenchURIConverter() {
return (WorkbenchURIConverter) getResourceSet().getURIConverter();
}
public IWorkspace getWorkspace() {
return getProject().getWorkspace();
}
/**
* @deprecated use getResource(URI)
*/
public Resource getXmiResource(String uri) {
return getResource(URI.createURI(uri));
}
/**
* Get the resource for this uri. It will use the resource set of the project to find it. It will load if not already loaded.
*
* @param uri
* @return resource or <code>null</code> if resource is not found.
*
* @since 1.0.0
*/
public Resource getResource(URI uri) {
try {
return getResourceSet().getResource(uri, true);
} catch (WrappedException ex) {
if (!WorkbenchResourceHelperBase.isResourceNotFound(ex))
throw ex;
}
return null;
}
/**
* @deprecated use getResourceSet()
*/
public ResourceSet getXmiResourceSet() {
return getResourceSet();
}
/**
* Make sure that all dependent components are initialized before creating the ResourceSet.
*/
protected void initializeDependentComponents() {
//com.ibm.etools.java.init.JavaInit.init();
}
/**
* @deprecated use createResource(URI)
*/
public Resource makeXmiResource(String uri) {
return createResource(URI.createURI(uri));
}
/**
* @deprecated use createResource(URI)
*/
public Resource makeXmiResource(String uri, EList anExtent) {
Resource res = makeXmiResource(uri);
if (res != null)
res.getContents().addAll(anExtent);
return res;
}
/**
* Create the resource for this uri. It will use the resource set of the project to create it.
*
* @param uri
* @return resource
*
* @since 1.0.0
*/
public Resource createResource(URI uri) {
return getResourceSet().createResource(uri);
}
/*
* Return the QualifedValue for key for storage in the repository. The key is qualifed with the package name to avoid collision. @return
* QualifedName @param key java.lang.String
*/
private QualifiedName qualifiedKey(String key) {
return new QualifiedName(getPluginID(), key);
}
/**
* Register the given nature id as an EMFNature.
*
* @param natureID
*
* @since 1.0.0
*/
public static void registerNatureID(String natureID) {
EMFNatureRegistry.singleton().REGISTERED_NATURE_IDS.add(natureID);
}
/**
* Sets the project to which this nature applies. Used when instantiating this project nature runtime. This is called by
* <code>IProject.addNature</code> and should not be called directly by clients.
*
* @param project
* the project to which this nature applies
*
* @since 1.0.0
*/
public void setProject(org.eclipse.core.resources.IProject newProject) {
project = newProject;
}
/**
* Set the server property of the project from the supplied value
*
* @param key
* java.lang.String
* @param value
* String
* @deprecated we cannont use persistent properties because they are not stored in the repository
*/
protected void setProjectServerValue(String key, String value) {
if (key != null) {
try {
QualifiedName wholeName = qualifiedKey(key);
getProject().setPersistentProperty(wholeName, value);
} catch (CoreException exception) {
//If we can't find it assume it is null
exception.printStackTrace();
return;
}
}
}
/**
* Shutdown the EMF nature
*
*
* @since 1.0.0
*/
public void shutdown() {
if (getResourceSet() != null)
((ProjectResourceSet) getResourceSet()).release();
}
/**
* Return a list of EMFNatures based on the natures that have been configured for this project.
*
* @return List of EMFNatures
* @param project
* @return list of natures configured for the project.
* @since 1.0.0
*/
public static List getRegisteredRuntimes(IProject project) {
List result = null;
EMFNature nature = null;
if (project != null && project.isAccessible()) {
String natureID;
Iterator it = EMFNatureRegistry.singleton().REGISTERED_NATURE_IDS.iterator();
while (it.hasNext()) {
natureID = (String) it.next();
try {
nature = (EMFNature) project.getNature(natureID);
} catch (CoreException e) {
}
if (nature != null) {
if (result == null)
result = new ArrayList(2);
result.add(nature);
}
}
}
return result == null ? Collections.EMPTY_LIST : result;
}
/**
* Return a list of nature ids based on the natures that have been configured for this project.
*
* @return list of configured nature ids.
* @param project
*/
public static List getRegisteredRuntimeIDs(IProject project) {
List result = null;
String natureID = null;
if (project != null && project.isAccessible()) {
Iterator it = EMFNatureRegistry.singleton().REGISTERED_NATURE_IDS.iterator();
while (it.hasNext()) {
natureID = (String) it.next();
try {
if (project.hasNature(natureID)) {
if (result == null)
result = new ArrayList(2);
result.add(natureID);
}
} catch (CoreException e) {
}
}
}
return result == null ? Collections.EMPTY_LIST : result;
}
/**
* Return if the project has the given nature.
*
* @param project
* @param natureId
* @return <code>true</code> if project has given nature
*
* @since 1.0.0
*/
public static boolean hasRuntime(IProject project, String natureId) {
if (project == null || !project.isAccessible())
return false;
try {
return project.hasNature(natureId);
} catch (CoreException e) {
return false;
}
}
/**
* Return if the project has any one of the possible given nature ids.
*
* @param project
* @param possibleNatureIds
* @return <code>true</code> if at least one of the possible natures id is configured for the project.
*
* @since 1.0.0
*/
public static boolean hasRuntime(IProject project, String[] possibleNatureIds) {
if (project != null) {
for (int i = 0; i < possibleNatureIds.length; i++) {
if (hasRuntime(project, possibleNatureIds[i]))
return true;
}
}
return false;
}
}