## Project natures

Project natures allow a plug-in to tag a project as a specific kind of project. For example, the Java development tools (JDT) use a "Java nature" to add Java-specific behavior to projects. Project natures are defined by plug-ins, and are typically added or removed per-project when the user performs some action defined by the plug-in.

A project can have more than one nature. However, when you define a project nature, you can define special constraints for the nature:

- one-of-nature - specifies that the nature is one of a named set. Natures in a set are mutually exclusive; that is, only one nature belonging to the set can exist for a project.
- requires-nature - specifies that the nature depends on another nature and can only be added to a project that already has the required nature.

To implement your own nature, you need to define an extension and supply a class which implements IProjectNature.

### Defining a nature

The org.eclipse.core.resources.natures extension point is used to add a project nature definition. The following markup adds a nature for the hypothetical com.example.natures plug-in.

       <extension
          point="org.eclipse.core.resources.natures"
          id="myNature"
          name="My Nature">
          <runtime>
             <run class="com.example.natures.MyNature">
             </run>
          </runtime>
       </extension>

The class identified in the extension must implement the platform interface IProjectNature. This class implements plug-in specific behavior for associating nature-specific information with a project when the nature is configured.

       public class MyNature implements IProjectNature {

          private IProject project;

          public void configure() throws CoreException {
             // Add nature-specific information
             // for the project, such as adding a builder
             // to a project's build spec.
          }
          public void deconfigure() throws CoreException {
             // Remove the nature-specific information here.
          }
          public IProject getProject() {
             return project;
          }
          public void setProject(IProject value) {
             project = value;
          }
       }

The configure() and deconfigure() methods are sent by the platform when natures are added and removed from a project. You can implement the configure() method to add a builder to a project as discussed in Builders.

### Associating the nature with a project

Defining the nature is not enough to associate it with a project. You must assign a nature to a project by updating the project's description to include your nature. This usually happens when the user creates a new project with a specialized new project wizard that assigns the nature. The following snippet shows how to assign our new nature to a given project.

       try {
          IProjectDescription description = project.getDescription();
          String[] natures = description.getNatureIds();
          String[] newNatures = new String[natures.length + 1];
          System.arraycopy(natures, 0, newNatures, 0, natures.length);
          newNatures[natures.length] = "com.example.natures.myNature";
          description.setNatureIds(newNatures);
          project.setDescription(description, null);
       } catch (CoreException e) {
          // Something went wrong
       }

The natures are not actually assigned to (and configured) for the project until you set the project description into the project. Also note that the identifier used for the nature is the fully qualified name (plug-in id + extension id) of the nature extension.

If the nature has been defined with constraints, then workspace API can be used to validate the new nature. For example, suppose a nature is defined with a prerequisite:

       <extension
          point="org.eclipse.core.resources.natures"
          id="myOtherNature"
          name="My Other Nature">
          <runtime>
             <run class="com.example.natures.MyOtherNature">
             </run>
          </runtime>
       <requires-nature id="com.example.natures.myNature"/>
       </extension>

The new nature is not valid unless the first nature exists for the project. Depending on the design of your plug-in, you may want to check whether the prerequisite nature has been installed, or you may want to add the prerequisite nature yourself. Either way, you can check on the validity of proposed combinations of project natures using workspace API.

       try {
          IProjectDescription description = project.getDescription();
          String[] natures = description.getNatureIds();
          String[] newNatures = new String[natures.length + 1];
          System.arraycopy(natures, 0, newNatures, 0, natures.length);
          newNatures[natures.length] = "com.example.natures.myOtherNature";
          IStatus status = workspace.validateNatureSet(natures);

          // check the status and decide what to do
          if (status.getCode() == IStatus.OK) {
          	description.setNatureIds(newNatures);
          	project.setDescription(description, null);
          } else {
          	// raise a user error
    	...
          }
       } catch (CoreException e) {
          // Something went wrong
       }

### Nature descriptors

In addition to working with natures by their id, you can obtain the descriptor (IProjectNatureDescriptor) which describes a nature, its constraints, and its label. You can query a particular nature for its descriptor, or get descriptors from the workspace. The following snippet gets the project nature descriptor for our new nature:

          IProjectNatureDescriptor descriptor = workspace.getNatureDescriptor("com.example.natures.myOtherNature");

You can also get an array of descriptors for all installed natures:

          IProjectNatureDescriptor[] descriptors = workspace.getNatureDescriptors();