/******************************************************************************* * Copyright (c) 2004, 2015 Tasktop Technologies and others. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at * http://www.eclipse.org/legal/epl-v10.html * * Contributors: * Tasktop Technologies - initial API and implementation *******************************************************************************/ package org.eclipse.mylyn.internal.bugzilla.ui.editor; import java.text.MessageFormat; import java.util.ArrayList; import java.util.Collections; import java.util.HashMap; import java.util.List; import java.util.Map; import java.util.Set; import org.eclipse.core.runtime.CoreException; import org.eclipse.core.runtime.IStatus; import org.eclipse.core.runtime.NullProgressMonitor; import org.eclipse.jface.dialogs.IMessageProvider; import org.eclipse.jface.fieldassist.ControlDecoration; import org.eclipse.jface.fieldassist.FieldDecoration; import org.eclipse.jface.fieldassist.FieldDecorationRegistry; import org.eclipse.mylyn.commons.core.StatusHandler; import org.eclipse.mylyn.commons.workbench.WorkbenchUtil; import org.eclipse.mylyn.internal.bugzilla.core.BugzillaAttribute; import org.eclipse.mylyn.internal.bugzilla.core.BugzillaCorePlugin; import org.eclipse.mylyn.internal.bugzilla.core.BugzillaCustomField; import org.eclipse.mylyn.internal.bugzilla.core.BugzillaOperation; import org.eclipse.mylyn.internal.bugzilla.core.BugzillaRepositoryConnector; import org.eclipse.mylyn.internal.bugzilla.core.BugzillaRepositoryResponse; import org.eclipse.mylyn.internal.bugzilla.core.BugzillaStatus; import org.eclipse.mylyn.internal.bugzilla.core.BugzillaTaskDataHandler; import org.eclipse.mylyn.internal.bugzilla.core.BugzillaUserMatchResponse; import org.eclipse.mylyn.internal.bugzilla.core.BugzillaVersion; import org.eclipse.mylyn.internal.bugzilla.core.IBugzillaConstants; import org.eclipse.mylyn.internal.bugzilla.core.RepositoryConfiguration; import org.eclipse.mylyn.internal.bugzilla.ui.BugzillaUiPlugin; import org.eclipse.mylyn.internal.tasks.ui.PersonProposalProvider; import org.eclipse.mylyn.internal.tasks.ui.editors.PersonAttributeEditor; import org.eclipse.mylyn.internal.tasks.ui.editors.TaskEditorActionPart; import org.eclipse.mylyn.tasks.core.RepositoryResponse; import org.eclipse.mylyn.tasks.core.RepositoryStatus; import org.eclipse.mylyn.tasks.core.TaskRepository; import org.eclipse.mylyn.tasks.core.data.TaskAttribute; import org.eclipse.mylyn.tasks.core.data.TaskAttributeMetaData; import org.eclipse.mylyn.tasks.core.data.TaskData; import org.eclipse.mylyn.tasks.core.data.TaskDataModel; import org.eclipse.mylyn.tasks.core.data.TaskDataModelEvent; import org.eclipse.mylyn.tasks.core.data.TaskDataModelListener; import org.eclipse.mylyn.tasks.core.sync.SubmitJobEvent; import org.eclipse.mylyn.tasks.ui.TasksUi; import org.eclipse.mylyn.tasks.ui.TasksUiUtil; import org.eclipse.mylyn.tasks.ui.editors.AbstractAttributeEditor; import org.eclipse.mylyn.tasks.ui.editors.AbstractTaskEditorPage; import org.eclipse.mylyn.tasks.ui.editors.AbstractTaskEditorPart; import org.eclipse.mylyn.tasks.ui.editors.AttributeEditorFactory; import org.eclipse.mylyn.tasks.ui.editors.LayoutHint; import org.eclipse.mylyn.tasks.ui.editors.LayoutHint.ColumnSpan; import org.eclipse.mylyn.tasks.ui.editors.LayoutHint.RowSpan; import org.eclipse.mylyn.tasks.ui.editors.TaskEditor; import org.eclipse.mylyn.tasks.ui.editors.TaskEditorInput; import org.eclipse.mylyn.tasks.ui.editors.TaskEditorPartDescriptor; import org.eclipse.osgi.util.NLS; import org.eclipse.swt.SWT; import org.eclipse.swt.events.ModifyEvent; import org.eclipse.swt.events.ModifyListener; import org.eclipse.swt.widgets.Control; import org.eclipse.ui.PlatformUI; import org.eclipse.ui.fieldassist.ContentAssistCommandAdapter; import org.eclipse.ui.forms.events.HyperlinkAdapter; import org.eclipse.ui.forms.events.HyperlinkEvent; import org.eclipse.ui.forms.widgets.ExpandableComposite; import org.eclipse.ui.keys.IBindingService; /** * @author Rob Elves * @author Frank Becker * @since 3.0 */ public class BugzillaTaskEditorPage extends AbstractTaskEditorPage { public static final String ID_PART_BUGZILLA_PLANNING = "org.eclipse.mylyn.bugzilla.ui.editors.part.planning"; //$NON-NLS-1$ public static final String ID_PART_BUGZILLA_FLAGS = "org.eclipse.mylyn.bugzilla.ui.editors.part.flags"; //$NON-NLS-1$ public static final String PATH_FLAGS = "flags"; //$NON-NLS-1$ private final Map<TaskAttribute, AbstractAttributeEditor> attributeEditorMap; private TaskDataModelListener productListener; private final List<ControlDecoration> errorDecorations = new ArrayList<ControlDecoration>(); private final List<PersonAttributeEditor> editorsWithError = new ArrayList<PersonAttributeEditor>(3); public BugzillaTaskEditorPage(TaskEditor editor) { this(editor, BugzillaCorePlugin.CONNECTOR_KIND); } /** * Call this constructor if extending the Bugzilla connector * * @param editor * @param connectorKind */ public BugzillaTaskEditorPage(TaskEditor editor, String connectorKind) { super(editor, connectorKind); this.attributeEditorMap = new HashMap<TaskAttribute, AbstractAttributeEditor>(); setNeedsPrivateSection(true); setNeedsSubmitButton(true); } @Override protected Set<TaskEditorPartDescriptor> createPartDescriptors() { Set<TaskEditorPartDescriptor> descriptors = super.createPartDescriptors(); boolean hasPartComments = false; boolean hasPartNewComment = false; boolean hasPartDescription = false; // remove unnecessary default editor parts for (TaskEditorPartDescriptor taskEditorPartDescriptor : descriptors) { if (taskEditorPartDescriptor.getId().equals(ID_PART_PEOPLE)) { descriptors.remove(taskEditorPartDescriptor); break; } } for (TaskEditorPartDescriptor taskEditorPartDescriptor : descriptors) { if (taskEditorPartDescriptor.getId().equals(ID_PART_COMMENTS)) { descriptors.remove(taskEditorPartDescriptor); hasPartComments = true; break; } } for (TaskEditorPartDescriptor taskEditorPartDescriptor : descriptors) { if (taskEditorPartDescriptor.getId().equals(ID_PART_NEW_COMMENT)) { descriptors.remove(taskEditorPartDescriptor); hasPartNewComment = true; break; } } for (TaskEditorPartDescriptor taskEditorPartDescriptor : descriptors) { if (taskEditorPartDescriptor.getId().equals(ID_PART_DESCRIPTION)) { descriptors.remove(taskEditorPartDescriptor); hasPartDescription = true; break; } } // Add Bugzilla Planning part try { TaskData data = TasksUi.getTaskDataManager().getTaskData(getTask()); if (data != null) { // Add Bugzilla Flag part Map<String, TaskAttribute> attributes = data.getRoot().getAttributes(); for (TaskAttribute attribute : attributes.values()) { if (BugzillaAttribute.KIND_FLAG.equals(attribute.getMetaData().getKind())) { descriptors.add(new TaskEditorPartDescriptor(ID_PART_BUGZILLA_FLAGS) { @Override public AbstractTaskEditorPart createPart() { return new BugzillaFlagPart(); } }.setPath(ID_PART_ATTRIBUTES + "/" + PATH_FLAGS)); //$NON-NLS-1$ break; } } TaskAttribute attrEstimatedTime = data.getRoot() .getMappedAttribute(BugzillaAttribute.ESTIMATED_TIME.getKey()); if (attrEstimatedTime != null) { descriptors.add(new TaskEditorPartDescriptor(ID_PART_BUGZILLA_PLANNING) { @Override public AbstractTaskEditorPart createPart() { return new BugzillaPlanningEditorPart(); } }.setPath(ID_PART_ATTRIBUTES + "/" + PATH_PLANNING)); //$NON-NLS-1$ } } if (hasPartDescription) { descriptors.add(new TaskEditorPartDescriptor(ID_PART_DESCRIPTION) { @Override public AbstractTaskEditorPart createPart() { BugzillaTaskEditorDescriptionPart part = new BugzillaTaskEditorDescriptionPart(); if (getModel().getTaskData().isNew()) { part.setExpandVertically(true); part.setSectionStyle(ExpandableComposite.TITLE_BAR | ExpandableComposite.EXPANDED); } return part; } }.setPath(PATH_COMMENTS)); } if (hasPartComments) { descriptors.add(new TaskEditorPartDescriptor(ID_PART_COMMENTS) { @Override public AbstractTaskEditorPart createPart() { return new BugzillaTaskEditorCommentPart(); } }.setPath(PATH_COMMENTS)); } } catch (CoreException e) { // ignore } if (hasPartNewComment) { // Add the updated Bugzilla new comment part descriptors.add(new TaskEditorPartDescriptor(ID_PART_NEW_COMMENT) { @Override public AbstractTaskEditorPart createPart() { return new BugzillaTaskEditorNewCommentPart(); } }.setPath(PATH_COMMENTS)); } // Add the updated Bugzilla people part descriptors.add(new TaskEditorPartDescriptor(ID_PART_PEOPLE) { @Override public AbstractTaskEditorPart createPart() { return new BugzillaPeoplePart(); } }.setPath(PATH_PEOPLE)); return descriptors; } @Override protected AttributeEditorFactory createAttributeEditorFactory() { AttributeEditorFactory factory = new AttributeEditorFactory(getModel(), getTaskRepository(), getEditorSite()) { @Override public AbstractAttributeEditor createEditor(String type, final TaskAttribute taskAttribute) { AbstractAttributeEditor editor; if (IBugzillaConstants.EDITOR_TYPE_KEYWORDS.equals(type)) { editor = new BugzillaKeywordAttributeEditor(getModel(), taskAttribute); } else if (IBugzillaConstants.EDITOR_TYPE_REMOVECC.equals(type)) { editor = new BugzillaCcAttributeEditor(getModel(), taskAttribute); } else if (IBugzillaConstants.EDITOR_TYPE_VOTES.equals(type)) { editor = new BugzillaVotesEditor(getModel(), taskAttribute); } else if (IBugzillaConstants.EDITOR_TYPE_FLAG.equals(type)) { editor = new FlagAttributeEditor(getModel(), taskAttribute); } else if (IBugzillaConstants.EDITOR_TYPE_SEEALSO.equals(type)) { editor = new BugzillaSeeAlsoAttributeEditor(getModel(), taskAttribute); } else { editor = super.createEditor(type, taskAttribute); if (TaskAttribute.TYPE_BOOLEAN.equals(type)) { editor.setDecorationEnabled(false); } } if (editor != null && taskAttribute.getId().startsWith(BugzillaCustomField.CUSTOM_FIELD_PREFIX)) { editor.setLayoutHint(new LayoutHint(editor.getLayoutHint()) { @Override public int getPriority() { return super.getPriority() * 10; } }); } TaskAttributeMetaData properties = taskAttribute.getMetaData(); if (editor != null && IBugzillaConstants.EDITOR_TYPE_FLAG.equals(properties.getType())) { editor.setLayoutHint(new LayoutHint(editor.getLayoutHint()) { @Override public int getPriority() { return super.getPriority() * 5; } }); } if (editor != null && BugzillaAttribute.NEWCC.getKey().equals(taskAttribute.getId())) { editor.setLayoutHint(new LayoutHint(RowSpan.SINGLE, ColumnSpan.SINGLE)); } BugzillaTaskEditorPage.this.addToAttributeEditorMap(taskAttribute, editor); return editor; } }; return factory; } @Override public void doSubmit() { TaskAttribute summaryAttribute = getModel().getTaskData().getRoot().getMappedAttribute(TaskAttribute.SUMMARY); if (summaryAttribute != null && summaryAttribute.getValue().length() == 0) { getTaskEditor().setMessage(Messages.BugzillaTaskEditorPage_Please_enter_a_short_summary_before_submitting, IMessageProvider.ERROR); AbstractTaskEditorPart part = getPart(ID_PART_SUMMARY); if (part != null) { part.setFocus(); } return; } TaskAttribute componentAttribute = getModel().getTaskData() .getRoot() .getMappedAttribute(BugzillaAttribute.COMPONENT.getKey()); if (componentAttribute != null && componentAttribute.getValue().length() == 0) { getTaskEditor().setMessage(Messages.BugzillaTaskEditorPage_Please_select_a_component_before_submitting, IMessageProvider.ERROR); AbstractTaskEditorPart part = getPart(ID_PART_ATTRIBUTES); if (part != null) { part.setFocus(); } return; } TaskAttribute descriptionAttribute = getModel().getTaskData() .getRoot() .getMappedAttribute(TaskAttribute.DESCRIPTION); if (descriptionAttribute != null && descriptionAttribute.getValue().length() == 0 && getModel().getTaskData().isNew()) { getTaskEditor().setMessage(Messages.BugzillaTaskEditorPage_Please_enter_a_description_before_submitting, IMessageProvider.ERROR); AbstractTaskEditorPart descriptionPart = getPart(ID_PART_DESCRIPTION); if (descriptionPart != null) { descriptionPart.setFocus(); } return; } TaskAttribute targetMilestoneAttribute = getModel().getTaskData() .getRoot() .getMappedAttribute(BugzillaAttribute.TARGET_MILESTONE.getKey()); if (targetMilestoneAttribute != null && targetMilestoneAttribute.getValue().length() == 0 && getModel().getTaskData().isNew()) { getTaskEditor().setMessage( Messages.BugzillaTaskEditorPage_Please_enter_a_target_milestone_before_submitting, IMessageProvider.ERROR); AbstractTaskEditorPart descriptionPart = getPart(ID_PART_ATTRIBUTES); if (descriptionPart != null) { descriptionPart.setFocus(); } return; } TaskAttribute attributeOperation = getModel().getTaskData() .getRoot() .getMappedAttribute(TaskAttribute.OPERATION); if (attributeOperation != null) { if ("duplicate".equals(attributeOperation.getValue())) { //$NON-NLS-1$ TaskAttribute originalOperation = getModel().getTaskData() .getRoot() .getAttribute(TaskAttribute.PREFIX_OPERATION + attributeOperation.getValue()); String inputAttributeId = originalOperation.getMetaData() .getValue(TaskAttribute.META_ASSOCIATED_ATTRIBUTE_ID); if (inputAttributeId != null && !inputAttributeId.equals("")) { //$NON-NLS-1$ TaskAttribute inputAttribute = attributeOperation.getTaskData() .getRoot() .getAttribute(inputAttributeId); if (inputAttribute != null) { String dupValue = inputAttribute.getValue(); if (dupValue == null || dupValue.equals("")) { //$NON-NLS-1$ getTaskEditor().setMessage( Messages.BugzillaTaskEditorPage_Please_enter_a_bugid_for_duplicate_of_before_submitting, IMessageProvider.ERROR); AbstractTaskEditorPart part = getPart(ID_PART_ACTIONS); if (part != null) { part.setFocus(); } return; } } } } } if (getModel().getTaskData().isNew()) { TaskAttribute productAttribute = getModel().getTaskData() .getRoot() .getMappedAttribute(TaskAttribute.PRODUCT); if (productAttribute != null && productAttribute.getValue().length() > 0) { getModel().getTaskRepository().setProperty(IBugzillaConstants.LAST_PRODUCT_SELECTION, productAttribute.getValue()); } TaskAttribute componentSelectedAttribute = getModel().getTaskData() .getRoot() .getMappedAttribute(TaskAttribute.COMPONENT); if (componentSelectedAttribute != null && componentSelectedAttribute.getValue().length() > 0) { getModel().getTaskRepository().setProperty(IBugzillaConstants.LAST_COMPONENT_SELECTION, componentSelectedAttribute.getValue()); } } // Force the most recent known good token onto the outgoing task data to ensure submit // bug#263318 TaskAttribute attrToken = getModel().getTaskData().getRoot().getAttribute(BugzillaAttribute.TOKEN.getKey()); if (attrToken != null) { String tokenString = getModel().getTask().getAttribute(BugzillaAttribute.TOKEN.getKey()); if (tokenString != null) { attrToken.setValue(tokenString); } } for (ControlDecoration decoration : errorDecorations) { decoration.hide(); decoration.dispose(); } errorDecorations.clear(); editorsWithError.clear(); if (!checkCanSubmit(IMessageProvider.ERROR)) { return; } getTaskEditor().setMessage("", IMessageProvider.NONE); //$NON-NLS-1$ super.doSubmit(); } @Override protected void createParts() { attributeEditorMap.clear(); super.createParts(); checkCanSubmit(IMessageProvider.INFORMATION); } @Override protected TaskDataModel createModel(TaskEditorInput input) throws CoreException { TaskDataModel model = super.createModel(input); productListener = new ProductSelectionListener(); model.addModelListener(productListener); return model; } /** * @since 3.1 */ private void addToAttributeEditorMap(TaskAttribute attribute, AbstractAttributeEditor editor) { if (attributeEditorMap.containsKey(attribute)) { attributeEditorMap.remove(attribute); } attributeEditorMap.put(attribute, editor); } /** * @since 3.1 */ private AbstractAttributeEditor getEditorForAttribute(TaskAttribute attribute) { return attributeEditorMap.get(attribute); } private void refresh(TaskAttribute attributeComponent) { AbstractAttributeEditor editor = getEditorForAttribute(attributeComponent); if (editor != null) { try { editor.refresh(); } catch (UnsupportedOperationException e) { // ignore } } } private class ProductSelectionListener extends TaskDataModelListener { @Override public void attributeChanged(TaskDataModelEvent event) { TaskAttribute taskAttribute = event.getTaskAttribute(); if (taskAttribute != null) { if (taskAttribute.getId().equals(BugzillaAttribute.PRODUCT.getKey())) { RepositoryConfiguration repositoryConfiguration = null; try { BugzillaRepositoryConnector connector = (BugzillaRepositoryConnector) TasksUi .getRepositoryConnector(getModel().getTaskRepository().getConnectorKind()); repositoryConfiguration = connector.getRepositoryConfiguration(getModel().getTaskRepository(), false, new NullProgressMonitor()); } catch (CoreException e) { StatusHandler.log(new RepositoryStatus(getTaskRepository(), IStatus.ERROR, BugzillaUiPlugin.ID_PLUGIN, 0, "Failed to obtain repository configuration", e)); //$NON-NLS-1$ getTaskEditor().setMessage("Problem occured when updating attributes", IMessageProvider.ERROR); //$NON-NLS-1$ return; } TaskAttribute attributeComponent = taskAttribute.getTaskData() .getRoot() .getMappedAttribute(BugzillaAttribute.COMPONENT.getKey()); if (attributeComponent != null) { List<String> optionValues = repositoryConfiguration .getProductOptionValues(BugzillaAttribute.COMPONENT, taskAttribute.getValue()); Collections.sort(optionValues); attributeComponent.clearOptions(); for (String option : optionValues) { attributeComponent.putOption(option, option); } if (optionValues.size() > 0) { attributeComponent.setValue(optionValues.get(0)); } refresh(attributeComponent); } TaskAttribute attributeTargetMilestone = taskAttribute.getTaskData() .getRoot() .getMappedAttribute(BugzillaAttribute.TARGET_MILESTONE.getKey()); if (attributeTargetMilestone != null) { List<String> optionValues = repositoryConfiguration .getProductOptionValues(BugzillaAttribute.TARGET_MILESTONE, taskAttribute.getValue()); Collections.sort(optionValues); attributeTargetMilestone.clearOptions(); for (String option : optionValues) { attributeTargetMilestone.putOption(option, option); } String defaultMilestones = repositoryConfiguration .getDefaultMilestones(taskAttribute.getValue()); if (defaultMilestones != null) { attributeTargetMilestone.setValue(defaultMilestones); } else if (optionValues.size() == 1) { attributeTargetMilestone.setValue(optionValues.get(0)); } else { attributeTargetMilestone.setValue("---"); //$NON-NLS-1$ } refresh(attributeTargetMilestone); } TaskAttribute attributeVersion = taskAttribute.getTaskData() .getRoot() .getMappedAttribute(BugzillaAttribute.VERSION.getKey()); if (attributeVersion != null) { List<String> optionValues = repositoryConfiguration .getProductOptionValues(BugzillaAttribute.VERSION, taskAttribute.getValue()); Collections.sort(optionValues); attributeVersion.clearOptions(); for (String option : optionValues) { attributeVersion.putOption(option, option); } if (optionValues.size() == 1) { attributeVersion.setValue(optionValues.get(0)); } else { attributeVersion.setValue("unspecified"); //$NON-NLS-1$ } refresh(attributeVersion); } TaskAttribute attributeDefaultAssignee = taskAttribute.getTaskData() .getRoot() .getMappedAttribute(BugzillaAttribute.SET_DEFAULT_ASSIGNEE.getKey()); if (attributeDefaultAssignee != null) { attributeDefaultAssignee.setValue("1"); //$NON-NLS-1$ refresh(attributeDefaultAssignee); } if (taskAttribute.getTaskData().isNew()) { BugzillaVersion bugzillaVersion = repositoryConfiguration.getInstallVersion(); if (bugzillaVersion == null) { bugzillaVersion = BugzillaVersion.MIN_VERSION; } if (bugzillaVersion.compareMajorMinorOnly(BugzillaVersion.BUGZILLA_4_0) >= 0) { AbstractTaskEditorPart part = getPart(ID_PART_ACTIONS); boolean unconfirmedAllowed = repositoryConfiguration .getUnconfirmedAllowed(taskAttribute.getValue()); TaskAttribute unconfirmedAttribute = taskAttribute.getTaskData().getRoot().getAttribute( TaskAttribute.PREFIX_OPERATION + BugzillaOperation.unconfirmed.toString()); if (unconfirmedAttribute != null) { unconfirmedAttribute.getMetaData().setReadOnly(!unconfirmedAllowed); } if (part != null) { TaskEditorActionPart actionPart = (TaskEditorActionPart) part; actionPart.refreshOperations(); } } } /* * add confirm_product_change to avoid verification page on submit */ TaskAttribute attributeConfirmeProductChange = taskAttribute.getTaskData() .getRoot() .getMappedAttribute(BugzillaAttribute.CONFIRM_PRODUCT_CHANGE.getKey()); if (attributeConfirmeProductChange == null) { attributeConfirmeProductChange = BugzillaTaskDataHandler.createAttribute( taskAttribute.getTaskData().getRoot(), BugzillaAttribute.CONFIRM_PRODUCT_CHANGE); } if (attributeConfirmeProductChange != null) { attributeConfirmeProductChange.setValue("1"); //$NON-NLS-1$ } } } } } @Override protected void handleTaskSubmitted(SubmitJobEvent event) { if (event.getJob().getStatus() != null) { switch (event.getJob().getStatus().getCode()) { case BugzillaStatus.ERROR_CONFIRM_MATCH: case BugzillaStatus.ERROR_MATCH_FAILED: showError((BugzillaStatus) event.getJob().getStatus()); return; } } if (event.getJob().getResponse() != null && event.getJob().getResponse() instanceof BugzillaRepositoryResponse) { final RepositoryResponse response = event.getJob().getResponse(); if (response instanceof BugzillaRepositoryResponse) { final BugzillaRepositoryResponse bugzillaResponse = (BugzillaRepositoryResponse) response; if (bugzillaResponse.getResponseData().size() > 0) { getTaskEditor().setMessage(Messages.BugzillaTaskEditorPage_Changes_Submitted_Message, IMessageProvider.INFORMATION, new HyperlinkAdapter() { @Override public void linkActivated(HyperlinkEvent event) { showSubmitResponse(bugzillaResponse); } }); } else { getTaskEditor().setMessage(Messages.BugzillaTaskEditorPage_Changes_Submitted_Message, IMessageProvider.INFORMATION); } } } else { super.handleTaskSubmitted(event); } } @Override public void refresh() { super.refresh(); checkCanSubmit(IMessageProvider.INFORMATION); } private boolean checkCanSubmit(final int type) { final TaskRepository taskRepository = getModel().getTaskRepository(); String username = taskRepository.getUserName(); if (username == null || username.length() == 0) { PlatformUI.getWorkbench().getDisplay().asyncExec(new Runnable() { public void run() { getTaskEditor().setMessage(Messages.BugzillaTaskEditorPage_Anonymous_can_not_submit_Tasks, type, new HyperlinkAdapter() { @Override public void linkActivated(HyperlinkEvent e) { TasksUiUtil.openEditRepositoryWizard(taskRepository); refresh(); } }); } }); return false; } if (!getModel().getTaskData().isNew()) { TaskAttribute exporter = getModel().getTaskData() .getRoot() .getAttribute(BugzillaAttribute.EXPORTER_NAME.getKey()); if (exporter == null || exporter.getValue().equals("")) { //$NON-NLS-1$ PlatformUI.getWorkbench().getDisplay().asyncExec(new Runnable() { public void run() { getTaskEditor().setMessage(Messages.BugzillaTaskEditorPage_submit_disabled_please_refresh, type, new HyperlinkAdapter() { @Override public void linkActivated(HyperlinkEvent e) { TasksUiUtil.openEditRepositoryWizard(taskRepository); refresh(); } }); } }); return false; } } return true; } private void showError(BugzillaStatus bugzillaStatus) { int count = 0; BugzillaUserMatchResponse response = bugzillaStatus.getUserMatchResponse(); FieldDecorationRegistry registry = FieldDecorationRegistry.getDefault(); FieldDecoration fieldDecoration = registry.getFieldDecoration(FieldDecorationRegistry.DEC_ERROR); FieldDecoration fieldDecorationWarning = registry.getFieldDecoration(FieldDecorationRegistry.DEC_WARNING); StringBuilder fields = new StringBuilder(); StringBuilder detail = new StringBuilder(); count += decorateControlsAndUpdateMessages(response.getAssignedToMsg(), response.getAssignedToProposals(), getModel().getTaskData().getRoot().getAttribute(BugzillaAttribute.ASSIGNED_TO.getKey()), fields, detail, fieldDecoration, fieldDecorationWarning); count += decorateControlsAndUpdateMessages(response.getQaContactMsg(), response.getQaContactProposals(), getModel().getTaskData().getRoot().getAttribute(BugzillaAttribute.QA_CONTACT.getKey()), fields, detail, fieldDecoration, fieldDecorationWarning); count += decorateControlsAndUpdateMessages(response.getNewCCMsg(), response.getNewCCProposals(), getModel().getTaskData().getRoot().getAttribute(BugzillaAttribute.NEWCC.getKey()), fields, detail, fieldDecoration, fieldDecorationWarning); updateTaskEditorPageMessageWithError(bugzillaStatus, detail.toString(), count == 1, fields.toString()); } private int decorateControlsAndUpdateMessages(String message, List<String> proposals, TaskAttribute attribute, StringBuilder fields, StringBuilder detail, FieldDecoration fieldDecoration, FieldDecoration fieldDecorationWarning) { if (attribute == null || (message == null && proposals.size() == 0)) { return 0; } Map<String, String> newPersonProposalMap = new HashMap<String, String>(); if (fields.length() > 0) { fields.append(MessageFormat.format(Messages.BugzillaTaskEditorPage_Error_Label_N, attribute.getMetaData().getLabel())); } else { fields.append(MessageFormat.format(Messages.BugzillaTaskEditorPage_Error_Label_1, attribute.getMetaData().getLabel())); } detail.append(attribute.getMetaData().getLabel() + "\n"); //$NON-NLS-1$ if (message != null && !message.equals("")) { //$NON-NLS-1$ detail.append(MessageFormat.format(Messages.BugzillaTaskEditorPage_DetailLine, message)); } else { for (String proposalValue : proposals) { detail.append(MessageFormat.format(Messages.BugzillaTaskEditorPage_DetailLine, proposalValue)); newPersonProposalMap.put(proposalValue, proposalValue); } } AbstractAttributeEditor editor = getEditorForAttribute(attribute); if (editor != null) { decorateEditorWithError(fieldDecoration, fieldDecorationWarning, message, newPersonProposalMap, editor); } return 1; } private int decorateControlsAndUpdateMessages(String message, Map<String, List<String>> proposals, TaskAttribute attribute, StringBuilder fields, StringBuilder detail, FieldDecoration fieldDecoration, FieldDecoration fieldDecorationWarning) { if (attribute == null || (message == null && proposals.size() == 0)) { return 0; } Map<String, String> newPersonProposalMap = new HashMap<String, String>(); if (fields.length() > 0) { fields.append(MessageFormat.format(Messages.BugzillaTaskEditorPage_Error_Label_N, attribute.getMetaData().getLabel())); } else { fields.append(MessageFormat.format(Messages.BugzillaTaskEditorPage_Error_Label_1, attribute.getMetaData().getLabel())); } detail.append(attribute.getMetaData().getLabel() + "\n"); //$NON-NLS-1$ if (message != null && !message.equals("")) { //$NON-NLS-1$ detail.append(MessageFormat.format(Messages.BugzillaTaskEditorPage_DetailLine, message)); } else { for (String key : proposals.keySet()) { detail.append(MessageFormat.format(Messages.BugzillaTaskEditorPage_Proposal_Detail, key)); for (String proposalValue : proposals.get(key)) { detail.append(MessageFormat.format(Messages.BugzillaTaskEditorPage_DetailLine, proposalValue)); newPersonProposalMap.put(proposalValue, proposalValue); } } } AbstractAttributeEditor editor = getEditorForAttribute(attribute); if (editor != null) { decorateEditorWithError(fieldDecoration, fieldDecorationWarning, message, newPersonProposalMap, editor); } return 1; } /** * @param bugzillaStatus * @param resultDetail * @param oneError * @param fieldString */ private void updateTaskEditorPageMessageWithError(BugzillaStatus bugzillaStatus, String resultDetail, boolean oneError, String fieldString) { String resultString; final String titleString; switch (bugzillaStatus.getCode()) { case BugzillaStatus.ERROR_CONFIRM_MATCH: if (oneError) { resultString = MessageFormat.format(Messages.BugzillaTaskEditorPage_Message_one, Messages.BugzillaTaskEditorPage_Confirm, fieldString); } else { resultString = MessageFormat.format(Messages.BugzillaTaskEditorPage_Message_more, Messages.BugzillaTaskEditorPage_Confirm, fieldString); } titleString = Messages.BugzillaTaskEditorPage_ConfirmDetailTitle; break; case BugzillaStatus.ERROR_MATCH_FAILED: if (oneError) { resultString = MessageFormat.format(Messages.BugzillaTaskEditorPage_Message_one, Messages.BugzillaTaskEditorPage_Error, fieldString); } else { resultString = MessageFormat.format(Messages.BugzillaTaskEditorPage_Message_more, Messages.BugzillaTaskEditorPage_Error, fieldString); } titleString = Messages.BugzillaTaskEditorPage_ErrorDetailTitle; break; default: throw new RuntimeException("unexpected BugzillaStatus: " + bugzillaStatus.getCode()); //$NON-NLS-1$ } final String resultDetailString = resultDetail; getTaskEditor().setMessage(resultString, IMessageProvider.ERROR, new HyperlinkAdapter() { @Override public void linkActivated(HyperlinkEvent event) { BugzillaResponseDetailDialog dialog = new BugzillaResponseDetailDialog(WorkbenchUtil.getShell(), titleString, resultDetailString); dialog.open(); } }); } /** * @param fieldDecoration * @param message * @param newPersonProposalMap * @param editor */ private void decorateEditorWithError(FieldDecoration fieldDecoration, FieldDecoration fieldDecorationWarning, String message, Map<String, String> newPersonProposalMap, AbstractAttributeEditor editor) { final Control control = editor.getControl(); final ControlDecoration decoration = new ControlDecoration(control, SWT.LEFT | SWT.DOWN); decoration.setImage( newPersonProposalMap.size() == 1 ? fieldDecorationWarning.getImage() : fieldDecoration.getImage()); IBindingService bindingService = PlatformUI.getWorkbench().getService(IBindingService.class); if (message != null && !message.equals("")) { //$NON-NLS-1$ decoration.setDescriptionText(message); errorDecorations.add(decoration); } else { decoration.setDescriptionText( NLS.bind(Messages.BugzillaTaskEditorPage_Content_Assist_for_Error_Available, bindingService .getBestActiveBindingFormattedFor(ContentAssistCommandAdapter.CONTENT_PROPOSAL_COMMAND))); errorDecorations.add(decoration); final PersonAttributeEditor personEditor = ((PersonAttributeEditor) editor); final PersonProposalProvider personProposalProvider = (PersonProposalProvider) personEditor .getContentAssistCommandAdapter().getContentProposalProvider(); personProposalProvider.setErrorProposals(newPersonProposalMap); editorsWithError.add(personEditor); if (newPersonProposalMap.size() == 1) { personEditor.setValue(newPersonProposalMap.keySet().iterator().next()); } personEditor.getText().addModifyListener(new ModifyListener() { public void modifyText(ModifyEvent e) { decoration.hide(); errorDecorations.remove(decoration); decoration.dispose(); personProposalProvider.setErrorProposals(null); } }); } } /** * @param bugzillaResponse */ private void showSubmitResponse(final BugzillaRepositoryResponse bugzillaResponse) { StringBuilder message = new StringBuilder(); for (String iterable_map : bugzillaResponse.getResponseData().keySet()) { if (message.length() > 0) { message.append("\n"); //$NON-NLS-1$ } message.append(NLS.bind(Messages.BugzillaTaskEditorPage_Bug_Line, iterable_map)); Map<String, List<String>> responseMap = bugzillaResponse.getResponseData().get(iterable_map); for (String iterable_list : responseMap.keySet()) { message.append(NLS.bind(Messages.BugzillaTaskEditorPage_Action_Line, iterable_list)); List<String> responseList = responseMap.get(iterable_list); for (String string : responseList) { message.append(NLS.bind(Messages.BugzillaTaskEditorPage_Email_Line, string)); } } } BugzillaResponseDetailDialog dialog = new BugzillaResponseDetailDialog(WorkbenchUtil.getShell(), Messages.BugzillaTaskEditorPage_submitted_Changes_Details, message.toString()); dialog.open(); } }