Skip to content

Instantly share code, notes, and snippets.

@leonardinius
Created December 18, 2010 23:40
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save leonardinius/746976 to your computer and use it in GitHub Desktop.
Save leonardinius/746976 to your computer and use it in GitHub Desktop.
Issue Crud Operation interface
public interface IssueCrudOperations
{
/**
* Used to create new Issue instance
* <p/>
* PS: Do not stores issue in the database (launch workflow Create action).
* <p/>
* Use {@link #storeNewIssue(com.opensymphony.user.User, com.atlassian.jira.issue.MutableIssue)} to store object.
*/
MutableIssue makeNewIssue(@NotNull String issueType, @NotNull Project projectObject, @NotNull String summary) throws CreateException;
/**
* Used to update <strong>existing issues</strong>.
* Use {@link #storeNewIssue(com.opensymphony.user.User, com.atlassian.jira.issue.MutableIssue)} to persist new issue instances.
*/
void saveIssue(User actionUser, @NotNull MutableIssue issueObject, boolean dispatchEvent) throws JiraException;
MutableIssue storeNewIssue(User actionUser, @NotNull MutableIssue issueObject) throws CreateException;
void updateIssueValues(User actionUser, @NotNull MutableIssue issue,
@NotNull Map<String, Object> fieldValues) throws JiraException;
}
public class IssueCrudOperationsImpl implements IssueCrudOperations
{
// ------------------------------ FIELDS ------------------------------
private final IssueManager issueManager;
private final FieldManager fieldManager;
private final CustomFieldManager customFieldManager;
private final FieldLayoutManager fieldLayoutManager;
private final IssueFactory issueFactory;
private final IssueSecurityLevelManager issueSecurityLevelManager;
private final ConstantsManager constantsManager;
private final Logger log = LoggerFactory.getLogger(IssueCrudOperationsImpl.class);
// --------------------------- CONSTRUCTORS ---------------------------
public IssueCrudOperationsImpl(final ProjectManager projectManager, final IssueManager issueManager, final FieldManager fieldManager,
final CustomFieldManager customFieldManager, final FieldLayoutManager fieldLayoutManager, final IssueFactory issueFactory,
final IssueSecurityLevelManager issueSecurityLevelManager, final ConstantsManager constantsManager)
{
this.issueManager = issueManager;
this.fieldManager = fieldManager;
this.customFieldManager = customFieldManager;
this.fieldLayoutManager = fieldLayoutManager;
this.issueFactory = issueFactory;
this.issueSecurityLevelManager = issueSecurityLevelManager;
this.constantsManager = constantsManager;
}
// ------------------------ INTERFACE METHODS ------------------------
// --------------------- Interface IssueCrudOperations ---------------------
@Override
public MutableIssue makeNewIssue(@NotNull final String issueType, @NotNull final Project projectObject,
@NotNull final String summary) throws CreateException
{
final MutableIssue issueObject;
try
{
//noinspection deprecation
final GenericValue projectGv = projectObject.getGenericValue();
//noinspection deprecation
final GenericValue issueTypeGv = getIssueTypeObject(issueType).getGenericValue();
//noinspection deprecation
final String summaryText = StringUtils.trimToNull(checkPrepareSummary(summary));
// the issueObject is created here, because it moves issueKey forward on the database level;
issueObject = issueFactory.getIssue();
issueObject.setProject(projectGv);
issueObject.setIssueType(issueTypeGv);
issueObject.setSummary(summaryText);
setDefaultSecurityLevel(issueObject);
}
catch (GeneralException e)
{
throw new CreateException(e);
}
catch (IllegalArgumentException e)
{
throw new CreateException(e);
}
return applyCustomFieldDefaultValues(issueObject);
}
@Override
public void saveIssue(final User actionUser, final MutableIssue issueObject, final boolean dispatchEvent) throws JiraException
{
final Map<String, Object> actionParams = ImmutableMap.of(
"issue", issueObject.getGenericValue(),
"issueObject", issueObject,
"remoteUser", actionUser,
"dispatchEvent", dispatchEvent);
try
{
final ActionResult aResult = getActionDispatcher().execute(ActionNames.ISSUE_UPDATE, Maps.newHashMap(actionParams));
ActionUtils.checkForErrors(aResult);
}
catch (Exception e)
{
throw new JiraException(e);
}
}
@Override
@SuppressWarnings({"deprecation"})
public MutableIssue storeNewIssue(final User actionUser, final MutableIssue issueObject)
throws CreateException
{
final Map<String, Object> fields = Maps.newHashMap();
fields.put("issue", issueObject);
// TODO: How is this supposed to work? There is no issue created yet; ID = null.
fields.put(WorkflowFunctionUtils.ORIGINAL_ISSUE_KEY, issueFactory.getIssue(issueManager.getIssue(issueObject.getId())));
final GenericValue issueGv = issueManager.createIssue(actionUser, fields);
return issueManager.getIssueObject(GenericValueUtils.transformToLongIds(ImmutableList.of(issueGv))[0]);
}
@Override
public final void updateIssueValues(final User actionUser, final MutableIssue issue,
final Map<String, Object> fieldValues) throws JiraException
{
Assertions.notNull("Issue", issue);
Assertions.notNull("Issue data", fieldValues);
//noinspection ConstantConditions
for (final Map.Entry<String, Object> entry : fieldValues.entrySet())
{
try
{
doSetFieldValue(actionUser, issue, entry.getKey(), entry.getValue());
}
catch (FieldException e)
{
throw new JiraException(e);
}
catch (FieldLayoutStorageException e)
{
throw new JiraException(e);
}
}
}
// -------------------------- OTHER METHODS --------------------------
private MutableIssue applyCustomFieldDefaultValues(final MutableIssue issueObject)
{
// Give the CustomFields a chance to set their default values JRA-11762
final List<CustomField> customFieldObjects = customFieldManager.getCustomFieldObjects(issueObject);
for (final CustomField customField : customFieldObjects)
{
issueObject.setCustomFieldValue(customField, customField.getDefaultValue(issueObject));
}
return issueObject;
}
private String checkPrepareSummary(final String summary)
{
Assertions.notBlank("Summary field", summary);
if (summary != null && summary.length() > SummarySystemField.MAX_LEN.intValue())
{
log.warn("Truncating summary field because it is too long: " + summary);
return summary.substring(0, SummarySystemField.MAX_LEN.intValue() - 3) + "...";
}
return summary;
}
private void doSetFieldValue(final User actionUser, final MutableIssue issue, final String fieldIdName,
final Object fieldValue) throws FieldException, FieldLayoutStorageException
{
Assertions.notNull("Issue object", issue);
final CustomField cf;
if (CustomFieldUtils.getCustomFieldId(fieldIdName) != null)
{
cf = getCustomFieldById(actionUser, issue, fieldIdName);
}
else
{
cf = getCustomFieldByName(actionUser, issue, fieldIdName);
}
if (cf != null)
{
updateCustomField(issue, cf, fieldValue);
}
else
{
// supposed to be id in this case
final OrderableField field = fieldManager.getOrderableField(fieldIdName);
Assertions.not("Could not locate system field object (field: " + fieldIdName + ")", field == null);
updateSystemField(issue, field, fieldValue);
}
}
private CustomField getCustomFieldById(final User actionUser, final Issue issue, final String id) throws FieldException
{
return CommonUtils.findOrNull(getAvailableCustomFields(actionUser, issue), new Predicate<CustomField>()
{
@Override
public boolean apply(@Nullable final CustomField input)
{
return StringUtils.equals(id, input.getId());
}
});
}
private Set<CustomField> getAvailableCustomFields(final User actionUser, final Issue issue) throws FieldException
{
return fieldManager.getAvailableCustomFields(actionUser, issue);
}
private CustomField getCustomFieldByName(final User actionUser, final Issue issue, final String name) throws FieldException
{
return CommonUtils.findOrNull(getAvailableCustomFields(actionUser, issue), new Predicate<CustomField>()
{
@Override
public boolean apply(@Nullable final CustomField input)
{
return StringUtils.equals(name, input.getName());
}
});
}
private void updateCustomField(final MutableIssue issue, final CustomField cf, final Object value)
{
issue.setCustomFieldValue(cf, value);
if (issue.isCreated())
{
final FieldLayoutItem fieldLayoutItem = fieldLayoutManager.getFieldLayout(issue.getGenericValue()).getFieldLayoutItem(cf);
final Map<Object, Object> dataHolder = MapBuilder.<Object, Object>build(cf.getId(), new CustomFieldParamsImpl(cf, value));
if (!cf.hasValue(issue))
{
cf.createValue(issue, value);
}
cf.updateIssue(fieldLayoutItem, issue, dataHolder);
}
}
private void updateSystemField(final MutableIssue issue, final OrderableField field,
final Object fieldValue) throws FieldLayoutStorageException
{
final FieldLayoutItem fieldLayoutItem = fieldLayoutManager.getFieldLayout(
issue.getGenericValue()).getFieldLayoutItem(field);
final Map<Object, Object> dataHolder = Maps.newHashMapWithExpectedSize(2);
dataHolder.put(field.getId(), fieldValue);
if (!field.hasValue(issue))
{
field.createValue(issue, fieldValue);
}
field.updateIssue(fieldLayoutItem, issue, dataHolder);
}
private ActionDispatcher getActionDispatcher()
{
return CoreFactory.getActionDispatcher();
}
private IssueType getIssueTypeObject(final String issueType) throws GeneralException
{
final IssueType issueTypeObject = constantsManager.getIssueTypeObject(issueType);
if (issueTypeObject == null)
{
throw new GeneralException("Could not locate issue type: " + issueType);
}
return issueTypeObject;
}
private void setDefaultSecurityLevel(final MutableIssue issue) throws GeneralException
{
@SuppressWarnings({"deprecation"}) final GenericValue project = issue.getProject();
if (project != null)
{
final Long levelId = issueSecurityLevelManager.getSchemeDefaultSecurityLevel(project);
if (levelId != null)
{
issue.setSecurityLevel(issueSecurityLevelManager.getIssueSecurity(levelId));
}
}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment