com.almworks.jira.structure.api.sync.StructureSynchronizer Maven / Gradle / Ivy
Show all versions of structure-api Show documentation
package com.almworks.jira.structure.api.sync;
import com.almworks.jira.structure.api.error.StructureException;
import com.almworks.jira.structure.api.forest.ForestSource;
import com.almworks.jira.structure.api.forest.raw.Forest;
import com.almworks.jira.structure.api.job.StructureJobManager;
import com.almworks.jira.structure.api.util.StructureUtil;
import com.atlassian.annotations.PublicSpi;
import com.atlassian.jira.web.action.JiraWebActionSupport;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import java.io.IOException;
import java.util.List;
import java.util.Map;
/**
* A StructureSynchronizer
is a pluggable Structure extension that
* allows you to sync structure with any other aspect of issues, be it links, subtasks or anything
* else. By implementing this interface and registering it with <structure-synchronizer>
* module, you define a new type of the synchronizer, which can be accessed from
* the Structure's synchronization features.
*
* To get started with synchronizers, read section about Synchronization in the Structure user documentation.
*
* You typically implement a synchronizer by extending {@link AbstractSynchronizer}.
*
* Two main methods - {@link #resync} and {@link #sync} - do the main synchronization job,
* while other methods are used to create synchronizer configuration and provide necessary information
* for the Structure plugin.
*
* The instance of StructureSynchronizer
represents a type of synchronization and
* is instantiated only once. The synchronizer instances that the users install into a structure
* are represented by {@link SyncInstance} interface.
*
* Synchronizer is configured with some kind of parameters, which are serialized via
* {@link #storeParameters(Object)} and {@link #restoreParameters(String)} and stored in
* the database. The type of parameters is up to the synchronizer, whenever parameters
* are passed they have type Object
, so the synchronizer needs to cast them to its
* parameters type.
*
* @author Igor Sereda
*/
@PublicSpi
public interface StructureSynchronizer {
/**
* Checks if this type of synchronizer is currently available. A synchronizer may not be available
* if, for example, some feature is turned off; for example, subtasks synchronizer would be
* unavailable if sub-tasks are turned off in JIRA.
*
* @return true if the synchronizer can be used
*/
boolean isAvailable();
/**
* Checks if synchronizer supports automatic incremental synchronization.
*
* If autosync is supported, the synchronizer may be installed and enabled for a structure.
* If it's not supported, the synchronizer may only be used to run resync (or import/export).
*
* @return true if the synchronizer supports autosync with {@link #sync} method
*/
boolean isAutosyncSupported();
/**
* Creates a short one-line description of the configuration parameters, shown in
* a few places in the Structure interface, such as on the Manage Structure page.
*
* @param parameters sync parameters
* @return a string describing the configuration, or null
*/
@Nullable
String getConfigDescription(@Nullable Object parameters);
/**
* Creates a list of strings that fully describe the synchronizer's configuration. Used on some pages such as
* Synchronization Settings.
*
* @param parameters sync parameters
* @return a list of lines, describing the configuration, or null
*/
@Nullable
List getConfigDescriptionDetails(@Nullable Object parameters);
/**
* Creates a list of strings that describe possible changes that might happen during resync
* @param parameters sync parameters
* @return a list of lines, describing possible changes, or null for no changes
*/
@Nullable
List getPossibleResyncEffects(@Nullable Object parameters);
/**
* Serializes parameters into a string (for example, JSON) for storing in the database. The result of using
* {@link #restoreParameters(String)} on the resulting string should reconstruct the same parameters object.
*
* Empty String ("") returned from this method is treated in the same way as {@code null} by Structure.
* It is recommended to return {@code null} instead of empty String.
*
* @param parameters sync parameters
* @return string representing serialized parameters, e.g., a JSON string
* @throws IOException if parameters cannot be stored
*/
@Nullable
String storeParameters(@Nullable Object parameters) throws IOException;
/**
* Deserializes a string previously created {@link #storeParameters(Object)} into this synchronizer's
* parameters object.
*
* @param data string with serialized parameters; never an empty String
* @return the parameters object
* @throws IOException if there's a problem reading parameters
*/
@Nullable
Object restoreParameters(@Nullable String data) throws IOException;
/**
* @return module descriptor, which is used to get configuration properties from the plugin XML descriptor
*/
@NotNull
SynchronizerDescriptor getDescriptor();
/**
* Creates an instance of synchronizer parameters. If parameters cannot be created, the method
* should return null and add errors to the action.
*
* To read the parameters, you can use {@link StructureUtil#getSingleParameter}
* method and others like it.
*
* @param formParameters the map from String
to values that is constructed from the HTML form
* parameters sent by the browser
* @param action the action executing the update - use it to report errors
* @return the created parameters, or null if they cannot be created
* @see JiraWebActionSupport#addError
* @see JiraWebActionSupport#addErrorMessage
* @see StructureUtil#getSingleParameter
* @see StructureUtil#getSingleParameterLong
* @see StructureUtil#getSingleParameterBoolean
*/
@Nullable
Object buildParametersFromForm(@NotNull Map formParameters, @NotNull JiraWebActionSupport action);
/**
* Adds to the map the default values for the parameters in the synchronizer parameters form.
* The default values then will be available for the synchronizer's <form> the first time
* it's loaded.
*
* @param params the map of parameters that the synchronizer can add to
*/
void addDefaultFormParameters(@NotNull Map params);
/**
* Converts an instance's parameters object to a parameter map for the "Edit Synchronizer' form.
* This is the inverse of {@link #buildParametersFromForm}, which is always called after this method to validate the
* resulting form and collect error messages.
* @param syncParams synchronizer parameters object
* @param formParams writable map to put form parameters into
*/
void addFormParameters(@Nullable Object syncParams, @NotNull Map formParams);
/**
* Perform full resync.
*
* This method is called when the user request full resync or runs Import or Export.
*
* The implementation of this method should make structure and other aspect of an issue synchronized,
* inspecting and making changes to all issues that are subject for synchronization according to the
* synchronizer's configuration.
*
* The implementation should detect the resync direction on its own: if only one direction is supported, then
* this direction should be used; if both directions are supported, the direction should be specified in the parameters.
*
* @param instance the configured instance of the synchronizer
* @param forestSource the source from which to retrieve {@link Forest} for
* the synchronized structure and to which to apply Structure updates
* @see StructureSyncManager#resync
*/
void resync(@NotNull SyncInstance instance, @NotNull ForestSource forestSource) throws StructureException;
/**
* Perform incremental synchronization.
*
* This method is called when the synchronizer is installed and enabled, and sync manager detects changes
* in the structure or in any of the tracked items since the last run.
* The synchronizer can use the updates to check only those items that have been affected and also to choose the
* direction of the synchronization based on where the changes have occurred.
* The update is never empty - there is at least one JIRA or Structure change. The Structure changes are specified
* up to the version of the forest contained in the data.
*
* The process is decoupled from the changing thread; the synchronization is run as a separate background
* job with {@link StructureJobManager} shortly after the changes have taken place. In JIRA Data Center,
* the synchronizer might run on a different node from the one where the changes were made.
* @param instance the configured instance of the synchronizer
* @param data the changes since the last incremental synchronization or resync - in JIRA and in Structure
* @param forestSource the source from which to retrieve {@link Forest} for
*/
void sync(@NotNull SyncInstance instance, @NotNull IncrementalSyncData data, @NotNull ForestSource forestSource)
throws StructureException;
}