/******************************************************************************* * Copyright (c) 2004, 2016 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 * Red Hat Inc. - fixes for bug 259291 *******************************************************************************/ package org.eclipse.mylyn.internal.bugzilla.core; import java.io.Serializable; import java.util.ArrayList; import java.util.Collections; import java.util.Date; import java.util.HashMap; import java.util.HashSet; import java.util.List; import java.util.Locale; import java.util.Map; import org.apache.commons.lang.BooleanUtils; import org.eclipse.core.runtime.CoreException; import org.eclipse.core.runtime.IProgressMonitor; import org.eclipse.mylyn.internal.bugzilla.core.IBugzillaConstants.BUGZILLA_REPORT_STATUS; import org.eclipse.mylyn.internal.bugzilla.core.IBugzillaConstants.BUGZILLA_REPORT_STATUS_4_0; import org.eclipse.mylyn.internal.bugzilla.core.service.BugzillaXmlRpcClient; import org.eclipse.mylyn.tasks.core.data.TaskAttribute; import org.eclipse.mylyn.tasks.core.data.TaskData; import org.eclipse.mylyn.tasks.core.data.TaskOperation; /** * Class describing the configuration of products and components for a given Bugzilla installation. * * @author Rob Elves * @author Charley Wang * @author Frank Becker */ public class RepositoryConfiguration implements Serializable { // old value private static final long serialVersionUID = -7248029094079799975L; private static final long serialVersionUID = -7051029281842783666L; private String repositoryUrl = "<unknown>"; //$NON-NLS-1$ private final Map<String, ProductEntry> products = new HashMap<String, ProductEntry>(); private final List<String> platforms = new ArrayList<String>(); private final List<String> operatingSystems = new ArrayList<String>(); private final List<String> priorities = new ArrayList<String>(); private final List<String> severities = new ArrayList<String>(); private final List<String> bugStatus = new ArrayList<String>(); private final List<String> openStatusValues = new ArrayList<String>(); private final List<String> closedStatusValues = new ArrayList<String>(); private final List<String> resolutionValues = new ArrayList<String>(); private final List<String> keywords = new ArrayList<String>(); // master lists private final List<String> versions = new ArrayList<String>(); private final List<String> components = new ArrayList<String>(); private final List<String> milestones = new ArrayList<String>(); private final List<BugzillaCustomField> customFields = new ArrayList<BugzillaCustomField>(); private final List<BugzillaFlag> flags = new ArrayList<BugzillaFlag>(); private BugzillaVersion version = BugzillaVersion.MIN_VERSION; private CustomTransitionManager validTransitions; private String encoding = null; private String eTagValue = null; private Date lastModifiedHeader = null; public RepositoryConfiguration() { } public List<String> getResolutions() { return resolutionValues; } /** * Adds a product to the configuration. */ public void addProduct(String name) { if (!products.containsKey(name)) { ProductEntry product = new ProductEntry(name); products.put(name, product); } } /** * Returns an array of names of current products. */ public List<String> getProducts() { ArrayList<String> productList = new ArrayList<String>(products.keySet()); Collections.sort(productList, String.CASE_INSENSITIVE_ORDER); return productList; } /** * Returns an array of names of component that exist for a given product or <code>null</code> if the product does * not exist. */ public List<String> getComponents(String product) { ProductEntry entry = products.get(product); if (entry != null) { return entry.getComponents(); } else { return Collections.emptyList(); } } /** * Returns an array of names of versions that exist for a given product or <code>null</code> if the product does not * exist. */ public List<String> getVersions(String product) { ProductEntry entry = products.get(product); if (entry != null) { return entry.getVersions(); } else { return Collections.emptyList(); } } /** * Returns an array of names of valid severity values. */ public List<String> getSeverities() { return severities; } /** * Returns an array of names of valid OS values. */ public List<String> getOSs() { return operatingSystems; } /** * Returns an array of names of valid platform values. */ public List<String> getPlatforms() { return platforms; } /** * Returns an array of names of valid platform values. */ public List<String> getPriorities() { return priorities; } /** * Adds a component to the given product. */ private void addComponent(String product, String component) { if (!components.contains(component)) { components.add(component); } ProductEntry entry = products.get(product); if (entry == null) { entry = new ProductEntry(product); products.put(product, entry); } entry.addComponent(component); } private void addVersion(String product, String version) { if (!versions.contains(version)) { versions.add(version); } ProductEntry entry = products.get(product); if (entry == null) { entry = new ProductEntry(product); products.put(product, entry); } entry.addVersion(version); } public List<String> getKeywords() { return keywords; } public void setInstallVersion(String version) { this.version = new BugzillaVersion(version); } public BugzillaVersion getInstallVersion() { return version; } private void addTargetMilestone(String product, String target) { if (!milestones.contains(target)) { milestones.add(target); } ProductEntry entry = products.get(product); if (entry == null) { entry = new ProductEntry(product); products.put(product, entry); } entry.addTargetMilestone(target); } public List<String> getTargetMilestones(String product) { ProductEntry entry = products.get(product); if (entry != null) { return entry.getTargetMilestones(); } else { return Collections.emptyList(); } } public void addUnconfirmedAllowed(String product, Boolean unconfirmedAllowed) { ProductEntry entry = products.get(product); if (entry == null) { entry = new ProductEntry(product); products.put(product, entry); } entry.setUnconfirmedAllowed(unconfirmedAllowed); } /** * Container for product information: name, components. */ private static class ProductEntry implements Serializable { private static final long serialVersionUID = 4120139521246741120L; @SuppressWarnings("unused") String productName; List<String> components = new ArrayList<String>(); List<String> versions = new ArrayList<String>(); List<String> milestones = new ArrayList<String>(); String defaultMilestone = null; Boolean unconfirmedAllowed = false; ProductEntry(String name) { this.productName = name; } List<String> getComponents() { return components; } void addComponent(String componentName) { if (!components.contains(componentName)) { components.add(componentName); } } List<String> getVersions() { return versions; } void addVersion(String name) { if (!versions.contains(name)) { versions.add(name); } } List<String> getTargetMilestones() { return milestones; } void addTargetMilestone(String target) { milestones.add(target); } public String getDefaultMilestone() { return defaultMilestone; } public void setDefaultMilestone(String defaultMilestone) { this.defaultMilestone = defaultMilestone; } public Boolean getUnconfirmedAllowed() { return unconfirmedAllowed; } public void setUnconfirmedAllowed(Boolean unconfirmedAllowed) { this.unconfirmedAllowed = unconfirmedAllowed; } } public List<String> getOpenStatusValues() { return openStatusValues; } public void addOpenStatusValue(String value) { openStatusValues.add(value); } public List<String> getClosedStatusValues() { if (validTransitions != null) { ArrayList<String> closedStatus = validTransitions.getClosedStatuses(); if (closedStatus != null && !closedStatus.isEmpty()) { return closedStatus; } } return closedStatusValues; } public void addClosedStatusValue(String value) { closedStatusValues.add(value); } public List<String> getComponents() { return components; } public List<String> getTargetMilestones() { return milestones; } public List<String> getVersions() { return versions; } public String getRepositoryUrl() { return repositoryUrl; } public void setRepositoryUrl(String repositoryUrl) { this.repositoryUrl = repositoryUrl; } /** * Create a custom transition manager. If fileName is invalid, the resulting transition manager will also be * invalid. * * @param fileName * @throws CoreException */ public void setValidTransitions(IProgressMonitor monitor, String fileName, BugzillaXmlRpcClient xmlClient) throws CoreException { //Custom transitions only possible for newer versions of Bugzilla if (getInstallVersion() != null && getInstallVersion().compareMajorMinorOnly(BugzillaVersion.BUGZILLA_3_2) < 0) { return; } try { if (validTransitions == null) { validTransitions = new CustomTransitionManager(); } if (xmlClient == null) { if (!validTransitions.parse(fileName)) { validTransitions = null; } } else { if (!version.isSmaller(BugzillaVersion.BUGZILLA_3_6)) { validTransitions.parse(monitor, xmlClient); } else { validTransitions = null; } } } catch (CoreException e) { validTransitions = null; throw e; } } public List<String> getOptionValues(BugzillaAttribute element) { switch (element) { case PRODUCT: return getProducts(); case TARGET_MILESTONE: return milestones; case BUG_STATUS: return bugStatus; case VERSION: return versions; case COMPONENT: return components; case REP_PLATFORM: return platforms; case OP_SYS: return operatingSystems; case PRIORITY: return priorities; case BUG_SEVERITY: return severities; case KEYWORDS: return keywords; case RESOLUTION: return resolutionValues; default: return Collections.emptyList(); } } public List<String> getProductOptionValues(BugzillaAttribute element, String product) { switch (element) { case TARGET_MILESTONE: return getTargetMilestones(product); case VERSION: return getVersions(product); case COMPONENT: return getComponents(product); default: return Collections.emptyList(); } } public void addItem(BugzillaAttribute element, String value) { switch (element) { case BUG_STATUS: bugStatus.add(value); break; case RESOLUTION: resolutionValues.add(value); break; case KEYWORDS: keywords.add(value); break; case REP_PLATFORM: platforms.add(value); break; case OP_SYS: operatingSystems.add(value); break; case PRIORITY: priorities.add(value); break; case BUG_SEVERITY: severities.add(value); break; case PRODUCT: addProduct(value); break; default: break; } } public void addItem2ProductConfiguration(BugzillaAttribute element, String product, String value) { switch (element) { case COMPONENT: addComponent(product, value); break; case VERSION: addVersion(product, value); break; case TARGET_MILESTONE: addTargetMilestone(product, value); default: break; } } /** * Adds a field to the configuration. */ public void addCustomField(BugzillaCustomField newField) { customFields.add(newField); } public List<BugzillaCustomField> getCustomFields() { return customFields; } public void configureTaskData(TaskData taskData, boolean localuser, BugzillaRepositoryConnector connector) { if (taskData != null) { addMissingFlags(taskData, connector); updateAttributeOptions(taskData); addValidOperations(taskData); if (localuser) { removeDomain(taskData); } addMissingAttachmentFlags(taskData, connector); updateAttachmentOptions(taskData); } } private void removeDomain(TaskData taskData) { for (BugzillaAttribute element : BugzillaAttribute.PERSON_ATTRIBUTES) { TaskAttribute attribute = taskData.getRoot().getAttribute(element.getKey()); if (attribute != null) { cleanShortLogin(attribute); } } } private void cleanShortLogin(TaskAttribute a) { if (a.getValue() != null && a.getValue().length() > 0) { int atIndex = a.getValue().indexOf("@"); //$NON-NLS-1$ if (atIndex != -1) { String newValue = a.getValue().substring(0, atIndex); a.setValue(newValue); } } } private void addMissingFlags(TaskData taskData, BugzillaRepositoryConnector connector) { List<String> existingFlags = new ArrayList<String>(); List<BugzillaFlag> flags = getFlags(); for (TaskAttribute attribute : new HashSet<TaskAttribute>(taskData.getRoot().getAttributes().values())) { if (attribute.getId().startsWith(BugzillaAttribute.KIND_FLAG)) { TaskAttribute state = attribute.getAttribute("state"); //$NON-NLS-1$ if (state != null) { String nameValue = state.getMetaData().getLabel(); if (!existingFlags.contains(nameValue)) { existingFlags.add(nameValue); } String desc = attribute.getMetaData().getLabel(); if (desc == null || desc.equals("")) { //$NON-NLS-1$ for (BugzillaFlag bugzillaFlag : flags) { if (bugzillaFlag.getType().equals("attachment")) { //$NON-NLS-1$ continue; } if (bugzillaFlag.getName().equals(nameValue)) { attribute.getMetaData().setLabel(bugzillaFlag.getDescription()); } } } } } } TaskAttribute productAttribute = taskData.getRoot().getMappedAttribute(BugzillaAttribute.PRODUCT.getKey()); TaskAttribute componentAttribute = taskData.getRoot().getMappedAttribute(BugzillaAttribute.COMPONENT.getKey()); for (BugzillaFlag bugzillaFlag : flags) { if (bugzillaFlag.getType().equals("attachment")) { //$NON-NLS-1$ continue; } if (!bugzillaFlag.isUsedIn(productAttribute.getValue(), componentAttribute.getValue())) { continue; } if (existingFlags.contains(bugzillaFlag.getName()) && !bugzillaFlag.isMultiplicable()) { continue; } BugzillaFlagMapper mapper = new BugzillaFlagMapper(connector); mapper.setRequestee(""); //$NON-NLS-1$ mapper.setSetter(""); //$NON-NLS-1$ mapper.setState(" "); //$NON-NLS-1$ mapper.setFlagId(bugzillaFlag.getName()); mapper.setNumber(0); mapper.setDescription(bugzillaFlag.getDescription()); TaskAttribute attribute = taskData.getRoot() .createAttribute(BugzillaAttribute.KIND_FLAG_TYPE + bugzillaFlag.getFlagId()); mapper.applyTo(attribute); } setFlagsRequestee(taskData); } private void setFlagsRequestee(TaskData taskData) { for (TaskAttribute attribute : new HashSet<TaskAttribute>(taskData.getRoot().getAttributes().values())) { if (attribute.getId().startsWith(BugzillaAttribute.KIND_FLAG)) { TaskAttribute state = attribute.getAttribute("state"); //$NON-NLS-1$ if (state != null) { String nameValue = state.getMetaData().getLabel(); for (BugzillaFlag bugzillaFlag : flags) { if (nameValue.equals(bugzillaFlag.getName())) { TaskAttribute requestee = attribute.getAttribute("requestee"); //$NON-NLS-1$ if (requestee == null) { requestee = attribute.createMappedAttribute("requestee"); //$NON-NLS-1$ requestee.getMetaData().defaults().setType(TaskAttribute.TYPE_PERSON); requestee.setValue(""); //$NON-NLS-1$ } requestee.getMetaData().setReadOnly(!bugzillaFlag.isSpecifically_requestable()); } } } } } } public void updateAttributeOptions(TaskData existingReport) { TaskAttribute attributeProduct = existingReport.getRoot() .getMappedAttribute(BugzillaAttribute.PRODUCT.getKey()); if (attributeProduct == null) { return; } String product = attributeProduct.getValue(); for (TaskAttribute attribute : new HashSet<TaskAttribute>(existingReport.getRoot().getAttributes().values())) { List<String> optionValues = getAttributeOptions(product, attribute); if (attribute.getId().equals(BugzillaAttribute.TARGET_MILESTONE.getKey()) && optionValues.isEmpty()) { existingReport.getRoot().removeAttribute(BugzillaAttribute.TARGET_MILESTONE.getKey()); continue; } if (attribute.getId().startsWith(BugzillaAttribute.KIND_FLAG)) { attribute = attribute.getAttribute("state"); //$NON-NLS-1$ } attribute.clearOptions(); for (String option : optionValues) { attribute.putOption(option, option); } } } public List<String> getAttributeOptions(String product, TaskAttribute attribute) { List<String> options = new ArrayList<String>(); if (attribute.getId().startsWith(BugzillaCustomField.CUSTOM_FIELD_PREFIX)) { for (BugzillaCustomField bugzillaCustomField : customFields) { if (bugzillaCustomField.getName().equals(attribute.getId())) { options.addAll(bugzillaCustomField.getOptions()); break; } } } else if (attribute.getId().startsWith(BugzillaAttribute.KIND_FLAG)) { TaskAttribute state = attribute.getAttribute("state"); //$NON-NLS-1$ if (state != null) { String nameValue = state.getMetaData().getLabel(); options.add(""); //$NON-NLS-1$ for (BugzillaFlag bugzillaFlag : flags) { if (nameValue.equals(bugzillaFlag.getName())) { if (nameValue.equals(bugzillaFlag.getName())) { if (bugzillaFlag.isRequestable()) { options.add("?"); //$NON-NLS-1$ } break; } } } options.add("+"); //$NON-NLS-1$ options.add("-"); //$NON-NLS-1$ } } else { String type = attribute.getMetaData().getType(); if (type != null && type.equals(IBugzillaConstants.EDITOR_TYPE_FLAG)) { options.add(""); //$NON-NLS-1$ options.add("?"); //$NON-NLS-1$ options.add("+"); //$NON-NLS-1$ options.add("-"); //$NON-NLS-1$ } else { BugzillaAttribute element; try { element = BugzillaAttribute.valueOf(attribute.getId().trim().toUpperCase(Locale.ENGLISH)); } catch (RuntimeException e) { if (e instanceof IllegalArgumentException) { // ignore unrecognized tags return options; } throw e; } if ((element == BugzillaAttribute.TARGET_MILESTONE || element == BugzillaAttribute.VERSION || element == BugzillaAttribute.COMPONENT) && (product != null && !product.equals(""))) { //$NON-NLS-1$ options.addAll(getProductOptionValues(element, product)); } else { options.addAll(getOptionValues(element)); } if (element != BugzillaAttribute.RESOLUTION && element != BugzillaAttribute.OP_SYS && element != BugzillaAttribute.BUG_SEVERITY && element != BugzillaAttribute.PRIORITY && element != BugzillaAttribute.BUG_STATUS && element != BugzillaAttribute.TARGET_MILESTONE && element != BugzillaAttribute.PRODUCT) { Collections.sort(options); } } } return options; } public void addValidOperations(TaskData bugReport) { BugzillaVersion bugzillaVersion = getInstallVersion(); if (bugzillaVersion == null) { bugzillaVersion = BugzillaVersion.MIN_VERSION; } if (bugzillaVersion.compareMajorMinorOnly(BugzillaVersion.BUGZILLA_4_0) < 0) { addValidOperationsBefore4(bugReport); } else { if (getOptionValues(BugzillaAttribute.BUG_STATUS) .contains(BUGZILLA_REPORT_STATUS_4_0.IN_PROGRESS.toString()) || getOptionValues(BugzillaAttribute.BUG_STATUS) .contains(BUGZILLA_REPORT_STATUS_4_0.CONFIRMED.toString())) { addValidOperationsAfter4(bugReport); } else { addValidOperationsBefore4(bugReport); } } } public void addValidOperationsAfter4(TaskData bugReport) { TaskAttribute attributeStatus = bugReport.getRoot().getMappedAttribute(TaskAttribute.STATUS); BUGZILLA_REPORT_STATUS_4_0 status = BUGZILLA_REPORT_STATUS_4_0.UNCONFIRMED; if (attributeStatus != null) { try { status = BUGZILLA_REPORT_STATUS_4_0.valueOf(attributeStatus.getValue()); } catch (RuntimeException e) { status = BUGZILLA_REPORT_STATUS_4_0.UNCONFIRMED; } } if (validTransitions != null && attributeStatus != null && validTransitions.isValid()) { //Handle custom operations. Currently only tuned for transitions based on default status names if (attributeStatus.getValue().equals("START")) { //$NON-NLS-1$ addOperation(bugReport, BugzillaOperation.new_default); TaskAttribute operationAttribute = bugReport.getRoot().getAttribute(TaskAttribute.OPERATION); TaskOperation.applyTo(operationAttribute, BugzillaOperation.new_default.toString(), IBugzillaConstants.BUGZILLA_REPORT_STATUS_4_0.START.toString()); } else { addOperation(bugReport, BugzillaOperation.none); for (AbstractBugzillaOperation b : validTransitions.getValidTransitions(attributeStatus.getValue())) { //Special case: the CLOSED status needs a Resolution input. //This happens automatically if current status is RESOLVED, else we need to supply one if (b.toString().equals(BugzillaOperation.close.toString())) { if (attributeStatus.getValue().equals("RESOLVED") && b.getInputId() != null) { //$NON-NLS-1$ //Do not add close with resolution operation if status is RESOLVED continue; } else if (!attributeStatus.getValue().equals("RESOLVED") && b.getInputId() == null) { //$NON-NLS-1$ //Do not add normal 'close' operation if status is not currently RESOLVED continue; } } addOperation(bugReport, b); } } } else { TaskAttribute everConfirmed = bugReport.getRoot().getAttribute(BugzillaAttribute.EVERCONFIRMED.getKey()); TaskAttribute product = bugReport.getRoot().getMappedAttribute(TaskAttribute.PRODUCT); boolean unconfirmedAllowed = getUnconfirmedAllowed(product.getValue()); switch (status) { case START: addOperation(bugReport, BugzillaOperation.new_default); addOperation(bugReport, BugzillaOperation.unconfirmed); TaskAttribute unconfirmedAttribute = bugReport.getRoot() .getAttribute(TaskAttribute.PREFIX_OPERATION + BugzillaOperation.unconfirmed.toString()); if (unconfirmedAttribute != null) { unconfirmedAttribute.getMetaData().setDisabled(!unconfirmedAllowed); } addOperation(bugReport, BugzillaOperation.confirmed); addOperation(bugReport, BugzillaOperation.in_progress); TaskAttribute operationAttribute = bugReport.getRoot().getAttribute(TaskAttribute.OPERATION); TaskOperation.applyTo(operationAttribute, BugzillaOperation.new_default.toString(), IBugzillaConstants.BUGZILLA_REPORT_STATUS_4_0.START.toString()); break; case UNCONFIRMED: addOperation(bugReport, BugzillaOperation.none); addOperation(bugReport, BugzillaOperation.confirmed); addOperation(bugReport, BugzillaOperation.in_progress); addOperation(bugReport, BugzillaOperation.resolve); break; case CONFIRMED: addOperation(bugReport, BugzillaOperation.none); addOperation(bugReport, BugzillaOperation.in_progress); addOperation(bugReport, BugzillaOperation.resolve); break; case IN_PROGRESS: addOperation(bugReport, BugzillaOperation.none); addOperation(bugReport, BugzillaOperation.confirmed); addOperation(bugReport, BugzillaOperation.resolve); break; case RESOLVED: addOperation(bugReport, BugzillaOperation.none); if (unconfirmedAllowed) { addOperation(bugReport, BugzillaOperation.unconfirmed); } if (everConfirmed != null && "1".equals(everConfirmed.getValue())) { //$NON-NLS-1$ addOperation(bugReport, BugzillaOperation.confirmed); } addOperation(bugReport, BugzillaOperation.verify_with_resolution); break; case VERIFIED: addOperation(bugReport, BugzillaOperation.none); if (unconfirmedAllowed) { addOperation(bugReport, BugzillaOperation.unconfirmed); } if (everConfirmed != null && "1".equals(everConfirmed.getValue())) { //$NON-NLS-1$ addOperation(bugReport, BugzillaOperation.confirmed); } addOperation(bugReport, BugzillaOperation.resolve); break; } if (status != BUGZILLA_REPORT_STATUS_4_0.START) { addOperation(bugReport, BugzillaOperation.duplicate); } } BugzillaAttribute key = BugzillaAttribute.SET_DEFAULT_ASSIGNEE; TaskAttribute operationAttribute = bugReport.getRoot().getAttribute(key.getKey()); if (operationAttribute == null) { operationAttribute = bugReport.getRoot().createAttribute(key.getKey()); operationAttribute.getMetaData() .defaults() .setReadOnly(key.isReadOnly()) .setKind(key.getKind()) .setLabel(key.toString()) .setType(key.getType()); operationAttribute.setValue("0"); //$NON-NLS-1$ } operationAttribute = bugReport.getRoot().getMappedAttribute(TaskAttribute.USER_ASSIGNED); if (operationAttribute != null) { operationAttribute.getMetaData().setReadOnly(false); } } public void addValidOperationsBefore4(TaskData bugReport) { TaskAttribute attributeStatus = bugReport.getRoot().getMappedAttribute(TaskAttribute.STATUS); BUGZILLA_REPORT_STATUS status = BUGZILLA_REPORT_STATUS.NEW; if (attributeStatus != null) { try { status = BUGZILLA_REPORT_STATUS.valueOf(attributeStatus.getValue()); } catch (RuntimeException e) { status = BUGZILLA_REPORT_STATUS.NEW; } } BugzillaVersion bugzillaVersion = getInstallVersion(); if (bugzillaVersion == null) { bugzillaVersion = BugzillaVersion.MIN_VERSION; } if (validTransitions != null && attributeStatus != null && validTransitions.isValid()) { //Handle custom operations. Currently only tuned for transitions based on default status names addOperation(bugReport, BugzillaOperation.none); for (AbstractBugzillaOperation b : validTransitions.getValidTransitions(attributeStatus.getValue())) { //Special case: the CLOSED status needs a Resolution input. //This happens automatically if current status is RESOLVED, else we need to supply one if (b.toString().equals(BugzillaOperation.close.toString())) { if (attributeStatus.getValue().equals("RESOLVED") && b.getInputId() != null) { //$NON-NLS-1$ //Do not add close with resolution operation if status is RESOLVED continue; } else if (!attributeStatus.getValue().equals("RESOLVED") && b.getInputId() == null) { //$NON-NLS-1$ //Do not add normal 'close' operation if status is not currently RESOLVED continue; } } addOperation(bugReport, b); } } else { // Eclipse Bugzilla State transitions // UNCONFIRMED // NEW ASSIGNED RESOLVED# CLOSED# // ASSIGNED NEW RESOLVED# CLOSED# // REOPENED NEW ASSIGNED RESOLVED# CLOSED# // RESOLVED REOPENED VERIFIED# CLOSED# // VERIFIED REOPENED RESOLVED# CLOSED# // CLOSED REOPENED RESOLVED# switch (status) { case NEW: addOperation(bugReport, BugzillaOperation.none); addOperation(bugReport, BugzillaOperation.accept); addOperation(bugReport, BugzillaOperation.resolve); // This is not the standard workflow add with bug 326216 to support eclipse.org if (bugzillaVersion.compareMajorMinorOnly(BugzillaVersion.BUGZILLA_3_2) >= 0) { addOperation(bugReport, BugzillaOperation.close_with_resolution); } addOperation(bugReport, BugzillaOperation.duplicate); break; case UNCONFIRMED: case REOPENED: addOperation(bugReport, BugzillaOperation.none); addOperation(bugReport, BugzillaOperation.accept); addOperation(bugReport, BugzillaOperation.resolve); // This is not the standard workflow add with bug 326216 to support eclipse.org if (bugzillaVersion.compareMajorMinorOnly(BugzillaVersion.BUGZILLA_3_2) >= 0) { addOperation(bugReport, BugzillaOperation.close_with_resolution); } addOperation(bugReport, BugzillaOperation.duplicate); if (bugzillaVersion.compareMajorMinorOnly(BugzillaVersion.BUGZILLA_3_2) >= 0) { addOperation(bugReport, BugzillaOperation.markNew); } break; case ASSIGNED: addOperation(bugReport, BugzillaOperation.none); addOperation(bugReport, BugzillaOperation.resolve); // This is not the standard workflow add with bug 326216 to support eclipse.org if (bugzillaVersion.compareMajorMinorOnly(BugzillaVersion.BUGZILLA_3_2) >= 0) { addOperation(bugReport, BugzillaOperation.close_with_resolution); } addOperation(bugReport, BugzillaOperation.duplicate); if (bugzillaVersion.compareMajorMinorOnly(BugzillaVersion.BUGZILLA_3_2) >= 0) { addOperation(bugReport, BugzillaOperation.markNew); } break; case RESOLVED: addOperation(bugReport, BugzillaOperation.none); addOperation(bugReport, BugzillaOperation.reopen); addOperation(bugReport, BugzillaOperation.verify); addOperation(bugReport, BugzillaOperation.close); if (bugzillaVersion.compareMajorMinorOnly(BugzillaVersion.BUGZILLA_3_0) >= 0) { addOperation(bugReport, BugzillaOperation.duplicate); addOperation(bugReport, BugzillaOperation.resolve); } break; case CLOSED: addOperation(bugReport, BugzillaOperation.none); addOperation(bugReport, BugzillaOperation.reopen); if (bugzillaVersion.compareMajorMinorOnly(BugzillaVersion.BUGZILLA_3_0) >= 0) { addOperation(bugReport, BugzillaOperation.duplicate); addOperation(bugReport, BugzillaOperation.resolve); } break; case VERIFIED: addOperation(bugReport, BugzillaOperation.none); addOperation(bugReport, BugzillaOperation.reopen); addOperation(bugReport, BugzillaOperation.close); if (bugzillaVersion.compareMajorMinorOnly(BugzillaVersion.BUGZILLA_3_0) >= 0) { addOperation(bugReport, BugzillaOperation.duplicate); addOperation(bugReport, BugzillaOperation.resolve); } } } if (bugzillaVersion.compareTo(BugzillaVersion.BUGZILLA_3_0) < 0) { // Product change is only supported for Versions >= 3.0 without verify html page TaskAttribute productAttribute = bugReport.getRoot().getMappedAttribute(BugzillaAttribute.PRODUCT.getKey()); productAttribute.getMetaData().setReadOnly(true); } if (bugzillaVersion.compareMajorMinorOnly(BugzillaVersion.BUGZILLA_3_0) <= 0) { if (status == BUGZILLA_REPORT_STATUS.NEW || status == BUGZILLA_REPORT_STATUS.ASSIGNED || status == BUGZILLA_REPORT_STATUS.REOPENED || status == BUGZILLA_REPORT_STATUS.UNCONFIRMED) { // old bugzilla workflow is used addOperation(bugReport, BugzillaOperation.reassign); addOperation(bugReport, BugzillaOperation.reassignbycomponent); } } else { BugzillaAttribute key = BugzillaAttribute.SET_DEFAULT_ASSIGNEE; TaskAttribute operationAttribute = bugReport.getRoot().getAttribute(key.getKey()); if (operationAttribute == null) { operationAttribute = bugReport.getRoot().createAttribute(key.getKey()); operationAttribute.getMetaData() .defaults() .setReadOnly(key.isReadOnly()) .setKind(key.getKind()) .setLabel(key.toString()) .setType(key.getType()); operationAttribute.setValue("0"); //$NON-NLS-1$ } operationAttribute = bugReport.getRoot().getMappedAttribute(TaskAttribute.USER_ASSIGNED); if (operationAttribute != null) { operationAttribute.getMetaData().setReadOnly(false); } } } public void addOperation(TaskData bugReport, AbstractBugzillaOperation op) { TaskAttribute attribute; TaskAttribute operationAttribute = bugReport.getRoot().getAttribute(TaskAttribute.OPERATION); if (operationAttribute == null) { operationAttribute = bugReport.getRoot().createAttribute(TaskAttribute.OPERATION); } if (op.toString() == BugzillaOperation.none.toString()) { attribute = bugReport.getRoot().createAttribute(TaskAttribute.PREFIX_OPERATION + op.toString()); String label = "Leave"; //$NON-NLS-1$ TaskAttribute attributeStatus = bugReport.getRoot().getMappedAttribute(TaskAttribute.STATUS); TaskAttribute attributeResolution = bugReport.getRoot().getMappedAttribute(TaskAttribute.RESOLUTION); if (attributeStatus != null && attributeResolution != null) { label = String.format(op.getLabel(), attributeStatus.getValue(), attributeResolution.getValue()); } TaskOperation.applyTo(attribute, op.toString(), label); // set as default TaskOperation.applyTo(operationAttribute, op.toString(), label); } else if (op.toString() == BugzillaOperation.resolve.toString()) { attribute = bugReport.getRoot().createAttribute(TaskAttribute.PREFIX_OPERATION + op.toString()); TaskOperation.applyTo(attribute, op.toString(), op.getLabel()); TaskAttribute attrResolvedInput = attribute.getTaskData().getRoot().createAttribute(op.getInputId()); attrResolvedInput.getMetaData().setType(op.getInputType()); attribute.getMetaData().putValue(TaskAttribute.META_ASSOCIATED_ATTRIBUTE_ID, op.getInputId()); for (String resolution : getOptionValues(BugzillaAttribute.RESOLUTION)) { // DUPLICATE and MOVED have special meanings so do not show as resolution if (resolution.compareTo("DUPLICATE") != 0 && resolution.compareTo("MOVED") != 0) { //$NON-NLS-1$ //$NON-NLS-2$ attrResolvedInput.putOption(resolution, resolution); } } if (getOptionValues(BugzillaAttribute.RESOLUTION).size() > 0) { attrResolvedInput.setValue(getOptionValues(BugzillaAttribute.RESOLUTION).get(0)); } } else if (op.toString().equals(BugzillaOperation.verify_with_resolution.toString()) && op.getInputId() != null) { TaskAttribute attributeResolution = bugReport.getRoot().getMappedAttribute(TaskAttribute.RESOLUTION); String oldResolutionValue = attributeResolution.getValue(); attribute = bugReport.getRoot().createAttribute(TaskAttribute.PREFIX_OPERATION + op.toString()); TaskOperation.applyTo(attribute, op.toString(), op.getLabel()); TaskAttribute attrResolvedInput = attribute.getTaskData().getRoot().createAttribute(op.getInputId()); attrResolvedInput.getMetaData().setType(op.getInputType()); attribute.getMetaData().putValue(TaskAttribute.META_ASSOCIATED_ATTRIBUTE_ID, op.getInputId()); for (String resolution : getOptionValues(BugzillaAttribute.RESOLUTION)) { // DUPLICATE and MOVED have special meanings so do not show as resolution if (resolution.compareTo("DUPLICATE") != 0 && resolution.compareTo("MOVED") != 0) { //$NON-NLS-1$ //$NON-NLS-2$ attrResolvedInput.putOption(resolution, resolution); } } if (getOptionValues(BugzillaAttribute.RESOLUTION).size() > 0) { attrResolvedInput.setValue(oldResolutionValue); } } else if (op.toString().equals(BugzillaOperation.close_with_resolution.toString()) && op.getInputId() != null) { attribute = bugReport.getRoot().createAttribute(TaskAttribute.PREFIX_OPERATION + op.toString()); TaskOperation.applyTo(attribute, op.toString(), op.getLabel()); TaskAttribute attrResolvedInput = attribute.getTaskData().getRoot().createAttribute(op.getInputId()); attrResolvedInput.getMetaData().setType(op.getInputType()); attribute.getMetaData().putValue(TaskAttribute.META_ASSOCIATED_ATTRIBUTE_ID, op.getInputId()); for (String resolution : getOptionValues(BugzillaAttribute.RESOLUTION)) { // DUPLICATE and MOVED have special meanings so do not show as resolution if (resolution.compareTo("DUPLICATE") != 0 && resolution.compareTo("MOVED") != 0) { //$NON-NLS-1$ //$NON-NLS-2$ attrResolvedInput.putOption(resolution, resolution); } } if (getOptionValues(BugzillaAttribute.RESOLUTION).size() > 0) { attrResolvedInput.setValue(getOptionValues(BugzillaAttribute.RESOLUTION).get(0)); } } else if (op.toString() == BugzillaOperation.duplicate.toString()) { attribute = bugReport.getRoot().createAttribute(TaskAttribute.PREFIX_OPERATION + op.toString()); TaskOperation.applyTo(attribute, op.toString(), op.getLabel()); if (op.getInputId() != null) { TaskAttribute attrInput = bugReport.getRoot().getAttribute(op.getInputId()); if (attrInput == null) { attrInput = bugReport.getRoot().createAttribute(op.getInputId()); } attrInput.getMetaData().defaults().setReadOnly(false).setType(op.getInputType()); attribute.getMetaData().putValue(TaskAttribute.META_ASSOCIATED_ATTRIBUTE_ID, op.getInputId()); } } else if (op.toString() == BugzillaOperation.new_default.toString()) { attribute = bugReport.getRoot().createAttribute(TaskAttribute.PREFIX_OPERATION + op.toString()); TaskOperation.applyTo(attribute, op.toString(), op.getLabel()); } else { attribute = bugReport.getRoot().createAttribute(TaskAttribute.PREFIX_OPERATION + op.toString()); if (bugReport.isNew()) { TaskOperation.applyTo(attribute, op.toString(), op.getLabel()); } else { TaskOperation.applyTo(attribute, op.toString(), op.getLabel()); } if (op.getInputId() != null) { TaskAttribute attrInput = bugReport.getRoot().createAttribute(op.getInputId()); attrInput.getMetaData().defaults().setReadOnly(false).setType(op.getInputType()); attribute.getMetaData().putValue(TaskAttribute.META_ASSOCIATED_ATTRIBUTE_ID, op.getInputId()); } } //set the Tooltip if (op.toString().equals(BugzillaOperation.none.toString())) { attribute.getMetaData().putValue(TaskAttribute.META_DESCRIPTION, Messages.RepositoryConfiguration_Operation_Tooltip_none); } else if (op.toString().equals(BugzillaOperation.new_default.toString())) { attribute.getMetaData().putValue(TaskAttribute.META_DESCRIPTION, Messages.RepositoryConfiguration_Operation_Tooltip_new_default); } else if (op.toString().equals(BugzillaOperation.unconfirmed.toString())) { attribute.getMetaData().putValue(TaskAttribute.META_DESCRIPTION, Messages.RepositoryConfiguration_Operation_Tooltip_unconfirmed); } else if (op.toString().equals(BugzillaOperation.confirmed.toString())) { attribute.getMetaData().putValue(TaskAttribute.META_DESCRIPTION, Messages.RepositoryConfiguration_Operation_Tooltip_confirmed); } else if (op.toString().equals(BugzillaOperation.in_progress.toString())) { attribute.getMetaData().putValue(TaskAttribute.META_DESCRIPTION, Messages.RepositoryConfiguration_Operation_Tooltip_in_progress); } else if (op.toString().equals(BugzillaOperation.resolve.toString())) { attribute.getMetaData().putValue(TaskAttribute.META_DESCRIPTION, Messages.RepositoryConfiguration_Operation_Tooltip_resolve); } else if (op.toString().equals(BugzillaOperation.verify.toString()) || op.toString().equals(BugzillaOperation.verify_with_resolution.toString())) { attribute.getMetaData().putValue(TaskAttribute.META_DESCRIPTION, Messages.RepositoryConfiguration_Operation_Tooltip_veryfy); } else if (op.toString().equals(BugzillaOperation.duplicate.toString())) { attribute.getMetaData().putValue(TaskAttribute.META_DESCRIPTION, Messages.RepositoryConfiguration_Operation_Tooltip_duplicate); } else if (op.toString().equals(BugzillaOperation.reopen.toString())) { attribute.getMetaData().putValue(TaskAttribute.META_DESCRIPTION, Messages.RepositoryConfiguration_Operation_Tooltip_reopen); } else if (op.toString().equals(BugzillaOperation.close.toString()) || op.toString().equals(BugzillaOperation.close_with_resolution.toString())) { attribute.getMetaData().putValue(TaskAttribute.META_DESCRIPTION, Messages.RepositoryConfiguration_Operation_Tooltip_close); } } /** * Adds a flag to the configuration. */ public void addFlag(BugzillaFlag newFlag) { flags.add(newFlag); } public List<BugzillaFlag> getFlags() { return flags; } public BugzillaFlag getFlagWithId(Integer id) { for (BugzillaFlag bugzillaFlag : flags) { if (bugzillaFlag.getFlagId() == id) { return bugzillaFlag; } } return null; } public void setEncoding(String encoding) { this.encoding = encoding; } public String getEncoding() { return encoding; } public void updateAttachmentOptions(TaskData existingReport) { for (TaskAttribute attribute : new HashSet<TaskAttribute>(existingReport.getRoot().getAttributes().values())) { if (!attribute.getId().startsWith("task.common.attachment")) { //$NON-NLS-1$ continue; } for (TaskAttribute attachmentAttribute : attribute.getAttributes().values()) { if (!attachmentAttribute.getId().startsWith(BugzillaAttribute.KIND_FLAG)) { continue; } TaskAttribute state = attachmentAttribute.getAttribute("state"); //$NON-NLS-1$ attachmentAttribute.clearOptions(); String nameValue = state.getMetaData().getLabel(); state.putOption("", ""); //$NON-NLS-1$ //$NON-NLS-2$ for (BugzillaFlag bugzillaFlag : flags) { if (nameValue.equals(bugzillaFlag.getName()) && bugzillaFlag.getType().equals("attachment")) { //$NON-NLS-1$ if ("attachment".equals(bugzillaFlag.getType())) { //$NON-NLS-1$ if (bugzillaFlag.isRequestable()) { state.putOption("?", "?"); //$NON-NLS-1$ //$NON-NLS-2$ } break; } } } state.putOption("-", "-"); //$NON-NLS-1$ //$NON-NLS-2$ state.putOption("+", "+"); //$NON-NLS-1$ //$NON-NLS-2$ String flagNameValue = state.getMetaData().getLabel(); for (BugzillaFlag bugzillaFlag : flags) { if (flagNameValue.equals(bugzillaFlag.getName()) && bugzillaFlag.getType().equals("attachment")) { //$NON-NLS-1$ TaskAttribute requestee = attachmentAttribute.getAttribute("requestee"); //$NON-NLS-1$ if (requestee == null) { requestee = attachmentAttribute.createMappedAttribute("requestee"); //$NON-NLS-1$ requestee.getMetaData().defaults().setType(TaskAttribute.TYPE_SHORT_TEXT); requestee.setValue(""); //$NON-NLS-1$ } requestee.getMetaData().setReadOnly(!bugzillaFlag.isSpecifically_requestable()); } } } } } private void addMissingAttachmentFlags(TaskData taskData, BugzillaRepositoryConnector connector) { List<String> existingFlags = new ArrayList<String>(); List<BugzillaFlag> flags = getFlags(); for (TaskAttribute attribute : new HashSet<TaskAttribute>(taskData.getRoot().getAttributes().values())) { if (!attribute.getId().startsWith("task.common.attachment")) { //$NON-NLS-1$ continue; } existingFlags.clear(); for (TaskAttribute attachmentAttribute : attribute.getAttributes().values()) { if (!attachmentAttribute.getId().startsWith(BugzillaAttribute.KIND_FLAG)) { continue; } TaskAttribute state = attachmentAttribute.getAttribute("state"); //$NON-NLS-1$ if (state != null) { String nameValue = state.getMetaData().getLabel(); if (!existingFlags.contains(nameValue)) { existingFlags.add(nameValue); } } } TaskAttribute productAttribute = taskData.getRoot().getMappedAttribute(BugzillaAttribute.PRODUCT.getKey()); TaskAttribute componentAttribute = taskData.getRoot() .getMappedAttribute(BugzillaAttribute.COMPONENT.getKey()); for (BugzillaFlag bugzillaFlag : flags) { if (!bugzillaFlag.getType().equals("attachment")) { //$NON-NLS-1$ continue; } if (!bugzillaFlag.isUsedIn(productAttribute.getValue(), componentAttribute.getValue())) { continue; } if (existingFlags.contains(bugzillaFlag.getName()) && !bugzillaFlag.isMultiplicable()) { continue; } BugzillaFlagMapper mapper = new BugzillaFlagMapper(connector); mapper.setRequestee(""); //$NON-NLS-1$ mapper.setSetter(""); //$NON-NLS-1$ mapper.setState(" "); //$NON-NLS-1$ mapper.setFlagId(bugzillaFlag.getName()); mapper.setNumber(0); mapper.setDescription(bugzillaFlag.getDescription()); TaskAttribute newattribute = attribute .createAttribute(BugzillaAttribute.KIND_FLAG_TYPE + bugzillaFlag.getFlagId()); mapper.applyTo(newattribute); } } } public void setETagValue(String eTagValue) { this.eTagValue = eTagValue; } public String getETagValue() { return eTagValue; } public String getDuplicateStatus() { return validTransitions == null ? IBugzillaConstants.BUGZILLA_REPORT_STATUS.RESOLVED.toString() : validTransitions.getDuplicateStatus(); } public String getStartStatus() { if (validTransitions == null) { return version.compareMajorMinorOnly(BugzillaVersion.BUGZILLA_4_0) < 0 || !(getOptionValues(BugzillaAttribute.BUG_STATUS) .contains(BUGZILLA_REPORT_STATUS_4_0.IN_PROGRESS.toString()) || getOptionValues(BugzillaAttribute.BUG_STATUS) .contains(BUGZILLA_REPORT_STATUS_4_0.CONFIRMED.toString())) ? IBugzillaConstants.BUGZILLA_REPORT_STATUS.NEW.toString() : IBugzillaConstants.BUGZILLA_REPORT_STATUS_4_0.CONFIRMED.toString(); } else { return validTransitions.getStartStatus(); } } public String getDefaultMilestones(String product) { ProductEntry entry = products.get(product); if (entry != null) { return entry.getDefaultMilestone(); } else { return null; } } public void setDefaultMilestone(String product, String defaultMilestone) { ProductEntry entry = products.get(product); if (entry == null) { entry = new ProductEntry(product); products.put(product, entry); } entry.setDefaultMilestone(defaultMilestone); } public Date getLastModifiedHeader() { return lastModifiedHeader; } public void setLastModifiedHeader(Date lastModifiedHeader) { this.lastModifiedHeader = lastModifiedHeader; } public boolean getUnconfirmedAllowed(String product) { ProductEntry entry = products.get(product); if (entry != null) { return BooleanUtils.toBoolean(entry.getUnconfirmedAllowed()); } else { return false; } } }