#  REST Fragment Plugin Module

## Introduction

A REST fragment module defines a Java component that can extend the functionality of a REST endpoint. The REST fragment
will be executed in conjunction with any other REST fragments registered to the same location.

Only REST endpoints that are configured to execute REST fragments can be extended. A list of locations that a REST
fragment module can extend, and the context that they provide, is included below.

## Configuration

The root element for the REST fragment plugin module is `<rest-fragment/>`. It allows the following four attributes for
configuration:

### Attributes

<table>
    <tr>
        <th>Name</th>
        <th>Required</th>
        <th>Description</th>
        <th>Default</th>
    </tr>
    <tr>
        <td>key</td>
        <td><span class="tick"/></td>
        <td>The unique identifier of the plugin module. This key must be unique within the plugin where it is defined.</td>
        <td>N/A</td>
    </tr>
    <tr>
        <td>location</td>
        <td><span class="tick"/></td>
        <td>The REST endpoint location to register the REST fragment to.</td>
        <td>N/A</td>
    </tr>
    <tr>
        <td>class</td>
        <td><span class="tick"/></td>
        <td>The fully qualified Java class name of REST fragment. This class must implement <a href="https://developer.atlassian.com/static/javadoc/bitbucket-server/${project.version}/rest-spi/reference/com/atlassian/bitbucket/rest/fragment/RestFragment.html"><code>RestFragment</code></a>.</td>
        <td>N/A</td>
    </tr>
    <tr>
        <td>weight</td>
        <td></td>
        <td>Determines the order in which the REST fragments execute. The 'lightest' weight fragment executes first,
        and the 'heaviest' executes last.</td>
        <td>100</td>
    </tr>
</table>

### Locations

<table>
    <tr>
        <th>Location</th>
        <th>Description</th>
        <th>REST URI</th>
        <th>Context</th>
        <th>Since</th>
    </tr>
    <tr>
        <td>bitbucket.repository.settings.pullRequests</td>
        <td>Pull request settings for a repository</td>
        <td>/rest/api/1.0/projects/{projectKey}/repos/{repositorySlug}/settings/pull-requests</td>
        <td>repository</td>
        <td>4.7</td>
    </tr>
    <tr>
</table>


### Example

Here is an example `atlassian-plugin.xml` file containing a single REST fragment:

```xml
<atlassian-plugin name="My Rest Fragment" key="example.plugin.fragment" plugins-version="2">
    <plugin-info>
        <description>A basic component import module test</description>
        <vendor name="My Company" url="http://www.mycompany.com"/>
        <version>1.0</version>
    </plugin-info>

    <rest-fragment key="myRestFragment" location="bitbucket.repository.settings.pullRequests" class="com.mycompany.example.plugin.fragment.MyRestFragment"/>
</atlassian-plugin>
```

and the corresponding implementation of the REST fragment.

```java
public class MyRestFragment implements RestFragment {

    @Nonnull
    @Override
    public Map<String, Object> validate(@Nonnull RestFragmentContext fragmentContext,
                                        @Nonnull Map<String, Object> requestContext) {
        if (fragmentContext.getMethod().equals("POST")) {
            // Validate request body for this fragment. If any fragment fails validation then no fragments will execute.
            // A request is still valid if it doesn't contain any information about this fragment, as it may be just
            // updating other fragments.

            // If the request was not valid, return the errors.
            // return new RestErrorMessage("myRestFragment", "Invalid request");
        }

        return new HashMap<String, Object>();
    }

    @Nonnull
    @Override
    public Map<String, Object> execute(@Nonnull RestFragmentContext fragmentContext,
                                       @Nonnull Map<String, Object> requestContext) {
        // The "bitbucket.repository.settings.pullRequests" location provides the context repository from the request.
        Repository repository = (Repository) requestContext.get("repository");

        // What the fragment does depends on the HTTP method of the request.
        String httpMethod = fragmentContext.getMethod();
        if (httpMethod.equals("GET")) {
            return doGet(repository);
        } else if (httpMethod.equals("POST")) {
            return doPost(fragmentContext, repository);
        }

        // Return a message indicating that the HTTP method is unsupported by this fragment. This is not an error,
        // because other fragments registered to the same endpoint may use this HTTP method. It is possible to return an
        // empty Map here, but specifically noting that the request had no effect on this fragment can be useful to
        // consumers of the endpoint.
        Map<String, Object> map = new HashMap<String, Object>();
        map.put("WARNING-myInternalProjectTrackingDescription", "myRestFragment does not support the HTTP method " + httpMethod);
        return map;
    }

    private Map<String, Object> doGet(Repository repository) {
       // retrieve settings for this plugin
       return new HashMap<String, Object>();
    }

    private Map<String, Object> doPost(RestFragmentContext fragmentContext, Repository repository) {
        // update settings for this plugin
        return doGet(repository);
    }
}
```

See also the [Auto Unapprove Pull Request plugin](https://bitbucket.org/atlassian/stash-auto-unapprove-plugin/) for an
example of how to implement a REST fragment.