package eu.doppel_helix.netbeans.mantisintegration.issue;
import biz.futureware.mantisconnect.AccountData;
import biz.futureware.mantisconnect.AttachmentData;
import biz.futureware.mantisconnect.CustomFieldDefinitionData;
import biz.futureware.mantisconnect.CustomFieldValueForIssueData;
import biz.futureware.mantisconnect.IssueData;
import biz.futureware.mantisconnect.IssueNoteData;
import biz.futureware.mantisconnect.ObjectRef;
import biz.futureware.mantisconnect.ProjectData;
import biz.futureware.mantisconnect.ProjectVersionData;
import biz.futureware.mantisconnect.RelationshipData;
import biz.futureware.mantisconnect.UserData;
import eu.doppel_helix.netbeans.mantisintegration.data.FlattenedProjectData;
import eu.doppel_helix.netbeans.mantisintegration.data.Permission;
import eu.doppel_helix.netbeans.mantisintegration.repository.MantisRepository;
import eu.doppel_helix.netbeans.mantisintegration.swing.AttachmentDisplay;
import org.jdesktop.swingx.JXHyperlink;
import eu.doppel_helix.netbeans.mantisintegration.swing.ListBackedComboBoxModel;
import eu.doppel_helix.netbeans.mantisintegration.swing.NoteDisplay;
import eu.doppel_helix.netbeans.mantisintegration.swing.RelationshipDisplay;
import eu.doppel_helix.netbeans.mantisintegration.swing.TagDisplay;
import eu.doppel_helix.netbeans.mantisintegration.util.SafeAutocloseable;
import java.awt.Component;
import java.awt.Desktop;
import java.awt.Dimension;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.beans.PropertyChangeEvent;
import java.beans.PropertyChangeListener;
import java.io.File;
import java.io.IOException;
import java.math.BigInteger;
import java.net.URI;
import java.rmi.RemoteException;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.logging.Logger;
import javax.swing.Box;
import javax.swing.JComponent;
import javax.swing.JFileChooser;
import javax.swing.JFrame;
import javax.swing.SwingWorker;
import javax.swing.event.DocumentEvent;
import javax.swing.event.DocumentListener;
import javax.swing.text.DefaultCaret;
import javax.xml.rpc.ServiceException;
import javax.xml.ws.Holder;
import org.netbeans.modules.bugtracking.spi.IssueController;
import org.netbeans.modules.bugtracking.spi.IssueProvider;
import org.openide.util.HelpCtx;
import org.openide.util.Mutex;
import org.openide.windows.WindowManager;
public class MantisIssueController implements PropertyChangeListener, ActionListener, IssueController {
private static final Logger logger = Logger.getLogger(MantisIssueController.class.getName());
private static File lastDirectory;
private SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
private ListBackedComboBoxModel<FlattenedProjectData> projectModel = new ListBackedComboBoxModel<>(FlattenedProjectData.class);
private ListBackedComboBoxModel<ObjectRef> viewstatesModel = new ListBackedComboBoxModel<>(ObjectRef.class);
private ListBackedComboBoxModel<ObjectRef> viewstatesModel2 = new ListBackedComboBoxModel<>(ObjectRef.class);
private ListBackedComboBoxModel<ObjectRef> severitiesModel = new ListBackedComboBoxModel<>(ObjectRef.class);
private ListBackedComboBoxModel<ObjectRef> reproducibilitiesModel = new ListBackedComboBoxModel<>(ObjectRef.class);
private ListBackedComboBoxModel<ObjectRef> prioritiesModel = new ListBackedComboBoxModel<>(ObjectRef.class);
private ListBackedComboBoxModel<ObjectRef> resolutionsModel = new ListBackedComboBoxModel<>(ObjectRef.class);
private ListBackedComboBoxModel<ObjectRef> statesModel = new ListBackedComboBoxModel<>(ObjectRef.class);
private ListBackedComboBoxModel<ObjectRef> etasModel = new ListBackedComboBoxModel<>(ObjectRef.class);
private ListBackedComboBoxModel<String> targetVersionModel = new ListBackedComboBoxModel<>(String.class);
private ListBackedComboBoxModel<String> productVersionModel = new ListBackedComboBoxModel<>(String.class);
private ListBackedComboBoxModel<String> fixVersionModel = new ListBackedComboBoxModel<>(String.class);
private ListBackedComboBoxModel<ObjectRef> projectionsModel = new ListBackedComboBoxModel<>(ObjectRef.class);
private ListBackedComboBoxModel<String> categoriesModel = new ListBackedComboBoxModel<>(String.class);
private ListBackedComboBoxModel<AccountData> assignedModel = new ListBackedComboBoxModel<>(AccountData.class);
private Map<BigInteger,String> customFieldValueBackingStore = new HashMap<>();
private MantisIssuePanel panel;
private final MantisIssue issue;
private StateMonitor stateMonitor = new StateMonitor();
private final SwingWorker updateModel = new SwingWorker() {
List<FlattenedProjectData> projects;
List<ObjectRef> viewStates;
List<ObjectRef> severities;
List<ObjectRef> reproducibilities;
List<ObjectRef> resolutions;
List<ObjectRef> priorities;
List<ObjectRef> states;
List<ObjectRef> etas;
List<ObjectRef> projections;
@Override
protected Object doInBackground() throws Exception {
try(SafeAutocloseable ac = issue.busy()) {
MantisRepository mr = issue.getMantisRepository();
viewStates = Arrays.asList(mr.getMasterData().getViewStates());
projects = new ArrayList<>();
projects.add(null);
for(ProjectData pd: mr.getMasterData().getProjects()) {
projects.addAll(FlattenedProjectData.buildList(pd));
}
severities = Arrays.asList(mr.getMasterData().getSeverities());
reproducibilities = Arrays.asList(mr.getMasterData().getReproducibilities());
resolutions = Arrays.asList(mr.getMasterData().getResolutions());
priorities = Arrays.asList(mr.getMasterData().getPriorities());
states = new ArrayList<>(Arrays.asList(mr.getMasterData().getStates()));
states.add(0, null);
etas = Arrays.asList(mr.getMasterData().getEtas());
projections = Arrays.asList(mr.getMasterData().getProjections());
return null;
}
}
@Override
protected void done() {
try {
get();
projectModel.setBackingList(projects);
viewstatesModel.setBackingList(viewStates);
viewstatesModel2.setBackingList(viewStates);
viewstatesModel2.setSelectedItem(viewStates.get(0));
severitiesModel.setBackingList(severities);
reproducibilitiesModel.setBackingList(reproducibilities);
prioritiesModel.setBackingList(priorities);
resolutionsModel.setBackingList(resolutions);
statesModel.setBackingList(states);
etasModel.setBackingList(etas);
projectionsModel.setBackingList(projections);
updateInfo(null);
} catch (Exception ex) {
issue.getMantisRepository()
.getExceptionHandler()
.handleException(logger, "Failed to update", ex);
}
}
};
public MantisIssueController(final MantisIssue issue) {
this.issue = issue;
issue.addPropertyChangeListener(this);
updateModel.execute();
}
@Override
public JComponent getComponent() {
if (panel == null) {
panel = new MantisIssuePanel();
panel.addNoteViewStateComboBox.setModel(viewstatesModel2);
panel.projectComboBox.setModel(projectModel);
panel.categoryComboBox.setModel(categoriesModel);
panel.viewStatusComboBox.setModel(viewstatesModel);
panel.severityComboBox.setModel(severitiesModel);
panel.reproducibilityComboBox.setModel(reproducibilitiesModel);
panel.priorityComboBox.setModel(prioritiesModel);
panel.assignedToComboBox.setModel(assignedModel);
panel.resolutionComboBox.setModel(resolutionsModel);
panel.statusComboBox.setModel(statesModel);
panel.projectionComboBox.setModel(projectionsModel);
panel.etaComboBox.setModel(etasModel);
panel.targetVersionComboBox.setModel(targetVersionModel);
panel.fixVersionComboBox.setModel(fixVersionModel);
panel.versionComboBox.setModel(productVersionModel);
panel.refreshLinkButton.addActionListener(this);
panel.openIssueWebbrowserLinkButton.addActionListener(this);
panel.projectComboBox.addActionListener(this);
panel.updateIssueButton.setVisible(false);
panel.addNoteButton.addActionListener(this);
panel.addIssueButton.addActionListener(this);
panel.updateIssueButton.addActionListener(this);
panel.projectComboBox.addActionListener(stateMonitor);
panel.descriptionEditorPane.getDocument().addDocumentListener(stateMonitor);
panel.summaryTextField.getDocument().addDocumentListener(stateMonitor);
panel.waitPanel.setVisible(issue.isBusy());
updateInfo(null);
}
return panel;
}
private final Runnable updateInputState = new Runnable() {
@Override
public void run() {
panel.updateIssueButton.setVisible(false);
panel.addIssueButton.setVisible(false);
panel.notesOuterPanel.setVisible(false);
panel.statusComboBox.setEnabled(false);
panel.resolutionComboBox.setEnabled(false);
panel.headerPanel.setVisible(false);
panel.subheaderPanel.setVisible(false);
panel.relationsLabel.setVisible(false);
panel.relationsPanel.setVisible(false);
panel.tagsLabel.setVisible(false);
panel.tagsPanel.setVisible(false);
panel.attachmentLabel.setVisible(false);
panel.attachmentPanel.setVisible(false);
// panel.filler1.setVisible(false);
if (issue.getId() == null) {
setUpdateEnabledFields(true);
panel.addIssueButton.setVisible(true);
// panel.filler1.setVisible(true);
} else {
if (issue.canUpdate()) {
panel.updateIssueButton.setVisible(true);
panel.statusComboBox.setEnabled(true);
panel.resolutionComboBox.setEnabled(true);
}
setUpdateEnabledFields(issue.canUpdate());
panel.notesOuterPanel.setVisible(true);
panel.headerPanel.setVisible(true);
panel.subheaderPanel.setVisible(true);
panel.relationsLabel.setVisible(true);
panel.relationsPanel.setVisible(true);
panel.tagsLabel.setVisible(true);
panel.tagsPanel.setVisible(true);
panel.attachmentLabel.setVisible(true);
panel.attachmentPanel.setVisible(true);
boolean timeTracking = issue.getTimetracking() == Permission.WRITE;
panel.timetrackInput.setVisible(timeTracking);
panel.timetrackLabel.setVisible(timeTracking);
}
}
};
private void setUpdateEnabledFields(boolean enabled) {
panel.projectComboBox.setEnabled(enabled);
panel.viewStatusComboBox.setEnabled(enabled);
panel.assignedToComboBox.setEnabled(enabled);
panel.categoryComboBox.setEnabled(enabled);
panel.severityComboBox.setEnabled(enabled);
panel.reproducibilityComboBox.setEnabled(enabled);
panel.priorityComboBox.setEnabled(enabled);
panel.projectionComboBox.setEnabled(enabled);
panel.etaComboBox.setEnabled(enabled);
panel.targetVersionComboBox.setEnabled(enabled);
panel.fixVersionComboBox.setEnabled(enabled);
panel.versionComboBox.setEnabled(enabled);
panel.platformTextField.setEditable(enabled);
panel.osTextField.setEditable(enabled);
panel.osVersionTextField.setEditable(enabled);
panel.buildTextField.setEditable(enabled);
panel.summaryTextField.setEditable(enabled);
panel.descriptionEditorPane.setEditable(enabled);
panel.stepsToReproduceEditorPane.setEditable(enabled);
panel.additionalInformationEditorPane.setEditable(enabled);
}
private void updateInfo(String property) {
if (panel != null) {
if (property == null || "id".equals(property)) {
issue.getMantisRepository().getRequestProcessor()
.execute(updateInputState);
panel.issueHeader.setText(issue.getDisplayValue());
}
if (property == null || "summary".equals(property)) {
panel.issueHeader.setText(issue.getDisplayValue());
panel.summaryTextField.setText(issue.getSummary());
}
if (property == null || "date_submitted".equals(property)) {
if (issue.getDate_submitted() == null) {
panel.createdValueLabel.setText("-");
} else {
panel.createdValueLabel.setText(dateFormat.format(issue.getDate_submitted().getTime()));
}
}
if (property == null || "last_updated".equals(property)) {
if (issue.getLast_updated() == null) {
panel.updatedValueLabel.setText("-");
} else {
panel.updatedValueLabel.setText(dateFormat.format(issue.getLast_updated().getTime()));
}
}
if (property == null || "reporter".equals(property)) {
if (issue.getReporter() == null) {
panel.reporterValueLabel.setText(" - ");
} else {
String account = issue.getReporter().getName();
String name = issue.getReporter().getReal_name();
if (name == null) {
panel.reporterValueLabel.setText(account);
} else {
panel.reporterValueLabel.setText(account + " - " + name);
}
}
}
if (property == null || "project".equals(property)) {
FlattenedProjectData current = null;
if (issue.getProject() != null) {
BigInteger id = issue.getProject().getId();
for (int i = 0; i < projectModel.getSize(); i++) {
if ((projectModel.getElementAt(i) != null)
&& (projectModel.getElementAt(i).getProjectData().getId().equals(id))) {
current = projectModel.getElementAt(i);
break;
}
}
}
panel.projectComboBox.setSelectedItem(current);
}
if (property == null || "category".equals(property)) {
categoriesModel.setSelectedItem(issue.getCategory());
}
if (property == null || "target_version".equals(property)) {
targetVersionModel.setSelectedItem(issue.getTarget_version());
}
if (property == null || "version".equals(property)) {
productVersionModel.setSelectedItem(issue.getVersion());
}
if (property == null || "fixed_in_version".equals(property)) {
fixVersionModel.setSelectedItem(issue.getFixed_in_version());
}
if (property == null || "view_state".equals(property)) {
panel.viewStatusComboBox.setSelectedItem(issue.getView_state());
}
if (property == null || "severity".equals(property)) {
panel.severityComboBox.setSelectedItem(issue.getSeverity());
}
if (property == null || "reproducibility".equals(property)) {
panel.reproducibilityComboBox.setSelectedItem(issue.getReproducibility());
}
if (property == null || "priority".equals(property)) {
panel.priorityComboBox.setSelectedItem(issue.getPriority());
}
if (property == null || "handler".equals(property)) {
AccountData target = issue.getHandler();
assignedModel.setSelectedItem(target);
}
if (property == null || "resolution".equals(property)) {
panel.resolutionComboBox.setSelectedItem(issue.getResolution());
}
if (property == null || "status".equals(property)) {
panel.statusComboBox.setSelectedItem(issue.getStatus());
}
if (property == null || "eta".equals(property)) {
panel.etaComboBox.setSelectedItem(issue.getEta());
}
if (property == null || "projection".equals(property)) {
panel.projectionComboBox.setSelectedItem(issue.getProjection());
}
if (property == null || "description".equals(property)) {
DefaultCaret caret = (DefaultCaret) panel.descriptionEditorPane.getCaret();
int oldPolicy = caret.getUpdatePolicy();
caret.setUpdatePolicy(DefaultCaret.NEVER_UPDATE);
panel.descriptionEditorPane.setText(issue.getDescription());
caret.setUpdatePolicy(oldPolicy);
panel.descriptionScrollPane.setPreferredSize(new Dimension(
10,
Math.max(
(int) panel.descriptionEditorPane.getPreferredSize().getHeight() + 10,
95)));
}
if (property == null || "additional_information".equals(property)) {
DefaultCaret caret = (DefaultCaret) panel.additionalInformationEditorPane.getCaret();
int oldPolicy = caret.getUpdatePolicy();
caret.setUpdatePolicy(DefaultCaret.NEVER_UPDATE);
panel.additionalInformationEditorPane.setText(issue.getAdditional_information());
caret.setUpdatePolicy(oldPolicy);
panel.additionalInformationScrollPane.setPreferredSize(new Dimension(
10,
Math.max(
(int) panel.additionalInformationEditorPane.getPreferredSize().getHeight() + 10,
70)));
}
if (property == null || "steps_to_reproduce".equals(property)) {
DefaultCaret caret = (DefaultCaret) panel.stepsToReproduceEditorPane.getCaret();
int oldPolicy = caret.getUpdatePolicy();
caret.setUpdatePolicy(DefaultCaret.NEVER_UPDATE);
panel.stepsToReproduceEditorPane.setText(issue.getSteps_to_reproduce());
caret.setUpdatePolicy(oldPolicy);
panel.stepsToReproduceScrollPane.setPreferredSize(new Dimension(
10,
Math.max(
(int) panel.stepsToReproduceEditorPane.getPreferredSize().getHeight() + 10,
70)));
}
if (property == null || "platform".equals(property)) {
panel.platformTextField.setText(issue.getPlatform());
}
if (property == null || "os".equals(property)) {
panel.osTextField.setText(issue.getOs());
}
if (property == null || "os_build".equals(property)) {
panel.osVersionTextField.setText(issue.getOs_build());
}
if (property == null || "build".equals(property)) {
panel.buildTextField.setText(issue.getBuild());
}
if (property == null || "relationships".equals(property)) {
panel.relationsPanel.removeAll();
if (issue.getRelationships() != null) {
for (RelationshipData rd : issue.getRelationships()) {
panel.relationsPanel.add(new RelationshipDisplay(issue, rd));
}
}
JXHyperlink lb = new JXHyperlink();
lb.setText("Add");
lb.setActionCommand("addRelationship");
lb.addActionListener(this);
panel.relationsPanel.add(lb);
}
if (property == null || "tags".equals(property)) {
panel.tagsPanel.removeAll();
if (issue.getTags() != null) {
for (ObjectRef or : issue.getTags()) {
panel.tagsPanel.add(new TagDisplay(issue, or));
}
}
JXHyperlink lb = new JXHyperlink();
lb.setText("Add");
lb.setActionCommand("addTag");
lb.addActionListener(this);
panel.tagsPanel.add(lb);
}
if (property == null || "attachments".equals(property)) {
panel.attachmentPanel.removeAll();
if (issue.getAttachments() != null) {
for (AttachmentData ad : issue.getAttachments()) {
AttachmentDisplay adisplay = new AttachmentDisplay(issue, ad);
adisplay.setAlignmentX(Component.LEFT_ALIGNMENT);
panel.attachmentPanel.add(adisplay);
}
}
JXHyperlink lb = new JXHyperlink();
lb.setText("Add");
lb.setActionCommand("addAttachment");
lb.addActionListener(this);
panel.attachmentPanel.add(lb);
}
if (property == null || "notes".equals(property)) {
panel.notesPanel.removeAll();
Dimension fixedDim = new Dimension(1, 5);
if (issue.getNotes() != null) {
boolean first = true;
for (IssueNoteData ind : issue.getNotes()) {
if (!first) {
panel.notesPanel.add(new Box.Filler(fixedDim, fixedDim, fixedDim));
}
boolean showTimeTracking = issue.getTimetracking() == Permission.WRITE;
showTimeTracking |= issue.getTimetracking() == Permission.READ;
panel.notesPanel.add(new NoteDisplay(ind, showTimeTracking));
if (first) {
first = false;
}
}
}
}
if (property == null || "custom_fields".equals(property)) {
if (issue.getCustom_fields() != null) {
for (CustomFieldValueForIssueData cfvfi : issue.getCustom_fields()) {
CustomFieldComponent cfc = panel.getCustomFieldById(cfvfi.getField().getId());
if (cfc != null) {
cfc.setValue(cfvfi.getValue());
}
}
}
}
panel.timetrackInput.setValue(BigInteger.ZERO);
panel.revalidate();
panel.repaint();
}
}
private IssueData getUpdateData() {
IssueData updateData = new IssueData();
updateData.setId(issue.getId());
updateData.setAdditional_information(panel.additionalInformationEditorPane.getText());
// Skip attachments
updateData.setBuild(panel.buildTextField.getText());
updateData.setCategory((String) categoriesModel.getSelectedItem());
// Skip updating submitdate
updateData.setDescription(panel.descriptionEditorPane.getText());
updateData.setEta((ObjectRef) panel.etaComboBox.getSelectedItem());
updateData.setHandler((AccountData) assignedModel.getSelectedItem());
// Skip notes
// Skip tags
updateData.setOs(panel.osTextField.getText());
updateData.setOs_build(panel.osVersionTextField.getText());
updateData.setPlatform(panel.platformTextField.getText());
updateData.setPriority((ObjectRef) panel.priorityComboBox.getSelectedItem());
FlattenedProjectData pd = (FlattenedProjectData) panel.projectComboBox.getSelectedItem();
if (pd == null) {
updateData.setProject(null);
} else {
ObjectRef project = new ObjectRef(pd.getProjectData().getId(),
pd.getProjectData().getName());
updateData.setProject(project);
}
updateData.setProjection((ObjectRef) panel.projectionComboBox.getSelectedItem());
// Skip relationships
updateData.setReproducibility((ObjectRef) panel.reproducibilityComboBox.getSelectedItem());
updateData.setResolution((ObjectRef) panel.resolutionComboBox.getSelectedItem());
updateData.setSeverity((ObjectRef) panel.severityComboBox.getSelectedItem());
updateData.setStatus((ObjectRef) panel.statusComboBox.getSelectedItem());
updateData.setSteps_to_reproduce(panel.stepsToReproduceEditorPane.getText());
updateData.setSummary(panel.summaryTextField.getText());
updateData.setView_state((ObjectRef) panel.viewStatusComboBox.getSelectedItem());
String targetVersion = (String) targetVersionModel.getSelectedItem();
String version = (String)productVersionModel.getSelectedItem();
String fixedInVersion = (String)fixVersionModel.getSelectedItem();
updateData.setTarget_version(targetVersion == null ? "" : targetVersion);
updateData.setVersion(version == null ? "" : version);
updateData.setFixed_in_version(fixedInVersion == null ? "" : fixedInVersion);
updateData.setSponsorship_total(issue.getSponsorship_total());
// Should reporter/submitdate/last be updateable?
updateData.setReporter(issue.getReporter());
updateData.setDate_submitted(issue.getDate_submitted());
updateData.setLast_updated(issue.getLast_updated());
if(pd != null) {
try {
List<ObjectRef> fields = new ArrayList<>();
for (CustomFieldDefinitionData cfdd : issue.getMantisRepository().getMasterData().getCustomFieldDefinitions(pd.getProjectData().getId())) {
fields.add(cfdd.getField());
}
CustomFieldValueForIssueData[] customFieldData = new CustomFieldValueForIssueData[fields.size()];
for(int i = 0; i < customFieldData.length; i++) {
ObjectRef field = fields.get(i);
try {
customFieldData[i] = new CustomFieldValueForIssueData(
field,
panel.getCustomFieldById(field.getId()).getValue()
);
} catch (NullPointerException ex) {
}
}
updateData.setCustom_fields(customFieldData);
} catch (Exception ex) {
issue.getMantisRepository()
.getExceptionHandler()
.handleException(logger, "Failed to get custom field definitions", ex);
}
}
return updateData;
}
@Override
public HelpCtx getHelpCtx() {
return new HelpCtx(MantisIssueController.class.getName());
}
public boolean isValid() {
boolean result = true;
result &= panel.projectComboBox.getSelectedItem() != null;
result &= (!panel.descriptionEditorPane.getText().trim().isEmpty());
result &= (!panel.summaryTextField.getText().trim().isEmpty());
return result;
}
@Override
public void propertyChange(PropertyChangeEvent evt) {
String propertyName = evt.getPropertyName();
if ("busy".equals(propertyName) && panel != null) {
panel.waitPanel.setVisible((Boolean) evt.getNewValue());
} else {
if (IssueProvider.EVENT_ISSUE_DATA_CHANGED.equals(propertyName)) {
propertyName = null;
customFieldValueBackingStore.clear();
}
updateInfo(propertyName);
}
}
@Override
public void actionPerformed(ActionEvent e) {
final MantisRepository mr = issue.getMantisRepository();
if ("addIssue".equals(e.getActionCommand())
|| "updateIssue".equals(e.getActionCommand())) {
mr.getRequestProcessor().submit(new Runnable() {
public void run() {
saveChanges();
}
});
} else if ("addNote".equals(e.getActionCommand())) {
final ObjectRef viewState = (ObjectRef) panel.addNoteViewStateComboBox.getSelectedItem();
final String comment = panel.addNoteEditorPane.getText();
final BigInteger timetracking = (BigInteger) panel.timetrackInput.getValue();
panel.addNoteViewStateComboBox.setSelectedIndex(0);
panel.addNoteEditorPane.setText("");
panel.timetrackInput.setValue(BigInteger.ZERO);
mr.getRequestProcessor().submit(new Runnable() {
@Override
public void run() {
try {
issue.addComment(comment, viewState, timetracking);
} catch (Exception ex) {
mr
.getExceptionHandler()
.handleException(logger, "Failed to comment to issue", ex);
}
}
});
} else if ("selectProject".equals(e.getActionCommand())) {
final FlattenedProjectData fpd = (FlattenedProjectData) panel.projectComboBox.getSelectedItem();
mr.getRequestProcessor().submit(new Runnable() {
@Override
public void run() {
try (SafeAutocloseable saf = issue.busy()) {
final List<String> categories = new ArrayList<>();
final List<AccountData> users = new ArrayList<>();
final List<String> versions = new ArrayList<>();
final Holder<CustomFieldDefinitionData[]> customFields = new Holder<>();
if (fpd != null) {
BigInteger projectId = fpd.getProjectData().getId();
categories.add(null);
categories.addAll(Arrays.asList(mr.getMasterData().getCategories(projectId)));
users.add(null);
users.addAll(Arrays.asList(mr.getMasterData().getUsers(projectId)));
versions.add(null);
for (ProjectVersionData vdata : mr.getMasterData().getVersions(projectId)) {
versions.add(vdata.getName());
}
customFields.value = mr.getMasterData().getCustomFieldDefinitions(projectId);
} else {
customFields.value = new CustomFieldDefinitionData[0];
}
final Holder<UserData> ud = new Holder<>();
try {
ud.value = mr.getAccount();
} catch (ServiceException | RemoteException ex) {
};
Mutex.EVENT.writeAccess(new Mutex.Action<Void>() {
public Void run() {
categoriesModel.setBackingList(categories);
assignedModel.setBackingList(users);
targetVersionModel.setBackingList(versions);
productVersionModel.setBackingList(versions);
fixVersionModel.setBackingList(versions);
for (CustomFieldComponent cfc : panel.getCustomFields()) {
customFieldValueBackingStore.put(
cfc.getCustomFieldDefinitionData().getField().getId(),
cfc.getValue());
}
Map<BigInteger,String> issueData = new HashMap<>();
for(CustomFieldValueForIssueData cfvfid: issue.getCustom_fields()) {
issueData.put(cfvfid.getField().getId(), cfvfid.getValue());
}
panel.clearCustomFields();
for (CustomFieldDefinitionData cfdd : customFields.value) {
CustomFieldComponent cfc = CustomFieldComponent.create(cfdd, ud.value);
BigInteger id = cfc.getCustomFieldDefinitionData().getField().getId();
if (customFieldValueBackingStore.containsKey(id)) {
cfc.setValue(customFieldValueBackingStore.get(id));
} else if (issue.getId() == null
|| BigInteger.ZERO.equals(issue.getId())) {
cfc.setDefaultValue();
} else {
cfc.setValue(issueData.get(id));
}
panel.addCustomField(cfc);
}
return null;
}
});
} catch (Exception ex) {
mr
.getExceptionHandler()
.handleException(logger, "Failed to create/add issue", ex);
}
}
});
} else if ("refreshIssue".equals(e.getActionCommand())) {
if (issue.getId() != null) {
mr.getRequestProcessor().submit(new Runnable() {
public void run() {
try {
issue.refresh();
} catch (Exception ex) {
mr
.getExceptionHandler()
.handleException(logger, "Failed to refresh issue", ex);
}
}
});
}
} else if ("openIssueWebbrowser".equals(e.getActionCommand())) {
URI uri = mr.getIssueUrl(issue);
try {
Desktop.getDesktop().browse(uri);
} catch (IOException ex) {
throw new RuntimeException(ex);
}
} else if ("addRelationship".equals(e.getActionCommand())) {
new AddRelationshipDialog((JFrame) WindowManager.getDefault().getMainWindow(), issue).setVisible(true);
} else if ("addTag".equals(e.getActionCommand())) {
new AddTagDialog((JFrame) WindowManager.getDefault().getMainWindow(), issue).setVisible(true);
} else if ("addAttachment".equals(e.getActionCommand())) {
final JFileChooser fileChooser = new JFileChooser(lastDirectory);
fileChooser.setDialogTitle("Add attachment");
int result = fileChooser.showOpenDialog(getComponent());
if (result == JFileChooser.APPROVE_OPTION) {
lastDirectory = fileChooser.getCurrentDirectory();
mr.getRequestProcessor().submit(new Runnable() {
@Override
public void run() {
try {
issue.addFile(fileChooser.getSelectedFile(), null);
} catch (Exception ex) {
mr
.getExceptionHandler()
.handleException(logger, "Failed to add file to issue", ex);
}
}
});
}
}
}
@Override
public void opened() {
}
@Override
public void closed() {
}
@Override
public boolean saveChanges() {
try(SafeAutocloseable ac = issue.busy()) {
if (isValid()) {
if (issue.getId() == null) {
MantisRepository mr = issue.getMantisRepository();
mr.addIssue(issue, getUpdateData());
} else {
MantisRepository mr = issue.getMantisRepository();
mr.updateIssue(issue, getUpdateData());
}
}
} catch (Exception ex) {
issue.getMantisRepository()
.getExceptionHandler()
.handleException(logger, "Failed to create/add issue", ex);
}
return true;
}
@Override
public boolean discardUnsavedChanges() {
updateInfo(null);
return true;
}
@Override
public boolean isChanged() {
// @todo: Impelement change detection
return false;
}
@Override
public void addPropertyChangeListener(PropertyChangeListener l) {
issue.addPropertyChangeListener(l);
}
@Override
public void removePropertyChangeListener(PropertyChangeListener l) {
issue.removePropertyChangeListener(l);
}
private class StateMonitor implements DocumentListener, ActionListener {
private void updateButtonState() {
if (isValid()) {
panel.addIssueButton.setEnabled(true);
panel.updateIssueButton.setEnabled(true);
} else {
panel.addIssueButton.setEnabled(false);
panel.updateIssueButton.setEnabled(false);
}
}
@Override
public void insertUpdate(DocumentEvent e) {
updateButtonState();
}
@Override
public void removeUpdate(DocumentEvent e) {
updateButtonState();
}
@Override
public void changedUpdate(DocumentEvent e) {
updateButtonState();
}
@Override
public void actionPerformed(ActionEvent e) {
updateButtonState();
}
}
}