/******************************************************************************* * 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.tasks.core.data; import java.util.Date; import java.util.List; import org.eclipse.core.runtime.Assert; import org.eclipse.jdt.annotation.NonNull; import org.eclipse.jdt.annotation.Nullable; import org.eclipse.mylyn.internal.tasks.core.ITasksCoreConstants; import org.eclipse.mylyn.tasks.core.ITask; import org.eclipse.mylyn.tasks.core.ITask.PriorityLevel; import org.eclipse.mylyn.tasks.core.ITaskMapping; import org.eclipse.mylyn.tasks.core.data.AbstractTaskSchema.Field; /** * @author Steffen Pingel * @since 3.0 */ public class TaskMapper implements ITaskMapping { private final boolean createNonExistingAttributes; private final TaskData taskData; public TaskMapper(@NonNull TaskData taskData) { this(taskData, false); } public TaskMapper(@NonNull TaskData taskData, boolean createNonExistingAttributes) { this.createNonExistingAttributes = createNonExistingAttributes; Assert.isNotNull(taskData); this.taskData = taskData; } public boolean applyTo(@NonNull ITask task) { boolean changed = false; if (hasChanges(task.getCompletionDate(), getCompletionDate(), TaskAttribute.DATE_COMPLETION)) { task.setCompletionDate(getCompletionDate()); changed = true; } if (hasChanges(task.getCreationDate(), getCreationDate(), TaskAttribute.DATE_CREATION)) { task.setCreationDate(getCreationDate()); changed = true; } if (hasChanges(task.getModificationDate(), getModificationDate(), TaskAttribute.DATE_MODIFICATION)) { task.setModificationDate(getModificationDate()); changed = true; } if (hasChanges(task.getDueDate(), getDueDate(), TaskAttribute.DATE_DUE)) { task.setDueDate(getDueDate()); changed = true; } if (hasChanges(task.getOwner(), getOwner(), TaskAttribute.USER_ASSIGNED)) { task.setOwner(getOwner()); changed = true; } if (hasChanges(task.getOwnerId(), getOwnerId(), TaskAttribute.USER_ASSIGNED)) { task.setOwnerId(getOwnerId()); changed = true; } if (hasChanges(task.getPriority(), getPriorityLevelString(), TaskAttribute.PRIORITY)) { task.setPriority(getPriorityLevelString()); changed = true; } String priorityLabel = getPriority(); if (hasChanges(task.getAttribute(ITasksCoreConstants.ATTRIBUTE_PRIORITY_LABEL), priorityLabel, TaskAttribute.PRIORITY)) { task.setAttribute(ITasksCoreConstants.ATTRIBUTE_PRIORITY_LABEL, priorityLabel); changed = true; } if (hasChanges(task.getSummary(), getSummary(), TaskAttribute.SUMMARY)) { task.setSummary(getSummary()); changed = true; } if (hasChanges(task.getTaskKey(), getTaskKey(), TaskAttribute.TASK_KEY)) { task.setTaskKey(getTaskKey()); changed = true; } if (hasChanges(task.getTaskKind(), getTaskKind(), TaskAttribute.TASK_KIND)) { task.setTaskKind(getTaskKind()); changed = true; } if (hasChanges(task.getUrl(), getTaskUrl(), TaskAttribute.TASK_URL)) { task.setUrl(getTaskUrl()); changed = true; } return changed; } @Nullable private String getPriorityLevelString() { PriorityLevel priorityLevel = getPriorityLevel(); return (priorityLevel != null) ? priorityLevel.toString() : PriorityLevel.getDefault().toString(); } private boolean hasChanges(@Nullable Object existingValue, @Nullable Object newValue, @NonNull String attributeId) { TaskAttribute attribute = taskData.getRoot().getMappedAttribute(attributeId); if (attribute != null) { return areNotEquals(existingValue, newValue); } return false; } private boolean areNotEquals(@Nullable Object existingProperty, @Nullable Object newProperty) { return (existingProperty != null) ? !existingProperty.equals(newProperty) : newProperty != null; } private void copyAttributeValue(@NonNull TaskAttribute sourceAttribute, @Nullable TaskAttribute targetAttribute) { if (targetAttribute == null) { return; } if (!targetAttribute.getMetaData().isReadOnly()) { targetAttribute.clearValues(); if (targetAttribute.getOptions().size() > 0) { List<String> values = sourceAttribute.getValues(); for (String value : values) { if (targetAttribute.getOptions().containsKey(value)) { targetAttribute.addValue(value); } } } else { List<String> values = sourceAttribute.getValues(); for (String value : values) { targetAttribute.addValue(value); } } } } /** * TODO update comment Sets attribute values from <code>sourceTaskData</code> on <code>targetTaskData</code>. Sets * the following attributes: * <ul> * <li>summary * <li>description * </ul> * Other attribute values are only set if they exist on <code>sourceTaskData</code> and <code>targetTaskData</code>. * * @param sourceTaskData * the source task data values are copied from, the connector kind of repository of * <code>sourceTaskData</code> can be different from <code>targetTaskData</code> * @param targetTaskData * the target task data values are copied to, the connector kind matches the one of this task data * handler * @since 2.2 */ public void merge(@NonNull ITaskMapping source) { if (source.getTaskData() != null && this.getTaskData() != null && source.getTaskData().getConnectorKind().equals(this.getTaskData().getConnectorKind())) { // task data objects are from the same connector, copy all attributes for (TaskAttribute sourceAttribute : source.getTaskData().getRoot().getAttributes().values()) { copyAttributeValue(sourceAttribute, this.getTaskData().getRoot().getAttribute(sourceAttribute.getId())); } } else { if (source.getCc() != null) { setCc(source.getCc()); } if (source.getDescription() != null) { setDescription(source.getDescription()); } if (source.getComponent() != null) { setComponent(source.getComponent()); } if (source.getKeywords() != null) { setKeywords(source.getKeywords()); } if (source.getOwner() != null) { setOwner(source.getOwner()); } if (source.getPriorityLevel() != null) { setPriorityLevel(source.getPriorityLevel()); } if (source.getProduct() != null) { setProduct(source.getProduct()); } if (source.getSeverity() != null) { setSeverity(source.getSeverity()); } if (source.getSummary() != null) { setSummary(source.getSummary()); } if (source.getVersion() != null) { setVersion(source.getVersion()); } } } @NonNull private TaskAttribute createAttribute(@NonNull String attributeKey, @Nullable String type) { TaskAttribute attribute; Field field = DefaultTaskSchema.getField(attributeKey); if (field != null) { attribute = field.createAttribute(taskData.getRoot()); } else { attribute = taskData.getRoot().createMappedAttribute(attributeKey); attribute.getMetaData().defaults().setType(type); } return attribute; } @Nullable public List<String> getCc() { return getValues(TaskAttribute.USER_CC); } @Nullable public Date getCompletionDate() { return getDateValue(TaskAttribute.DATE_COMPLETION); } @Nullable public String getComponent() { return getValue(TaskAttribute.COMPONENT); } @Nullable public Date getCreationDate() { return getDateValue(TaskAttribute.DATE_CREATION); } @Nullable private Date getDateValue(@NonNull String attributeKey) { TaskAttribute attribute = taskData.getRoot().getMappedAttribute(attributeKey); if (attribute != null) { return taskData.getAttributeMapper().getDateValue(attribute); } return null; } @Nullable public String getDescription() { return getValue(TaskAttribute.DESCRIPTION); } @Nullable public Date getDueDate() { return getDateValue(TaskAttribute.DATE_DUE); } @Nullable public List<String> getKeywords() { return getValues(TaskAttribute.KEYWORDS); } @Nullable private TaskAttribute getWriteableAttribute(@NonNull String attributeKey, String type) { TaskAttribute attribute = taskData.getRoot().getMappedAttribute(attributeKey); if (createNonExistingAttributes) { if (attribute == null) { attribute = createAttribute(attributeKey, type); } } else if (attribute != null && attribute.getMetaData().isReadOnly()) { return null; } return attribute; } @Nullable public Date getModificationDate() { return getDateValue(TaskAttribute.DATE_MODIFICATION); } @Nullable public String getOwner() { return getValue(TaskAttribute.USER_ASSIGNED); } /** * @since 3.15 */ @Nullable public String getOwnerId() { return getValueId(TaskAttribute.USER_ASSIGNED); } @Nullable public String getPriority() { return getValue(TaskAttribute.PRIORITY); } /** * Connectors should override {@link TaskAttributeMapper#getPriorityLevel(TaskAttribute, String)} to customize how * priority options are mapped to {@link PriorityLevel} */ @Nullable public PriorityLevel getPriorityLevel() { String valueLabel = getPriority(); if (valueLabel != null && PriorityLevel.isValidPriority(valueLabel)) { return PriorityLevel.fromString(valueLabel); } TaskAttribute attribute = taskData.getRoot().getMappedAttribute(TaskAttribute.PRIORITY); if (attribute != null) { return getTaskData().getAttributeMapper().getPriorityLevel(attribute, attribute.getValue()); } return null; } @Nullable public String getProduct() { return getValue(TaskAttribute.PRODUCT); } @Nullable public String getReporter() { return getValue(TaskAttribute.USER_REPORTER); } @Nullable public String getResolution() { return getValue(TaskAttribute.RESOLUTION); } /** * @since 3.2 */ @Nullable public String getSeverity() { return getValue(TaskAttribute.SEVERITY); } @Nullable public String getSummary() { return getValue(TaskAttribute.SUMMARY); } @Nullable public String getStatus() { return getValue(TaskAttribute.STATUS); } @NonNull public TaskData getTaskData() { return taskData; } @Nullable public String getTaskKey() { return getValue(TaskAttribute.TASK_KEY); } @Nullable public String getTaskKind() { return getValue(TaskAttribute.TASK_KIND); } @Nullable public String getTaskStatus() { return getValue(TaskAttribute.STATUS); } @Nullable public String getTaskUrl() { return getValue(TaskAttribute.TASK_URL); } /** * Returns the label of the attribute value. */ @Nullable public String getValue(@NonNull String attributeKey) { TaskAttribute attribute = taskData.getRoot().getMappedAttribute(attributeKey); if (attribute != null) { return taskData.getAttributeMapper().getValueLabel(attribute); } return null; } /** * Returns the id of the attribute value. */ @Nullable private String getValueId(@NonNull String attributeKey) { TaskAttribute attribute = taskData.getRoot().getMappedAttribute(attributeKey); if (attribute != null) { return taskData.getAttributeMapper().getValue(attribute); } return null; } @Nullable private List<String> getValues(@NonNull String attributeKey) { TaskAttribute attribute = taskData.getRoot().getMappedAttribute(attributeKey); if (attribute != null) { return taskData.getAttributeMapper().getValueLabels(attribute); } return null; } /** * @since 3.2 */ @Nullable public String getVersion() { return getValue(TaskAttribute.VERSION); } public boolean hasChanges(@NonNull ITask task) { boolean changed = false; changed |= hasChanges(task.getCompletionDate(), getCompletionDate(), TaskAttribute.DATE_COMPLETION); changed |= hasChanges(task.getCreationDate(), getCreationDate(), TaskAttribute.DATE_CREATION); changed |= hasChanges(task.getModificationDate(), getModificationDate(), TaskAttribute.DATE_MODIFICATION); changed |= hasChanges(task.getDueDate(), getDueDate(), TaskAttribute.DATE_DUE); changed |= hasChanges(task.getOwner(), getOwner(), TaskAttribute.USER_ASSIGNED); changed |= hasChanges(task.getOwnerId(), getOwnerId(), TaskAttribute.USER_ASSIGNED); changed |= hasChanges(task.getPriority(), getPriorityLevelString(), TaskAttribute.PRIORITY); changed |= hasChanges(task.getSummary(), getSummary(), TaskAttribute.SUMMARY); changed |= hasChanges(task.getTaskKey(), getTaskKey(), TaskAttribute.TASK_KEY); changed |= hasChanges(task.getTaskKind(), getTaskKind(), TaskAttribute.TASK_KIND); changed |= hasChanges(task.getUrl(), getTaskUrl(), TaskAttribute.TASK_URL); changed |= hasChanges(task.getAttribute(ITasksCoreConstants.ATTRIBUTE_PRIORITY_LABEL), getPriority(), TaskAttribute.PRIORITY); return changed; } // private boolean hasChanges(Object value, String attributeKey) { // TaskAttribute attribute = taskData.getRoot().getMappedAttribute(attributeKey); // if (attribute != null) { // if (TaskAttribute.TYPE_BOOLEAN.equals(attribute.getMetaData().getType())) { // return areNotEquals(value, taskData.getAttributeMapper().getBooleanValue(attribute)); // } else if (TaskAttribute.TYPE_DATE.equals(attribute.getMetaData().getType())) { // return areNotEquals(value, taskData.getAttributeMapper().getDateValue(attribute)); // } else if (TaskAttribute.TYPE_INTEGER.equals(attribute.getMetaData().getType())) { // return areNotEquals(value, taskData.getAttributeMapper().getIntegerValue(attribute)); // } else { // return areNotEquals(value, taskData.getAttributeMapper().getValue(attribute)); // } // } // return false; // } public void setCc(@NonNull List<String> cc) { setValues(TaskAttribute.USER_CC, cc); } public void setCompletionDate(@Nullable Date dateCompleted) { setDateValue(TaskAttribute.DATE_COMPLETION, dateCompleted); } public void setComponent(@NonNull String component) { setValue(TaskAttribute.COMPONENT, component); } public void setCreationDate(@Nullable Date dateCreated) { setDateValue(TaskAttribute.DATE_CREATION, dateCreated); } @Nullable private TaskAttribute setDateValue(@NonNull String attributeKey, @Nullable Date value) { TaskAttribute attribute = getWriteableAttribute(attributeKey, TaskAttribute.TYPE_DATE); if (attribute != null) { taskData.getAttributeMapper().setDateValue(attribute, value); } return attribute; } public void setDescription(@NonNull String description) { setValue(TaskAttribute.DESCRIPTION, description); } public void setDueDate(Date value) { setDateValue(TaskAttribute.DATE_DUE, value); } public void setKeywords(@NonNull List<String> keywords) { setValues(TaskAttribute.KEYWORDS, keywords); } public void setModificationDate(@Nullable Date dateModified) { setDateValue(TaskAttribute.DATE_MODIFICATION, dateModified); } // TODO use Person class? public void setOwner(@NonNull String owner) { setValue(TaskAttribute.USER_ASSIGNED, owner); } public void setPriority(@NonNull String priority) { setValue(TaskAttribute.PRIORITY, priority); } public void setPriorityLevel(@NonNull PriorityLevel priority) { setPriority(priority.toString()); } public void setProduct(@NonNull String product) { setValue(TaskAttribute.PRODUCT, product); } // TODO use Person class? public void setReporter(@NonNull String reporter) { setValue(TaskAttribute.USER_REPORTER, reporter); } /** * @since 3.2 */ public void setSeverity(@NonNull String severity) { setValue(TaskAttribute.SEVERITY, severity); } public void setSummary(@NonNull String summary) { setValue(TaskAttribute.SUMMARY, summary); } public void setStatus(@NonNull String status) { setValue(TaskAttribute.STATUS, status); } public void setTaskKind(@NonNull String taskKind) { setValue(TaskAttribute.TASK_KIND, taskKind); } /** * @since 3.3 */ public void setTaskKey(@NonNull String taskKey) { setValue(TaskAttribute.TASK_KEY, taskKey); } public void setTaskUrl(@NonNull String taskUrl) { setValue(TaskAttribute.TASK_URL, taskUrl); } /** * @since 3.2 */ public void setVersion(@NonNull String version) { setValue(TaskAttribute.VERSION, version); } @Nullable public TaskAttribute setValue(@NonNull String attributeKey, @NonNull String value) { TaskAttribute attribute = getWriteableAttribute(attributeKey, TaskAttribute.TYPE_SHORT_TEXT); if (attribute != null) { taskData.getAttributeMapper().setValue(attribute, value); } return attribute; } @Nullable private TaskAttribute setValues(@NonNull String attributeKey, @NonNull List<String> values) { TaskAttribute attribute = getWriteableAttribute(attributeKey, TaskAttribute.TYPE_SHORT_TEXT); if (attribute != null) { taskData.getAttributeMapper().setValues(attribute, values); } return attribute; } }