/******************************************************************************* * Copyright (c) 2011 GitHub Inc. * 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: * Kevin Sawicki (GitHub Inc.) - initial API and implementation *******************************************************************************/ package org.eclipse.mylyn.internal.github.core.gist; import java.io.IOException; import java.text.DecimalFormat; import java.text.MessageFormat; import java.util.List; import java.util.Map; import java.util.Set; import org.eclipse.core.runtime.CoreException; import org.eclipse.core.runtime.IProgressMonitor; import org.eclipse.egit.github.core.Comment; import org.eclipse.egit.github.core.Gist; import org.eclipse.egit.github.core.GistFile; import org.eclipse.egit.github.core.User; import org.eclipse.egit.github.core.client.GitHubClient; import org.eclipse.egit.github.core.service.GistService; import org.eclipse.mylyn.commons.net.AuthenticationCredentials; import org.eclipse.mylyn.commons.net.AuthenticationType; import org.eclipse.mylyn.internal.github.core.GitHub; import org.eclipse.mylyn.internal.github.core.GitHubTaskDataHandler; import org.eclipse.mylyn.tasks.core.IRepositoryPerson; import org.eclipse.mylyn.tasks.core.ITaskMapping; import org.eclipse.mylyn.tasks.core.RepositoryResponse; import org.eclipse.mylyn.tasks.core.RepositoryResponse.ResponseKind; 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; import org.eclipse.mylyn.tasks.core.data.TaskData; /** * Gist task data handler class. */ public class GistTaskDataHandler extends GitHubTaskDataHandler { /** * SUMMARY_LENGTH */ public static final int SUMMARY_LENGTH = 80; /** * Fill task data with comments * * @param repository * @param data * @param comments * @return specified task data */ public TaskData fillComments(TaskRepository repository, TaskData data, List<Comment> comments) { addComments(data.getRoot(), comments, repository); return data; } /** * Get gist url * * @param repositoryUrl * @param gist * @return url */ public String getGistUrl(String repositoryUrl, Gist gist) { return repositoryUrl + '/' + gist.getId(); } /** * Fill task data with data from gist * * @param repository * @param data * @param gist * @return specified task data */ public TaskData fillTaskData(TaskRepository repository, TaskData data, Gist gist) { boolean isOwner = isOwner(repository, gist.getOwner()); TaskAttributeMapper mapper = data.getAttributeMapper(); TaskAttribute key = GistAttribute.KEY.getMetadata().create(data); mapper.setValue(key, gist.getId()); TaskAttribute description = GistAttribute.DESCRIPTION.getMetadata() .create(data); description.getMetaData().setReadOnly(!isOwner); String gistDescription = gist.getDescription(); if (gistDescription != null) mapper.setValue(description, gistDescription); TaskAttribute created = GistAttribute.CREATED.getMetadata() .create(data); mapper.setDateValue(created, gist.getCreatedAt()); TaskAttribute updated = GistAttribute.UPDATED.getMetadata() .create(data); mapper.setDateValue(updated, gist.getUpdatedAt()); TaskAttribute url = GistAttribute.URL.getMetadata().create(data); url.setValue(gist.getHtmlUrl()); TaskAttribute cloneUrl = GistAttribute.CLONE_URL.getMetadata().create( data); if (isOwner) cloneUrl.setValue(gist.getGitPushUrl()); else cloneUrl.setValue(gist.getGitPullUrl()); IRepositoryPerson reporterPerson = null; User owner = gist.getOwner(); if (owner != null) { TaskAttribute reporter = GistAttribute.AUTHOR.getMetadata().create( data); reporterPerson = createPerson(owner, repository); mapper.setRepositoryPerson(reporter, reporterPerson); TaskAttribute gravatar = GistAttribute.AUTHOR_GRAVATAR .getMetadata().create(data); mapper.setValue(gravatar, owner.getAvatarUrl()); } Map<String, GistFile> files = gist.getFiles(); int fileCount = 0; long sizeCount = 0; if (files != null && !files.isEmpty()) { int count = 1; for (GistFile file : files.values()) { fileCount++; sizeCount += file.getSize(); TaskAttachmentMapper attachmentMapper = new TaskAttachmentMapper(); attachmentMapper.setFileName(file.getFilename()); attachmentMapper.setReplaceExisting(true); attachmentMapper.setLength((long) file.getSize()); attachmentMapper.setPatch(false); attachmentMapper.setAuthor(reporterPerson); attachmentMapper.setAttachmentId(file.getFilename()); TaskAttribute attribute = data.getRoot().createAttribute( TaskAttribute.PREFIX_ATTACHMENT + count); attachmentMapper.applyTo(attribute); GistAttribute.RAW_FILE_URL.getMetadata().create(attribute) .setValue(file.getRawUrl()); count++; } } GistAttribute.COMMENT_NEW.getMetadata().create(data); TaskAttribute summary = GistAttribute.SUMMARY.getMetadata() .create(data); mapper.setValue(summary, generateSummary(fileCount, sizeCount, gist.getDescription())); return data; } private String generateSummary(int files, long size, String description) { StringBuilder summaryText = new StringBuilder(); if (description != null && description.length() > 0) { description = description.trim(); int firstLine = description.indexOf('\n'); if (firstLine != -1) description = description.substring(0, firstLine).trim(); if (description.length() > SUMMARY_LENGTH) { // Break on last whitespace if maximum length is in the middle // of a word if (!Character.isWhitespace(description.charAt(SUMMARY_LENGTH)) && !Character.isWhitespace(description .charAt(SUMMARY_LENGTH - 1))) { int lastWhitespace = description.lastIndexOf(' '); if (lastWhitespace > 0) description = description.substring(0, lastWhitespace); else description = description.substring(0, SUMMARY_LENGTH); } else description = description.substring(0, SUMMARY_LENGTH); description = description.trim(); } if (description.length() > 0) summaryText.append(description).append(' '); } if (files != 1) summaryText.append(MessageFormat.format( Messages.GistTaskDataHandler_FilesMultiple, files)); else summaryText.append(Messages.GistTaskDataHandler_FilesSingle); summaryText.append(',').append(' ').append(formatSize(size)); return summaryText.toString(); } private String formatSize(long size) { if (size == 1) return Messages.GistTaskDataHandler_SizeByte; else if (size < 1024) return new DecimalFormat(Messages.GistTaskDataHandler_SizeBytes) .format(size); else if (size >= 1024 && size <= 1048575) return new DecimalFormat(Messages.GistTaskDataHandler_SizeKilobytes) .format(size / 1024.0); else if (size >= 1048576 && size <= 1073741823) return new DecimalFormat(Messages.GistTaskDataHandler_SizeMegabytes) .format(size / 1048576.0); else return new DecimalFormat(Messages.GistTaskDataHandler_SizeGigabytes) .format(size / 1073741824.0); } /** * @see org.eclipse.mylyn.tasks.core.data.AbstractTaskDataHandler#postTaskData(org.eclipse.mylyn.tasks.core.TaskRepository, * org.eclipse.mylyn.tasks.core.data.TaskData, java.util.Set, * org.eclipse.core.runtime.IProgressMonitor) */ public RepositoryResponse postTaskData(TaskRepository repository, TaskData taskData, Set<TaskAttribute> oldAttributes, IProgressMonitor monitor) throws CoreException { RepositoryResponse response = null; Gist gist = new Gist(); GitHubClient client = GistConnector.createClient(repository); AuthenticationCredentials credentials = repository .getCredentials(AuthenticationType.REPOSITORY); if (credentials != null) { client.setCredentials(credentials.getUserName(), credentials.getPassword()); gist.setUser(new User().setLogin(credentials.getUserName())); } GistService service = new GistService(client); TaskAttribute root = taskData.getRoot(); gist.setId(taskData.getTaskId()); gist.setDescription(root.getAttribute( GistAttribute.DESCRIPTION.getMetadata().getId()).getValue()); if (taskData.isNew()) { try { gist = service.createGist(gist); } catch (IOException e) { throw new CoreException(GitHub.createWrappedStatus(e)); } response = new RepositoryResponse(ResponseKind.TASK_CREATED, gist.getId()); } else { try { String newComment = root.getAttribute( GistAttribute.COMMENT_NEW.getMetadata().getId()) .getValue(); if (newComment.length() > 0) service.createComment(taskData.getTaskId(), newComment); String author = GistAttribute.AUTHOR.getMetadata().getValue( taskData); if (isOwner(repository, author)) service.updateGist(gist); } catch (IOException e) { throw new CoreException(GitHub.createWrappedStatus(e)); } response = new RepositoryResponse(ResponseKind.TASK_UPDATED, taskData.getTaskId()); } return response; } /** * @see org.eclipse.mylyn.tasks.core.data.AbstractTaskDataHandler#initializeTaskData(org.eclipse.mylyn.tasks.core.TaskRepository, * org.eclipse.mylyn.tasks.core.data.TaskData, * org.eclipse.mylyn.tasks.core.ITaskMapping, * org.eclipse.core.runtime.IProgressMonitor) */ public boolean initializeTaskData(TaskRepository repository, TaskData data, ITaskMapping initializationData, IProgressMonitor monitor) throws CoreException { TaskAttributeMapper mapper = data.getAttributeMapper(); TaskAttribute summary = GistAttribute.SUMMARY.getMetadata() .create(data); mapper.setValue(summary, Messages.GistTaskDataHandler_SummaryNewGist); GistAttribute.DESCRIPTION.getMetadata().create(data); return true; } /** * Is the given Gist author the same user as configured via the task * repository's credentials? * * @param repository * @param author * @return true if owner, false otherwise */ protected boolean isOwner(TaskRepository repository, User author) { if (author == null) return false; return isOwner(repository, author.getLogin()); } /** * Is the given Gist author the same user as configured via the task * repository's credentials? * * @param repository * @param author * @return true if owner, false otherwise */ protected boolean isOwner(TaskRepository repository, String author) { AuthenticationCredentials creds = repository .getCredentials(AuthenticationType.REPOSITORY); if (creds == null) return false; return author != null && author.length() > 0 && author.equals(creds.getUserName()); } }