/src/main/java/com/atlassian/jconnect/jira/IssueHelper.java
Java | 293 lines | 244 code | 40 blank | 9 comment | 28 complexity | 253aaaeec854ec3996ad7cd48d1a2e68 MD5 | raw file
- package com.atlassian.jconnect.jira;
-
- import com.atlassian.core.util.FileUtils;
- import com.atlassian.crowd.embedded.api.User;
- import com.atlassian.jconnect.rest.entities.IssueEntity;
- import com.atlassian.jconnect.rest.entities.UploadData;
- import com.atlassian.jira.bc.issue.comment.CommentService;
- import com.atlassian.jira.bc.project.component.ProjectComponent;
- import com.atlassian.jira.bc.project.component.ProjectComponentManager;
- import com.atlassian.jira.config.ConstantsManager;
- import com.atlassian.jira.event.type.EventDispatchOption;
- import com.atlassian.jira.exception.CreateException;
- import com.atlassian.jira.exception.UpdateException;
- import com.atlassian.jira.issue.*;
- import com.atlassian.jira.issue.fields.CustomField;
- import com.atlassian.jira.issue.issuetype.IssueType;
- import com.atlassian.jira.issue.label.Label;
- import com.atlassian.jira.project.DefaultAssigneeException;
- import com.atlassian.jira.project.Project;
- import com.atlassian.jira.project.ProjectManager;
- import com.atlassian.jira.project.version.Version;
- import com.atlassian.jira.project.version.VersionManager;
- import com.atlassian.jira.util.ErrorCollection;
- import com.atlassian.jira.util.SimpleErrorCollection;
- import com.atlassian.jira.web.util.AttachmentException;
- import com.google.common.collect.ImmutableMap;
- import org.ofbiz.core.entity.GenericEntityException;
- import org.ofbiz.core.entity.GenericValue;
- import org.slf4j.Logger;
- import org.slf4j.LoggerFactory;
-
- import java.io.File;
- import java.io.IOException;
- import java.util.*;
- import java.util.regex.Pattern;
-
- /**
- * Handles some common issue operations.
- */
- public class IssueHelper
- {
- private static final Logger log = LoggerFactory.getLogger(IssueHelper.class);
- private static final Map<String, String> SUPPORTED_ATTACHMENT_TYPE_SUFFIXES;
-
- public static final String ENVIRONMENT_FORMAT = "Model: %s\n" +
- "OS Version: %s\n" +
- "App Version: %s\n" +
- "Language: %s\n";
-
- // TODO: all this (and more?) should be stored using ActiveObjects for version 1.0-Final.
- // ActiveObjects is currently not in JIRA 4.3
- public static final Pattern ENV_FIELD_PATTERN =
- Pattern.compile("Model: (.*)[\r\n]*" +
- "OS Version: (.*)[\r\n]*" +
- "App Version: (.*)[\r\n]*", Pattern.MULTILINE);
-
-
-
- static
- {
- final Map<String, String> typeSuffixes = new HashMap<String, String>();
- typeSuffixes.put("image/gif", ".gif");
- typeSuffixes.put("image/jpeg", ".jpg");
- typeSuffixes.put("image/png", ".png");
- typeSuffixes.put("audio/x-caf", ".caf");
- typeSuffixes.put("audio/mpeg", ".mp3");
- typeSuffixes.put("audio/x-wav", ".wav");
- SUPPORTED_ATTACHMENT_TYPE_SUFFIXES = ImmutableMap.copyOf(typeSuffixes);
- }
-
-
- private static String getContentTypeFileSuffix(String contentType)
- {
- return SUPPORTED_ATTACHMENT_TYPE_SUFFIXES.get(contentType);
- }
-
- private final IssueManager issueManager;
- private final AttachmentManager attachmentManager;
- private final ProjectManager projectManager;
- private final VersionManager versionManager;
- private final ConstantsManager constantsManager;
- private final IssueFactory issueFactory;
- private final CommentService commentService;
- private final ProjectComponentManager componentManager;
-
- public IssueHelper(IssueManager issueManager, AttachmentManager attachmentManager,
- final ProjectManager projectManager, final VersionManager versionManager,
- final ConstantsManager constantsManager, final IssueFactory issueFactory,
- final CommentService commentService, ProjectComponentManager componentManager)
- {
- this.issueManager = issueManager;
- this.attachmentManager = attachmentManager;
- this.projectManager = projectManager;
- this.versionManager = versionManager;
- this.constantsManager = constantsManager;
- this.issueFactory = issueFactory;
- this.commentService = commentService;
- this.componentManager = componentManager;
- }
-
- public MutableIssue getIssue(String issueKey)
- {
- return issueManager.getIssueObject(issueKey);
- }
-
- public Issue createIssue(IssueEntity issueEntity,
- CustomField uuid,
- Project project,
- User user,
- List<CustomField> customFields,
- List<Object> customValues)
- throws AttachmentException, IOException, GenericEntityException, CreateException
- {
-
- final IssueType issueType = resolveIssueType(issueEntity);
- final MutableIssue issue = issueFactory.getIssue();
-
- final HashMap<String, Version> allVersions = new HashMap<String, Version>();
- final Version appVersion = getVersionNamed(project.getId(), issueEntity.getAppVersion());
- final Version appShortVersion = getVersionNamed(project.getId(), issueEntity.getAppVersionShort());
-
- addIfNonNull(allVersions, appVersion);
- addIfNonNull(allVersions, appShortVersion);
-
- // set issue fields
- issue.setProjectId(project.getId());
- issue.setIssueTypeId(issueType.getId());
- issue.setAffectedVersions(allVersions.values());
- final Collection<ProjectComponent> components = setProjectComponents(issueEntity, project, issue);
-
- final String appVersionName = issueEntity.getAppVersionShort() != null ? // use short if provided, else use AppVersion.
- issueEntity.getAppVersionShort() : issueEntity.getAppVersion();
- final String env = String.format(ENVIRONMENT_FORMAT,
- issueEntity.getModel(),
- issueEntity.getSystemVersion(),
- appVersionName,
- issueEntity.getLanguage());
- issue.setEnvironment(env);
- issue.setSummary(issueEntity.getSummary());
- issue.setDescription(issueEntity.getDescription());
- issue.setReporter(user);
- setDefaultAssignee(project, issue, components);
-
- final Set<Label> labels = new HashSet<Label>(3);
- addLabel(labels, "", issueEntity.getSystemVersion());
- addLabel(labels, "", issueEntity.getModel());
- addLabel(labels, "", issueEntity.getLanguage());
- addLabel(labels, "build-", issueEntity.getAppVersion()); // appVersionShort is known as the 'marketing version' appVersion is the build number.
- issue.setLabels(labels);
-
- for (int i = 0; i < customFields.size(); i++) {
- final CustomField field = customFields.get(i);
- final Object value = customValues.get(i);
- log.debug("Setting customfield: " + field.getName() + " = " + value);
- if (field.getRelevantConfig(issue) != null) {
- issue.setCustomFieldValue(field, value);
- } else {
- log.debug("Field " + field.getName() + " is missing a configuration context for project: " + project.getName() +
- ". This field wont be added to the issue.");
- }
- }
- // ensure the uuid is always set. ie. overwrite any uuid fields previously set above.
- if (uuid != null && uuid.getRelevantConfig(issue) != null) {
- issue.setCustomFieldValue(uuid, issueEntity.getUuid());
- } else {
- final String missingUUIDMessage = "\n*NB " +
- project.getName() + " is missing the custom field called uuid. " +
- "JIRAConnect uses this to map mobile users to issues. Without this field, " +
- "users will not receive any In-App issue comments.*";
- issue.setEnvironment(issue.getEnvironment() + "\n" + missingUUIDMessage);
- log.warn(missingUUIDMessage);
- }
- // store the issue
- issueManager.createIssue(user, issue);
-
- log.debug(String.format("User %s created issue %s: %s", user.getName(), issue.getKey(), issue.getSummary()));
-
- return issue;
- }
-
- private void setDefaultAssignee(Project project, MutableIssue issue, Collection<ProjectComponent> components) {
-
- final User defaultAssignee;
- try {
- defaultAssignee = projectManager.getDefaultAssignee(project, components);
- if (defaultAssignee != null) {
- issue.setAssignee(defaultAssignee);
- }
- } catch (DefaultAssigneeException e) {
- log.info("Not setting default assignee on issue: " + issue.getKey() + " due to: " + e.getLocalizedMessage());
- }
-
- }
-
- private void addIfNonNull(Map<String, Version> allVersions, Version appVersion) {
- if (appVersion != null) {
- allVersions.put(appVersion.getName(), appVersion);
- }
- }
-
- private Version getVersionNamed(Long projectId, String name) {
- if (name == null) {
- return null;
- }
- final Collection<Version> versions = versionManager.getVersions(projectId);
- for (Iterator<Version> iterator = versions.iterator(); iterator.hasNext(); ) {
- final Version next = iterator.next();
- if (name.equals(next.getName())) {
- return next;
- }
- }
- return null;
- }
-
- private void addLabel(Set<Label> labels, String prefix, String value) {
- if (value != null) {
- final String label = value.replaceAll("\\s", "-");
- labels.add(new Label(null, null, prefix + label));
- }
- }
-
- private Collection<ProjectComponent> setProjectComponents(IssueEntity issueEntity, Project project, MutableIssue issue) {
- final Collection<ProjectComponent> projectComponents = new ArrayList<ProjectComponent>();
- if (issueEntity.getComponents() != null)
- {
- String[] comps = issueEntity.getComponents();
- final Collection<GenericValue> components = new ArrayList<GenericValue>(comps.length);
- for (int i = 0; i < comps.length; i++) {
- final String compName = comps[i];
- final ProjectComponent component = componentManager.findByComponentName(project.getId(), compName);
- if (component != null) {
- components.add(component.getGenericValue());
- projectComponents.add(component);
- }
- }
- issue.setComponents(components);
- }
- return projectComponents;
- }
-
- private IssueType resolveIssueType(IssueEntity issueEntity) {
- final Collection<IssueType> types = constantsManager.getAllIssueTypeObjects();
- for (IssueType next : types) {
- if (next.getName().equalsIgnoreCase(issueEntity.getType())) {
- return next;
- }
- }
- return types.iterator().next(); // if none are matching, return the first issue type. This should be BUG.
- }
-
- public void addAttachment(Issue issue, UploadData data, User user) throws IOException, AttachmentException, GenericEntityException
- {
- final File attachmentFile = File.createTempFile("jconnect-" + issue.getKey() + "-", getContentTypeFileSuffix(data.getContentType()));
- FileUtils.copyFile(data.getInputStream(), attachmentFile, true);
- attachmentManager.createAttachment(attachmentFile, data.getFilename(), data.getContentType(), user, issue.getGenericValue());
-
- log.debug(String.format("User %s attached %s to %s", user.getName(), data.getFilename(), issue.getKey()));
- }
-
- public ErrorCollection updateIssue(MutableIssue issue, IssueEntity issueEntity, User user) throws UpdateException {
- final ErrorCollection errors = new SimpleErrorCollection();
- // add any new versions that may exist
- final Long projectId = issue.getProjectObject().getId();
-
- final Map<String, Version> uniqueVersions = new HashMap<String, Version>();
- addIfNonNull(uniqueVersions, getVersionNamed(projectId, issueEntity.getAppVersion()));
- addIfNonNull(uniqueVersions, getVersionNamed(projectId, issueEntity.getAppVersionShort()));
-
- final Collection<Version> affectedVersions = issue.getAffectedVersions();
- for (Iterator<Version> iterator = affectedVersions.iterator(); iterator.hasNext(); ) {
- addIfNonNull(uniqueVersions, iterator.next());
- }
- issue.setAffectedVersions(uniqueVersions.values());
-
- issueManager.updateIssue(user, issue, EventDispatchOption.ISSUE_UPDATED, true);
- return errors;
- }
-
- public ErrorCollection addComment(Issue issue, String bodyText, User user) {
- ErrorCollection errors = new SimpleErrorCollection();
- commentService.create(user, issue, bodyText, true, errors);
- log.debug("Comment was: " + bodyText);
- return errors;
- }
-
- public Project lookupProjectByName(String projectName) {
- return projectManager.getProjectObjByName(projectName);
- }
-
- public Project lookupProjectByKey(String projectKey) {
- return projectManager.getProjectObjByKey(projectKey);
- }
- }