Interface StructureManager


@PublicApi public interface StructureManager

StructureManager is the main component used to manage structures as entities. To access and manage structure contents - its forest, a hierarchical list of items, - see ForestService.

A Structure is a named entity that has properties like name, description and permissions. Methods in this interface allow creating/removing structures and changing those properties.

Unless otherwise stated, all methods are thread-safe. Note that the methods of the Structure interface are not thread-safe - you need to retrieve a separate instance in every thread where you need it.

All methods that return Structure instances return new independent instances every time they are called.

All methods check permissions for the current user as returned by StructureAuth.getUser(), unless permission checking is turned off by setting StructureAuth.isSecurityOverridden() flag (useful if you are writing an administrative task - see StructureAuth.sudo(ApplicationUser, boolean, CallableE)).

Examples

Creating a structure:

   Structure newStructure = 
     structureManager.createStructure().setName("structureName").saveChanges();
 

Changing a structure:

   List<Structure> structures =
     structureManager.getStructuresByName("hideme", ADMIN);
   for (Structure s : structures) {
     s.setPermissions(Collections.emptyList()).saveChanges();
   }
 
Author:
Igor Sereda
See Also:
  • Method Details

    • getStructure

      @NotNull Structure getStructure(@Nullable Long structureId, @Nullable PermissionLevel requiredLevel) throws StructureException

      Retrieves a structure given structure ID. Throws exception if the structure does not exist or is not accessible.

      The second parameter allows to specify the required permission level for the current user.

      Unless StructureAuth.isSecurityOverridden() is true, we also check if the user has access to Structure plugin.

      Every call to getStructure() will return a new instance of Structure, which will contain a snapshot of the structure's properties. You shouldn't keep that instance around for long, because any changes to the structure, made by other code in parallel, will not be reflected in this snapshot instance.

      Parameters:
      structureId - the ID of the structure, nullable for convenience (if null, will throw StructureException)
      requiredLevel - when checking for user's permission, require that the user has at least the specified permission. Passing null of PermissionLevel.NONE effectively disables the structure permissions check, but we still check that the user has access to Structure plugin (unless StructureAuth.isSecurityOverridden() is true).
      Returns:
      an instance of a structure, not null
      Throws:
      StructureException - if structure is not found, or the user is not allowed to use Structure, or the user does not have the required access level to this structure, or if any other problem is encountered
    • getAllStructures

      @NotNull List<Structure> getAllStructures(@Nullable PermissionLevel requiredLevel)

      Retrieves a list of all unarchived structures that are accessible to the current user at the specified permission level.

      The method scans all existing structures, selects unarchived ones and checks permissions. If the user has no access to Structure plugin, returns empty list. If StructureAuth.isSecurityOverridden() is true, ignores all of the checks above and returns all unarchived structures.

      The resulting list is sorted by name, using the current user's locale.

      Parameters:
      requiredLevel - when checking for user's permission, require that the user has at least the specified permission for every structure in the returned list. Passing null of PermissionLevel.NONE effectively disables the structure permissions check, but we still check that the user has access to Structure plugin (unless StructureAuth.isSecurityOverridden() is true).
      Returns:
      a list of unarchived structures available to the user, not null
      See Also:
    • getAllStructures

      @NotNull List<Structure> getAllStructures(@Nullable PermissionLevel requiredLevel, boolean includeArchived)

      Retrieves a list of all structures that are visible to the current user at the specified permission level.

      The method scans all existing structures and checks permissions. If the user has no access to Structure plugin, returns empty list. If StructureAuth.isSecurityOverridden() is true, ignores all of the checks above and returns all structures (or only unarchived, depending on the parameter).

      The resulting list is sorted by name, using the current user's locale.

      Parameters:
      requiredLevel - when checking for user's permission, require that the user has at least the specified permission for every structure in the returned list. Passing null of PermissionLevel.NONE effectively disables the structure permissions check, but we still check that the user has access to Structure plugin (unless StructureAuth.isSecurityOverridden() is true).
      includeArchived - if true, result will also contain archived structures
      Returns:
      a list of structures available to the user, not null
    • getArchivedStructures

      @NotNull List<Structure> getArchivedStructures(@Nullable PermissionLevel requiredLevel)

      Retrieves a list of all archived structures that are visible to the current user at the specified permission level.

      The method scans all existing structures, selects archived ones and checks permissions. If the user has no access to Structure plugin, returns empty list. If StructureAuth.isSecurityOverridden() is true, ignores all of the checks above and returns all archived structures.

      The resulting list is sorted by name, using the current user's locale.

      Parameters:
      requiredLevel - when checking for user's permission, require that the user has at least the specified permission for every structure in the returned list. Passing null of PermissionLevel.NONE effectively disables the structure permissions check, but we still check that the user has access to Structure plugin (unless StructureAuth.isSecurityOverridden() is true).
      Returns:
      a list of archived structures available to the user, not null
    • getStructuresOwnedBy

      @NotNull List<Structure> getStructuresOwnedBy(@Nullable ApplicationUser user)

      Retrieves a list of all structures visible to the current user, for which the specified user is the owner.

      The method scans all existing structures and looks for those that are owned by the specified user and visible to the current user. If the user has no access to Structure plugin, returns empty list. If StructureAuth.isSecurityOverridden() is true, ignores all of the checks above and returns all structures that the specified user owns.

      The resulting list is sorted by name, using the current user's locale.

      Parameters:
      user - owner of the structures to look for
      Returns:
      a list of structures owned by the specified user, not null
      See Also:
    • getStructuresByName

      @NotNull List<Structure> getStructuresByName(@Nullable String name, @Nullable PermissionLevel requiredLevel)

      Convenience method to search for unarchived structures with the specified name. Using this method is more efficient than retrieving all structures and filtering.

      Structures are not required to have unique names, therefore this method returns a list.

      Returns only structures for which the current user has access at the specified permission level. If the user has no access to Structure plugin, returns empty list. If StructureAuth.isSecurityOverridden() is true, ignores all of the checks above.

      The resulting list is sorted by name, using the current user's locale.

      Parameters:
      name - the name of the structure sought, case-insensitive and trim-insensitive (leading and trailing whitespace don't matter). If null, an empty list is returned.
      requiredLevel - when checking for user's permission, require that the user has at least the specified permission for every structure in the returned list. Passing null or PermissionLevel.NONE effectively disables the structure permissions check, but we still check that the user has access to Structure plugin (unless StructureAuth.isSecurityOverridden() is true).
      Returns:
      a list of the matching unarchived structures
    • getStructuresByName

      @NotNull List<Structure> getStructuresByName(@Nullable String name, @Nullable PermissionLevel requiredLevel, boolean searchArchivedStructures)

      Convenience method that searches for structures with the specified name. It is more efficient than retrieving all structures and filtering.

      Structures are not required to have unique names, therefore this method returns a list.

      Returns only structures for which the current user has access at the specified permission level. If the user has no access to Structure plugin, returns empty list. If StructureAuth.isSecurityOverridden() is true, ignores all of the checks above.

      The resulting list is sorted by name, using the current user's locale.

      Parameters:
      name - the name of the structure sought, case-insensitive and trim-insensitive (leading and trailing whitespace don't matter). If null, an empty list is returned.
      requiredLevel - when checking for user's permission, require that the user has at least the specified permission for every structure in the returned list. Passing null or PermissionLevel.NONE effectively disables the structure permissions check, but we still check that the user has access to Structure plugin (unless StructureAuth.isSecurityOverridden() is true).
      searchArchivedStructures - if true, result will also contain archived structures
      Returns:
      a list of the matching unarchived structures
    • hasNonArchivedStructuresForUser

      boolean hasNonArchivedStructuresForUser()

      Convenience method that checks whether the current user can see at least one unarchived structure. This works functionally the same as !getAllStructures(PermissionLevel.VIEW).isEmpty(), but much faster.

      If the user has no access to Structure plugin, returns false. (Unless StructureAuth.isSecurityOverridden() is on, in which case user's access to Structure is not checked.)

      Returns:
      true if the current user has access to the Structure plugin (this check is skipped if StructureAuth.isSecurityOverridden() is true) and if there exists at least one unarchived structure, to which the current user has PermissionLevel.VIEW access.
    • getSingleViewableStructureId

      @Nullable Long getSingleViewableStructureId()

      Convenience method that returns the ID of a single structure that the current user can see. This works much faster than getAllStructures(PermissionLevel.VIEW).

      If the user does not have PermissionLevel.VIEW access to any structure, or if the user has the access to more than one structure, this method returns null. Also, if the user has no access to the Structure plugin, returns null.

      Note that the resulting structure may be archived.

      Note that this method ignores StructureAuth.isSecurityOverridden(), unlike most other methods.

      Returns:
      the ID of the structure that the current user can see, only if it's the only one; null otherwise
    • isIssueInStructureNoAccessCheck

      boolean isIssueInStructureNoAccessCheck(@Nullable Long issueId, @Nullable Long structureId)

      Checks if a specific issue (not row!) belongs to a specific structure.

      Only issues that have been manually added to the structure are checked. Issues that have been added or removed by generators are not checked.

      This method does not perform any permission checks.

      Parameters:
      issueId - the ID of the issue. Nullable for convenience - if null, returns false
      structureId - the ID of the structure. Nullable for convenience - if null, returns false
      Returns:
      true if the the issue is in the structure
    • getViewableStructuresWithIssue

      @NotNull List<Structure> getViewableStructuresWithIssue(@Nullable Long issueId)

      Retrieves all structures that contain the specified issue. This is functionally the same as checking every forest manually, but much faster.

      Only issues that have been manually added to the structure are checked. Issues that have been added or removed by generators are not checked.

      Note that forest changes may happen asynchronously, so consistency for the returned list is not guaranteed. All we can say is that each structure in the returned list either contains the specified issue or has contained it recently.

      This method returns only the structures that the current user can see. If the user has no access to Structure plugin, returns empty list. If StructureAuth.isSecurityOverridden() is true, these checks are not performed.

      The resulting list is sorted by name, using the current user's locale.

      Parameters:
      issueId - the ID of the issue. Nullable for convenience - if null, returns empty list
      Returns:
      a list of structures, visible to the current user, containing the specified issue, not null
    • getStructurePermission

      @NotNull PermissionLevel getStructurePermission(@Nullable Long structureId)

      Calculates access level to a structure for the current user. If the user is not allowed to use Structure plugin, the result will always be PermissionLevel.NONE.

      Note that this method ignores StructureAuth.isSecurityOverridden(), unlike most other methods.

      Parameters:
      structureId - the ID of the structure checked. Nullable for convenience - if null, returns NONE
      Returns:
      the calculated access level, not null
    • getStructurePermission

      @NotNull PermissionLevel getStructurePermission(@Nullable Long structureId, @Nullable ApplicationUser user)

      Calculates access level to a structure for the specified user. If the user is not allowed to use Structure plugin, the result will always be PermissionLevel.NONE.

      Note that StructureAuth.isSecurityOverridden() is not applicable here.

      Parameters:
      structureId - the ID of the structure checked. Nullable for convenience - if null, returns NONE
      user - the user to check permissions for, null for anonymous
      Returns:
      the calculated access level, not null
    • isAccessible

      boolean isAccessible(@Nullable Long structureId, @Nullable PermissionLevel requiredLevel)

      Checks that the specified structure exists and the current user has access to it with the required permission level.

      If structureId is null, or structure with that ID does not exist, false is returned.

      If the user has no access to Structure plugin, returns false (unless StructureAuth.isSecurityOverridden() is true).

      Parameters:
      structureId - the ID of the structure. Nullable for convenience - if null, returns false
      requiredLevel - when checking for user's permission, require that the user has at least the specified permission level for the structure. Passing null or PermissionLevel.NONE effectively disables the structure permissions check, but we still check that the user has access to Structure plugin (unless StructureAuth.isSecurityOverridden() is true).
      Returns:
      true if the specified structure exists and the user has access to it with the specified access level
    • isGeneratorConfigurationAllowed

      boolean isGeneratorConfigurationAllowed(@Nullable Long structureId, @Nullable ApplicationUser user)

      Checks that the specified user has the CONFIGURE_GENERATORS app permission and has at least AUTOMATE access level to the specified structure.

      Note that StructureAuth.isSecurityOverridden() is not applicable here.

      Parameters:
      structureId - the ID of the structure checked. Nullable for convenience - if null, returns false
      user - the user to check permissions for, null for anonymous
      Returns:
      true if the specified user is able to configure generators for the specified structure
    • isEffectorConfigurationAllowed

      boolean isEffectorConfigurationAllowed(@Nullable Long structureId, @Nullable ApplicationUser user)

      Checks that the specified user has the CONFIGURE_EFFECTORS app permission and has at least AUTOMATE access level to the specified structure.

      Note that StructureAuth.isSecurityOverridden() is not applicable here.

      Parameters:
      structureId - the ID of the structure checked. Nullable for convenience - if null, returns false
      user - the user to check permissions for, null for anonymous
      Returns:
      true if the specified user is able to configure effectors for the specified structure
    • isEffectorExecutionAllowed

      boolean isEffectorExecutionAllowed(@Nullable Long structureId, @Nullable ApplicationUser user)

      Checks that the specified user has the EXECUTE_EFFECTORS app permission and has at least VIEW access level to the specified structure.

      Note that StructureAuth.isSecurityOverridden() is not applicable here.

      Parameters:
      structureId - the ID of the structure checked. Nullable for convenience - if null, returns false
      user - the user to check permissions for, null for anonymous
      Returns:
      true if the specified user is able to execute effectors for the specified structure
    • createStructure

      @NotNull Structure createStructure()

      Creates an empty new structure. The structure returned is not yet persisted - you need to call the required setter methods and then call Structure.saveChanges() to write the new structure to the database and be able to fill it with items.

      The structure will have the current user as its owner. This method checks that the current user can use Structure plugin and can create structures, unless StructureAuth.isSecurityOverridden() is true.

      Note that in order to write the contents of the structure you need to obtain an instance of ForestSource from ForestService:

         StructureManager sm = ...
         ForestService fs = ...
         Structure s = sm.createStructure().setName("new structure").saveChanges();
         ForestSpec spec = ForestSpec.structure(s.getId());
         ForestSource ufs = fs.getForestSource(spec);
         ufs.apply(new Add(CoreIdentities.issue(issueId), 0, 0, 0));
       
    • copyStructure

      @NotNull Structure copyStructure(@Nullable Long structureId, @Nullable ApplicationUser newOwner, boolean copyPermissions) throws StructureException

      Copies the structure and the forest it contains into a new structure.

      This method checks that the current user has all required permissions: to use Structure plugin, to create structures, and to view the copied structure; also, requires PermissionLevel.ADMIN access to copy permissions. All these checks are not performed if StructureAuth.isSecurityOverridden() is true.

      Parameters:
      structureId - the ID of the structure. Nullable for convenience - if null, throws exception
      newOwner - the user who will be the owner of the new structure, if null - keep the old owner
      copyPermissions - if true, the permission list will be copied - this requires ADMIN permission level to the original structure, if the user does not have it, StructureException is thrown
      Returns:
      the freshly created structure. You can use Structure.getId() to learn its ID
      Throws:
      StructureException - if the copied structure doesn't exist, the user has not enough permissions, or any other problem happens
    • copyStructureWithoutForest

      @NotNull Structure copyStructureWithoutForest(@Nullable Long structureId, @Nullable ApplicationUser newOwner, boolean copyPermissions) throws StructureException

      Copies the structure into a new structure - only the properties (such as name, description, permissions) are copied, not the forest.

      This method checks that the current user has all required permissions: to use Structure plugin, to create structures, and to view the copied structure; also, requires PermissionLevel.ADMIN access to copy permissions. All these checks are not performed if StructureAuth.isSecurityOverridden() is true.

      Parameters:
      structureId - the ID of the structure. Nullable for convenience - if null, throws exception
      newOwner - the user who will be the owner of the new structure, if null - keep the old owner
      copyPermissions - if true, the permission list will be copied - this requires ADMIN permission level to the original structure, if the user does not have it, StructureException is thrown
      Returns:
      the freshly created structure. You can use Structure.getId() to learn its ID
      Throws:
      StructureException - if the copied structure doesn't exist, the user has not enough permissions, or any other problem happens
    • deleteStructure

      void deleteStructure(@Nullable Long id) throws StructureException

      Deletes the specified structure and its content.

      JIRA items such as issues or projects are not themselves deleted. Structure-owned items such as folders or generators are deleted.

      This method checks that the current user can use Structure plugin and has PermissionLevel.ADMIN access to the specified structure. These checks are waived if StructureAuth.isSecurityOverridden() is true.

      This method will dispatch the StructureDeletedEvent after structure deleting. An event listener can be registered using JIRA notification system.

      Parameters:
      id - the ID of the structure. Nullable for convenience - if null, throws exception
      Throws:
      StructureException - if the structure doesn't exist, is not accessible at ADMIN permission level, or there's problem deleting structure
    • addListener

      void addListener(@NotNull StructureListener listener)

      Adds a structure listener. Whenever structure's static content is changed, the listeners are called synchronously after the changes are persisted.

      See StructureListener for details about listener contract.

      Parameters:
      listener - the listener
      See Also:
    • removeListener

      void removeListener(@NotNull StructureListener listener)

      Removes the listener previously added via addListener(StructureListener).

      Parameters:
      listener - listener to be removed