/******************************************************************************* * Copyright (c) 2004, 2012 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.core; import java.text.ParseException; import java.text.SimpleDateFormat; import java.util.Date; import java.util.LinkedHashMap; import java.util.List; import java.util.Map; import org.eclipse.mylyn.tasks.core.IRepositoryPerson; import org.eclipse.mylyn.tasks.core.TaskRepository; import org.eclipse.mylyn.tasks.core.data.TaskAttachmentMapper; import org.eclipse.mylyn.tasks.core.data.TaskAttribute; import org.eclipse.mylyn.tasks.core.data.TaskAttributeMapper; /** * @author Rob Elves * @author Frank Becker */ public class BugzillaAttributeMapper extends TaskAttributeMapper { private static final String dateFormat_1 = "yyyy-MM-dd HH:mm:ss"; //$NON-NLS-1$ private static final String dateFormat_2 = "yyyy-MM-dd HH:mm"; //$NON-NLS-1$ private static final String dateFormat_3 = "yyyy-MM-dd"; //$NON-NLS-1$ private static final String dateFormat_1_TimeZone = "yyyy-MM-dd HH:mm:ss Z"; //$NON-NLS-1$ private static final String dateFormat_2_TimeZone = "yyyy-MM-dd HH:mm z"; //$NON-NLS-1$ private static final String dateFormat_3_TimeZone = "yyyy-MM-dd z"; //$NON-NLS-1$ // Order is significant private static final String[] dateFormats = { dateFormat_1_TimeZone, dateFormat_1, dateFormat_2_TimeZone, dateFormat_2, dateFormat_3_TimeZone, dateFormat_3 }; private final BugzillaRepositoryConnector connector; public BugzillaAttributeMapper(TaskRepository taskRepository, BugzillaRepositoryConnector connector) { super(taskRepository); this.connector = connector; } @Override public Date getDateValue(TaskAttribute attribute) { if (attribute == null) { return null; } Date parsedDate = parseDate(attribute.getValue()); if (parsedDate != null) { return parsedDate; } return super.getDateValue(attribute); } @Override public boolean getBooleanValue(TaskAttribute attribute) { if (attribute.getValue().equals("1")) { //$NON-NLS-1$ return true; } else { return false; } } @Override public void setBooleanValue(TaskAttribute attribute, Boolean value) { if (value == null) { attribute.setValue("0"); //$NON-NLS-1$ } else if (value) { attribute.setValue("1"); //$NON-NLS-1$ } else { attribute.setValue("0"); //$NON-NLS-1$ } } /** * Note: Date formatter constructed within method for thread safety */ public static final Date parseDate(String dateString) { for (String format : dateFormats) { try { SimpleDateFormat simpleFormatter = new SimpleDateFormat(format); return simpleFormatter.parse(dateString); } catch (ParseException e) { } catch (NumberFormatException e) { } } return null; } @Override public void setDateValue(TaskAttribute attribute, Date date) { if (date != null) { RepositoryConfiguration repositoryConfiguration; BugzillaVersion bugzillaVersion = null; repositoryConfiguration = connector.getRepositoryConfiguration(getTaskRepository().getUrl()); if (repositoryConfiguration != null) { bugzillaVersion = repositoryConfiguration.getInstallVersion(); } else { bugzillaVersion = BugzillaVersion.MIN_VERSION; } SimpleDateFormat comment_creation_ts_Format; SimpleDateFormat attachment_creation_ts_Format; String dateString = null; String attributeId = attribute.getId(); if (attributeId.equals(BugzillaAttribute.DELTA_TS.getKey())) { dateString = new SimpleDateFormat(dateFormat_1).format(date); } else if (attributeId.equals(BugzillaAttribute.CREATION_TS.getKey())) { dateString = new SimpleDateFormat(dateFormat_2).format(date); } else if (attributeId.equals(BugzillaAttribute.BUG_WHEN.getKey())) { if (bugzillaVersion.compareMajorMinorOnly(BugzillaVersion.BUGZILLA_2_22) < 0) { comment_creation_ts_Format = new SimpleDateFormat(dateFormat_2); } else { comment_creation_ts_Format = new SimpleDateFormat(dateFormat_1); } dateString = comment_creation_ts_Format.format(date); } else if (attributeId.equals(BugzillaAttribute.DATE.getKey())) { if (bugzillaVersion.compareMajorMinorOnly(BugzillaVersion.BUGZILLA_2_22) < 0) { attachment_creation_ts_Format = new SimpleDateFormat(dateFormat_2); } else { attachment_creation_ts_Format = new SimpleDateFormat(dateFormat_1); } dateString = attachment_creation_ts_Format.format(date); } else if (attributeId.equals(BugzillaAttribute.DEADLINE.getKey())) { dateString = new SimpleDateFormat(dateFormat_3).format(date); } else if (attributeId.startsWith(BugzillaCustomField.CUSTOM_FIELD_PREFIX)) { dateString = new SimpleDateFormat(dateFormat_1).format(date); } if (dateString == null) { super.setDateValue(attribute, date); } else { attribute.setValue(dateString); } } else { attribute.clearValues(); } } @SuppressWarnings("deprecation") @Override public String mapToRepositoryKey(TaskAttribute parent, String key) { /*if (key.equals(TaskAttribute.NEW_CC)) { return BugzillaReportElement.NEWCC.getKey(); } else*/if (key.equals(TaskAttribute.COMMENT_DATE)) { return BugzillaAttribute.BUG_WHEN.getKey(); } else if (key.equals(TaskAttribute.COMMENT_AUTHOR)) { return BugzillaAttribute.WHO.getKey(); } else if (key.equals(TaskAttribute.COMMENT_AUTHOR_NAME)) { return BugzillaAttribute.WHO_NAME.getKey(); } else if (key.equals(TaskAttribute.USER_CC)) { return BugzillaAttribute.CC.getKey(); } else if (key.equals(TaskAttribute.COMMENT_TEXT)) { return BugzillaAttribute.THETEXT.getKey(); } else if (key.equals(TaskAttribute.COMMENT_ISPRIVATE)) { return BugzillaAttribute.IS_PRIVATE.getKey(); } else if (key.equals(TaskAttribute.DATE_CREATION)) { return BugzillaAttribute.CREATION_TS.getKey(); } else if (key.equals(TaskAttribute.DESCRIPTION)) { return BugzillaAttribute.LONG_DESC.getKey(); } else if (key.equals(TaskAttribute.ATTACHMENT_ID)) { return BugzillaAttribute.ATTACHID.getKey(); } else if (key.equals(TaskAttribute.ATTACHMENT_DESCRIPTION)) { return BugzillaAttribute.DESC.getKey(); } else if (key.equals(TaskAttribute.ATTACHMENT_CONTENT_TYPE)) { return BugzillaAttribute.CTYPE.getKey(); //return BugzillaReportElement.TYPE.getKey();*/ } else if (key.equals(TaskAttribute.USER_ASSIGNED)) { return BugzillaAttribute.ASSIGNED_TO.getKey(); } else if (key.equals(TaskAttribute.USER_ASSIGNED_NAME)) { return BugzillaAttribute.ASSIGNED_TO_NAME.getKey(); } else if (key.equals(TaskAttribute.RESOLUTION)) { return BugzillaAttribute.RESOLUTION.getKey(); } else if (key.equals(TaskAttribute.STATUS)) { return BugzillaAttribute.BUG_STATUS.getKey(); } else if (key.equals(TaskAttribute.DATE_MODIFICATION)) { return BugzillaAttribute.DELTA_TS.getKey(); } else if (key.equals(TaskAttribute.USER_REPORTER)) { return BugzillaAttribute.REPORTER.getKey(); } else if (key.equals(TaskAttribute.USER_REPORTER_NAME)) { return BugzillaAttribute.REPORTER_NAME.getKey(); } else if (key.equals(TaskAttribute.SUMMARY)) { return BugzillaAttribute.SHORT_DESC.getKey(); } else if (key.equals(TaskAttribute.PRODUCT)) { return BugzillaAttribute.PRODUCT.getKey(); } else if (key.equals(TaskAttribute.KEYWORDS)) { return BugzillaAttribute.KEYWORDS.getKey(); } else if (key.equals(TaskAttribute.ATTACHMENT_DATE)) { return BugzillaAttribute.DATE.getKey(); } else if (key.equals(TaskAttribute.ATTACHMENT_SIZE)) { return BugzillaAttribute.SIZE.getKey(); } else if (key.equals(TaskAttribute.ADD_SELF_CC)) { return BugzillaAttribute.ADDSELFCC.getKey(); } else if (key.equals(TaskAttribute.PRIORITY)) { return BugzillaAttribute.PRIORITY.getKey(); } else if (key.equals(TaskAttribute.COMMENT_NEW)) { return BugzillaAttribute.NEW_COMMENT.getKey(); } else if (key.equals(TaskAttribute.COMPONENT)) { return BugzillaAttribute.COMPONENT.getKey(); } else if (key.equals(TaskAttribute.TASK_KEY)) { return BugzillaAttribute.BUG_ID.getKey(); } else if (key.equals(TaskAttribute.DATE_DUE)) { return BugzillaAttribute.DEADLINE.getKey(); } else if (key.equals(TaskAttribute.SEVERITY)) { return BugzillaAttribute.BUG_SEVERITY.getKey(); } else if (key.equals(TaskAttribute.VERSION)) { return BugzillaAttribute.VERSION.getKey(); } return super.mapToRepositoryKey(parent, key); } @Override public TaskAttribute getAssoctiatedAttribute(TaskAttribute taskAttribute) { String id = taskAttribute.getMetaData().getValue(TaskAttribute.META_ASSOCIATED_ATTRIBUTE_ID); if (id != null) { // operation associated input attributes are stored on the root attribute if (TaskAttribute.TYPE_OPERATION.equals(taskAttribute.getMetaData().getType())) { return taskAttribute.getTaskData().getRoot().getMappedAttribute(id); } return taskAttribute.getMappedAttribute(id); } return null; } @Override public IRepositoryPerson getRepositoryPerson(TaskAttribute taskAttribute) { IRepositoryPerson person = super.getRepositoryPerson(taskAttribute); if (person.getName() == null) { if (taskAttribute.getId().equals(BugzillaAttribute.ASSIGNED_TO.getKey())) { TaskAttribute attrAssigned = taskAttribute.getTaskData() .getRoot() .getAttribute(BugzillaAttribute.ASSIGNED_TO_NAME.getKey()); if (attrAssigned != null) { person.setName(attrAssigned.getValue()); } } else if (taskAttribute.getId().equals(BugzillaAttribute.REPORTER.getKey())) { TaskAttribute attrReporter = taskAttribute.getTaskData() .getRoot() .getAttribute(BugzillaAttribute.REPORTER_NAME.getKey()); if (attrReporter != null) { person.setName(attrReporter.getValue()); } } else if (taskAttribute.getId().equals(BugzillaAttribute.QA_CONTACT.getKey())) { TaskAttribute attrReporter = taskAttribute.getTaskData() .getRoot() .getAttribute(BugzillaAttribute.QA_CONTACT_NAME.getKey()); if (attrReporter != null) { person.setName(attrReporter.getValue()); } } } return person; } @Override public Map<String, String> getOptions(TaskAttribute attribute) { RepositoryConfiguration configuration = connector.getRepositoryConfiguration(getTaskRepository().getRepositoryUrl()); if (configuration != null) { TaskAttribute attributeProduct = attribute.getTaskData() .getRoot() .getMappedAttribute(BugzillaAttribute.PRODUCT.getKey()); if (attributeProduct != null && attributeProduct.getValue().length() > 0) { List<String> options = configuration.getAttributeOptions(attributeProduct.getValue(), attribute); if (options.size() == 0 && attribute.getId().equals("resolutionInput")) { //$NON-NLS-1$ options = configuration.getOptionValues(BugzillaAttribute.RESOLUTION); // DUPLICATE and MOVED have special meanings so do not show as resolution // TODO: COPIED FUNCTIONALITY from RepositoryConfiguration.addOperation() refactor. options.remove("DUPLICATE"); //$NON-NLS-1$ options.remove("MOVED"); //$NON-NLS-1$ } Map<String, String> newOptions = new LinkedHashMap<String, String>(); for (String option : options) { newOptions.put(option, option); } if (newOptions != null && !newOptions.isEmpty()) { List<String> values = attribute.getValues(); for (String value : values) { if (!newOptions.containsKey(value)) { // the RepositoryConfiguration is not up to date a new option was add // but Mylyn has not updated the RepositoryConfiguration. So we can have a value // which is not in the Options of the RepositoryConfiguration and need to add // it to the newOptions. // TODO: change this with bug 338347 newOptions.put(value, value); } } } return newOptions; } } return super.getOptions(attribute); } @Override public boolean equals(TaskAttribute newAttribute, TaskAttribute oldAttribute) { if (TaskAttribute.TYPE_COMMENT.equals(newAttribute.getMetaData().getType())) { // the ID mapping for Bugzilla changed in Mylyn 3.7, always consider existing comments equal return true; } String id = oldAttribute.getId(); if (id.startsWith(TaskAttribute.PREFIX_ATTACHMENT)) { TaskAttachmentMapper oldAttachment; oldAttachment = TaskAttachmentMapper.createFrom(oldAttribute); TaskAttachmentMapper newAttachment; newAttachment = TaskAttachmentMapper.createFrom(newAttribute); return newAttachment.equals(oldAttachment); } boolean result = super.equals(newAttribute, oldAttribute); // bug 367861: avoid showing incomings for fields that were previously not part of the schema when empty if (!result // && (BugzillaAttribute.RESOLUTION.getKey().equals(id) || BugzillaAttribute.BUG_FILE_LOC.getKey().equals(id) || BugzillaAttribute.STATUS_WHITEBOARD.getKey().equals(id) // || BugzillaAttribute.KEYWORDS.getKey().equals(id))) { if (oldAttribute.getValue().length() == 0 && newAttribute.getValue().length() == 0 && oldAttribute.getValues().size() <= 1 && newAttribute.getValues().size() <= 1) { return true; } } return result; } @Override public String getLabel(TaskAttribute taskAttribute) { if (taskAttribute.getId().startsWith(BugzillaCustomField.CUSTOM_FIELD_PREFIX)) { return super.getLabel(taskAttribute) + ":"; //$NON-NLS-1$ } else { return super.getLabel(taskAttribute); } } }