From b53db5e05c25c8c771d7b60a1f93b2a76e425a94 Mon Sep 17 00:00:00 2001 From: Frank Becker Date: Wed, 7 Jun 2023 19:12:31 +0200 Subject: [PATCH 01/13] Preview: retrive and show Gitlab Issues --- .../org.eclipse.mylyn.gitlab.core/.classpath | 11 + .../org.eclipse.mylyn.gitlab.core/.project | 28 + .../org.eclipse.core.resources.prefs | 2 + .../.settings/org.eclipse.jdt.core.prefs | 9 + .../META-INF/MANIFEST.MF | 23 + .../build.properties | 4 + .../org.eclipse.mylyn.gitlab.core/plugin.xml | 26 + .../eclipse/mylyn/gitlab/core/Duration.java | 23 + .../gitlab/core/GitlabConfiguration.java | 133 ++++ .../gitlab/core/GitlabCoreActivator.java | 61 ++ .../mylyn/gitlab/core/GitlabException.java | 35 + .../gitlab/core/GitlabJSonArrayOperation.java | 54 ++ .../mylyn/gitlab/core/GitlabOperation.java | 129 ++++ .../core/GitlabRepositoryConnector.java | 498 ++++++++++++ .../mylyn/gitlab/core/GitlabRestClient.java | 714 ++++++++++++++++++ .../core/GitlabTaskAttributeMapper.java | 80 ++ .../gitlab/core/GitlabTaskDataHandler.java | 95 +++ .../mylyn/gitlab/core/GitlabTaskSchema.java | 140 ++++ .../org.eclipse.mylyn.gitlab.feature/.project | 17 + .../org.eclipse.core.resources.prefs | 2 + .../build.properties | 1 + .../feature.xml | 35 + .../org.eclipse.mylyn.gitlab.ui/.classpath | 7 + .../org.eclipse.mylyn.gitlab.ui/.project | 28 + .../org.eclipse.core.resources.prefs | 2 + .../.settings/org.eclipse.jdt.core.prefs | 9 + .../META-INF/MANIFEST.MF | 21 + .../build.properties | 5 + .../icons/eview16/gitlab-icon.gif | Bin 0 -> 1431 bytes .../icons/eview16/gitlab-overlay.gif | Bin 0 -> 276 bytes .../org.eclipse.mylyn.gitlab.ui/plugin.xml | 34 + .../mylyn/gitlab/ui/GitlabConnectorUI.java | 81 ++ .../gitlab/ui/GitlabQuerySchemaPage.java | 65 ++ .../gitlab/ui/GitlabQueryTypeWizardPage.java | 72 ++ .../ui/GitlabRepositorySettingsPage.java | 261 +++++++ .../ui/GitlabSearchQueryPageSchema.java | 29 + .../mylyn/gitlab/ui/GitlabTaskEditorPage.java | 48 ++ .../ui/GitlabTaskEditorPageFactory.java | 55 ++ .../mylyn/gitlab/ui/GitlabUiActivator.java | 61 ++ 39 files changed, 2898 insertions(+) create mode 100644 mylyn.tasks/connectors/gitlab/org.eclipse.mylyn.gitlab.core/.classpath create mode 100644 mylyn.tasks/connectors/gitlab/org.eclipse.mylyn.gitlab.core/.project create mode 100644 mylyn.tasks/connectors/gitlab/org.eclipse.mylyn.gitlab.core/.settings/org.eclipse.core.resources.prefs create mode 100644 mylyn.tasks/connectors/gitlab/org.eclipse.mylyn.gitlab.core/.settings/org.eclipse.jdt.core.prefs create mode 100644 mylyn.tasks/connectors/gitlab/org.eclipse.mylyn.gitlab.core/META-INF/MANIFEST.MF create mode 100644 mylyn.tasks/connectors/gitlab/org.eclipse.mylyn.gitlab.core/build.properties create mode 100644 mylyn.tasks/connectors/gitlab/org.eclipse.mylyn.gitlab.core/plugin.xml create mode 100644 mylyn.tasks/connectors/gitlab/org.eclipse.mylyn.gitlab.core/src/org/eclipse/mylyn/gitlab/core/Duration.java create mode 100644 mylyn.tasks/connectors/gitlab/org.eclipse.mylyn.gitlab.core/src/org/eclipse/mylyn/gitlab/core/GitlabConfiguration.java create mode 100644 mylyn.tasks/connectors/gitlab/org.eclipse.mylyn.gitlab.core/src/org/eclipse/mylyn/gitlab/core/GitlabCoreActivator.java create mode 100644 mylyn.tasks/connectors/gitlab/org.eclipse.mylyn.gitlab.core/src/org/eclipse/mylyn/gitlab/core/GitlabException.java create mode 100644 mylyn.tasks/connectors/gitlab/org.eclipse.mylyn.gitlab.core/src/org/eclipse/mylyn/gitlab/core/GitlabJSonArrayOperation.java create mode 100644 mylyn.tasks/connectors/gitlab/org.eclipse.mylyn.gitlab.core/src/org/eclipse/mylyn/gitlab/core/GitlabOperation.java create mode 100644 mylyn.tasks/connectors/gitlab/org.eclipse.mylyn.gitlab.core/src/org/eclipse/mylyn/gitlab/core/GitlabRepositoryConnector.java create mode 100644 mylyn.tasks/connectors/gitlab/org.eclipse.mylyn.gitlab.core/src/org/eclipse/mylyn/gitlab/core/GitlabRestClient.java create mode 100644 mylyn.tasks/connectors/gitlab/org.eclipse.mylyn.gitlab.core/src/org/eclipse/mylyn/gitlab/core/GitlabTaskAttributeMapper.java create mode 100644 mylyn.tasks/connectors/gitlab/org.eclipse.mylyn.gitlab.core/src/org/eclipse/mylyn/gitlab/core/GitlabTaskDataHandler.java create mode 100644 mylyn.tasks/connectors/gitlab/org.eclipse.mylyn.gitlab.core/src/org/eclipse/mylyn/gitlab/core/GitlabTaskSchema.java create mode 100644 mylyn.tasks/connectors/gitlab/org.eclipse.mylyn.gitlab.feature/.project create mode 100644 mylyn.tasks/connectors/gitlab/org.eclipse.mylyn.gitlab.feature/.settings/org.eclipse.core.resources.prefs create mode 100644 mylyn.tasks/connectors/gitlab/org.eclipse.mylyn.gitlab.feature/build.properties create mode 100644 mylyn.tasks/connectors/gitlab/org.eclipse.mylyn.gitlab.feature/feature.xml create mode 100644 mylyn.tasks/connectors/gitlab/org.eclipse.mylyn.gitlab.ui/.classpath create mode 100644 mylyn.tasks/connectors/gitlab/org.eclipse.mylyn.gitlab.ui/.project create mode 100644 mylyn.tasks/connectors/gitlab/org.eclipse.mylyn.gitlab.ui/.settings/org.eclipse.core.resources.prefs create mode 100644 mylyn.tasks/connectors/gitlab/org.eclipse.mylyn.gitlab.ui/.settings/org.eclipse.jdt.core.prefs create mode 100644 mylyn.tasks/connectors/gitlab/org.eclipse.mylyn.gitlab.ui/META-INF/MANIFEST.MF create mode 100644 mylyn.tasks/connectors/gitlab/org.eclipse.mylyn.gitlab.ui/build.properties create mode 100644 mylyn.tasks/connectors/gitlab/org.eclipse.mylyn.gitlab.ui/icons/eview16/gitlab-icon.gif create mode 100644 mylyn.tasks/connectors/gitlab/org.eclipse.mylyn.gitlab.ui/icons/eview16/gitlab-overlay.gif create mode 100644 mylyn.tasks/connectors/gitlab/org.eclipse.mylyn.gitlab.ui/plugin.xml create mode 100644 mylyn.tasks/connectors/gitlab/org.eclipse.mylyn.gitlab.ui/src/org/eclipse/mylyn/gitlab/ui/GitlabConnectorUI.java create mode 100644 mylyn.tasks/connectors/gitlab/org.eclipse.mylyn.gitlab.ui/src/org/eclipse/mylyn/gitlab/ui/GitlabQuerySchemaPage.java create mode 100644 mylyn.tasks/connectors/gitlab/org.eclipse.mylyn.gitlab.ui/src/org/eclipse/mylyn/gitlab/ui/GitlabQueryTypeWizardPage.java create mode 100644 mylyn.tasks/connectors/gitlab/org.eclipse.mylyn.gitlab.ui/src/org/eclipse/mylyn/gitlab/ui/GitlabRepositorySettingsPage.java create mode 100644 mylyn.tasks/connectors/gitlab/org.eclipse.mylyn.gitlab.ui/src/org/eclipse/mylyn/gitlab/ui/GitlabSearchQueryPageSchema.java create mode 100644 mylyn.tasks/connectors/gitlab/org.eclipse.mylyn.gitlab.ui/src/org/eclipse/mylyn/gitlab/ui/GitlabTaskEditorPage.java create mode 100644 mylyn.tasks/connectors/gitlab/org.eclipse.mylyn.gitlab.ui/src/org/eclipse/mylyn/gitlab/ui/GitlabTaskEditorPageFactory.java create mode 100644 mylyn.tasks/connectors/gitlab/org.eclipse.mylyn.gitlab.ui/src/org/eclipse/mylyn/gitlab/ui/GitlabUiActivator.java diff --git a/mylyn.tasks/connectors/gitlab/org.eclipse.mylyn.gitlab.core/.classpath b/mylyn.tasks/connectors/gitlab/org.eclipse.mylyn.gitlab.core/.classpath new file mode 100644 index 0000000000..3628e33687 --- /dev/null +++ b/mylyn.tasks/connectors/gitlab/org.eclipse.mylyn.gitlab.core/.classpath @@ -0,0 +1,11 @@ + + + + + + + + + + + diff --git a/mylyn.tasks/connectors/gitlab/org.eclipse.mylyn.gitlab.core/.project b/mylyn.tasks/connectors/gitlab/org.eclipse.mylyn.gitlab.core/.project new file mode 100644 index 0000000000..8ff9b2d441 --- /dev/null +++ b/mylyn.tasks/connectors/gitlab/org.eclipse.mylyn.gitlab.core/.project @@ -0,0 +1,28 @@ + + + org.eclipse.mylyn.gitlab.core + + + + + + org.eclipse.jdt.core.javabuilder + + + + + org.eclipse.pde.ManifestBuilder + + + + + org.eclipse.pde.SchemaBuilder + + + + + + org.eclipse.pde.PluginNature + org.eclipse.jdt.core.javanature + + diff --git a/mylyn.tasks/connectors/gitlab/org.eclipse.mylyn.gitlab.core/.settings/org.eclipse.core.resources.prefs b/mylyn.tasks/connectors/gitlab/org.eclipse.mylyn.gitlab.core/.settings/org.eclipse.core.resources.prefs new file mode 100644 index 0000000000..99f26c0203 --- /dev/null +++ b/mylyn.tasks/connectors/gitlab/org.eclipse.mylyn.gitlab.core/.settings/org.eclipse.core.resources.prefs @@ -0,0 +1,2 @@ +eclipse.preferences.version=1 +encoding/=UTF-8 diff --git a/mylyn.tasks/connectors/gitlab/org.eclipse.mylyn.gitlab.core/.settings/org.eclipse.jdt.core.prefs b/mylyn.tasks/connectors/gitlab/org.eclipse.mylyn.gitlab.core/.settings/org.eclipse.jdt.core.prefs new file mode 100644 index 0000000000..62ef3488cc --- /dev/null +++ b/mylyn.tasks/connectors/gitlab/org.eclipse.mylyn.gitlab.core/.settings/org.eclipse.jdt.core.prefs @@ -0,0 +1,9 @@ +eclipse.preferences.version=1 +org.eclipse.jdt.core.compiler.codegen.targetPlatform=17 +org.eclipse.jdt.core.compiler.compliance=17 +org.eclipse.jdt.core.compiler.problem.assertIdentifier=error +org.eclipse.jdt.core.compiler.problem.enablePreviewFeatures=disabled +org.eclipse.jdt.core.compiler.problem.enumIdentifier=error +org.eclipse.jdt.core.compiler.problem.reportPreviewFeatures=warning +org.eclipse.jdt.core.compiler.release=enabled +org.eclipse.jdt.core.compiler.source=17 diff --git a/mylyn.tasks/connectors/gitlab/org.eclipse.mylyn.gitlab.core/META-INF/MANIFEST.MF b/mylyn.tasks/connectors/gitlab/org.eclipse.mylyn.gitlab.core/META-INF/MANIFEST.MF new file mode 100644 index 0000000000..583400020b --- /dev/null +++ b/mylyn.tasks/connectors/gitlab/org.eclipse.mylyn.gitlab.core/META-INF/MANIFEST.MF @@ -0,0 +1,23 @@ +Manifest-Version: 1.0 +Bundle-ManifestVersion: 2 +Bundle-Name: Gitlab Connector Core +Bundle-SymbolicName: org.eclipse.mylyn.gitlab.core;singleton:=true +Bundle-Version: 3.26.1.qualifier +Export-Package: org.eclipse.mylyn.gitlab.core +Bundle-Activator: org.eclipse.mylyn.gitlab.core.GitlabCoreActivator +Require-Bundle: org.eclipse.ui, + org.eclipse.core.runtime, + org.eclipse.mylyn.tasks.core;bundle-version="3.26.0", + org.eclipse.mylyn.commons.repositories.http.core;bundle-version="3.26.0", + org.apache.httpcomponents.httpclient;bundle-version="4.5.13", + org.eclipse.mylyn.commons.core;bundle-version="3.26.0", + org.apache.httpcomponents.httpcore;bundle-version="4.4.15", + org.eclipse.mylyn.commons.repositories.core;bundle-version="3.26.0", + com.google.gson;bundle-version="2.9.1", + com.google.guava;bundle-version="21.0.0", + org.eclipse.mylyn.commons.net;bundle-version="3.26.0", + org.eclipse.equinox.security;bundle-version="1.3.1000", + org.eclipse.jdt.annotation +Bundle-RequiredExecutionEnvironment: JavaSE-17 +Automatic-Module-Name: org.eclipse.mylyn.gitlab.core +Bundle-ActivationPolicy: lazy diff --git a/mylyn.tasks/connectors/gitlab/org.eclipse.mylyn.gitlab.core/build.properties b/mylyn.tasks/connectors/gitlab/org.eclipse.mylyn.gitlab.core/build.properties new file mode 100644 index 0000000000..5b359b5b78 --- /dev/null +++ b/mylyn.tasks/connectors/gitlab/org.eclipse.mylyn.gitlab.core/build.properties @@ -0,0 +1,4 @@ +source.. = src/ +output.. = bin/ +bin.includes = META-INF/,\ + . \ No newline at end of file diff --git a/mylyn.tasks/connectors/gitlab/org.eclipse.mylyn.gitlab.core/plugin.xml b/mylyn.tasks/connectors/gitlab/org.eclipse.mylyn.gitlab.core/plugin.xml new file mode 100644 index 0000000000..f4b994f1da --- /dev/null +++ b/mylyn.tasks/connectors/gitlab/org.eclipse.mylyn.gitlab.core/plugin.xml @@ -0,0 +1,26 @@ + + + + + + + + + \ No newline at end of file diff --git a/mylyn.tasks/connectors/gitlab/org.eclipse.mylyn.gitlab.core/src/org/eclipse/mylyn/gitlab/core/Duration.java b/mylyn.tasks/connectors/gitlab/org.eclipse.mylyn.gitlab.core/src/org/eclipse/mylyn/gitlab/core/Duration.java new file mode 100644 index 0000000000..ae62a52d33 --- /dev/null +++ b/mylyn.tasks/connectors/gitlab/org.eclipse.mylyn.gitlab.core/src/org/eclipse/mylyn/gitlab/core/Duration.java @@ -0,0 +1,23 @@ +package org.eclipse.mylyn.gitlab.core; + +import java.util.concurrent.TimeUnit; + +public class Duration { + final TimeUnit unit; + + final long value; + + public Duration(long value, TimeUnit unit) { + this.unit = unit; + this.value = value; + } + + public TimeUnit getUnit() { + return unit; + } + + public long getValue() { + return value; + } + +} diff --git a/mylyn.tasks/connectors/gitlab/org.eclipse.mylyn.gitlab.core/src/org/eclipse/mylyn/gitlab/core/GitlabConfiguration.java b/mylyn.tasks/connectors/gitlab/org.eclipse.mylyn.gitlab.core/src/org/eclipse/mylyn/gitlab/core/GitlabConfiguration.java new file mode 100644 index 0000000000..83b511b81f --- /dev/null +++ b/mylyn.tasks/connectors/gitlab/org.eclipse.mylyn.gitlab.core/src/org/eclipse/mylyn/gitlab/core/GitlabConfiguration.java @@ -0,0 +1,133 @@ +package org.eclipse.mylyn.gitlab.core; + +import java.io.Serializable; +import java.math.BigInteger; +import java.util.ArrayList; +import java.util.HashMap; +import java.util.Map; +import java.util.Optional; +import java.util.Set; + +import org.eclipse.jdt.annotation.NonNull; +import org.eclipse.mylyn.tasks.core.data.TaskAttribute; +import org.eclipse.mylyn.tasks.core.data.TaskData; + +import com.google.gson.JsonElement; +import com.google.gson.JsonObject; + +public class GitlabConfiguration implements Serializable { + + private static final long serialVersionUID = -6859757478504901423L; + + private static final GitlabTaskSchema SCHEMA = GitlabTaskSchema.getDefault(); + private final String repositoryURL; + private BigInteger userID; + private JsonElement userDetails; + private Map projectDetailsMap = new HashMap<>(); + private Map projectIDsMap = new HashMap<>(); + private ArrayList projects = new ArrayList<>(); + private Map groupsDetailsMap = new HashMap<>(); + private ArrayList groups = new ArrayList<>(); + + public GitlabConfiguration(String repositoryURL) { + this.repositoryURL = repositoryURL; + } + + public String getRepositoryURL() { + return repositoryURL; + } + + public BigInteger getUserID() { + return userID; + } + + public void setUserID(BigInteger userID) { + this.userID = userID; + } + + public JsonElement getUserDetails() { + return userDetails; + } + + public void setUserDetails(JsonElement userDetails) { + this.userDetails = userDetails; + } + + public ArrayList getProjects() { + return projects; + } + + public void addProject(JsonElement project) { + projects.add(project); + projectDetailsMap.put(project.getAsJsonObject().get("name_with_namespace").getAsString(), project); + projectIDsMap.put(project.getAsJsonObject().get("id").getAsInt(), project); + } + + public JsonElement getProjcetDetail(String project) { + return projectDetailsMap.get(project); + } + + public JsonElement getProjcetDetailFromNumber(Integer id) { + return projectIDsMap.get(id); + } + + public JsonElement getGroupDetail(String project) { + return groupsDetailsMap.get(project); + } + + public Set getProjectNames() { + return projectDetailsMap.keySet(); + } + + public Set getGroupNames() { + return groupsDetailsMap.keySet(); + } + + public ArrayList getGroups() { + return groups; + } + + public void addGroup(JsonElement group) { + groups.add(group); + groupsDetailsMap.put(group.getAsJsonObject().get("full_path").getAsString(), group); + + } + + public boolean updateProductOptions(@NonNull TaskData taskData) { + if (taskData == null) { + return false; + } + TaskAttribute attributeProduct = taskData.getRoot().getMappedAttribute(SCHEMA.PRODUCT.getKey()); + if (attributeProduct == null) { + return false; + } + for (JsonElement product : projects) { + JsonObject productObject = (JsonObject) product; + attributeProduct.putOption(productObject.get("id").getAsString(), productObject.get("name_with_namespace").getAsString()); + } + TaskAttribute attributeGroups = taskData.getRoot().getMappedAttribute(SCHEMA.GROUP.getKey()); + if (attributeGroups == null) { + return false; + } + Set groups = getGroupNames(); + for (String string : groups) { + attributeGroups.putOption(string, string); + } + TaskAttribute stateAttrib = taskData.getRoot().getMappedAttribute("STATE"); + if (stateAttrib!=null) { + stateAttrib.putOption("opened", "Opened"); + stateAttrib.putOption("closed", "Closed"); + stateAttrib.putOption("", "All"); + } + return true; + } + + public String getGroupID(String path) { + Optional groupId = Optional.ofNullable(groupsDetailsMap.get(path)) + .map(ma -> ma.getAsJsonObject().get("id").getAsString()); + if (groupId.isPresent()) { + return (String) groupId.get(); + } + return ""; + } +} diff --git a/mylyn.tasks/connectors/gitlab/org.eclipse.mylyn.gitlab.core/src/org/eclipse/mylyn/gitlab/core/GitlabCoreActivator.java b/mylyn.tasks/connectors/gitlab/org.eclipse.mylyn.gitlab.core/src/org/eclipse/mylyn/gitlab/core/GitlabCoreActivator.java new file mode 100644 index 0000000000..f8ef066470 --- /dev/null +++ b/mylyn.tasks/connectors/gitlab/org.eclipse.mylyn.gitlab.core/src/org/eclipse/mylyn/gitlab/core/GitlabCoreActivator.java @@ -0,0 +1,61 @@ +/******************************************************************************* + * Copyright (c) 2023 Frank Becker and others. + * + * This program and the accompanying materials are made available under the + * terms of the Eclipse Public License v. 2.0 which is available at + * https://www.eclipse.org/legal/epl-2.0 + * + * SPDX-License-Identifier: EPL-2.0 + * + * Contributors: + * Frank Becker - initial API and implementation + *******************************************************************************/ + +package org.eclipse.mylyn.gitlab.core; + +import org.eclipse.ui.plugin.AbstractUIPlugin; +import org.osgi.framework.BundleContext; + +/** + * The activator class controls the plug-in life cycle + */ +public class GitlabCoreActivator extends AbstractUIPlugin { + + // The plug-in ID + public static final String PLUGIN_ID = "org.eclipse.mylyn.gitlab.core"; //$NON-NLS-1$ + + public static final String CONNECTOR_KIND = "gitlab"; + public static final String GROUPS = "gitlab.groups"; + public static final String PROJECTS = "gitlab.projects"; + + // The shared instance + private static GitlabCoreActivator plugin; + + /** + * The constructor + */ + public GitlabCoreActivator() { + } + + @Override + public void start(BundleContext context) throws Exception { + super.start(context); + plugin = this; + } + + @Override + public void stop(BundleContext context) throws Exception { + plugin = null; + super.stop(context); + } + + /** + * Returns the shared instance + * + * @return the shared instance + */ + public static GitlabCoreActivator getDefault() { + return plugin; + } + +} diff --git a/mylyn.tasks/connectors/gitlab/org.eclipse.mylyn.gitlab.core/src/org/eclipse/mylyn/gitlab/core/GitlabException.java b/mylyn.tasks/connectors/gitlab/org.eclipse.mylyn.gitlab.core/src/org/eclipse/mylyn/gitlab/core/GitlabException.java new file mode 100644 index 0000000000..b879e0994f --- /dev/null +++ b/mylyn.tasks/connectors/gitlab/org.eclipse.mylyn.gitlab.core/src/org/eclipse/mylyn/gitlab/core/GitlabException.java @@ -0,0 +1,35 @@ +/******************************************************************************* + * Copyright (c) 2023 Frank Becker and others. + * + * This program and the accompanying materials are made available under the + * terms of the Eclipse Public License v. 2.0 which is available at + * https://www.eclipse.org/legal/epl-2.0 + * + * SPDX-License-Identifier: EPL-2.0 + * + * Contributors: + * Frank Becker - initial API and implementation + *******************************************************************************/ + +package org.eclipse.mylyn.gitlab.core; + +public class GitlabException extends Exception { + + private static final long serialVersionUID = 4915767534271733762L; + + public GitlabException() { + } + + public GitlabException(String message) { + super(message); + } + + public GitlabException(Throwable cause) { + super(cause.getMessage(), cause); + } + + public GitlabException(String message, Throwable cause) { + super(message, cause); + } + +} diff --git a/mylyn.tasks/connectors/gitlab/org.eclipse.mylyn.gitlab.core/src/org/eclipse/mylyn/gitlab/core/GitlabJSonArrayOperation.java b/mylyn.tasks/connectors/gitlab/org.eclipse.mylyn.gitlab.core/src/org/eclipse/mylyn/gitlab/core/GitlabJSonArrayOperation.java new file mode 100644 index 0000000000..cf19645204 --- /dev/null +++ b/mylyn.tasks/connectors/gitlab/org.eclipse.mylyn.gitlab.core/src/org/eclipse/mylyn/gitlab/core/GitlabJSonArrayOperation.java @@ -0,0 +1,54 @@ +package org.eclipse.mylyn.gitlab.core; + +import java.io.IOException; +import java.io.InputStreamReader; +import java.util.ArrayList; + +import org.apache.http.Header; +import org.apache.http.client.methods.HttpGet; +import org.apache.http.client.methods.HttpRequestBase; +import org.eclipse.mylyn.commons.core.operations.IOperationMonitor; +import org.eclipse.mylyn.commons.repositories.http.core.CommonHttpClient; +import org.eclipse.mylyn.commons.repositories.http.core.CommonHttpResponse; + +import com.google.gson.JsonArray; + +public abstract class GitlabJSonArrayOperation extends GitlabOperation { + + public GitlabJSonArrayOperation(CommonHttpClient client, String urlSuffix) { + super(client, urlSuffix); + } + @Override + protected JsonArray execute(IOperationMonitor monitor) throws IOException, GitlabException { + JsonArray result = null; + HttpRequestBase request = createHttpRequestBase(); + addHttpRequestEntities(request); + CommonHttpResponse response = execute(request, monitor); + result = processAndRelease(response, monitor); + Header[] lh = response.getResponse().getHeaders("Link"); + if (lh.length > 0) { +// System.out.print("Page Act: "); +// System.out.println(response.getResponse().getHeaders("X-Page")[0].getValue()); +// System.out.print("Page Count: "); +// System.out.println(response.getResponse().getHeaders("X-Total-Pages")[0].getValue()); + Header lh1 = lh[0]; + for (String lh2 : lh1.getValue().split(", ")) { + String[] lh3 = lh2.split("; "); +// System.out.print(lh3[1]); +// System.out.print(" "); +// System.out.println(lh3[0]); + if ("rel=\"next\"".equals(lh3[1])) { +// System.out.println("process "+lh3[0].substring(1, lh3[0].length()-1)); + HttpRequestBase looprequest = new HttpGet(lh3[0].substring(1, lh3[0].length()-1)); + addHttpRequestEntities(looprequest); + CommonHttpResponse loopresponse = execute(looprequest, monitor); + JsonArray loopresult = processAndRelease(loopresponse, monitor); + result.addAll(loopresult); + break; + } + } + } + + return result; + } +} diff --git a/mylyn.tasks/connectors/gitlab/org.eclipse.mylyn.gitlab.core/src/org/eclipse/mylyn/gitlab/core/GitlabOperation.java b/mylyn.tasks/connectors/gitlab/org.eclipse.mylyn.gitlab.core/src/org/eclipse/mylyn/gitlab/core/GitlabOperation.java new file mode 100644 index 0000000000..f011afa8d1 --- /dev/null +++ b/mylyn.tasks/connectors/gitlab/org.eclipse.mylyn.gitlab.core/src/org/eclipse/mylyn/gitlab/core/GitlabOperation.java @@ -0,0 +1,129 @@ +/******************************************************************************* + * Copyright (c) 2023 Frank Becker and others. + * + * This program and the accompanying materials are made available under the + * terms of the Eclipse Public License v. 2.0 which is available at + * https://www.eclipse.org/legal/epl-2.0 + * + * SPDX-License-Identifier: EPL-2.0 + * + * Contributors: + * Frank Becker - initial API and implementation + *******************************************************************************/ + +package org.eclipse.mylyn.gitlab.core; + +import java.io.BufferedInputStream; +import java.io.IOException; +import java.io.InputStreamReader; + +import org.apache.http.Header; +import org.apache.http.HttpStatus; +import org.apache.http.client.methods.HttpGet; +import org.apache.http.client.methods.HttpRequestBase; +import org.eclipse.mylyn.commons.core.operations.IOperationMonitor; +import org.eclipse.mylyn.commons.repositories.http.core.CommonHttpClient; +import org.eclipse.mylyn.commons.repositories.http.core.CommonHttpOperation; +import org.eclipse.mylyn.commons.repositories.http.core.CommonHttpResponse; +import org.eclipse.mylyn.commons.repositories.http.core.HttpUtil; +import org.eclipse.osgi.util.NLS; + +public abstract class GitlabOperation extends CommonHttpOperation { + + protected static final String ACCEPT = "Accept"; //$NON-NLS-1$ + + protected static final String CONTENT_TYPE = "Content-Type"; //$NON-NLS-1$ + + protected static final String APPLICATION_JSON = "application/json"; //$NON-NLS-1$ + + protected static final String TEXT_XML_CHARSET_UTF_8 = "text/xml; charset=UTF-8"; //$NON-NLS-1$ + + private final String urlSuffix; + + public GitlabOperation(CommonHttpClient client, String urlSuffix) { + super(client); + this.urlSuffix = urlSuffix; + } + + public T run(IOperationMonitor monitor) throws GitlabException { + try { + return execute(monitor); + } catch (IOException e) { + throw new GitlabException(e); + } + } + + protected abstract HttpRequestBase createHttpRequestBase(String url); + + protected abstract T parseFromJson(InputStreamReader in) throws GitlabException; + + protected HttpRequestBase createHttpRequestBase() { + HttpRequestBase request = createHttpRequestBase(createHttpRequestURL()); + return request; + } + + protected void addHttpRequestEntities(HttpRequestBase request) throws GitlabException { + request.setHeader(ACCEPT, APPLICATION_JSON); + String accessToken = (String) getClient().getAttribute(GitlabRestClient.AUTHORIZATION_HEADER); + request.setHeader("Authorization", accessToken); + } + + protected T doProcess(CommonHttpResponse response, IOperationMonitor monitor) throws IOException, GitlabException { + try (BufferedInputStream is = new BufferedInputStream(response.getResponseEntityAsStream())) { + InputStreamReader in = new InputStreamReader(is); + return parseFromJson(in); + } + } + + protected T processAndRelease(CommonHttpResponse response, IOperationMonitor monitor) + throws IOException, GitlabException { + try { + doValidate(response, monitor); + return doProcess(response, monitor); + } finally { + response.release(); + } + } + + protected void doValidate(CommonHttpResponse response, IOperationMonitor monitor) + throws IOException, GitlabException { + validate(response, HttpStatus.SC_OK, monitor); + } + + protected void validate(CommonHttpResponse response, int expected, IOperationMonitor monitor) + throws GitlabException { + int statusCode = response.getStatusCode(); + if (statusCode != expected && statusCode != HttpStatus.SC_BAD_REQUEST) { + if (statusCode == HttpStatus.SC_NOT_FOUND) { + throw new GitlabException( + NLS.bind("Requested resource ''{0}'' does not exist", response.getRequestPath())); + } + throw new GitlabException(NLS.bind("Unexpected response from Gitlab REST server for ''{0}'': {1}", + response.getRequestPath(), HttpUtil.getStatusText(statusCode))); + } + } + + protected String baseUrl() { + String url = getClient().getLocation().getUrl(); + if (!url.endsWith("/api/v4")) { + url += "/api/v4"; + } + return url; + } + + protected T execute(IOperationMonitor monitor) throws IOException, GitlabException { + HttpRequestBase request = createHttpRequestBase(); + addHttpRequestEntities(request); + CommonHttpResponse response = execute(request, monitor); + return processAndRelease(response, monitor); + } + + protected String getUrlSuffix() { + return urlSuffix; + } + + protected String createHttpRequestURL() { + String urlSuffix = getUrlSuffix(); + return baseUrl() + urlSuffix; + } +} diff --git a/mylyn.tasks/connectors/gitlab/org.eclipse.mylyn.gitlab.core/src/org/eclipse/mylyn/gitlab/core/GitlabRepositoryConnector.java b/mylyn.tasks/connectors/gitlab/org.eclipse.mylyn.gitlab.core/src/org/eclipse/mylyn/gitlab/core/GitlabRepositoryConnector.java new file mode 100644 index 0000000000..54fb542b76 --- /dev/null +++ b/mylyn.tasks/connectors/gitlab/org.eclipse.mylyn.gitlab.core/src/org/eclipse/mylyn/gitlab/core/GitlabRepositoryConnector.java @@ -0,0 +1,498 @@ +/******************************************************************************* + * Copyright (c) 2023 Frank Becker and others. + * + * This program and the accompanying materials are made available under the + * terms of the Eclipse Public License v. 2.0 which is available at + * https://www.eclipse.org/legal/epl-2.0 + * + * SPDX-License-Identifier: EPL-2.0 + * + * Contributors: + * Frank Becker - initial API and implementation + *******************************************************************************/ + +package org.eclipse.mylyn.gitlab.core; + +import java.beans.PropertyChangeEvent; +import java.beans.PropertyChangeListener; +import java.text.SimpleDateFormat; +import java.util.Collections; +import java.util.HashSet; +import java.util.List; +import java.util.Map; +import java.util.Set; +import java.util.concurrent.ExecutionException; +import java.util.concurrent.Executor; +import java.util.concurrent.TimeUnit; +import java.util.concurrent.TimeoutException; +import java.util.stream.Collectors; + +import org.eclipse.core.runtime.CoreException; +import org.eclipse.core.runtime.IProgressMonitor; +import org.eclipse.core.runtime.IStatus; +import org.eclipse.core.runtime.Status; +import org.eclipse.core.runtime.jobs.IJobChangeEvent; +import org.eclipse.core.runtime.jobs.Job; +import org.eclipse.core.runtime.jobs.JobChangeAdapter; +import org.eclipse.jdt.annotation.NonNull; +import org.eclipse.jdt.annotation.Nullable; +import org.eclipse.mylyn.commons.core.operations.IOperationMonitor; +import org.eclipse.mylyn.commons.core.operations.OperationUtil; +import org.eclipse.mylyn.commons.net.AuthenticationCredentials; +import org.eclipse.mylyn.commons.repositories.core.RepositoryLocation; +import org.eclipse.mylyn.commons.repositories.core.auth.AuthenticationType; +import org.eclipse.mylyn.commons.repositories.core.auth.UserCredentials; +import org.eclipse.mylyn.internal.commons.core.operations.NullOperationMonitor; +import org.eclipse.mylyn.internal.tasks.core.IRepositoryConstants; +import org.eclipse.mylyn.tasks.core.AbstractRepositoryConnector; +import org.eclipse.mylyn.tasks.core.IRepositoryQuery; +import org.eclipse.mylyn.tasks.core.ITask; +import org.eclipse.mylyn.tasks.core.RepositoryInfo; +import org.eclipse.mylyn.tasks.core.RepositoryVersion; +import org.eclipse.mylyn.tasks.core.TaskRepository; +import org.eclipse.mylyn.tasks.core.data.AbstractTaskDataHandler; +import org.eclipse.mylyn.tasks.core.data.TaskAttribute; +import org.eclipse.mylyn.tasks.core.data.TaskData; +import org.eclipse.mylyn.tasks.core.data.TaskDataCollector; +import org.eclipse.mylyn.tasks.core.data.TaskMapper; +import org.eclipse.mylyn.tasks.core.sync.ISynchronizationSession; + +import com.google.common.base.Objects; +import com.google.common.base.Optional; +import com.google.common.cache.CacheBuilder; +import com.google.common.cache.CacheLoader; +import com.google.common.cache.LoadingCache; +import com.google.common.collect.Lists; +import com.google.common.util.concurrent.ListenableFuture; +import com.google.common.util.concurrent.UncheckedExecutionException; + +public class GitlabRepositoryConnector extends AbstractRepositoryConnector { + + public class RepositoryKey { + private final TaskRepository repository; + + public RepositoryKey(@NonNull TaskRepository repository) { + super(); + this.repository = repository; + } + + public TaskRepository getRepository() { + return repository; + } + + @Override + public int hashCode() { + return repository.hashCode(); + } + + @Override + public boolean equals(Object obj) { + if (this == obj) { + return true; + } + if (obj == null || getClass() != obj.getClass()) { + return false; + } + return this.repository.equals(((RepositoryKey) obj).getRepository()); + } + } + + private static final ThreadLocal context = new ThreadLocal(); + + private final LoadingCache> configurationCache; + private SimpleDateFormat simpleFormatter = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss.SSS'Z'"); + public static Duration CONFIGURATION_CACHE_EXPIRE_DURATION = new Duration(7, TimeUnit.DAYS); + public static Duration CONFIGURATION_CACHE_REFRESH_AFTER_WRITE_DURATION = new Duration(1, TimeUnit.DAYS); + public static Duration CLIENT_CACHE_DURATION = new Duration(24, TimeUnit.HOURS); + + private boolean ignoredProperty(String propertyName) { + if (propertyName.equals(RepositoryLocation.PROPERTY_LABEL) || propertyName.equals(TaskRepository.OFFLINE) + || propertyName.equals(IRepositoryConstants.PROPERTY_ENCODING) + || propertyName.equals(TaskRepository.PROXY_HOSTNAME) || propertyName.equals(TaskRepository.PROXY_PORT) + || propertyName.equals("org.eclipse.mylyn.tasklist.repositories.savePassword") //$NON-NLS-1$ + || propertyName.equals("org.eclipse.mylyn.tasklist.repositories.proxy.usedefault") //$NON-NLS-1$ + || propertyName.equals("org.eclipse.mylyn.tasklist.repositories.proxy.savePassword") //$NON-NLS-1$ + || propertyName.equals("org.eclipse.mylyn.tasklist.repositories.proxy.username") //$NON-NLS-1$ + || propertyName.equals("org.eclipse.mylyn.tasklist.repositories.proxy.password") //$NON-NLS-1$ + || propertyName.equals("org.eclipse.mylyn.tasklist.repositories.proxy.enabled")) { //$NON-NLS-1$ + return true; + } + return false; + } + + abstract class ListenableFutureJob extends Job implements ListenableFuture { + + private class Listener { + + Runnable runnable; + + Executor executor; + + public Listener(Runnable runnable, Executor executor) { + this.runnable = runnable; + this.executor = executor; + } + + public void run() { + executor.execute(runnable); + } + } + + List listeners = Collections.synchronizedList(Lists.newArrayList()); + + private volatile boolean done; + + private V resultObject; + + public ListenableFutureJob(String name) { + super(name); + resultObject = null; + this.addJobChangeListener(new JobChangeAdapter() { + + @Override + public void done(IJobChangeEvent event) { + done = true; + synchronized (listeners) { + for (Listener listener : listeners) { + listener.run(); + } + } + } + }); + } + + @Override + public boolean cancel(boolean mayInterruptIfRunning) { + return this.cancel(); + } + + @Override + public V get() throws InterruptedException, ExecutionException { + this.join(); + return resultObject; + } + + @Override + public V get(long timeout, TimeUnit unit) throws InterruptedException, ExecutionException, TimeoutException { + long start = System.currentTimeMillis(); + while (!done && System.currentTimeMillis() - start < unit.toMillis(timeout)) { + Thread.sleep(250); + } + if (!done) { + throw new TimeoutException("ListenableFutureJob.get() could not get the result!"); + } + return resultObject; + } + + protected void set(V future) { + this.resultObject = future; + } + + @Override + public boolean isCancelled() { + return this.getResult().getSeverity() == IStatus.CANCEL; + } + + @Override + public boolean isDone() { + return done; + } + + @Override + public void addListener(Runnable listener, Executor executor) { + listeners.add(new Listener(listener, executor)); + } + } + + private final PropertyChangeListener repositoryChangeListener4ConfigurationCache = new PropertyChangeListener() { + + @Override + public void propertyChange(PropertyChangeEvent evt) { + if (ignoredProperty(evt.getPropertyName()) + || evt.getPropertyName().equals("org.eclipse.mylyn.tasklist.repositories.password")) { //$NON-NLS-1$ + return; + } + TaskRepository taskRepository = (TaskRepository) evt.getSource(); + configurationCache.invalidate(new RepositoryKey(taskRepository)); + } + }; + + protected CacheBuilder createCacheBuilder(Duration expireAfterWriteDuration, + Duration refreshAfterWriteDuration) { + return CacheBuilder.newBuilder() + .expireAfterWrite(expireAfterWriteDuration.getValue(), expireAfterWriteDuration.getUnit()) + .refreshAfterWrite(refreshAfterWriteDuration.getValue(), refreshAfterWriteDuration.getUnit()); + } + + public GitlabRepositoryConnector() { + this(CONFIGURATION_CACHE_REFRESH_AFTER_WRITE_DURATION); + } + + public GitlabRepositoryConnector(Duration refreshAfterWriteDuration) { + super(); + configurationCache = createCacheBuilder(CONFIGURATION_CACHE_EXPIRE_DURATION, refreshAfterWriteDuration) + .build(new CacheLoader>() { + + @Override + public Optional load(RepositoryKey key) throws Exception { + GitlabRestClient client = clientCache.get(key); + TaskRepository repository = key.getRepository(); + repository.addChangeListener(repositoryChangeListener4ConfigurationCache); + return Optional.fromNullable(client.getConfiguration(key.getRepository(), context.get())); + } + + @Override + public ListenableFuture> reload(final RepositoryKey key, + Optional oldValue) throws Exception { + // asynchronous! + ListenableFutureJob> job = new ListenableFutureJob>( + "") { + + @Override + protected IStatus run(IProgressMonitor monitor) { + GitlabRestClient client; + try { + client = clientCache.get(key); + set(Optional + .fromNullable(client.getConfiguration(key.getRepository(), context.get()))); + } catch (ExecutionException e) { + e.printStackTrace(); + return new Status(IStatus.ERROR, GitlabCoreActivator.PLUGIN_ID, + "GitlabConnector reload Configuration", e); + } + return Status.OK_STATUS; + } + }; + job.schedule(); + return job; + } + }); + } + + public GitlabConfiguration getRepositoryConfiguration(TaskRepository repository) throws CoreException { + if (clientCache.getIfPresent(new RepositoryKey(repository)) == null) { + getClient(repository); + } + try { + Optional configurationOptional = configurationCache.get(new RepositoryKey(repository)); + return configurationOptional.isPresent() ? configurationOptional.get() : null; + } catch (UncheckedExecutionException e) { + throw new CoreException(new Status(IStatus.ERROR, GitlabCoreActivator.PLUGIN_ID, e.getMessage(), e)); + } catch (ExecutionException e) { + throw new CoreException(new Status(IStatus.ERROR, GitlabCoreActivator.PLUGIN_ID, e.getMessage(), e)); + } + } + + @Override + public boolean canCreateNewTask(@NonNull TaskRepository repository) { + // TODO Auto-generated method stub + return false; + } + + @Override + public boolean canCreateTaskFromKey(@NonNull TaskRepository repository) { + // TODO Auto-generated method stub + return false; + } + + @Override + public @Nullable String getRepositoryUrlFromTaskUrl(@NonNull String taskUrl) { + throw new UnsupportedOperationException(); + } + + @Override + public @Nullable String getTaskIdFromTaskUrl(@NonNull String taskUrl) { + throw new UnsupportedOperationException(); + } + + @Override + public @Nullable String getTaskUrl(@NonNull String repositoryUrl, @NonNull String taskIdOrKey) { + throw new UnsupportedOperationException(); + } + + @Override + public boolean hasTaskChanged(@NonNull TaskRepository taskRepository, @NonNull ITask task, + @NonNull TaskData taskData) { + String lastKnownLocalModValue = task.getModificationDate() != null + ? simpleFormatter.format(task.getModificationDate()) + : ""; + TaskAttribute latestRemoteModAttribute = taskData.getRoot().getMappedAttribute(TaskAttribute.DATE_MODIFICATION); + String latestRemoteModValue = latestRemoteModAttribute != null ? latestRemoteModAttribute.getValue() : null; + return !Objects.equal(latestRemoteModValue, lastKnownLocalModValue); + } + + @Override + public void updateRepositoryConfiguration(@NonNull TaskRepository taskRepository, @NonNull IProgressMonitor monitor) + throws CoreException { + context.set(monitor != null ? OperationUtil.convert(monitor) : new NullOperationMonitor()); + GitlabRestClient client; + client = getClient(taskRepository); + IOperationMonitor progress = OperationUtil.convert(monitor, "performQuery", 3); //$NON-NLS-1$ + client.getConfiguration(taskRepository, progress); + context.remove(); + } + + @Override + public String getConnectorKind() { + return GitlabCoreActivator.CONNECTOR_KIND; + } + + @Override + public String getLabel() { + return "Gitlab"; + } + + public class SingleTaskDataCollector extends TaskDataCollector { + final TaskData[] retrievedData = new TaskData[1]; + + @Override + public void accept(TaskData taskData) { + retrievedData[0] = taskData; + } + + public TaskData getTaskData() { + return retrievedData[0]; + } + + } + + @Override + public TaskData getTaskData(TaskRepository repository, String taskId, IProgressMonitor monitor) + throws CoreException { + Set taskIds = new HashSet(); + taskIds.add(taskId); + SingleTaskDataCollector singleTaskDataCollector = new SingleTaskDataCollector(); + getTaskDataHandler().getMultiTaskData(repository, taskIds, singleTaskDataCollector, monitor); + + if (singleTaskDataCollector.getTaskData() == null) { + throw new CoreException(new Status(IStatus.ERROR, GitlabCoreActivator.PLUGIN_ID, + "Task data could not be retrieved. Please re-synchronize task")); //$NON-NLS-1$ + } + return singleTaskDataCollector.getTaskData(); + } + + @Override + public IStatus performQuery(TaskRepository repository, IRepositoryQuery query, TaskDataCollector collector, + ISynchronizationSession session, IProgressMonitor monitor) { + monitor.beginTask("performQuery", IProgressMonitor.UNKNOWN); + GitlabRestClient client; + try { + client = getClient(repository); + IOperationMonitor progress = OperationUtil.convert(monitor, "performQuery", 3); //$NON-NLS-1$ + client.getIssues(query, collector, new NullOperationMonitor()); + } catch (CoreException e) { + return new Status(IStatus.ERROR, GitlabCoreActivator.PLUGIN_ID, IStatus.INFO, + "CoreException from performQuery", e); + } catch (GitlabException e) { + return new Status(IStatus.ERROR, GitlabCoreActivator.PLUGIN_ID, IStatus.INFO, + "GitlabException from performQuery", e); + } + return Status.OK_STATUS; + } + + @Override + public void updateTaskFromTaskData(TaskRepository taskRepository, ITask task, TaskData taskData) { + TaskMapper scheme = getTaskMapping(taskData); + scheme.applyTo(task); + } + + @Override + public AbstractTaskDataHandler getTaskDataHandler() { + return new GitlabTaskDataHandler(this); + } + + @Override + public RepositoryInfo validateRepository(TaskRepository repository, IProgressMonitor monitor) throws CoreException { + try { + GitlabRestClient client = createClient(repository); + if (!client.validate(OperationUtil.convert(monitor))) { + throw new CoreException( + new Status(IStatus.ERROR, GitlabCoreActivator.PLUGIN_ID, "repository is invalide")); + } + return new RepositoryInfo(new RepositoryVersion(client.getVersion(OperationUtil.convert(monitor)))); + } catch (Exception e) { + throw new CoreException(new Status(IStatus.ERROR, GitlabCoreActivator.PLUGIN_ID, e.getMessage(), e)); + } + } + + public GitlabRestClient getClient(TaskRepository repository) throws CoreException { + try { + return clientCache.get(new RepositoryKey(repository)); + } catch (ExecutionException e) { + throw new CoreException( + new Status(IStatus.ERROR, GitlabCoreActivator.PLUGIN_ID, "TaskRepositoryManager is null")); + } + } + + private final PropertyChangeListener repositoryChangeListener4ClientCache = new PropertyChangeListener() { + + @Override + public void propertyChange(PropertyChangeEvent evt) { + TaskRepository taskRepository = (TaskRepository) evt.getSource(); + clientCache.invalidate(new RepositoryKey(taskRepository)); + } + }; + + private final LoadingCache clientCache = CacheBuilder.newBuilder() + .expireAfterAccess(CLIENT_CACHE_DURATION.getValue(), CLIENT_CACHE_DURATION.getUnit()) + .build(new CacheLoader() { + + @Override + public GitlabRestClient load(RepositoryKey key) throws Exception { + TaskRepository repository = key.getRepository(); + repository.addChangeListener(repositoryChangeListener4ClientCache); + return createClient(repository); + } + }); + + public GitlabRestClient createClient(TaskRepository repository) { + RepositoryLocation location = new RepositoryLocation(convertProperties(repository)); + AuthenticationCredentials credentials1 = repository + .getCredentials(org.eclipse.mylyn.commons.net.AuthenticationType.REPOSITORY); + UserCredentials credentials = new UserCredentials(credentials1.getUserName(), credentials1.getPassword(), null, + true); + location.setCredentials(AuthenticationType.REPOSITORY, credentials); + GitlabRestClient client = new GitlabRestClient(location, this, repository); + + return client; + } + + private Map convertProperties(TaskRepository repository) { + return repository.getProperties().entrySet().stream() + .collect(Collectors.toMap(e -> convertProperty(e.getKey()), Map.Entry::getValue)); + } + + @SuppressWarnings("restriction") + private String convertProperty(String key) { + if (TaskRepository.PROXY_USEDEFAULT.equals(key)) { + return RepositoryLocation.PROPERTY_PROXY_USEDEFAULT; + } else if (TaskRepository.PROXY_HOSTNAME.equals(key)) { + return RepositoryLocation.PROPERTY_PROXY_HOST; + } else if (TaskRepository.PROXY_PORT.equals(key)) { + return RepositoryLocation.PROPERTY_PROXY_PORT; + } + return key; + } + + @Override + public TaskMapper getTaskMapping(final TaskData taskData) { + + return new TaskMapper(taskData) { + @Override + public String getTaskKey() { + TaskAttribute attribute = getTaskData().getRoot() + .getAttribute(GitlabTaskSchema.getDefault().TASK_KEY.getKey()); + if (attribute != null) { + return attribute.getValue(); + } + return super.getTaskKey(); + } + + @Override + public String getTaskKind() { + return taskData.getConnectorKind(); + } + }; + } + +} diff --git a/mylyn.tasks/connectors/gitlab/org.eclipse.mylyn.gitlab.core/src/org/eclipse/mylyn/gitlab/core/GitlabRestClient.java b/mylyn.tasks/connectors/gitlab/org.eclipse.mylyn.gitlab.core/src/org/eclipse/mylyn/gitlab/core/GitlabRestClient.java new file mode 100644 index 0000000000..709dac2b69 --- /dev/null +++ b/mylyn.tasks/connectors/gitlab/org.eclipse.mylyn.gitlab.core/src/org/eclipse/mylyn/gitlab/core/GitlabRestClient.java @@ -0,0 +1,714 @@ +/******************************************************************************* + * Copyright (c) 2023 Frank Becker and others. + * + * This program and the accompanying materials are made available under the + * terms of the Eclipse Public License v. 2.0 which is available at + * https://www.eclipse.org/legal/epl-2.0 + * + * SPDX-License-Identifier: EPL-2.0 + * + * Contributors: + * Frank Becker - initial API and implementation + *******************************************************************************/ + +package org.eclipse.mylyn.gitlab.core; + +import java.io.BufferedReader; +import java.io.InputStreamReader; +import java.io.PrintStream; +import java.lang.reflect.Type; +import java.net.HttpURLConnection; +import java.net.URL; +import java.util.ArrayList; +import java.util.List; +import java.util.Map.Entry; +import java.util.Set; +import java.util.regex.Matcher; +import java.util.regex.Pattern; +import java.util.stream.Collectors; + +import org.apache.http.client.methods.HttpGet; +import org.apache.http.client.methods.HttpRequestBase; +import org.eclipse.core.runtime.CoreException; +import org.eclipse.core.runtime.IProgressMonitor; +import org.eclipse.core.runtime.ISafeRunnable; +import org.eclipse.core.runtime.IStatus; +import org.eclipse.core.runtime.SafeRunner; +import org.eclipse.core.runtime.Status; +import org.eclipse.mylyn.commons.core.StatusHandler; +import org.eclipse.mylyn.commons.core.operations.IOperationMonitor; +import org.eclipse.mylyn.commons.core.operations.OperationUtil; +import org.eclipse.mylyn.commons.net.AuthenticationCredentials; +import org.eclipse.mylyn.commons.repositories.core.RepositoryLocation; +import org.eclipse.mylyn.commons.repositories.http.core.CommonHttpClient; +import org.eclipse.mylyn.tasks.core.IRepositoryQuery; +import org.eclipse.mylyn.tasks.core.TaskRepository; +import org.eclipse.mylyn.tasks.core.data.TaskAttribute; +import org.eclipse.mylyn.tasks.core.data.TaskAttributeMapper; +import org.eclipse.mylyn.tasks.core.data.TaskCommentMapper; +import org.eclipse.mylyn.tasks.core.data.TaskData; +import org.eclipse.mylyn.tasks.core.data.TaskDataCollector; +import org.eclipse.osgi.util.NLS; + +import com.google.gson.Gson; +import com.google.gson.GsonBuilder; +import com.google.gson.JsonArray; +import com.google.gson.JsonDeserializationContext; +import com.google.gson.JsonDeserializer; +import com.google.gson.JsonElement; +import com.google.gson.JsonObject; +import com.google.gson.JsonParseException; +import com.google.gson.reflect.TypeToken; + +public class GitlabRestClient { + + @SuppressWarnings("restriction") + private final CommonHttpClient client; + private final GitlabRepositoryConnector connector; + private final TaskRepository taskRepository; + + public static String AUTHORIZATION_HEADER = "authorization_header"; + + @SuppressWarnings("restriction") + public GitlabRestClient(RepositoryLocation location, GitlabRepositoryConnector connector, + TaskRepository taskRepository) { + super(); + client = new CommonHttpClient(location); + this.connector = connector; + this.taskRepository = taskRepository; + } + + @SuppressWarnings("restriction") + public RepositoryLocation getLocation() { + return client.getLocation(); + } + + @SuppressWarnings("restriction") + public CommonHttpClient getClient() { + return client; + } + + public TaskRepository getTaskRepository() { + return taskRepository; + } + + public IStatus getIssues(IRepositoryQuery query, TaskDataCollector collector, final IOperationMonitor monitor) + throws GitlabException, CoreException { + getAccessTokenIfNotPresent(monitor); +// GitlabConfiguration conf = connector.getRepositoryConfiguration(taskRepository); + String[] queryProjects = query.getAttribute(GitlabTaskSchema.getDefault().PRODUCT.getKey()).split(","); + String[] gueryGroups = query.getAttribute(GitlabTaskSchema.getDefault().GROUP.getKey()).split(","); + + if (!queryProjects[0].isEmpty()) { + for (String string : queryProjects) { +// String path = "/projects/" + ((JsonObject) conf.getProjcetDetail(string)).get("path_with_namespace") +// .getAsString().replaceAll("/", "%2F"); + String path = "/projects/" + string.replaceAll("/", "%2F"); + getIssuesInternal(query, collector, path, monitor); + } + } + if (!gueryGroups[0].isEmpty()) { + for (String string : gueryGroups) { +// String path = "/groups/" + ((JsonObject) conf.getGroupDetail(string)).get("full_path").getAsString() +// .replaceAll("/", "%2F"); + String path = "/groups/" + string.replaceAll("/", "%2F"); + getIssuesInternal(query, collector, path, monitor); + } + } + + return Status.OK_STATUS; + } + + private void getIssuesInternal(IRepositoryQuery query, TaskDataCollector collector, String path, + final IOperationMonitor monitor) throws GitlabException { + List taskDataArray = new GitlabOperation>(client, path + "/issues") { + + @Override + protected HttpRequestBase createHttpRequestBase(String url) { + String state = query.getAttribute("STATE"); + String suffix; + switch (state != null ? state : "") { + case "opened": + suffix = "?state=opened"; + break; + case "closed": + suffix = "?state=closed"; + break; + default: + suffix = ""; + } + HttpRequestBase request = new HttpGet(url + suffix); + return request; + } + + @Override + protected List parseFromJson(InputStreamReader in) throws GitlabException { + + String text = new BufferedReader(in).lines().collect(Collectors.joining("\n")); + JsonArray convertedObject = new Gson().fromJson(text, JsonArray.class); + TypeToken> type = new TypeToken>() { + }; + + return new GsonBuilder().registerTypeAdapter(type.getType(), new JSonTaskDataListDeserializer()) + .create().fromJson(text, type.getType()); + } + }.run(monitor); + for (final TaskData taskData : taskDataArray) { + taskData.setPartial(true); + SafeRunner.run(new ISafeRunnable() { + + @Override + public void run() throws Exception { + collector.accept(taskData); + } + + @Override + public void handleException(Throwable exception) { + StatusHandler.log(new Status(IStatus.ERROR, GitlabCoreActivator.PLUGIN_ID, + NLS.bind("Unexpected error during result collection. TaskID {0} in repository {1}", //$NON-NLS-1$ + taskData.getTaskId(), taskData.getRepositoryUrl()), + exception)); + } + }); + } + } + + public String getVersion(IOperationMonitor monitor) throws GitlabException { + getAccessTokenIfNotPresent(monitor); + JsonObject versionInfo = new GitlabOperation(client, "/version") { + + @Override + protected HttpRequestBase createHttpRequestBase(String url) { + HttpRequestBase request = new HttpGet(url); + return request; + } + + @Override + protected JsonObject parseFromJson(InputStreamReader in) throws GitlabException { + return new Gson().fromJson(in, JsonObject.class); + } + }.run(monitor); + return versionInfo.get("version").getAsString(); + } + + public String getVersionAndRevision(IOperationMonitor monitor) throws GitlabException { + getAccessTokenIfNotPresent(monitor); + JsonObject versionInfo = new GitlabOperation(client, "/version") { + + @Override + protected HttpRequestBase createHttpRequestBase(String url) { + HttpRequestBase request = new HttpGet(url); + return request; + } + + @Override + protected JsonObject parseFromJson(InputStreamReader in) throws GitlabException { + return new Gson().fromJson(in, JsonObject.class); + } + }.run(monitor); + return versionInfo.get("version").getAsString() + "(rev: " + versionInfo.get("revision").getAsString() + ")"; + } + + public boolean validate(IOperationMonitor monitor) throws GitlabException { + getAccessTokenIfNotPresent(monitor); + String validate = new GitlabOperation(client, "/version") { + + protected boolean isRepeatable() { + return false; + }; + + @Override + protected HttpRequestBase createHttpRequestBase(String url) { + HttpRequestBase request = new HttpGet(url); + return request; + } + + @Override + protected String parseFromJson(InputStreamReader in) throws GitlabException { + return new BufferedReader(in).lines().parallel().collect(Collectors.joining("\n")); + } + }.run(monitor); + return validate.length() > 0 && validate.contains("version"); + } + + public JsonObject getMetadata(IOperationMonitor monitor) throws GitlabException { + getAccessTokenIfNotPresent(monitor); + JsonObject jsonArray = new GitlabOperation(client, "/metadata") { + @Override + protected HttpRequestBase createHttpRequestBase(String url) { + HttpRequestBase request = new HttpGet(url); + return request; + } + + @Override + protected JsonObject parseFromJson(InputStreamReader in) throws GitlabException { + return new Gson().fromJson(in, JsonObject.class); + } + }.run(monitor); + return jsonArray; + } + + private class JSonTaskDataListDeserializer implements JsonDeserializer> { + + @Override + public ArrayList deserialize(JsonElement json, Type typeOfT, JsonDeserializationContext context) + throws JsonParseException { + ArrayList response = new ArrayList(); + GitlabConfiguration config =getConfiguration(); + JsonArray ja = json.getAsJsonArray(); + for (JsonElement jsonElement : ja) { + JsonObject jo = jsonElement.getAsJsonObject(); + TaskData taskData = getFromJson(jo); + if (config != null) + config.updateProductOptions(taskData); + response.add(taskData); + } + return response; + } + } + + private TaskData getFromJson(JsonObject jo) { + GitlabTaskDataHandler dataHandler = (GitlabTaskDataHandler) connector.getTaskDataHandler(); + TaskAttributeMapper mapper = dataHandler.getAttributeMapper(taskRepository); + + TaskData response = null; + String selfString = jo.get("_links").getAsJsonObject().get("self").getAsString(); + + TaskData taskData = null; + taskData = new TaskData(mapper, connector.getConnectorKind(), taskRepository.getRepositoryUrl(), selfString); + response = taskData; + try { + dataHandler.initializeTaskData(taskRepository, taskData, null, null); + } catch (CoreException e) { + throw new RuntimeException(e); + } + for (Entry entry : jo.entrySet()) { + String attributeId = GitlabTaskSchema.getAttributeNameFromJsonName(entry.getKey()); + TaskAttribute attribute = taskData.getRoot().getAttribute(attributeId); + if (attribute == null) { + PrintStream ps = attribute == null ? System.err : System.out; + ps.println(entry.getKey() + " -> " + entry.getValue() // + + " -> " + attributeId + " -> " + attribute + "\n" // + + entry.getValue().isJsonPrimitive() + entry.getValue().isJsonObject() + + entry.getValue().isJsonArray()); + ps.close(); + } + if (attribute != null && entry.getValue() != null && entry.getValue().isJsonPrimitive()) { + attribute.setValue(entry.getValue().getAsString()); + } + if (entry.getKey().equals("severity")) { + attribute.putOption(entry.getValue().getAsString(), entry.getValue().getAsString()); + } + if (entry.getKey().equals("author") && entry.getValue().isJsonObject()) { + attribute.setValue(entry.getValue().getAsJsonObject().get("name").getAsString()); + } + } + return response; + } + + private class JSonTaskDataDeserializer implements JsonDeserializer { + + @Override + public TaskData deserialize(JsonElement json, Type typeOfT, JsonDeserializationContext context) + throws JsonParseException { + GitlabConfiguration config = getConfiguration(); + JsonObject jo = json.getAsJsonObject(); + TaskData taskData = getFromJson(jo); + if (config != null) + config.updateProductOptions(taskData); + return taskData; + } + + } + + private GitlabConfiguration getConfiguration() { + GitlabConfiguration config; + try { + config = connector.getRepositoryConfiguration(taskRepository); + } catch (CoreException e) { + // TODO Auto-generated catch block + e.printStackTrace(); + config = null; + } + return config; + } + + private void getAccessTokenIfNotPresent(IOperationMonitor monitor) { + if (getClientAttribute(AUTHORIZATION_HEADER) == null) { + try { + obtainAccessToken(monitor); + } catch (Exception e) { + // TODO Auto-generated catch block + e.printStackTrace(); + } + } + } + + @SuppressWarnings("restriction") + private Object getClientAttribute(String attribute) { + return getClient().getAttribute(attribute); + } + + @SuppressWarnings("restriction") + private void setClientAttribute(String attribute, Object value) { + getClient().setAttribute(attribute, value); + } + + public String obtainAccessToken(IOperationMonitor monitor) throws Exception { + AuthenticationCredentials credentials1 = taskRepository + .getCredentials(org.eclipse.mylyn.commons.net.AuthenticationType.REPOSITORY); + String username = credentials1.getUserName(); + String password = credentials1.getPassword(); + String repositoryUrl = taskRepository.getRepositoryUrl(); + + URL url = new URL(repositoryUrl + "/oauth/token"); + HttpURLConnection connection = (HttpURLConnection) url.openConnection(); + connection.setRequestMethod("POST"); + connection.setDoOutput(true); + connection.getOutputStream() + .write(("grant_type=password&username=" + username + "&password=" + password).getBytes()); + connection.connect(); + + int responseCode = connection.getResponseCode(); + if (responseCode != 200) { + throw new Exception("Failed to obtain access token"); + } + + String response = new String(connection.getInputStream().readAllBytes()); + String accessToken = response.split("\"access_token\":\"")[1].split("\"")[0]; + setClientAttribute(AUTHORIZATION_HEADER, "Bearer " + accessToken); + return accessToken; + } + + public TaskData getTaskData(TaskRepository repository, String taskId, IProgressMonitor monitor) + throws GitlabException { + String searchString = ".+(/projects/\\d+)/issues/(\\d+)"; + Pattern pattern = Pattern.compile(searchString, Pattern.CASE_INSENSITIVE); + Matcher matcher = pattern.matcher(taskId); + if (matcher.find()) { + TaskData result; +// System.out.println("found: " + matcher.group(0)); +// System.out.println(" " + matcher.group(1)); +// System.out.println(" " + matcher.group(2)); + GitlabConfiguration config = getConfiguration(); + JsonObject iss = getIssue(matcher.group(1), matcher.group(2), OperationUtil.convert(monitor)); + TypeToken type = new TypeToken() { + }; + result = new GsonBuilder().registerTypeAdapter(type.getType(), new JSonTaskDataDeserializer()).create() + .fromJson(iss, type.getType()); + + JsonArray notes = getIssueNotes(matcher.group(1), matcher.group(2), OperationUtil.convert(monitor)); + if (notes != null) { + for (int i = 0; i < notes.size(); i++) { + JsonObject note = notes.get(i).getAsJsonObject(); + TaskCommentMapper cmapper = new TaskCommentMapper(); + cmapper.setAuthor( + repository.createPerson(note.get("author").getAsJsonObject().get("name").getAsString())); + cmapper.setCreationDate(GitlabTaskAttributeMapper.parseDate(note.get("created_at").getAsString())); + cmapper.setText(note.get("body").getAsString()); + cmapper.setNumber(i + 1); + TaskAttribute attribute = result.getRoot().createAttribute(TaskAttribute.PREFIX_COMMENT + (i + 1)); + cmapper.applyTo(attribute); + } + } + config.updateProductOptions(result); + + return result; + } + return null; + } + + public void getTaskData(Set taskIds, TaskRepository taskRepository, TaskDataCollector collector, + IOperationMonitor monitor) throws GitlabException { + + for (String taskId : taskIds) { + TaskData data; + data = getTaskData(taskRepository, taskId, monitor); + collector.accept(data); + } + } + + public JsonObject getUser(IOperationMonitor monitor) throws GitlabException { + getAccessTokenIfNotPresent(monitor); + JsonObject jsonArray = new GitlabOperation(client, "/user") { + @Override + protected HttpRequestBase createHttpRequestBase(String url) { + HttpRequestBase request = new HttpGet(url); + return request; + } + + @Override + protected JsonObject parseFromJson(InputStreamReader in) throws GitlabException { + return new Gson().fromJson(in, JsonObject.class); + } + }.run(monitor); + return jsonArray; + } + + public JsonArray getUsers(String path, IOperationMonitor monitor) throws GitlabException { + getAccessTokenIfNotPresent(monitor); + JsonArray jsonArray = new GitlabJSonArrayOperation(client, "/users" + path) { + @Override + protected HttpRequestBase createHttpRequestBase(String url) { + HttpRequestBase request = new HttpGet(url); + return request; + } + + @Override + protected JsonArray parseFromJson(InputStreamReader in) throws GitlabException { + return new Gson().fromJson(in, JsonArray.class); + } + }.run(monitor); + return jsonArray; + } + + public JsonArray getNamespaces(IOperationMonitor monitor) throws GitlabException { + getAccessTokenIfNotPresent(monitor); + JsonArray jsonArray = new GitlabJSonArrayOperation(client, "/namespaces") { + @Override + protected HttpRequestBase createHttpRequestBase(String url) { + HttpRequestBase request = new HttpGet(url); + return request; + } + + @Override + protected JsonArray parseFromJson(InputStreamReader in) throws GitlabException { + return new Gson().fromJson(in, JsonArray.class); + } + }.run(monitor); + return jsonArray; + } + + public JsonObject getGroup(String path, IOperationMonitor monitor) throws GitlabException { + getAccessTokenIfNotPresent(monitor); + JsonObject jsonArray = new GitlabOperation(client, "/groups" + path) { + @Override + protected HttpRequestBase createHttpRequestBase(String url) { + HttpRequestBase request = new HttpGet(url); + return request; + } + + @Override + protected JsonObject parseFromJson(InputStreamReader in) throws GitlabException { + return new Gson().fromJson(in, JsonObject.class); + } + }.run(monitor); + return jsonArray; + } + + public JsonArray getSubGroups(String path, IOperationMonitor monitor) throws GitlabException { + getAccessTokenIfNotPresent(monitor); + JsonArray jsonArray = new GitlabJSonArrayOperation(client, "/groups" + path + "/subgroups?all_available=true") { + @Override + protected HttpRequestBase createHttpRequestBase(String url) { + HttpRequestBase request = new HttpGet(url); + return request; + } + + @Override + protected JsonArray parseFromJson(InputStreamReader in) throws GitlabException { + return new Gson().fromJson(in, JsonArray.class); + } + }.run(monitor); + return jsonArray; + } + + public JsonArray getDescendantGroups(String path, IOperationMonitor monitor) throws GitlabException { + getAccessTokenIfNotPresent(monitor); + JsonArray jsonArray = new GitlabJSonArrayOperation(client, + "/groups" + path + "/descendant_groups?all_available=true") { + @Override + protected HttpRequestBase createHttpRequestBase(String url) { + HttpRequestBase request = new HttpGet(url); + return request; + } + + @Override + protected JsonArray parseFromJson(InputStreamReader in) throws GitlabException { + return new Gson().fromJson(in, JsonArray.class); + } + }.run(monitor); + return jsonArray; + } + + public JsonObject getNamespace(String path, IOperationMonitor monitor) throws GitlabException { + getAccessTokenIfNotPresent(monitor); + JsonObject jsonObject = new GitlabOperation(client, "/namespaces" + path) { + @Override + protected HttpRequestBase createHttpRequestBase(String url) { + HttpRequestBase request = new HttpGet(url); + return request; + } + + @Override + protected JsonObject parseFromJson(InputStreamReader in) throws GitlabException { + return new Gson().fromJson(in, JsonObject.class); + } + }.run(monitor); + return jsonObject; + } + + public JsonArray getProjects(String path, IOperationMonitor monitor) throws GitlabException { + getAccessTokenIfNotPresent(monitor); + JsonArray jsonArray = new GitlabJSonArrayOperation(client, path + "/projects") { + @Override + protected HttpRequestBase createHttpRequestBase(String url) { + HttpRequestBase request = new HttpGet(url); + return request; + } + + @Override + protected JsonArray parseFromJson(InputStreamReader in) throws GitlabException { + return new Gson().fromJson(in, JsonArray.class); + } + }.run(monitor); + return jsonArray; + } + + public JsonObject getProject(String projectid, IOperationMonitor monitor) throws GitlabException { + getAccessTokenIfNotPresent(monitor); + JsonObject jsonArray = new GitlabOperation(client, "/projects/" + projectid) { + @Override + protected HttpRequestBase createHttpRequestBase(String url) { + HttpRequestBase request = new HttpGet(url); + return request; + } + + @Override + protected JsonObject parseFromJson(InputStreamReader in) throws GitlabException { + return new Gson().fromJson(in, JsonObject.class); + } + }.run(monitor); + return jsonArray; + } + + public JsonArray getGroupProjects(String projectid, IOperationMonitor monitor) throws GitlabException { + getAccessTokenIfNotPresent(monitor); + JsonArray jsonArray = new GitlabJSonArrayOperation(client, + "/groups/" + projectid + "/projects?include_subgroups=true") { + @Override + protected HttpRequestBase createHttpRequestBase(String url) { + HttpRequestBase request = new HttpGet(url); + return request; + } + + @Override + protected JsonArray parseFromJson(InputStreamReader in) throws GitlabException { + return new Gson().fromJson(in, JsonArray.class); + } + }.run(monitor); + return jsonArray; + } + + public JsonArray getIssues(String path, IOperationMonitor monitor) throws GitlabException { + getAccessTokenIfNotPresent(monitor); + JsonArray jsonArray = new GitlabJSonArrayOperation(client, path + "/issues") { + @Override + protected HttpRequestBase createHttpRequestBase(String url) { + HttpRequestBase request = new HttpGet(url); + return request; + } + + @Override + protected JsonArray parseFromJson(InputStreamReader in) throws GitlabException { + return new Gson().fromJson(in, JsonArray.class); + } + }.run(monitor); + return jsonArray; + } + + public JsonObject getIssue(String path, String id, IOperationMonitor monitor) throws GitlabException { + getAccessTokenIfNotPresent(monitor); + JsonObject jsonArray = new GitlabOperation(client, path + "/issues/" + id) { + @Override + protected HttpRequestBase createHttpRequestBase(String url) { + HttpRequestBase request = new HttpGet(url); + return request; + } + + @Override + protected JsonObject parseFromJson(InputStreamReader in) throws GitlabException { + return new Gson().fromJson(in, JsonObject.class); + } + }.run(monitor); + return jsonArray; + } + + public JsonArray getIssueNotes(String path, String id, IOperationMonitor monitor) throws GitlabException { + getAccessTokenIfNotPresent(monitor); + JsonArray jsonArray = new GitlabJSonArrayOperation(client, path + "/issues/" + id + "/notes?sort=asc") { + @Override + protected HttpRequestBase createHttpRequestBase(String url) { + HttpRequestBase request = new HttpGet(url); + return request; + } + + @Override + protected JsonArray parseFromJson(InputStreamReader in) throws GitlabException { + return new Gson().fromJson(in, JsonArray.class); + } + }.run(monitor); + return jsonArray; + } + + public GitlabConfiguration getConfiguration(TaskRepository repository, IOperationMonitor monitor) { + GitlabConfiguration config = new GitlabConfiguration(repository.getUrl()); + try { + JsonObject user = getUser(monitor); + config.setUserID(user.get("id").getAsBigInteger()); + config.setUserDetails(user); + JsonElement projects = getProjects("/users/" + config.getUserID(), monitor); + for (JsonElement project : (JsonArray) projects) { +// System.out.println(project.getAsJsonObject().get("name_with_namespace").getAsString()); + config.addProject(project); + } + String groupsValue = repository.getProperty(GitlabCoreActivator.GROUPS); + String[] groupList = groupsValue.split(","); + for (String group : groupList) { + JsonObject groupDetail = getGroup("/" + group, monitor); +// System.out.println(groupDetail.getAsJsonObject().get("full_path").getAsString()); + config.addGroup(groupDetail); + projects = getGroupProjects(group, monitor); + for (JsonElement project : (JsonArray) projects) { +// System.out.print(project.getAsJsonObject().get("id").getAsString()); +// System.out.print(" "); +// System.out.println(project.getAsJsonObject().get("name_with_namespace").getAsString()); + config.addProject(project); + } + } + } catch (GitlabException e) { + // TODO Auto-generated catch block + e.printStackTrace(); + } + return config; + } + +// public String getProjects(IOperationMonitor monitor) throws GitlabException { +// getAccessTokenIfNotPresent(monitor); +// Version versionInfo = new GitlabOperation(client, "/namespaces") { +//// Version versionInfo = new GitlabOperation(client, "/projects?membership=true") { +//// Version versionInfo = new GitlabOperation(client, "/projects?owned=true") { +// +// @Override +// protected HttpRequestBase createHttpRequestBase(String url) { +// HttpRequestBase request = new HttpGet(url); +// return request; +// } +// +// @Override +// protected Version parseFromJson(InputStreamReader in) throws GitlabException { +// String result = new BufferedReader(in) +// .lines().collect(Collectors.joining("\n")); +//// Gson gson = new GsonBuilder().setPrettyPrinting().create(); +// JsonArray convertedObject = new Gson().fromJson(result, JsonArray.class); +// Gson gson = new GsonBuilder().setPrettyPrinting().create(); +// String prettyJson = gson.toJson(convertedObject); +// TypeToken type = new TypeToken() { +// }; +// return new Gson().fromJson(result, type.getType()); +// } +// }.run(monitor); +// return versionInfo.getVersion(); +// } + +} diff --git a/mylyn.tasks/connectors/gitlab/org.eclipse.mylyn.gitlab.core/src/org/eclipse/mylyn/gitlab/core/GitlabTaskAttributeMapper.java b/mylyn.tasks/connectors/gitlab/org.eclipse.mylyn.gitlab.core/src/org/eclipse/mylyn/gitlab/core/GitlabTaskAttributeMapper.java new file mode 100644 index 0000000000..d26f897b13 --- /dev/null +++ b/mylyn.tasks/connectors/gitlab/org.eclipse.mylyn.gitlab.core/src/org/eclipse/mylyn/gitlab/core/GitlabTaskAttributeMapper.java @@ -0,0 +1,80 @@ +/******************************************************************************* + * Copyright (c) 2023 Frank Becker and others. + * + * This program and the accompanying materials are made available under the + * terms of the Eclipse Public License v. 2.0 which is available at + * https://www.eclipse.org/legal/epl-2.0 + * + * SPDX-License-Identifier: EPL-2.0 + * + * Contributors: + * Frank Becker - initial API and implementation + *******************************************************************************/ + +package org.eclipse.mylyn.gitlab.core; + +import java.text.ParseException; +import java.text.SimpleDateFormat; +import java.util.Date; + +import org.eclipse.mylyn.tasks.core.TaskRepository; +import org.eclipse.mylyn.tasks.core.data.TaskAttribute; +import org.eclipse.mylyn.tasks.core.data.TaskAttributeMapper; + +public class GitlabTaskAttributeMapper extends TaskAttributeMapper { + + private final GitlabRepositoryConnector connector; + + private static final String dateFormat_1 = "yyyy-MM-dd HH:mm:ss.sss"; //$NON-NLS-1$ + + private static final String dateFormat_2 = "yyyy-MM-dd HH:mm:ss"; //$NON-NLS-1$ + + private static final String dateFormat_3 = "yyyy-MM-dd HH:mm"; //$NON-NLS-1$ + + private static final String dateFormat_4 = "yyyy-MM-dd"; //$NON-NLS-1$ + + private static final String dateFormat_1_TimeZone = "yyyy-MM-dd'T'HH:mm:ss.SSS'Z'"; //$NON-NLS-1$ + + private static final String dateFormat_2_TimeZone = "yyyy-MM-dd'T'HH:mm:ss'Z'"; //$NON-NLS-1$ + + private static final String dateFormat_3_TimeZone = "yyyy-MM-dd'T'HH:mm'Z'"; //$NON-NLS-1$ + + private static final String dateFormat_4_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, dateFormat_4_TimeZone, dateFormat_4 }; + + public GitlabTaskAttributeMapper(TaskRepository taskRepository, GitlabRepositoryConnector 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); + } + + /** + * 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; + } + +} diff --git a/mylyn.tasks/connectors/gitlab/org.eclipse.mylyn.gitlab.core/src/org/eclipse/mylyn/gitlab/core/GitlabTaskDataHandler.java b/mylyn.tasks/connectors/gitlab/org.eclipse.mylyn.gitlab.core/src/org/eclipse/mylyn/gitlab/core/GitlabTaskDataHandler.java new file mode 100644 index 0000000000..d49b7ab990 --- /dev/null +++ b/mylyn.tasks/connectors/gitlab/org.eclipse.mylyn.gitlab.core/src/org/eclipse/mylyn/gitlab/core/GitlabTaskDataHandler.java @@ -0,0 +1,95 @@ +/******************************************************************************* + * Copyright (c) 2023 Frank Becker and others. + * + * This program and the accompanying materials are made available under the + * terms of the Eclipse Public License v. 2.0 which is available at + * https://www.eclipse.org/legal/epl-2.0 + * + * SPDX-License-Identifier: EPL-2.0 + * + * Contributors: + * Frank Becker - initial API and implementation + *******************************************************************************/ + +package org.eclipse.mylyn.gitlab.core; + +import java.util.Set; + +import org.eclipse.core.runtime.CoreException; +import org.eclipse.core.runtime.IProgressMonitor; +import org.eclipse.core.runtime.IStatus; +import org.eclipse.core.runtime.Status; +import org.eclipse.mylyn.commons.core.operations.IOperationMonitor; +import org.eclipse.mylyn.commons.core.operations.IOperationMonitor.OperationFlag; +import org.eclipse.mylyn.commons.core.operations.OperationUtil; +import org.eclipse.mylyn.commons.net.Policy; +import org.eclipse.mylyn.tasks.core.ITaskMapping; +import org.eclipse.mylyn.tasks.core.RepositoryResponse; +import org.eclipse.mylyn.tasks.core.TaskRepository; +import org.eclipse.mylyn.tasks.core.data.AbstractTaskDataHandler; +import org.eclipse.mylyn.tasks.core.data.TaskAttribute; +import org.eclipse.mylyn.tasks.core.data.TaskAttributeMapper; +import org.eclipse.mylyn.tasks.core.data.TaskData; +import org.eclipse.mylyn.tasks.core.data.TaskDataCollector; + +public class GitlabTaskDataHandler extends AbstractTaskDataHandler { + protected final GitlabRepositoryConnector connector; + + public GitlabTaskDataHandler(GitlabRepositoryConnector connector) { + super(); + this.connector = connector; + } + + @Override + public RepositoryResponse postTaskData(TaskRepository repository, TaskData taskData, + Set oldAttributes, IProgressMonitor monitor) throws CoreException { + // TODO Auto-generated method stub + return null; + } + + @Override + public boolean initializeTaskData(TaskRepository repository, TaskData data, ITaskMapping initializationData, + IProgressMonitor monitor) throws CoreException { + // Note: setting current version to latest assumes the data arriving + // here is either for a new task or is + // fresh from the repository (not locally stored data that may not have + // been migrated). + data.setVersion("0"); //$NON-NLS-1$ +// if (data.isNew()) { +// BugzillaRestCreateTaskSchema.getDefault().initialize(data); +// } else { +// BugzillaRestTaskSchema.getDefault().initialize(data); +// } + GitlabTaskSchema.getDefault().initialize(data); + if (initializationData != null) { + connector.getTaskMapping(data).merge(initializationData); + } + return true; + } + + @Override + public TaskAttributeMapper getAttributeMapper(TaskRepository repository) { + return new GitlabTaskAttributeMapper(repository, connector); + } + + @Override + public void getMultiTaskData(final TaskRepository repository, Set taskIds, + final TaskDataCollector collector, IProgressMonitor monitor) throws CoreException { + monitor = Policy.monitorFor(monitor); + try { + monitor.beginTask("retrive_task", IProgressMonitor.UNKNOWN); + GitlabRestClient client = connector.getClient(repository); + try { + IOperationMonitor progress = OperationUtil.convert(monitor, "post taskdata", 3); + progress.addFlag(OperationFlag.BACKGROUND); + client.getTaskData(taskIds, repository, collector, progress); + } catch (GitlabException e) { + throw new CoreException(new Status(IStatus.ERROR, GitlabCoreActivator.PLUGIN_ID, 2, + "Error get taskdata.\n\n" + e.getMessage(), e)); + } + } finally { + monitor.done(); + } + } + +} diff --git a/mylyn.tasks/connectors/gitlab/org.eclipse.mylyn.gitlab.core/src/org/eclipse/mylyn/gitlab/core/GitlabTaskSchema.java b/mylyn.tasks/connectors/gitlab/org.eclipse.mylyn.gitlab.core/src/org/eclipse/mylyn/gitlab/core/GitlabTaskSchema.java new file mode 100644 index 0000000000..23b401bc66 --- /dev/null +++ b/mylyn.tasks/connectors/gitlab/org.eclipse.mylyn.gitlab.core/src/org/eclipse/mylyn/gitlab/core/GitlabTaskSchema.java @@ -0,0 +1,140 @@ +/******************************************************************************* + * Copyright (c) 2023 Frank Becker and others. + * + * This program and the accompanying materials are made available under the + * terms of the Eclipse Public License v. 2.0 which is available at + * https://www.eclipse.org/legal/epl-2.0 + * + * SPDX-License-Identifier: EPL-2.0 + * + * Contributors: + * Frank Becker - initial API and implementation + *******************************************************************************/ + +package org.eclipse.mylyn.gitlab.core; + +import org.eclipse.mylyn.tasks.core.data.AbstractTaskSchema; +import org.eclipse.mylyn.tasks.core.data.DefaultTaskSchema; +import org.eclipse.mylyn.tasks.core.data.TaskAttribute; +import org.eclipse.mylyn.tasks.core.data.AbstractTaskSchema.Field; + +import com.google.common.collect.ImmutableMap; + +public class GitlabTaskSchema extends AbstractTaskSchema { + + private final DefaultTaskSchema parent = DefaultTaskSchema.getInstance(); + + private static final GitlabTaskSchema instance = new GitlabTaskSchema(); + + public static GitlabTaskSchema getDefault() { + return instance; + } + + public final Field PRODUCT = inheritFrom(parent.PRODUCT).addFlags(Flag.REQUIRED).create(); + + public final Field DESCRIPTION = inheritFrom(parent.DESCRIPTION).addFlags(Flag.REQUIRED).create(); + + public final Field SUMMARY = inheritFrom(parent.SUMMARY).addFlags(Flag.REQUIRED).create(); + + public final Field STATUS = inheritFrom(parent.STATUS).create(); + + public final Field ASSIGNED_TO = inheritFrom(parent.USER_ASSIGNED).label("Assigned to").create(); + + public final Field CREATED = inheritFrom(parent.DATE_CREATION).create(); + + public final Field UPDATED = inheritFrom(parent.DATE_MODIFICATION).create(); + + public final Field COMPLETED = inheritFrom(parent.DATE_COMPLETION).create(); + + public final Field AUTHOR = inheritFrom(parent.USER_REPORTER).create(); + + public final Field TASK_KEY = inheritFrom(parent.TASK_KEY).create(); + + public final Field URL = inheritFrom(parent.TASK_URL).addFlags(Flag.ATTRIBUTE).create(); + + public final Field PRIORITY = inheritFrom(parent.PRIORITY).create(); + + public final Field ISSUE_TYPE = createField("issue_type", "Issue Type", TaskAttribute.TYPE_SHORT_TEXT, + Flag.ATTRIBUTE); + + public final Field USER_NOTES_COUNT = createField("user_notes_count", "User Notes Count", + TaskAttribute.TYPE_INTEGER, Flag.ATTRIBUTE); + + public final Field BLOCKING_ISSUE_COUNT = createField("blocking_issues_count", "Blocking Issue Count", + TaskAttribute.TYPE_INTEGER, Flag.ATTRIBUTE); + + public final Field MERGE_REQUEST_COUNT = createField("merge_requests_count", "Merge Request Count", + TaskAttribute.TYPE_INTEGER, Flag.ATTRIBUTE); + + public final Field UPVOTES = createField("upvotes", "Up Votes", TaskAttribute.TYPE_INTEGER, Flag.ATTRIBUTE); + + public final Field DOWNVOTES = createField("downvotes", "Down Notes", TaskAttribute.TYPE_INTEGER, Flag.ATTRIBUTE); + + public final Field TYPE = createField("type", "Type", TaskAttribute.TYPE_SHORT_TEXT, Flag.ATTRIBUTE); + +// public final Field WEB_URL = createField("web_url", "WEB URL", TaskAttribute.TYPE_SHORT_TEXT, Flag.ATTRIBUTE); + + public final Field TASK_STATUS = createField("task_status", "Task Status", TaskAttribute.TYPE_SHORT_TEXT, + Flag.ATTRIBUTE); + + public final Field HAS_TASKS = createField("has_tasks", "has Tasks", TaskAttribute.TYPE_BOOLEAN, Flag.ATTRIBUTE); + + public final Field SUBSCRIBED = createField("subscribed", "subscribed", TaskAttribute.TYPE_BOOLEAN, Flag.ATTRIBUTE); + + public final Field CONFIDENTIAL = createField("confidential", "confidential", TaskAttribute.TYPE_BOOLEAN, + Flag.ATTRIBUTE); + + + public final Field DISCUSSION_LOCKED = createField("discussion_locked", "Discussion locked", + TaskAttribute.TYPE_BOOLEAN, Flag.ATTRIBUTE); + + public final Field GROUP = createField("group", "Group", TaskAttribute.TYPE_SHORT_TEXT); + + private static ImmutableMap json2AttributeMapper = new ImmutableMap.Builder() + .put("project_id", getDefault().PRODUCT.getKey()) //$NON-NLS-1$ + .put("description", getDefault().DESCRIPTION.getKey()) //$NON-NLS-1$ + .put("title", getDefault().SUMMARY.getKey()) //$NON-NLS-1$ + .put("state", getDefault().STATUS.getKey()) //$NON-NLS-1$ + .put("assignee", getDefault().ASSIGNED_TO.getKey()) //$NON-NLS-1$ + .put("author", getDefault().AUTHOR.getKey()) //$NON-NLS-1$ + .put("id", getDefault().TASK_KEY.getKey()) //$NON-NLS-1$ + .put("severity", getDefault().PRIORITY.getKey()) //$NON-NLS-1$ + .put("created_at", getDefault().CREATED.getKey()) //$NON-NLS-1$ + .put("updated_at", getDefault().UPDATED.getKey()) //$NON-NLS-1$ + .put("closed_at", getDefault().COMPLETED.getKey()) //$NON-NLS-1$ + .put("web_url", getDefault().URL.getKey()) //$NON-NLS-1$ + + .build(); + + private static ImmutableMap attribute2jsonMapper = new ImmutableMap.Builder() + .put(getDefault().PRODUCT.getKey(), "project_id") //$NON-NLS-1$ + .put(getDefault().DESCRIPTION.getKey(), "description") //$NON-NLS-1$ + .put(getDefault().SUMMARY.getKey(), "title") //$NON-NLS-1$ + .put(getDefault().STATUS.getKey(), "state") //$NON-NLS-1$ + .put(getDefault().ASSIGNED_TO.getKey(), "assignee") //$NON-NLS-1$ + .put(getDefault().AUTHOR.getKey(), "author") //$NON-NLS-1$ + .put(getDefault().TASK_KEY.getKey(), "id") //$NON-NLS-1$ + .put(getDefault().PRIORITY.getKey(), "severity") //$NON-NLS-1$ + .put(getDefault().CREATED.getKey(), "created_at") //$NON-NLS-1$ + .put(getDefault().UPDATED.getKey(), "updated_at") //$NON-NLS-1$ + .put(getDefault().COMPLETED.getKey(), "closed_at") //$NON-NLS-1$ + .put(getDefault().URL.getKey(), "web_url") //$NON-NLS-1$ + .build(); + + public static String getAttributeNameFromJsonName(String fieldName) { + String result = json2AttributeMapper.get(fieldName); + if (result == null) { + result = fieldName; + } + return result; + } + + public static String getJsonNameFromAttributeName(String attributeName) { + String result = attribute2jsonMapper.get(attributeName); + if (result == null) { + result = attributeName; + } + return result; + } + +} diff --git a/mylyn.tasks/connectors/gitlab/org.eclipse.mylyn.gitlab.feature/.project b/mylyn.tasks/connectors/gitlab/org.eclipse.mylyn.gitlab.feature/.project new file mode 100644 index 0000000000..b5a213cd68 --- /dev/null +++ b/mylyn.tasks/connectors/gitlab/org.eclipse.mylyn.gitlab.feature/.project @@ -0,0 +1,17 @@ + + + org.eclipse.mylyn.gitlab.feature + + + + + + org.eclipse.pde.FeatureBuilder + + + + + + org.eclipse.pde.FeatureNature + + diff --git a/mylyn.tasks/connectors/gitlab/org.eclipse.mylyn.gitlab.feature/.settings/org.eclipse.core.resources.prefs b/mylyn.tasks/connectors/gitlab/org.eclipse.mylyn.gitlab.feature/.settings/org.eclipse.core.resources.prefs new file mode 100644 index 0000000000..99f26c0203 --- /dev/null +++ b/mylyn.tasks/connectors/gitlab/org.eclipse.mylyn.gitlab.feature/.settings/org.eclipse.core.resources.prefs @@ -0,0 +1,2 @@ +eclipse.preferences.version=1 +encoding/=UTF-8 diff --git a/mylyn.tasks/connectors/gitlab/org.eclipse.mylyn.gitlab.feature/build.properties b/mylyn.tasks/connectors/gitlab/org.eclipse.mylyn.gitlab.feature/build.properties new file mode 100644 index 0000000000..64f93a9f0b --- /dev/null +++ b/mylyn.tasks/connectors/gitlab/org.eclipse.mylyn.gitlab.feature/build.properties @@ -0,0 +1 @@ +bin.includes = feature.xml diff --git a/mylyn.tasks/connectors/gitlab/org.eclipse.mylyn.gitlab.feature/feature.xml b/mylyn.tasks/connectors/gitlab/org.eclipse.mylyn.gitlab.feature/feature.xml new file mode 100644 index 0000000000..04b41d39b2 --- /dev/null +++ b/mylyn.tasks/connectors/gitlab/org.eclipse.mylyn.gitlab.feature/feature.xml @@ -0,0 +1,35 @@ + + + + + [Enter Feature Description here.] + + + + [Enter Copyright Description here.] + + + + [Enter License Description here.] + + + + + + + diff --git a/mylyn.tasks/connectors/gitlab/org.eclipse.mylyn.gitlab.ui/.classpath b/mylyn.tasks/connectors/gitlab/org.eclipse.mylyn.gitlab.ui/.classpath new file mode 100644 index 0000000000..81fe078c20 --- /dev/null +++ b/mylyn.tasks/connectors/gitlab/org.eclipse.mylyn.gitlab.ui/.classpath @@ -0,0 +1,7 @@ + + + + + + + diff --git a/mylyn.tasks/connectors/gitlab/org.eclipse.mylyn.gitlab.ui/.project b/mylyn.tasks/connectors/gitlab/org.eclipse.mylyn.gitlab.ui/.project new file mode 100644 index 0000000000..8688c7258b --- /dev/null +++ b/mylyn.tasks/connectors/gitlab/org.eclipse.mylyn.gitlab.ui/.project @@ -0,0 +1,28 @@ + + + org.eclipse.mylyn.gitlab.ui + + + + + + org.eclipse.jdt.core.javabuilder + + + + + org.eclipse.pde.ManifestBuilder + + + + + org.eclipse.pde.SchemaBuilder + + + + + + org.eclipse.pde.PluginNature + org.eclipse.jdt.core.javanature + + diff --git a/mylyn.tasks/connectors/gitlab/org.eclipse.mylyn.gitlab.ui/.settings/org.eclipse.core.resources.prefs b/mylyn.tasks/connectors/gitlab/org.eclipse.mylyn.gitlab.ui/.settings/org.eclipse.core.resources.prefs new file mode 100644 index 0000000000..99f26c0203 --- /dev/null +++ b/mylyn.tasks/connectors/gitlab/org.eclipse.mylyn.gitlab.ui/.settings/org.eclipse.core.resources.prefs @@ -0,0 +1,2 @@ +eclipse.preferences.version=1 +encoding/=UTF-8 diff --git a/mylyn.tasks/connectors/gitlab/org.eclipse.mylyn.gitlab.ui/.settings/org.eclipse.jdt.core.prefs b/mylyn.tasks/connectors/gitlab/org.eclipse.mylyn.gitlab.ui/.settings/org.eclipse.jdt.core.prefs new file mode 100644 index 0000000000..62ef3488cc --- /dev/null +++ b/mylyn.tasks/connectors/gitlab/org.eclipse.mylyn.gitlab.ui/.settings/org.eclipse.jdt.core.prefs @@ -0,0 +1,9 @@ +eclipse.preferences.version=1 +org.eclipse.jdt.core.compiler.codegen.targetPlatform=17 +org.eclipse.jdt.core.compiler.compliance=17 +org.eclipse.jdt.core.compiler.problem.assertIdentifier=error +org.eclipse.jdt.core.compiler.problem.enablePreviewFeatures=disabled +org.eclipse.jdt.core.compiler.problem.enumIdentifier=error +org.eclipse.jdt.core.compiler.problem.reportPreviewFeatures=warning +org.eclipse.jdt.core.compiler.release=enabled +org.eclipse.jdt.core.compiler.source=17 diff --git a/mylyn.tasks/connectors/gitlab/org.eclipse.mylyn.gitlab.ui/META-INF/MANIFEST.MF b/mylyn.tasks/connectors/gitlab/org.eclipse.mylyn.gitlab.ui/META-INF/MANIFEST.MF new file mode 100644 index 0000000000..91d455a60c --- /dev/null +++ b/mylyn.tasks/connectors/gitlab/org.eclipse.mylyn.gitlab.ui/META-INF/MANIFEST.MF @@ -0,0 +1,21 @@ +Manifest-Version: 1.0 +Bundle-ManifestVersion: 2 +Bundle-Name: Gitlab Connector UI +Bundle-SymbolicName: org.eclipse.mylyn.gitlab.ui;singleton:=true +Bundle-Version: 3.26.1.qualifier +Export-Package: org.eclipse.mylyn.gitlab.ui +Bundle-Activator: org.eclipse.mylyn.gitlab.ui.GitlabUiActivator +Require-Bundle: org.eclipse.ui, + org.eclipse.core.runtime, + org.eclipse.mylyn.tasks.ui, + org.eclipse.mylyn.tasks.core, + org.eclipse.ui.forms;bundle-version="3.11.500", + org.eclipse.mylyn.gitlab.core;bundle-version="1.0.0", + com.google.guava, + org.eclipse.mylyn.commons.workbench;bundle-version="3.26.0", + org.eclipse.mylyn.commons.ui;bundle-version="3.26.0", + org.eclipse.mylyn.commons.core;bundle-version="3.26.1", + org.eclipse.jdt.annotation +Bundle-RequiredExecutionEnvironment: JavaSE-17 +Automatic-Module-Name: org.eclipse.mylyn.gitlab.ui +Bundle-ActivationPolicy: lazy diff --git a/mylyn.tasks/connectors/gitlab/org.eclipse.mylyn.gitlab.ui/build.properties b/mylyn.tasks/connectors/gitlab/org.eclipse.mylyn.gitlab.ui/build.properties new file mode 100644 index 0000000000..e9863e281e --- /dev/null +++ b/mylyn.tasks/connectors/gitlab/org.eclipse.mylyn.gitlab.ui/build.properties @@ -0,0 +1,5 @@ +source.. = src/ +output.. = bin/ +bin.includes = META-INF/,\ + .,\ + plugin.xml diff --git a/mylyn.tasks/connectors/gitlab/org.eclipse.mylyn.gitlab.ui/icons/eview16/gitlab-icon.gif b/mylyn.tasks/connectors/gitlab/org.eclipse.mylyn.gitlab.ui/icons/eview16/gitlab-icon.gif new file mode 100644 index 0000000000000000000000000000000000000000..f2847251a6b46deb8691dd6bbfbe6eab76437bb4 GIT binary patch literal 1431 zcmc)Ji$Bu|008jc)@JjF%{FXJjcv9xk2UiMnZj5^GbJQW%)5znDP8j}aIi7 zVV>8g>*oC`&xt&u7b!%mJi6T7Uvc06;mdY%Ft_k00t8@w0sue&00tC600;trp&$qh z4245ricnP;6s`Rz;|&A$KCw)sQHJIvR;WtD`X}O$}9y1{$M@*3iOe zYH47#kT@Jl8;8Z=vAgg%ZM+74H(q-Wo~%P45w(dVT{3w$iA*Hvk;oJhg+icGbo8iX z3RQ0}RY#w;mqsJ+Gtf6Mq!}6+>^C$pG&V4z8`A0ebcXSM2Hk`~W0>q`Fd0myp@}Jj zX=Y+-&a^Z$HM20awlq3mX>q{H!rI2_Aj{f@b*OdANHV=XrZ^y?jpk`0!4h_VM*Qb=u$8 zKfv!yfX|u0fWV+LLHs~|a8PgvKRA>h9u^Q99ugK28Xg%IaW*_s5OFptQgH5U^tsTO z*y!^YVq$+hf8kSp_*+IeFQ+`8j!_-28$(QDJ^Tk*M%yK~ZsGaY@mgTcx*tE-e$^y8Vmz zZuzg}mA_ToE3d4oxK~|S`#@YP`Ms{bR?<+{)byaCslKtfp{b?u;UBeswf-q>d)(SC zZR=?5=xXom?&#|2?C$Lv=+-J~U)DFjZfvb@e%sjk zd-L1&*7xmi+y4ih4G2gH*am38zy3P`z`q0Af$QuVu{05mQs>PH#mQF3(Yrsi9@dpA z#K<8!o`9mM0}QR;=0={-hk?*zX&ugX&;(0xOshkBiWKFnHP_mi$FH(+;GjzdDU>}B z5Lul}vTAudm6gP&s~$z8r_i&=I&~PpeAqh{T5ALv_uFEC(`@yG z#jG@A$^92)H^6d#!d?UWHSdgQ@ zL%kRZR-#$kyW0U4-M4!ZwapVV3C&W(HEgy=M;@(cmgRFLe*2&qU(w+UO=#M8R5Y;mVKeMX5Ne z)r4fhiKPTEK7v4!QvGWL%HAEG4I199%~v}qY9vUqiB&hS(>t45=crp*FWQ0Z3?>X| z_gB=kM;#9oPJ%=}_L&I6=*vWV(5y}$=tMr>gW#Hf&V%Vq^;5!XV0ezSsFMLAW^9=k zlMOUi=Y-mVwC*?o*D~T{1dw@d$9>qvAvSPzJqC&jQfWgGLH(U39v2&(5FeA2l#rK~Q(jtF zQ&rL0($vw>(bL^EapHuTGiNSZv}oDV#j97X+^~NA)~#C(9N2&G;J(9$4qUi!{?esO z*REZ?bNkNSJ9qBgyZiCOhi~7${rLIg_wV2T{{8#^ABd<46o0ZXaxvI5=r8~Q$WIJx zh6fJib4V&N^-eg+QpMvb9qeiRD^R7SgZaQr10xl0*OtgXBJ;eTPnP({=G|DGVX>o` G!5RRvAglEN literal 0 HcmV?d00001 diff --git a/mylyn.tasks/connectors/gitlab/org.eclipse.mylyn.gitlab.ui/plugin.xml b/mylyn.tasks/connectors/gitlab/org.eclipse.mylyn.gitlab.ui/plugin.xml new file mode 100644 index 0000000000..8bb9a1c362 --- /dev/null +++ b/mylyn.tasks/connectors/gitlab/org.eclipse.mylyn.gitlab.ui/plugin.xml @@ -0,0 +1,34 @@ + + + + + + + + + + + + + + diff --git a/mylyn.tasks/connectors/gitlab/org.eclipse.mylyn.gitlab.ui/src/org/eclipse/mylyn/gitlab/ui/GitlabConnectorUI.java b/mylyn.tasks/connectors/gitlab/org.eclipse.mylyn.gitlab.ui/src/org/eclipse/mylyn/gitlab/ui/GitlabConnectorUI.java new file mode 100644 index 0000000000..595ca8fb0f --- /dev/null +++ b/mylyn.tasks/connectors/gitlab/org.eclipse.mylyn.gitlab.ui/src/org/eclipse/mylyn/gitlab/ui/GitlabConnectorUI.java @@ -0,0 +1,81 @@ +/******************************************************************************* + * Copyright (c) 2023 Frank Becker and others. + * + * This program and the accompanying materials are made available under the + * terms of the Eclipse Public License v. 2.0 which is available at + * https://www.eclipse.org/legal/epl-2.0 + * + * SPDX-License-Identifier: EPL-2.0 + * + * Contributors: + * Frank Becker - initial API and implementation + *******************************************************************************/ + +package org.eclipse.mylyn.gitlab.ui; + +import org.eclipse.core.runtime.CoreException; +import org.eclipse.jface.wizard.IWizard; +import org.eclipse.mylyn.gitlab.core.GitlabConfiguration; +import org.eclipse.mylyn.gitlab.core.GitlabCoreActivator; +import org.eclipse.mylyn.gitlab.core.GitlabRepositoryConnector; +import org.eclipse.mylyn.gitlab.core.GitlabTaskAttributeMapper; +import org.eclipse.mylyn.internal.provisional.tasks.ui.wizards.QueryPageDetails; +import org.eclipse.mylyn.tasks.core.IRepositoryQuery; +import org.eclipse.mylyn.tasks.core.ITaskMapping; +import org.eclipse.mylyn.tasks.core.TaskRepository; +import org.eclipse.mylyn.tasks.core.data.TaskData; +import org.eclipse.mylyn.tasks.ui.AbstractRepositoryConnectorUi; +import org.eclipse.mylyn.tasks.ui.wizards.ITaskRepositoryPage; +import org.eclipse.mylyn.tasks.ui.wizards.NewTaskWizard; +import org.eclipse.mylyn.tasks.ui.wizards.RepositoryQueryWizard; + +public class GitlabConnectorUI extends AbstractRepositoryConnectorUi { + + @Override + public String getConnectorKind() { + return GitlabCoreActivator.CONNECTOR_KIND; + } + + @Override + public ITaskRepositoryPage getSettingsPage(TaskRepository repository) { + return new GitlabRepositorySettingsPage("New repository", "Enter the HTTPS-URL to your GitLab repository", + repository); + } + + @Override + public IWizard getQueryWizard(TaskRepository repository, IRepositoryQuery query) { + RepositoryQueryWizard wizard = new RepositoryQueryWizard(repository); + GitlabRepositoryConnector connector = (GitlabRepositoryConnector) getConnector(); + TaskData taskData = new TaskData( + new GitlabTaskAttributeMapper(repository, connector), + repository.getConnectorKind(), "Query", "Query"); //$NON-NLS-1$ //$NON-NLS-2$ + GitlabSearchQueryPageSchema.getInstance().initialize(taskData); + try { + GitlabConfiguration config = connector.getRepositoryConfiguration(repository); + config.updateProductOptions(taskData); + } catch (CoreException e) { + // TODO Auto-generated catch block + e.printStackTrace(); + } + GitlabQuerySchemaPage mp = new GitlabQuerySchemaPage(getConnectorKind(), repository, query, + GitlabSearchQueryPageSchema.getInstance(), taskData, + new QueryPageDetails(true, "", "EnterQueryParameter", //$NON-NLS-1$ + "EnterTitleAndURL", "([a-zA-Z][a-zA-Z+.-]{0,10}://[a-zA-Z0-9%._~!$&?#'()*+,;:@/=-]+)", + null)); + wizard.addPage(mp); + + return wizard; + } + + @Override + public IWizard getNewTaskWizard(TaskRepository repository, ITaskMapping selection) { + return new NewTaskWizard(repository, selection); + } + + @Override + public boolean hasSearchPage() { + // TODO Auto-generated method stub + return false; + } + +} diff --git a/mylyn.tasks/connectors/gitlab/org.eclipse.mylyn.gitlab.ui/src/org/eclipse/mylyn/gitlab/ui/GitlabQuerySchemaPage.java b/mylyn.tasks/connectors/gitlab/org.eclipse.mylyn.gitlab.ui/src/org/eclipse/mylyn/gitlab/ui/GitlabQuerySchemaPage.java new file mode 100644 index 0000000000..42d4aa340a --- /dev/null +++ b/mylyn.tasks/connectors/gitlab/org.eclipse.mylyn.gitlab.ui/src/org/eclipse/mylyn/gitlab/ui/GitlabQuerySchemaPage.java @@ -0,0 +1,65 @@ +package org.eclipse.mylyn.gitlab.ui; + +import java.util.Arrays; +import java.util.List; +import java.util.Map.Entry; +import java.util.Optional; + +import org.eclipse.jdt.annotation.NonNull; +import org.eclipse.mylyn.gitlab.core.GitlabTaskSchema; +import org.eclipse.mylyn.internal.provisional.tasks.ui.wizards.AbstractQueryPageSchema; +import org.eclipse.mylyn.internal.provisional.tasks.ui.wizards.QueryPageDetails; +import org.eclipse.mylyn.internal.provisional.tasks.ui.wizards.RepositoryQuerySchemaPage; +import org.eclipse.mylyn.internal.tasks.ui.editors.MultiSelectionAttributeEditor; +import org.eclipse.mylyn.tasks.core.IRepositoryQuery; +import org.eclipse.mylyn.tasks.core.TaskRepository; +import org.eclipse.mylyn.tasks.core.data.TaskAttribute; +import org.eclipse.mylyn.tasks.core.data.TaskData; +import org.eclipse.mylyn.tasks.ui.editors.AbstractAttributeEditor; + +public class GitlabQuerySchemaPage extends RepositoryQuerySchemaPage { + + public GitlabQuerySchemaPage(String pageName, TaskRepository repository, IRepositoryQuery query, + AbstractQueryPageSchema schema, TaskData data, QueryPageDetails pageDetails) { + super(pageName, repository, query, schema, data, pageDetails); + } + + private void updateTaskDataFromGroup(TaskData taskData, IRepositoryQuery query, String key) { + + TaskAttribute productAttribute = taskData.getRoot().getAttribute(key); + productAttribute.setValues(Arrays.asList( + Optional.ofNullable(query.getAttribute(key)).map(st -> st.split(",")).orElse(new String[] { "" }))); + + } + + @Override + protected boolean restoreState(@NonNull IRepositoryQuery query) { + TaskData taskData = getTargetTaskData(); + for (String entry : editorMap.keySet()) { + updateTaskDataFromGroup(taskData, query, entry); + } + + doRefreshControls(); + return true; + } + + @Override + public void applyTo(IRepositoryQuery query) { + query.setSummary(this.getQueryTitle()); + query.setUrl(getQueryUrl(getTaskRepository().getRepositoryUrl())); + for (Entry entry : editorMap.entrySet()) { + if (entry.getValue() instanceof MultiSelectionAttributeEditor) + query.setAttribute(entry.getKey(), + String.join(",", ((MultiSelectionAttributeEditor) entry.getValue()).getValues())); + else + query.setAttribute(entry.getKey(), entry.getValue().getTaskAttribute().getValue()); + } + } + + @Override + protected void doRefreshControls() { + for (Entry entry : editorMap.entrySet()) { + entry.getValue().refresh(); + } + } +} diff --git a/mylyn.tasks/connectors/gitlab/org.eclipse.mylyn.gitlab.ui/src/org/eclipse/mylyn/gitlab/ui/GitlabQueryTypeWizardPage.java b/mylyn.tasks/connectors/gitlab/org.eclipse.mylyn.gitlab.ui/src/org/eclipse/mylyn/gitlab/ui/GitlabQueryTypeWizardPage.java new file mode 100644 index 0000000000..c9fe8821f6 --- /dev/null +++ b/mylyn.tasks/connectors/gitlab/org.eclipse.mylyn.gitlab.ui/src/org/eclipse/mylyn/gitlab/ui/GitlabQueryTypeWizardPage.java @@ -0,0 +1,72 @@ +/******************************************************************************* + * Copyright (c) 2023 Frank Becker and others. + * + * This program and the accompanying materials are made available under the + * terms of the Eclipse Public License v. 2.0 which is available at + * https://www.eclipse.org/legal/epl-2.0 + * + * SPDX-License-Identifier: EPL-2.0 + * + * Contributors: + * Frank Becker - initial API and implementation + *******************************************************************************/ + +package org.eclipse.mylyn.gitlab.ui; + +import org.eclipse.jface.dialogs.Dialog; +import org.eclipse.jface.wizard.IWizardPage; +import org.eclipse.jface.wizard.WizardPage; +import org.eclipse.mylyn.internal.provisional.tasks.ui.wizards.AbstractQueryPageSchema; +import org.eclipse.mylyn.internal.provisional.tasks.ui.wizards.QueryPageDetails; +import org.eclipse.mylyn.internal.provisional.tasks.ui.wizards.RepositoryQuerySchemaPage; +import org.eclipse.mylyn.tasks.core.AbstractRepositoryConnector; +import org.eclipse.mylyn.tasks.core.IRepositoryQuery; +import org.eclipse.mylyn.tasks.core.TaskRepository; +import org.eclipse.mylyn.tasks.core.data.TaskData; +import org.eclipse.mylyn.tasks.ui.TasksUiImages; +import org.eclipse.mylyn.tasks.ui.wizards.AbstractRepositoryQueryPage; +import org.eclipse.mylyn.tasks.ui.wizards.AbstractRepositoryQueryPage2; +import org.eclipse.osgi.util.NLS; +import org.eclipse.swt.SWT; +import org.eclipse.swt.layout.GridData; +import org.eclipse.swt.layout.GridLayout; +import org.eclipse.swt.widgets.Button; +import org.eclipse.swt.widgets.Composite; +public class GitlabQueryTypeWizardPage extends WizardPage { + + + private Button buttonCustom; + + private Button buttonForm; + + private Composite composite; + + public GitlabQueryTypeWizardPage(TaskRepository repository, AbstractRepositoryConnector connector) { + super("Super"); + setTitle("Title"); + setDescription("Desc"); + setImageDescriptor(TasksUiImages.BANNER_REPOSITORY); + } + + @Override + public void createControl(Composite parent) { + composite = new Composite(parent, SWT.NONE); + GridData gridData = new GridData(GridData.FILL_HORIZONTAL); + gridData.grabExcessVerticalSpace = false; + composite.setLayoutData(gridData); + composite.setLayout(new GridLayout(1, false)); + + buttonForm = new Button(composite, SWT.RADIO); + buttonForm.setText("Messages.BugzillaRestQueryTypeWizardPage_CreateQueryUsingForm"); + buttonForm.setSelection(true); + + buttonCustom = new Button(composite, SWT.RADIO); + buttonCustom.setText("Messages.BugzillaRestQueryTypeWizardPage_CreateQueryFromExistingURL"); + + setPageComplete(true); + setControl(composite); + Dialog.applyDialogFont(composite); + } + + +} diff --git a/mylyn.tasks/connectors/gitlab/org.eclipse.mylyn.gitlab.ui/src/org/eclipse/mylyn/gitlab/ui/GitlabRepositorySettingsPage.java b/mylyn.tasks/connectors/gitlab/org.eclipse.mylyn.gitlab.ui/src/org/eclipse/mylyn/gitlab/ui/GitlabRepositorySettingsPage.java new file mode 100644 index 0000000000..0f287e38c4 --- /dev/null +++ b/mylyn.tasks/connectors/gitlab/org.eclipse.mylyn.gitlab.ui/src/org/eclipse/mylyn/gitlab/ui/GitlabRepositorySettingsPage.java @@ -0,0 +1,261 @@ +/******************************************************************************* + * Copyright (c) 2023 Frank Becker and others. + * + * This program and the accompanying materials are made available under the + * terms of the Eclipse Public License v. 2.0 which is available at + * https://www.eclipse.org/legal/epl-2.0 + * + * SPDX-License-Identifier: EPL-2.0 + * + * Contributors: + * Frank Becker - initial API and implementation + *******************************************************************************/ + +package org.eclipse.mylyn.gitlab.ui; + +import java.util.ArrayList; +import java.util.Arrays; + +import org.eclipse.jface.layout.GridDataFactory; +import org.eclipse.jface.layout.GridLayoutFactory; +import org.eclipse.jface.viewers.ArrayContentProvider; +import org.eclipse.jface.viewers.ISelectionChangedListener; +import org.eclipse.jface.viewers.IStructuredSelection; +import org.eclipse.jface.viewers.LabelProvider; +import org.eclipse.jface.viewers.ListViewer; +import org.eclipse.jface.viewers.SelectionChangedEvent; +import org.eclipse.jface.viewers.StructuredSelection; +import org.eclipse.mylyn.gitlab.core.GitlabCoreActivator; +import org.eclipse.mylyn.internal.tasks.ui.TasksUiPlugin; +import org.eclipse.mylyn.tasks.core.TaskRepository; +import org.eclipse.mylyn.tasks.ui.wizards.AbstractRepositorySettingsPage; +import org.eclipse.swt.SWT; +import org.eclipse.swt.events.KeyAdapter; +import org.eclipse.swt.events.KeyEvent; +import org.eclipse.swt.events.SelectionAdapter; +import org.eclipse.swt.events.SelectionEvent; +import org.eclipse.swt.layout.GridData; +import org.eclipse.swt.widgets.Button; +import org.eclipse.swt.widgets.Composite; +import org.eclipse.swt.widgets.Label; +import org.eclipse.swt.widgets.Text; +import org.eclipse.ui.forms.widgets.FormToolkit; + +public class GitlabRepositorySettingsPage extends AbstractRepositorySettingsPage { + + private ListViewer groups; + private ArrayList groupList = new ArrayList<>(); + private Text groupInput; + private Button groupRemoveButton; + private Button groupAddButton; + + private ListViewer projects; + private ArrayList projectList = new ArrayList<>(); + private Text projectInput; + private Button projectRemoveButton; + private Button projectAddButton; + + public GitlabRepositorySettingsPage(String title, String description, TaskRepository taskRepository) { + super(title, description, taskRepository); + setNeedsRepositoryCredentials(true); // setNeedsRepositoryCredentials(true); + setNeedsAnonymousLogin(false); // setNeedsAnonymousLogin(false); + setNeedsEncoding(false); // setNeedsEncoding(true); + setNeedsTimeZone(false); // setNeedsTimeZone(true); + setNeedsProxy(false); // setNeedsProxy(true); + setNeedsValidation(true); // setNeedsValidation(true); + setNeedsAdvanced(true); // setNeedsAdvanced(true); + setNeedsValidateOnFinish(false); // setNeedsValidateOnFinish(false); + } + + @Override + public String getConnectorKind() { + return GitlabCoreActivator.CONNECTOR_KIND; + } + + @Override + protected void createAdditionalControls(Composite parent) { + FormToolkit toolkit = new FormToolkit(TasksUiPlugin.getDefault().getFormColors(parent.getDisplay())); + Composite aditionalContainer = new Composite(parent, SWT.NONE); + GridLayoutFactory.fillDefaults().margins(0, 0).numColumns(3).applyTo(aditionalContainer); + GridDataFactory.fillDefaults().grab(true, true).align(SWT.FILL, SWT.FILL).applyTo(aditionalContainer); +// aditionalContainer.setBackground(new Color(aditionalContainer.getDisplay(), 0, 255, 0)); + + Label groupsLabel = new Label(aditionalContainer, SWT.NONE); + groupsLabel.setText("include Groups"); + GridData gd = new GridData(GridData.VERTICAL_ALIGN_CENTER); + gd.horizontalSpan = 1; + gd.verticalSpan = 3; + groupsLabel.setLayoutData(gd); + groups = new ListViewer(aditionalContainer, SWT.H_SCROLL | SWT.V_SCROLL); + gd = new GridData(GridData.FILL_BOTH); + gd.horizontalSpan = 1; + gd.verticalSpan = 3; + gd.grabExcessHorizontalSpace = true; + groups.getList().setLayoutData(gd); + groups.setLabelProvider(new LabelProvider()); + groups.setContentProvider(ArrayContentProvider.getInstance()); + if (repository != null) { + String groupsValue = repository.getProperty(GitlabCoreActivator.GROUPS); + if (groupsValue != null) + groupList = new ArrayList(Arrays.asList(groupsValue.split(","))); + } + groups.setInput(groupList); + groupInput = new Text(aditionalContainer, SWT.NONE); + gd = new GridData(GridData.HORIZONTAL_ALIGN_BEGINNING); + gd.widthHint = 200; + groupInput.setLayoutData(gd); + groupInput.addKeyListener(new KeyAdapter() { + + @Override + public void keyReleased(KeyEvent e) { + super.keyReleased(e); + updateUIEnablement(); + } + + }); + groups.addSelectionChangedListener(new ISelectionChangedListener() { + + @Override + public void selectionChanged(SelectionChangedEvent event) { + IStructuredSelection selection = (IStructuredSelection) event.getSelection(); + if (selection.size() > 0) { + groupInput.setText((String) selection.getFirstElement()); + } + updateUIEnablement(); + } + }); +// groupInput.setBackground(new Color(aditionalContainer.getDisplay(), 255, 0 , 0)); + + groupAddButton = new Button(aditionalContainer, SWT.PUSH); + groupAddButton.setText("Add"); + groupAddButton.addSelectionListener(new SelectionAdapter() { + @Override + public void widgetSelected(SelectionEvent e) { + groupList.add(groupInput.getText()); + groupInput.setText(""); + groups.refresh(); + updateUIEnablement(); + } + }); + + groupRemoveButton = new Button(aditionalContainer, SWT.PUSH); + groupRemoveButton.setText("remove"); + groupRemoveButton.addSelectionListener(new SelectionAdapter() { + @Override + public void widgetSelected(SelectionEvent e) { + IStructuredSelection selection = (IStructuredSelection) groups.getSelection(); + int lastIdx = -1; + if (selection != null) { + Object firstElement = selection.getFirstElement(); + lastIdx = groupList.indexOf(firstElement); + } + groupList.remove(groupInput.getText()); + groupInput.setText(""); + groups.refresh(); + if (lastIdx >= 0 && lastIdx < groupList.size()) { + groups.setSelection(new StructuredSelection(groupList.get(lastIdx)), true); + } + updateUIEnablement(); + } + }); + + Label projectsLabel = new Label(aditionalContainer, SWT.NONE); + projectsLabel.setText("include Projects"); + gd = new GridData(GridData.VERTICAL_ALIGN_CENTER); + gd.horizontalSpan = 1; + gd.verticalSpan = 3; + projectsLabel.setLayoutData(gd); + projects = new ListViewer(aditionalContainer, SWT.H_SCROLL | SWT.V_SCROLL); + gd = new GridData(GridData.FILL_BOTH); + gd.horizontalSpan = 1; + gd.verticalSpan = 3; + gd.grabExcessHorizontalSpace = true; + projects.getList().setLayoutData(gd); + projects.setLabelProvider(new LabelProvider()); + projects.setContentProvider(ArrayContentProvider.getInstance()); + if (repository != null) { + String projectsValue = repository.getProperty(GitlabCoreActivator.PROJECTS); + if (projectsValue != null) + projectList = new ArrayList(Arrays.asList(projectsValue.split(","))); + } + projects.setInput(projectList); + projectInput = new Text(aditionalContainer, SWT.NONE); + gd = new GridData(GridData.HORIZONTAL_ALIGN_BEGINNING); + gd.widthHint = 200; + projectInput.setLayoutData(gd); + projectInput.addKeyListener(new KeyAdapter() { + + @Override + public void keyReleased(KeyEvent e) { + super.keyReleased(e); + updateUIEnablement(); + } + + }); + projects.addSelectionChangedListener(new ISelectionChangedListener() { + + @Override + public void selectionChanged(SelectionChangedEvent event) { + IStructuredSelection selection = (IStructuredSelection) event.getSelection(); + if (selection.size() > 0) { + projectInput.setText((String) selection.getFirstElement()); + } + updateUIEnablement(); + } + }); +// projectInput.setBackground(new Color(aditionalContainer.getDisplay(), 255, 0 , 0)); + + projectAddButton = new Button(aditionalContainer, SWT.PUSH); + projectAddButton.setText("Add"); + projectAddButton.addSelectionListener(new SelectionAdapter() { + @Override + public void widgetSelected(SelectionEvent e) { + projectList.add(projectInput.getText()); + projectInput.setText(""); + projects.refresh(); + updateUIEnablement(); + } + }); + + projectRemoveButton = new Button(aditionalContainer, SWT.PUSH); + projectRemoveButton.setText("remove"); + projectRemoveButton.addSelectionListener(new SelectionAdapter() { + @Override + public void widgetSelected(SelectionEvent e) { + IStructuredSelection selection = (IStructuredSelection) projects.getSelection(); + int lastIdx = -1; + if (selection != null) { + Object firstElement = selection.getFirstElement(); + lastIdx = projectList.indexOf(firstElement); + } + projectList.remove(projectInput.getText()); + projectInput.setText(""); + projects.refresh(); + if (lastIdx >= 0 && lastIdx < projectList.size()) { + projects.setSelection(new StructuredSelection(projectList.get(lastIdx)), true); + } + updateUIEnablement(); + } + }); + + updateUIEnablement(); + } + + private void updateUIEnablement() { + IStructuredSelection selection = (IStructuredSelection) groups.getSelection(); + groupRemoveButton.setEnabled(selection.size() > 0); + groupAddButton.setEnabled(!groupInput.getText().isEmpty()); + + selection = (IStructuredSelection) projects.getSelection(); + projectRemoveButton.setEnabled(selection.size() > 0); + projectAddButton.setEnabled(!projectInput.getText().isEmpty()); +} + + @Override + public void applyTo(TaskRepository repository) { + repository.setProperty(GitlabCoreActivator.GROUPS, String.join(",", groupList)); + repository.setProperty(GitlabCoreActivator.PROJECTS, String.join(",", projectList)); + super.applyTo(repository); + } + +} diff --git a/mylyn.tasks/connectors/gitlab/org.eclipse.mylyn.gitlab.ui/src/org/eclipse/mylyn/gitlab/ui/GitlabSearchQueryPageSchema.java b/mylyn.tasks/connectors/gitlab/org.eclipse.mylyn.gitlab.ui/src/org/eclipse/mylyn/gitlab/ui/GitlabSearchQueryPageSchema.java new file mode 100644 index 0000000000..1d1b031b34 --- /dev/null +++ b/mylyn.tasks/connectors/gitlab/org.eclipse.mylyn.gitlab.ui/src/org/eclipse/mylyn/gitlab/ui/GitlabSearchQueryPageSchema.java @@ -0,0 +1,29 @@ +package org.eclipse.mylyn.gitlab.ui; + +import org.eclipse.mylyn.gitlab.core.GitlabTaskSchema; +import org.eclipse.mylyn.internal.provisional.tasks.ui.wizards.AbstractQueryPageSchema; +import org.eclipse.mylyn.internal.provisional.tasks.ui.wizards.AbstractQueryPageSchema.Field; +import org.eclipse.mylyn.tasks.core.data.TaskAttribute; +import org.eclipse.mylyn.tasks.core.data.AbstractTaskSchema.Flag; + +public class GitlabSearchQueryPageSchema extends AbstractQueryPageSchema { + + private static final GitlabSearchQueryPageSchema instance = new GitlabSearchQueryPageSchema(); + private final GitlabTaskSchema parent = GitlabTaskSchema.getDefault(); + + public static GitlabSearchQueryPageSchema getInstance() { + return instance; + } + + public GitlabSearchQueryPageSchema() { + } + + public final Field product = copyFrom(parent.PRODUCT).type(TaskAttribute.TYPE_MULTI_SELECT) + .layoutPriority(11) + .create(); + public final Field group = copyFrom(parent.GROUP).type(TaskAttribute.TYPE_MULTI_SELECT) + .layoutPriority(11) + .create(); + public final Field state = createField("STATE", "State", TaskAttribute.TYPE_SINGLE_SELECT, + null, 1); +} diff --git a/mylyn.tasks/connectors/gitlab/org.eclipse.mylyn.gitlab.ui/src/org/eclipse/mylyn/gitlab/ui/GitlabTaskEditorPage.java b/mylyn.tasks/connectors/gitlab/org.eclipse.mylyn.gitlab.ui/src/org/eclipse/mylyn/gitlab/ui/GitlabTaskEditorPage.java new file mode 100644 index 0000000000..21d67194fb --- /dev/null +++ b/mylyn.tasks/connectors/gitlab/org.eclipse.mylyn.gitlab.ui/src/org/eclipse/mylyn/gitlab/ui/GitlabTaskEditorPage.java @@ -0,0 +1,48 @@ +/******************************************************************************* + * Copyright (c) 2023 Frank Becker and others. + * + * This program and the accompanying materials are made available under the + * terms of the Eclipse Public License v. 2.0 which is available at + * https://www.eclipse.org/legal/epl-2.0 + * + * SPDX-License-Identifier: EPL-2.0 + * + * Contributors: + * Frank Becker - initial API and implementation + *******************************************************************************/ + +package org.eclipse.mylyn.gitlab.ui; + +import java.util.Set; + +import org.eclipse.mylyn.gitlab.core.GitlabCoreActivator; +import org.eclipse.mylyn.tasks.ui.editors.AbstractTaskEditorPage; +import org.eclipse.mylyn.tasks.ui.editors.AttributeEditorFactory; +import org.eclipse.mylyn.tasks.ui.editors.TaskEditor; +import org.eclipse.mylyn.tasks.ui.editors.TaskEditorPartDescriptor; + +public class GitlabTaskEditorPage extends AbstractTaskEditorPage { + + public GitlabTaskEditorPage(TaskEditor editor) { + this(editor, GitlabCoreActivator.CONNECTOR_KIND); + } + + + public GitlabTaskEditorPage(TaskEditor editor, String connectorKind) { + super(editor, connectorKind); + setNeedsPrivateSection(false); + setNeedsSubmitButton(true); + } + + @Override + protected AttributeEditorFactory createAttributeEditorFactory() { + // TODO Auto-generated method stub + return super.createAttributeEditorFactory(); + } + + @Override + protected Set createPartDescriptors() { + // TODO Auto-generated method stub + return super.createPartDescriptors(); + } +} diff --git a/mylyn.tasks/connectors/gitlab/org.eclipse.mylyn.gitlab.ui/src/org/eclipse/mylyn/gitlab/ui/GitlabTaskEditorPageFactory.java b/mylyn.tasks/connectors/gitlab/org.eclipse.mylyn.gitlab.ui/src/org/eclipse/mylyn/gitlab/ui/GitlabTaskEditorPageFactory.java new file mode 100644 index 0000000000..db266b740c --- /dev/null +++ b/mylyn.tasks/connectors/gitlab/org.eclipse.mylyn.gitlab.ui/src/org/eclipse/mylyn/gitlab/ui/GitlabTaskEditorPageFactory.java @@ -0,0 +1,55 @@ +/******************************************************************************* + * Copyright (c) 2023 Frank Becker and others. + * + * This program and the accompanying materials are made available under the + * terms of the Eclipse Public License v. 2.0 which is available at + * https://www.eclipse.org/legal/epl-2.0 + * + * SPDX-License-Identifier: EPL-2.0 + * + * Contributors: + * Frank Becker - initial API and implementation + *******************************************************************************/ + +package org.eclipse.mylyn.gitlab.ui; + +import org.eclipse.mylyn.commons.ui.CommonImages; +import org.eclipse.mylyn.gitlab.core.GitlabCoreActivator; +import org.eclipse.mylyn.tasks.ui.TasksUiImages; +import org.eclipse.mylyn.tasks.ui.editors.AbstractTaskEditorPageFactory; +import org.eclipse.mylyn.tasks.ui.editors.TaskEditor; +import org.eclipse.mylyn.tasks.ui.editors.TaskEditorInput; +import org.eclipse.swt.graphics.Image; +import org.eclipse.ui.forms.editor.IFormPage; + +public class GitlabTaskEditorPageFactory extends AbstractTaskEditorPageFactory { + + @Override + public boolean canCreatePageFor(TaskEditorInput input) { + if (input.getTask().getConnectorKind().equals(GitlabCoreActivator.CONNECTOR_KIND)) { + return true; + } + return false; + } + + @Override + public IFormPage createPage(TaskEditor parentEditor) { + return new GitlabTaskEditorPage(parentEditor); + } + + @Override + public Image getPageImage() { + return CommonImages.getImage(TasksUiImages.REPOSITORY_SMALL); + } + + @Override + public String getPageText() { + return "Gitlab"; + } + + @Override + public int getPriority() { + return PRIORITY_TASK; + } + +} diff --git a/mylyn.tasks/connectors/gitlab/org.eclipse.mylyn.gitlab.ui/src/org/eclipse/mylyn/gitlab/ui/GitlabUiActivator.java b/mylyn.tasks/connectors/gitlab/org.eclipse.mylyn.gitlab.ui/src/org/eclipse/mylyn/gitlab/ui/GitlabUiActivator.java new file mode 100644 index 0000000000..0c28e06f19 --- /dev/null +++ b/mylyn.tasks/connectors/gitlab/org.eclipse.mylyn.gitlab.ui/src/org/eclipse/mylyn/gitlab/ui/GitlabUiActivator.java @@ -0,0 +1,61 @@ +/******************************************************************************* + * Copyright (c) 2023 Frank Becker and others. + * + * This program and the accompanying materials are made available under the + * terms of the Eclipse Public License v. 2.0 which is available at + * https://www.eclipse.org/legal/epl-2.0 + * + * SPDX-License-Identifier: EPL-2.0 + * + * Contributors: + * Frank Becker - initial API and implementation + *******************************************************************************/ + +package org.eclipse.mylyn.gitlab.ui; + +import java.io.File; + +import org.eclipse.mylyn.internal.tasks.core.ITasksCoreConstants; +import org.eclipse.mylyn.internal.tasks.ui.TasksUiPlugin; +import org.eclipse.ui.plugin.AbstractUIPlugin; +import org.osgi.framework.BundleContext; + +/** + * The activator class controls the plug-in life cycle + */ +public class GitlabUiActivator extends AbstractUIPlugin { + + // The plug-in ID + public static final String PLUGIN_ID = "org.eclipse.mylyn.gitlab.ui"; //$NON-NLS-1$ + + // The shared instance + private static GitlabUiActivator plugin; + + /** + * The constructor + */ + public GitlabUiActivator() { + } + + @Override + public void start(BundleContext context) throws Exception { + super.start(context); + plugin = this; + } + + @Override + public void stop(BundleContext context) throws Exception { + plugin = null; + super.stop(context); + } + + /** + * Returns the shared instance + * + * @return the shared instance + */ + public static GitlabUiActivator getDefault() { + return plugin; + } + +} From d3fcf69f85fada0b79344b677976d8f1260e11cf Mon Sep 17 00:00:00 2001 From: Frank Becker Date: Thu, 8 Jun 2023 07:17:50 +0200 Subject: [PATCH 02/13] add Gitlab Connector to Maven Build and p2 Repository --- .mvn/maven.config | 2 +- org.eclipse.mylyn-site/category.xml | 14 +++++++------- 2 files changed, 8 insertions(+), 8 deletions(-) diff --git a/.mvn/maven.config b/.mvn/maven.config index 3e0a907b2c..c8299a0bba 100644 --- a/.mvn/maven.config +++ b/.mvn/maven.config @@ -1 +1 @@ --Dtycho.pomless.aggregator.names=mylyn.builds,mylyn.commons,mylyn.context,mylyn.egit,mylyn.github,mylyn.releng,mylyn.reviews,mylyn.tasks,mylyn.versions,connectors,bugzilla,bugzilla-rest,trac +-Dtycho.pomless.aggregator.names=mylyn.builds,mylyn.commons,mylyn.context,mylyn.egit,mylyn.github,mylyn.releng,mylyn.reviews,mylyn.tasks,mylyn.versions,connectors,bugzilla,bugzilla-rest,trac,gitlab diff --git a/org.eclipse.mylyn-site/category.xml b/org.eclipse.mylyn-site/category.xml index 388c6ce3b3..1909f9685e 100644 --- a/org.eclipse.mylyn-site/category.xml +++ b/org.eclipse.mylyn-site/category.xml @@ -24,7 +24,7 @@ - + @@ -48,7 +48,7 @@ - + @@ -105,11 +105,14 @@ - + + + + @@ -145,10 +148,7 @@ Source code and documentation for integrators building on Mylyn. - - - - + From a463f4288f0f29e69a2fd10bb7e34c43e358db94 Mon Sep 17 00:00:00 2001 From: Frank Becker Date: Sun, 11 Jun 2023 16:45:53 +0200 Subject: [PATCH 03/13] update of some attributes is now supported and the creation of comments --- .../gitlab/core/GitlabConfiguration.java | 39 +++ .../mylyn/gitlab/core/GitlabOperation.java | 2 +- .../gitlab/core/GitlabPostOperation.java | 48 ++++ .../mylyn/gitlab/core/GitlabPutOperation.java | 49 ++++ .../core/GitlabRepositoryConnector.java | 6 +- .../mylyn/gitlab/core/GitlabRestClient.java | 233 +++++++++++++----- .../gitlab/core/GitlabTaskDataHandler.java | 16 +- .../mylyn/gitlab/core/GitlabTaskSchema.java | 11 +- .../mylyn/tasks/core/TaskRepository.java | 6 +- 9 files changed, 339 insertions(+), 71 deletions(-) create mode 100644 mylyn.tasks/connectors/gitlab/org.eclipse.mylyn.gitlab.core/src/org/eclipse/mylyn/gitlab/core/GitlabPostOperation.java create mode 100644 mylyn.tasks/connectors/gitlab/org.eclipse.mylyn.gitlab.core/src/org/eclipse/mylyn/gitlab/core/GitlabPutOperation.java diff --git a/mylyn.tasks/connectors/gitlab/org.eclipse.mylyn.gitlab.core/src/org/eclipse/mylyn/gitlab/core/GitlabConfiguration.java b/mylyn.tasks/connectors/gitlab/org.eclipse.mylyn.gitlab.core/src/org/eclipse/mylyn/gitlab/core/GitlabConfiguration.java index 83b511b81f..53c6adaf63 100644 --- a/mylyn.tasks/connectors/gitlab/org.eclipse.mylyn.gitlab.core/src/org/eclipse/mylyn/gitlab/core/GitlabConfiguration.java +++ b/mylyn.tasks/connectors/gitlab/org.eclipse.mylyn.gitlab.core/src/org/eclipse/mylyn/gitlab/core/GitlabConfiguration.java @@ -11,6 +11,7 @@ import org.eclipse.jdt.annotation.NonNull; import org.eclipse.mylyn.tasks.core.data.TaskAttribute; import org.eclipse.mylyn.tasks.core.data.TaskData; +import org.eclipse.mylyn.tasks.core.data.TaskOperation; import com.google.gson.JsonElement; import com.google.gson.JsonObject; @@ -98,6 +99,7 @@ public boolean updateProductOptions(@NonNull TaskData taskData) { return false; } TaskAttribute attributeProduct = taskData.getRoot().getMappedAttribute(SCHEMA.PRODUCT.getKey()); + if (attributeProduct == null) { return false; } @@ -113,6 +115,21 @@ public boolean updateProductOptions(@NonNull TaskData taskData) { for (String string : groups) { attributeGroups.putOption(string, string); } + TaskAttribute priorityAttrib = taskData.getRoot().getMappedAttribute(SCHEMA.PRIORITY.getKey()); + if (priorityAttrib!=null) { + priorityAttrib.putOption("CRITICAL", "critical"); + priorityAttrib.putOption("HIGH", "high"); + priorityAttrib.putOption("MEDIUM", "Medium"); + priorityAttrib.putOption("LOW", "low"); + priorityAttrib.putOption("UNKNOWN", "unknown"); + } + + + TaskAttribute typeAttrib = taskData.getRoot().getMappedAttribute(SCHEMA.ISSUE_TYPE.getKey()); + if (typeAttrib!=null) { + typeAttrib.putOption("issue", "Issue"); + typeAttrib.putOption("incident", "Incident"); + } TaskAttribute stateAttrib = taskData.getRoot().getMappedAttribute("STATE"); if (stateAttrib!=null) { stateAttrib.putOption("opened", "Opened"); @@ -130,4 +147,26 @@ public String getGroupID(String path) { } return ""; } + + public void addValidOperations(TaskData bugReport) { + TaskAttribute attributeStatus = bugReport.getRoot().getMappedAttribute(TaskAttribute.STATUS); + String attributeStatusValue = attributeStatus.getValue(); + TaskAttribute operationAttribute = bugReport.getRoot().getAttribute(TaskAttribute.OPERATION); + if (operationAttribute == null) { + operationAttribute = bugReport.getRoot().createAttribute(TaskAttribute.OPERATION); + } + TaskOperation.applyTo(operationAttribute, attributeStatusValue, attributeStatusValue); + + TaskAttribute attribute = bugReport.getRoot().createAttribute(TaskAttribute.PREFIX_OPERATION + "opened"); + TaskOperation.applyTo(attribute, attributeStatusValue, attributeStatusValue); + + attribute = bugReport.getRoot().createAttribute(TaskAttribute.PREFIX_OPERATION + "closed"); + if (attributeStatusValue.equals("closed")) { + TaskOperation.applyTo(attribute, "reopen", "Reopen"); + } else { + TaskOperation.applyTo(attribute, "close", "Close"); + } + int i=9; + i++; + } } diff --git a/mylyn.tasks/connectors/gitlab/org.eclipse.mylyn.gitlab.core/src/org/eclipse/mylyn/gitlab/core/GitlabOperation.java b/mylyn.tasks/connectors/gitlab/org.eclipse.mylyn.gitlab.core/src/org/eclipse/mylyn/gitlab/core/GitlabOperation.java index f011afa8d1..965cfc82c6 100644 --- a/mylyn.tasks/connectors/gitlab/org.eclipse.mylyn.gitlab.core/src/org/eclipse/mylyn/gitlab/core/GitlabOperation.java +++ b/mylyn.tasks/connectors/gitlab/org.eclipse.mylyn.gitlab.core/src/org/eclipse/mylyn/gitlab/core/GitlabOperation.java @@ -93,7 +93,7 @@ protected void doValidate(CommonHttpResponse response, IOperationMonitor monitor protected void validate(CommonHttpResponse response, int expected, IOperationMonitor monitor) throws GitlabException { int statusCode = response.getStatusCode(); - if (statusCode != expected && statusCode != HttpStatus.SC_BAD_REQUEST) { + if (statusCode != expected /*&& statusCode != HttpStatus.SC_BAD_REQUEST*/) { if (statusCode == HttpStatus.SC_NOT_FOUND) { throw new GitlabException( NLS.bind("Requested resource ''{0}'' does not exist", response.getRequestPath())); diff --git a/mylyn.tasks/connectors/gitlab/org.eclipse.mylyn.gitlab.core/src/org/eclipse/mylyn/gitlab/core/GitlabPostOperation.java b/mylyn.tasks/connectors/gitlab/org.eclipse.mylyn.gitlab.core/src/org/eclipse/mylyn/gitlab/core/GitlabPostOperation.java new file mode 100644 index 0000000000..505de9f45f --- /dev/null +++ b/mylyn.tasks/connectors/gitlab/org.eclipse.mylyn.gitlab.core/src/org/eclipse/mylyn/gitlab/core/GitlabPostOperation.java @@ -0,0 +1,48 @@ +/******************************************************************************* + * Copyright (c) 2023 Frank Becker and others. + * + * This program and the accompanying materials are made available under the + * terms of the Eclipse Public License v. 2.0 which is available at + * https://www.eclipse.org/legal/epl-2.0 + * + * SPDX-License-Identifier: EPL-2.0 + * + * Contributors: + * Frank Becker - initial API and implementation + *******************************************************************************/ + +package org.eclipse.mylyn.gitlab.core; + +import java.io.UnsupportedEncodingException; + +import org.apache.http.client.methods.HttpPost; +import org.apache.http.client.methods.HttpRequestBase; +import org.apache.http.entity.StringEntity; +import org.eclipse.mylyn.commons.repositories.http.core.CommonHttpClient; + +public abstract class GitlabPostOperation extends GitlabOperation { + + private final String body; + public GitlabPostOperation(CommonHttpClient client, String urlSuffix, String body) { + super(client, urlSuffix); + this.body = body; + } + + @Override + protected HttpRequestBase createHttpRequestBase(String url) { + HttpRequestBase request = new HttpPost(url); + return request; + } + + protected void addHttpRequestEntities(HttpRequestBase request) throws GitlabException { + super.addHttpRequestEntities(request); + request.setHeader(CONTENT_TYPE, APPLICATION_JSON); + try { + ((HttpPost) request).setEntity(new StringEntity(body)); + } catch (UnsupportedEncodingException e) { + throw new GitlabException(e); + } + }; + + +} diff --git a/mylyn.tasks/connectors/gitlab/org.eclipse.mylyn.gitlab.core/src/org/eclipse/mylyn/gitlab/core/GitlabPutOperation.java b/mylyn.tasks/connectors/gitlab/org.eclipse.mylyn.gitlab.core/src/org/eclipse/mylyn/gitlab/core/GitlabPutOperation.java new file mode 100644 index 0000000000..ff9fd4eeec --- /dev/null +++ b/mylyn.tasks/connectors/gitlab/org.eclipse.mylyn.gitlab.core/src/org/eclipse/mylyn/gitlab/core/GitlabPutOperation.java @@ -0,0 +1,49 @@ +/******************************************************************************* + * Copyright (c) 2023 Frank Becker and others. + * + * This program and the accompanying materials are made available under the + * terms of the Eclipse Public License v. 2.0 which is available at + * https://www.eclipse.org/legal/epl-2.0 + * + * SPDX-License-Identifier: EPL-2.0 + * + * Contributors: + * Frank Becker - initial API and implementation + *******************************************************************************/ + +package org.eclipse.mylyn.gitlab.core; + +import java.io.UnsupportedEncodingException; + +import org.apache.http.client.methods.HttpPost; +import org.apache.http.client.methods.HttpPut; +import org.apache.http.client.methods.HttpRequestBase; +import org.apache.http.entity.StringEntity; +import org.eclipse.mylyn.commons.repositories.http.core.CommonHttpClient; + +public abstract class GitlabPutOperation extends GitlabOperation { + + private final String body; + public GitlabPutOperation(CommonHttpClient client, String urlSuffix, String body) { + super(client, urlSuffix); + this.body = body; + } + + @Override + protected HttpRequestBase createHttpRequestBase(String url) { + HttpRequestBase request = new HttpPut(url); + return request; + } + + protected void addHttpRequestEntities(HttpRequestBase request) throws GitlabException { + super.addHttpRequestEntities(request); + request.setHeader(CONTENT_TYPE, APPLICATION_JSON); + try { + ((HttpPut) request).setEntity(new StringEntity(body)); + } catch (UnsupportedEncodingException e) { + throw new GitlabException(e); + } + }; + + +} diff --git a/mylyn.tasks/connectors/gitlab/org.eclipse.mylyn.gitlab.core/src/org/eclipse/mylyn/gitlab/core/GitlabRepositoryConnector.java b/mylyn.tasks/connectors/gitlab/org.eclipse.mylyn.gitlab.core/src/org/eclipse/mylyn/gitlab/core/GitlabRepositoryConnector.java index 54fb542b76..e8bb49634c 100644 --- a/mylyn.tasks/connectors/gitlab/org.eclipse.mylyn.gitlab.core/src/org/eclipse/mylyn/gitlab/core/GitlabRepositoryConnector.java +++ b/mylyn.tasks/connectors/gitlab/org.eclipse.mylyn.gitlab.core/src/org/eclipse/mylyn/gitlab/core/GitlabRepositoryConnector.java @@ -325,10 +325,8 @@ public boolean hasTaskChanged(@NonNull TaskRepository taskRepository, @NonNull I public void updateRepositoryConfiguration(@NonNull TaskRepository taskRepository, @NonNull IProgressMonitor monitor) throws CoreException { context.set(monitor != null ? OperationUtil.convert(monitor) : new NullOperationMonitor()); - GitlabRestClient client; - client = getClient(taskRepository); - IOperationMonitor progress = OperationUtil.convert(monitor, "performQuery", 3); //$NON-NLS-1$ - client.getConfiguration(taskRepository, progress); + configurationCache.invalidate(new RepositoryKey(taskRepository)); + getRepositoryConfiguration(taskRepository); context.remove(); } diff --git a/mylyn.tasks/connectors/gitlab/org.eclipse.mylyn.gitlab.core/src/org/eclipse/mylyn/gitlab/core/GitlabRestClient.java b/mylyn.tasks/connectors/gitlab/org.eclipse.mylyn.gitlab.core/src/org/eclipse/mylyn/gitlab/core/GitlabRestClient.java index 709dac2b69..c55ad3871c 100644 --- a/mylyn.tasks/connectors/gitlab/org.eclipse.mylyn.gitlab.core/src/org/eclipse/mylyn/gitlab/core/GitlabRestClient.java +++ b/mylyn.tasks/connectors/gitlab/org.eclipse.mylyn.gitlab.core/src/org/eclipse/mylyn/gitlab/core/GitlabRestClient.java @@ -14,12 +14,15 @@ package org.eclipse.mylyn.gitlab.core; import java.io.BufferedReader; +import java.io.IOException; import java.io.InputStreamReader; import java.io.PrintStream; import java.lang.reflect.Type; import java.net.HttpURLConnection; import java.net.URL; +import java.text.SimpleDateFormat; import java.util.ArrayList; +import java.util.Date; import java.util.List; import java.util.Map.Entry; import java.util.Set; @@ -27,6 +30,7 @@ import java.util.regex.Pattern; import java.util.stream.Collectors; +import org.apache.http.HttpStatus; import org.apache.http.client.methods.HttpGet; import org.apache.http.client.methods.HttpRequestBase; import org.eclipse.core.runtime.CoreException; @@ -41,8 +45,12 @@ import org.eclipse.mylyn.commons.net.AuthenticationCredentials; import org.eclipse.mylyn.commons.repositories.core.RepositoryLocation; import org.eclipse.mylyn.commons.repositories.http.core.CommonHttpClient; +import org.eclipse.mylyn.commons.repositories.http.core.CommonHttpResponse; import org.eclipse.mylyn.tasks.core.IRepositoryQuery; +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.AbstractTaskSchema.Field; import org.eclipse.mylyn.tasks.core.data.TaskAttribute; import org.eclipse.mylyn.tasks.core.data.TaskAttributeMapper; import org.eclipse.mylyn.tasks.core.data.TaskCommentMapper; @@ -50,6 +58,7 @@ import org.eclipse.mylyn.tasks.core.data.TaskDataCollector; import org.eclipse.osgi.util.NLS; +import com.google.common.collect.ImmutableMap; import com.google.gson.Gson; import com.google.gson.GsonBuilder; import com.google.gson.JsonArray; @@ -95,22 +104,17 @@ public TaskRepository getTaskRepository() { public IStatus getIssues(IRepositoryQuery query, TaskDataCollector collector, final IOperationMonitor monitor) throws GitlabException, CoreException { getAccessTokenIfNotPresent(monitor); -// GitlabConfiguration conf = connector.getRepositoryConfiguration(taskRepository); String[] queryProjects = query.getAttribute(GitlabTaskSchema.getDefault().PRODUCT.getKey()).split(","); String[] gueryGroups = query.getAttribute(GitlabTaskSchema.getDefault().GROUP.getKey()).split(","); if (!queryProjects[0].isEmpty()) { for (String string : queryProjects) { -// String path = "/projects/" + ((JsonObject) conf.getProjcetDetail(string)).get("path_with_namespace") -// .getAsString().replaceAll("/", "%2F"); String path = "/projects/" + string.replaceAll("/", "%2F"); getIssuesInternal(query, collector, path, monitor); } } if (!gueryGroups[0].isEmpty()) { for (String string : gueryGroups) { -// String path = "/groups/" + ((JsonObject) conf.getGroupDetail(string)).get("full_path").getAsString() -// .replaceAll("/", "%2F"); String path = "/groups/" + string.replaceAll("/", "%2F"); getIssuesInternal(query, collector, path, monitor); } @@ -144,13 +148,11 @@ protected HttpRequestBase createHttpRequestBase(String url) { @Override protected List parseFromJson(InputStreamReader in) throws GitlabException { - String text = new BufferedReader(in).lines().collect(Collectors.joining("\n")); - JsonArray convertedObject = new Gson().fromJson(text, JsonArray.class); TypeToken> type = new TypeToken>() { }; return new GsonBuilder().registerTypeAdapter(type.getType(), new JSonTaskDataListDeserializer()) - .create().fromJson(text, type.getType()); + .create().fromJson(in, type.getType()); } }.run(monitor); for (final TaskData taskData : taskDataArray) { @@ -254,7 +256,7 @@ private class JSonTaskDataListDeserializer implements JsonDeserializer deserialize(JsonElement json, Type typeOfT, JsonDeserializationContext context) throws JsonParseException { ArrayList response = new ArrayList(); - GitlabConfiguration config =getConfiguration(); + GitlabConfiguration config = getConfiguration(); JsonArray ja = json.getAsJsonArray(); for (JsonElement jsonElement : ja) { JsonObject jo = jsonElement.getAsJsonObject(); @@ -285,21 +287,19 @@ private TaskData getFromJson(JsonObject jo) { for (Entry entry : jo.entrySet()) { String attributeId = GitlabTaskSchema.getAttributeNameFromJsonName(entry.getKey()); TaskAttribute attribute = taskData.getRoot().getAttribute(attributeId); + Field field = GitlabTaskSchema.getDefault().getFieldByKey(attributeId); if (attribute == null) { PrintStream ps = attribute == null ? System.err : System.out; ps.println(entry.getKey() + " -> " + entry.getValue() // + " -> " + attributeId + " -> " + attribute + "\n" // + entry.getValue().isJsonPrimitive() + entry.getValue().isJsonObject() + entry.getValue().isJsonArray()); - ps.close(); + ps.flush(); } if (attribute != null && entry.getValue() != null && entry.getValue().isJsonPrimitive()) { attribute.setValue(entry.getValue().getAsString()); } - if (entry.getKey().equals("severity")) { - attribute.putOption(entry.getValue().getAsString(), entry.getValue().getAsString()); - } - if (entry.getKey().equals("author") && entry.getValue().isJsonObject()) { + if (field != null && TaskAttribute.TYPE_PERSON.equals(field.getType()) && entry.getValue().isJsonObject()) { attribute.setValue(entry.getValue().getAsJsonObject().get("name").getAsString()); } } @@ -314,8 +314,10 @@ public TaskData deserialize(JsonElement json, Type typeOfT, JsonDeserializationC GitlabConfiguration config = getConfiguration(); JsonObject jo = json.getAsJsonObject(); TaskData taskData = getFromJson(jo); - if (config != null) + if (config != null) { config.updateProductOptions(taskData); + config.addValidOperations(taskData); + } return taskData; } @@ -399,18 +401,31 @@ public TaskData getTaskData(TaskRepository repository, String taskId, IProgressM JsonArray notes = getIssueNotes(matcher.group(1), matcher.group(2), OperationUtil.convert(monitor)); if (notes != null) { - for (int i = 0; i < notes.size(); i++) { - JsonObject note = notes.get(i).getAsJsonObject(); - TaskCommentMapper cmapper = new TaskCommentMapper(); - cmapper.setAuthor( - repository.createPerson(note.get("author").getAsJsonObject().get("name").getAsString())); - cmapper.setCreationDate(GitlabTaskAttributeMapper.parseDate(note.get("created_at").getAsString())); - cmapper.setText(note.get("body").getAsString()); - cmapper.setNumber(i + 1); - TaskAttribute attribute = result.getRoot().createAttribute(TaskAttribute.PREFIX_COMMENT + (i + 1)); - cmapper.applyTo(attribute); + int i = 0; + for (JsonElement jsonElement : notes) { + JsonObject note = jsonElement.getAsJsonObject(); + i = createNoteTaskAttribute(repository, result, i, note); } } +// JsonArray discussions = getIssueDiscussions(matcher.group(1), matcher.group(2), +// OperationUtil.convert(monitor)); +// if (discussions != null) { +// int i = 0; +// for (JsonElement jsonElement : discussions) { +// JsonObject discussion = (JsonObject) jsonElement; +// JsonArray notesArray = discussion.get("notes").getAsJsonArray(); +// if (discussion.get("individual_note").getAsBoolean()) { +// JsonObject note = notesArray.get(0).getAsJsonObject(); +// i = createNoteTaskAttribute(repository, result, i, note); +// } else { +// for ( JsonElement jsonElement2 : notesArray) { +// JsonObject note = jsonElement2.getAsJsonObject(); +// i = createNoteTaskAttribute(repository, result, i, note); +// } +// } +// } +// } + config.updateProductOptions(result); return result; @@ -418,13 +433,24 @@ public TaskData getTaskData(TaskRepository repository, String taskId, IProgressM return null; } + private int createNoteTaskAttribute(TaskRepository repository, TaskData result, int i, JsonObject note) { + TaskCommentMapper cmapper = new TaskCommentMapper(); + cmapper.setAuthor(repository.createPerson(note.get("author").getAsJsonObject().get("name").getAsString())); + cmapper.setCreationDate(GitlabTaskAttributeMapper.parseDate(note.get("created_at").getAsString())); + cmapper.setText(note.get("body").getAsString()); + cmapper.setNumber(++i); + TaskAttribute attribute = result.getRoot().createAttribute(TaskAttribute.PREFIX_COMMENT + (i + 1)); + cmapper.applyTo(attribute); + return i; + } + public void getTaskData(Set taskIds, TaskRepository taskRepository, TaskDataCollector collector, IOperationMonitor monitor) throws GitlabException { for (String taskId : taskIds) { TaskData data; - data = getTaskData(taskRepository, taskId, monitor); - collector.accept(data); + data = getTaskData(taskRepository, taskId, monitor); + collector.accept(data); } } @@ -651,6 +677,75 @@ protected JsonArray parseFromJson(InputStreamReader in) throws GitlabException { return jsonArray; } + public JsonArray getIssueDiscussions(String path, String id, IOperationMonitor monitor) throws GitlabException { + getAccessTokenIfNotPresent(monitor); + JsonArray jsonArray = new GitlabJSonArrayOperation(client, path + "/issues/" + id + "/discussions") { + @Override + protected HttpRequestBase createHttpRequestBase(String url) { + HttpRequestBase request = new HttpGet(url); + return request; + } + + @Override + protected JsonArray parseFromJson(InputStreamReader in) throws GitlabException { + return new Gson().fromJson(in, JsonArray.class); + } + }.run(monitor); + return jsonArray; + } + + public JsonElement createIssueNote(String path, String id, String body, IOperationMonitor monitor) + throws GitlabException { + getAccessTokenIfNotPresent(monitor); + JsonObject jsonElement; + jsonElement = new GitlabPostOperation(client, path + "/issues/" + id + "/notes", body) { + + @Override + protected void doValidate(CommonHttpResponse response, IOperationMonitor monitor) + throws IOException, GitlabException { + validate(response, HttpStatus.SC_CREATED, monitor); + } + + @Override + protected JsonObject parseFromJson(InputStreamReader in) throws GitlabException { + return new Gson().fromJson(in, JsonObject.class); + } + }.run(monitor); + return jsonElement; + } + + public JsonElement updateIssue(String path, String id, String body, IOperationMonitor monitor) + throws GitlabException { + getAccessTokenIfNotPresent(monitor); + JsonObject jsonElement; + jsonElement = new GitlabPutOperation(client, path + "/issues/" + id, body) { + @Override + + protected void doValidate(CommonHttpResponse response, IOperationMonitor monitor) + throws IOException, GitlabException { + validate(response, HttpStatus.SC_OK, monitor); + } + + @Override + protected JsonObject parseFromJson(InputStreamReader in) throws GitlabException { + StringBuilder result = new StringBuilder(); +// String rr = ""; +// try { +// // Read each byte and convert into a char, adding to the StringBuilder +// for (int data = in.read(); data != -1; data = in.read()) { +// result.append((char) data); +// rr = result.toString(); +// } +// } catch (IOException e) { +// // TODO: handle exception +// } +// return null; + return new Gson().fromJson(in, JsonObject.class); + } + }.run(monitor); + return jsonElement; + } + public GitlabConfiguration getConfiguration(TaskRepository repository, IOperationMonitor monitor) { GitlabConfiguration config = new GitlabConfiguration(repository.getUrl()); try { @@ -659,20 +754,15 @@ public GitlabConfiguration getConfiguration(TaskRepository repository, IOperatio config.setUserDetails(user); JsonElement projects = getProjects("/users/" + config.getUserID(), monitor); for (JsonElement project : (JsonArray) projects) { -// System.out.println(project.getAsJsonObject().get("name_with_namespace").getAsString()); config.addProject(project); } String groupsValue = repository.getProperty(GitlabCoreActivator.GROUPS); String[] groupList = groupsValue.split(","); for (String group : groupList) { JsonObject groupDetail = getGroup("/" + group, monitor); -// System.out.println(groupDetail.getAsJsonObject().get("full_path").getAsString()); config.addGroup(groupDetail); projects = getGroupProjects(group, monitor); for (JsonElement project : (JsonArray) projects) { -// System.out.print(project.getAsJsonObject().get("id").getAsString()); -// System.out.print(" "); -// System.out.println(project.getAsJsonObject().get("name_with_namespace").getAsString()); config.addProject(project); } } @@ -683,32 +773,57 @@ public GitlabConfiguration getConfiguration(TaskRepository repository, IOperatio return config; } -// public String getProjects(IOperationMonitor monitor) throws GitlabException { -// getAccessTokenIfNotPresent(monitor); -// Version versionInfo = new GitlabOperation(client, "/namespaces") { -//// Version versionInfo = new GitlabOperation(client, "/projects?membership=true") { -//// Version versionInfo = new GitlabOperation(client, "/projects?owned=true") { -// -// @Override -// protected HttpRequestBase createHttpRequestBase(String url) { -// HttpRequestBase request = new HttpGet(url); -// return request; -// } -// -// @Override -// protected Version parseFromJson(InputStreamReader in) throws GitlabException { -// String result = new BufferedReader(in) -// .lines().collect(Collectors.joining("\n")); -//// Gson gson = new GsonBuilder().setPrettyPrinting().create(); -// JsonArray convertedObject = new Gson().fromJson(result, JsonArray.class); -// Gson gson = new GsonBuilder().setPrettyPrinting().create(); -// String prettyJson = gson.toJson(convertedObject); -// TypeToken type = new TypeToken() { -// }; -// return new Gson().fromJson(result, type.getType()); -// } -// }.run(monitor); -// return versionInfo.getVersion(); -// } + ImmutableMap updatable = new ImmutableMap.Builder() + .put(GitlabTaskSchema.getDefault().SUMMARY.getKey(), "title") + .put(GitlabTaskSchema.getDefault().DESCRIPTION.getKey(), "description") + .put(GitlabTaskSchema.getDefault().DISCUSSION_LOCKED.getKey(), + GitlabTaskSchema.getDefault().DISCUSSION_LOCKED.getKey()) + .put(GitlabTaskSchema.getDefault().CONFIDENTIAL.getKey(), + GitlabTaskSchema.getDefault().CONFIDENTIAL.getKey()) + .put(GitlabTaskSchema.getDefault().ISSUE_TYPE.getKey(), GitlabTaskSchema.getDefault().ISSUE_TYPE.getKey()) + .put(GitlabTaskSchema.getDefault().OPERATION.getKey(), "state_event") + .put(GitlabTaskSchema.getDefault().DUE_DATE.getKey(), GitlabTaskSchema.getDefault().DUE_DATE.getKey()) + .build(); + + private static SimpleDateFormat dmyFormat = new SimpleDateFormat("yyyy-MM-dd"); + + public RepositoryResponse postTaskData(TaskData taskData, Set oldAttributes, + IOperationMonitor monitor) throws GitlabException { + ArrayList changedAtributes = new ArrayList<>(); + String newComentValue = ""; + for (TaskAttribute taskAttribute : oldAttributes) { + String attributeID = taskAttribute.getId(); + if (updatable.containsKey(attributeID)) { + TaskAttribute newAttrib = taskData.getRoot().getAttribute(attributeID); + String newValue = newAttrib.getValue(); + if (attributeID.equals("due_date")) { + if (newValue.length() > 0) { + newValue = dmyFormat.format(new Date(Long.parseLong(newValue))); + } + } +// changedAtributes.add("\"" + updatable.get(attributeID) + "\":\"" + newValue + "\""); + changedAtributes.add(NLS.bind("\"{0}\":\"{1}\"", updatable.get(attributeID), newValue)); + } + if (GitlabTaskSchema.getDefault().NEW_COMMENT.getKey().equals(taskAttribute.getId())) { + TaskAttribute newAttrib = taskData.getRoot().getAttribute(attributeID); + newComentValue = "{\"body\":\"" + newAttrib.getValue() + "\"}"; + } + } + + TaskAttribute productAttribute = taskData.getRoot() + .getAttribute(GitlabTaskSchema.getDefault().PRODUCT.getKey()); + if (productAttribute != null && !productAttribute.getValue().isEmpty()) { + TaskAttribute iidAttribute = taskData.getRoot().getAttribute(GitlabTaskSchema.getDefault().IID.getKey()); + if (!changedAtributes.isEmpty()) { + updateIssue("/projects/" + productAttribute.getValue(), iidAttribute.getValue(), + "{" + String.join(",", changedAtributes) + "}", monitor); + } + if (!newComentValue.isEmpty()) { + createIssueNote("/projects/" + productAttribute.getValue(), iidAttribute.getValue(), newComentValue, + monitor); + } + } + return new RepositoryResponse(ResponseKind.TASK_UPDATED, taskData.getTaskId()); + } } diff --git a/mylyn.tasks/connectors/gitlab/org.eclipse.mylyn.gitlab.core/src/org/eclipse/mylyn/gitlab/core/GitlabTaskDataHandler.java b/mylyn.tasks/connectors/gitlab/org.eclipse.mylyn.gitlab.core/src/org/eclipse/mylyn/gitlab/core/GitlabTaskDataHandler.java index d49b7ab990..2aa6ae3f1f 100644 --- a/mylyn.tasks/connectors/gitlab/org.eclipse.mylyn.gitlab.core/src/org/eclipse/mylyn/gitlab/core/GitlabTaskDataHandler.java +++ b/mylyn.tasks/connectors/gitlab/org.eclipse.mylyn.gitlab.core/src/org/eclipse/mylyn/gitlab/core/GitlabTaskDataHandler.java @@ -43,8 +43,20 @@ public GitlabTaskDataHandler(GitlabRepositoryConnector connector) { @Override public RepositoryResponse postTaskData(TaskRepository repository, TaskData taskData, Set oldAttributes, IProgressMonitor monitor) throws CoreException { - // TODO Auto-generated method stub - return null; + monitor = Policy.monitorFor(monitor); + try { + monitor.beginTask("Submitting_task", IProgressMonitor.UNKNOWN); + GitlabRestClient client = connector.getClient(repository); + IOperationMonitor progress = OperationUtil.convert(monitor, "post taskdata", 3); + try { + return client.postTaskData(taskData, oldAttributes, progress); + } catch (GitlabException e) { + throw new CoreException(new Status(IStatus.ERROR, GitlabCoreActivator.PLUGIN_ID, 2, + "Error post taskdata.\n\n" + e.getMessage(), e)); + } + } finally { + monitor.done(); + } } @Override diff --git a/mylyn.tasks/connectors/gitlab/org.eclipse.mylyn.gitlab.core/src/org/eclipse/mylyn/gitlab/core/GitlabTaskSchema.java b/mylyn.tasks/connectors/gitlab/org.eclipse.mylyn.gitlab.core/src/org/eclipse/mylyn/gitlab/core/GitlabTaskSchema.java index 23b401bc66..1bfcf32fca 100644 --- a/mylyn.tasks/connectors/gitlab/org.eclipse.mylyn.gitlab.core/src/org/eclipse/mylyn/gitlab/core/GitlabTaskSchema.java +++ b/mylyn.tasks/connectors/gitlab/org.eclipse.mylyn.gitlab.core/src/org/eclipse/mylyn/gitlab/core/GitlabTaskSchema.java @@ -17,6 +17,7 @@ import org.eclipse.mylyn.tasks.core.data.DefaultTaskSchema; import org.eclipse.mylyn.tasks.core.data.TaskAttribute; import org.eclipse.mylyn.tasks.core.data.AbstractTaskSchema.Field; +import org.eclipse.mylyn.tasks.core.data.AbstractTaskSchema.Flag; import com.google.common.collect.ImmutableMap; @@ -54,7 +55,7 @@ public static GitlabTaskSchema getDefault() { public final Field PRIORITY = inheritFrom(parent.PRIORITY).create(); - public final Field ISSUE_TYPE = createField("issue_type", "Issue Type", TaskAttribute.TYPE_SHORT_TEXT, + public final Field ISSUE_TYPE = createField("issue_type", "Issue Type", TaskAttribute.TYPE_SINGLE_SELECT, Flag.ATTRIBUTE); public final Field USER_NOTES_COUNT = createField("user_notes_count", "User Notes Count", @@ -84,12 +85,18 @@ public static GitlabTaskSchema getDefault() { public final Field CONFIDENTIAL = createField("confidential", "confidential", TaskAttribute.TYPE_BOOLEAN, Flag.ATTRIBUTE); + public final Field NEW_COMMENT = inheritFrom(parent.NEW_COMMENT).create(); public final Field DISCUSSION_LOCKED = createField("discussion_locked", "Discussion locked", TaskAttribute.TYPE_BOOLEAN, Flag.ATTRIBUTE); public final Field GROUP = createField("group", "Group", TaskAttribute.TYPE_SHORT_TEXT); - + public final Field IID = createField("iid", "interne ID", TaskAttribute.TYPE_SHORT_TEXT, Flag.ATTRIBUTE); + public final Field OPERATION = createField(TaskAttribute.OPERATION, "Operation", TaskAttribute.TYPE_OPERATION); + public final Field CLOSED_BY = createField("closed_by", "closed by", TaskAttribute.TYPE_PERSON, Flag.PEOPLE, //$NON-NLS-1$ + Flag.READ_ONLY); + + public final Field DUE_DATE = createField("due_date", "Due date", TaskAttribute.TYPE_DATE, Flag.ATTRIBUTE); private static ImmutableMap json2AttributeMapper = new ImmutableMap.Builder() .put("project_id", getDefault().PRODUCT.getKey()) //$NON-NLS-1$ .put("description", getDefault().DESCRIPTION.getKey()) //$NON-NLS-1$ diff --git a/mylyn.tasks/org.eclipse.mylyn.tasks.core/src/org/eclipse/mylyn/tasks/core/TaskRepository.java b/mylyn.tasks/org.eclipse.mylyn.tasks.core/src/org/eclipse/mylyn/tasks/core/TaskRepository.java index 9d3cbabd95..75b93a6399 100644 --- a/mylyn.tasks/org.eclipse.mylyn.tasks.core/src/org/eclipse/mylyn/tasks/core/TaskRepository.java +++ b/mylyn.tasks/org.eclipse.mylyn.tasks.core/src/org/eclipse/mylyn/tasks/core/TaskRepository.java @@ -1,10 +1,10 @@ /******************************************************************************* * Copyright (c) 2004, 2015 Tasktop Technologies and others. - * + * * This program and the accompanying materials are made available under the * terms of the Eclipse Public License v. 2.0 which is available at * https://www.eclipse.org/legal/epl-2.0 - * + * * SPDX-License-Identifier: EPL-2.0 * * Contributors: @@ -547,7 +547,7 @@ public boolean hasCredentials() { @Override public int hashCode() { - return getConnectorKind().hashCode(); + return getConnectorKind().hashCode() + 31 * getRepositoryUrl().hashCode(); } public boolean hasProperty(String name) { From 51ae0c1c6de31a18338a34f71dfc31b362ad8de0 Mon Sep 17 00:00:00 2001 From: Frank Becker Date: Mon, 12 Jun 2023 16:47:21 +0200 Subject: [PATCH 04/13] create new tasks --- .../gitlab/core/GitlabConfiguration.java | 58 ++++--- .../gitlab/core/GitlabCoreActivator.java | 3 +- .../gitlab/core/GitlabNewTaskSchema.java | 80 ++++++++++ .../mylyn/gitlab/core/GitlabOperation.java | 4 +- .../gitlab/core/GitlabPostOperation.java | 17 +- .../core/GitlabRepositoryConnector.java | 3 +- .../mylyn/gitlab/core/GitlabRestClient.java | 150 +++++++++++++++--- .../gitlab/core/GitlabTaskDataHandler.java | 15 +- .../mylyn/gitlab/core/GitlabTaskSchema.java | 32 ++-- .../mylyn/gitlab/ui/GitlabConnectorUI.java | 2 +- .../ui/GitlabSearchQueryPageSchema.java | 10 +- .../ui/GitlabTaskEditorPageFactory.java | 4 +- 12 files changed, 270 insertions(+), 108 deletions(-) create mode 100644 mylyn.tasks/connectors/gitlab/org.eclipse.mylyn.gitlab.core/src/org/eclipse/mylyn/gitlab/core/GitlabNewTaskSchema.java diff --git a/mylyn.tasks/connectors/gitlab/org.eclipse.mylyn.gitlab.core/src/org/eclipse/mylyn/gitlab/core/GitlabConfiguration.java b/mylyn.tasks/connectors/gitlab/org.eclipse.mylyn.gitlab.core/src/org/eclipse/mylyn/gitlab/core/GitlabConfiguration.java index 53c6adaf63..29386523e0 100644 --- a/mylyn.tasks/connectors/gitlab/org.eclipse.mylyn.gitlab.core/src/org/eclipse/mylyn/gitlab/core/GitlabConfiguration.java +++ b/mylyn.tasks/connectors/gitlab/org.eclipse.mylyn.gitlab.core/src/org/eclipse/mylyn/gitlab/core/GitlabConfiguration.java @@ -19,7 +19,7 @@ public class GitlabConfiguration implements Serializable { private static final long serialVersionUID = -6859757478504901423L; - + private static final GitlabTaskSchema SCHEMA = GitlabTaskSchema.getDefault(); private final String repositoryURL; private BigInteger userID; @@ -105,38 +105,46 @@ public boolean updateProductOptions(@NonNull TaskData taskData) { } for (JsonElement product : projects) { JsonObject productObject = (JsonObject) product; - attributeProduct.putOption(productObject.get("id").getAsString(), productObject.get("name_with_namespace").getAsString()); - } - TaskAttribute attributeGroups = taskData.getRoot().getMappedAttribute(SCHEMA.GROUP.getKey()); - if (attributeGroups == null) { - return false; - } - Set groups = getGroupNames(); - for (String string : groups) { - attributeGroups.putOption(string, string); + attributeProduct.putOption(productObject.get("id").getAsString(), + productObject.get("name_with_namespace").getAsString()); } TaskAttribute priorityAttrib = taskData.getRoot().getMappedAttribute(SCHEMA.PRIORITY.getKey()); - if (priorityAttrib!=null) { - priorityAttrib.putOption("CRITICAL", "critical"); - priorityAttrib.putOption("HIGH", "high"); - priorityAttrib.putOption("MEDIUM", "Medium"); - priorityAttrib.putOption("LOW", "low"); + if (priorityAttrib != null) { + priorityAttrib.putOption("CRITICAL", "critical"); + priorityAttrib.putOption("HIGH", "high"); + priorityAttrib.putOption("MEDIUM", "Medium"); + priorityAttrib.putOption("LOW", "low"); priorityAttrib.putOption("UNKNOWN", "unknown"); } - TaskAttribute typeAttrib = taskData.getRoot().getMappedAttribute(SCHEMA.ISSUE_TYPE.getKey()); - if (typeAttrib!=null) { + if (typeAttrib != null) { typeAttrib.putOption("issue", "Issue"); - typeAttrib.putOption("incident", "Incident"); + typeAttrib.putOption("incident", "Incident"); + } + + return true; + } + + public boolean updateQueryOptions(@NonNull TaskData taskData) { + if (taskData == null) { + return false; + } + + TaskAttribute attributeGroups = taskData.getRoot().getMappedAttribute("GROUP"); + if (attributeGroups != null) { + Set groups = getGroupNames(); + for (String string : groups) { + attributeGroups.putOption(string, string); + } } TaskAttribute stateAttrib = taskData.getRoot().getMappedAttribute("STATE"); - if (stateAttrib!=null) { + if (stateAttrib != null) { stateAttrib.putOption("opened", "Opened"); stateAttrib.putOption("closed", "Closed"); stateAttrib.putOption("", "All"); } - return true; + return updateProductOptions(taskData); } public String getGroupID(String path) { @@ -147,7 +155,7 @@ public String getGroupID(String path) { } return ""; } - + public void addValidOperations(TaskData bugReport) { TaskAttribute attributeStatus = bugReport.getRoot().getMappedAttribute(TaskAttribute.STATUS); String attributeStatusValue = attributeStatus.getValue(); @@ -160,13 +168,11 @@ public void addValidOperations(TaskData bugReport) { TaskAttribute attribute = bugReport.getRoot().createAttribute(TaskAttribute.PREFIX_OPERATION + "opened"); TaskOperation.applyTo(attribute, attributeStatusValue, attributeStatusValue); - attribute = bugReport.getRoot().createAttribute(TaskAttribute.PREFIX_OPERATION + "closed"); + attribute = bugReport.getRoot().createAttribute(TaskAttribute.PREFIX_OPERATION + "closed"); if (attributeStatusValue.equals("closed")) { - TaskOperation.applyTo(attribute, "reopen", "Reopen"); + TaskOperation.applyTo(attribute, "reopen", "Reopen"); } else { - TaskOperation.applyTo(attribute, "close", "Close"); + TaskOperation.applyTo(attribute, "close", "Close"); } - int i=9; - i++; } } diff --git a/mylyn.tasks/connectors/gitlab/org.eclipse.mylyn.gitlab.core/src/org/eclipse/mylyn/gitlab/core/GitlabCoreActivator.java b/mylyn.tasks/connectors/gitlab/org.eclipse.mylyn.gitlab.core/src/org/eclipse/mylyn/gitlab/core/GitlabCoreActivator.java index f8ef066470..058cb2abfc 100644 --- a/mylyn.tasks/connectors/gitlab/org.eclipse.mylyn.gitlab.core/src/org/eclipse/mylyn/gitlab/core/GitlabCoreActivator.java +++ b/mylyn.tasks/connectors/gitlab/org.eclipse.mylyn.gitlab.core/src/org/eclipse/mylyn/gitlab/core/GitlabCoreActivator.java @@ -24,9 +24,10 @@ public class GitlabCoreActivator extends AbstractUIPlugin { // The plug-in ID public static final String PLUGIN_ID = "org.eclipse.mylyn.gitlab.core"; //$NON-NLS-1$ - public static final String CONNECTOR_KIND = "gitlab"; + public static final String CONNECTOR_KIND = "org.eclipse.mylyn.gitlab"; public static final String GROUPS = "gitlab.groups"; public static final String PROJECTS = "gitlab.projects"; + public static final String API_VERSION = "/api/v4"; // The shared instance private static GitlabCoreActivator plugin; diff --git a/mylyn.tasks/connectors/gitlab/org.eclipse.mylyn.gitlab.core/src/org/eclipse/mylyn/gitlab/core/GitlabNewTaskSchema.java b/mylyn.tasks/connectors/gitlab/org.eclipse.mylyn.gitlab.core/src/org/eclipse/mylyn/gitlab/core/GitlabNewTaskSchema.java new file mode 100644 index 0000000000..aa7edf35cf --- /dev/null +++ b/mylyn.tasks/connectors/gitlab/org.eclipse.mylyn.gitlab.core/src/org/eclipse/mylyn/gitlab/core/GitlabNewTaskSchema.java @@ -0,0 +1,80 @@ +/******************************************************************************* + * Copyright (c) 2023 Frank Becker and others. + * + * This program and the accompanying materials are made available under the + * terms of the Eclipse Public License v. 2.0 which is available at + * https://www.eclipse.org/legal/epl-2.0 + * + * SPDX-License-Identifier: EPL-2.0 + * + * Contributors: + * Frank Becker - initial API and implementation + *******************************************************************************/ + +package org.eclipse.mylyn.gitlab.core; + +import org.eclipse.mylyn.tasks.core.data.AbstractTaskSchema; +import org.eclipse.mylyn.tasks.core.data.DefaultTaskSchema; +import org.eclipse.mylyn.tasks.core.data.TaskAttribute; +import org.eclipse.mylyn.tasks.core.data.AbstractTaskSchema.Field; +import org.eclipse.mylyn.tasks.core.data.AbstractTaskSchema.Flag; + +import com.google.common.collect.ImmutableMap; + +public class GitlabNewTaskSchema extends AbstractTaskSchema { + + private final DefaultTaskSchema parent = DefaultTaskSchema.getInstance(); + + private static final GitlabNewTaskSchema instance = new GitlabNewTaskSchema(); + + public static GitlabNewTaskSchema getDefault() { + return instance; + } + + public final Field PRODUCT = inheritFrom(parent.PRODUCT).addFlags(Flag.REQUIRED).create(); + + public final Field DESCRIPTION = inheritFrom(parent.DESCRIPTION).addFlags(Flag.REQUIRED).create(); + + public final Field SUMMARY = inheritFrom(parent.SUMMARY).addFlags(Flag.REQUIRED).create(); + + public final Field STATUS = inheritFrom(parent.STATUS).create(); + + public final Field PRIORITY = inheritFrom(parent.PRIORITY).create(); + + public final Field ISSUE_TYPE = createField("issue_type", "Issue Type", TaskAttribute.TYPE_SINGLE_SELECT, + Flag.ATTRIBUTE); + + private static ImmutableMap json2AttributeMapper = new ImmutableMap.Builder() + .put("project_id", getDefault().PRODUCT.getKey()) //$NON-NLS-1$ + .put("description", getDefault().DESCRIPTION.getKey()) //$NON-NLS-1$ + .put("title", getDefault().SUMMARY.getKey()) //$NON-NLS-1$ + .put("state", getDefault().STATUS.getKey()) //$NON-NLS-1$ + .put("severity", getDefault().PRIORITY.getKey()) //$NON-NLS-1$ + + .build(); + + private static ImmutableMap attribute2jsonMapper = new ImmutableMap.Builder() + .put(getDefault().PRODUCT.getKey(), "project_id") //$NON-NLS-1$ + .put(getDefault().DESCRIPTION.getKey(), "description") //$NON-NLS-1$ + .put(getDefault().SUMMARY.getKey(), "title") //$NON-NLS-1$ + .put(getDefault().STATUS.getKey(), "state") //$NON-NLS-1$ + .put(getDefault().PRIORITY.getKey(), "severity") //$NON-NLS-1$ + .build(); + + public static String getAttributeNameFromJsonName(String fieldName) { + String result = json2AttributeMapper.get(fieldName); + if (result == null) { + result = fieldName; + } + return result; + } + + public static String getJsonNameFromAttributeName(String attributeName) { + String result = attribute2jsonMapper.get(attributeName); + if (result == null) { + result = attributeName; + } + return result; + } + +} diff --git a/mylyn.tasks/connectors/gitlab/org.eclipse.mylyn.gitlab.core/src/org/eclipse/mylyn/gitlab/core/GitlabOperation.java b/mylyn.tasks/connectors/gitlab/org.eclipse.mylyn.gitlab.core/src/org/eclipse/mylyn/gitlab/core/GitlabOperation.java index 965cfc82c6..826f83b2ce 100644 --- a/mylyn.tasks/connectors/gitlab/org.eclipse.mylyn.gitlab.core/src/org/eclipse/mylyn/gitlab/core/GitlabOperation.java +++ b/mylyn.tasks/connectors/gitlab/org.eclipse.mylyn.gitlab.core/src/org/eclipse/mylyn/gitlab/core/GitlabOperation.java @@ -105,8 +105,8 @@ protected void validate(CommonHttpResponse response, int expected, IOperationMon protected String baseUrl() { String url = getClient().getLocation().getUrl(); - if (!url.endsWith("/api/v4")) { - url += "/api/v4"; + if (!url.endsWith(GitlabCoreActivator.API_VERSION)) { + url += GitlabCoreActivator.API_VERSION; } return url; } diff --git a/mylyn.tasks/connectors/gitlab/org.eclipse.mylyn.gitlab.core/src/org/eclipse/mylyn/gitlab/core/GitlabPostOperation.java b/mylyn.tasks/connectors/gitlab/org.eclipse.mylyn.gitlab.core/src/org/eclipse/mylyn/gitlab/core/GitlabPostOperation.java index 505de9f45f..05fc6f0bbb 100644 --- a/mylyn.tasks/connectors/gitlab/org.eclipse.mylyn.gitlab.core/src/org/eclipse/mylyn/gitlab/core/GitlabPostOperation.java +++ b/mylyn.tasks/connectors/gitlab/org.eclipse.mylyn.gitlab.core/src/org/eclipse/mylyn/gitlab/core/GitlabPostOperation.java @@ -13,19 +13,14 @@ package org.eclipse.mylyn.gitlab.core; -import java.io.UnsupportedEncodingException; - import org.apache.http.client.methods.HttpPost; import org.apache.http.client.methods.HttpRequestBase; -import org.apache.http.entity.StringEntity; import org.eclipse.mylyn.commons.repositories.http.core.CommonHttpClient; public abstract class GitlabPostOperation extends GitlabOperation { - private final String body; - public GitlabPostOperation(CommonHttpClient client, String urlSuffix, String body) { + public GitlabPostOperation(CommonHttpClient client, String urlSuffix) { super(client, urlSuffix); - this.body = body; } @Override @@ -34,15 +29,5 @@ protected HttpRequestBase createHttpRequestBase(String url) { return request; } - protected void addHttpRequestEntities(HttpRequestBase request) throws GitlabException { - super.addHttpRequestEntities(request); - request.setHeader(CONTENT_TYPE, APPLICATION_JSON); - try { - ((HttpPost) request).setEntity(new StringEntity(body)); - } catch (UnsupportedEncodingException e) { - throw new GitlabException(e); - } - }; - } diff --git a/mylyn.tasks/connectors/gitlab/org.eclipse.mylyn.gitlab.core/src/org/eclipse/mylyn/gitlab/core/GitlabRepositoryConnector.java b/mylyn.tasks/connectors/gitlab/org.eclipse.mylyn.gitlab.core/src/org/eclipse/mylyn/gitlab/core/GitlabRepositoryConnector.java index e8bb49634c..86c515866d 100644 --- a/mylyn.tasks/connectors/gitlab/org.eclipse.mylyn.gitlab.core/src/org/eclipse/mylyn/gitlab/core/GitlabRepositoryConnector.java +++ b/mylyn.tasks/connectors/gitlab/org.eclipse.mylyn.gitlab.core/src/org/eclipse/mylyn/gitlab/core/GitlabRepositoryConnector.java @@ -285,8 +285,7 @@ public GitlabConfiguration getRepositoryConfiguration(TaskRepository repository) @Override public boolean canCreateNewTask(@NonNull TaskRepository repository) { - // TODO Auto-generated method stub - return false; + return true; } @Override diff --git a/mylyn.tasks/connectors/gitlab/org.eclipse.mylyn.gitlab.core/src/org/eclipse/mylyn/gitlab/core/GitlabRestClient.java b/mylyn.tasks/connectors/gitlab/org.eclipse.mylyn.gitlab.core/src/org/eclipse/mylyn/gitlab/core/GitlabRestClient.java index c55ad3871c..710786762b 100644 --- a/mylyn.tasks/connectors/gitlab/org.eclipse.mylyn.gitlab.core/src/org/eclipse/mylyn/gitlab/core/GitlabRestClient.java +++ b/mylyn.tasks/connectors/gitlab/org.eclipse.mylyn.gitlab.core/src/org/eclipse/mylyn/gitlab/core/GitlabRestClient.java @@ -17,6 +17,7 @@ import java.io.IOException; import java.io.InputStreamReader; import java.io.PrintStream; +import java.io.UnsupportedEncodingException; import java.lang.reflect.Type; import java.net.HttpURLConnection; import java.net.URL; @@ -32,7 +33,9 @@ import org.apache.http.HttpStatus; import org.apache.http.client.methods.HttpGet; +import org.apache.http.client.methods.HttpPost; import org.apache.http.client.methods.HttpRequestBase; +import org.apache.http.entity.StringEntity; import org.eclipse.core.runtime.CoreException; import org.eclipse.core.runtime.IProgressMonitor; import org.eclipse.core.runtime.ISafeRunnable; @@ -67,7 +70,10 @@ import com.google.gson.JsonElement; import com.google.gson.JsonObject; import com.google.gson.JsonParseException; +import com.google.gson.TypeAdapter; import com.google.gson.reflect.TypeToken; +import com.google.gson.stream.JsonReader; +import com.google.gson.stream.JsonWriter; public class GitlabRestClient { @@ -105,7 +111,7 @@ public IStatus getIssues(IRepositoryQuery query, TaskDataCollector collector, fi throws GitlabException, CoreException { getAccessTokenIfNotPresent(monitor); String[] queryProjects = query.getAttribute(GitlabTaskSchema.getDefault().PRODUCT.getKey()).split(","); - String[] gueryGroups = query.getAttribute(GitlabTaskSchema.getDefault().GROUP.getKey()).split(","); + String groupAttribute = query.getAttribute("group"); if (!queryProjects[0].isEmpty()) { for (String string : queryProjects) { @@ -113,13 +119,15 @@ public IStatus getIssues(IRepositoryQuery query, TaskDataCollector collector, fi getIssuesInternal(query, collector, path, monitor); } } - if (!gueryGroups[0].isEmpty()) { - for (String string : gueryGroups) { - String path = "/groups/" + string.replaceAll("/", "%2F"); - getIssuesInternal(query, collector, path, monitor); + if (groupAttribute != null) { + String[] gueryGroups = groupAttribute.split(","); + if (!gueryGroups[0].isEmpty()) { + for (String string : gueryGroups) { + String path = "/groups/" + string.replaceAll("/", "%2F"); + getIssuesInternal(query, collector, path, monitor); + } } } - return Status.OK_STATUS; } @@ -272,21 +280,16 @@ public ArrayList deserialize(JsonElement json, Type typeOfT, JsonDeser private TaskData getFromJson(JsonObject jo) { GitlabTaskDataHandler dataHandler = (GitlabTaskDataHandler) connector.getTaskDataHandler(); TaskAttributeMapper mapper = dataHandler.getAttributeMapper(taskRepository); - - TaskData response = null; String selfString = jo.get("_links").getAsJsonObject().get("self").getAsString(); - - TaskData taskData = null; - taskData = new TaskData(mapper, connector.getConnectorKind(), taskRepository.getRepositoryUrl(), selfString); - response = taskData; + TaskData response = new TaskData(mapper, connector.getConnectorKind(), taskRepository.getRepositoryUrl(), selfString.replace(taskRepository.getUrl() + GitlabCoreActivator.API_VERSION, "")); try { - dataHandler.initializeTaskData(taskRepository, taskData, null, null); + dataHandler.initializeTaskData(taskRepository, response, null, null); } catch (CoreException e) { throw new RuntimeException(e); } for (Entry entry : jo.entrySet()) { String attributeId = GitlabTaskSchema.getAttributeNameFromJsonName(entry.getKey()); - TaskAttribute attribute = taskData.getRoot().getAttribute(attributeId); + TaskAttribute attribute = response.getRoot().getAttribute(attributeId); Field field = GitlabTaskSchema.getDefault().getFieldByKey(attributeId); if (attribute == null) { PrintStream ps = attribute == null ? System.err : System.out; @@ -320,7 +323,6 @@ public TaskData deserialize(JsonElement json, Type typeOfT, JsonDeserializationC } return taskData; } - } private GitlabConfiguration getConfiguration() { @@ -384,14 +386,11 @@ public String obtainAccessToken(IOperationMonitor monitor) throws Exception { public TaskData getTaskData(TaskRepository repository, String taskId, IProgressMonitor monitor) throws GitlabException { - String searchString = ".+(/projects/\\d+)/issues/(\\d+)"; + TaskData result = null; + String searchString = ".*(/projects/\\d+)/issues/(\\d+)"; Pattern pattern = Pattern.compile(searchString, Pattern.CASE_INSENSITIVE); Matcher matcher = pattern.matcher(taskId); if (matcher.find()) { - TaskData result; -// System.out.println("found: " + matcher.group(0)); -// System.out.println(" " + matcher.group(1)); -// System.out.println(" " + matcher.group(2)); GitlabConfiguration config = getConfiguration(); JsonObject iss = getIssue(matcher.group(1), matcher.group(2), OperationUtil.convert(monitor)); TypeToken type = new TypeToken() { @@ -427,10 +426,8 @@ public TaskData getTaskData(TaskRepository repository, String taskId, IProgressM // } config.updateProductOptions(result); - - return result; } - return null; + return result; } private int createNoteTaskAttribute(TaskRepository repository, TaskData result, int i, JsonObject note) { @@ -698,7 +695,18 @@ public JsonElement createIssueNote(String path, String id, String body, IOperati throws GitlabException { getAccessTokenIfNotPresent(monitor); JsonObject jsonElement; - jsonElement = new GitlabPostOperation(client, path + "/issues/" + id + "/notes", body) { + jsonElement = new GitlabPostOperation(client, path + "/issues/" + id + "/notes") { + + @Override + protected void addHttpRequestEntities(HttpRequestBase request) throws GitlabException { + super.addHttpRequestEntities(request); + request.setHeader(CONTENT_TYPE, APPLICATION_JSON); + try { + ((HttpPost) request).setEntity(new StringEntity(body)); + } catch (UnsupportedEncodingException e) { + throw new GitlabException(e); + } + }; @Override protected void doValidate(CommonHttpResponse response, IOperationMonitor monitor) @@ -789,6 +797,19 @@ public GitlabConfiguration getConfiguration(TaskRepository repository, IOperatio public RepositoryResponse postTaskData(TaskData taskData, Set oldAttributes, IOperationMonitor monitor) throws GitlabException { + if (taskData.isNew()) { + JsonElement result = createNewIssue(taskData, monitor); + JsonObject resObj = (JsonObject) result; + String newID = resObj.get("iid").getAsString(); + String projectID = resObj.get("project_id").getAsString(); + return new RepositoryResponse(ResponseKind.TASK_CREATED, "/projects/" + projectID + "/issues/" + newID); + } else { + return updateExistingIssue(taskData, oldAttributes, monitor); + } + } + + private RepositoryResponse updateExistingIssue(TaskData taskData, Set oldAttributes, + IOperationMonitor monitor) throws GitlabException { ArrayList changedAtributes = new ArrayList<>(); String newComentValue = ""; for (TaskAttribute taskAttribute : oldAttributes) { @@ -826,4 +847,85 @@ public RepositoryResponse postTaskData(TaskData taskData, Set old } return new RepositoryResponse(ResponseKind.TASK_UPDATED, taskData.getTaskId()); } + + public JsonElement createNewIssue(TaskData taskData, IOperationMonitor monitor) throws GitlabException { + getAccessTokenIfNotPresent(monitor); + TaskAttribute productAttribute = taskData.getRoot() + .getAttribute(GitlabTaskSchema.getDefault().PRODUCT.getKey()); + if (productAttribute == null || productAttribute.getValue().isEmpty()) { + throw new GitlabException("productAttribute should not be null"); + } + JsonObject jsonElement; + jsonElement = new GitlabPostOperation(client, + "/projects/" + productAttribute.getValue() + "/issues") { + + protected void addHttpRequestEntities(HttpRequestBase request) throws GitlabException { + super.addHttpRequestEntities(request); + request.setHeader(CONTENT_TYPE, APPLICATION_JSON); + Gson gson = new GsonBuilder().registerTypeAdapter(TaskData.class, new TaskAttributeTypeAdapter()) + .create(); + String jsondata = gson.toJson(taskData); + try { + ((HttpPost) request).setEntity(new StringEntity(jsondata)); + } catch (UnsupportedEncodingException e) { + throw new GitlabException(e); + } + }; + + @Override + protected void doValidate(CommonHttpResponse response, IOperationMonitor monitor) + throws IOException, GitlabException { + validate(response, HttpStatus.SC_CREATED, monitor); + } + + @Override + protected JsonObject parseFromJson(InputStreamReader in) throws GitlabException { + return new Gson().fromJson(in, JsonObject.class); + } + }.run(monitor); + return jsonElement; + } + + class TaskAttributeTypeAdapter extends TypeAdapter { + + @Override + public void write(JsonWriter out, TaskData taskData) throws IOException { + out.beginObject(); + for (TaskAttribute taskAttribute : taskData.getRoot().getAttributes().values()) { + String id = taskAttribute.getId(); + String attributValue = convertString2GSonString(taskAttribute.getValue()); + id = GitlabNewTaskSchema.getJsonNameFromAttributeName(id); + if ("project_id".equals(id) || "state".equals(id)) { + continue; + } + out.name(id).value(attributValue); + } + out.endObject(); + } + + @Override + public TaskData read(JsonReader in) throws IOException { + throw new UnsupportedOperationException("TaskAttributeTypeAdapter in GitlabRestClient only supports write"); //$NON-NLS-1$ + } + } + + public static String convertString2GSonString(String str) { + str = str.replace("\"", "\\\"").replace("\n", "\\\n"); //$NON-NLS-1$//$NON-NLS-2$ //$NON-NLS-3$//$NON-NLS-4$ + StringBuffer ostr = new StringBuffer(); + for (int i = 0; i < str.length(); i++) { + char ch = str.charAt(i); + if ((ch >= 0x0020) && (ch <= 0x007e)) { + ostr.append(ch); + } else { + ostr.append("\\u"); //$NON-NLS-1$ + String hex = Integer.toHexString(str.charAt(i) & 0xFFFF); + for (int j = 0; j < 4 - hex.length(); j++) { + ostr.append("0"); //$NON-NLS-1$ + } + ostr.append(hex.toLowerCase()); + } + } + return (new String(ostr)); + } + } diff --git a/mylyn.tasks/connectors/gitlab/org.eclipse.mylyn.gitlab.core/src/org/eclipse/mylyn/gitlab/core/GitlabTaskDataHandler.java b/mylyn.tasks/connectors/gitlab/org.eclipse.mylyn.gitlab.core/src/org/eclipse/mylyn/gitlab/core/GitlabTaskDataHandler.java index 2aa6ae3f1f..09bb68828f 100644 --- a/mylyn.tasks/connectors/gitlab/org.eclipse.mylyn.gitlab.core/src/org/eclipse/mylyn/gitlab/core/GitlabTaskDataHandler.java +++ b/mylyn.tasks/connectors/gitlab/org.eclipse.mylyn.gitlab.core/src/org/eclipse/mylyn/gitlab/core/GitlabTaskDataHandler.java @@ -67,15 +67,18 @@ public boolean initializeTaskData(TaskRepository repository, TaskData data, ITas // fresh from the repository (not locally stored data that may not have // been migrated). data.setVersion("0"); //$NON-NLS-1$ -// if (data.isNew()) { -// BugzillaRestCreateTaskSchema.getDefault().initialize(data); -// } else { -// BugzillaRestTaskSchema.getDefault().initialize(data); -// } - GitlabTaskSchema.getDefault().initialize(data); + if (data.isNew()) { + GitlabNewTaskSchema.getDefault().initialize(data); + } else { + GitlabTaskSchema.getDefault().initialize(data); + } if (initializationData != null) { connector.getTaskMapping(data).merge(initializationData); } + GitlabConfiguration config = connector.getRepositoryConfiguration(repository); + if (config != null) { + config.updateProductOptions(data); + } return true; } diff --git a/mylyn.tasks/connectors/gitlab/org.eclipse.mylyn.gitlab.core/src/org/eclipse/mylyn/gitlab/core/GitlabTaskSchema.java b/mylyn.tasks/connectors/gitlab/org.eclipse.mylyn.gitlab.core/src/org/eclipse/mylyn/gitlab/core/GitlabTaskSchema.java index 1bfcf32fca..552302b329 100644 --- a/mylyn.tasks/connectors/gitlab/org.eclipse.mylyn.gitlab.core/src/org/eclipse/mylyn/gitlab/core/GitlabTaskSchema.java +++ b/mylyn.tasks/connectors/gitlab/org.eclipse.mylyn.gitlab.core/src/org/eclipse/mylyn/gitlab/core/GitlabTaskSchema.java @@ -21,7 +21,7 @@ import com.google.common.collect.ImmutableMap; -public class GitlabTaskSchema extends AbstractTaskSchema { +public class GitlabTaskSchema extends GitlabNewTaskSchema { private final DefaultTaskSchema parent = DefaultTaskSchema.getInstance(); @@ -31,16 +31,6 @@ public static GitlabTaskSchema getDefault() { return instance; } - public final Field PRODUCT = inheritFrom(parent.PRODUCT).addFlags(Flag.REQUIRED).create(); - - public final Field DESCRIPTION = inheritFrom(parent.DESCRIPTION).addFlags(Flag.REQUIRED).create(); - - public final Field SUMMARY = inheritFrom(parent.SUMMARY).addFlags(Flag.REQUIRED).create(); - - public final Field STATUS = inheritFrom(parent.STATUS).create(); - - public final Field ASSIGNED_TO = inheritFrom(parent.USER_ASSIGNED).label("Assigned to").create(); - public final Field CREATED = inheritFrom(parent.DATE_CREATION).create(); public final Field UPDATED = inheritFrom(parent.DATE_MODIFICATION).create(); @@ -53,11 +43,6 @@ public static GitlabTaskSchema getDefault() { public final Field URL = inheritFrom(parent.TASK_URL).addFlags(Flag.ATTRIBUTE).create(); - public final Field PRIORITY = inheritFrom(parent.PRIORITY).create(); - - public final Field ISSUE_TYPE = createField("issue_type", "Issue Type", TaskAttribute.TYPE_SINGLE_SELECT, - Flag.ATTRIBUTE); - public final Field USER_NOTES_COUNT = createField("user_notes_count", "User Notes Count", TaskAttribute.TYPE_INTEGER, Flag.ATTRIBUTE); @@ -71,13 +56,8 @@ public static GitlabTaskSchema getDefault() { public final Field DOWNVOTES = createField("downvotes", "Down Notes", TaskAttribute.TYPE_INTEGER, Flag.ATTRIBUTE); - public final Field TYPE = createField("type", "Type", TaskAttribute.TYPE_SHORT_TEXT, Flag.ATTRIBUTE); - // public final Field WEB_URL = createField("web_url", "WEB URL", TaskAttribute.TYPE_SHORT_TEXT, Flag.ATTRIBUTE); - public final Field TASK_STATUS = createField("task_status", "Task Status", TaskAttribute.TYPE_SHORT_TEXT, - Flag.ATTRIBUTE); - public final Field HAS_TASKS = createField("has_tasks", "has Tasks", TaskAttribute.TYPE_BOOLEAN, Flag.ATTRIBUTE); public final Field SUBSCRIBED = createField("subscribed", "subscribed", TaskAttribute.TYPE_BOOLEAN, Flag.ATTRIBUTE); @@ -90,12 +70,18 @@ public static GitlabTaskSchema getDefault() { public final Field DISCUSSION_LOCKED = createField("discussion_locked", "Discussion locked", TaskAttribute.TYPE_BOOLEAN, Flag.ATTRIBUTE); - public final Field GROUP = createField("group", "Group", TaskAttribute.TYPE_SHORT_TEXT); public final Field IID = createField("iid", "interne ID", TaskAttribute.TYPE_SHORT_TEXT, Flag.ATTRIBUTE); public final Field OPERATION = createField(TaskAttribute.OPERATION, "Operation", TaskAttribute.TYPE_OPERATION); public final Field CLOSED_BY = createField("closed_by", "closed by", TaskAttribute.TYPE_PERSON, Flag.PEOPLE, //$NON-NLS-1$ Flag.READ_ONLY); - + + public final Field ASSIGNED_TO = inheritFrom(parent.USER_ASSIGNED).label("Assigned to").create(); + + public final Field TYPE = createField("type", "Type", TaskAttribute.TYPE_SHORT_TEXT, Flag.ATTRIBUTE); + + public final Field TASK_STATUS = createField("task_status", "Task Status", TaskAttribute.TYPE_SHORT_TEXT, + Flag.ATTRIBUTE); + public final Field DUE_DATE = createField("due_date", "Due date", TaskAttribute.TYPE_DATE, Flag.ATTRIBUTE); private static ImmutableMap json2AttributeMapper = new ImmutableMap.Builder() .put("project_id", getDefault().PRODUCT.getKey()) //$NON-NLS-1$ diff --git a/mylyn.tasks/connectors/gitlab/org.eclipse.mylyn.gitlab.ui/src/org/eclipse/mylyn/gitlab/ui/GitlabConnectorUI.java b/mylyn.tasks/connectors/gitlab/org.eclipse.mylyn.gitlab.ui/src/org/eclipse/mylyn/gitlab/ui/GitlabConnectorUI.java index 595ca8fb0f..6a0db7cd64 100644 --- a/mylyn.tasks/connectors/gitlab/org.eclipse.mylyn.gitlab.ui/src/org/eclipse/mylyn/gitlab/ui/GitlabConnectorUI.java +++ b/mylyn.tasks/connectors/gitlab/org.eclipse.mylyn.gitlab.ui/src/org/eclipse/mylyn/gitlab/ui/GitlabConnectorUI.java @@ -52,7 +52,7 @@ public IWizard getQueryWizard(TaskRepository repository, IRepositoryQuery query) GitlabSearchQueryPageSchema.getInstance().initialize(taskData); try { GitlabConfiguration config = connector.getRepositoryConfiguration(repository); - config.updateProductOptions(taskData); + config.updateQueryOptions(taskData); } catch (CoreException e) { // TODO Auto-generated catch block e.printStackTrace(); diff --git a/mylyn.tasks/connectors/gitlab/org.eclipse.mylyn.gitlab.ui/src/org/eclipse/mylyn/gitlab/ui/GitlabSearchQueryPageSchema.java b/mylyn.tasks/connectors/gitlab/org.eclipse.mylyn.gitlab.ui/src/org/eclipse/mylyn/gitlab/ui/GitlabSearchQueryPageSchema.java index 1d1b031b34..92adfb856a 100644 --- a/mylyn.tasks/connectors/gitlab/org.eclipse.mylyn.gitlab.ui/src/org/eclipse/mylyn/gitlab/ui/GitlabSearchQueryPageSchema.java +++ b/mylyn.tasks/connectors/gitlab/org.eclipse.mylyn.gitlab.ui/src/org/eclipse/mylyn/gitlab/ui/GitlabSearchQueryPageSchema.java @@ -1,15 +1,14 @@ package org.eclipse.mylyn.gitlab.ui; +import org.eclipse.mylyn.gitlab.core.GitlabNewTaskSchema; import org.eclipse.mylyn.gitlab.core.GitlabTaskSchema; import org.eclipse.mylyn.internal.provisional.tasks.ui.wizards.AbstractQueryPageSchema; -import org.eclipse.mylyn.internal.provisional.tasks.ui.wizards.AbstractQueryPageSchema.Field; import org.eclipse.mylyn.tasks.core.data.TaskAttribute; -import org.eclipse.mylyn.tasks.core.data.AbstractTaskSchema.Flag; public class GitlabSearchQueryPageSchema extends AbstractQueryPageSchema { private static final GitlabSearchQueryPageSchema instance = new GitlabSearchQueryPageSchema(); - private final GitlabTaskSchema parent = GitlabTaskSchema.getDefault(); + private final GitlabNewTaskSchema parent = GitlabNewTaskSchema.getDefault(); public static GitlabSearchQueryPageSchema getInstance() { return instance; @@ -21,9 +20,8 @@ public GitlabSearchQueryPageSchema() { public final Field product = copyFrom(parent.PRODUCT).type(TaskAttribute.TYPE_MULTI_SELECT) .layoutPriority(11) .create(); - public final Field group = copyFrom(parent.GROUP).type(TaskAttribute.TYPE_MULTI_SELECT) - .layoutPriority(11) - .create(); + public final Field group = createField("GROUP", "Group", TaskAttribute.TYPE_MULTI_SELECT, + null, 11); public final Field state = createField("STATE", "State", TaskAttribute.TYPE_SINGLE_SELECT, null, 1); } diff --git a/mylyn.tasks/connectors/gitlab/org.eclipse.mylyn.gitlab.ui/src/org/eclipse/mylyn/gitlab/ui/GitlabTaskEditorPageFactory.java b/mylyn.tasks/connectors/gitlab/org.eclipse.mylyn.gitlab.ui/src/org/eclipse/mylyn/gitlab/ui/GitlabTaskEditorPageFactory.java index db266b740c..b1b013ea9b 100644 --- a/mylyn.tasks/connectors/gitlab/org.eclipse.mylyn.gitlab.ui/src/org/eclipse/mylyn/gitlab/ui/GitlabTaskEditorPageFactory.java +++ b/mylyn.tasks/connectors/gitlab/org.eclipse.mylyn.gitlab.ui/src/org/eclipse/mylyn/gitlab/ui/GitlabTaskEditorPageFactory.java @@ -16,6 +16,7 @@ import org.eclipse.mylyn.commons.ui.CommonImages; import org.eclipse.mylyn.gitlab.core.GitlabCoreActivator; import org.eclipse.mylyn.tasks.ui.TasksUiImages; +import org.eclipse.mylyn.tasks.ui.TasksUiUtil; import org.eclipse.mylyn.tasks.ui.editors.AbstractTaskEditorPageFactory; import org.eclipse.mylyn.tasks.ui.editors.TaskEditor; import org.eclipse.mylyn.tasks.ui.editors.TaskEditorInput; @@ -26,7 +27,8 @@ public class GitlabTaskEditorPageFactory extends AbstractTaskEditorPageFactory { @Override public boolean canCreatePageFor(TaskEditorInput input) { - if (input.getTask().getConnectorKind().equals(GitlabCoreActivator.CONNECTOR_KIND)) { + if (input.getTask().getConnectorKind().equals(GitlabCoreActivator.CONNECTOR_KIND) + || TasksUiUtil.isOutgoingNewTask(input.getTask(), GitlabCoreActivator.CONNECTOR_KIND)) { return true; } return false; From f47e3cc5614ad4cdd9bd357f1fa8608a0a2c0bff Mon Sep 17 00:00:00 2001 From: Frank Becker Date: Mon, 12 Jun 2023 17:54:53 +0200 Subject: [PATCH 05/13] fix failing unittest --- .../src/org/eclipse/mylyn/tasks/core/TaskRepository.java | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/mylyn.tasks/org.eclipse.mylyn.tasks.core/src/org/eclipse/mylyn/tasks/core/TaskRepository.java b/mylyn.tasks/org.eclipse.mylyn.tasks.core/src/org/eclipse/mylyn/tasks/core/TaskRepository.java index 75b93a6399..7395c80e6b 100644 --- a/mylyn.tasks/org.eclipse.mylyn.tasks.core/src/org/eclipse/mylyn/tasks/core/TaskRepository.java +++ b/mylyn.tasks/org.eclipse.mylyn.tasks.core/src/org/eclipse/mylyn/tasks/core/TaskRepository.java @@ -547,7 +547,10 @@ public boolean hasCredentials() { @Override public int hashCode() { - return getConnectorKind().hashCode() + 31 * getRepositoryUrl().hashCode(); + // do not add the URL to the hash + // equals use ConnectorKind and URL + // org.eclipse.mylyn.tasks.tests.TaskRepositoryManagerTest.testDeletion() fails with the URL + return getConnectorKind().hashCode(); } public boolean hasProperty(String name) { From a4e2e3f103a78fa4b61aa8de84311be41fa57611 Mon Sep 17 00:00:00 2001 From: Frank Becker Date: Sun, 9 Jul 2023 18:24:13 +0200 Subject: [PATCH 06/13] Switch from Comment to Discussion in TaskEditor Page --- .../.settings/.api_filters | 16 + .../icons/obj16/gitlab.png | Bin 0 -> 1055 bytes .../icons/obj48/gitlab.png | Bin 0 -> 6493 bytes .../mylyn/commons/ui/CommonImages.java | 6 +- .../mylyn/gitlab/core/GitlabRestClient.java | 58 ++-- .../gitlab/core/GitlabTaskCommentMapper.java | 7 + .../icons/eview16/gitlab-icon.gif | Bin 1431 -> 0 bytes .../icons/eview16/gitlab-icon.png | Bin 0 -> 1019 bytes .../icons/eview16/gitlab-icon38.png | Bin 0 -> 1130 bytes .../icons/eview16/gitlab-overlay.gif | Bin 276 -> 0 bytes .../icons/eview16/gitlab-overlay.png | Bin 0 -> 758 bytes .../org.eclipse.mylyn.gitlab.ui/plugin.xml | 4 +- .../ui/GitlabTaskEditorCommentPart.java | 290 ++++++++++++++++++ .../mylyn/gitlab/ui/GitlabTaskEditorPage.java | 25 +- .../internal/tasks/ui/editors/EditorUtil.java | 22 +- .../ui/editors/TaskEditorCommentPart.java | 54 ++-- org.eclipse.mylyn-target/mylyn-e4.28.target | 2 +- 17 files changed, 414 insertions(+), 70 deletions(-) create mode 100644 mylyn.commons/org.eclipse.mylyn.commons.ui/.settings/.api_filters create mode 100644 mylyn.commons/org.eclipse.mylyn.commons.ui/icons/obj16/gitlab.png create mode 100644 mylyn.commons/org.eclipse.mylyn.commons.ui/icons/obj48/gitlab.png create mode 100644 mylyn.tasks/connectors/gitlab/org.eclipse.mylyn.gitlab.core/src/org/eclipse/mylyn/gitlab/core/GitlabTaskCommentMapper.java delete mode 100644 mylyn.tasks/connectors/gitlab/org.eclipse.mylyn.gitlab.ui/icons/eview16/gitlab-icon.gif create mode 100644 mylyn.tasks/connectors/gitlab/org.eclipse.mylyn.gitlab.ui/icons/eview16/gitlab-icon.png create mode 100644 mylyn.tasks/connectors/gitlab/org.eclipse.mylyn.gitlab.ui/icons/eview16/gitlab-icon38.png delete mode 100644 mylyn.tasks/connectors/gitlab/org.eclipse.mylyn.gitlab.ui/icons/eview16/gitlab-overlay.gif create mode 100644 mylyn.tasks/connectors/gitlab/org.eclipse.mylyn.gitlab.ui/icons/eview16/gitlab-overlay.png create mode 100644 mylyn.tasks/connectors/gitlab/org.eclipse.mylyn.gitlab.ui/src/org/eclipse/mylyn/gitlab/ui/GitlabTaskEditorCommentPart.java diff --git a/mylyn.commons/org.eclipse.mylyn.commons.ui/.settings/.api_filters b/mylyn.commons/org.eclipse.mylyn.commons.ui/.settings/.api_filters new file mode 100644 index 0000000000..e9799d8f15 --- /dev/null +++ b/mylyn.commons/org.eclipse.mylyn.commons.ui/.settings/.api_filters @@ -0,0 +1,16 @@ + + + + + + + + + + + + + + + + diff --git a/mylyn.commons/org.eclipse.mylyn.commons.ui/icons/obj16/gitlab.png b/mylyn.commons/org.eclipse.mylyn.commons.ui/icons/obj16/gitlab.png new file mode 100644 index 0000000000000000000000000000000000000000..d7f648155f60ec5e6b717852a04e8c685265a3ad GIT binary patch literal 1055 zcmV+)1mOFLP)EX>4Tx04R}tkv&MmKpe$iQ>7vmhjtKg$WS|35G&%SRVYG*P%E_RU~=gfG%+M8 zE{=k0!NHHks)LKOt`4q(Aou~|>f)s6A|?JWDYS_3;J6>}?mh0_0YbCJG^=ME&~)3( zrc+|Rup)+D5rTjS;z-KOGG-+y1K;s=j{slq5;;BvB z;Ji;9WffT^J|`YC>4LKlt6PRZ32HN#PXG`{Fnsqd;gEXf+(?``B?>CqVESxY9fRjV3VtNqVEB z#g2f%ZQ$a%qbYm9A(Ki)<$Su&n>h;#%$LRx*qpmVHz`-F9 zFH`oK&%67&d;9lHyT2cmv2wM|dNmRN000JJOGiWi{{a60|De66lK=n!32;bRa{vG? zBLDy{BLR4&KXw2B00(qQO+^Ri2Lcl?JFk&f{{R308FWQhbVF}#ZDnqB07G(RVRU6= zAa`kWXdp*PO;A^X4i^9b0r*KoK~y-)jgn1I6Hyd~pF3@xeo#N!LP#(O8;mS)B_^(1 zyHOJtZuJMaG;w9ZhJ`Er3mOeX6HSb$F@i=#BI<$^iBSwx5wwL8oDS2OxyQw{Q&2~J zlbf4+KAw|v&P5vXYBj08d?Ejm^=V%0&!zBf(9p)4X*Pz>Q?ITODG}C3u2Q{u9T5S* z2<(D&?>6$If<5;xGQYmMiuY;)ckBlBa=8VtON;2KF#zo66On-0ToJ0v;5k^+Q!Rk? z>`55pPCjDu`!}@fZaaS6!G8L<1-mnXc3qTfS@QMFNvM=Ur|RxUrP_Y!U!&(|z;i;= zo-3oo)x8uaAEMukxGc7o~6>Ccd+KtFmknIrK zavG(;|1yiAa_ynt%n0qhK4$j!`mr65->1pugJb~JwI9Ri8$fpqwgTgj+pEcT3aar- zlDmXLkB^z&0*+-cjvPaYi1;f@$hBeA!ozJ<9Y^5_q)iE{0!XF@P7e`3csKw6h+V^b zFp4pL3B-dW&`WTafZ*St`%Yk-I!COtD`=w$2sWkhi?8AS5UTJV5={qCP9g^`5IcGt zl}xqfx)sorUtK{@UdE{03i8c<7`#Zldw_5-e**xB>)_AaMb1^@s672Hr}000UxX+uL$Nkc;* zaB^>EX>4Tx07!|QmUmQB*%pV-y*Is3k`RiN&}(Q?0!R(LNRcioF$oY#z>okUHbhi# zL{X8Z2r?+(fTKf^u_B6v0a3B*1Q|rsac~qHmPur-8Q;8l@6DUvANPK1pS{oBXYYO1 zx&V;;g9XA&SP6g(p;#2*=f#MPi)Ua50Sxc}18e}`aI>>Q7WhU2nF4&+jBJ?`_!qsp z4j}paD$_rV!2tiCl(|_VF#u4QjOX(B*<2YH$v8b%oF%tU$(Xh@P0lb%&LUZYGFFpw z@+@0?_L*f5IrB1vJQ>S#&f;b8cV}o=_hCs$|GJ-ARc>v%@$zSl&FIdda6Uz_9&dgda5+tXH875p)hK-XG zi{a1DP3Mcn%rFi&jU(bQ*qIqw9N}^RX3zXt6nSkKvLZX!I5{{lZ7prSDAa#l{F{>Z zc9vd*f9@GXANa%eSALld0I;TIwb}ZIZD|z%UF!i*yZwjFU@riQvc7c=eQ_STd|pz- z;w)z?tK8gNO97v2DKF^n`kxMeLtlK)Qoh~qM8wF>;&Ay4 z=AVc79|!(*9u^V&B)*6*lto0#rc5AAmbF{R6Nm+wLWV&2pPKj&!~Ue%xt59A_z}>S zSOTRX8bE#?04OREAPIY9E70$K3&uwS`OS;bnV6mX&w~DaSGY|6$QC4jj$=neGPn{^ z&g`1}S^_j607XCp>OdRl0~5dmw!jg%01w~;0zoK<1aV+7;DQv80Yo4d6o9p$7?gso zU?->sb)XS6gEnv&bb({wG&lz?fy-b7+yPQB4xWH1@CwX85QK%u5EW8~bRa{>9I}O2 zkQ?L!1w#=~9FzzpLqbRb6+r8tQm7oNhU%ea=v(M0bQ-z<4MVq}QD_qS6?z9FFbSr? zTCfpp1+!pJI0%k}7s1K!GB_VDg15kxa07f0?u1Xnm*5dt3O|9T5r7a8I--j(5f;Km zLXmhR2@xTykP@TC$XgT!MMW`COq2`C9~Fh-qL!gnp*EwcQ3p_+ zs6NzH)F^5S^$|@*Yog83&gcMiEIJvTi!Mf2pqtPg=(Fe%^f>wz27{qvj4_TFe@q-E z6|(}f8M7PHjyZ)H#*AU6u~@7+)*S1K4aIV>Vr((C3VRTH5_<(Zj(vk8;&gDfIA2^m zPKYbSRp451CvaDA6Sx_?65bH+j1R^0@XPUK_(psWeh5E~pCKp{j0vuUNJ1)MEuoUo zMmS5jOL##f67`5q#Bid3xQ19sJVZQC93{RbQAlPaHYtH5A#EY;C!HeQBE2A!$wp)k zay(f~-a>9BpCR8TzfqtnSSkc4@Dx@n)F^Z+Tv2$Yh*vaJ^i*7|n6Fr&ctmkX@u?DC z$w-N<#8FzMRHJlM>4ws@GF90|IaE1Ad9!kh@&)Bb6fDJv;zQw4iYWUiXDDM-gsM+v zQ@PZ2)JE!A>NpKUGo}U5QfZ~MZ)k(GDHV!}ol3Myo=T0%aTO^Yp&QWy=;`z_`eFKY z`a4xERZmsE>L%4T)hnv6)#j*qsPWZG)Y{cX)ZVEx)P2;`)VHa3so&E;X_#q*YvgL| z(KxH|bPjEf%N*{Uk~xRx+}4CO%`_u4S7`3j9MGKB($@0R%F?RRI-~Veo38DlovOV< z`-JwS4pqlZN1(Gq=cLYKh6=-zkLZ@rEqJ6vJJH{f4iNjE!Q9HW+moJu+4^4lvF)ZZ*DZ zLN;+XS!U8;a?KQD$}&we-EDf=3^ubjOEIf48#0H@9n1yhyUm9!&=yV>LW>5A8%z?@ zlbOS8WsX|XErTr!ExRnASs7TxTWz!IxB6&pZ=G)4Xnn_qViRanXwzf!tF4(W*S5y? z+FbHn-?^*jcF%ooXKu&0+hcdro@yUrzrnuO{)2;~gUF%HVbamSG10Ns@dk^=3S(_% zop(Yzc{#0iI_C7&*}+-teAxLH7p6;^ON+~+dB*ej^BU)kx$3!cTZVb0Xx4mvs zcU^amdxQG}4}A}wN0Y~dr>SSE=RwbBUe;bBuMV%*Y-jdL_9<_~+t0hid(emC6XjFw zbKh6bH`%w{0a^jvfaZXyK*zw9fqg-wpantIK@Wn>fV8I2F~=-fTgudr?_nHF76Ya z2X6;&lJCkd=T9WLCY2{WN_I`&o;;c2o>GzWRKONg3!bO?r`DyuP76)jpY|y|CcQla zmywupR7eq~3Hvg&GxIWsv&^%Kv!u(Mm+f3OB?=NXWkcDEvb)7J+0WE~#6+@QGMeL- zQhTd=lZbfxFY`c=@XrK@^Z>#r_a zJ-)_o&4IOqwP|aAD6}ptFMPQ!W?fH_R?(WGvGsoITZV0)e^+=6ZO?$0o?WWq-yLr2> z?D5#sR;N{0TK8_RVDHU(zxvJwqlSuon0-0>9yUfd_J7U#y17ZCskG_Ce&K%UfrtZr z&5q5@Et)N5t#GTPb@E`s!OP!xf79K@Y^!glx0fCQha`s{f1CL2^}|7jdylY=w0&pz zU2O-oqofn+T;4g=mC_~cj_V#i8hEs~$EBy^d&}?lAJaWnb6n+k*$Kjlq7$D^=AWEC zm38Xr>EzR6y-RxUoQXYituMT9@NCf8^XGieo$2@NKY8Bu{ILtp7mi+JUF^E#aH(^^ zexTzA`yV<69R@px9EZ9uJ6-M>o;Q5riu;w*SG}*EyB2Wm(#ZUg;pqt>?FMZqM9Va~FNLGD$lbNT*KP&%S`^@CocfWZ2GB6c8HU3=m{L`|I+Sd?{wJo{Z|>UW?q-PQGavbE$eOnyO?(qGr8}v?<+r;e(3oa^zrVej8C6_ z1NVgU`*8t=>i_@%24YJ`L;(K){{a7>y{D4^000SaNLh0L04^f{04^f|c%?sf00007 zbV*G`2j>R@6DTR(GrsNs000?uMObu0Z*6U5Zgc=ca%Ew3Wn>_CX>@2HM@dakSAh-} z000h%Nklu2 z2}*>JO4|_BNah$`Eo!GnUc5dfE|GP4W>BNMrC=9EX5g`^dd zllTE3IwXfb=!$OHc=+u4$k1>vw}Sp^t@5wg&=}fSBf9ESpY7@C-}%U~u8p7f^zUHG zcylDN>DkL`x1=XFUC|*qeCwC(OZGZl49)qypZHeMkSjN?{&Eh_UaQFHvQDkw#z@zzaM z-(KLj)xPrQi`n${_M$S+5=$CyQJH5+rr{HgTY52jv2Cs|Zgn$WF*nX}YrgT8g`^dF z1^``*H_7P;6oX8TTk|lRlH??QJp%yIC&9jg6U=dIezZ$z?Nt57^mH+v7B|dsYrgSj z`^0&Ajp=D_yjs!Kkk3p7$1S~>Ep}wW6ys@iqiP18x%8{Jdi8EKH=dR^%A=n7d6(>D zXkQLQ>%?ji-nsGUDu-4bW->H2p4K9KG?GviHiIs#g^%k&EKtV@sSF0IQ! zGvl@DG_lN$r%rPuv8j-$N~3$Xgw`A5#-l3$XuWWN&|J$nZt1G1T8>y~Vm!T#-%{g@q1A8n>GN%5xeX*y=aaZ7gv)e5(SmK)(wk8aGS)LiCS zti_mKQO2tkT@B4;p2ggF>|<8z5e#DX4XDBG97$~A7BjzMYH=-MmBbodt2t&fEBWw! zab-`6F`bc#<+!D*LKb^XVx`2^h^~5$TRJLav5zMdWIR0<1aRCI-oZ1PJX(|mv0CAC z+|rXD#dIzUGhVfM#^bnUqbyV#Z;m83Y4I=*$E`M)HM=Ydou?;8U5MkB&3q_y;Q+B> zVmWTj$81W4E*wy0yw)oJ8od_;aNJr4vlq)k{d_&q`vM%d?5Dqwg#$!Q4Kr#%0LQI0 zFgyBw)CDD?*NF|OX#ssV59FB5Uut&|C3>CMjXv1tuE35pg^BvP8`6M*kYlwL5H@c$Hy>DQ?!(2qG6LH+~2(Km( z5Uozc3&R-9(!OutY@awUpJ6U%wl8T|5Rh*zJJ84en;)B1z9_{kt*r~L-*Djcnu3jI zm1(KjK5^bF3+lIn%Q6Ha*^L)i!?Te~tt2P$=L%XRTePEPK>(Nalq+ZvyEoXm^lFc0 zUpO$K@zlQVlZ$KOPG9DzN7Vj+iz{Dco8KpDf563+ud?kTI?i~7zV4HYOHC((sO^n# zaj8+Jg#)9ENBe>RE^BI{g$<*OcSnPNol8`BPH|}_;sAa(r{d3JKX;`6v+b7JkIE*) z~@E0Fnrwo;7FkjN$J)B3!h}B`T znm%0cm=IUtLnIXq=9wP0s(?`GW?Ysy++9GO?LE*Xv^i2lZFiO1{IWeWSsBd z=w%hH)S!04hAu}hb7-aBcpSZKqcx>iLLQ(7wVBX+uAM+0<_2N`ttlNkAO8*j$lD!# zZ_$`>E-_hK-CmAf7SKBGK07WX+Nr%c0+iRwe8AblXdSDzaN@{F8!y_g#OTIGavqT{ zHpt#QDX-UlVqa?==o$QW#CW|iIZS)TmUuXNGojT=9kNu@j-)sEsLy1M-f`{VP@{E* zpa$d0P^xK10O0N8eOs*6W8>)c29p!~R$A?I^xW`Be}VwOlZSd9wOYp86}?tNYr1xx z>fbTScmU8HQF<*`2;ZaE8?=Y{tcKRHdhtkj^El&eKXK8GR+GOnxpJ0e^jZ5BF% zu{~X}&&C<=AK#vT*vbVXO37%z+TJf#Mr*p>KidDnsC1?N*wYpJ%!;^8m%{~w8reaw zOH_(_j+G{j4Q!)^8(%*heS?JpV*$OMfP(S{nTZJA9Z`DIF+0w9_kP~FZZNJ4v0y%{ zqL(<54@L#5>7RwjS5JT4`}85;6KW7;=dUf^`Z+ zA3N>T!MHNC^qr2y3ZSo=szcHkB|Kzl90o*ePYv` z$t9PvlmSjR;PwHD7+o7p5(nU~N-kp(7~AzN+ONbGZ#{9!`ru?x`mat-nd?3 zgG|k?2B}^vtGg`xX;=3jGmb!H`l9!O5?wysdp&EJAqdHihrx8|@$Q=%zFJsc(ga487!c5V+W4JK{grG_^T{%l>6?#D%eKfk zYlr=|k58>&5xHiem$d=zOnP8<&qKLZwrB0kp)rtY(r?=oO`8d(O%D zrbT<(vsHXM(JYMM7hxG_9`f|Nt7$3O{cn7n@KMniEJhbBDU0)UM&b<{@qd~rGO{_gM9*& zF^hqvkc>bz`@PnYk&ZJ%ZS^m;O^GB5e;&K&tZELGw!C*!?Y2VR3}kimrk17Cyk&&e z?YU>Zj68qu=bh_{J(p&6)GoscavSvD+_?D2~a8k zp$7ot0q@|Mp|+MSCl-Fu72BoNIW;#3>*$qB0W$kyl~ode&;}sF(Q2ykSVpf>0|+%4 zzUu&lGaRjkqn2g#DgcDJfKZ;L2Kxco0|;U3qgM~K8W!BpjT_O=Dc1EAZ-Bp z?S)qAjAtf#4{!5(P}h$X+tZusMQm_G@#W;^wNk{%S1e_&`TRy^+c~MLwR6# z&qEu(>iPri>9owMkwVZ*Gg`Ao=mdZhfN)M7T9X14fOL_(ry3xP34PjpWxKud>`(J?Ogs`#}b~i z+<1ndSB^tjzo~1(lY4s})aF!XY?a^o3_UXE67Jl*v8 zjg`;-@+ZOqFnz6oZAwWXo)&X00000NkvXXu0mjf DRl<`V literal 0 HcmV?d00001 diff --git a/mylyn.commons/org.eclipse.mylyn.commons.ui/src/org/eclipse/mylyn/commons/ui/CommonImages.java b/mylyn.commons/org.eclipse.mylyn.commons.ui/src/org/eclipse/mylyn/commons/ui/CommonImages.java index 783ffc535e..5068b12faa 100644 --- a/mylyn.commons/org.eclipse.mylyn.commons.ui/src/org/eclipse/mylyn/commons/ui/CommonImages.java +++ b/mylyn.commons/org.eclipse.mylyn.commons.ui/src/org/eclipse/mylyn/commons/ui/CommonImages.java @@ -1,10 +1,10 @@ /******************************************************************************* * Copyright (c) 2004, 2015 Tasktop Technologies and others. - * + * * This program and the accompanying materials are made available under the * terms of the Eclipse Public License v. 2.0 which is available at * https://www.eclipse.org/legal/epl-2.0 - * + * * SPDX-License-Identifier: EPL-2.0 * * Tasktop Technologies - initial API and implementation @@ -321,6 +321,8 @@ public class CommonImages { public static final ImageDescriptor PERSON_LARGE = create(T_OBJ48, "person.gif"); //$NON-NLS-1$; + public static final ImageDescriptor GITLAB = create(T_OBJ, "gitlab.png"); //$NON-NLS-1$ + private static ImageDescriptor create(String prefix, String name) { try { return ImageDescriptor.createFromURL(makeIconFileURL(prefix, name)); diff --git a/mylyn.tasks/connectors/gitlab/org.eclipse.mylyn.gitlab.core/src/org/eclipse/mylyn/gitlab/core/GitlabRestClient.java b/mylyn.tasks/connectors/gitlab/org.eclipse.mylyn.gitlab.core/src/org/eclipse/mylyn/gitlab/core/GitlabRestClient.java index 710786762b..5e07e50e22 100644 --- a/mylyn.tasks/connectors/gitlab/org.eclipse.mylyn.gitlab.core/src/org/eclipse/mylyn/gitlab/core/GitlabRestClient.java +++ b/mylyn.tasks/connectors/gitlab/org.eclipse.mylyn.gitlab.core/src/org/eclipse/mylyn/gitlab/core/GitlabRestClient.java @@ -398,47 +398,53 @@ public TaskData getTaskData(TaskRepository repository, String taskId, IProgressM result = new GsonBuilder().registerTypeAdapter(type.getType(), new JSonTaskDataDeserializer()).create() .fromJson(iss, type.getType()); - JsonArray notes = getIssueNotes(matcher.group(1), matcher.group(2), OperationUtil.convert(monitor)); - if (notes != null) { - int i = 0; - for (JsonElement jsonElement : notes) { - JsonObject note = jsonElement.getAsJsonObject(); - i = createNoteTaskAttribute(repository, result, i, note); - } - } -// JsonArray discussions = getIssueDiscussions(matcher.group(1), matcher.group(2), -// OperationUtil.convert(monitor)); -// if (discussions != null) { +// JsonArray notes = getIssueNotes(matcher.group(1), matcher.group(2), OperationUtil.convert(monitor)); +// if (notes != null) { // int i = 0; -// for (JsonElement jsonElement : discussions) { -// JsonObject discussion = (JsonObject) jsonElement; -// JsonArray notesArray = discussion.get("notes").getAsJsonArray(); -// if (discussion.get("individual_note").getAsBoolean()) { -// JsonObject note = notesArray.get(0).getAsJsonObject(); -// i = createNoteTaskAttribute(repository, result, i, note); -// } else { -// for ( JsonElement jsonElement2 : notesArray) { -// JsonObject note = jsonElement2.getAsJsonObject(); -// i = createNoteTaskAttribute(repository, result, i, note); -// } -// } +// for (JsonElement jsonElement : notes) { +// JsonObject note = jsonElement.getAsJsonObject(); +// i = createNoteTaskAttribute(repository, result, i, note); // } // } + JsonArray discussions = getIssueDiscussions(matcher.group(1), matcher.group(2), + OperationUtil.convert(monitor)); + if (discussions != null) { + int i = 0; + TaskAttribute attrib = null; + for (JsonElement jsonElement : discussions) { + JsonObject discussion = (JsonObject) jsonElement; + JsonArray notesArray = discussion.get("notes").getAsJsonArray(); + if (discussion.get("individual_note").getAsBoolean()) { + JsonObject note = notesArray.get(0).getAsJsonObject(); + attrib = createNoteTaskAttribute(repository, result.getRoot(), i++, note); + } else { + TaskAttribute reply = null; + for ( JsonElement jsonElement2 : notesArray) { + JsonObject note = jsonElement2.getAsJsonObject(); + attrib = createNoteTaskAttribute(repository, reply==null?result.getRoot():reply, i++, note); + if (reply == null) { + reply = attrib.createAttribute("reply"); + } + } + } + } + } config.updateProductOptions(result); } return result; } - private int createNoteTaskAttribute(TaskRepository repository, TaskData result, int i, JsonObject note) { + private TaskAttribute createNoteTaskAttribute(TaskRepository repository, TaskAttribute result, int i, JsonObject note) { TaskCommentMapper cmapper = new TaskCommentMapper(); cmapper.setAuthor(repository.createPerson(note.get("author").getAsJsonObject().get("name").getAsString())); cmapper.setCreationDate(GitlabTaskAttributeMapper.parseDate(note.get("created_at").getAsString())); cmapper.setText(note.get("body").getAsString()); cmapper.setNumber(++i); - TaskAttribute attribute = result.getRoot().createAttribute(TaskAttribute.PREFIX_COMMENT + (i + 1)); + TaskAttribute attribute = result.createAttribute(TaskAttribute.PREFIX_COMMENT + i); cmapper.applyTo(attribute); - return i; + attribute.createAttribute("system").setValue(note.get("system").getAsString()); + return attribute; } public void getTaskData(Set taskIds, TaskRepository taskRepository, TaskDataCollector collector, diff --git a/mylyn.tasks/connectors/gitlab/org.eclipse.mylyn.gitlab.core/src/org/eclipse/mylyn/gitlab/core/GitlabTaskCommentMapper.java b/mylyn.tasks/connectors/gitlab/org.eclipse.mylyn.gitlab.core/src/org/eclipse/mylyn/gitlab/core/GitlabTaskCommentMapper.java new file mode 100644 index 0000000000..98d321d4d3 --- /dev/null +++ b/mylyn.tasks/connectors/gitlab/org.eclipse.mylyn.gitlab.core/src/org/eclipse/mylyn/gitlab/core/GitlabTaskCommentMapper.java @@ -0,0 +1,7 @@ +package org.eclipse.mylyn.gitlab.core; + +import org.eclipse.mylyn.tasks.core.data.TaskCommentMapper; + +public class GitlabTaskCommentMapper extends TaskCommentMapper { + +} diff --git a/mylyn.tasks/connectors/gitlab/org.eclipse.mylyn.gitlab.ui/icons/eview16/gitlab-icon.gif b/mylyn.tasks/connectors/gitlab/org.eclipse.mylyn.gitlab.ui/icons/eview16/gitlab-icon.gif deleted file mode 100644 index f2847251a6b46deb8691dd6bbfbe6eab76437bb4..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 1431 zcmc)Ji$Bu|008jc)@JjF%{FXJjcv9xk2UiMnZj5^GbJQW%)5znDP8j}aIi7 zVV>8g>*oC`&xt&u7b!%mJi6T7Uvc06;mdY%Ft_k00t8@w0sue&00tC600;trp&$qh z4245ricnP;6s`Rz;|&A$KCw)sQHJIvR;WtD`X}O$}9y1{$M@*3iOe zYH47#kT@Jl8;8Z=vAgg%ZM+74H(q-Wo~%P45w(dVT{3w$iA*Hvk;oJhg+icGbo8iX z3RQ0}RY#w;mqsJ+Gtf6Mq!}6+>^C$pG&V4z8`A0ebcXSM2Hk`~W0>q`Fd0myp@}Jj zX=Y+-&a^Z$HM20awlq3mX>q{H!rI2_Aj{f@b*OdANHV=XrZ^y?jpk`0!4h_VM*Qb=u$8 zKfv!yfX|u0fWV+LLHs~|a8PgvKRA>h9u^Q99ugK28Xg%IaW*_s5OFptQgH5U^tsTO z*y!^YVq$+hf8kSp_*+IeFQ+`8j!_-28$(QDJ^Tk*M%yK~ZsGaY@mgTcx*tE-e$^y8Vmz zZuzg}mA_ToE3d4oxK~|S`#@YP`Ms{bR?<+{)byaCslKtfp{b?u;UBeswf-q>d)(SC zZR=?5=xXom?&#|2?C$Lv=+-J~U)DFjZfvb@e%sjk zd-L1&*7xmi+y4ih4G2gH*am38zy3P`z`q0Af$QuVu{05mQs>PH#mQF3(Yrsi9@dpA z#K<8!o`9mM0}QR;=0={-hk?*zX&ugX&;(0xOshkBiWKFnHP_mi$FH(+;GjzdDU>}B z5Lul}vTAudm6gP&s~$z8r_i&=I&~PpeAqh{T5ALv_uFEC(`@yG z#jG@A$^92)H^6d#!d?UWHSdgQ@ zL%kRZR-#$kyW0U4-M4!ZwapVV3C&W(HEgy=M;@(cmgRFLe*2&qU(w+UO=#M8R5Y;mVKeMX5Ne z)r4fhiKPTEK7v4!QvGWL%HAEG4I199%~v}qY9vUqiB&hS(>t45=crp*FWQ0Z3?>X| z_gB=kM;#9oPJ%=}_L&I6=*vWV(5y}$=tMr>gW#Hf&V%Vq^;5!XV0ezSsFMLAW^9=k zlMOUi=Y-mVwC*?o*D~T{1dw@d$9>qvAvSPzJqC&jQfWgGLH(EX>4Tx04R}tkv&MmKp2MKrb>%c9qb_DkfDl$1yK=4twIqhgj%6h2a`*GgeDD1 zii@M*T5#}ZvFhOBtgC~oAPD||xVktgx=4xNC509--f`T+d*AzV_Z=YA%S^L6#sE#X z&2%y$W^*fI=oKM^(L-}YW|lE4Nh$b_uX_aeei!Fi{&jzjZZ&T)ARrRYFvGNo*NLY# zZG-bZag>#0mH3=^)T9d%KXP61_>FVXWr1f#%}jcZI7%!Q+gNF1Rx&l>N#dBQ>69;I zJytnyan{OJ*1RWwVI;3FFL9mLAd*J%U`Jj)1Rc* zT3YM~=-mb`u3MV22VCv|{ZEE$%B~coB@_z4`x$*x4(PiDx>miuHP3PS0A#3FsT<(n z5Ew2}_L|ST!|i?hx2D;@A3*nVlg?=w3;+NC24YJ`L;(K){{a7>y{D4^000SaNLh0L z01FZT01FZU(%pXi00007bV*G`2j>R}4=*g6nP%1i000?uMObu0Z*6U5Zgc=ca%Ew3 zWn>_CX>@2HM@dakSAh-}0005fNkl%s&v(LJL#bh?Rwvf}n-5P|*ApffOmy#lIkUg^-0{k0Oi0W?f(D~>|Hpj{u>GRFq6VRADl0ZsFF zLo|W+aTNZ@ap%q55Szdo;4~u`EUBoM$Z{_c(mnuH;Qo}hu^n)Iz3lor0zPM2b}D*( zW==`aPH|^7e}g-#3EC+$b4r|wULR{&gan{ehDJ+~R4sm;3+g)e*(LCr8vjPdDaqJS zv|@ks!mlgpErnClgLw)#HBG&x@atJIlRIXcBQ)>+hzhu#rarIm0*x08_O53N3|}_L zIm!zPz~$qccFEBXM0g7fEMo&prsQ`Z9eJ7N>2+WBDj&b4g@Qv|?R3_}<`q77XyH;b zj0@n59zQwODbLHh-LI2|Ciy`BS*K;Sd4kU)#Q08g&IO;;DIc8I-Lq*fkfPw#mrezX pdm`)tXw43agYv`fCI9iy@f(&XfvJ%Cy)6I$002ovPDHLkV1hK3!odIl literal 0 HcmV?d00001 diff --git a/mylyn.tasks/connectors/gitlab/org.eclipse.mylyn.gitlab.ui/icons/eview16/gitlab-icon38.png b/mylyn.tasks/connectors/gitlab/org.eclipse.mylyn.gitlab.ui/icons/eview16/gitlab-icon38.png new file mode 100644 index 0000000000000000000000000000000000000000..8a7f2ce79218dee97db08b19d81cfe6ccaf3cd1e GIT binary patch literal 1130 zcmV-w1eN=VP)EX>4Tx04R}tkv&MmKp2MKrb>%c9qb_DkfDl$1yK=4twIqhgj%6h2a`*GgeDD1 zii@M*T5#}ZvFhOBtgC~oAPD||xVktgx=4xNC509--f`T+d*AzV_Z=YA%S^L6#sE#X z&2%y$W^*fI=oKM^(L-}YW|lE4Nh$b_uX_aeei!Fi{&jzjZZ&T)ARrRYFvGNo*NLY# zZG-bZag>#0mH3=^)T9d%KXP61_>FVXWr1f#%}jcZI7%!Q+gNF1Rx&l>N#dBQ>69;I zJytnyan{OJ*1RWwVI;3FFL9mLAd*J%U`Jj)1Rc* zT3YM~=-mb`u3MV22VCv|{ZEE$%B~coB@_z4`x$*x4(PiDx>miuHP3PS0A#3FsT<(n z5Ew2}_L|ST!|i?hx2D;@A3*nVlg?=w3;+NC24YJ`L;(K){{a7>y{D4^000SaNLh0L z01FZT01FZU(%pXi00007bV*G`2j>R}4+9bUz(HvM000?uMObu0Z*6U5Zgc=ca%Ew3 zWn>_CX>@2HM@dakSAh-}0006(NklFU3xK)Q)+CQw5AqXu8B+6 zEJ7g;ZkdF(LUA!g1^)s63qgyOfQ#6nI=gfighHprpi5HJMG6M0z4YGKAs3q_sktOq z$Z+5Bx#!3C`Ek#42LS>E2oPX2P|0PcE4j?{Md>#Y8i3n7pbp&fsQ(r)fNVcOM4#1K z07`%auFvf3fA6861P%ZV$jt2Qm%PT(`mEM^i(TG>e!e9}p`SpWiB)dj)PdC&(OnN_ ztvai&51%WhR34aYkt|hmnTh|jaROLs5ly;2d>{U`E=fJDC@;_@{`bQ})9 zX&l$QZJMyD7@v}8dUI5eitsQok0A(oPu3DwiiOekWhQ&R1|hOU@&_@uQ>mw8oU zL?3^}#coHNB8vE&gAqL?U_=|TZlqA`+DH1fuP4cV zWF<7655Qu#=e3`W9L<B?o1gz&$PsU%{@7X;8k>Mg)Fl;eJ_No3zZ!*9lET>Y@>bs~X3$M}{Lo74Q*3dA z#SSkDsIuoAupHhfmj>~#4N5G$Q7+Z5h^&$nJ7!!`teYY`D5;?;cBZwjt$RY_rAumk w?0)&p$b53!MQheBTC>5=M}PnU0*pBR0#QSx$_X9%i~s-t07*qoM6N<$f=^NWX8-^I literal 0 HcmV?d00001 diff --git a/mylyn.tasks/connectors/gitlab/org.eclipse.mylyn.gitlab.ui/icons/eview16/gitlab-overlay.gif b/mylyn.tasks/connectors/gitlab/org.eclipse.mylyn.gitlab.ui/icons/eview16/gitlab-overlay.gif deleted file mode 100644 index bd7af837d9cbe17495cc2d616273c4f5a0225a0d..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 276 zcmZ?wbhEHbU39v2&(5FeA2l#rK~Q(jtF zQ&rL0($vw>(bL^EapHuTGiNSZv}oDV#j97X+^~NA)~#C(9N2&G;J(9$4qUi!{?esO z*REZ?bNkNSJ9qBgyZiCOhi~7${rLIg_wV2T{{8#^ABd<46o0ZXaxvI5=r8~Q$WIJx zh6fJib4V&N^-eg+QpMvb9qeiRD^R7SgZaQr10xl0*OtgXBJ;eTPnP({=G|DGVX>o` G!5RRvAglEN diff --git a/mylyn.tasks/connectors/gitlab/org.eclipse.mylyn.gitlab.ui/icons/eview16/gitlab-overlay.png b/mylyn.tasks/connectors/gitlab/org.eclipse.mylyn.gitlab.ui/icons/eview16/gitlab-overlay.png new file mode 100644 index 0000000000000000000000000000000000000000..1db15b8676ff3af64ef773ad6858f03b7d037a54 GIT binary patch literal 758 zcmVEX>4Tx04R}tkv&MmKp2MKrb>%c9qb_DkfDl$1yK=4twIqhgj%6h2a`*GgeDD1 zii@M*T5#}ZvFhOBtgC~oAPD||xVktgx=4xNC509--f`T+d*AzV_Z=YA%S^L6#sE#X z&2%y$W^*fI=oKM^(L-}YW|lE4Nh$b_uX_aeei!Fi{&jzjZZ&T)ARrRYFvGNo*NLY# zZG-bZag>#0mH3=^)T9d%KXP61_>FVXWr1f#%}jcZI7%!Q+gNF1Rx&l>N#dBQ>69;I zJytnyan{OJ*1RWwVI;3FFL9mLAd*J%U`Jj)1Rc* zT3YM~=-mb`u3MV22VCv|{ZEE$%B~coB@_z4`x$*x4(PiDx>miuHP3PS0A#3FsT<(n z5Ew2}_L|ST!|i?hx2D;@A3*nVlg?=w3;+NC24YJ`L;(K){{a7>y{D4^000SaNLh0L z01FZT01FZU(%pXi00007bV*G`2j>R}4_CX>@2HM@dakSAh-}0002ZNklN zEf=VD5FER;Tdv?Jt`4H7=+q0iDP$_KTQPzWA(Z6rkScxC@hZdd45EC!j+M7y}M4&Es&fOD=ZXSblF$Kgv((SKq=u-9yFob!FL( zR{pV4ItD-MHaa*`++G7hWdSL|gX=dv+iQcap#TMt3czL(gyQkc3Fio~1CA#ga7~l07*qoM6N<$g04|P7XSbN literal 0 HcmV?d00001 diff --git a/mylyn.tasks/connectors/gitlab/org.eclipse.mylyn.gitlab.ui/plugin.xml b/mylyn.tasks/connectors/gitlab/org.eclipse.mylyn.gitlab.ui/plugin.xml index 8bb9a1c362..4549ae35f2 100644 --- a/mylyn.tasks/connectors/gitlab/org.eclipse.mylyn.gitlab.ui/plugin.xml +++ b/mylyn.tasks/connectors/gitlab/org.eclipse.mylyn.gitlab.ui/plugin.xml @@ -18,9 +18,9 @@ name="Gitlab Respository" point="org.eclipse.mylyn.tasks.ui.repositories"> + overlayIcon="icons/eview16/gitlab-overlay.png"> diff --git a/mylyn.tasks/connectors/gitlab/org.eclipse.mylyn.gitlab.ui/src/org/eclipse/mylyn/gitlab/ui/GitlabTaskEditorCommentPart.java b/mylyn.tasks/connectors/gitlab/org.eclipse.mylyn.gitlab.ui/src/org/eclipse/mylyn/gitlab/ui/GitlabTaskEditorCommentPart.java new file mode 100644 index 0000000000..ae2cbe1a12 --- /dev/null +++ b/mylyn.tasks/connectors/gitlab/org.eclipse.mylyn.gitlab.ui/src/org/eclipse/mylyn/gitlab/ui/GitlabTaskEditorCommentPart.java @@ -0,0 +1,290 @@ +package org.eclipse.mylyn.gitlab.ui; + +import java.util.ArrayList; +import java.util.List; +import java.util.Map; + +import org.eclipse.jface.action.ToolBarManager; +import org.eclipse.jface.layout.GridDataFactory; +import org.eclipse.mylyn.commons.ui.CommonImages; +import org.eclipse.mylyn.commons.ui.FillWidthLayout; +import org.eclipse.mylyn.commons.workbench.forms.CommonFormUtil; +import org.eclipse.mylyn.internal.tasks.core.TaskComment; +import org.eclipse.mylyn.internal.tasks.ui.editors.CommentGroupStrategy.CommentGroup; +import org.eclipse.mylyn.internal.tasks.ui.editors.EditorUtil; +import org.eclipse.mylyn.internal.tasks.ui.editors.TaskEditorCommentPart; +import org.eclipse.mylyn.internal.tasks.ui.editors.TaskEditorExtensions; +import org.eclipse.mylyn.internal.tasks.ui.editors.UserAttributeEditor; +import org.eclipse.mylyn.tasks.core.IRepositoryPerson; +import org.eclipse.mylyn.tasks.core.ITaskComment; +import org.eclipse.mylyn.tasks.core.data.TaskAttribute; +import org.eclipse.swt.SWT; +import org.eclipse.swt.events.MouseAdapter; +import org.eclipse.swt.events.MouseEvent; +import org.eclipse.swt.layout.GridData; +import org.eclipse.swt.layout.GridLayout; +import org.eclipse.swt.layout.RowLayout; +import org.eclipse.swt.widgets.Composite; +import org.eclipse.swt.widgets.Control; +import org.eclipse.swt.widgets.Label; +import org.eclipse.swt.widgets.Menu; +import org.eclipse.ui.forms.IFormColors; +import org.eclipse.ui.forms.events.ExpansionAdapter; +import org.eclipse.ui.forms.events.ExpansionEvent; +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.forms.widgets.FormToolkit; +import org.eclipse.ui.forms.widgets.ImageHyperlink; + +public class GitlabTaskEditorCommentPart extends TaskEditorCommentPart { + + public class GitlabCommentGroupViewer extends CommentGroupViewer { + + private ArrayList commentViewers; + + public GitlabCommentGroupViewer(CommentGroup commentGroup) { + super(commentGroup); + } + + @Override + public List getCommentViewers() { + if (commentViewers != null) { + return commentViewers; + } + + commentViewers = new ArrayList(commentGroup.getCommentAttributes().size()); + for (TaskAttribute commentAttribute : commentGroup.getCommentAttributes()) { + CommentViewer commentViewer = new GitlabCommentViewer(commentAttribute); + commentViewers.add(commentViewer); + } + return commentViewers; + } + + } + + public class GitlabCommentViewer extends CommentViewer { + + ArrayList subViewer = new ArrayList(); + + public GitlabCommentViewer(TaskAttribute commentAttribute) { + super(commentAttribute); + } + + public Control createControl(Composite composite, FormToolkit toolkit) { + boolean hasIncomingChanges = getModel().hasIncomingChanges(commentAttribute); + getTaskData().getAttributeMapper().updateTaskComment(taskComment, commentAttribute); + int style = ExpandableComposite.TREE_NODE | ExpandableComposite.LEFT_TEXT_CLIENT_ALIGNMENT + | ExpandableComposite.COMPACT; + if (hasIncomingChanges || (expandAllInProgress && !suppressExpandViewers)) { + style |= ExpandableComposite.EXPANDED; + } + composite.setMenu(null); + commentComposite = toolkit.createExpandableComposite(composite, style); + commentComposite.clientVerticalSpacing = 0; + commentComposite.setLayout(new GridLayout()); + commentComposite.setLayoutData(new GridData(GridData.FILL_HORIZONTAL)); + commentComposite.setTitleBarForeground(toolkit.getColors().getColor(IFormColors.TITLE)); + + buttonComposite = createTitle(commentComposite, toolkit); + + Composite commentViewerComposite = toolkit.createComposite(commentComposite); + commentComposite.setClient(commentViewerComposite); + commentViewerComposite + .setLayout(new FillWidthLayout(EditorUtil.getLayoutAdvisor(getTaskEditorPage()), 15, 0, 0, 3)); + + commentComposite.addExpansionListener(new ExpansionAdapter() { + @Override + public void expansionStateChanged(ExpansionEvent event) { + if (commentViewerComposite != null && !commentViewerComposite.isDisposed()) + expandComment(toolkit, commentViewerComposite, event.getState()); + } + }); + if (hasIncomingChanges) { + commentComposite.setBackground(getTaskEditorPage().getAttributeEditorToolkit().getColorIncoming()); + } + if (commentComposite.isExpanded()) { + if (commentViewerComposite != null && !commentViewerComposite.isDisposed()) + expandComment(toolkit, commentViewerComposite, true); + } + // for outline + EditorUtil.setMarker(commentComposite, commentAttribute.getId()); + return commentComposite; + } + + @Override + protected void expandComment(FormToolkit toolkit, Composite composite, boolean expanded) { + buttonComposite.setVisible(expanded); + if (expanded && composite.getData(KEY_EDITOR) == null) { + Menu mm0 = composite.getMenu(); + commentViewer = toolkit.createComposite(composite); + commentViewer.setLayout(new GridLayout(1, false)); + commentViewer.setLayoutData(new GridData(GridData.VERTICAL_ALIGN_BEGINNING)); + + // Create user image viewer + boolean showAvatar = Boolean.parseBoolean(getModel().getTaskRepository() + .getProperty(TaskEditorExtensions.REPOSITORY_PROPERTY_AVATAR_SUPPORT)); + if (showAvatar) { + String commentAuthor = getTaskData().getAttributeMapper().mapToRepositoryKey(commentAttribute, + TaskAttribute.COMMENT_AUTHOR); + TaskAttribute userImageAttribute = commentAttribute.getAttribute(commentAuthor); + + if (userImageAttribute != null) { + userImageComposite = toolkit.createComposite(commentViewer); + userImageComposite.setLayout(new GridLayout(1, false)); + GridDataFactory.swtDefaults().align(SWT.LEFT, SWT.BEGINNING).applyTo(userImageComposite); + toolkit.paintBordersFor(userImageComposite); + + UserAttributeEditor userImage = new UserAttributeEditor(getModel(), userImageAttribute, 30); + userImage.createControl(userImageComposite, toolkit); + + userImage.refresh(); + } + } + + // Create comment text viewer + TaskAttribute textAttribute = getTaskData().getAttributeMapper() + .getAssoctiatedAttribute(taskComment.getTaskAttribute()); + commentTextEditor = createAttributeEditor(textAttribute); + if (commentTextEditor != null) { + commentTextEditor.setDecorationEnabled(false); + commentTextEditor.createControl(commentViewer, toolkit); + GridData commentGridData = new GridData(GridData.FILL_HORIZONTAL); + commentGridData.verticalAlignment = GridData.BEGINNING; + commentTextEditor.getControl().setLayoutData(commentGridData); + + commentTextEditor.getControl().addMouseListener(new MouseAdapter() { + @Override + public void mouseDown(MouseEvent e) { + getTaskEditorPage().selectionChanged(taskComment); + } + }); + composite.setData(KEY_EDITOR, commentTextEditor); + TaskAttribute reply = commentAttribute.getAttribute("reply"); + if (reply != null) { + for (TaskAttribute taskAttributeReply : reply.getAttributes().values()) { + TaskComment replyComment = new TaskComment(getModel().getTaskRepository(), + getModel().getTask(), taskAttributeReply); + commentAttribute.getTaskData().getAttributeMapper().updateTaskComment(replyComment, + taskAttributeReply); + GitlabCommentViewer replyCommentViewer = new GitlabCommentViewer(taskAttributeReply); + subViewer.add(replyCommentViewer); + replyCommentViewer.createControl(commentViewer, toolkit); + } + } + getTaskEditorPage().getAttributeEditorToolkit().adapt(commentTextEditor); + reflow(); + } + } else if (!expanded && composite.getData(KEY_EDITOR) != null) { + // dispose viewer + commentTextEditor.getControl().setMenu(null); + commentTextEditor.getControl().dispose(); + if (userImageComposite != null) { + userImageComposite.setMenu(null); + userImageComposite.dispose(); + } + if (commentViewer != null) { + for (GitlabCommentViewer subView : subViewer) { + if (subView != null) { + if (subView.commentTextEditor != null && subView.commentTextEditor.getControl() != null + && !subView.commentTextEditor.getControl().isDisposed()) { + subView.commentTextEditor.getControl().setMenu(null); + subView.commentTextEditor.getControl().dispose(); + } + if (subView.userImageComposite != null && subView.userImageComposite.isDisposed()) { + subView.userImageComposite.setMenu(null); + subView.userImageComposite.dispose(); + } + if (subView.commentViewer != null && !subView.commentViewer.isDisposed()) { + subView.commentViewer.setMenu(null); + subView.commentViewer.dispose(); + } + } + } + commentViewer.setMenu(null); + commentViewer.dispose(); + } + composite.setData(KEY_EDITOR, null); + reflow(); + } + if (!suppressSelectionChanged) { + getTaskEditorPage().selectionChanged(taskComment); + } + } + + @Override + protected Composite createTitle(ExpandableComposite commentComposite, FormToolkit toolkit) { + // always visible + Composite titleComposite = toolkit.createComposite(commentComposite); + commentComposite.setTextClient(titleComposite); + RowLayout rowLayout = new RowLayout(); + rowLayout.pack = true; + rowLayout.marginLeft = 0; + rowLayout.marginBottom = 0; + rowLayout.marginTop = 0; + rowLayout.center = true; + titleComposite.setLayout(rowLayout); + titleComposite.setBackground(null); + + ImageHyperlink expandCommentHyperlink = createTitleHyperLink(toolkit, titleComposite, taskComment); + expandCommentHyperlink.addHyperlinkListener(new HyperlinkAdapter() { + @Override + public void linkActivated(HyperlinkEvent e) { + CommonFormUtil.setExpanded(commentComposite, !commentComposite.isExpanded()); + } + }); + TaskAttribute systemAttribute = taskComment.getTaskAttribute().getAttribute("system"); + String systemAttributeValue = systemAttribute != null ? systemAttribute.getValue() : "false"; + if ("true".equals(systemAttributeValue)) { + expandCommentHyperlink.setImage(CommonImages.getImage(CommonImages.GITLAB)); + } + + ToolBarManager toolBarManagerTitle = new ToolBarManager(SWT.FLAT); + addActionsToToolbarTitle(toolBarManagerTitle, taskComment, this); + toolBarManagerTitle.createControl(titleComposite); + + // only visible when section is expanded + Composite buttonComposite = toolkit.createComposite(titleComposite); + RowLayout buttonCompLayout = new RowLayout(); + buttonCompLayout.marginBottom = 0; + buttonCompLayout.marginTop = 0; + buttonComposite.setLayout(buttonCompLayout); + buttonComposite.setBackground(null); + buttonComposite.setVisible(commentComposite.isExpanded()); + + ToolBarManager toolBarManagerButton = new ToolBarManager(SWT.FLAT); + addActionsToToolbarButton(toolBarManagerButton, taskComment, this); + toolBarManagerButton.createControl(buttonComposite); + + return buttonComposite; + } + + } + + @Override + public List getCommentGroupViewers() { + if (commentGroupViewers != null) { + return commentGroupViewers; + } + + // group comments + List comments = new ArrayList(); + for (TaskAttribute commentAttribute : this.commentAttributes) { + comments.add(convertToTaskComment(getModel(), commentAttribute)); + } + String currentPersonId = getModel().getTaskRepository().getUserName(); + List commentGroups = getCommentGroupStrategy().groupComments(comments, currentPersonId); + + commentGroupViewers = new ArrayList(commentGroups.size()); + if (commentGroups.size() > 0) { + for (int i = 0; i < commentGroups.size(); i++) { + GitlabCommentGroupViewer viewer = new GitlabCommentGroupViewer(commentGroups.get(i)); + boolean isLastGroup = i == commentGroups.size() - 1; + viewer.setRenderedInSubSection(!isLastGroup); + commentGroupViewers.add(viewer); + } + } + return commentGroupViewers; + } + +} diff --git a/mylyn.tasks/connectors/gitlab/org.eclipse.mylyn.gitlab.ui/src/org/eclipse/mylyn/gitlab/ui/GitlabTaskEditorPage.java b/mylyn.tasks/connectors/gitlab/org.eclipse.mylyn.gitlab.ui/src/org/eclipse/mylyn/gitlab/ui/GitlabTaskEditorPage.java index 21d67194fb..7d18d0e184 100644 --- a/mylyn.tasks/connectors/gitlab/org.eclipse.mylyn.gitlab.ui/src/org/eclipse/mylyn/gitlab/ui/GitlabTaskEditorPage.java +++ b/mylyn.tasks/connectors/gitlab/org.eclipse.mylyn.gitlab.ui/src/org/eclipse/mylyn/gitlab/ui/GitlabTaskEditorPage.java @@ -13,10 +13,13 @@ package org.eclipse.mylyn.gitlab.ui; +import java.util.ArrayList; import java.util.Set; import org.eclipse.mylyn.gitlab.core.GitlabCoreActivator; +import org.eclipse.mylyn.internal.tasks.ui.editors.TaskEditorCommentPart; 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.TaskEditor; import org.eclipse.mylyn.tasks.ui.editors.TaskEditorPartDescriptor; @@ -43,6 +46,26 @@ protected AttributeEditorFactory createAttributeEditorFactory() { @Override protected Set createPartDescriptors() { // TODO Auto-generated method stub - return super.createPartDescriptors(); + Set descriptors = super.createPartDescriptors(); + // remove unnecessary default editor parts + ArrayList descriptorsToRemove = new ArrayList(2); + boolean hasCommentPart = false; + for (TaskEditorPartDescriptor taskEditorPartDescriptor : descriptors) { + if (taskEditorPartDescriptor.getId().equals(ID_PART_COMMENTS)) { + hasCommentPart = hasCommentPart || taskEditorPartDescriptor.getId().equals(ID_PART_COMMENTS); + descriptorsToRemove.add(taskEditorPartDescriptor); + continue; + } + } + descriptors.removeAll(descriptorsToRemove); + if (hasCommentPart) { + descriptors.add(new TaskEditorPartDescriptor(ID_PART_COMMENTS) { + @Override + public AbstractTaskEditorPart createPart() { + return new GitlabTaskEditorCommentPart(); + } + }.setPath(PATH_COMMENTS)); + } + return descriptors; } } diff --git a/mylyn.tasks/org.eclipse.mylyn.tasks.ui/src/org/eclipse/mylyn/internal/tasks/ui/editors/EditorUtil.java b/mylyn.tasks/org.eclipse.mylyn.tasks.ui/src/org/eclipse/mylyn/internal/tasks/ui/editors/EditorUtil.java index ad04f3b0d2..b4ece9859a 100644 --- a/mylyn.tasks/org.eclipse.mylyn.tasks.ui/src/org/eclipse/mylyn/internal/tasks/ui/editors/EditorUtil.java +++ b/mylyn.tasks/org.eclipse.mylyn.tasks.ui/src/org/eclipse/mylyn/internal/tasks/ui/editors/EditorUtil.java @@ -1,10 +1,10 @@ /******************************************************************************* * Copyright (c) 2004, 2014 Tasktop Technologies and others. - * + * * This program and the accompanying materials are made available under the * terms of the Eclipse Public License v. 2.0 which is available at * https://www.eclipse.org/legal/epl-2.0 - * + * * SPDX-License-Identifier: EPL-2.0 * * Contributors: @@ -155,7 +155,7 @@ private static Control findControl(Composite composite, String key) { /** * Scroll to a specified piece of text - * + * * @param control * The StyledText to scroll to */ @@ -183,7 +183,7 @@ static String formatDate(Date date) { return getDateFormat().format(date); } - static String formatDateTime(Date date) { + public static String formatDateTime(Date date) { return getDateTimeFormat().format(date); } @@ -243,7 +243,7 @@ public void widgetDisposed(DisposeEvent e) { /** * Selects the given object in the editor. - * + * * @param o * The object to be selected. * @param highlight @@ -311,7 +311,7 @@ public static void setTextViewer(Widget widget, TextViewer textViewer) { /** * Programmatically expand the provided ExpandableComposite, using reflection to fire the expansion listeners (see * bug#70358) - * + * * @param comp * @deprecated Use {@link CommonFormUtil#setExpanded(ExpandableComposite,boolean)} instead */ @@ -376,7 +376,7 @@ public static Composite getLayoutAdvisor(AbstractTaskEditorPage page) { /** * Recursively sets the menu of all children of composite. - * + * * @deprecated Use {@link CommonUiUtil#setMenu(Composite,Menu)} instead */ @Deprecated @@ -455,14 +455,14 @@ public static GridData getTextControlLayoutData(TaskFormPage page, Control contr final GridData gd = new GridData(); // wrap text at this margin, see comment below int width = getEditorWidth(page); - // the goal is to make the text viewer as big as the text so it does not require scrolling when first drawn + // the goal is to make the text viewer as big as the text so it does not require scrolling when first drawn // on screen Point size = control.computeSize(width, SWT.DEFAULT, true); gd.widthHint = EditorUtil.MAXIMUM_WIDTH; gd.minimumWidth = EditorUtil.MAXIMUM_WIDTH; gd.horizontalAlignment = SWT.FILL; gd.grabExcessHorizontalSpace = true; - // limit height to be avoid dynamic resizing of the text widget: + // limit height to be avoid dynamic resizing of the text widget: // MAXIMUM_HEIGHT < height < MAXIMUM_HEIGHT * 3 //gd.minimumHeight = AbstractAttributeEditor.MAXIMUM_HEIGHT; gd.heightHint = Math.min(Math.max(EditorUtil.MAXIMUM_HEIGHT, size.y), EditorUtil.MAXIMUM_HEIGHT * 3); @@ -471,8 +471,8 @@ public static GridData getTextControlLayoutData(TaskFormPage page, Control contr gd.grabExcessVerticalSpace = true; } return gd; - // shrink the text control if the editor width is reduced, otherwise the text field will always keep it's original - // width and will cause the editor to have a horizonal scroll bar + // shrink the text control if the editor width is reduced, otherwise the text field will always keep it's original + // width and will cause the editor to have a horizonal scroll bar // composite.addControlListener(new ControlAdapter() { // @Override // public void controlResized(ControlEvent e) { diff --git a/mylyn.tasks/org.eclipse.mylyn.tasks.ui/src/org/eclipse/mylyn/internal/tasks/ui/editors/TaskEditorCommentPart.java b/mylyn.tasks/org.eclipse.mylyn.tasks.ui/src/org/eclipse/mylyn/internal/tasks/ui/editors/TaskEditorCommentPart.java index 74929426d1..6d84637401 100644 --- a/mylyn.tasks/org.eclipse.mylyn.tasks.ui/src/org/eclipse/mylyn/internal/tasks/ui/editors/TaskEditorCommentPart.java +++ b/mylyn.tasks/org.eclipse.mylyn.tasks.ui/src/org/eclipse/mylyn/internal/tasks/ui/editors/TaskEditorCommentPart.java @@ -1,10 +1,10 @@ /******************************************************************************* * Copyright (c) 2004, 2015 Tasktop Technologies and others. - * + * * This program and the accompanying materials are made available under the * terms of the Eclipse Public License v. 2.0 which is available at * https://www.eclipse.org/legal/epl-2.0 - * + * * SPDX-License-Identifier: EPL-2.0 * * Contributors: @@ -82,11 +82,11 @@ public class TaskEditorCommentPart extends AbstractTaskEditorPart { public class CommentGroupViewer { - private final CommentGroup commentGroup; + protected final CommentGroup commentGroup; - private ArrayList commentViewers; + protected ArrayList commentViewers; - private Section groupSection; + protected Section groupSection; private boolean renderedInSubSection; @@ -94,7 +94,7 @@ public CommentGroupViewer(CommentGroup commentGroup) { this.commentGroup = commentGroup; } - private Composite createCommentViewers(Composite parent, FormToolkit toolkit) { + protected Composite createCommentViewers(Composite parent, FormToolkit toolkit) { List viewers = getCommentViewers(); Composite composite = toolkit.createComposite(parent); @@ -279,21 +279,21 @@ public void clearSectionHyperlink() { public class CommentViewer { - private Composite buttonComposite; + protected Composite buttonComposite; - private final TaskAttribute commentAttribute; + protected final TaskAttribute commentAttribute; - private ExpandableComposite commentComposite; + protected ExpandableComposite commentComposite; - private final TaskComment taskComment; + protected final TaskComment taskComment; - private Composite commentViewer; + protected Composite commentViewer; - private Composite userImageComposite; + protected Composite userImageComposite; - private AbstractAttributeEditor commentTextEditor; + protected AbstractAttributeEditor commentTextEditor; - private boolean suppressSelectionChanged; + protected boolean suppressSelectionChanged; public CommentViewer(TaskAttribute commentAttribute) { this.commentAttribute = commentAttribute; @@ -339,7 +339,7 @@ public void expansionStateChanged(ExpansionEvent event) { return commentComposite; } - private Composite createTitle(ExpandableComposite commentComposite, FormToolkit toolkit) { + protected Composite createTitle(ExpandableComposite commentComposite, FormToolkit toolkit) { // always visible Composite titleComposite = toolkit.createComposite(commentComposite); commentComposite.setTextClient(titleComposite); @@ -380,7 +380,7 @@ public void linkActivated(HyperlinkEvent e) { return buttonComposite; } - private ImageHyperlink createTitleHyperLink(FormToolkit toolkit, Composite toolbarComp, + protected ImageHyperlink createTitleHyperLink(FormToolkit toolkit, Composite toolbarComp, ITaskComment taskComment) { ImageHyperlink formHyperlink = toolkit.createImageHyperlink(toolbarComp, SWT.NONE); formHyperlink.setBackground(null); @@ -417,7 +417,7 @@ private ImageHyperlink createTitleHyperLink(FormToolkit toolkit, Composite toolb return formHyperlink; } - private void expandComment(FormToolkit toolkit, Composite composite, boolean expanded) { + protected void expandComment(FormToolkit toolkit, Composite composite, boolean expanded) { buttonComposite.setVisible(expanded); if (expanded && composite.getData(KEY_EDITOR) == null) { commentViewer = toolkit.createComposite(composite); @@ -601,15 +601,15 @@ public Menu getMenu(Menu parent) { /** Expandable composites are indented by 6 pixels by default. */ private static final int INDENT = -6; - private static final String KEY_EDITOR = "viewer"; //$NON-NLS-1$ + protected static final String KEY_EDITOR = "viewer"; //$NON-NLS-1$ - private List commentAttributes; + protected List commentAttributes; private CommentGroupStrategy commentGroupStrategy; - private List commentGroupViewers; + protected List commentGroupViewers; - private boolean expandAllInProgress; + protected boolean expandAllInProgress; private boolean hasIncoming; @@ -630,7 +630,7 @@ public Menu getMenu(Menu parent) { private CommentActionGroup actionGroup; - private boolean suppressExpandViewers; + protected boolean suppressExpandViewers; public TaskEditorCommentPart() { this.commentGroupStrategy = new CommentGroupStrategy() { @@ -660,10 +660,10 @@ private void collapseAllComments() { @SuppressWarnings("unused") boolean collapsed = false; List viewers = getCommentGroupViewers(); - for (int i = 0; i < viewers.size(); i++) { - if (viewers.get(i).isExpanded()) { - viewers.get(i).setFullyExpanded(false); - collapsed = viewers.get(i).isRenderedInSubSection(); + for (CommentGroupViewer viewer : viewers) { + if (viewer.isExpanded()) { + viewer.setFullyExpanded(false); + collapsed = viewer.isRenderedInSubSection(); // bug 280152: collapse all groups //break; } @@ -675,7 +675,7 @@ private void collapseAllComments() { reflow(); } - private TaskComment convertToTaskComment(TaskDataModel taskDataModel, TaskAttribute commentAttribute) { + protected TaskComment convertToTaskComment(TaskDataModel taskDataModel, TaskAttribute commentAttribute) { TaskComment taskComment = new TaskComment(taskDataModel.getTaskRepository(), taskDataModel.getTask(), commentAttribute); taskDataModel.getTaskData().getAttributeMapper().updateTaskComment(taskComment, commentAttribute); diff --git a/org.eclipse.mylyn-target/mylyn-e4.28.target b/org.eclipse.mylyn-target/mylyn-e4.28.target index 0c556495d2..7a8ffe8a25 100644 --- a/org.eclipse.mylyn-target/mylyn-e4.28.target +++ b/org.eclipse.mylyn-target/mylyn-e4.28.target @@ -7,7 +7,7 @@ - + From 80f9836fcb2ae80962baceb6085399fe14e1d1ff Mon Sep 17 00:00:00 2001 From: Frank Becker Date: Wed, 12 Jul 2023 06:43:58 +0200 Subject: [PATCH 07/13] some cleanup --- .../icons/obj16/gitlab.png | Bin 1055 -> 0 bytes .../icons/obj48/gitlab.png | Bin 6493 -> 0 bytes .../mylyn/commons/ui/CommonImages.java | 2 - .../META-INF/MANIFEST.MF | 16 ++-- .../feature.xml | 2 +- .../META-INF/MANIFEST.MF | 8 +- .../eclipse/mylyn/gitlab/ui/GitlabImages.java | 85 ++++++++++++++++++ .../ui/GitlabTaskEditorCommentPart.java | 2 +- 8 files changed, 99 insertions(+), 16 deletions(-) delete mode 100644 mylyn.commons/org.eclipse.mylyn.commons.ui/icons/obj16/gitlab.png delete mode 100644 mylyn.commons/org.eclipse.mylyn.commons.ui/icons/obj48/gitlab.png create mode 100644 mylyn.tasks/connectors/gitlab/org.eclipse.mylyn.gitlab.ui/src/org/eclipse/mylyn/gitlab/ui/GitlabImages.java diff --git a/mylyn.commons/org.eclipse.mylyn.commons.ui/icons/obj16/gitlab.png b/mylyn.commons/org.eclipse.mylyn.commons.ui/icons/obj16/gitlab.png deleted file mode 100644 index d7f648155f60ec5e6b717852a04e8c685265a3ad..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 1055 zcmV+)1mOFLP)EX>4Tx04R}tkv&MmKpe$iQ>7vmhjtKg$WS|35G&%SRVYG*P%E_RU~=gfG%+M8 zE{=k0!NHHks)LKOt`4q(Aou~|>f)s6A|?JWDYS_3;J6>}?mh0_0YbCJG^=ME&~)3( zrc+|Rup)+D5rTjS;z-KOGG-+y1K;s=j{slq5;;BvB z;Ji;9WffT^J|`YC>4LKlt6PRZ32HN#PXG`{Fnsqd;gEXf+(?``B?>CqVESxY9fRjV3VtNqVEB z#g2f%ZQ$a%qbYm9A(Ki)<$Su&n>h;#%$LRx*qpmVHz`-F9 zFH`oK&%67&d;9lHyT2cmv2wM|dNmRN000JJOGiWi{{a60|De66lK=n!32;bRa{vG? zBLDy{BLR4&KXw2B00(qQO+^Ri2Lcl?JFk&f{{R308FWQhbVF}#ZDnqB07G(RVRU6= zAa`kWXdp*PO;A^X4i^9b0r*KoK~y-)jgn1I6Hyd~pF3@xeo#N!LP#(O8;mS)B_^(1 zyHOJtZuJMaG;w9ZhJ`Er3mOeX6HSb$F@i=#BI<$^iBSwx5wwL8oDS2OxyQw{Q&2~J zlbf4+KAw|v&P5vXYBj08d?Ejm^=V%0&!zBf(9p)4X*Pz>Q?ITODG}C3u2Q{u9T5S* z2<(D&?>6$If<5;xGQYmMiuY;)ckBlBa=8VtON;2KF#zo66On-0ToJ0v;5k^+Q!Rk? z>`55pPCjDu`!}@fZaaS6!G8L<1-mnXc3qTfS@QMFNvM=Ur|RxUrP_Y!U!&(|z;i;= zo-3oo)x8uaAEMukxGc7o~6>Ccd+KtFmknIrK zavG(;|1yiAa_ynt%n0qhK4$j!`mr65->1pugJb~JwI9Ri8$fpqwgTgj+pEcT3aar- zlDmXLkB^z&0*+-cjvPaYi1;f@$hBeA!ozJ<9Y^5_q)iE{0!XF@P7e`3csKw6h+V^b zFp4pL3B-dW&`WTafZ*St`%Yk-I!COtD`=w$2sWkhi?8AS5UTJV5={qCP9g^`5IcGt zl}xqfx)sorUtK{@UdE{03i8c<7`#Zldw_5-e**xB>)_AaMb1^@s672Hr}000UxX+uL$Nkc;* zaB^>EX>4Tx07!|QmUmQB*%pV-y*Is3k`RiN&}(Q?0!R(LNRcioF$oY#z>okUHbhi# zL{X8Z2r?+(fTKf^u_B6v0a3B*1Q|rsac~qHmPur-8Q;8l@6DUvANPK1pS{oBXYYO1 zx&V;;g9XA&SP6g(p;#2*=f#MPi)Ua50Sxc}18e}`aI>>Q7WhU2nF4&+jBJ?`_!qsp z4j}paD$_rV!2tiCl(|_VF#u4QjOX(B*<2YH$v8b%oF%tU$(Xh@P0lb%&LUZYGFFpw z@+@0?_L*f5IrB1vJQ>S#&f;b8cV}o=_hCs$|GJ-ARc>v%@$zSl&FIdda6Uz_9&dgda5+tXH875p)hK-XG zi{a1DP3Mcn%rFi&jU(bQ*qIqw9N}^RX3zXt6nSkKvLZX!I5{{lZ7prSDAa#l{F{>Z zc9vd*f9@GXANa%eSALld0I;TIwb}ZIZD|z%UF!i*yZwjFU@riQvc7c=eQ_STd|pz- z;w)z?tK8gNO97v2DKF^n`kxMeLtlK)Qoh~qM8wF>;&Ay4 z=AVc79|!(*9u^V&B)*6*lto0#rc5AAmbF{R6Nm+wLWV&2pPKj&!~Ue%xt59A_z}>S zSOTRX8bE#?04OREAPIY9E70$K3&uwS`OS;bnV6mX&w~DaSGY|6$QC4jj$=neGPn{^ z&g`1}S^_j607XCp>OdRl0~5dmw!jg%01w~;0zoK<1aV+7;DQv80Yo4d6o9p$7?gso zU?->sb)XS6gEnv&bb({wG&lz?fy-b7+yPQB4xWH1@CwX85QK%u5EW8~bRa{>9I}O2 zkQ?L!1w#=~9FzzpLqbRb6+r8tQm7oNhU%ea=v(M0bQ-z<4MVq}QD_qS6?z9FFbSr? zTCfpp1+!pJI0%k}7s1K!GB_VDg15kxa07f0?u1Xnm*5dt3O|9T5r7a8I--j(5f;Km zLXmhR2@xTykP@TC$XgT!MMW`COq2`C9~Fh-qL!gnp*EwcQ3p_+ zs6NzH)F^5S^$|@*Yog83&gcMiEIJvTi!Mf2pqtPg=(Fe%^f>wz27{qvj4_TFe@q-E z6|(}f8M7PHjyZ)H#*AU6u~@7+)*S1K4aIV>Vr((C3VRTH5_<(Zj(vk8;&gDfIA2^m zPKYbSRp451CvaDA6Sx_?65bH+j1R^0@XPUK_(psWeh5E~pCKp{j0vuUNJ1)MEuoUo zMmS5jOL##f67`5q#Bid3xQ19sJVZQC93{RbQAlPaHYtH5A#EY;C!HeQBE2A!$wp)k zay(f~-a>9BpCR8TzfqtnSSkc4@Dx@n)F^Z+Tv2$Yh*vaJ^i*7|n6Fr&ctmkX@u?DC z$w-N<#8FzMRHJlM>4ws@GF90|IaE1Ad9!kh@&)Bb6fDJv;zQw4iYWUiXDDM-gsM+v zQ@PZ2)JE!A>NpKUGo}U5QfZ~MZ)k(GDHV!}ol3Myo=T0%aTO^Yp&QWy=;`z_`eFKY z`a4xERZmsE>L%4T)hnv6)#j*qsPWZG)Y{cX)ZVEx)P2;`)VHa3so&E;X_#q*YvgL| z(KxH|bPjEf%N*{Uk~xRx+}4CO%`_u4S7`3j9MGKB($@0R%F?RRI-~Veo38DlovOV< z`-JwS4pqlZN1(Gq=cLYKh6=-zkLZ@rEqJ6vJJH{f4iNjE!Q9HW+moJu+4^4lvF)ZZ*DZ zLN;+XS!U8;a?KQD$}&we-EDf=3^ubjOEIf48#0H@9n1yhyUm9!&=yV>LW>5A8%z?@ zlbOS8WsX|XErTr!ExRnASs7TxTWz!IxB6&pZ=G)4Xnn_qViRanXwzf!tF4(W*S5y? z+FbHn-?^*jcF%ooXKu&0+hcdro@yUrzrnuO{)2;~gUF%HVbamSG10Ns@dk^=3S(_% zop(Yzc{#0iI_C7&*}+-teAxLH7p6;^ON+~+dB*ej^BU)kx$3!cTZVb0Xx4mvs zcU^amdxQG}4}A}wN0Y~dr>SSE=RwbBUe;bBuMV%*Y-jdL_9<_~+t0hid(emC6XjFw zbKh6bH`%w{0a^jvfaZXyK*zw9fqg-wpantIK@Wn>fV8I2F~=-fTgudr?_nHF76Ya z2X6;&lJCkd=T9WLCY2{WN_I`&o;;c2o>GzWRKONg3!bO?r`DyuP76)jpY|y|CcQla zmywupR7eq~3Hvg&GxIWsv&^%Kv!u(Mm+f3OB?=NXWkcDEvb)7J+0WE~#6+@QGMeL- zQhTd=lZbfxFY`c=@XrK@^Z>#r_a zJ-)_o&4IOqwP|aAD6}ptFMPQ!W?fH_R?(WGvGsoITZV0)e^+=6ZO?$0o?WWq-yLr2> z?D5#sR;N{0TK8_RVDHU(zxvJwqlSuon0-0>9yUfd_J7U#y17ZCskG_Ce&K%UfrtZr z&5q5@Et)N5t#GTPb@E`s!OP!xf79K@Y^!glx0fCQha`s{f1CL2^}|7jdylY=w0&pz zU2O-oqofn+T;4g=mC_~cj_V#i8hEs~$EBy^d&}?lAJaWnb6n+k*$Kjlq7$D^=AWEC zm38Xr>EzR6y-RxUoQXYituMT9@NCf8^XGieo$2@NKY8Bu{ILtp7mi+JUF^E#aH(^^ zexTzA`yV<69R@px9EZ9uJ6-M>o;Q5riu;w*SG}*EyB2Wm(#ZUg;pqt>?FMZqM9Va~FNLGD$lbNT*KP&%S`^@CocfWZ2GB6c8HU3=m{L`|I+Sd?{wJo{Z|>UW?q-PQGavbE$eOnyO?(qGr8}v?<+r;e(3oa^zrVej8C6_ z1NVgU`*8t=>i_@%24YJ`L;(K){{a7>y{D4^000SaNLh0L04^f{04^f|c%?sf00007 zbV*G`2j>R@6DTR(GrsNs000?uMObu0Z*6U5Zgc=ca%Ew3Wn>_CX>@2HM@dakSAh-} z000h%Nklu2 z2}*>JO4|_BNah$`Eo!GnUc5dfE|GP4W>BNMrC=9EX5g`^dd zllTE3IwXfb=!$OHc=+u4$k1>vw}Sp^t@5wg&=}fSBf9ESpY7@C-}%U~u8p7f^zUHG zcylDN>DkL`x1=XFUC|*qeCwC(OZGZl49)qypZHeMkSjN?{&Eh_UaQFHvQDkw#z@zzaM z-(KLj)xPrQi`n${_M$S+5=$CyQJH5+rr{HgTY52jv2Cs|Zgn$WF*nX}YrgT8g`^dF z1^``*H_7P;6oX8TTk|lRlH??QJp%yIC&9jg6U=dIezZ$z?Nt57^mH+v7B|dsYrgSj z`^0&Ajp=D_yjs!Kkk3p7$1S~>Ep}wW6ys@iqiP18x%8{Jdi8EKH=dR^%A=n7d6(>D zXkQLQ>%?ji-nsGUDu-4bW->H2p4K9KG?GviHiIs#g^%k&EKtV@sSF0IQ! zGvl@DG_lN$r%rPuv8j-$N~3$Xgw`A5#-l3$XuWWN&|J$nZt1G1T8>y~Vm!T#-%{g@q1A8n>GN%5xeX*y=aaZ7gv)e5(SmK)(wk8aGS)LiCS zti_mKQO2tkT@B4;p2ggF>|<8z5e#DX4XDBG97$~A7BjzMYH=-MmBbodt2t&fEBWw! zab-`6F`bc#<+!D*LKb^XVx`2^h^~5$TRJLav5zMdWIR0<1aRCI-oZ1PJX(|mv0CAC z+|rXD#dIzUGhVfM#^bnUqbyV#Z;m83Y4I=*$E`M)HM=Ydou?;8U5MkB&3q_y;Q+B> zVmWTj$81W4E*wy0yw)oJ8od_;aNJr4vlq)k{d_&q`vM%d?5Dqwg#$!Q4Kr#%0LQI0 zFgyBw)CDD?*NF|OX#ssV59FB5Uut&|C3>CMjXv1tuE35pg^BvP8`6M*kYlwL5H@c$Hy>DQ?!(2qG6LH+~2(Km( z5Uozc3&R-9(!OutY@awUpJ6U%wl8T|5Rh*zJJ84en;)B1z9_{kt*r~L-*Djcnu3jI zm1(KjK5^bF3+lIn%Q6Ha*^L)i!?Te~tt2P$=L%XRTePEPK>(Nalq+ZvyEoXm^lFc0 zUpO$K@zlQVlZ$KOPG9DzN7Vj+iz{Dco8KpDf563+ud?kTI?i~7zV4HYOHC((sO^n# zaj8+Jg#)9ENBe>RE^BI{g$<*OcSnPNol8`BPH|}_;sAa(r{d3JKX;`6v+b7JkIE*) z~@E0Fnrwo;7FkjN$J)B3!h}B`T znm%0cm=IUtLnIXq=9wP0s(?`GW?Ysy++9GO?LE*Xv^i2lZFiO1{IWeWSsBd z=w%hH)S!04hAu}hb7-aBcpSZKqcx>iLLQ(7wVBX+uAM+0<_2N`ttlNkAO8*j$lD!# zZ_$`>E-_hK-CmAf7SKBGK07WX+Nr%c0+iRwe8AblXdSDzaN@{F8!y_g#OTIGavqT{ zHpt#QDX-UlVqa?==o$QW#CW|iIZS)TmUuXNGojT=9kNu@j-)sEsLy1M-f`{VP@{E* zpa$d0P^xK10O0N8eOs*6W8>)c29p!~R$A?I^xW`Be}VwOlZSd9wOYp86}?tNYr1xx z>fbTScmU8HQF<*`2;ZaE8?=Y{tcKRHdhtkj^El&eKXK8GR+GOnxpJ0e^jZ5BF% zu{~X}&&C<=AK#vT*vbVXO37%z+TJf#Mr*p>KidDnsC1?N*wYpJ%!;^8m%{~w8reaw zOH_(_j+G{j4Q!)^8(%*heS?JpV*$OMfP(S{nTZJA9Z`DIF+0w9_kP~FZZNJ4v0y%{ zqL(<54@L#5>7RwjS5JT4`}85;6KW7;=dUf^`Z+ zA3N>T!MHNC^qr2y3ZSo=szcHkB|Kzl90o*ePYv` z$t9PvlmSjR;PwHD7+o7p5(nU~N-kp(7~AzN+ONbGZ#{9!`ru?x`mat-nd?3 zgG|k?2B}^vtGg`xX;=3jGmb!H`l9!O5?wysdp&EJAqdHihrx8|@$Q=%zFJsc(ga487!c5V+W4JK{grG_^T{%l>6?#D%eKfk zYlr=|k58>&5xHiem$d=zOnP8<&qKLZwrB0kp)rtY(r?=oO`8d(O%D zrbT<(vsHXM(JYMM7hxG_9`f|Nt7$3O{cn7n@KMniEJhbBDU0)UM&b<{@qd~rGO{_gM9*& zF^hqvkc>bz`@PnYk&ZJ%ZS^m;O^GB5e;&K&tZELGw!C*!?Y2VR3}kimrk17Cyk&&e z?YU>Zj68qu=bh_{J(p&6)GoscavSvD+_?D2~a8k zp$7ot0q@|Mp|+MSCl-Fu72BoNIW;#3>*$qB0W$kyl~ode&;}sF(Q2ykSVpf>0|+%4 zzUu&lGaRjkqn2g#DgcDJfKZ;L2Kxco0|;U3qgM~K8W!BpjT_O=Dc1EAZ-Bp z?S)qAjAtf#4{!5(P}h$X+tZusMQm_G@#W;^wNk{%S1e_&`TRy^+c~MLwR6# z&qEu(>iPri>9owMkwVZ*Gg`Ao=mdZhfN)M7T9X14fOL_(ry3xP34PjpWxKud>`(J?Ogs`#}b~i z+<1ndSB^tjzo~1(lY4s})aF!XY?a^o3_UXE67Jl*v8 zjg`;-@+ZOqFnz6oZAwWXo)&X00000NkvXXu0mjf DRl<`V diff --git a/mylyn.commons/org.eclipse.mylyn.commons.ui/src/org/eclipse/mylyn/commons/ui/CommonImages.java b/mylyn.commons/org.eclipse.mylyn.commons.ui/src/org/eclipse/mylyn/commons/ui/CommonImages.java index 5068b12faa..d939a20fa8 100644 --- a/mylyn.commons/org.eclipse.mylyn.commons.ui/src/org/eclipse/mylyn/commons/ui/CommonImages.java +++ b/mylyn.commons/org.eclipse.mylyn.commons.ui/src/org/eclipse/mylyn/commons/ui/CommonImages.java @@ -321,8 +321,6 @@ public class CommonImages { public static final ImageDescriptor PERSON_LARGE = create(T_OBJ48, "person.gif"); //$NON-NLS-1$; - public static final ImageDescriptor GITLAB = create(T_OBJ, "gitlab.png"); //$NON-NLS-1$ - private static ImageDescriptor create(String prefix, String name) { try { return ImageDescriptor.createFromURL(makeIconFileURL(prefix, name)); diff --git a/mylyn.tasks/connectors/gitlab/org.eclipse.mylyn.gitlab.core/META-INF/MANIFEST.MF b/mylyn.tasks/connectors/gitlab/org.eclipse.mylyn.gitlab.core/META-INF/MANIFEST.MF index 583400020b..90ea3bab57 100644 --- a/mylyn.tasks/connectors/gitlab/org.eclipse.mylyn.gitlab.core/META-INF/MANIFEST.MF +++ b/mylyn.tasks/connectors/gitlab/org.eclipse.mylyn.gitlab.core/META-INF/MANIFEST.MF @@ -2,22 +2,22 @@ Manifest-Version: 1.0 Bundle-ManifestVersion: 2 Bundle-Name: Gitlab Connector Core Bundle-SymbolicName: org.eclipse.mylyn.gitlab.core;singleton:=true -Bundle-Version: 3.26.1.qualifier +Bundle-Version: 4.0.0.qualifier Export-Package: org.eclipse.mylyn.gitlab.core Bundle-Activator: org.eclipse.mylyn.gitlab.core.GitlabCoreActivator Require-Bundle: org.eclipse.ui, org.eclipse.core.runtime, - org.eclipse.mylyn.tasks.core;bundle-version="3.26.0", - org.eclipse.mylyn.commons.repositories.http.core;bundle-version="3.26.0", + org.eclipse.jdt.annotation, + org.eclipse.mylyn.tasks.core;bundle-version="4.0.0", + org.eclipse.mylyn.commons.repositories.http.core;bundle-version="4.0.0", + org.eclipse.mylyn.commons.repositories.core;bundle-version="4.0.0", + org.eclipse.mylyn.commons.net;bundle-version="4.0.0", + org.eclipse.mylyn.commons.core;bundle-version="4.0.0", org.apache.httpcomponents.httpclient;bundle-version="4.5.13", - org.eclipse.mylyn.commons.core;bundle-version="3.26.0", org.apache.httpcomponents.httpcore;bundle-version="4.4.15", - org.eclipse.mylyn.commons.repositories.core;bundle-version="3.26.0", com.google.gson;bundle-version="2.9.1", com.google.guava;bundle-version="21.0.0", - org.eclipse.mylyn.commons.net;bundle-version="3.26.0", - org.eclipse.equinox.security;bundle-version="1.3.1000", - org.eclipse.jdt.annotation + org.eclipse.equinox.security;bundle-version="1.3.1000" Bundle-RequiredExecutionEnvironment: JavaSE-17 Automatic-Module-Name: org.eclipse.mylyn.gitlab.core Bundle-ActivationPolicy: lazy diff --git a/mylyn.tasks/connectors/gitlab/org.eclipse.mylyn.gitlab.feature/feature.xml b/mylyn.tasks/connectors/gitlab/org.eclipse.mylyn.gitlab.feature/feature.xml index 04b41d39b2..8a2673e54d 100644 --- a/mylyn.tasks/connectors/gitlab/org.eclipse.mylyn.gitlab.feature/feature.xml +++ b/mylyn.tasks/connectors/gitlab/org.eclipse.mylyn.gitlab.feature/feature.xml @@ -2,7 +2,7 @@ diff --git a/mylyn.tasks/connectors/gitlab/org.eclipse.mylyn.gitlab.ui/META-INF/MANIFEST.MF b/mylyn.tasks/connectors/gitlab/org.eclipse.mylyn.gitlab.ui/META-INF/MANIFEST.MF index 91d455a60c..879dfbec81 100644 --- a/mylyn.tasks/connectors/gitlab/org.eclipse.mylyn.gitlab.ui/META-INF/MANIFEST.MF +++ b/mylyn.tasks/connectors/gitlab/org.eclipse.mylyn.gitlab.ui/META-INF/MANIFEST.MF @@ -2,7 +2,7 @@ Manifest-Version: 1.0 Bundle-ManifestVersion: 2 Bundle-Name: Gitlab Connector UI Bundle-SymbolicName: org.eclipse.mylyn.gitlab.ui;singleton:=true -Bundle-Version: 3.26.1.qualifier +Bundle-Version: 4.0.0.qualifier Export-Package: org.eclipse.mylyn.gitlab.ui Bundle-Activator: org.eclipse.mylyn.gitlab.ui.GitlabUiActivator Require-Bundle: org.eclipse.ui, @@ -12,9 +12,9 @@ Require-Bundle: org.eclipse.ui, org.eclipse.ui.forms;bundle-version="3.11.500", org.eclipse.mylyn.gitlab.core;bundle-version="1.0.0", com.google.guava, - org.eclipse.mylyn.commons.workbench;bundle-version="3.26.0", - org.eclipse.mylyn.commons.ui;bundle-version="3.26.0", - org.eclipse.mylyn.commons.core;bundle-version="3.26.1", + org.eclipse.mylyn.commons.workbench;bundle-version="4.0.0", + org.eclipse.mylyn.commons.ui;bundle-version="4.0.0", + org.eclipse.mylyn.commons.core;bundle-version="4.0.0", org.eclipse.jdt.annotation Bundle-RequiredExecutionEnvironment: JavaSE-17 Automatic-Module-Name: org.eclipse.mylyn.gitlab.ui diff --git a/mylyn.tasks/connectors/gitlab/org.eclipse.mylyn.gitlab.ui/src/org/eclipse/mylyn/gitlab/ui/GitlabImages.java b/mylyn.tasks/connectors/gitlab/org.eclipse.mylyn.gitlab.ui/src/org/eclipse/mylyn/gitlab/ui/GitlabImages.java new file mode 100644 index 0000000000..c2f63da30a --- /dev/null +++ b/mylyn.tasks/connectors/gitlab/org.eclipse.mylyn.gitlab.ui/src/org/eclipse/mylyn/gitlab/ui/GitlabImages.java @@ -0,0 +1,85 @@ +package org.eclipse.mylyn.gitlab.ui; + +import java.net.MalformedURLException; +import java.net.URL; + +import org.eclipse.core.runtime.Platform; +import org.eclipse.jface.resource.ImageDescriptor; +import org.eclipse.jface.resource.ImageRegistry; +import org.eclipse.mylyn.commons.ui.CommonImages; +import org.eclipse.mylyn.internal.commons.ui.CommonsUiConstants; +import org.eclipse.swt.graphics.Image; +import org.osgi.framework.Bundle; + +public class GitlabImages { + + private static final URL baseUrl; + static { + Bundle bundle = Platform.getBundle(GitlabUiActivator.PLUGIN_ID); + if (bundle != null) { + baseUrl = bundle.getEntry("/icons/"); //$NON-NLS-1$ + } else { + URL iconsUrl = null; + try { + // lookup location of CommonImages class on disk + iconsUrl = new URL(GitlabImages.class.getResource("GitlabImages.class"), "../../../../../../icons/"); //$NON-NLS-1$ //$NON-NLS-2$ + } catch (MalformedURLException e) { + // ignore + } + baseUrl = iconsUrl; + } + } + + private static ImageRegistry imageRegistry; + + private static final String T_EVIEW = "eview16"; //$NON-NLS-1$ + private static final String T_OBJ = "obj16"; //$NON-NLS-1$ + + public static final ImageDescriptor GITLAB_ICON = create(T_EVIEW, "gitlab-icon.png"); //$NON-NLS-1$ + + public static final ImageDescriptor GITLAB_OVERLAY = create(T_EVIEW, "gitlab-overlay.png"); //$NON-NLS-1$ + public static final ImageDescriptor GITLAB = create(T_OBJ, "gitlab.png"); //$NON-NLS-1$ + + private static ImageDescriptor create(String prefix, String name) { + try { + return ImageDescriptor.createFromURL(makeIconFileURL(prefix, name)); + } catch (MalformedURLException e) { + return ImageDescriptor.getMissingImageDescriptor(); + } + } + + private static URL makeIconFileURL(String prefix, String name) throws MalformedURLException { + if (baseUrl == null) { + throw new MalformedURLException(); + } + + StringBuffer buffer = new StringBuffer(prefix); + buffer.append('/'); + buffer.append(name); + return new URL(baseUrl, buffer.toString()); + } + + private static ImageRegistry getImageRegistry() { + if (imageRegistry == null) { + imageRegistry = new ImageRegistry(); + } + + return imageRegistry; + } + + /** + * Lazily initializes image map. + * + * @param imageDescriptor + * @return Image + */ + public static Image getImage(ImageDescriptor imageDescriptor) { + ImageRegistry imageRegistry = getImageRegistry(); + Image image = imageRegistry.get("" + imageDescriptor.hashCode()); //$NON-NLS-1$ + if (image == null) { + image = imageDescriptor.createImage(true); + imageRegistry.put("" + imageDescriptor.hashCode(), image); //$NON-NLS-1$ + } + return image; + } +} diff --git a/mylyn.tasks/connectors/gitlab/org.eclipse.mylyn.gitlab.ui/src/org/eclipse/mylyn/gitlab/ui/GitlabTaskEditorCommentPart.java b/mylyn.tasks/connectors/gitlab/org.eclipse.mylyn.gitlab.ui/src/org/eclipse/mylyn/gitlab/ui/GitlabTaskEditorCommentPart.java index ae2cbe1a12..fbfe3d0e6b 100644 --- a/mylyn.tasks/connectors/gitlab/org.eclipse.mylyn.gitlab.ui/src/org/eclipse/mylyn/gitlab/ui/GitlabTaskEditorCommentPart.java +++ b/mylyn.tasks/connectors/gitlab/org.eclipse.mylyn.gitlab.ui/src/org/eclipse/mylyn/gitlab/ui/GitlabTaskEditorCommentPart.java @@ -236,7 +236,7 @@ public void linkActivated(HyperlinkEvent e) { TaskAttribute systemAttribute = taskComment.getTaskAttribute().getAttribute("system"); String systemAttributeValue = systemAttribute != null ? systemAttribute.getValue() : "false"; if ("true".equals(systemAttributeValue)) { - expandCommentHyperlink.setImage(CommonImages.getImage(CommonImages.GITLAB)); + expandCommentHyperlink.setImage(GitlabImages.getImage(GitlabImages.GITLAB)); } ToolBarManager toolBarManagerTitle = new ToolBarManager(SWT.FLAT); From 011737ce02240d2aff577ec85f0acdb91b00aaea Mon Sep 17 00:00:00 2001 From: Frank Becker Date: Mon, 17 Jul 2023 18:35:59 +0200 Subject: [PATCH 08/13] Comment/Discussion Update support; Avantar enabled --- .../commons/identity/core/IdentityModel.java | 6 +- .../gitlab/core/GitlabCoreActivator.java | 1 + .../core/GitlabRepositoryConnector.java | 753 ++++---- .../mylyn/gitlab/core/GitlabRestClient.java | 1684 +++++++++-------- .../core/GitlabTaskAttributeMapper.java | 98 +- .../feature.xml | 2 +- .../META-INF/MANIFEST.MF | 1 + .../mylyn/gitlab/ui/GitlabConnectorUI.java | 96 +- .../ui/GitlabRepositorySettingsPage.java | 397 ++-- .../ui/GitlabTaskEditorCommentPart.java | 132 +- .../mylyn/gitlab/ui/GitlabTaskEditorPage.java | 93 +- .../ui/GitlabTaskEditorSummaryPart.java | 90 + .../ui/editors/TaskEditorCommentPart.java | 30 +- .../ui/editors/TaskEditorSummaryPart.java | 14 +- .../tasks/ui/editors/UserAttributeEditor.java | 6 +- org.eclipse.mylyn.releng/oomph/Mylyn.setup | 7 + 16 files changed, 1902 insertions(+), 1508 deletions(-) create mode 100644 mylyn.tasks/connectors/gitlab/org.eclipse.mylyn.gitlab.ui/src/org/eclipse/mylyn/gitlab/ui/GitlabTaskEditorSummaryPart.java diff --git a/mylyn.commons/org.eclipse.mylyn.commons.identity.core/src/org/eclipse/mylyn/internal/commons/identity/core/IdentityModel.java b/mylyn.commons/org.eclipse.mylyn.commons.identity.core/src/org/eclipse/mylyn/internal/commons/identity/core/IdentityModel.java index 2178b5b2cd..5aea4c540e 100644 --- a/mylyn.commons/org.eclipse.mylyn.commons.identity.core/src/org/eclipse/mylyn/internal/commons/identity/core/IdentityModel.java +++ b/mylyn.commons/org.eclipse.mylyn.commons.identity.core/src/org/eclipse/mylyn/internal/commons/identity/core/IdentityModel.java @@ -1,10 +1,10 @@ /******************************************************************************* * Copyright (c) 2011 Tasktop Technologies and others. - * + * * This program and the accompanying materials are made available under the * terms of the Eclipse Public License v. 2.0 which is available at * https://www.eclipse.org/legal/epl-2.0 - * + * * SPDX-License-Identifier: EPL-2.0 * * Tasktop Technologies - initial API and implementation @@ -46,7 +46,7 @@ public IdentityModel() { } public void addConnector(IdentityConnector connector) { - connectors.add(new GravatarConnector()); + connectors.add(connector); } public synchronized IIdentity getIdentity(Account account) { diff --git a/mylyn.tasks/connectors/gitlab/org.eclipse.mylyn.gitlab.core/src/org/eclipse/mylyn/gitlab/core/GitlabCoreActivator.java b/mylyn.tasks/connectors/gitlab/org.eclipse.mylyn.gitlab.core/src/org/eclipse/mylyn/gitlab/core/GitlabCoreActivator.java index 058cb2abfc..af6a2a8c62 100644 --- a/mylyn.tasks/connectors/gitlab/org.eclipse.mylyn.gitlab.core/src/org/eclipse/mylyn/gitlab/core/GitlabCoreActivator.java +++ b/mylyn.tasks/connectors/gitlab/org.eclipse.mylyn.gitlab.core/src/org/eclipse/mylyn/gitlab/core/GitlabCoreActivator.java @@ -27,6 +27,7 @@ public class GitlabCoreActivator extends AbstractUIPlugin { public static final String CONNECTOR_KIND = "org.eclipse.mylyn.gitlab"; public static final String GROUPS = "gitlab.groups"; public static final String PROJECTS = "gitlab.projects"; + public static final String AVANTAR = "gitlab.avantar"; public static final String API_VERSION = "/api/v4"; // The shared instance diff --git a/mylyn.tasks/connectors/gitlab/org.eclipse.mylyn.gitlab.core/src/org/eclipse/mylyn/gitlab/core/GitlabRepositoryConnector.java b/mylyn.tasks/connectors/gitlab/org.eclipse.mylyn.gitlab.core/src/org/eclipse/mylyn/gitlab/core/GitlabRepositoryConnector.java index 86c515866d..ba67c94e0a 100644 --- a/mylyn.tasks/connectors/gitlab/org.eclipse.mylyn.gitlab.core/src/org/eclipse/mylyn/gitlab/core/GitlabRepositoryConnector.java +++ b/mylyn.tasks/connectors/gitlab/org.eclipse.mylyn.gitlab.core/src/org/eclipse/mylyn/gitlab/core/GitlabRepositoryConnector.java @@ -15,6 +15,11 @@ import java.beans.PropertyChangeEvent; import java.beans.PropertyChangeListener; +import java.io.ByteArrayOutputStream; +import java.io.IOException; +import java.io.InputStream; +import java.net.HttpURLConnection; +import java.net.URL; import java.text.SimpleDateFormat; import java.util.Collections; import java.util.HashSet; @@ -68,428 +73,472 @@ public class GitlabRepositoryConnector extends AbstractRepositoryConnector { - public class RepositoryKey { - private final TaskRepository repository; + public class RepositoryKey { + private final TaskRepository repository; - public RepositoryKey(@NonNull TaskRepository repository) { - super(); - this.repository = repository; - } - - public TaskRepository getRepository() { - return repository; - } + public RepositoryKey(@NonNull TaskRepository repository) { + super(); + this.repository = repository; + } - @Override - public int hashCode() { - return repository.hashCode(); - } + public TaskRepository getRepository() { + return repository; + } - @Override - public boolean equals(Object obj) { - if (this == obj) { - return true; - } - if (obj == null || getClass() != obj.getClass()) { - return false; - } - return this.repository.equals(((RepositoryKey) obj).getRepository()); - } + @Override + public int hashCode() { + return repository.hashCode(); } - private static final ThreadLocal context = new ThreadLocal(); - - private final LoadingCache> configurationCache; - private SimpleDateFormat simpleFormatter = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss.SSS'Z'"); - public static Duration CONFIGURATION_CACHE_EXPIRE_DURATION = new Duration(7, TimeUnit.DAYS); - public static Duration CONFIGURATION_CACHE_REFRESH_AFTER_WRITE_DURATION = new Duration(1, TimeUnit.DAYS); - public static Duration CLIENT_CACHE_DURATION = new Duration(24, TimeUnit.HOURS); - - private boolean ignoredProperty(String propertyName) { - if (propertyName.equals(RepositoryLocation.PROPERTY_LABEL) || propertyName.equals(TaskRepository.OFFLINE) - || propertyName.equals(IRepositoryConstants.PROPERTY_ENCODING) - || propertyName.equals(TaskRepository.PROXY_HOSTNAME) || propertyName.equals(TaskRepository.PROXY_PORT) - || propertyName.equals("org.eclipse.mylyn.tasklist.repositories.savePassword") //$NON-NLS-1$ - || propertyName.equals("org.eclipse.mylyn.tasklist.repositories.proxy.usedefault") //$NON-NLS-1$ - || propertyName.equals("org.eclipse.mylyn.tasklist.repositories.proxy.savePassword") //$NON-NLS-1$ - || propertyName.equals("org.eclipse.mylyn.tasklist.repositories.proxy.username") //$NON-NLS-1$ - || propertyName.equals("org.eclipse.mylyn.tasklist.repositories.proxy.password") //$NON-NLS-1$ - || propertyName.equals("org.eclipse.mylyn.tasklist.repositories.proxy.enabled")) { //$NON-NLS-1$ - return true; - } + @Override + public boolean equals(Object obj) { + if (this == obj) { + return true; + } + if (obj == null || getClass() != obj.getClass()) { return false; + } + return this.repository.equals(((RepositoryKey) obj).getRepository()); } + } + + private static final ThreadLocal context = new ThreadLocal(); + + private final LoadingCache> configurationCache; + private SimpleDateFormat simpleFormatter = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss.SSS'Z'"); + public static Duration CONFIGURATION_CACHE_EXPIRE_DURATION = new Duration(7, TimeUnit.DAYS); + public static Duration CONFIGURATION_CACHE_REFRESH_AFTER_WRITE_DURATION = new Duration(1, TimeUnit.DAYS); + public static Duration CLIENT_CACHE_DURATION = new Duration(24, TimeUnit.HOURS); + + private boolean ignoredProperty(String propertyName) { + if (propertyName.equals(RepositoryLocation.PROPERTY_LABEL) || propertyName.equals(TaskRepository.OFFLINE) + || propertyName.equals(IRepositoryConstants.PROPERTY_ENCODING) + || propertyName.equals(TaskRepository.PROXY_HOSTNAME) || propertyName.equals(TaskRepository.PROXY_PORT) + || propertyName.equals("org.eclipse.mylyn.tasklist.repositories.savePassword") //$NON-NLS-1$ + || propertyName.equals("org.eclipse.mylyn.tasklist.repositories.proxy.usedefault") //$NON-NLS-1$ + || propertyName.equals("org.eclipse.mylyn.tasklist.repositories.proxy.savePassword") //$NON-NLS-1$ + || propertyName.equals("org.eclipse.mylyn.tasklist.repositories.proxy.username") //$NON-NLS-1$ + || propertyName.equals("org.eclipse.mylyn.tasklist.repositories.proxy.password") //$NON-NLS-1$ + || propertyName.equals("org.eclipse.mylyn.tasklist.repositories.proxy.enabled")) { //$NON-NLS-1$ + return true; + } + return false; + } - abstract class ListenableFutureJob extends Job implements ListenableFuture { - - private class Listener { - - Runnable runnable; - - Executor executor; + abstract class ListenableFutureJob extends Job implements ListenableFuture { - public Listener(Runnable runnable, Executor executor) { - this.runnable = runnable; - this.executor = executor; - } + private class Listener { - public void run() { - executor.execute(runnable); - } - } + Runnable runnable; - List listeners = Collections.synchronizedList(Lists.newArrayList()); + Executor executor; - private volatile boolean done; + public Listener(Runnable runnable, Executor executor) { + this.runnable = runnable; + this.executor = executor; + } - private V resultObject; + public void run() { + executor.execute(runnable); + } + } - public ListenableFutureJob(String name) { - super(name); - resultObject = null; - this.addJobChangeListener(new JobChangeAdapter() { + List listeners = Collections.synchronizedList(Lists.newArrayList()); - @Override - public void done(IJobChangeEvent event) { - done = true; - synchronized (listeners) { - for (Listener listener : listeners) { - listener.run(); - } - } - } - }); - } + private volatile boolean done; - @Override - public boolean cancel(boolean mayInterruptIfRunning) { - return this.cancel(); - } + private V resultObject; - @Override - public V get() throws InterruptedException, ExecutionException { - this.join(); - return resultObject; - } + public ListenableFutureJob(String name) { + super(name); + resultObject = null; + this.addJobChangeListener(new JobChangeAdapter() { @Override - public V get(long timeout, TimeUnit unit) throws InterruptedException, ExecutionException, TimeoutException { - long start = System.currentTimeMillis(); - while (!done && System.currentTimeMillis() - start < unit.toMillis(timeout)) { - Thread.sleep(250); - } - if (!done) { - throw new TimeoutException("ListenableFutureJob.get() could not get the result!"); + public void done(IJobChangeEvent event) { + done = true; + synchronized (listeners) { + for (Listener listener : listeners) { + listener.run(); } - return resultObject; - } - - protected void set(V future) { - this.resultObject = future; - } - - @Override - public boolean isCancelled() { - return this.getResult().getSeverity() == IStatus.CANCEL; - } - - @Override - public boolean isDone() { - return done; - } - - @Override - public void addListener(Runnable listener, Executor executor) { - listeners.add(new Listener(listener, executor)); + } } + }); } - private final PropertyChangeListener repositoryChangeListener4ConfigurationCache = new PropertyChangeListener() { - - @Override - public void propertyChange(PropertyChangeEvent evt) { - if (ignoredProperty(evt.getPropertyName()) - || evt.getPropertyName().equals("org.eclipse.mylyn.tasklist.repositories.password")) { //$NON-NLS-1$ - return; - } - TaskRepository taskRepository = (TaskRepository) evt.getSource(); - configurationCache.invalidate(new RepositoryKey(taskRepository)); - } - }; - - protected CacheBuilder createCacheBuilder(Duration expireAfterWriteDuration, - Duration refreshAfterWriteDuration) { - return CacheBuilder.newBuilder() - .expireAfterWrite(expireAfterWriteDuration.getValue(), expireAfterWriteDuration.getUnit()) - .refreshAfterWrite(refreshAfterWriteDuration.getValue(), refreshAfterWriteDuration.getUnit()); + @Override + public boolean cancel(boolean mayInterruptIfRunning) { + return this.cancel(); } - public GitlabRepositoryConnector() { - this(CONFIGURATION_CACHE_REFRESH_AFTER_WRITE_DURATION); + @Override + public V get() throws InterruptedException, ExecutionException { + this.join(); + return resultObject; } - public GitlabRepositoryConnector(Duration refreshAfterWriteDuration) { - super(); - configurationCache = createCacheBuilder(CONFIGURATION_CACHE_EXPIRE_DURATION, refreshAfterWriteDuration) - .build(new CacheLoader>() { - - @Override - public Optional load(RepositoryKey key) throws Exception { - GitlabRestClient client = clientCache.get(key); - TaskRepository repository = key.getRepository(); - repository.addChangeListener(repositoryChangeListener4ConfigurationCache); - return Optional.fromNullable(client.getConfiguration(key.getRepository(), context.get())); - } - - @Override - public ListenableFuture> reload(final RepositoryKey key, - Optional oldValue) throws Exception { - // asynchronous! - ListenableFutureJob> job = new ListenableFutureJob>( - "") { - - @Override - protected IStatus run(IProgressMonitor monitor) { - GitlabRestClient client; - try { - client = clientCache.get(key); - set(Optional - .fromNullable(client.getConfiguration(key.getRepository(), context.get()))); - } catch (ExecutionException e) { - e.printStackTrace(); - return new Status(IStatus.ERROR, GitlabCoreActivator.PLUGIN_ID, - "GitlabConnector reload Configuration", e); - } - return Status.OK_STATUS; - } - }; - job.schedule(); - return job; - } - }); + @Override + public V get(long timeout, TimeUnit unit) throws InterruptedException, ExecutionException, TimeoutException { + long start = System.currentTimeMillis(); + while (!done && System.currentTimeMillis() - start < unit.toMillis(timeout)) { + Thread.sleep(250); + } + if (!done) { + throw new TimeoutException("ListenableFutureJob.get() could not get the result!"); + } + return resultObject; } - public GitlabConfiguration getRepositoryConfiguration(TaskRepository repository) throws CoreException { - if (clientCache.getIfPresent(new RepositoryKey(repository)) == null) { - getClient(repository); - } - try { - Optional configurationOptional = configurationCache.get(new RepositoryKey(repository)); - return configurationOptional.isPresent() ? configurationOptional.get() : null; - } catch (UncheckedExecutionException e) { - throw new CoreException(new Status(IStatus.ERROR, GitlabCoreActivator.PLUGIN_ID, e.getMessage(), e)); - } catch (ExecutionException e) { - throw new CoreException(new Status(IStatus.ERROR, GitlabCoreActivator.PLUGIN_ID, e.getMessage(), e)); - } + protected void set(V future) { + this.resultObject = future; } @Override - public boolean canCreateNewTask(@NonNull TaskRepository repository) { - return true; + public boolean isCancelled() { + return this.getResult().getSeverity() == IStatus.CANCEL; } @Override - public boolean canCreateTaskFromKey(@NonNull TaskRepository repository) { - // TODO Auto-generated method stub - return false; + public boolean isDone() { + return done; } @Override - public @Nullable String getRepositoryUrlFromTaskUrl(@NonNull String taskUrl) { - throw new UnsupportedOperationException(); + public void addListener(Runnable listener, Executor executor) { + listeners.add(new Listener(listener, executor)); } + } - @Override - public @Nullable String getTaskIdFromTaskUrl(@NonNull String taskUrl) { - throw new UnsupportedOperationException(); - } + private final PropertyChangeListener repositoryChangeListener4ConfigurationCache = new PropertyChangeListener() { @Override - public @Nullable String getTaskUrl(@NonNull String repositoryUrl, @NonNull String taskIdOrKey) { - throw new UnsupportedOperationException(); + public void propertyChange(PropertyChangeEvent evt) { + if (ignoredProperty(evt.getPropertyName()) + || evt.getPropertyName().equals("org.eclipse.mylyn.tasklist.repositories.password")) { //$NON-NLS-1$ + return; + } + TaskRepository taskRepository = (TaskRepository) evt.getSource(); + configurationCache.invalidate(new RepositoryKey(taskRepository)); } - - @Override - public boolean hasTaskChanged(@NonNull TaskRepository taskRepository, @NonNull ITask task, - @NonNull TaskData taskData) { - String lastKnownLocalModValue = task.getModificationDate() != null - ? simpleFormatter.format(task.getModificationDate()) - : ""; - TaskAttribute latestRemoteModAttribute = taskData.getRoot().getMappedAttribute(TaskAttribute.DATE_MODIFICATION); - String latestRemoteModValue = latestRemoteModAttribute != null ? latestRemoteModAttribute.getValue() : null; - return !Objects.equal(latestRemoteModValue, lastKnownLocalModValue); + }; + + protected CacheBuilder createCacheBuilder(Duration expireAfterWriteDuration, + Duration refreshAfterWriteDuration) { + return CacheBuilder.newBuilder() + .expireAfterWrite(expireAfterWriteDuration.getValue(), expireAfterWriteDuration.getUnit()) + .refreshAfterWrite(refreshAfterWriteDuration.getValue(), refreshAfterWriteDuration.getUnit()); + } + + public GitlabRepositoryConnector() { + this(CONFIGURATION_CACHE_REFRESH_AFTER_WRITE_DURATION); + } + + public GitlabRepositoryConnector(Duration refreshAfterWriteDuration) { + super(); + configurationCache = createCacheBuilder(CONFIGURATION_CACHE_EXPIRE_DURATION, refreshAfterWriteDuration) + .build(new CacheLoader>() { + + @Override + public Optional load(RepositoryKey key) throws Exception { + GitlabRestClient client = clientCache.get(key); + TaskRepository repository = key.getRepository(); + repository.addChangeListener(repositoryChangeListener4ConfigurationCache); + return Optional.fromNullable(client.getConfiguration(key.getRepository(), context.get())); + } + + @Override + public ListenableFuture> reload(final RepositoryKey key, + Optional oldValue) throws Exception { + // asynchronous! + ListenableFutureJob> job = new ListenableFutureJob>( + "") { + + @Override + protected IStatus run(IProgressMonitor monitor) { + GitlabRestClient client; + try { + client = clientCache.get(key); + set(Optional + .fromNullable(client.getConfiguration(key.getRepository(), context.get()))); + } catch (ExecutionException e) { + e.printStackTrace(); + return new Status(IStatus.ERROR, GitlabCoreActivator.PLUGIN_ID, + "GitlabConnector reload Configuration", e); + } + return Status.OK_STATUS; + } + }; + job.schedule(); + return job; + } + }); + } + + public GitlabConfiguration getRepositoryConfiguration(TaskRepository repository) throws CoreException { + if (clientCache.getIfPresent(new RepositoryKey(repository)) == null) { + getClient(repository); } - - @Override - public void updateRepositoryConfiguration(@NonNull TaskRepository taskRepository, @NonNull IProgressMonitor monitor) - throws CoreException { - context.set(monitor != null ? OperationUtil.convert(monitor) : new NullOperationMonitor()); - configurationCache.invalidate(new RepositoryKey(taskRepository)); - getRepositoryConfiguration(taskRepository); - context.remove(); + try { + Optional configurationOptional = configurationCache.get(new RepositoryKey(repository)); + return configurationOptional.isPresent() ? configurationOptional.get() : null; + } catch (UncheckedExecutionException e) { + throw new CoreException(new Status(IStatus.ERROR, GitlabCoreActivator.PLUGIN_ID, e.getMessage(), e)); + } catch (ExecutionException e) { + throw new CoreException(new Status(IStatus.ERROR, GitlabCoreActivator.PLUGIN_ID, e.getMessage(), e)); } + } + + @Override + public boolean canCreateNewTask(@NonNull TaskRepository repository) { + return true; + } + + @Override + public boolean canCreateTaskFromKey(@NonNull TaskRepository repository) { + return false; + } + + @Override + public @Nullable String getRepositoryUrlFromTaskUrl(@NonNull String taskUrl) { + throw new UnsupportedOperationException(); + } + + @Override + public @Nullable String getTaskIdFromTaskUrl(@NonNull String taskUrl) { + throw new UnsupportedOperationException(); + } + + @Override + public @Nullable String getTaskUrl(@NonNull String repositoryUrl, @NonNull String taskIdOrKey) { + throw new UnsupportedOperationException(); + } + + @Override + public boolean hasTaskChanged(@NonNull TaskRepository taskRepository, @NonNull ITask task, + @NonNull TaskData taskData) { + String lastKnownLocalModValue = task.getModificationDate() != null + ? simpleFormatter.format(task.getModificationDate()) + : ""; + TaskAttribute latestRemoteModAttribute = taskData.getRoot().getMappedAttribute(TaskAttribute.DATE_MODIFICATION); + String latestRemoteModValue = latestRemoteModAttribute != null ? latestRemoteModAttribute.getValue() : null; + return !Objects.equal(latestRemoteModValue, lastKnownLocalModValue); + } + + @Override + public void updateRepositoryConfiguration(@NonNull TaskRepository taskRepository, @NonNull IProgressMonitor monitor) + throws CoreException { + context.set(monitor != null ? OperationUtil.convert(monitor) : new NullOperationMonitor()); + configurationCache.invalidate(new RepositoryKey(taskRepository)); + getRepositoryConfiguration(taskRepository); + context.remove(); + } + + @Override + public String getConnectorKind() { + return GitlabCoreActivator.CONNECTOR_KIND; + } + + @Override + public String getLabel() { + return "Gitlab"; + } + + public class SingleTaskDataCollector extends TaskDataCollector { + final TaskData[] retrievedData = new TaskData[1]; @Override - public String getConnectorKind() { - return GitlabCoreActivator.CONNECTOR_KIND; + public void accept(TaskData taskData) { + retrievedData[0] = taskData; } - @Override - public String getLabel() { - return "Gitlab"; + public TaskData getTaskData() { + return retrievedData[0]; } - public class SingleTaskDataCollector extends TaskDataCollector { - final TaskData[] retrievedData = new TaskData[1]; - - @Override - public void accept(TaskData taskData) { - retrievedData[0] = taskData; - } + } - public TaskData getTaskData() { - return retrievedData[0]; - } + @Override + public TaskData getTaskData(TaskRepository repository, String taskId, IProgressMonitor monitor) + throws CoreException { + Set taskIds = new HashSet(); + taskIds.add(taskId); + SingleTaskDataCollector singleTaskDataCollector = new SingleTaskDataCollector(); + getTaskDataHandler().getMultiTaskData(repository, taskIds, singleTaskDataCollector, monitor); + if (singleTaskDataCollector.getTaskData() == null) { + throw new CoreException(new Status(IStatus.ERROR, GitlabCoreActivator.PLUGIN_ID, + "Task data could not be retrieved. Please re-synchronize task")); //$NON-NLS-1$ } - - @Override - public TaskData getTaskData(TaskRepository repository, String taskId, IProgressMonitor monitor) - throws CoreException { - Set taskIds = new HashSet(); - taskIds.add(taskId); - SingleTaskDataCollector singleTaskDataCollector = new SingleTaskDataCollector(); - getTaskDataHandler().getMultiTaskData(repository, taskIds, singleTaskDataCollector, monitor); - - if (singleTaskDataCollector.getTaskData() == null) { - throw new CoreException(new Status(IStatus.ERROR, GitlabCoreActivator.PLUGIN_ID, - "Task data could not be retrieved. Please re-synchronize task")); //$NON-NLS-1$ - } - return singleTaskDataCollector.getTaskData(); + return singleTaskDataCollector.getTaskData(); + } + + @Override + public IStatus performQuery(TaskRepository repository, IRepositoryQuery query, TaskDataCollector collector, + ISynchronizationSession session, IProgressMonitor monitor) { + monitor.beginTask("performQuery", IProgressMonitor.UNKNOWN); + GitlabRestClient client; + try { + client = getClient(repository); + IOperationMonitor progress = OperationUtil.convert(monitor, "performQuery", 3); //$NON-NLS-1$ + client.getIssues(query, collector, new NullOperationMonitor()); + } catch (CoreException e) { + return new Status(IStatus.ERROR, GitlabCoreActivator.PLUGIN_ID, IStatus.INFO, + "CoreException from performQuery", e); + } catch (GitlabException e) { + return new Status(IStatus.ERROR, GitlabCoreActivator.PLUGIN_ID, IStatus.INFO, + "GitlabException from performQuery", e); } - - @Override - public IStatus performQuery(TaskRepository repository, IRepositoryQuery query, TaskDataCollector collector, - ISynchronizationSession session, IProgressMonitor monitor) { - monitor.beginTask("performQuery", IProgressMonitor.UNKNOWN); - GitlabRestClient client; - try { - client = getClient(repository); - IOperationMonitor progress = OperationUtil.convert(monitor, "performQuery", 3); //$NON-NLS-1$ - client.getIssues(query, collector, new NullOperationMonitor()); - } catch (CoreException e) { - return new Status(IStatus.ERROR, GitlabCoreActivator.PLUGIN_ID, IStatus.INFO, - "CoreException from performQuery", e); - } catch (GitlabException e) { - return new Status(IStatus.ERROR, GitlabCoreActivator.PLUGIN_ID, IStatus.INFO, - "GitlabException from performQuery", e); - } - return Status.OK_STATUS; + return Status.OK_STATUS; + } + + @Override + public void updateTaskFromTaskData(TaskRepository taskRepository, ITask task, TaskData taskData) { + TaskMapper scheme = getTaskMapping(taskData); + scheme.applyTo(task); + } + + @Override + public AbstractTaskDataHandler getTaskDataHandler() { + return new GitlabTaskDataHandler(this); + } + + @Override + public RepositoryInfo validateRepository(TaskRepository repository, IProgressMonitor monitor) throws CoreException { + try { + GitlabRestClient client = createClient(repository); + if (!client.validate(OperationUtil.convert(monitor))) { + throw new CoreException( + new Status(IStatus.ERROR, GitlabCoreActivator.PLUGIN_ID, "repository is invalide")); + } + return new RepositoryInfo(new RepositoryVersion(client.getVersion(OperationUtil.convert(monitor)))); + } catch (Exception e) { + throw new CoreException(new Status(IStatus.ERROR, GitlabCoreActivator.PLUGIN_ID, e.getMessage(), e)); } - - @Override - public void updateTaskFromTaskData(TaskRepository taskRepository, ITask task, TaskData taskData) { - TaskMapper scheme = getTaskMapping(taskData); - scheme.applyTo(task); + } + + public GitlabRestClient getClient(TaskRepository repository) throws CoreException { + try { + return clientCache.get(new RepositoryKey(repository)); + } catch (ExecutionException e) { + throw new CoreException( + new Status(IStatus.ERROR, GitlabCoreActivator.PLUGIN_ID, "TaskRepositoryManager is null")); } + } - @Override - public AbstractTaskDataHandler getTaskDataHandler() { - return new GitlabTaskDataHandler(this); - } + private final PropertyChangeListener repositoryChangeListener4ClientCache = new PropertyChangeListener() { @Override - public RepositoryInfo validateRepository(TaskRepository repository, IProgressMonitor monitor) throws CoreException { - try { - GitlabRestClient client = createClient(repository); - if (!client.validate(OperationUtil.convert(monitor))) { - throw new CoreException( - new Status(IStatus.ERROR, GitlabCoreActivator.PLUGIN_ID, "repository is invalide")); - } - return new RepositoryInfo(new RepositoryVersion(client.getVersion(OperationUtil.convert(monitor)))); - } catch (Exception e) { - throw new CoreException(new Status(IStatus.ERROR, GitlabCoreActivator.PLUGIN_ID, e.getMessage(), e)); - } + public void propertyChange(PropertyChangeEvent evt) { + TaskRepository taskRepository = (TaskRepository) evt.getSource(); + clientCache.invalidate(new RepositoryKey(taskRepository)); } + }; - public GitlabRestClient getClient(TaskRepository repository) throws CoreException { - try { - return clientCache.get(new RepositoryKey(repository)); - } catch (ExecutionException e) { - throw new CoreException( - new Status(IStatus.ERROR, GitlabCoreActivator.PLUGIN_ID, "TaskRepositoryManager is null")); - } - } - - private final PropertyChangeListener repositoryChangeListener4ClientCache = new PropertyChangeListener() { + private final LoadingCache clientCache = CacheBuilder.newBuilder() + .expireAfterAccess(CLIENT_CACHE_DURATION.getValue(), CLIENT_CACHE_DURATION.getUnit()) + .build(new CacheLoader() { @Override - public void propertyChange(PropertyChangeEvent evt) { - TaskRepository taskRepository = (TaskRepository) evt.getSource(); - clientCache.invalidate(new RepositoryKey(taskRepository)); + public GitlabRestClient load(RepositoryKey key) throws Exception { + TaskRepository repository = key.getRepository(); + repository.addChangeListener(repositoryChangeListener4ClientCache); + return createClient(repository); } - }; - - private final LoadingCache clientCache = CacheBuilder.newBuilder() - .expireAfterAccess(CLIENT_CACHE_DURATION.getValue(), CLIENT_CACHE_DURATION.getUnit()) - .build(new CacheLoader() { - - @Override - public GitlabRestClient load(RepositoryKey key) throws Exception { - TaskRepository repository = key.getRepository(); - repository.addChangeListener(repositoryChangeListener4ClientCache); - return createClient(repository); - } - }); - - public GitlabRestClient createClient(TaskRepository repository) { - RepositoryLocation location = new RepositoryLocation(convertProperties(repository)); - AuthenticationCredentials credentials1 = repository - .getCredentials(org.eclipse.mylyn.commons.net.AuthenticationType.REPOSITORY); - UserCredentials credentials = new UserCredentials(credentials1.getUserName(), credentials1.getPassword(), null, - true); - location.setCredentials(AuthenticationType.REPOSITORY, credentials); - GitlabRestClient client = new GitlabRestClient(location, this, repository); - - return client; - } + }); - private Map convertProperties(TaskRepository repository) { - return repository.getProperties().entrySet().stream() - .collect(Collectors.toMap(e -> convertProperty(e.getKey()), Map.Entry::getValue)); - } + private final LoadingCache avatarCache = CacheBuilder.newBuilder() + .expireAfterAccess(CLIENT_CACHE_DURATION.getValue(), CLIENT_CACHE_DURATION.getUnit()) + .build(new CacheLoader() { - @SuppressWarnings("restriction") - private String convertProperty(String key) { - if (TaskRepository.PROXY_USEDEFAULT.equals(key)) { - return RepositoryLocation.PROPERTY_PROXY_USEDEFAULT; - } else if (TaskRepository.PROXY_HOSTNAME.equals(key)) { - return RepositoryLocation.PROPERTY_PROXY_HOST; - } else if (TaskRepository.PROXY_PORT.equals(key)) { - return RepositoryLocation.PROPERTY_PROXY_PORT; + @Override + public byte[] load(String key) throws Exception { + byte[] avatarBytes = null; + HttpURLConnection connection; + + connection = (HttpURLConnection) new URL(key).openConnection(); + connection.setConnectTimeout(30000); + connection.setUseCaches(false); + connection.connect(); + + if (connection.getResponseCode() == 200) { + ByteArrayOutputStream output = new ByteArrayOutputStream(); + InputStream input = connection.getInputStream(); + try { + byte[] buffer = new byte[8192]; + int read = -1; + while ((read = input.read(buffer)) != -1) { + output.write(buffer, 0, read); + } + } finally { + try { + input.close(); + } catch (IOException ignore) { + } + } + avatarBytes = output.toByteArray(); + } + return avatarBytes; } - return key; + }); + + public GitlabRestClient createClient(TaskRepository repository) { + RepositoryLocation location = new RepositoryLocation(convertProperties(repository)); + AuthenticationCredentials credentials1 = repository + .getCredentials(org.eclipse.mylyn.commons.net.AuthenticationType.REPOSITORY); + UserCredentials credentials = new UserCredentials(credentials1.getUserName(), credentials1.getPassword(), null, + true); + location.setCredentials(AuthenticationType.REPOSITORY, credentials); + GitlabRestClient client = new GitlabRestClient(location, this, repository); + + return client; + } + + private Map convertProperties(TaskRepository repository) { + return repository.getProperties().entrySet().stream() + .collect(Collectors.toMap(e -> convertProperty(e.getKey()), Map.Entry::getValue)); + } + + @SuppressWarnings("restriction") + private String convertProperty(String key) { + if (TaskRepository.PROXY_USEDEFAULT.equals(key)) { + return RepositoryLocation.PROPERTY_PROXY_USEDEFAULT; + } else if (TaskRepository.PROXY_HOSTNAME.equals(key)) { + return RepositoryLocation.PROPERTY_PROXY_HOST; + } else if (TaskRepository.PROXY_PORT.equals(key)) { + return RepositoryLocation.PROPERTY_PROXY_PORT; } + return key; + } + + @Override + public TaskMapper getTaskMapping(final TaskData taskData) { + + return new TaskMapper(taskData) { + @Override + public String getTaskKey() { + TaskAttribute attribute = getTaskData().getRoot() + .getAttribute(GitlabTaskSchema.getDefault().TASK_KEY.getKey()); + if (attribute != null) { + return attribute.getValue(); + } + return super.getTaskKey(); + } - @Override - public TaskMapper getTaskMapping(final TaskData taskData) { - - return new TaskMapper(taskData) { - @Override - public String getTaskKey() { - TaskAttribute attribute = getTaskData().getRoot() - .getAttribute(GitlabTaskSchema.getDefault().TASK_KEY.getKey()); - if (attribute != null) { - return attribute.getValue(); - } - return super.getTaskKey(); - } - - @Override - public String getTaskKind() { - return taskData.getConnectorKind(); - } - }; + @Override + public String getTaskKind() { + return taskData.getConnectorKind(); + } + }; + } + + public byte[] getAvatarData(String url) { + try { + return avatarCache.get(url); + } catch (ExecutionException e) { +// throw new CoreException( +// new Status(IStatus.ERROR, GitlabCoreActivator.PLUGIN_ID, "TaskRepositoryManager is null")); } + return null; + } } diff --git a/mylyn.tasks/connectors/gitlab/org.eclipse.mylyn.gitlab.core/src/org/eclipse/mylyn/gitlab/core/GitlabRestClient.java b/mylyn.tasks/connectors/gitlab/org.eclipse.mylyn.gitlab.core/src/org/eclipse/mylyn/gitlab/core/GitlabRestClient.java index 5e07e50e22..d6d3c958ae 100644 --- a/mylyn.tasks/connectors/gitlab/org.eclipse.mylyn.gitlab.core/src/org/eclipse/mylyn/gitlab/core/GitlabRestClient.java +++ b/mylyn.tasks/connectors/gitlab/org.eclipse.mylyn.gitlab.core/src/org/eclipse/mylyn/gitlab/core/GitlabRestClient.java @@ -49,6 +49,8 @@ import org.eclipse.mylyn.commons.repositories.core.RepositoryLocation; import org.eclipse.mylyn.commons.repositories.http.core.CommonHttpClient; import org.eclipse.mylyn.commons.repositories.http.core.CommonHttpResponse; +import org.eclipse.mylyn.internal.commons.core.operations.NullOperationMonitor; +import org.eclipse.mylyn.tasks.core.IRepositoryPerson; import org.eclipse.mylyn.tasks.core.IRepositoryQuery; import org.eclipse.mylyn.tasks.core.RepositoryResponse; import org.eclipse.mylyn.tasks.core.RepositoryResponse.ResponseKind; @@ -77,326 +79,335 @@ public class GitlabRestClient { - @SuppressWarnings("restriction") - private final CommonHttpClient client; - private final GitlabRepositoryConnector connector; - private final TaskRepository taskRepository; - - public static String AUTHORIZATION_HEADER = "authorization_header"; - - @SuppressWarnings("restriction") - public GitlabRestClient(RepositoryLocation location, GitlabRepositoryConnector connector, - TaskRepository taskRepository) { - super(); - client = new CommonHttpClient(location); - this.connector = connector; - this.taskRepository = taskRepository; - } - - @SuppressWarnings("restriction") - public RepositoryLocation getLocation() { - return client.getLocation(); - } - - @SuppressWarnings("restriction") - public CommonHttpClient getClient() { - return client; - } - - public TaskRepository getTaskRepository() { - return taskRepository; - } - - public IStatus getIssues(IRepositoryQuery query, TaskDataCollector collector, final IOperationMonitor monitor) - throws GitlabException, CoreException { - getAccessTokenIfNotPresent(monitor); - String[] queryProjects = query.getAttribute(GitlabTaskSchema.getDefault().PRODUCT.getKey()).split(","); - String groupAttribute = query.getAttribute("group"); - - if (!queryProjects[0].isEmpty()) { - for (String string : queryProjects) { - String path = "/projects/" + string.replaceAll("/", "%2F"); - getIssuesInternal(query, collector, path, monitor); - } + @SuppressWarnings("restriction") + private final CommonHttpClient client; + private final GitlabRepositoryConnector connector; + private final TaskRepository taskRepository; + + public static String AUTHORIZATION_HEADER = "authorization_header"; + + @SuppressWarnings("restriction") + public GitlabRestClient(RepositoryLocation location, GitlabRepositoryConnector connector, + TaskRepository taskRepository) { + super(); + client = new CommonHttpClient(location); + this.connector = connector; + this.taskRepository = taskRepository; + } + + @SuppressWarnings("restriction") + public RepositoryLocation getLocation() { + return client.getLocation(); + } + + @SuppressWarnings("restriction") + public CommonHttpClient getClient() { + return client; + } + + public TaskRepository getTaskRepository() { + return taskRepository; + } + + public IStatus getIssues(IRepositoryQuery query, TaskDataCollector collector, final IOperationMonitor monitor) + throws GitlabException, CoreException { + getAccessTokenIfNotPresent(monitor); + String[] queryProjects = query.getAttribute(GitlabTaskSchema.getDefault().PRODUCT.getKey()).split(","); + String groupAttribute = query.getAttribute("group"); + + if (!queryProjects[0].isEmpty()) { + for (String string : queryProjects) { + String path = "/projects/" + string.replaceAll("/", "%2F"); + getIssuesInternal(query, collector, path, monitor); + } + } + if (groupAttribute != null) { + String[] gueryGroups = groupAttribute.split(","); + if (!gueryGroups[0].isEmpty()) { + for (String string : gueryGroups) { + String path = "/groups/" + string.replaceAll("/", "%2F"); + getIssuesInternal(query, collector, path, monitor); } - if (groupAttribute != null) { - String[] gueryGroups = groupAttribute.split(","); - if (!gueryGroups[0].isEmpty()) { - for (String string : gueryGroups) { - String path = "/groups/" + string.replaceAll("/", "%2F"); - getIssuesInternal(query, collector, path, monitor); - } - } + } + } + return Status.OK_STATUS; + } + + private void getIssuesInternal(IRepositoryQuery query, TaskDataCollector collector, String path, + final IOperationMonitor monitor) throws GitlabException { + List taskDataArray = new GitlabOperation>(client, path + "/issues") { + + @Override + protected HttpRequestBase createHttpRequestBase(String url) { + String state = query.getAttribute("STATE"); + String suffix; + switch (state != null ? state : "") { + case "opened": + suffix = "?state=opened"; + break; + case "closed": + suffix = "?state=closed"; + break; + default: + suffix = ""; } - return Status.OK_STATUS; - } - - private void getIssuesInternal(IRepositoryQuery query, TaskDataCollector collector, String path, - final IOperationMonitor monitor) throws GitlabException { - List taskDataArray = new GitlabOperation>(client, path + "/issues") { - - @Override - protected HttpRequestBase createHttpRequestBase(String url) { - String state = query.getAttribute("STATE"); - String suffix; - switch (state != null ? state : "") { - case "opened": - suffix = "?state=opened"; - break; - case "closed": - suffix = "?state=closed"; - break; - default: - suffix = ""; - } - HttpRequestBase request = new HttpGet(url + suffix); - return request; - } - - @Override - protected List parseFromJson(InputStreamReader in) throws GitlabException { - - TypeToken> type = new TypeToken>() { - }; - - return new GsonBuilder().registerTypeAdapter(type.getType(), new JSonTaskDataListDeserializer()) - .create().fromJson(in, type.getType()); - } - }.run(monitor); - for (final TaskData taskData : taskDataArray) { - taskData.setPartial(true); - SafeRunner.run(new ISafeRunnable() { - - @Override - public void run() throws Exception { - collector.accept(taskData); - } - - @Override - public void handleException(Throwable exception) { - StatusHandler.log(new Status(IStatus.ERROR, GitlabCoreActivator.PLUGIN_ID, - NLS.bind("Unexpected error during result collection. TaskID {0} in repository {1}", //$NON-NLS-1$ - taskData.getTaskId(), taskData.getRepositoryUrl()), - exception)); - } - }); - } - } - - public String getVersion(IOperationMonitor monitor) throws GitlabException { - getAccessTokenIfNotPresent(monitor); - JsonObject versionInfo = new GitlabOperation(client, "/version") { - - @Override - protected HttpRequestBase createHttpRequestBase(String url) { - HttpRequestBase request = new HttpGet(url); - return request; - } + HttpRequestBase request = new HttpGet(url + suffix); + return request; + } - @Override - protected JsonObject parseFromJson(InputStreamReader in) throws GitlabException { - return new Gson().fromJson(in, JsonObject.class); - } - }.run(monitor); - return versionInfo.get("version").getAsString(); - } + @Override + protected List parseFromJson(InputStreamReader in) throws GitlabException { - public String getVersionAndRevision(IOperationMonitor monitor) throws GitlabException { - getAccessTokenIfNotPresent(monitor); - JsonObject versionInfo = new GitlabOperation(client, "/version") { - - @Override - protected HttpRequestBase createHttpRequestBase(String url) { - HttpRequestBase request = new HttpGet(url); - return request; - } - - @Override - protected JsonObject parseFromJson(InputStreamReader in) throws GitlabException { - return new Gson().fromJson(in, JsonObject.class); - } - }.run(monitor); - return versionInfo.get("version").getAsString() + "(rev: " + versionInfo.get("revision").getAsString() + ")"; - } + TypeToken> type = new TypeToken>() { + }; - public boolean validate(IOperationMonitor monitor) throws GitlabException { - getAccessTokenIfNotPresent(monitor); - String validate = new GitlabOperation(client, "/version") { - - protected boolean isRepeatable() { - return false; - }; - - @Override - protected HttpRequestBase createHttpRequestBase(String url) { - HttpRequestBase request = new HttpGet(url); - return request; - } - - @Override - protected String parseFromJson(InputStreamReader in) throws GitlabException { - return new BufferedReader(in).lines().parallel().collect(Collectors.joining("\n")); - } - }.run(monitor); - return validate.length() > 0 && validate.contains("version"); - } - - public JsonObject getMetadata(IOperationMonitor monitor) throws GitlabException { - getAccessTokenIfNotPresent(monitor); - JsonObject jsonArray = new GitlabOperation(client, "/metadata") { - @Override - protected HttpRequestBase createHttpRequestBase(String url) { - HttpRequestBase request = new HttpGet(url); - return request; - } - - @Override - protected JsonObject parseFromJson(InputStreamReader in) throws GitlabException { - return new Gson().fromJson(in, JsonObject.class); - } - }.run(monitor); - return jsonArray; - } - - private class JSonTaskDataListDeserializer implements JsonDeserializer> { + return new GsonBuilder().registerTypeAdapter(type.getType(), new JSonTaskDataListDeserializer()) + .create().fromJson(in, type.getType()); + } + }.run(monitor); + for (final TaskData taskData : taskDataArray) { + taskData.setPartial(true); + SafeRunner.run(new ISafeRunnable() { @Override - public ArrayList deserialize(JsonElement json, Type typeOfT, JsonDeserializationContext context) - throws JsonParseException { - ArrayList response = new ArrayList(); - GitlabConfiguration config = getConfiguration(); - JsonArray ja = json.getAsJsonArray(); - for (JsonElement jsonElement : ja) { - JsonObject jo = jsonElement.getAsJsonObject(); - TaskData taskData = getFromJson(jo); - if (config != null) - config.updateProductOptions(taskData); - response.add(taskData); - } - return response; + public void run() throws Exception { + collector.accept(taskData); } - } - - private TaskData getFromJson(JsonObject jo) { - GitlabTaskDataHandler dataHandler = (GitlabTaskDataHandler) connector.getTaskDataHandler(); - TaskAttributeMapper mapper = dataHandler.getAttributeMapper(taskRepository); - String selfString = jo.get("_links").getAsJsonObject().get("self").getAsString(); - TaskData response = new TaskData(mapper, connector.getConnectorKind(), taskRepository.getRepositoryUrl(), selfString.replace(taskRepository.getUrl() + GitlabCoreActivator.API_VERSION, "")); - try { - dataHandler.initializeTaskData(taskRepository, response, null, null); - } catch (CoreException e) { - throw new RuntimeException(e); - } - for (Entry entry : jo.entrySet()) { - String attributeId = GitlabTaskSchema.getAttributeNameFromJsonName(entry.getKey()); - TaskAttribute attribute = response.getRoot().getAttribute(attributeId); - Field field = GitlabTaskSchema.getDefault().getFieldByKey(attributeId); - if (attribute == null) { - PrintStream ps = attribute == null ? System.err : System.out; - ps.println(entry.getKey() + " -> " + entry.getValue() // - + " -> " + attributeId + " -> " + attribute + "\n" // - + entry.getValue().isJsonPrimitive() + entry.getValue().isJsonObject() - + entry.getValue().isJsonArray()); - ps.flush(); - } - if (attribute != null && entry.getValue() != null && entry.getValue().isJsonPrimitive()) { - attribute.setValue(entry.getValue().getAsString()); - } - if (field != null && TaskAttribute.TYPE_PERSON.equals(field.getType()) && entry.getValue().isJsonObject()) { - attribute.setValue(entry.getValue().getAsJsonObject().get("name").getAsString()); - } - } - return response; - } - - private class JSonTaskDataDeserializer implements JsonDeserializer { @Override - public TaskData deserialize(JsonElement json, Type typeOfT, JsonDeserializationContext context) - throws JsonParseException { - GitlabConfiguration config = getConfiguration(); - JsonObject jo = json.getAsJsonObject(); - TaskData taskData = getFromJson(jo); - if (config != null) { - config.updateProductOptions(taskData); - config.addValidOperations(taskData); - } - return taskData; + public void handleException(Throwable exception) { + StatusHandler.log(new Status(IStatus.ERROR, GitlabCoreActivator.PLUGIN_ID, + NLS.bind("Unexpected error during result collection. TaskID {0} in repository {1}", //$NON-NLS-1$ + taskData.getTaskId(), taskData.getRepositoryUrl()), + exception)); } - } - - private GitlabConfiguration getConfiguration() { - GitlabConfiguration config; - try { - config = connector.getRepositoryConfiguration(taskRepository); - } catch (CoreException e) { - // TODO Auto-generated catch block - e.printStackTrace(); - config = null; - } - return config; - } - - private void getAccessTokenIfNotPresent(IOperationMonitor monitor) { - if (getClientAttribute(AUTHORIZATION_HEADER) == null) { - try { - obtainAccessToken(monitor); - } catch (Exception e) { - // TODO Auto-generated catch block - e.printStackTrace(); - } - } - } - - @SuppressWarnings("restriction") - private Object getClientAttribute(String attribute) { - return getClient().getAttribute(attribute); - } - - @SuppressWarnings("restriction") - private void setClientAttribute(String attribute, Object value) { - getClient().setAttribute(attribute, value); - } - - public String obtainAccessToken(IOperationMonitor monitor) throws Exception { - AuthenticationCredentials credentials1 = taskRepository - .getCredentials(org.eclipse.mylyn.commons.net.AuthenticationType.REPOSITORY); - String username = credentials1.getUserName(); - String password = credentials1.getPassword(); - String repositoryUrl = taskRepository.getRepositoryUrl(); - - URL url = new URL(repositoryUrl + "/oauth/token"); - HttpURLConnection connection = (HttpURLConnection) url.openConnection(); - connection.setRequestMethod("POST"); - connection.setDoOutput(true); - connection.getOutputStream() - .write(("grant_type=password&username=" + username + "&password=" + password).getBytes()); - connection.connect(); - - int responseCode = connection.getResponseCode(); - if (responseCode != 200) { - throw new Exception("Failed to obtain access token"); - } - - String response = new String(connection.getInputStream().readAllBytes()); - String accessToken = response.split("\"access_token\":\"")[1].split("\"")[0]; - setClientAttribute(AUTHORIZATION_HEADER, "Bearer " + accessToken); - return accessToken; - } - - public TaskData getTaskData(TaskRepository repository, String taskId, IProgressMonitor monitor) - throws GitlabException { - TaskData result = null; - String searchString = ".*(/projects/\\d+)/issues/(\\d+)"; - Pattern pattern = Pattern.compile(searchString, Pattern.CASE_INSENSITIVE); - Matcher matcher = pattern.matcher(taskId); - if (matcher.find()) { - GitlabConfiguration config = getConfiguration(); - JsonObject iss = getIssue(matcher.group(1), matcher.group(2), OperationUtil.convert(monitor)); - TypeToken type = new TypeToken() { - }; - result = new GsonBuilder().registerTypeAdapter(type.getType(), new JSonTaskDataDeserializer()).create() - .fromJson(iss, type.getType()); + }); + } + } + + public String getVersion(IOperationMonitor monitor) throws GitlabException { + getAccessTokenIfNotPresent(monitor); + JsonObject versionInfo = new GitlabOperation(client, "/version") { + + @Override + protected HttpRequestBase createHttpRequestBase(String url) { + HttpRequestBase request = new HttpGet(url); + return request; + } + + @Override + protected JsonObject parseFromJson(InputStreamReader in) throws GitlabException { + return new Gson().fromJson(in, JsonObject.class); + } + }.run(monitor); + return versionInfo.get("version").getAsString(); + } + + public String getVersionAndRevision(IOperationMonitor monitor) throws GitlabException { + getAccessTokenIfNotPresent(monitor); + JsonObject versionInfo = new GitlabOperation(client, "/version") { + + @Override + protected HttpRequestBase createHttpRequestBase(String url) { + HttpRequestBase request = new HttpGet(url); + return request; + } + + @Override + protected JsonObject parseFromJson(InputStreamReader in) throws GitlabException { + return new Gson().fromJson(in, JsonObject.class); + } + }.run(monitor); + return versionInfo.get("version").getAsString() + "(rev: " + versionInfo.get("revision").getAsString() + ")"; + } + + public boolean validate(IOperationMonitor monitor) throws GitlabException { + getAccessTokenIfNotPresent(monitor); + String validate = new GitlabOperation(client, "/version") { + + protected boolean isRepeatable() { + return false; + }; + + @Override + protected HttpRequestBase createHttpRequestBase(String url) { + HttpRequestBase request = new HttpGet(url); + return request; + } + + @Override + protected String parseFromJson(InputStreamReader in) throws GitlabException { + return new BufferedReader(in).lines().parallel().collect(Collectors.joining("\n")); + } + }.run(monitor); + return validate.length() > 0 && validate.contains("version"); + } + + public JsonObject getMetadata(IOperationMonitor monitor) throws GitlabException { + getAccessTokenIfNotPresent(monitor); + JsonObject jsonArray = new GitlabOperation(client, "/metadata") { + @Override + protected HttpRequestBase createHttpRequestBase(String url) { + HttpRequestBase request = new HttpGet(url); + return request; + } + + @Override + protected JsonObject parseFromJson(InputStreamReader in) throws GitlabException { + return new Gson().fromJson(in, JsonObject.class); + } + }.run(monitor); + return jsonArray; + } + + private class JSonTaskDataListDeserializer implements JsonDeserializer> { + + @Override + public ArrayList deserialize(JsonElement json, Type typeOfT, JsonDeserializationContext context) + throws JsonParseException { + ArrayList response = new ArrayList(); + GitlabConfiguration config = getConfiguration(); + JsonArray ja = json.getAsJsonArray(); + for (JsonElement jsonElement : ja) { + JsonObject jo = jsonElement.getAsJsonObject(); + TaskData taskData = getFromJson(jo); + if (config != null) + config.updateProductOptions(taskData); + response.add(taskData); + } + return response; + } + } + + private TaskData getFromJson(JsonObject jo) { + GitlabTaskDataHandler dataHandler = (GitlabTaskDataHandler) connector.getTaskDataHandler(); + TaskAttributeMapper mapper = dataHandler.getAttributeMapper(taskRepository); + String selfString = jo.get("_links").getAsJsonObject().get("self").getAsString(); + TaskData response = new TaskData(mapper, connector.getConnectorKind(), taskRepository.getRepositoryUrl(), + selfString.replace(taskRepository.getUrl() + GitlabCoreActivator.API_VERSION, "")); + try { + dataHandler.initializeTaskData(taskRepository, response, null, null); + } catch (CoreException e) { + throw new RuntimeException(e); + } + for (Entry entry : jo.entrySet()) { + String attributeId = GitlabTaskSchema.getAttributeNameFromJsonName(entry.getKey()); + TaskAttribute attribute = response.getRoot().getAttribute(attributeId); + Field field = GitlabTaskSchema.getDefault().getFieldByKey(attributeId); + if (attribute == null) { + PrintStream ps = attribute == null ? System.err : System.out; + ps.println(entry.getKey() + " -> " + entry.getValue() // + + " -> " + attributeId + " -> " + attribute + "\n" // + + entry.getValue().isJsonPrimitive() + entry.getValue().isJsonObject() + + entry.getValue().isJsonArray()); + ps.flush(); + } + if (attribute != null && entry.getValue() != null && entry.getValue().isJsonPrimitive()) { + attribute.setValue(entry.getValue().getAsString()); + } + if (field != null && TaskAttribute.TYPE_PERSON.equals(field.getType()) && entry.getValue().isJsonObject()) { + + attribute.setValue(entry.getValue().getAsJsonObject().get("name").getAsString()); + IRepositoryPerson author = taskRepository + .createPerson(entry.getValue().getAsJsonObject().get("username").getAsString()); + author.setName( + entry.getValue().getAsJsonObject().get("name").getAsString()); + author.setAttribute("avatar_url", entry.getValue().getAsJsonObject() + .get("avatar_url").getAsString()); + mapper.setRepositoryPerson(attribute, author); + } + } + return response; + } + + private class JSonTaskDataDeserializer implements JsonDeserializer { + + @Override + public TaskData deserialize(JsonElement json, Type typeOfT, JsonDeserializationContext context) + throws JsonParseException { + GitlabConfiguration config = getConfiguration(); + JsonObject jo = json.getAsJsonObject(); + TaskData taskData = getFromJson(jo); + if (config != null) { + config.updateProductOptions(taskData); + config.addValidOperations(taskData); + } + return taskData; + } + } + + private GitlabConfiguration getConfiguration() { + GitlabConfiguration config; + try { + config = connector.getRepositoryConfiguration(taskRepository); + } catch (CoreException e) { + // TODO Auto-generated catch block + e.printStackTrace(); + config = null; + } + return config; + } + + private void getAccessTokenIfNotPresent(IOperationMonitor monitor) { + if (getClientAttribute(AUTHORIZATION_HEADER) == null) { + try { + obtainAccessToken(monitor); + } catch (Exception e) { + // TODO Auto-generated catch block + e.printStackTrace(); + } + } + } + + @SuppressWarnings("restriction") + private Object getClientAttribute(String attribute) { + return getClient().getAttribute(attribute); + } + + @SuppressWarnings("restriction") + private void setClientAttribute(String attribute, Object value) { + getClient().setAttribute(attribute, value); + } + + public String obtainAccessToken(IOperationMonitor monitor) throws Exception { + AuthenticationCredentials credentials1 = taskRepository + .getCredentials(org.eclipse.mylyn.commons.net.AuthenticationType.REPOSITORY); + String username = credentials1.getUserName(); + String password = credentials1.getPassword(); + String repositoryUrl = taskRepository.getRepositoryUrl(); + + URL url = new URL(repositoryUrl + "/oauth/token"); + HttpURLConnection connection = (HttpURLConnection) url.openConnection(); + connection.setRequestMethod("POST"); + connection.setDoOutput(true); + connection.getOutputStream() + .write(("grant_type=password&username=" + username + "&password=" + password).getBytes()); + connection.connect(); + + int responseCode = connection.getResponseCode(); + if (responseCode != 200) { + throw new Exception("Failed to obtain access token"); + } + + String response = new String(connection.getInputStream().readAllBytes()); + String accessToken = response.split("\"access_token\":\"")[1].split("\"")[0]; + setClientAttribute(AUTHORIZATION_HEADER, "Bearer " + accessToken); + return accessToken; + } + + public TaskData getTaskData(TaskRepository repository, String taskId, IProgressMonitor monitor) + throws GitlabException { + TaskData result = null; + String searchString = ".*(/projects/\\d+)/issues/(\\d+)"; + Pattern pattern = Pattern.compile(searchString, Pattern.CASE_INSENSITIVE); + Matcher matcher = pattern.matcher(taskId); + if (matcher.find()) { + GitlabConfiguration config = getConfiguration(); + JsonObject issue = getIssue(matcher.group(1), matcher.group(2), OperationUtil.convert(monitor)); + TypeToken type = new TypeToken() { + }; + result = new GsonBuilder().registerTypeAdapter(type.getType(), new JSonTaskDataDeserializer()).create() + .fromJson(issue, type.getType()); // JsonArray notes = getIssueNotes(matcher.group(1), matcher.group(2), OperationUtil.convert(monitor)); // if (notes != null) { @@ -406,343 +417,374 @@ public TaskData getTaskData(TaskRepository repository, String taskId, IProgressM // i = createNoteTaskAttribute(repository, result, i, note); // } // } - JsonArray discussions = getIssueDiscussions(matcher.group(1), matcher.group(2), - OperationUtil.convert(monitor)); - if (discussions != null) { - int i = 0; - TaskAttribute attrib = null; - for (JsonElement jsonElement : discussions) { - JsonObject discussion = (JsonObject) jsonElement; - JsonArray notesArray = discussion.get("notes").getAsJsonArray(); - if (discussion.get("individual_note").getAsBoolean()) { - JsonObject note = notesArray.get(0).getAsJsonObject(); - attrib = createNoteTaskAttribute(repository, result.getRoot(), i++, note); - } else { - TaskAttribute reply = null; - for ( JsonElement jsonElement2 : notesArray) { - JsonObject note = jsonElement2.getAsJsonObject(); - attrib = createNoteTaskAttribute(repository, reply==null?result.getRoot():reply, i++, note); - if (reply == null) { - reply = attrib.createAttribute("reply"); - } - } - } - } - } - - config.updateProductOptions(result); + JsonArray discussions = getIssueDiscussions(matcher.group(1), matcher.group(2), + OperationUtil.convert(monitor)); + if (discussions != null) { + int i = 0; + TaskAttribute attrib = null; + for (JsonElement jsonElement : discussions) { + JsonObject discussion = (JsonObject) jsonElement; + JsonArray notesArray = discussion.get("notes").getAsJsonArray(); + if (discussion.get("individual_note").getAsBoolean()) { + JsonObject note = notesArray.get(0).getAsJsonObject(); + attrib = createNoteTaskAttribute(repository, result.getRoot(), i++, note); + attrib.createAttribute("discussions").setValue(discussion.get("id").getAsString()); + attrib.createAttribute("noteable_id").setValue(note.get("noteable_id").getAsString()); + attrib.createAttribute("note_id").setValue(note.get("id").getAsString()); + } else { + TaskAttribute reply = null; + for (JsonElement jsonElement2 : notesArray) { + JsonObject note = jsonElement2.getAsJsonObject(); + attrib = createNoteTaskAttribute(repository, reply == null ? result.getRoot() : reply, i++, + note); + if (reply == null) { + reply = attrib.createAttribute("reply"); + } + attrib.createAttribute("discussions").setValue(discussion.get("id").getAsString()); + attrib.createAttribute("noteable_id").setValue(note.get("noteable_id").getAsString()); + attrib.createAttribute("note_id").setValue(note.get("id").getAsString()); + } + } } - return result; - } - - private TaskAttribute createNoteTaskAttribute(TaskRepository repository, TaskAttribute result, int i, JsonObject note) { - TaskCommentMapper cmapper = new TaskCommentMapper(); - cmapper.setAuthor(repository.createPerson(note.get("author").getAsJsonObject().get("name").getAsString())); - cmapper.setCreationDate(GitlabTaskAttributeMapper.parseDate(note.get("created_at").getAsString())); - cmapper.setText(note.get("body").getAsString()); - cmapper.setNumber(++i); - TaskAttribute attribute = result.createAttribute(TaskAttribute.PREFIX_COMMENT + i); - cmapper.applyTo(attribute); - attribute.createAttribute("system").setValue(note.get("system").getAsString()); - return attribute; - } - - public void getTaskData(Set taskIds, TaskRepository taskRepository, TaskDataCollector collector, - IOperationMonitor monitor) throws GitlabException { - - for (String taskId : taskIds) { - TaskData data; - data = getTaskData(taskRepository, taskId, monitor); - collector.accept(data); + } + + config.updateProductOptions(result); + } + return result; + } + + private TaskAttribute createNoteTaskAttribute(TaskRepository repository, TaskAttribute result, int i, + JsonObject note) { + TaskCommentMapper cmapper = new TaskCommentMapper(); + IRepositoryPerson author = repository + .createPerson(note.get("author").getAsJsonObject().get("username").getAsString()); + author.setName(note.get("author").getAsJsonObject().get("name").getAsString()); + author.setAttribute("avatar_url", note.get("author").getAsJsonObject().get("avatar_url").getAsString()); + cmapper.setAuthor(author); + cmapper.setCreationDate(GitlabTaskAttributeMapper.parseDate(note.get("created_at").getAsString())); + cmapper.setText(note.get("body").getAsString()); + cmapper.setNumber(++i); + TaskAttribute attribute = result.createAttribute(TaskAttribute.PREFIX_COMMENT + i); + cmapper.applyTo(attribute); + attribute.createAttribute("system").setValue(note.get("system").getAsString()); + return attribute; + } + + public void getTaskData(Set taskIds, TaskRepository taskRepository, TaskDataCollector collector, + IOperationMonitor monitor) throws GitlabException { + + for (String taskId : taskIds) { + TaskData data; + data = getTaskData(taskRepository, taskId, monitor); + collector.accept(data); + } + } + + public JsonObject getUser(IOperationMonitor monitor) throws GitlabException { + getAccessTokenIfNotPresent(monitor); + JsonObject jsonArray = new GitlabOperation(client, "/user") { + @Override + protected HttpRequestBase createHttpRequestBase(String url) { + HttpRequestBase request = new HttpGet(url); + return request; + } + + @Override + protected JsonObject parseFromJson(InputStreamReader in) throws GitlabException { + return new Gson().fromJson(in, JsonObject.class); + } + }.run(monitor); + return jsonArray; + } + + public JsonArray getUsers(String path, IOperationMonitor monitor) throws GitlabException { + getAccessTokenIfNotPresent(monitor); + JsonArray jsonArray = new GitlabJSonArrayOperation(client, "/users" + path) { + @Override + protected HttpRequestBase createHttpRequestBase(String url) { + HttpRequestBase request = new HttpGet(url); + return request; + } + + @Override + protected JsonArray parseFromJson(InputStreamReader in) throws GitlabException { + return new Gson().fromJson(in, JsonArray.class); + } + }.run(monitor); + return jsonArray; + } + + public JsonArray getNamespaces(IOperationMonitor monitor) throws GitlabException { + getAccessTokenIfNotPresent(monitor); + JsonArray jsonArray = new GitlabJSonArrayOperation(client, "/namespaces") { + @Override + protected HttpRequestBase createHttpRequestBase(String url) { + HttpRequestBase request = new HttpGet(url); + return request; + } + + @Override + protected JsonArray parseFromJson(InputStreamReader in) throws GitlabException { + return new Gson().fromJson(in, JsonArray.class); + } + }.run(monitor); + return jsonArray; + } + + public JsonObject getGroup(String path, IOperationMonitor monitor) throws GitlabException { + getAccessTokenIfNotPresent(monitor); + JsonObject jsonArray = new GitlabOperation(client, "/groups" + path) { + @Override + protected HttpRequestBase createHttpRequestBase(String url) { + HttpRequestBase request = new HttpGet(url); + return request; + } + + @Override + protected JsonObject parseFromJson(InputStreamReader in) throws GitlabException { + return new Gson().fromJson(in, JsonObject.class); + } + }.run(monitor); + return jsonArray; + } + + public JsonArray getSubGroups(String path, IOperationMonitor monitor) throws GitlabException { + getAccessTokenIfNotPresent(monitor); + JsonArray jsonArray = new GitlabJSonArrayOperation(client, "/groups" + path + "/subgroups?all_available=true") { + @Override + protected HttpRequestBase createHttpRequestBase(String url) { + HttpRequestBase request = new HttpGet(url); + return request; + } + + @Override + protected JsonArray parseFromJson(InputStreamReader in) throws GitlabException { + return new Gson().fromJson(in, JsonArray.class); + } + }.run(monitor); + return jsonArray; + } + + public JsonArray getDescendantGroups(String path, IOperationMonitor monitor) throws GitlabException { + getAccessTokenIfNotPresent(monitor); + JsonArray jsonArray = new GitlabJSonArrayOperation(client, + "/groups" + path + "/descendant_groups?all_available=true") { + @Override + protected HttpRequestBase createHttpRequestBase(String url) { + HttpRequestBase request = new HttpGet(url); + return request; + } + + @Override + protected JsonArray parseFromJson(InputStreamReader in) throws GitlabException { + return new Gson().fromJson(in, JsonArray.class); + } + }.run(monitor); + return jsonArray; + } + + public JsonObject getNamespace(String path, IOperationMonitor monitor) throws GitlabException { + getAccessTokenIfNotPresent(monitor); + JsonObject jsonObject = new GitlabOperation(client, "/namespaces" + path) { + @Override + protected HttpRequestBase createHttpRequestBase(String url) { + HttpRequestBase request = new HttpGet(url); + return request; + } + + @Override + protected JsonObject parseFromJson(InputStreamReader in) throws GitlabException { + return new Gson().fromJson(in, JsonObject.class); + } + }.run(monitor); + return jsonObject; + } + + public JsonArray getProjects(String path, IOperationMonitor monitor) throws GitlabException { + getAccessTokenIfNotPresent(monitor); + JsonArray jsonArray = new GitlabJSonArrayOperation(client, path + "/projects") { + @Override + protected HttpRequestBase createHttpRequestBase(String url) { + HttpRequestBase request = new HttpGet(url); + return request; + } + + @Override + protected JsonArray parseFromJson(InputStreamReader in) throws GitlabException { + return new Gson().fromJson(in, JsonArray.class); + } + }.run(monitor); + return jsonArray; + } + + public JsonObject getProject(String projectid, IOperationMonitor monitor) throws GitlabException { + getAccessTokenIfNotPresent(monitor); + JsonObject jsonArray = new GitlabOperation(client, "/projects/" + projectid) { + @Override + protected HttpRequestBase createHttpRequestBase(String url) { + HttpRequestBase request = new HttpGet(url); + return request; + } + + @Override + protected JsonObject parseFromJson(InputStreamReader in) throws GitlabException { + return new Gson().fromJson(in, JsonObject.class); + } + }.run(monitor); + return jsonArray; + } + + public JsonArray getGroupProjects(String projectid, IOperationMonitor monitor) throws GitlabException { + getAccessTokenIfNotPresent(monitor); + JsonArray jsonArray = new GitlabJSonArrayOperation(client, + "/groups/" + projectid + "/projects?include_subgroups=true") { + @Override + protected HttpRequestBase createHttpRequestBase(String url) { + HttpRequestBase request = new HttpGet(url); + return request; + } + + @Override + protected JsonArray parseFromJson(InputStreamReader in) throws GitlabException { + return new Gson().fromJson(in, JsonArray.class); + } + }.run(monitor); + return jsonArray; + } + + public JsonArray getIssues(String path, IOperationMonitor monitor) throws GitlabException { + getAccessTokenIfNotPresent(monitor); + JsonArray jsonArray = new GitlabJSonArrayOperation(client, path + "/issues") { + @Override + protected HttpRequestBase createHttpRequestBase(String url) { + HttpRequestBase request = new HttpGet(url); + return request; + } + + @Override + protected JsonArray parseFromJson(InputStreamReader in) throws GitlabException { + return new Gson().fromJson(in, JsonArray.class); + } + }.run(monitor); + return jsonArray; + } + + public JsonObject getIssue(String path, String id, IOperationMonitor monitor) throws GitlabException { + getAccessTokenIfNotPresent(monitor); + JsonObject jsonArray = new GitlabOperation(client, path + "/issues/" + id) { + @Override + protected HttpRequestBase createHttpRequestBase(String url) { + HttpRequestBase request = new HttpGet(url); + return request; + } + + @Override + protected JsonObject parseFromJson(InputStreamReader in) throws GitlabException { + return new Gson().fromJson(in, JsonObject.class); + } + }.run(monitor); + return jsonArray; + } + + public JsonArray getIssueNotes(String path, String id, IOperationMonitor monitor) throws GitlabException { + getAccessTokenIfNotPresent(monitor); + JsonArray jsonArray = new GitlabJSonArrayOperation(client, path + "/issues/" + id + "/notes?sort=asc") { + @Override + protected HttpRequestBase createHttpRequestBase(String url) { + HttpRequestBase request = new HttpGet(url); + return request; + } + + @Override + protected JsonArray parseFromJson(InputStreamReader in) throws GitlabException { + return new Gson().fromJson(in, JsonArray.class); + } + }.run(monitor); + return jsonArray; + } + + public JsonArray getIssueDiscussions(String path, String id, IOperationMonitor monitor) throws GitlabException { + getAccessTokenIfNotPresent(monitor); + JsonArray jsonArray = new GitlabJSonArrayOperation(client, path + "/issues/" + id + "/discussions") { + @Override + protected HttpRequestBase createHttpRequestBase(String url) { + HttpRequestBase request = new HttpGet(url); + return request; + } + + @Override + protected JsonArray parseFromJson(InputStreamReader in) throws GitlabException { + return new Gson().fromJson(in, JsonArray.class); + } + }.run(monitor); + return jsonArray; + } + + public JsonObject getIssueDiscussion(String path, String id, String discussion_id, IOperationMonitor monitor) + throws GitlabException { + getAccessTokenIfNotPresent(monitor); + JsonObject jsonArray = new GitlabOperation(client, + path + "/issues/" + id + "/discussions/" + discussion_id) { + @Override + protected HttpRequestBase createHttpRequestBase(String url) { + HttpRequestBase request = new HttpGet(url); + return request; + } + + @Override + protected JsonObject parseFromJson(InputStreamReader in) throws GitlabException { + return new Gson().fromJson(in, JsonObject.class); + } + }.run(monitor); + return jsonArray; + } + + public JsonElement createIssueNote(String path, String id, String body, IOperationMonitor monitor) + throws GitlabException { + getAccessTokenIfNotPresent(monitor); + JsonObject jsonElement; + jsonElement = new GitlabPostOperation(client, path + "/issues/" + id + "/notes") { + + @Override + protected void addHttpRequestEntities(HttpRequestBase request) throws GitlabException { + super.addHttpRequestEntities(request); + request.setHeader(CONTENT_TYPE, APPLICATION_JSON); + try { + ((HttpPost) request).setEntity(new StringEntity(body)); + } catch (UnsupportedEncodingException e) { + throw new GitlabException(e); } - } - - public JsonObject getUser(IOperationMonitor monitor) throws GitlabException { - getAccessTokenIfNotPresent(monitor); - JsonObject jsonArray = new GitlabOperation(client, "/user") { - @Override - protected HttpRequestBase createHttpRequestBase(String url) { - HttpRequestBase request = new HttpGet(url); - return request; - } - - @Override - protected JsonObject parseFromJson(InputStreamReader in) throws GitlabException { - return new Gson().fromJson(in, JsonObject.class); - } - }.run(monitor); - return jsonArray; - } - - public JsonArray getUsers(String path, IOperationMonitor monitor) throws GitlabException { - getAccessTokenIfNotPresent(monitor); - JsonArray jsonArray = new GitlabJSonArrayOperation(client, "/users" + path) { - @Override - protected HttpRequestBase createHttpRequestBase(String url) { - HttpRequestBase request = new HttpGet(url); - return request; - } - - @Override - protected JsonArray parseFromJson(InputStreamReader in) throws GitlabException { - return new Gson().fromJson(in, JsonArray.class); - } - }.run(monitor); - return jsonArray; - } - - public JsonArray getNamespaces(IOperationMonitor monitor) throws GitlabException { - getAccessTokenIfNotPresent(monitor); - JsonArray jsonArray = new GitlabJSonArrayOperation(client, "/namespaces") { - @Override - protected HttpRequestBase createHttpRequestBase(String url) { - HttpRequestBase request = new HttpGet(url); - return request; - } - - @Override - protected JsonArray parseFromJson(InputStreamReader in) throws GitlabException { - return new Gson().fromJson(in, JsonArray.class); - } - }.run(monitor); - return jsonArray; - } - - public JsonObject getGroup(String path, IOperationMonitor monitor) throws GitlabException { - getAccessTokenIfNotPresent(monitor); - JsonObject jsonArray = new GitlabOperation(client, "/groups" + path) { - @Override - protected HttpRequestBase createHttpRequestBase(String url) { - HttpRequestBase request = new HttpGet(url); - return request; - } - - @Override - protected JsonObject parseFromJson(InputStreamReader in) throws GitlabException { - return new Gson().fromJson(in, JsonObject.class); - } - }.run(monitor); - return jsonArray; - } - - public JsonArray getSubGroups(String path, IOperationMonitor monitor) throws GitlabException { - getAccessTokenIfNotPresent(monitor); - JsonArray jsonArray = new GitlabJSonArrayOperation(client, "/groups" + path + "/subgroups?all_available=true") { - @Override - protected HttpRequestBase createHttpRequestBase(String url) { - HttpRequestBase request = new HttpGet(url); - return request; - } - - @Override - protected JsonArray parseFromJson(InputStreamReader in) throws GitlabException { - return new Gson().fromJson(in, JsonArray.class); - } - }.run(monitor); - return jsonArray; - } - - public JsonArray getDescendantGroups(String path, IOperationMonitor monitor) throws GitlabException { - getAccessTokenIfNotPresent(monitor); - JsonArray jsonArray = new GitlabJSonArrayOperation(client, - "/groups" + path + "/descendant_groups?all_available=true") { - @Override - protected HttpRequestBase createHttpRequestBase(String url) { - HttpRequestBase request = new HttpGet(url); - return request; - } - - @Override - protected JsonArray parseFromJson(InputStreamReader in) throws GitlabException { - return new Gson().fromJson(in, JsonArray.class); - } - }.run(monitor); - return jsonArray; - } - - public JsonObject getNamespace(String path, IOperationMonitor monitor) throws GitlabException { - getAccessTokenIfNotPresent(monitor); - JsonObject jsonObject = new GitlabOperation(client, "/namespaces" + path) { - @Override - protected HttpRequestBase createHttpRequestBase(String url) { - HttpRequestBase request = new HttpGet(url); - return request; - } - - @Override - protected JsonObject parseFromJson(InputStreamReader in) throws GitlabException { - return new Gson().fromJson(in, JsonObject.class); - } - }.run(monitor); - return jsonObject; - } - - public JsonArray getProjects(String path, IOperationMonitor monitor) throws GitlabException { - getAccessTokenIfNotPresent(monitor); - JsonArray jsonArray = new GitlabJSonArrayOperation(client, path + "/projects") { - @Override - protected HttpRequestBase createHttpRequestBase(String url) { - HttpRequestBase request = new HttpGet(url); - return request; - } - - @Override - protected JsonArray parseFromJson(InputStreamReader in) throws GitlabException { - return new Gson().fromJson(in, JsonArray.class); - } - }.run(monitor); - return jsonArray; - } - - public JsonObject getProject(String projectid, IOperationMonitor monitor) throws GitlabException { - getAccessTokenIfNotPresent(monitor); - JsonObject jsonArray = new GitlabOperation(client, "/projects/" + projectid) { - @Override - protected HttpRequestBase createHttpRequestBase(String url) { - HttpRequestBase request = new HttpGet(url); - return request; - } - - @Override - protected JsonObject parseFromJson(InputStreamReader in) throws GitlabException { - return new Gson().fromJson(in, JsonObject.class); - } - }.run(monitor); - return jsonArray; - } - - public JsonArray getGroupProjects(String projectid, IOperationMonitor monitor) throws GitlabException { - getAccessTokenIfNotPresent(monitor); - JsonArray jsonArray = new GitlabJSonArrayOperation(client, - "/groups/" + projectid + "/projects?include_subgroups=true") { - @Override - protected HttpRequestBase createHttpRequestBase(String url) { - HttpRequestBase request = new HttpGet(url); - return request; - } - - @Override - protected JsonArray parseFromJson(InputStreamReader in) throws GitlabException { - return new Gson().fromJson(in, JsonArray.class); - } - }.run(monitor); - return jsonArray; - } - - public JsonArray getIssues(String path, IOperationMonitor monitor) throws GitlabException { - getAccessTokenIfNotPresent(monitor); - JsonArray jsonArray = new GitlabJSonArrayOperation(client, path + "/issues") { - @Override - protected HttpRequestBase createHttpRequestBase(String url) { - HttpRequestBase request = new HttpGet(url); - return request; - } - - @Override - protected JsonArray parseFromJson(InputStreamReader in) throws GitlabException { - return new Gson().fromJson(in, JsonArray.class); - } - }.run(monitor); - return jsonArray; - } - - public JsonObject getIssue(String path, String id, IOperationMonitor monitor) throws GitlabException { - getAccessTokenIfNotPresent(monitor); - JsonObject jsonArray = new GitlabOperation(client, path + "/issues/" + id) { - @Override - protected HttpRequestBase createHttpRequestBase(String url) { - HttpRequestBase request = new HttpGet(url); - return request; - } - - @Override - protected JsonObject parseFromJson(InputStreamReader in) throws GitlabException { - return new Gson().fromJson(in, JsonObject.class); - } - }.run(monitor); - return jsonArray; - } - - public JsonArray getIssueNotes(String path, String id, IOperationMonitor monitor) throws GitlabException { - getAccessTokenIfNotPresent(monitor); - JsonArray jsonArray = new GitlabJSonArrayOperation(client, path + "/issues/" + id + "/notes?sort=asc") { - @Override - protected HttpRequestBase createHttpRequestBase(String url) { - HttpRequestBase request = new HttpGet(url); - return request; - } - - @Override - protected JsonArray parseFromJson(InputStreamReader in) throws GitlabException { - return new Gson().fromJson(in, JsonArray.class); - } - }.run(monitor); - return jsonArray; - } - - public JsonArray getIssueDiscussions(String path, String id, IOperationMonitor monitor) throws GitlabException { - getAccessTokenIfNotPresent(monitor); - JsonArray jsonArray = new GitlabJSonArrayOperation(client, path + "/issues/" + id + "/discussions") { - @Override - protected HttpRequestBase createHttpRequestBase(String url) { - HttpRequestBase request = new HttpGet(url); - return request; - } - - @Override - protected JsonArray parseFromJson(InputStreamReader in) throws GitlabException { - return new Gson().fromJson(in, JsonArray.class); - } - }.run(monitor); - return jsonArray; - } - - public JsonElement createIssueNote(String path, String id, String body, IOperationMonitor monitor) - throws GitlabException { - getAccessTokenIfNotPresent(monitor); - JsonObject jsonElement; - jsonElement = new GitlabPostOperation(client, path + "/issues/" + id + "/notes") { - - @Override - protected void addHttpRequestEntities(HttpRequestBase request) throws GitlabException { - super.addHttpRequestEntities(request); - request.setHeader(CONTENT_TYPE, APPLICATION_JSON); - try { - ((HttpPost) request).setEntity(new StringEntity(body)); - } catch (UnsupportedEncodingException e) { - throw new GitlabException(e); - } - }; - - @Override - protected void doValidate(CommonHttpResponse response, IOperationMonitor monitor) - throws IOException, GitlabException { - validate(response, HttpStatus.SC_CREATED, monitor); - } - - @Override - protected JsonObject parseFromJson(InputStreamReader in) throws GitlabException { - return new Gson().fromJson(in, JsonObject.class); - } - }.run(monitor); - return jsonElement; - } - - public JsonElement updateIssue(String path, String id, String body, IOperationMonitor monitor) - throws GitlabException { - getAccessTokenIfNotPresent(monitor); - JsonObject jsonElement; - jsonElement = new GitlabPutOperation(client, path + "/issues/" + id, body) { - @Override - - protected void doValidate(CommonHttpResponse response, IOperationMonitor monitor) - throws IOException, GitlabException { - validate(response, HttpStatus.SC_OK, monitor); - } - - @Override - protected JsonObject parseFromJson(InputStreamReader in) throws GitlabException { - StringBuilder result = new StringBuilder(); + }; + + @Override + protected void doValidate(CommonHttpResponse response, IOperationMonitor monitor) + throws IOException, GitlabException { + validate(response, HttpStatus.SC_CREATED, monitor); + } + + @Override + protected JsonObject parseFromJson(InputStreamReader in) throws GitlabException { + return new Gson().fromJson(in, JsonObject.class); + } + }.run(monitor); + return jsonElement; + } + + public JsonElement updateIssue(String path, String id, String body, IOperationMonitor monitor) + throws GitlabException { + getAccessTokenIfNotPresent(monitor); + JsonObject jsonElement; + jsonElement = new GitlabPutOperation(client, path + "/issues/" + id, body) { + @Override + + protected void doValidate(CommonHttpResponse response, IOperationMonitor monitor) + throws IOException, GitlabException { + validate(response, HttpStatus.SC_OK, monitor); + } + + @Override + protected JsonObject parseFromJson(InputStreamReader in) throws GitlabException { + StringBuilder result = new StringBuilder(); // String rr = ""; // try { // // Read each byte and convert into a char, adding to the StringBuilder @@ -754,184 +796,194 @@ protected JsonObject parseFromJson(InputStreamReader in) throws GitlabException // // TODO: handle exception // } // return null; - return new Gson().fromJson(in, JsonObject.class); - } - }.run(monitor); - return jsonElement; - } - - public GitlabConfiguration getConfiguration(TaskRepository repository, IOperationMonitor monitor) { - GitlabConfiguration config = new GitlabConfiguration(repository.getUrl()); - try { - JsonObject user = getUser(monitor); - config.setUserID(user.get("id").getAsBigInteger()); - config.setUserDetails(user); - JsonElement projects = getProjects("/users/" + config.getUserID(), monitor); - for (JsonElement project : (JsonArray) projects) { - config.addProject(project); - } - String groupsValue = repository.getProperty(GitlabCoreActivator.GROUPS); - String[] groupList = groupsValue.split(","); - for (String group : groupList) { - JsonObject groupDetail = getGroup("/" + group, monitor); - config.addGroup(groupDetail); - projects = getGroupProjects(group, monitor); - for (JsonElement project : (JsonArray) projects) { - config.addProject(project); - } - } - } catch (GitlabException e) { - // TODO Auto-generated catch block - e.printStackTrace(); + return new Gson().fromJson(in, JsonObject.class); + } + }.run(monitor); + return jsonElement; + } + + public GitlabConfiguration getConfiguration(TaskRepository repository, IOperationMonitor monitor) { + GitlabConfiguration config = new GitlabConfiguration(repository.getUrl()); + try { + JsonObject user = getUser(monitor); + config.setUserID(user.get("id").getAsBigInteger()); + config.setUserDetails(user); + JsonElement projects = getProjects("/users/" + config.getUserID(), monitor); + for (JsonElement project : (JsonArray) projects) { + config.addProject(project); + } + String groupsValue = repository.getProperty(GitlabCoreActivator.GROUPS); + String[] groupList = groupsValue.split(","); + for (String group : groupList) { + JsonObject groupDetail = getGroup("/" + group, monitor); + config.addGroup(groupDetail); + projects = getGroupProjects(group, monitor); + for (JsonElement project : (JsonArray) projects) { + config.addProject(project); } - return config; - } - - ImmutableMap updatable = new ImmutableMap.Builder() - .put(GitlabTaskSchema.getDefault().SUMMARY.getKey(), "title") - .put(GitlabTaskSchema.getDefault().DESCRIPTION.getKey(), "description") - .put(GitlabTaskSchema.getDefault().DISCUSSION_LOCKED.getKey(), - GitlabTaskSchema.getDefault().DISCUSSION_LOCKED.getKey()) - .put(GitlabTaskSchema.getDefault().CONFIDENTIAL.getKey(), - GitlabTaskSchema.getDefault().CONFIDENTIAL.getKey()) - .put(GitlabTaskSchema.getDefault().ISSUE_TYPE.getKey(), GitlabTaskSchema.getDefault().ISSUE_TYPE.getKey()) - .put(GitlabTaskSchema.getDefault().OPERATION.getKey(), "state_event") - .put(GitlabTaskSchema.getDefault().DUE_DATE.getKey(), GitlabTaskSchema.getDefault().DUE_DATE.getKey()) - .build(); - - private static SimpleDateFormat dmyFormat = new SimpleDateFormat("yyyy-MM-dd"); - - public RepositoryResponse postTaskData(TaskData taskData, Set oldAttributes, - IOperationMonitor monitor) throws GitlabException { - if (taskData.isNew()) { - JsonElement result = createNewIssue(taskData, monitor); - JsonObject resObj = (JsonObject) result; - String newID = resObj.get("iid").getAsString(); - String projectID = resObj.get("project_id").getAsString(); - return new RepositoryResponse(ResponseKind.TASK_CREATED, "/projects/" + projectID + "/issues/" + newID); - } else { - return updateExistingIssue(taskData, oldAttributes, monitor); + } + } catch (GitlabException e) { + // TODO Auto-generated catch block + e.printStackTrace(); + } + return config; + } + + ImmutableMap updatable = new ImmutableMap.Builder() + .put(GitlabTaskSchema.getDefault().SUMMARY.getKey(), "title") + .put(GitlabTaskSchema.getDefault().DESCRIPTION.getKey(), "description") + .put(GitlabTaskSchema.getDefault().DISCUSSION_LOCKED.getKey(), + GitlabTaskSchema.getDefault().DISCUSSION_LOCKED.getKey()) + .put(GitlabTaskSchema.getDefault().CONFIDENTIAL.getKey(), + GitlabTaskSchema.getDefault().CONFIDENTIAL.getKey()) + .put(GitlabTaskSchema.getDefault().ISSUE_TYPE.getKey(), GitlabTaskSchema.getDefault().ISSUE_TYPE.getKey()) + .put(GitlabTaskSchema.getDefault().OPERATION.getKey(), "state_event") + .put(GitlabTaskSchema.getDefault().DUE_DATE.getKey(), GitlabTaskSchema.getDefault().DUE_DATE.getKey()) + .build(); + + private static SimpleDateFormat dmyFormat = new SimpleDateFormat("yyyy-MM-dd"); + + public RepositoryResponse postTaskData(TaskData taskData, Set oldAttributes, + IOperationMonitor monitor) throws GitlabException { + if (taskData.isNew()) { + JsonElement result = createNewIssue(taskData, monitor); + JsonObject resObj = (JsonObject) result; + String newID = resObj.get("iid").getAsString(); + String projectID = resObj.get("project_id").getAsString(); + return new RepositoryResponse(ResponseKind.TASK_CREATED, "/projects/" + projectID + "/issues/" + newID); + } else { + return updateExistingIssue(taskData, oldAttributes, monitor); + } + } + + private RepositoryResponse updateExistingIssue(TaskData taskData, Set oldAttributes, + IOperationMonitor monitor) throws GitlabException { + ArrayList changedAtributes = new ArrayList<>(); + String newComentValue = ""; + String discussionsId = ""; + for (TaskAttribute taskAttribute : oldAttributes) { + String attributeID = taskAttribute.getId(); + if (updatable.containsKey(attributeID)) { + TaskAttribute newAttrib = taskData.getRoot().getAttribute(attributeID); + String newValue = newAttrib.getValue(); + if (attributeID.equals("due_date")) { + if (newValue.length() > 0) { + newValue = dmyFormat.format(new Date(Long.parseLong(newValue))); + } } - } - - private RepositoryResponse updateExistingIssue(TaskData taskData, Set oldAttributes, - IOperationMonitor monitor) throws GitlabException { - ArrayList changedAtributes = new ArrayList<>(); - String newComentValue = ""; - for (TaskAttribute taskAttribute : oldAttributes) { - String attributeID = taskAttribute.getId(); - if (updatable.containsKey(attributeID)) { - TaskAttribute newAttrib = taskData.getRoot().getAttribute(attributeID); - String newValue = newAttrib.getValue(); - if (attributeID.equals("due_date")) { - if (newValue.length() > 0) { - newValue = dmyFormat.format(new Date(Long.parseLong(newValue))); - } - } -// changedAtributes.add("\"" + updatable.get(attributeID) + "\":\"" + newValue + "\""); - changedAtributes.add(NLS.bind("\"{0}\":\"{1}\"", updatable.get(attributeID), newValue)); - } - - if (GitlabTaskSchema.getDefault().NEW_COMMENT.getKey().equals(taskAttribute.getId())) { - TaskAttribute newAttrib = taskData.getRoot().getAttribute(attributeID); - newComentValue = "{\"body\":\"" + newAttrib.getValue() + "\"}"; - } - } - - TaskAttribute productAttribute = taskData.getRoot() - .getAttribute(GitlabTaskSchema.getDefault().PRODUCT.getKey()); - if (productAttribute != null && !productAttribute.getValue().isEmpty()) { - TaskAttribute iidAttribute = taskData.getRoot().getAttribute(GitlabTaskSchema.getDefault().IID.getKey()); - if (!changedAtributes.isEmpty()) { - updateIssue("/projects/" + productAttribute.getValue(), iidAttribute.getValue(), - "{" + String.join(",", changedAtributes) + "}", monitor); - } - if (!newComentValue.isEmpty()) { - createIssueNote("/projects/" + productAttribute.getValue(), iidAttribute.getValue(), newComentValue, - monitor); - } - } - return new RepositoryResponse(ResponseKind.TASK_UPDATED, taskData.getTaskId()); - } - - public JsonElement createNewIssue(TaskData taskData, IOperationMonitor monitor) throws GitlabException { - getAccessTokenIfNotPresent(monitor); - TaskAttribute productAttribute = taskData.getRoot() - .getAttribute(GitlabTaskSchema.getDefault().PRODUCT.getKey()); - if (productAttribute == null || productAttribute.getValue().isEmpty()) { - throw new GitlabException("productAttribute should not be null"); + changedAtributes.add(NLS.bind("\"{0}\":\"{1}\"", updatable.get(attributeID), newValue)); + } + + if (GitlabTaskSchema.getDefault().NEW_COMMENT.getKey().equals(taskAttribute.getId())) { + TaskAttribute newAttrib = taskData.getRoot().getAttribute(attributeID); + TaskAttribute noteableIdAttrib = newAttrib.getAttribute("noteable_id"); + TaskAttribute iidAttribute = taskData.getRoot() + .getAttribute(GitlabTaskSchema.getDefault().IID.getKey()); + discussionsId = iidAttribute.getValue(); + if (noteableIdAttrib != null) { + newComentValue = "{\"note_id\":" + noteableIdAttrib.getValue() + ",\"body\":\"" + + newAttrib.getValue().replaceAll("\n", "\\\\n").replaceAll("\"", "\\\\\"") + "\"}"; + TaskAttribute xx1 = newAttrib.getAttribute("discussions"); + discussionsId += ("/discussions/" + xx1.getValue()); + } else { + newComentValue = "{\"body\":\"" + newAttrib.getValue().replaceAll("\n", "\\\n") + "\"}"; } - JsonObject jsonElement; - jsonElement = new GitlabPostOperation(client, - "/projects/" + productAttribute.getValue() + "/issues") { - - protected void addHttpRequestEntities(HttpRequestBase request) throws GitlabException { - super.addHttpRequestEntities(request); - request.setHeader(CONTENT_TYPE, APPLICATION_JSON); - Gson gson = new GsonBuilder().registerTypeAdapter(TaskData.class, new TaskAttributeTypeAdapter()) - .create(); - String jsondata = gson.toJson(taskData); - try { - ((HttpPost) request).setEntity(new StringEntity(jsondata)); - } catch (UnsupportedEncodingException e) { - throw new GitlabException(e); - } - }; - - @Override - protected void doValidate(CommonHttpResponse response, IOperationMonitor monitor) - throws IOException, GitlabException { - validate(response, HttpStatus.SC_CREATED, monitor); - } - - @Override - protected JsonObject parseFromJson(InputStreamReader in) throws GitlabException { - return new Gson().fromJson(in, JsonObject.class); - } - }.run(monitor); - return jsonElement; - } - - class TaskAttributeTypeAdapter extends TypeAdapter { - - @Override - public void write(JsonWriter out, TaskData taskData) throws IOException { - out.beginObject(); - for (TaskAttribute taskAttribute : taskData.getRoot().getAttributes().values()) { - String id = taskAttribute.getId(); - String attributValue = convertString2GSonString(taskAttribute.getValue()); - id = GitlabNewTaskSchema.getJsonNameFromAttributeName(id); - if ("project_id".equals(id) || "state".equals(id)) { - continue; - } - out.name(id).value(attributValue); - } - out.endObject(); + } + } + + TaskAttribute productAttribute = taskData.getRoot() + .getAttribute(GitlabTaskSchema.getDefault().PRODUCT.getKey()); + if (productAttribute != null && !productAttribute.getValue().isEmpty()) { + TaskAttribute iidAttribute = taskData.getRoot().getAttribute(GitlabTaskSchema.getDefault().IID.getKey()); + if (!changedAtributes.isEmpty()) { + updateIssue("/projects/" + productAttribute.getValue(), iidAttribute.getValue(), + "{" + String.join(",", changedAtributes) + "}", monitor); + } + if (!newComentValue.isEmpty()) { + createIssueNote("/projects/" + productAttribute.getValue(), discussionsId, newComentValue, monitor); + } + } + return new RepositoryResponse(ResponseKind.TASK_UPDATED, taskData.getTaskId()); + } + + public JsonElement createNewIssue(TaskData taskData, IOperationMonitor monitor) throws GitlabException { + getAccessTokenIfNotPresent(monitor); + TaskAttribute productAttribute = taskData.getRoot() + .getAttribute(GitlabTaskSchema.getDefault().PRODUCT.getKey()); + if (productAttribute == null || productAttribute.getValue().isEmpty()) { + throw new GitlabException("productAttribute should not be null"); + } + JsonObject jsonElement; + jsonElement = new GitlabPostOperation(client, + "/projects/" + productAttribute.getValue() + "/issues") { + + protected void addHttpRequestEntities(HttpRequestBase request) throws GitlabException { + super.addHttpRequestEntities(request); + request.setHeader(CONTENT_TYPE, APPLICATION_JSON); + Gson gson = new GsonBuilder().registerTypeAdapter(TaskData.class, new TaskAttributeTypeAdapter()) + .create(); + String jsondata = gson.toJson(taskData); + try { + ((HttpPost) request).setEntity(new StringEntity(jsondata)); + } catch (UnsupportedEncodingException e) { + throw new GitlabException(e); } - - @Override - public TaskData read(JsonReader in) throws IOException { - throw new UnsupportedOperationException("TaskAttributeTypeAdapter in GitlabRestClient only supports write"); //$NON-NLS-1$ + }; + + @Override + protected void doValidate(CommonHttpResponse response, IOperationMonitor monitor) + throws IOException, GitlabException { + validate(response, HttpStatus.SC_CREATED, monitor); + } + + @Override + protected JsonObject parseFromJson(InputStreamReader in) throws GitlabException { + return new Gson().fromJson(in, JsonObject.class); + } + }.run(monitor); + return jsonElement; + } + + class TaskAttributeTypeAdapter extends TypeAdapter { + + @Override + public void write(JsonWriter out, TaskData taskData) throws IOException { + out.beginObject(); + for (TaskAttribute taskAttribute : taskData.getRoot().getAttributes().values()) { + String id = taskAttribute.getId(); + String attributValue = convertString2GSonString(taskAttribute.getValue()); + id = GitlabNewTaskSchema.getJsonNameFromAttributeName(id); + if ("project_id".equals(id) || "state".equals(id)) { + continue; } - } - - public static String convertString2GSonString(String str) { - str = str.replace("\"", "\\\"").replace("\n", "\\\n"); //$NON-NLS-1$//$NON-NLS-2$ //$NON-NLS-3$//$NON-NLS-4$ - StringBuffer ostr = new StringBuffer(); - for (int i = 0; i < str.length(); i++) { - char ch = str.charAt(i); - if ((ch >= 0x0020) && (ch <= 0x007e)) { - ostr.append(ch); - } else { - ostr.append("\\u"); //$NON-NLS-1$ - String hex = Integer.toHexString(str.charAt(i) & 0xFFFF); - for (int j = 0; j < 4 - hex.length(); j++) { - ostr.append("0"); //$NON-NLS-1$ - } - ostr.append(hex.toLowerCase()); - } + out.name(id).value(attributValue); + } + out.endObject(); + } + + @Override + public TaskData read(JsonReader in) throws IOException { + throw new UnsupportedOperationException("TaskAttributeTypeAdapter in GitlabRestClient only supports write"); //$NON-NLS-1$ + } + } + + public static String convertString2GSonString(String str) { + str = str.replace("\"", "\\\"").replace("\n", "\\\n"); //$NON-NLS-1$//$NON-NLS-2$ //$NON-NLS-3$//$NON-NLS-4$ + StringBuffer ostr = new StringBuffer(); + for (int i = 0; i < str.length(); i++) { + char ch = str.charAt(i); + if ((ch >= 0x0020) && (ch <= 0x007e)) { + ostr.append(ch); + } else { + ostr.append("\\u"); //$NON-NLS-1$ + String hex = Integer.toHexString(str.charAt(i) & 0xFFFF); + for (int j = 0; j < 4 - hex.length(); j++) { + ostr.append("0"); //$NON-NLS-1$ } - return (new String(ostr)); + ostr.append(hex.toLowerCase()); + } } + return (new String(ostr)); + } } diff --git a/mylyn.tasks/connectors/gitlab/org.eclipse.mylyn.gitlab.core/src/org/eclipse/mylyn/gitlab/core/GitlabTaskAttributeMapper.java b/mylyn.tasks/connectors/gitlab/org.eclipse.mylyn.gitlab.core/src/org/eclipse/mylyn/gitlab/core/GitlabTaskAttributeMapper.java index d26f897b13..3ae1b503da 100644 --- a/mylyn.tasks/connectors/gitlab/org.eclipse.mylyn.gitlab.core/src/org/eclipse/mylyn/gitlab/core/GitlabTaskAttributeMapper.java +++ b/mylyn.tasks/connectors/gitlab/org.eclipse.mylyn.gitlab.core/src/org/eclipse/mylyn/gitlab/core/GitlabTaskAttributeMapper.java @@ -16,65 +16,81 @@ import java.text.ParseException; import java.text.SimpleDateFormat; import java.util.Date; +import java.util.Map; +import java.util.Map.Entry; +import org.eclipse.jdt.annotation.NonNull; +import org.eclipse.mylyn.tasks.core.IRepositoryPerson; import org.eclipse.mylyn.tasks.core.TaskRepository; import org.eclipse.mylyn.tasks.core.data.TaskAttribute; import org.eclipse.mylyn.tasks.core.data.TaskAttributeMapper; public class GitlabTaskAttributeMapper extends TaskAttributeMapper { - private final GitlabRepositoryConnector connector; + private final GitlabRepositoryConnector connector; - private static final String dateFormat_1 = "yyyy-MM-dd HH:mm:ss.sss"; //$NON-NLS-1$ + private static final String dateFormat_1 = "yyyy-MM-dd HH:mm:ss.sss"; //$NON-NLS-1$ - private static final String dateFormat_2 = "yyyy-MM-dd HH:mm:ss"; //$NON-NLS-1$ + private static final String dateFormat_2 = "yyyy-MM-dd HH:mm:ss"; //$NON-NLS-1$ - private static final String dateFormat_3 = "yyyy-MM-dd HH:mm"; //$NON-NLS-1$ + private static final String dateFormat_3 = "yyyy-MM-dd HH:mm"; //$NON-NLS-1$ - private static final String dateFormat_4 = "yyyy-MM-dd"; //$NON-NLS-1$ + private static final String dateFormat_4 = "yyyy-MM-dd"; //$NON-NLS-1$ - private static final String dateFormat_1_TimeZone = "yyyy-MM-dd'T'HH:mm:ss.SSS'Z'"; //$NON-NLS-1$ + private static final String dateFormat_1_TimeZone = "yyyy-MM-dd'T'HH:mm:ss.SSS'Z'"; //$NON-NLS-1$ - private static final String dateFormat_2_TimeZone = "yyyy-MM-dd'T'HH:mm:ss'Z'"; //$NON-NLS-1$ + private static final String dateFormat_2_TimeZone = "yyyy-MM-dd'T'HH:mm:ss'Z'"; //$NON-NLS-1$ - private static final String dateFormat_3_TimeZone = "yyyy-MM-dd'T'HH:mm'Z'"; //$NON-NLS-1$ + private static final String dateFormat_3_TimeZone = "yyyy-MM-dd'T'HH:mm'Z'"; //$NON-NLS-1$ - private static final String dateFormat_4_TimeZone = "yyyy-MM-dd'Z'"; //$NON-NLS-1$ + private static final String dateFormat_4_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, dateFormat_4_TimeZone, dateFormat_4 }; + // Order is significant + private static final String[] dateFormats = { dateFormat_1_TimeZone, dateFormat_1, dateFormat_2_TimeZone, + dateFormat_2, dateFormat_3_TimeZone, dateFormat_3, dateFormat_4_TimeZone, dateFormat_4 }; - public GitlabTaskAttributeMapper(TaskRepository taskRepository, GitlabRepositoryConnector connector) { - super(taskRepository); - this.connector = connector; - } + public GitlabTaskAttributeMapper(TaskRepository taskRepository, GitlabRepositoryConnector 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 Date getDateValue(TaskAttribute attribute) { + if (attribute == null) { + return null; } - - /** - * 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; + Date parsedDate = parseDate(attribute.getValue()); + if (parsedDate != null) { + return parsedDate; } - + return super.getDateValue(attribute); + } + + /** + * 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 setRepositoryPerson(@NonNull TaskAttribute taskAttribute, @NonNull IRepositoryPerson person) { + super.setRepositoryPerson(taskAttribute, person); + if (person.getAttributes().size()>0) { + for ( Entry entry : person.getAttributes().entrySet()) { + TaskAttribute taskAttrib = taskAttribute.getAttribute(entry.getKey()); + if (taskAttrib==null) + taskAttrib = taskAttribute.createAttribute(entry.getKey()); + taskAttrib.setValue(entry.getValue()); + } + } + } } diff --git a/mylyn.tasks/connectors/gitlab/org.eclipse.mylyn.gitlab.feature/feature.xml b/mylyn.tasks/connectors/gitlab/org.eclipse.mylyn.gitlab.feature/feature.xml index 8a2673e54d..2979fcb16a 100644 --- a/mylyn.tasks/connectors/gitlab/org.eclipse.mylyn.gitlab.feature/feature.xml +++ b/mylyn.tasks/connectors/gitlab/org.eclipse.mylyn.gitlab.feature/feature.xml @@ -1,7 +1,7 @@ diff --git a/mylyn.tasks/connectors/gitlab/org.eclipse.mylyn.gitlab.ui/META-INF/MANIFEST.MF b/mylyn.tasks/connectors/gitlab/org.eclipse.mylyn.gitlab.ui/META-INF/MANIFEST.MF index 879dfbec81..b098064b1b 100644 --- a/mylyn.tasks/connectors/gitlab/org.eclipse.mylyn.gitlab.ui/META-INF/MANIFEST.MF +++ b/mylyn.tasks/connectors/gitlab/org.eclipse.mylyn.gitlab.ui/META-INF/MANIFEST.MF @@ -15,6 +15,7 @@ Require-Bundle: org.eclipse.ui, org.eclipse.mylyn.commons.workbench;bundle-version="4.0.0", org.eclipse.mylyn.commons.ui;bundle-version="4.0.0", org.eclipse.mylyn.commons.core;bundle-version="4.0.0", + org.eclipse.mylyn.commons.identity.core;bundle-version="4.0.0", org.eclipse.jdt.annotation Bundle-RequiredExecutionEnvironment: JavaSE-17 Automatic-Module-Name: org.eclipse.mylyn.gitlab.ui diff --git a/mylyn.tasks/connectors/gitlab/org.eclipse.mylyn.gitlab.ui/src/org/eclipse/mylyn/gitlab/ui/GitlabConnectorUI.java b/mylyn.tasks/connectors/gitlab/org.eclipse.mylyn.gitlab.ui/src/org/eclipse/mylyn/gitlab/ui/GitlabConnectorUI.java index 6a0db7cd64..32ab512098 100644 --- a/mylyn.tasks/connectors/gitlab/org.eclipse.mylyn.gitlab.ui/src/org/eclipse/mylyn/gitlab/ui/GitlabConnectorUI.java +++ b/mylyn.tasks/connectors/gitlab/org.eclipse.mylyn.gitlab.ui/src/org/eclipse/mylyn/gitlab/ui/GitlabConnectorUI.java @@ -13,16 +13,24 @@ package org.eclipse.mylyn.gitlab.ui; +import java.text.MessageFormat; + import org.eclipse.core.runtime.CoreException; +import org.eclipse.jdt.annotation.NonNull; +import org.eclipse.jdt.annotation.Nullable; import org.eclipse.jface.wizard.IWizard; import org.eclipse.mylyn.gitlab.core.GitlabConfiguration; import org.eclipse.mylyn.gitlab.core.GitlabCoreActivator; import org.eclipse.mylyn.gitlab.core.GitlabRepositoryConnector; import org.eclipse.mylyn.gitlab.core.GitlabTaskAttributeMapper; import org.eclipse.mylyn.internal.provisional.tasks.ui.wizards.QueryPageDetails; +import org.eclipse.mylyn.internal.tasks.ui.Messages; import org.eclipse.mylyn.tasks.core.IRepositoryQuery; +import org.eclipse.mylyn.tasks.core.ITask; +import org.eclipse.mylyn.tasks.core.ITaskComment; import org.eclipse.mylyn.tasks.core.ITaskMapping; import org.eclipse.mylyn.tasks.core.TaskRepository; +import org.eclipse.mylyn.tasks.core.data.TaskAttribute; import org.eclipse.mylyn.tasks.core.data.TaskData; import org.eclipse.mylyn.tasks.ui.AbstractRepositoryConnectorUi; import org.eclipse.mylyn.tasks.ui.wizards.ITaskRepositoryPage; @@ -31,51 +39,57 @@ public class GitlabConnectorUI extends AbstractRepositoryConnectorUi { - @Override - public String getConnectorKind() { - return GitlabCoreActivator.CONNECTOR_KIND; - } - - @Override - public ITaskRepositoryPage getSettingsPage(TaskRepository repository) { - return new GitlabRepositorySettingsPage("New repository", "Enter the HTTPS-URL to your GitLab repository", - repository); - } + @Override + public String getConnectorKind() { + return GitlabCoreActivator.CONNECTOR_KIND; + } - @Override - public IWizard getQueryWizard(TaskRepository repository, IRepositoryQuery query) { - RepositoryQueryWizard wizard = new RepositoryQueryWizard(repository); - GitlabRepositoryConnector connector = (GitlabRepositoryConnector) getConnector(); - TaskData taskData = new TaskData( - new GitlabTaskAttributeMapper(repository, connector), - repository.getConnectorKind(), "Query", "Query"); //$NON-NLS-1$ //$NON-NLS-2$ - GitlabSearchQueryPageSchema.getInstance().initialize(taskData); - try { - GitlabConfiguration config = connector.getRepositoryConfiguration(repository); - config.updateQueryOptions(taskData); - } catch (CoreException e) { - // TODO Auto-generated catch block - e.printStackTrace(); - } - GitlabQuerySchemaPage mp = new GitlabQuerySchemaPage(getConnectorKind(), repository, query, - GitlabSearchQueryPageSchema.getInstance(), taskData, - new QueryPageDetails(true, "", "EnterQueryParameter", //$NON-NLS-1$ - "EnterTitleAndURL", "([a-zA-Z][a-zA-Z+.-]{0,10}://[a-zA-Z0-9%._~!$&?#'()*+,;:@/=-]+)", - null)); - wizard.addPage(mp); + @Override + public ITaskRepositoryPage getSettingsPage(TaskRepository repository) { + return new GitlabRepositorySettingsPage("New repository", "Enter the HTTPS-URL to your GitLab repository", + repository); + } - return wizard; + @Override + public IWizard getQueryWizard(TaskRepository repository, IRepositoryQuery query) { + RepositoryQueryWizard wizard = new RepositoryQueryWizard(repository); + GitlabRepositoryConnector connector = (GitlabRepositoryConnector) getConnector(); + TaskData taskData = new TaskData(new GitlabTaskAttributeMapper(repository, connector), + repository.getConnectorKind(), "Query", "Query"); //$NON-NLS-1$ //$NON-NLS-2$ + GitlabSearchQueryPageSchema.getInstance().initialize(taskData); + try { + GitlabConfiguration config = connector.getRepositoryConfiguration(repository); + config.updateQueryOptions(taskData); + } catch (CoreException e) { + // TODO Auto-generated catch block + e.printStackTrace(); } + GitlabQuerySchemaPage mp = new GitlabQuerySchemaPage(getConnectorKind(), repository, query, + GitlabSearchQueryPageSchema.getInstance(), taskData, + new QueryPageDetails(true, "", "EnterQueryParameter", //$NON-NLS-1$ + "EnterTitleAndURL", "([a-zA-Z][a-zA-Z+.-]{0,10}://[a-zA-Z0-9%._~!$&?#'()*+,;:@/=-]+)", null)); + wizard.addPage(mp); - @Override - public IWizard getNewTaskWizard(TaskRepository repository, ITaskMapping selection) { - return new NewTaskWizard(repository, selection); - } + return wizard; + } - @Override - public boolean hasSearchPage() { - // TODO Auto-generated method stub - return false; - } + @Override + public IWizard getNewTaskWizard(TaskRepository repository, ITaskMapping selection) { + return new NewTaskWizard(repository, selection); + } + + @Override + public boolean hasSearchPage() { + // TODO Auto-generated method stub + return false; + } + @Override + public @Nullable String getReplyText(@NonNull TaskRepository taskRepository, @NonNull ITask task, + @Nullable ITaskComment taskComment, boolean includeTask) { + TaskAttribute note_id = taskComment.getTaskAttribute().getAttribute("note_id"); + String note_idValue = note_id != null ? note_id.getValue() : ""; + return MessageFormat.format("( In reply to {0}#note_{1} )\n", taskComment.getTask().getUrl(), + note_idValue); + } } diff --git a/mylyn.tasks/connectors/gitlab/org.eclipse.mylyn.gitlab.ui/src/org/eclipse/mylyn/gitlab/ui/GitlabRepositorySettingsPage.java b/mylyn.tasks/connectors/gitlab/org.eclipse.mylyn.gitlab.ui/src/org/eclipse/mylyn/gitlab/ui/GitlabRepositorySettingsPage.java index 0f287e38c4..e1042597a1 100644 --- a/mylyn.tasks/connectors/gitlab/org.eclipse.mylyn.gitlab.ui/src/org/eclipse/mylyn/gitlab/ui/GitlabRepositorySettingsPage.java +++ b/mylyn.tasks/connectors/gitlab/org.eclipse.mylyn.gitlab.ui/src/org/eclipse/mylyn/gitlab/ui/GitlabRepositorySettingsPage.java @@ -27,6 +27,8 @@ import org.eclipse.jface.viewers.StructuredSelection; import org.eclipse.mylyn.gitlab.core.GitlabCoreActivator; import org.eclipse.mylyn.internal.tasks.ui.TasksUiPlugin; +import org.eclipse.mylyn.internal.tasks.ui.editors.Messages; +import org.eclipse.mylyn.internal.tasks.ui.editors.TaskEditorExtensions; import org.eclipse.mylyn.tasks.core.TaskRepository; import org.eclipse.mylyn.tasks.ui.wizards.AbstractRepositorySettingsPage; import org.eclipse.swt.SWT; @@ -43,219 +45,232 @@ public class GitlabRepositorySettingsPage extends AbstractRepositorySettingsPage { - private ListViewer groups; - private ArrayList groupList = new ArrayList<>(); - private Text groupInput; - private Button groupRemoveButton; - private Button groupAddButton; + private ListViewer groups; + private ArrayList groupList = new ArrayList<>(); + private Text groupInput; + private Button groupRemoveButton; + private Button groupAddButton; - private ListViewer projects; - private ArrayList projectList = new ArrayList<>(); - private Text projectInput; - private Button projectRemoveButton; - private Button projectAddButton; + private ListViewer projects; + private ArrayList projectList = new ArrayList<>(); + private Text projectInput; + private Button projectRemoveButton; + private Button projectAddButton; + private Button avatarSupportButton; - public GitlabRepositorySettingsPage(String title, String description, TaskRepository taskRepository) { - super(title, description, taskRepository); - setNeedsRepositoryCredentials(true); // setNeedsRepositoryCredentials(true); - setNeedsAnonymousLogin(false); // setNeedsAnonymousLogin(false); - setNeedsEncoding(false); // setNeedsEncoding(true); - setNeedsTimeZone(false); // setNeedsTimeZone(true); - setNeedsProxy(false); // setNeedsProxy(true); - setNeedsValidation(true); // setNeedsValidation(true); - setNeedsAdvanced(true); // setNeedsAdvanced(true); - setNeedsValidateOnFinish(false); // setNeedsValidateOnFinish(false); - } + public GitlabRepositorySettingsPage(String title, String description, TaskRepository taskRepository) { + super(title, description, taskRepository); + setNeedsRepositoryCredentials(true); // setNeedsRepositoryCredentials(true); + setNeedsAnonymousLogin(false); // setNeedsAnonymousLogin(false); + setNeedsEncoding(false); // setNeedsEncoding(true); + setNeedsTimeZone(false); // setNeedsTimeZone(true); + setNeedsProxy(false); // setNeedsProxy(true); + setNeedsValidation(true); // setNeedsValidation(true); + setNeedsAdvanced(true); // setNeedsAdvanced(true); + setNeedsValidateOnFinish(false); // setNeedsValidateOnFinish(false); + } - @Override - public String getConnectorKind() { - return GitlabCoreActivator.CONNECTOR_KIND; - } + @Override + public String getConnectorKind() { + return GitlabCoreActivator.CONNECTOR_KIND; + } - @Override - protected void createAdditionalControls(Composite parent) { - FormToolkit toolkit = new FormToolkit(TasksUiPlugin.getDefault().getFormColors(parent.getDisplay())); - Composite aditionalContainer = new Composite(parent, SWT.NONE); - GridLayoutFactory.fillDefaults().margins(0, 0).numColumns(3).applyTo(aditionalContainer); - GridDataFactory.fillDefaults().grab(true, true).align(SWT.FILL, SWT.FILL).applyTo(aditionalContainer); + @Override + protected void createAdditionalControls(Composite parent) { + FormToolkit toolkit = new FormToolkit(TasksUiPlugin.getDefault().getFormColors(parent.getDisplay())); + Composite aditionalContainer = new Composite(parent, SWT.NONE); + GridLayoutFactory.fillDefaults().margins(0, 0).numColumns(3).applyTo(aditionalContainer); + GridDataFactory.fillDefaults().grab(true, true).align(SWT.FILL, SWT.FILL).applyTo(aditionalContainer); // aditionalContainer.setBackground(new Color(aditionalContainer.getDisplay(), 0, 255, 0)); - Label groupsLabel = new Label(aditionalContainer, SWT.NONE); - groupsLabel.setText("include Groups"); - GridData gd = new GridData(GridData.VERTICAL_ALIGN_CENTER); - gd.horizontalSpan = 1; - gd.verticalSpan = 3; - groupsLabel.setLayoutData(gd); - groups = new ListViewer(aditionalContainer, SWT.H_SCROLL | SWT.V_SCROLL); - gd = new GridData(GridData.FILL_BOTH); - gd.horizontalSpan = 1; - gd.verticalSpan = 3; - gd.grabExcessHorizontalSpace = true; - groups.getList().setLayoutData(gd); - groups.setLabelProvider(new LabelProvider()); - groups.setContentProvider(ArrayContentProvider.getInstance()); - if (repository != null) { - String groupsValue = repository.getProperty(GitlabCoreActivator.GROUPS); - if (groupsValue != null) - groupList = new ArrayList(Arrays.asList(groupsValue.split(","))); - } - groups.setInput(groupList); - groupInput = new Text(aditionalContainer, SWT.NONE); - gd = new GridData(GridData.HORIZONTAL_ALIGN_BEGINNING); - gd.widthHint = 200; - groupInput.setLayoutData(gd); - groupInput.addKeyListener(new KeyAdapter() { + Label groupsLabel = new Label(aditionalContainer, SWT.NONE); + groupsLabel.setText("include Groups"); + GridData gd = new GridData(GridData.VERTICAL_ALIGN_CENTER); + gd.horizontalSpan = 1; + gd.verticalSpan = 3; + groupsLabel.setLayoutData(gd); + groups = new ListViewer(aditionalContainer, SWT.H_SCROLL | SWT.V_SCROLL); + gd = new GridData(GridData.FILL_BOTH); + gd.horizontalSpan = 1; + gd.verticalSpan = 3; + gd.grabExcessHorizontalSpace = true; + groups.getList().setLayoutData(gd); + groups.setLabelProvider(new LabelProvider()); + groups.setContentProvider(ArrayContentProvider.getInstance()); + if (repository != null) { + String groupsValue = repository.getProperty(GitlabCoreActivator.GROUPS); + if (groupsValue != null) + groupList = new ArrayList(Arrays.asList(groupsValue.split(","))); + } + groups.setInput(groupList); + groupInput = new Text(aditionalContainer, SWT.NONE); + gd = new GridData(GridData.HORIZONTAL_ALIGN_BEGINNING); + gd.widthHint = 200; + groupInput.setLayoutData(gd); + groupInput.addKeyListener(new KeyAdapter() { - @Override - public void keyReleased(KeyEvent e) { - super.keyReleased(e); - updateUIEnablement(); - } + @Override + public void keyReleased(KeyEvent e) { + super.keyReleased(e); + updateUIEnablement(); + } - }); - groups.addSelectionChangedListener(new ISelectionChangedListener() { + }); + groups.addSelectionChangedListener(new ISelectionChangedListener() { - @Override - public void selectionChanged(SelectionChangedEvent event) { - IStructuredSelection selection = (IStructuredSelection) event.getSelection(); - if (selection.size() > 0) { - groupInput.setText((String) selection.getFirstElement()); - } - updateUIEnablement(); - } - }); + @Override + public void selectionChanged(SelectionChangedEvent event) { + IStructuredSelection selection = (IStructuredSelection) event.getSelection(); + if (selection.size() > 0) { + groupInput.setText((String) selection.getFirstElement()); + } + updateUIEnablement(); + } + }); // groupInput.setBackground(new Color(aditionalContainer.getDisplay(), 255, 0 , 0)); - groupAddButton = new Button(aditionalContainer, SWT.PUSH); - groupAddButton.setText("Add"); - groupAddButton.addSelectionListener(new SelectionAdapter() { - @Override - public void widgetSelected(SelectionEvent e) { - groupList.add(groupInput.getText()); - groupInput.setText(""); - groups.refresh(); - updateUIEnablement(); - } - }); + groupAddButton = new Button(aditionalContainer, SWT.PUSH); + groupAddButton.setText("Add"); + groupAddButton.addSelectionListener(new SelectionAdapter() { + @Override + public void widgetSelected(SelectionEvent e) { + groupList.add(groupInput.getText()); + groupInput.setText(""); + groups.refresh(); + updateUIEnablement(); + } + }); - groupRemoveButton = new Button(aditionalContainer, SWT.PUSH); - groupRemoveButton.setText("remove"); - groupRemoveButton.addSelectionListener(new SelectionAdapter() { - @Override - public void widgetSelected(SelectionEvent e) { - IStructuredSelection selection = (IStructuredSelection) groups.getSelection(); - int lastIdx = -1; - if (selection != null) { - Object firstElement = selection.getFirstElement(); - lastIdx = groupList.indexOf(firstElement); - } - groupList.remove(groupInput.getText()); - groupInput.setText(""); - groups.refresh(); - if (lastIdx >= 0 && lastIdx < groupList.size()) { - groups.setSelection(new StructuredSelection(groupList.get(lastIdx)), true); - } - updateUIEnablement(); - } - }); - - Label projectsLabel = new Label(aditionalContainer, SWT.NONE); - projectsLabel.setText("include Projects"); - gd = new GridData(GridData.VERTICAL_ALIGN_CENTER); - gd.horizontalSpan = 1; - gd.verticalSpan = 3; - projectsLabel.setLayoutData(gd); - projects = new ListViewer(aditionalContainer, SWT.H_SCROLL | SWT.V_SCROLL); - gd = new GridData(GridData.FILL_BOTH); - gd.horizontalSpan = 1; - gd.verticalSpan = 3; - gd.grabExcessHorizontalSpace = true; - projects.getList().setLayoutData(gd); - projects.setLabelProvider(new LabelProvider()); - projects.setContentProvider(ArrayContentProvider.getInstance()); - if (repository != null) { - String projectsValue = repository.getProperty(GitlabCoreActivator.PROJECTS); - if (projectsValue != null) - projectList = new ArrayList(Arrays.asList(projectsValue.split(","))); + groupRemoveButton = new Button(aditionalContainer, SWT.PUSH); + groupRemoveButton.setText("remove"); + groupRemoveButton.addSelectionListener(new SelectionAdapter() { + @Override + public void widgetSelected(SelectionEvent e) { + IStructuredSelection selection = (IStructuredSelection) groups.getSelection(); + int lastIdx = -1; + if (selection != null) { + Object firstElement = selection.getFirstElement(); + lastIdx = groupList.indexOf(firstElement); + } + groupList.remove(groupInput.getText()); + groupInput.setText(""); + groups.refresh(); + if (lastIdx >= 0 && lastIdx < groupList.size()) { + groups.setSelection(new StructuredSelection(groupList.get(lastIdx)), true); } - projects.setInput(projectList); - projectInput = new Text(aditionalContainer, SWT.NONE); - gd = new GridData(GridData.HORIZONTAL_ALIGN_BEGINNING); - gd.widthHint = 200; - projectInput.setLayoutData(gd); - projectInput.addKeyListener(new KeyAdapter() { + updateUIEnablement(); + } + }); + + Label projectsLabel = new Label(aditionalContainer, SWT.NONE); + projectsLabel.setText("include Projects"); + gd = new GridData(GridData.VERTICAL_ALIGN_CENTER); + gd.horizontalSpan = 1; + gd.verticalSpan = 3; + projectsLabel.setLayoutData(gd); + projects = new ListViewer(aditionalContainer, SWT.H_SCROLL | SWT.V_SCROLL); + gd = new GridData(GridData.FILL_BOTH); + gd.horizontalSpan = 1; + gd.verticalSpan = 3; + gd.grabExcessHorizontalSpace = true; + projects.getList().setLayoutData(gd); + projects.setLabelProvider(new LabelProvider()); + projects.setContentProvider(ArrayContentProvider.getInstance()); + if (repository != null) { + String projectsValue = repository.getProperty(GitlabCoreActivator.PROJECTS); + if (projectsValue != null) + projectList = new ArrayList(Arrays.asList(projectsValue.split(","))); + } + projects.setInput(projectList); + projectInput = new Text(aditionalContainer, SWT.NONE); + gd = new GridData(GridData.HORIZONTAL_ALIGN_BEGINNING); + gd.widthHint = 200; + projectInput.setLayoutData(gd); + projectInput.addKeyListener(new KeyAdapter() { - @Override - public void keyReleased(KeyEvent e) { - super.keyReleased(e); - updateUIEnablement(); - } + @Override + public void keyReleased(KeyEvent e) { + super.keyReleased(e); + updateUIEnablement(); + } - }); - projects.addSelectionChangedListener(new ISelectionChangedListener() { + }); + projects.addSelectionChangedListener(new ISelectionChangedListener() { - @Override - public void selectionChanged(SelectionChangedEvent event) { - IStructuredSelection selection = (IStructuredSelection) event.getSelection(); - if (selection.size() > 0) { - projectInput.setText((String) selection.getFirstElement()); - } - updateUIEnablement(); - } - }); + @Override + public void selectionChanged(SelectionChangedEvent event) { + IStructuredSelection selection = (IStructuredSelection) event.getSelection(); + if (selection.size() > 0) { + projectInput.setText((String) selection.getFirstElement()); + } + updateUIEnablement(); + } + }); // projectInput.setBackground(new Color(aditionalContainer.getDisplay(), 255, 0 , 0)); - projectAddButton = new Button(aditionalContainer, SWT.PUSH); - projectAddButton.setText("Add"); - projectAddButton.addSelectionListener(new SelectionAdapter() { - @Override - public void widgetSelected(SelectionEvent e) { - projectList.add(projectInput.getText()); - projectInput.setText(""); - projects.refresh(); - updateUIEnablement(); - } - }); + projectAddButton = new Button(aditionalContainer, SWT.PUSH); + projectAddButton.setText("Add"); + projectAddButton.addSelectionListener(new SelectionAdapter() { + @Override + public void widgetSelected(SelectionEvent e) { + projectList.add(projectInput.getText()); + projectInput.setText(""); + projects.refresh(); + updateUIEnablement(); + } + }); - projectRemoveButton = new Button(aditionalContainer, SWT.PUSH); - projectRemoveButton.setText("remove"); - projectRemoveButton.addSelectionListener(new SelectionAdapter() { - @Override - public void widgetSelected(SelectionEvent e) { - IStructuredSelection selection = (IStructuredSelection) projects.getSelection(); - int lastIdx = -1; - if (selection != null) { - Object firstElement = selection.getFirstElement(); - lastIdx = projectList.indexOf(firstElement); - } - projectList.remove(projectInput.getText()); - projectInput.setText(""); - projects.refresh(); - if (lastIdx >= 0 && lastIdx < projectList.size()) { - projects.setSelection(new StructuredSelection(projectList.get(lastIdx)), true); - } - updateUIEnablement(); - } - }); - + projectRemoveButton = new Button(aditionalContainer, SWT.PUSH); + projectRemoveButton.setText("remove"); + projectRemoveButton.addSelectionListener(new SelectionAdapter() { + @Override + public void widgetSelected(SelectionEvent e) { + IStructuredSelection selection = (IStructuredSelection) projects.getSelection(); + int lastIdx = -1; + if (selection != null) { + Object firstElement = selection.getFirstElement(); + lastIdx = projectList.indexOf(firstElement); + } + projectList.remove(projectInput.getText()); + projectInput.setText(""); + projects.refresh(); + if (lastIdx >= 0 && lastIdx < projectList.size()) { + projects.setSelection(new StructuredSelection(projectList.get(lastIdx)), true); + } updateUIEnablement(); - } + } + }); - private void updateUIEnablement() { - IStructuredSelection selection = (IStructuredSelection) groups.getSelection(); - groupRemoveButton.setEnabled(selection.size() > 0); - groupAddButton.setEnabled(!groupInput.getText().isEmpty()); + avatarSupportButton = new Button(aditionalContainer, SWT.CHECK); + avatarSupportButton.setText("Show Avantar images"); + avatarSupportButton.setSelection(getRepository() != null + && Boolean.parseBoolean(getRepository().getProperty(GitlabCoreActivator.AVANTAR))); - selection = (IStructuredSelection) projects.getSelection(); - projectRemoveButton.setEnabled(selection.size() > 0); - projectAddButton.setEnabled(!projectInput.getText().isEmpty()); -} + gd = new GridData(GridData.FILL_BOTH); + gd.horizontalSpan = 2; + gd.verticalSpan = 1; + gd.grabExcessHorizontalSpace = true; + avatarSupportButton.setLayoutData(gd); - @Override - public void applyTo(TaskRepository repository) { - repository.setProperty(GitlabCoreActivator.GROUPS, String.join(",", groupList)); - repository.setProperty(GitlabCoreActivator.PROJECTS, String.join(",", projectList)); - super.applyTo(repository); - } + updateUIEnablement(); + } + + private void updateUIEnablement() { + IStructuredSelection selection = (IStructuredSelection) groups.getSelection(); + groupRemoveButton.setEnabled(selection.size() > 0); + groupAddButton.setEnabled(!groupInput.getText().isEmpty()); + + selection = (IStructuredSelection) projects.getSelection(); + projectRemoveButton.setEnabled(selection.size() > 0); + projectAddButton.setEnabled(!projectInput.getText().isEmpty()); + } + + @Override + public void applyTo(TaskRepository repository) { + repository.setProperty(GitlabCoreActivator.GROUPS, String.join(",", groupList)); + repository.setProperty(GitlabCoreActivator.PROJECTS, String.join(",", projectList)); + repository.setProperty(GitlabCoreActivator.AVANTAR, Boolean.toString(avatarSupportButton.getSelection())); + super.applyTo(repository); + } } diff --git a/mylyn.tasks/connectors/gitlab/org.eclipse.mylyn.gitlab.ui/src/org/eclipse/mylyn/gitlab/ui/GitlabTaskEditorCommentPart.java b/mylyn.tasks/connectors/gitlab/org.eclipse.mylyn.gitlab.ui/src/org/eclipse/mylyn/gitlab/ui/GitlabTaskEditorCommentPart.java index fbfe3d0e6b..e3d11e54b0 100644 --- a/mylyn.tasks/connectors/gitlab/org.eclipse.mylyn.gitlab.ui/src/org/eclipse/mylyn/gitlab/ui/GitlabTaskEditorCommentPart.java +++ b/mylyn.tasks/connectors/gitlab/org.eclipse.mylyn.gitlab.ui/src/org/eclipse/mylyn/gitlab/ui/GitlabTaskEditorCommentPart.java @@ -2,22 +2,32 @@ import java.util.ArrayList; import java.util.List; -import java.util.Map; +import org.eclipse.jface.action.IMenuCreator; import org.eclipse.jface.action.ToolBarManager; import org.eclipse.jface.layout.GridDataFactory; -import org.eclipse.mylyn.commons.ui.CommonImages; +import org.eclipse.jface.viewers.StructuredSelection; +import org.eclipse.mylyn.commons.identity.core.spi.ProfileImage; import org.eclipse.mylyn.commons.ui.FillWidthLayout; import org.eclipse.mylyn.commons.workbench.forms.CommonFormUtil; +import org.eclipse.mylyn.gitlab.core.GitlabCoreActivator; +import org.eclipse.mylyn.gitlab.core.GitlabRepositoryConnector; +import org.eclipse.mylyn.internal.tasks.core.CommentQuoter; import org.eclipse.mylyn.internal.tasks.core.TaskComment; +import org.eclipse.mylyn.internal.tasks.ui.TasksUiPlugin; +import org.eclipse.mylyn.internal.tasks.ui.editors.AbstractReplyToCommentAction; import org.eclipse.mylyn.internal.tasks.ui.editors.CommentGroupStrategy.CommentGroup; import org.eclipse.mylyn.internal.tasks.ui.editors.EditorUtil; import org.eclipse.mylyn.internal.tasks.ui.editors.TaskEditorCommentPart; -import org.eclipse.mylyn.internal.tasks.ui.editors.TaskEditorExtensions; +import org.eclipse.mylyn.internal.tasks.ui.editors.TaskEditorRichTextPart; import org.eclipse.mylyn.internal.tasks.ui.editors.UserAttributeEditor; -import org.eclipse.mylyn.tasks.core.IRepositoryPerson; import org.eclipse.mylyn.tasks.core.ITaskComment; import org.eclipse.mylyn.tasks.core.data.TaskAttribute; +import org.eclipse.mylyn.tasks.ui.AbstractRepositoryConnectorUi; +import org.eclipse.mylyn.tasks.ui.TasksUi; +import org.eclipse.mylyn.tasks.ui.TasksUiImages; +import org.eclipse.mylyn.tasks.ui.editors.AbstractTaskEditorPage; +import org.eclipse.mylyn.tasks.ui.editors.AbstractTaskEditorPart; import org.eclipse.swt.SWT; import org.eclipse.swt.events.MouseAdapter; import org.eclipse.swt.events.MouseEvent; @@ -26,7 +36,6 @@ import org.eclipse.swt.layout.RowLayout; import org.eclipse.swt.widgets.Composite; import org.eclipse.swt.widgets.Control; -import org.eclipse.swt.widgets.Label; import org.eclipse.swt.widgets.Menu; import org.eclipse.ui.forms.IFormColors; import org.eclipse.ui.forms.events.ExpansionAdapter; @@ -38,6 +47,92 @@ import org.eclipse.ui.forms.widgets.ImageHyperlink; public class GitlabTaskEditorCommentPart extends TaskEditorCommentPart { + private class ReplyToCommentAction extends AbstractReplyToCommentAction { + private final AbstractTaskEditorPage editor; + + private final CommentViewer commentViewerGitlab; + + public ReplyToCommentAction(CommentViewer commentViewer) { + super(GitlabTaskEditorCommentPart.this.getTaskEditorPage(), commentViewer.getTaskComment()); + this.editor = GitlabTaskEditorCommentPart.this.getTaskEditorPage(); + this.commentViewerGitlab = commentViewer; + } + + @Override + protected String getReplyText() { + return commentViewerGitlab.getReplyToText(); + } + + protected CommentViewer getCommentViewer() { + return commentViewerGitlab; + } + + @Override + public void run() { + reply(editor, getCommentViewer().getTaskComment(), getReplyText()); + } + + public void dispose() { + } + + public static void reply(AbstractTaskEditorPage editor, ITaskComment taskComment, String text) { + AbstractRepositoryConnectorUi connectorUi = TasksUiPlugin.getConnectorUi(editor.getConnectorKind()); + String reference = connectorUi.getReplyText(editor.getTaskRepository(), editor.getTask(), taskComment, + false); + StringBuilder sb = new StringBuilder(); + sb.append(reference); + sb.append("\n"); //$NON-NLS-1$ + if (text != null) { + CommentQuoter quoter = new CommentQuoter(); + sb.append(quoter.quote(text)); + } + AbstractTaskEditorPart newCommentPart = editor + .getPart(org.eclipse.mylyn.tasks.ui.editors.AbstractTaskEditorPage.ID_PART_NEW_COMMENT); + if (newCommentPart instanceof TaskEditorRichTextPart) { + TaskAttribute newCommentAttrib = ((TaskEditorRichTextPart) newCommentPart).getAttribute(); + TaskAttribute newCommentDiscussion = newCommentAttrib.getAttribute("discussions"); + TaskAttribute newCommentNoteable = newCommentAttrib.getAttribute("noteable_id"); + TaskAttribute newCommentNoteID = newCommentAttrib.getAttribute("note_id"); + TaskAttribute commentDiscussion = taskComment.getTaskAttribute().getAttribute("discussions"); + TaskAttribute commentNoteable = taskComment.getTaskAttribute().getAttribute("noteable_id"); + TaskAttribute commentNoteID = taskComment.getTaskAttribute().getAttribute("note_id"); + if (newCommentDiscussion == null) { + newCommentDiscussion = newCommentAttrib.createAttribute("discussions"); + } + if (newCommentNoteable == null) { + newCommentNoteable = newCommentAttrib.createAttribute("noteable_id"); + } + if (newCommentNoteID == null) { + newCommentNoteID = newCommentAttrib.createAttribute("note_id"); + } + newCommentDiscussion.setValue(commentDiscussion.getValue()); + newCommentNoteable.setValue(commentNoteable.getValue()); + newCommentNoteID.setValue(commentNoteID.getValue()); + } + editor.appendTextToNewComment(sb.toString()); + } + + } + + private class ReplyToCommentActionWithMenu extends ReplyToCommentAction implements IMenuCreator { + + public ReplyToCommentActionWithMenu(CommentViewer commentViewer) { + super(commentViewer); + setMenuCreator(this); + } + + public Menu getMenu(Control parent) { + setCurrentViewer(getCommentViewer()); + getSelectionProvider().setSelection(new StructuredSelection(getCurrentViewer().getTaskComment())); + return getCommentMenu(); + } + + public Menu getMenu(Menu parent) { + getSelectionProvider().setSelection(new StructuredSelection(getCommentViewer().getTaskComment())); + return getCommentMenu(); + } + + } public class GitlabCommentGroupViewer extends CommentGroupViewer { @@ -118,12 +213,12 @@ protected void expandComment(FormToolkit toolkit, Composite composite, boolean e if (expanded && composite.getData(KEY_EDITOR) == null) { Menu mm0 = composite.getMenu(); commentViewer = toolkit.createComposite(composite); - commentViewer.setLayout(new GridLayout(1, false)); + commentViewer.setLayout(new GridLayout(2, false)); commentViewer.setLayoutData(new GridData(GridData.VERTICAL_ALIGN_BEGINNING)); // Create user image viewer - boolean showAvatar = Boolean.parseBoolean(getModel().getTaskRepository() - .getProperty(TaskEditorExtensions.REPOSITORY_PROPERTY_AVATAR_SUPPORT)); + boolean showAvatar = Boolean + .parseBoolean(getModel().getTaskRepository().getProperty(GitlabCoreActivator.AVANTAR)); if (showAvatar) { String commentAuthor = getTaskData().getAttributeMapper().mapToRepositoryKey(commentAttribute, TaskAttribute.COMMENT_AUTHOR); @@ -137,8 +232,15 @@ protected void expandComment(FormToolkit toolkit, Composite composite, boolean e UserAttributeEditor userImage = new UserAttributeEditor(getModel(), userImageAttribute, 30); userImage.createControl(userImageComposite, toolkit); - - userImage.refresh(); + TaskAttribute avatar_url = userImageAttribute.getAttribute("avatar_url"); + + if (avatar_url != null) { + GitlabRepositoryConnector gitlabConnector = (GitlabRepositoryConnector) TasksUi + .getRepositoryManager() + .getRepositoryConnector(userImageAttribute.getTaskData().getConnectorKind()); + byte[] avatarBytes = gitlabConnector.getAvatarData(avatar_url.getValue()); + userImage.updateImage(new ProfileImage(avatarBytes, 30, 30, "")); + } } } @@ -170,6 +272,9 @@ public void mouseDown(MouseEvent e) { GitlabCommentViewer replyCommentViewer = new GitlabCommentViewer(taskAttributeReply); subViewer.add(replyCommentViewer); replyCommentViewer.createControl(commentViewer, toolkit); + GridData subViewerGridData = new GridData(GridData.BEGINNING); + subViewerGridData.horizontalSpan = 2; + replyCommentViewer.getControl().setLayoutData(subViewerGridData); } } getTaskEditorPage().getAttributeEditorToolkit().adapt(commentTextEditor); @@ -287,4 +392,11 @@ public List getCommentGroupViewers() { return commentGroupViewers; } + protected void addActionsToToolbarButton(ToolBarManager toolBarManager, TaskComment taskComment, + CommentViewer commentViewer) { + ReplyToCommentAction replyAction = new ReplyToCommentActionWithMenu(commentViewer); + replyAction.setImageDescriptor(TasksUiImages.COMMENT_REPLY_SMALL); + toolBarManager.add(replyAction); + } + } diff --git a/mylyn.tasks/connectors/gitlab/org.eclipse.mylyn.gitlab.ui/src/org/eclipse/mylyn/gitlab/ui/GitlabTaskEditorPage.java b/mylyn.tasks/connectors/gitlab/org.eclipse.mylyn.gitlab.ui/src/org/eclipse/mylyn/gitlab/ui/GitlabTaskEditorPage.java index 7d18d0e184..0fe398f422 100644 --- a/mylyn.tasks/connectors/gitlab/org.eclipse.mylyn.gitlab.ui/src/org/eclipse/mylyn/gitlab/ui/GitlabTaskEditorPage.java +++ b/mylyn.tasks/connectors/gitlab/org.eclipse.mylyn.gitlab.ui/src/org/eclipse/mylyn/gitlab/ui/GitlabTaskEditorPage.java @@ -18,6 +18,8 @@ import org.eclipse.mylyn.gitlab.core.GitlabCoreActivator; import org.eclipse.mylyn.internal.tasks.ui.editors.TaskEditorCommentPart; +import org.eclipse.mylyn.internal.tasks.ui.editors.TaskEditorNewCommentPart; +import org.eclipse.mylyn.internal.tasks.ui.editors.TaskEditorSummaryPart; import org.eclipse.mylyn.tasks.ui.editors.AbstractTaskEditorPage; import org.eclipse.mylyn.tasks.ui.editors.AbstractTaskEditorPart; import org.eclipse.mylyn.tasks.ui.editors.AttributeEditorFactory; @@ -26,46 +28,63 @@ public class GitlabTaskEditorPage extends AbstractTaskEditorPage { - public GitlabTaskEditorPage(TaskEditor editor) { - this(editor, GitlabCoreActivator.CONNECTOR_KIND); - } - - - public GitlabTaskEditorPage(TaskEditor editor, String connectorKind) { - super(editor, connectorKind); - setNeedsPrivateSection(false); - setNeedsSubmitButton(true); - } + public GitlabTaskEditorPage(TaskEditor editor) { + this(editor, GitlabCoreActivator.CONNECTOR_KIND); + } + + public GitlabTaskEditorPage(TaskEditor editor, String connectorKind) { + super(editor, connectorKind); + setNeedsPrivateSection(false); + setNeedsSubmitButton(true); + } - @Override - protected AttributeEditorFactory createAttributeEditorFactory() { - // TODO Auto-generated method stub - return super.createAttributeEditorFactory(); + @Override + protected AttributeEditorFactory createAttributeEditorFactory() { + // TODO Auto-generated method stub + return super.createAttributeEditorFactory(); + } + + @Override + protected Set createPartDescriptors() { + // TODO Auto-generated method stub + Set descriptors = super.createPartDescriptors(); + // remove unnecessary default editor parts + ArrayList descriptorsToRemove = new ArrayList(2); + boolean hasCommentPart = false; + boolean hasNewCommentPart = false; + for (TaskEditorPartDescriptor taskEditorPartDescriptor : descriptors) { + if (taskEditorPartDescriptor.getId().equals(ID_PART_COMMENTS) + || taskEditorPartDescriptor.getId().equals(ID_PART_NEW_COMMENT) + || taskEditorPartDescriptor.getId().equals(ID_PART_SUMMARY)) { + hasCommentPart = hasCommentPart || taskEditorPartDescriptor.getId().equals(ID_PART_COMMENTS); + hasNewCommentPart = hasNewCommentPart || taskEditorPartDescriptor.getId().equals(ID_PART_NEW_COMMENT); + descriptorsToRemove.add(taskEditorPartDescriptor); + continue; + } } - - @Override - protected Set createPartDescriptors() { - // TODO Auto-generated method stub - Set descriptors = super.createPartDescriptors(); - // remove unnecessary default editor parts - ArrayList descriptorsToRemove = new ArrayList(2); - boolean hasCommentPart = false; - for (TaskEditorPartDescriptor taskEditorPartDescriptor : descriptors) { - if (taskEditorPartDescriptor.getId().equals(ID_PART_COMMENTS)) { - hasCommentPart = hasCommentPart || taskEditorPartDescriptor.getId().equals(ID_PART_COMMENTS); - descriptorsToRemove.add(taskEditorPartDescriptor); - continue; - } + descriptors.removeAll(descriptorsToRemove); + descriptors.add(new TaskEditorPartDescriptor(ID_PART_SUMMARY) { + @Override + public AbstractTaskEditorPart createPart() { + return new GitlabTaskEditorSummaryPart(); + } + }.setPath(PATH_HEADER)); + if (hasCommentPart) { + descriptors.add(new TaskEditorPartDescriptor(ID_PART_COMMENTS) { + @Override + public AbstractTaskEditorPart createPart() { + return new GitlabTaskEditorCommentPart(); } - descriptors.removeAll(descriptorsToRemove); - if (hasCommentPart) { - descriptors.add(new TaskEditorPartDescriptor(ID_PART_COMMENTS) { - @Override - public AbstractTaskEditorPart createPart() { - return new GitlabTaskEditorCommentPart(); - } - }.setPath(PATH_COMMENTS)); + }.setPath(PATH_COMMENTS)); + } + if (hasCommentPart) { + descriptors.add(new TaskEditorPartDescriptor(ID_PART_NEW_COMMENT) { + @Override + public AbstractTaskEditorPart createPart() { + return new TaskEditorNewCommentPart(); } - return descriptors; + }.setPath(PATH_COMMENTS)); } + return descriptors; + } } diff --git a/mylyn.tasks/connectors/gitlab/org.eclipse.mylyn.gitlab.ui/src/org/eclipse/mylyn/gitlab/ui/GitlabTaskEditorSummaryPart.java b/mylyn.tasks/connectors/gitlab/org.eclipse.mylyn.gitlab.ui/src/org/eclipse/mylyn/gitlab/ui/GitlabTaskEditorSummaryPart.java new file mode 100644 index 0000000000..dc64d0b0b1 --- /dev/null +++ b/mylyn.tasks/connectors/gitlab/org.eclipse.mylyn.gitlab.ui/src/org/eclipse/mylyn/gitlab/ui/GitlabTaskEditorSummaryPart.java @@ -0,0 +1,90 @@ +package org.eclipse.mylyn.gitlab.ui; + +import org.eclipse.jface.layout.GridDataFactory; +import org.eclipse.mylyn.commons.identity.core.spi.ProfileImage; +import org.eclipse.mylyn.gitlab.core.GitlabCoreActivator; +import org.eclipse.mylyn.gitlab.core.GitlabRepositoryConnector; +import org.eclipse.mylyn.internal.tasks.ui.TasksUiPlugin; +import org.eclipse.mylyn.internal.tasks.ui.editors.EditorUtil; +import org.eclipse.mylyn.internal.tasks.ui.editors.TaskEditorExtensions; +import org.eclipse.mylyn.internal.tasks.ui.editors.TaskEditorSummaryPart; +import org.eclipse.mylyn.internal.tasks.ui.editors.UserAttributeEditor; +import org.eclipse.mylyn.tasks.core.AbstractRepositoryConnector; +import org.eclipse.mylyn.tasks.core.data.TaskAttribute; +import org.eclipse.mylyn.tasks.ui.AbstractRepositoryConnectorUi; +import org.eclipse.mylyn.tasks.ui.TasksUi; +import org.eclipse.swt.SWT; +import org.eclipse.swt.events.FocusAdapter; +import org.eclipse.swt.events.FocusEvent; +import org.eclipse.swt.layout.GridLayout; +import org.eclipse.swt.widgets.Composite; +import org.eclipse.swt.widgets.Control; +import org.eclipse.ui.forms.widgets.FormToolkit; + +import com.google.common.base.Strings; + +public class GitlabTaskEditorSummaryPart extends TaskEditorSummaryPart { + + @Override + public void createControl(Composite parent, FormToolkit toolkit) { + + Composite composite = toolkit.createComposite(parent); + GridLayout layout = EditorUtil.createSectionClientLayout(); + layout.numColumns = 1; + layout.marginHeight = 0; + layout.marginTop = 0; + layout.marginWidth = 0; + layout.verticalSpacing = 3; + composite.setLayout(layout); + + TaskAttribute priorityAttribute = getTaskData().getRoot().getMappedAttribute(TaskAttribute.PRIORITY); + final Control priorityEditor = addPriorityAttributeWithIcon(composite, toolkit, priorityAttribute, false); + if (priorityEditor != null) { + GridDataFactory.fillDefaults().align(SWT.CENTER, SWT.CENTER).span(1, 2).applyTo(priorityEditor); + // forward focus to the summary editor + priorityEditor.addFocusListener(new FocusAdapter() { + @Override + public void focusGained(FocusEvent e) { + if (summaryEditor != null && summaryEditor.getControl() != null) { + summaryEditor.getControl().setFocus(); + // only forward it on first view + priorityEditor.removeFocusListener(this); + } + } + }); + layout.numColumns++; + } + + addSummaryText(composite, toolkit); + + if (Boolean.parseBoolean(getModel().getTaskRepository().getProperty(GitlabCoreActivator.AVANTAR))) { + TaskAttribute userAssignedAttribute = getTaskData().getRoot() + .getMappedAttribute(TaskAttribute.USER_ASSIGNED); + if (userAssignedAttribute != null && !Strings.isNullOrEmpty(userAssignedAttribute.getValue())) { + UserAttributeEditor editor = new UserAttributeEditor(getModel(), userAssignedAttribute); + editor.createControl(composite, toolkit); + GridDataFactory.fillDefaults().align(SWT.CENTER, SWT.CENTER).span(1, 2).indent(0, 2) + .applyTo(editor.getControl()); + layout.marginRight = 1; + layout.numColumns++; + TaskAttribute avatar_url = userAssignedAttribute.getAttribute("avatar_url"); + + if (avatar_url != null) { + GitlabRepositoryConnector gitlabConnector = (GitlabRepositoryConnector) TasksUi + .getRepositoryManager() + .getRepositoryConnector(userAssignedAttribute.getTaskData().getConnectorKind()); + byte[] avatarBytes = gitlabConnector.getAvatarData(avatar_url.getValue()); + editor.updateImage(new ProfileImage(avatarBytes, 30, 30, "")); + } + } + } + + if (needsHeader()) { + createHeaderLayout(composite, toolkit); + } + + toolkit.paintBordersFor(composite); + + setControl(composite); + } +} diff --git a/mylyn.tasks/org.eclipse.mylyn.tasks.ui/src/org/eclipse/mylyn/internal/tasks/ui/editors/TaskEditorCommentPart.java b/mylyn.tasks/org.eclipse.mylyn.tasks.ui/src/org/eclipse/mylyn/internal/tasks/ui/editors/TaskEditorCommentPart.java index 6d84637401..2289bbf510 100644 --- a/mylyn.tasks/org.eclipse.mylyn.tasks.ui/src/org/eclipse/mylyn/internal/tasks/ui/editors/TaskEditorCommentPart.java +++ b/mylyn.tasks/org.eclipse.mylyn.tasks.ui/src/org/eclipse/mylyn/internal/tasks/ui/editors/TaskEditorCommentPart.java @@ -586,14 +586,14 @@ public ReplyToCommentActionWithMenu(CommentViewer commentViewer) { } public Menu getMenu(Control parent) { - currentViewer = getCommentViewer(); - selectionProvider.setSelection(new StructuredSelection(currentViewer.getTaskComment())); - return commentMenu; + setCurrentViewer(getCommentViewer()); + selectionProvider.setSelection(new StructuredSelection(getCurrentViewer().getTaskComment())); + return getCommentMenu(); } public Menu getMenu(Menu parent) { selectionProvider.setSelection(new StructuredSelection(getCommentViewer().getTaskComment())); - return commentMenu; + return getCommentMenu(); } } @@ -642,6 +642,22 @@ protected boolean hasIncomingChanges(ITaskComment taskComment) { setPartName(Messages.TaskEditorCommentPart_Comments); } + public SelectionProviderAdapter getSelectionProvider() { + return selectionProvider; + } + + public Menu getCommentMenu() { + return commentMenu; + } + + public CommentViewer getCurrentViewer() { + return currentViewer; + } + + public void setCurrentViewer(CommentViewer currentViewer) { + this.currentViewer = currentViewer; + } + protected void addActionsToToolbarButton(ToolBarManager toolBarManager, TaskComment taskComment, CommentViewer commentViewer) { ReplyToCommentAction replyAction = new ReplyToCommentActionWithMenu(commentViewer); @@ -696,14 +712,14 @@ public void menuAboutToShow(IMenuManager manager) { // get comment and add reply action as first item in the menu ISelection selection = selectionProvider.getSelection(); if (selection instanceof IStructuredSelection && !selection.isEmpty()) { - ReplyToCommentAction replyAction = new ReplyToCommentAction(currentViewer); + ReplyToCommentAction replyAction = new ReplyToCommentAction(getCurrentViewer()); manager.add(replyAction); } actionGroup.setContext(new ActionContext(selectionProvider.getSelection())); actionGroup.fillContextMenu(manager); - if (currentViewer != null && currentViewer.getEditor() instanceof RichTextAttributeEditor) { - RichTextAttributeEditor editor = (RichTextAttributeEditor) currentViewer.getEditor(); + if (getCurrentViewer() != null && getCurrentViewer().getEditor() instanceof RichTextAttributeEditor) { + RichTextAttributeEditor editor = (RichTextAttributeEditor) getCurrentViewer().getEditor(); if (editor.getViewSourceAction().isEnabled()) { manager.add(new Separator("planning")); //$NON-NLS-1$ manager.add(editor.getViewSourceAction()); diff --git a/mylyn.tasks/org.eclipse.mylyn.tasks.ui/src/org/eclipse/mylyn/internal/tasks/ui/editors/TaskEditorSummaryPart.java b/mylyn.tasks/org.eclipse.mylyn.tasks.ui/src/org/eclipse/mylyn/internal/tasks/ui/editors/TaskEditorSummaryPart.java index 1485494572..a81ba6a3f1 100644 --- a/mylyn.tasks/org.eclipse.mylyn.tasks.ui/src/org/eclipse/mylyn/internal/tasks/ui/editors/TaskEditorSummaryPart.java +++ b/mylyn.tasks/org.eclipse.mylyn.tasks.ui/src/org/eclipse/mylyn/internal/tasks/ui/editors/TaskEditorSummaryPart.java @@ -1,10 +1,10 @@ /******************************************************************************* * Copyright (c) 2004, 2013 Tasktop Technologies and others. - * + * * This program and the accompanying materials are made available under the * terms of the Eclipse Public License v. 2.0 which is available at * https://www.eclipse.org/legal/epl-2.0 - * + * * SPDX-License-Identifier: EPL-2.0 * * Contributors: @@ -35,6 +35,8 @@ import org.eclipse.swt.widgets.Label; import org.eclipse.ui.forms.widgets.FormToolkit; +import com.google.common.base.Strings; + /** * @author Raphael Ackermann * @author Steffen Pingel @@ -42,7 +44,7 @@ */ public class TaskEditorSummaryPart extends AbstractTaskEditorPart { - private AbstractAttributeEditor summaryEditor; + protected AbstractAttributeEditor summaryEditor; public TaskEditorSummaryPart() { setPartName(Messages.TaskEditorSummaryPart_Summary); @@ -118,7 +120,7 @@ private boolean isAttribute(TaskAttribute attribute, String id) { .mapToRepositoryKey(attribute.getParentAttribute(), id)); } - private void addSummaryText(Composite composite, final FormToolkit toolkit) { + protected void addSummaryText(Composite composite, final FormToolkit toolkit) { TaskAttribute summaryAttrib = getTaskData().getRoot().getMappedAttribute(TaskAttribute.SUMMARY); summaryEditor = createAttributeEditor(summaryAttrib); if (summaryEditor != null) { @@ -165,7 +167,7 @@ public void createControl(Composite parent, FormToolkit toolkit) { final Control priorityEditor = addPriorityAttributeWithIcon(composite, toolkit, priorityAttribute, false); if (priorityEditor != null) { GridDataFactory.fillDefaults().align(SWT.CENTER, SWT.CENTER).span(1, 2).applyTo(priorityEditor); - // forward focus to the summary editor + // forward focus to the summary editor priorityEditor.addFocusListener(new FocusAdapter() { @Override public void focusGained(FocusEvent e) { @@ -185,7 +187,7 @@ public void focusGained(FocusEvent e) { getModel().getTaskRepository().getProperty(TaskEditorExtensions.REPOSITORY_PROPERTY_AVATAR_SUPPORT))) { TaskAttribute userAssignedAttribute = getTaskData().getRoot() .getMappedAttribute(TaskAttribute.USER_ASSIGNED); - if (userAssignedAttribute != null) { + if (userAssignedAttribute != null && !Strings.isNullOrEmpty(userAssignedAttribute.getValue())) { UserAttributeEditor editor = new UserAttributeEditor(getModel(), userAssignedAttribute); editor.createControl(composite, toolkit); GridDataFactory.fillDefaults() diff --git a/mylyn.tasks/org.eclipse.mylyn.tasks.ui/src/org/eclipse/mylyn/internal/tasks/ui/editors/UserAttributeEditor.java b/mylyn.tasks/org.eclipse.mylyn.tasks.ui/src/org/eclipse/mylyn/internal/tasks/ui/editors/UserAttributeEditor.java index a16a51cd9c..be4af535ad 100644 --- a/mylyn.tasks/org.eclipse.mylyn.tasks.ui/src/org/eclipse/mylyn/internal/tasks/ui/editors/UserAttributeEditor.java +++ b/mylyn.tasks/org.eclipse.mylyn.tasks.ui/src/org/eclipse/mylyn/internal/tasks/ui/editors/UserAttributeEditor.java @@ -1,10 +1,10 @@ /******************************************************************************* * Copyright (c) 2011 Tasktop Technologies and others. - * + * * This program and the accompanying materials are made available under the * terms of the Eclipse Public License v. 2.0 which is available at * https://www.eclipse.org/legal/epl-2.0 - * + * * SPDX-License-Identifier: EPL-2.0 * * Contributors: @@ -84,7 +84,7 @@ public UserAttributeEditor(TaskDataModel manager, TaskAttribute taskAttribute, i this.imageSize = imageSize; } - protected Image updateImage(IProfileImage profileImage) { + public Image updateImage(IProfileImage profileImage) { if (image != null) { image.dispose(); } diff --git a/org.eclipse.mylyn.releng/oomph/Mylyn.setup b/org.eclipse.mylyn.releng/oomph/Mylyn.setup index b692a818bb..3316756612 100755 --- a/org.eclipse.mylyn.releng/oomph/Mylyn.setup +++ b/org.eclipse.mylyn.releng/oomph/Mylyn.setup @@ -269,6 +269,13 @@ project="org.eclipse.mylyn-aggregator" relativePathPattern="mylyn.tasks/connectors/bugzilla-rest/.*"/> + + + Date: Mon, 24 Jul 2023 06:00:55 +0200 Subject: [PATCH 09/13] Integrate first round of feedback --- .../META-INF/MANIFEST.MF | 39 ++-- .../build.properties | 7 + .../org.eclipse.mylyn.gitlab.core/plugin.xml | 2 +- .../eclipse/mylyn/gitlab/core/Duration.java | 14 +- .../gitlab/core/GitlabConfiguration.java | 20 +- .../gitlab/core/GitlabCoreActivator.java | 4 +- .../mylyn/gitlab/core/GitlabException.java | 19 +- .../mylyn/gitlab/core/GitlabOperation.java | 129 ------------- .../gitlab/core/GitlabTaskCommentMapper.java | 7 - .../gitlab/core/GitlabTaskDataHandler.java | 110 ----------- .../mylyn/gitlab/core/GitlabTaskSchema.java | 133 ------------- .../gitlab/core/GitlabJSonArrayOperation.java | 31 ++- .../gitlab/core/GitlabNewTaskSchema.java | 39 ++-- .../internal/gitlab/core/GitlabOperation.java | 133 +++++++++++++ .../gitlab/core/GitlabPostOperation.java | 2 +- .../gitlab/core/GitlabPutOperation.java | 10 +- .../core/GitlabRepositoryConnector.java | 18 +- .../gitlab/core/GitlabRestClient.java | 31 +-- .../core/GitlabTaskAttributeMapper.java | 53 ++---- .../gitlab/core/GitlabTaskDataHandler.java | 113 +++++++++++ .../gitlab/core/GitlabTaskSchema.java | 129 +++++++++++++ .../build.properties | 10 +- .../feature.properties | 178 ++++++++++++++++++ .../feature.xml | 28 ++- .../org.eclipse.core.resources.prefs | 2 + .../build.properties | 9 + .../feature.properties | 178 ++++++++++++++++++ .../feature.xml | 51 +++++ .../META-INF/MANIFEST.MF | 20 +- .../build.properties | 7 + .../icons/eview16/gitlab-icon.png | Bin 1019 -> 0 bytes .../icons/eview16/gitlab-icon38.png | Bin 1130 -> 0 bytes .../icons/eview16/gitlab-overlay.png | Bin 758 -> 1230 bytes .../icons/eview16/gitlab-overlay@2x.png | Bin 0 -> 1298 bytes .../icons/obj16/gitlab.png | Bin 0 -> 1298 bytes .../icons/obj16/gitlab@2x.png | Bin 0 -> 2023 bytes .../org.eclipse.mylyn.gitlab.ui/plugin.xml | 6 +- .../eclipse/mylyn/gitlab/ui/GitlabImages.java | 91 +++------ .../mylyn/gitlab/ui/GitlabUiActivator.java | 12 ++ .../gitlab/ui/GitlabConnectorUI.java | 9 +- .../gitlab/ui/GitlabQuerySchemaPage.java | 16 +- .../gitlab/ui/GitlabQueryTypeWizardPage.java | 2 +- .../ui/GitlabRepositorySettingsPage.java | 16 +- .../ui/GitlabSearchQueryPageSchema.java | 18 +- .../ui/GitlabTaskEditorCommentPart.java | 19 +- .../gitlab/ui/GitlabTaskEditorPage.java | 2 +- .../ui/GitlabTaskEditorPageFactory.java | 2 +- .../ui/GitlabTaskEditorSummaryPart.java | 31 +-- org.eclipse.mylyn-site/category.xml | 14 +- 49 files changed, 1128 insertions(+), 636 deletions(-) delete mode 100644 mylyn.tasks/connectors/gitlab/org.eclipse.mylyn.gitlab.core/src/org/eclipse/mylyn/gitlab/core/GitlabOperation.java delete mode 100644 mylyn.tasks/connectors/gitlab/org.eclipse.mylyn.gitlab.core/src/org/eclipse/mylyn/gitlab/core/GitlabTaskCommentMapper.java delete mode 100644 mylyn.tasks/connectors/gitlab/org.eclipse.mylyn.gitlab.core/src/org/eclipse/mylyn/gitlab/core/GitlabTaskDataHandler.java delete mode 100644 mylyn.tasks/connectors/gitlab/org.eclipse.mylyn.gitlab.core/src/org/eclipse/mylyn/gitlab/core/GitlabTaskSchema.java rename mylyn.tasks/connectors/gitlab/org.eclipse.mylyn.gitlab.core/src/org/eclipse/mylyn/{ => internal}/gitlab/core/GitlabJSonArrayOperation.java (60%) rename mylyn.tasks/connectors/gitlab/org.eclipse.mylyn.gitlab.core/src/org/eclipse/mylyn/{ => internal}/gitlab/core/GitlabNewTaskSchema.java (63%) create mode 100644 mylyn.tasks/connectors/gitlab/org.eclipse.mylyn.gitlab.core/src/org/eclipse/mylyn/internal/gitlab/core/GitlabOperation.java rename mylyn.tasks/connectors/gitlab/org.eclipse.mylyn.gitlab.core/src/org/eclipse/mylyn/{ => internal}/gitlab/core/GitlabPostOperation.java (95%) rename mylyn.tasks/connectors/gitlab/org.eclipse.mylyn.gitlab.core/src/org/eclipse/mylyn/{ => internal}/gitlab/core/GitlabPutOperation.java (80%) rename mylyn.tasks/connectors/gitlab/org.eclipse.mylyn.gitlab.core/src/org/eclipse/mylyn/{ => internal}/gitlab/core/GitlabRepositoryConnector.java (95%) rename mylyn.tasks/connectors/gitlab/org.eclipse.mylyn.gitlab.core/src/org/eclipse/mylyn/{ => internal}/gitlab/core/GitlabRestClient.java (96%) rename mylyn.tasks/connectors/gitlab/org.eclipse.mylyn.gitlab.core/src/org/eclipse/mylyn/{ => internal}/gitlab/core/GitlabTaskAttributeMapper.java (52%) create mode 100644 mylyn.tasks/connectors/gitlab/org.eclipse.mylyn.gitlab.core/src/org/eclipse/mylyn/internal/gitlab/core/GitlabTaskDataHandler.java create mode 100644 mylyn.tasks/connectors/gitlab/org.eclipse.mylyn.gitlab.core/src/org/eclipse/mylyn/internal/gitlab/core/GitlabTaskSchema.java create mode 100644 mylyn.tasks/connectors/gitlab/org.eclipse.mylyn.gitlab.feature/feature.properties create mode 100644 mylyn.tasks/connectors/gitlab/org.eclipse.mylyn.gitlab.source.feature/.settings/org.eclipse.core.resources.prefs create mode 100644 mylyn.tasks/connectors/gitlab/org.eclipse.mylyn.gitlab.source.feature/build.properties create mode 100644 mylyn.tasks/connectors/gitlab/org.eclipse.mylyn.gitlab.source.feature/feature.properties create mode 100644 mylyn.tasks/connectors/gitlab/org.eclipse.mylyn.gitlab.source.feature/feature.xml delete mode 100644 mylyn.tasks/connectors/gitlab/org.eclipse.mylyn.gitlab.ui/icons/eview16/gitlab-icon.png delete mode 100644 mylyn.tasks/connectors/gitlab/org.eclipse.mylyn.gitlab.ui/icons/eview16/gitlab-icon38.png create mode 100644 mylyn.tasks/connectors/gitlab/org.eclipse.mylyn.gitlab.ui/icons/eview16/gitlab-overlay@2x.png create mode 100644 mylyn.tasks/connectors/gitlab/org.eclipse.mylyn.gitlab.ui/icons/obj16/gitlab.png create mode 100644 mylyn.tasks/connectors/gitlab/org.eclipse.mylyn.gitlab.ui/icons/obj16/gitlab@2x.png rename mylyn.tasks/connectors/gitlab/org.eclipse.mylyn.gitlab.ui/src/org/eclipse/mylyn/{ => internal}/gitlab/ui/GitlabConnectorUI.java (93%) rename mylyn.tasks/connectors/gitlab/org.eclipse.mylyn.gitlab.ui/src/org/eclipse/mylyn/{ => internal}/gitlab/ui/GitlabQuerySchemaPage.java (79%) rename mylyn.tasks/connectors/gitlab/org.eclipse.mylyn.gitlab.ui/src/org/eclipse/mylyn/{ => internal}/gitlab/ui/GitlabQueryTypeWizardPage.java (98%) rename mylyn.tasks/connectors/gitlab/org.eclipse.mylyn.gitlab.ui/src/org/eclipse/mylyn/{ => internal}/gitlab/ui/GitlabRepositorySettingsPage.java (94%) rename mylyn.tasks/connectors/gitlab/org.eclipse.mylyn.gitlab.ui/src/org/eclipse/mylyn/{ => internal}/gitlab/ui/GitlabSearchQueryPageSchema.java (55%) rename mylyn.tasks/connectors/gitlab/org.eclipse.mylyn.gitlab.ui/src/org/eclipse/mylyn/{ => internal}/gitlab/ui/GitlabTaskEditorCommentPart.java (95%) rename mylyn.tasks/connectors/gitlab/org.eclipse.mylyn.gitlab.ui/src/org/eclipse/mylyn/{ => internal}/gitlab/ui/GitlabTaskEditorPage.java (98%) rename mylyn.tasks/connectors/gitlab/org.eclipse.mylyn.gitlab.ui/src/org/eclipse/mylyn/{ => internal}/gitlab/ui/GitlabTaskEditorPageFactory.java (97%) rename mylyn.tasks/connectors/gitlab/org.eclipse.mylyn.gitlab.ui/src/org/eclipse/mylyn/{ => internal}/gitlab/ui/GitlabTaskEditorSummaryPart.java (75%) diff --git a/mylyn.tasks/connectors/gitlab/org.eclipse.mylyn.gitlab.core/META-INF/MANIFEST.MF b/mylyn.tasks/connectors/gitlab/org.eclipse.mylyn.gitlab.core/META-INF/MANIFEST.MF index 90ea3bab57..5d612a2870 100644 --- a/mylyn.tasks/connectors/gitlab/org.eclipse.mylyn.gitlab.core/META-INF/MANIFEST.MF +++ b/mylyn.tasks/connectors/gitlab/org.eclipse.mylyn.gitlab.core/META-INF/MANIFEST.MF @@ -3,21 +3,36 @@ Bundle-ManifestVersion: 2 Bundle-Name: Gitlab Connector Core Bundle-SymbolicName: org.eclipse.mylyn.gitlab.core;singleton:=true Bundle-Version: 4.0.0.qualifier -Export-Package: org.eclipse.mylyn.gitlab.core +Export-Package: org.eclipse.mylyn.gitlab.core, + org.eclipse.mylyn.internal.gitlab.core;x-internal:=true +Import-Package: com.google.common.base;version="31.1.0", + com.google.common.cache;version="31.1.0", + com.google.common.collect;version="31.1.0", + com.google.common.util.concurrent;version="31.1.0", + com.google.gson;version="2.10.1", + com.google.gson.reflect;version="2.10.1", + com.google.gson.stream;version="2.10.1", + org.apache.http;version="4.4.16", + org.apache.http.client;version="4.5.13", + org.apache.http.client.cache;version="4.5.13", + org.apache.http.client.config;version="4.5.13", + org.apache.http.client.entity;version="4.5.13", + org.apache.http.client.fluent;version="4.5.13", + org.apache.http.client.methods;version="4.5.13", + org.apache.http.client.params;version="4.5.13", + org.apache.http.client.protocol;version="4.5.13", + org.apache.http.client.utils;version="4.5.13", + org.apache.http.entity;version="4.4.16", + org.apache.http.message;version="4.4.16" Bundle-Activator: org.eclipse.mylyn.gitlab.core.GitlabCoreActivator -Require-Bundle: org.eclipse.ui, - org.eclipse.core.runtime, +Require-Bundle: org.eclipse.core.runtime, + org.eclipse.equinox.security;bundle-version="1.3.1000", org.eclipse.jdt.annotation, - org.eclipse.mylyn.tasks.core;bundle-version="4.0.0", - org.eclipse.mylyn.commons.repositories.http.core;bundle-version="4.0.0", - org.eclipse.mylyn.commons.repositories.core;bundle-version="4.0.0", - org.eclipse.mylyn.commons.net;bundle-version="4.0.0", org.eclipse.mylyn.commons.core;bundle-version="4.0.0", - org.apache.httpcomponents.httpclient;bundle-version="4.5.13", - org.apache.httpcomponents.httpcore;bundle-version="4.4.15", - com.google.gson;bundle-version="2.9.1", - com.google.guava;bundle-version="21.0.0", - org.eclipse.equinox.security;bundle-version="1.3.1000" + org.eclipse.mylyn.commons.net;bundle-version="4.0.0", + org.eclipse.mylyn.commons.repositories.core;bundle-version="4.0.0", + org.eclipse.mylyn.commons.repositories.http.core;bundle-version="4.0.0", + org.eclipse.mylyn.tasks.core;bundle-version="4.0.0" Bundle-RequiredExecutionEnvironment: JavaSE-17 Automatic-Module-Name: org.eclipse.mylyn.gitlab.core Bundle-ActivationPolicy: lazy diff --git a/mylyn.tasks/connectors/gitlab/org.eclipse.mylyn.gitlab.core/build.properties b/mylyn.tasks/connectors/gitlab/org.eclipse.mylyn.gitlab.core/build.properties index 5b359b5b78..b86c9791a6 100644 --- a/mylyn.tasks/connectors/gitlab/org.eclipse.mylyn.gitlab.core/build.properties +++ b/mylyn.tasks/connectors/gitlab/org.eclipse.mylyn.gitlab.core/build.properties @@ -1,3 +1,10 @@ +############################################################################### +# Copyright (c) 2023 Frank Becker and others. +# All rights reserved. This program and the accompanying materials +# are made available under the terms of the Eclipse Public License v2.0 +# which accompanies this distribution, and is available at +# http://www.eclipse.org/legal/epl-v20.html +############################################################################### source.. = src/ output.. = bin/ bin.includes = META-INF/,\ diff --git a/mylyn.tasks/connectors/gitlab/org.eclipse.mylyn.gitlab.core/plugin.xml b/mylyn.tasks/connectors/gitlab/org.eclipse.mylyn.gitlab.core/plugin.xml index f4b994f1da..28cc426294 100644 --- a/mylyn.tasks/connectors/gitlab/org.eclipse.mylyn.gitlab.core/plugin.xml +++ b/mylyn.tasks/connectors/gitlab/org.eclipse.mylyn.gitlab.core/plugin.xml @@ -18,7 +18,7 @@ name="Gitlab Repository" point="org.eclipse.mylyn.tasks.core.repositories"> diff --git a/mylyn.tasks/connectors/gitlab/org.eclipse.mylyn.gitlab.core/src/org/eclipse/mylyn/gitlab/core/Duration.java b/mylyn.tasks/connectors/gitlab/org.eclipse.mylyn.gitlab.core/src/org/eclipse/mylyn/gitlab/core/Duration.java index ae62a52d33..1cae977b18 100644 --- a/mylyn.tasks/connectors/gitlab/org.eclipse.mylyn.gitlab.core/src/org/eclipse/mylyn/gitlab/core/Duration.java +++ b/mylyn.tasks/connectors/gitlab/org.eclipse.mylyn.gitlab.core/src/org/eclipse/mylyn/gitlab/core/Duration.java @@ -1,8 +1,20 @@ +/******************************************************************************* + * Copyright (c) 2023 Frank Becker and others. + * + * This program and the accompanying materials are made available under the + * terms of the Eclipse Public License v. 2.0 which is available at + * https://www.eclipse.org/legal/epl-2.0 + * + * SPDX-License-Identifier: EPL-2.0 + * + * Contributors: + * Frank Becker - initial API and implementation + *******************************************************************************/ package org.eclipse.mylyn.gitlab.core; import java.util.concurrent.TimeUnit; -public class Duration { +public final class Duration { final TimeUnit unit; final long value; diff --git a/mylyn.tasks/connectors/gitlab/org.eclipse.mylyn.gitlab.core/src/org/eclipse/mylyn/gitlab/core/GitlabConfiguration.java b/mylyn.tasks/connectors/gitlab/org.eclipse.mylyn.gitlab.core/src/org/eclipse/mylyn/gitlab/core/GitlabConfiguration.java index 29386523e0..2dc8c2fce8 100644 --- a/mylyn.tasks/connectors/gitlab/org.eclipse.mylyn.gitlab.core/src/org/eclipse/mylyn/gitlab/core/GitlabConfiguration.java +++ b/mylyn.tasks/connectors/gitlab/org.eclipse.mylyn.gitlab.core/src/org/eclipse/mylyn/gitlab/core/GitlabConfiguration.java @@ -1,14 +1,28 @@ +/******************************************************************************* + * Copyright (c) 2023 Frank Becker and others. + * + * This program and the accompanying materials are made available under the + * terms of the Eclipse Public License v. 2.0 which is available at + * https://www.eclipse.org/legal/epl-2.0 + * + * SPDX-License-Identifier: EPL-2.0 + * + * Contributors: + * Frank Becker - initial API and implementation + *******************************************************************************/ package org.eclipse.mylyn.gitlab.core; import java.io.Serializable; import java.math.BigInteger; import java.util.ArrayList; import java.util.HashMap; +import java.util.List; import java.util.Map; import java.util.Optional; import java.util.Set; import org.eclipse.jdt.annotation.NonNull; +import org.eclipse.mylyn.internal.gitlab.core.GitlabTaskSchema; import org.eclipse.mylyn.tasks.core.data.TaskAttribute; import org.eclipse.mylyn.tasks.core.data.TaskData; import org.eclipse.mylyn.tasks.core.data.TaskOperation; @@ -16,7 +30,7 @@ import com.google.gson.JsonElement; import com.google.gson.JsonObject; -public class GitlabConfiguration implements Serializable { +public final class GitlabConfiguration implements Serializable { private static final long serialVersionUID = -6859757478504901423L; @@ -28,7 +42,7 @@ public class GitlabConfiguration implements Serializable { private Map projectIDsMap = new HashMap<>(); private ArrayList projects = new ArrayList<>(); private Map groupsDetailsMap = new HashMap<>(); - private ArrayList groups = new ArrayList<>(); + private List groups = new ArrayList(); public GitlabConfiguration(String repositoryURL) { this.repositoryURL = repositoryURL; @@ -84,7 +98,7 @@ public Set getGroupNames() { return groupsDetailsMap.keySet(); } - public ArrayList getGroups() { + public List getGroups() { return groups; } diff --git a/mylyn.tasks/connectors/gitlab/org.eclipse.mylyn.gitlab.core/src/org/eclipse/mylyn/gitlab/core/GitlabCoreActivator.java b/mylyn.tasks/connectors/gitlab/org.eclipse.mylyn.gitlab.core/src/org/eclipse/mylyn/gitlab/core/GitlabCoreActivator.java index af6a2a8c62..b316381768 100644 --- a/mylyn.tasks/connectors/gitlab/org.eclipse.mylyn.gitlab.core/src/org/eclipse/mylyn/gitlab/core/GitlabCoreActivator.java +++ b/mylyn.tasks/connectors/gitlab/org.eclipse.mylyn.gitlab.core/src/org/eclipse/mylyn/gitlab/core/GitlabCoreActivator.java @@ -13,13 +13,13 @@ package org.eclipse.mylyn.gitlab.core; -import org.eclipse.ui.plugin.AbstractUIPlugin; +import org.eclipse.core.runtime.Plugin; import org.osgi.framework.BundleContext; /** * The activator class controls the plug-in life cycle */ -public class GitlabCoreActivator extends AbstractUIPlugin { +public final class GitlabCoreActivator extends Plugin { // The plug-in ID public static final String PLUGIN_ID = "org.eclipse.mylyn.gitlab.core"; //$NON-NLS-1$ diff --git a/mylyn.tasks/connectors/gitlab/org.eclipse.mylyn.gitlab.core/src/org/eclipse/mylyn/gitlab/core/GitlabException.java b/mylyn.tasks/connectors/gitlab/org.eclipse.mylyn.gitlab.core/src/org/eclipse/mylyn/gitlab/core/GitlabException.java index b879e0994f..0b85098e94 100644 --- a/mylyn.tasks/connectors/gitlab/org.eclipse.mylyn.gitlab.core/src/org/eclipse/mylyn/gitlab/core/GitlabException.java +++ b/mylyn.tasks/connectors/gitlab/org.eclipse.mylyn.gitlab.core/src/org/eclipse/mylyn/gitlab/core/GitlabException.java @@ -13,23 +13,20 @@ package org.eclipse.mylyn.gitlab.core; -public class GitlabException extends Exception { +import org.eclipse.core.runtime.CoreException; +import org.eclipse.core.runtime.IStatus; - private static final long serialVersionUID = 4915767534271733762L; +public class GitlabException extends CoreException { - public GitlabException() { - } + private static final long serialVersionUID = -5584532559872640080L; - public GitlabException(String message) { - super(message); + public GitlabException(IStatus status) { + super(status); } - public GitlabException(Throwable cause) { - super(cause.getMessage(), cause); - } - public GitlabException(String message, Throwable cause) { - super(message, cause); + public GitlabException(CoreException exception) { + super(exception.getStatus()); } } diff --git a/mylyn.tasks/connectors/gitlab/org.eclipse.mylyn.gitlab.core/src/org/eclipse/mylyn/gitlab/core/GitlabOperation.java b/mylyn.tasks/connectors/gitlab/org.eclipse.mylyn.gitlab.core/src/org/eclipse/mylyn/gitlab/core/GitlabOperation.java deleted file mode 100644 index 826f83b2ce..0000000000 --- a/mylyn.tasks/connectors/gitlab/org.eclipse.mylyn.gitlab.core/src/org/eclipse/mylyn/gitlab/core/GitlabOperation.java +++ /dev/null @@ -1,129 +0,0 @@ -/******************************************************************************* - * Copyright (c) 2023 Frank Becker and others. - * - * This program and the accompanying materials are made available under the - * terms of the Eclipse Public License v. 2.0 which is available at - * https://www.eclipse.org/legal/epl-2.0 - * - * SPDX-License-Identifier: EPL-2.0 - * - * Contributors: - * Frank Becker - initial API and implementation - *******************************************************************************/ - -package org.eclipse.mylyn.gitlab.core; - -import java.io.BufferedInputStream; -import java.io.IOException; -import java.io.InputStreamReader; - -import org.apache.http.Header; -import org.apache.http.HttpStatus; -import org.apache.http.client.methods.HttpGet; -import org.apache.http.client.methods.HttpRequestBase; -import org.eclipse.mylyn.commons.core.operations.IOperationMonitor; -import org.eclipse.mylyn.commons.repositories.http.core.CommonHttpClient; -import org.eclipse.mylyn.commons.repositories.http.core.CommonHttpOperation; -import org.eclipse.mylyn.commons.repositories.http.core.CommonHttpResponse; -import org.eclipse.mylyn.commons.repositories.http.core.HttpUtil; -import org.eclipse.osgi.util.NLS; - -public abstract class GitlabOperation extends CommonHttpOperation { - - protected static final String ACCEPT = "Accept"; //$NON-NLS-1$ - - protected static final String CONTENT_TYPE = "Content-Type"; //$NON-NLS-1$ - - protected static final String APPLICATION_JSON = "application/json"; //$NON-NLS-1$ - - protected static final String TEXT_XML_CHARSET_UTF_8 = "text/xml; charset=UTF-8"; //$NON-NLS-1$ - - private final String urlSuffix; - - public GitlabOperation(CommonHttpClient client, String urlSuffix) { - super(client); - this.urlSuffix = urlSuffix; - } - - public T run(IOperationMonitor monitor) throws GitlabException { - try { - return execute(monitor); - } catch (IOException e) { - throw new GitlabException(e); - } - } - - protected abstract HttpRequestBase createHttpRequestBase(String url); - - protected abstract T parseFromJson(InputStreamReader in) throws GitlabException; - - protected HttpRequestBase createHttpRequestBase() { - HttpRequestBase request = createHttpRequestBase(createHttpRequestURL()); - return request; - } - - protected void addHttpRequestEntities(HttpRequestBase request) throws GitlabException { - request.setHeader(ACCEPT, APPLICATION_JSON); - String accessToken = (String) getClient().getAttribute(GitlabRestClient.AUTHORIZATION_HEADER); - request.setHeader("Authorization", accessToken); - } - - protected T doProcess(CommonHttpResponse response, IOperationMonitor monitor) throws IOException, GitlabException { - try (BufferedInputStream is = new BufferedInputStream(response.getResponseEntityAsStream())) { - InputStreamReader in = new InputStreamReader(is); - return parseFromJson(in); - } - } - - protected T processAndRelease(CommonHttpResponse response, IOperationMonitor monitor) - throws IOException, GitlabException { - try { - doValidate(response, monitor); - return doProcess(response, monitor); - } finally { - response.release(); - } - } - - protected void doValidate(CommonHttpResponse response, IOperationMonitor monitor) - throws IOException, GitlabException { - validate(response, HttpStatus.SC_OK, monitor); - } - - protected void validate(CommonHttpResponse response, int expected, IOperationMonitor monitor) - throws GitlabException { - int statusCode = response.getStatusCode(); - if (statusCode != expected /*&& statusCode != HttpStatus.SC_BAD_REQUEST*/) { - if (statusCode == HttpStatus.SC_NOT_FOUND) { - throw new GitlabException( - NLS.bind("Requested resource ''{0}'' does not exist", response.getRequestPath())); - } - throw new GitlabException(NLS.bind("Unexpected response from Gitlab REST server for ''{0}'': {1}", - response.getRequestPath(), HttpUtil.getStatusText(statusCode))); - } - } - - protected String baseUrl() { - String url = getClient().getLocation().getUrl(); - if (!url.endsWith(GitlabCoreActivator.API_VERSION)) { - url += GitlabCoreActivator.API_VERSION; - } - return url; - } - - protected T execute(IOperationMonitor monitor) throws IOException, GitlabException { - HttpRequestBase request = createHttpRequestBase(); - addHttpRequestEntities(request); - CommonHttpResponse response = execute(request, monitor); - return processAndRelease(response, monitor); - } - - protected String getUrlSuffix() { - return urlSuffix; - } - - protected String createHttpRequestURL() { - String urlSuffix = getUrlSuffix(); - return baseUrl() + urlSuffix; - } -} diff --git a/mylyn.tasks/connectors/gitlab/org.eclipse.mylyn.gitlab.core/src/org/eclipse/mylyn/gitlab/core/GitlabTaskCommentMapper.java b/mylyn.tasks/connectors/gitlab/org.eclipse.mylyn.gitlab.core/src/org/eclipse/mylyn/gitlab/core/GitlabTaskCommentMapper.java deleted file mode 100644 index 98d321d4d3..0000000000 --- a/mylyn.tasks/connectors/gitlab/org.eclipse.mylyn.gitlab.core/src/org/eclipse/mylyn/gitlab/core/GitlabTaskCommentMapper.java +++ /dev/null @@ -1,7 +0,0 @@ -package org.eclipse.mylyn.gitlab.core; - -import org.eclipse.mylyn.tasks.core.data.TaskCommentMapper; - -public class GitlabTaskCommentMapper extends TaskCommentMapper { - -} diff --git a/mylyn.tasks/connectors/gitlab/org.eclipse.mylyn.gitlab.core/src/org/eclipse/mylyn/gitlab/core/GitlabTaskDataHandler.java b/mylyn.tasks/connectors/gitlab/org.eclipse.mylyn.gitlab.core/src/org/eclipse/mylyn/gitlab/core/GitlabTaskDataHandler.java deleted file mode 100644 index 09bb68828f..0000000000 --- a/mylyn.tasks/connectors/gitlab/org.eclipse.mylyn.gitlab.core/src/org/eclipse/mylyn/gitlab/core/GitlabTaskDataHandler.java +++ /dev/null @@ -1,110 +0,0 @@ -/******************************************************************************* - * Copyright (c) 2023 Frank Becker and others. - * - * This program and the accompanying materials are made available under the - * terms of the Eclipse Public License v. 2.0 which is available at - * https://www.eclipse.org/legal/epl-2.0 - * - * SPDX-License-Identifier: EPL-2.0 - * - * Contributors: - * Frank Becker - initial API and implementation - *******************************************************************************/ - -package org.eclipse.mylyn.gitlab.core; - -import java.util.Set; - -import org.eclipse.core.runtime.CoreException; -import org.eclipse.core.runtime.IProgressMonitor; -import org.eclipse.core.runtime.IStatus; -import org.eclipse.core.runtime.Status; -import org.eclipse.mylyn.commons.core.operations.IOperationMonitor; -import org.eclipse.mylyn.commons.core.operations.IOperationMonitor.OperationFlag; -import org.eclipse.mylyn.commons.core.operations.OperationUtil; -import org.eclipse.mylyn.commons.net.Policy; -import org.eclipse.mylyn.tasks.core.ITaskMapping; -import org.eclipse.mylyn.tasks.core.RepositoryResponse; -import org.eclipse.mylyn.tasks.core.TaskRepository; -import org.eclipse.mylyn.tasks.core.data.AbstractTaskDataHandler; -import org.eclipse.mylyn.tasks.core.data.TaskAttribute; -import org.eclipse.mylyn.tasks.core.data.TaskAttributeMapper; -import org.eclipse.mylyn.tasks.core.data.TaskData; -import org.eclipse.mylyn.tasks.core.data.TaskDataCollector; - -public class GitlabTaskDataHandler extends AbstractTaskDataHandler { - protected final GitlabRepositoryConnector connector; - - public GitlabTaskDataHandler(GitlabRepositoryConnector connector) { - super(); - this.connector = connector; - } - - @Override - public RepositoryResponse postTaskData(TaskRepository repository, TaskData taskData, - Set oldAttributes, IProgressMonitor monitor) throws CoreException { - monitor = Policy.monitorFor(monitor); - try { - monitor.beginTask("Submitting_task", IProgressMonitor.UNKNOWN); - GitlabRestClient client = connector.getClient(repository); - IOperationMonitor progress = OperationUtil.convert(monitor, "post taskdata", 3); - try { - return client.postTaskData(taskData, oldAttributes, progress); - } catch (GitlabException e) { - throw new CoreException(new Status(IStatus.ERROR, GitlabCoreActivator.PLUGIN_ID, 2, - "Error post taskdata.\n\n" + e.getMessage(), e)); - } - } finally { - monitor.done(); - } - } - - @Override - public boolean initializeTaskData(TaskRepository repository, TaskData data, ITaskMapping initializationData, - IProgressMonitor monitor) throws CoreException { - // Note: setting current version to latest assumes the data arriving - // here is either for a new task or is - // fresh from the repository (not locally stored data that may not have - // been migrated). - data.setVersion("0"); //$NON-NLS-1$ - if (data.isNew()) { - GitlabNewTaskSchema.getDefault().initialize(data); - } else { - GitlabTaskSchema.getDefault().initialize(data); - } - if (initializationData != null) { - connector.getTaskMapping(data).merge(initializationData); - } - GitlabConfiguration config = connector.getRepositoryConfiguration(repository); - if (config != null) { - config.updateProductOptions(data); - } - return true; - } - - @Override - public TaskAttributeMapper getAttributeMapper(TaskRepository repository) { - return new GitlabTaskAttributeMapper(repository, connector); - } - - @Override - public void getMultiTaskData(final TaskRepository repository, Set taskIds, - final TaskDataCollector collector, IProgressMonitor monitor) throws CoreException { - monitor = Policy.monitorFor(monitor); - try { - monitor.beginTask("retrive_task", IProgressMonitor.UNKNOWN); - GitlabRestClient client = connector.getClient(repository); - try { - IOperationMonitor progress = OperationUtil.convert(monitor, "post taskdata", 3); - progress.addFlag(OperationFlag.BACKGROUND); - client.getTaskData(taskIds, repository, collector, progress); - } catch (GitlabException e) { - throw new CoreException(new Status(IStatus.ERROR, GitlabCoreActivator.PLUGIN_ID, 2, - "Error get taskdata.\n\n" + e.getMessage(), e)); - } - } finally { - monitor.done(); - } - } - -} diff --git a/mylyn.tasks/connectors/gitlab/org.eclipse.mylyn.gitlab.core/src/org/eclipse/mylyn/gitlab/core/GitlabTaskSchema.java b/mylyn.tasks/connectors/gitlab/org.eclipse.mylyn.gitlab.core/src/org/eclipse/mylyn/gitlab/core/GitlabTaskSchema.java deleted file mode 100644 index 552302b329..0000000000 --- a/mylyn.tasks/connectors/gitlab/org.eclipse.mylyn.gitlab.core/src/org/eclipse/mylyn/gitlab/core/GitlabTaskSchema.java +++ /dev/null @@ -1,133 +0,0 @@ -/******************************************************************************* - * Copyright (c) 2023 Frank Becker and others. - * - * This program and the accompanying materials are made available under the - * terms of the Eclipse Public License v. 2.0 which is available at - * https://www.eclipse.org/legal/epl-2.0 - * - * SPDX-License-Identifier: EPL-2.0 - * - * Contributors: - * Frank Becker - initial API and implementation - *******************************************************************************/ - -package org.eclipse.mylyn.gitlab.core; - -import org.eclipse.mylyn.tasks.core.data.AbstractTaskSchema; -import org.eclipse.mylyn.tasks.core.data.DefaultTaskSchema; -import org.eclipse.mylyn.tasks.core.data.TaskAttribute; -import org.eclipse.mylyn.tasks.core.data.AbstractTaskSchema.Field; -import org.eclipse.mylyn.tasks.core.data.AbstractTaskSchema.Flag; - -import com.google.common.collect.ImmutableMap; - -public class GitlabTaskSchema extends GitlabNewTaskSchema { - - private final DefaultTaskSchema parent = DefaultTaskSchema.getInstance(); - - private static final GitlabTaskSchema instance = new GitlabTaskSchema(); - - public static GitlabTaskSchema getDefault() { - return instance; - } - - public final Field CREATED = inheritFrom(parent.DATE_CREATION).create(); - - public final Field UPDATED = inheritFrom(parent.DATE_MODIFICATION).create(); - - public final Field COMPLETED = inheritFrom(parent.DATE_COMPLETION).create(); - - public final Field AUTHOR = inheritFrom(parent.USER_REPORTER).create(); - - public final Field TASK_KEY = inheritFrom(parent.TASK_KEY).create(); - - public final Field URL = inheritFrom(parent.TASK_URL).addFlags(Flag.ATTRIBUTE).create(); - - public final Field USER_NOTES_COUNT = createField("user_notes_count", "User Notes Count", - TaskAttribute.TYPE_INTEGER, Flag.ATTRIBUTE); - - public final Field BLOCKING_ISSUE_COUNT = createField("blocking_issues_count", "Blocking Issue Count", - TaskAttribute.TYPE_INTEGER, Flag.ATTRIBUTE); - - public final Field MERGE_REQUEST_COUNT = createField("merge_requests_count", "Merge Request Count", - TaskAttribute.TYPE_INTEGER, Flag.ATTRIBUTE); - - public final Field UPVOTES = createField("upvotes", "Up Votes", TaskAttribute.TYPE_INTEGER, Flag.ATTRIBUTE); - - public final Field DOWNVOTES = createField("downvotes", "Down Notes", TaskAttribute.TYPE_INTEGER, Flag.ATTRIBUTE); - -// public final Field WEB_URL = createField("web_url", "WEB URL", TaskAttribute.TYPE_SHORT_TEXT, Flag.ATTRIBUTE); - - public final Field HAS_TASKS = createField("has_tasks", "has Tasks", TaskAttribute.TYPE_BOOLEAN, Flag.ATTRIBUTE); - - public final Field SUBSCRIBED = createField("subscribed", "subscribed", TaskAttribute.TYPE_BOOLEAN, Flag.ATTRIBUTE); - - public final Field CONFIDENTIAL = createField("confidential", "confidential", TaskAttribute.TYPE_BOOLEAN, - Flag.ATTRIBUTE); - - public final Field NEW_COMMENT = inheritFrom(parent.NEW_COMMENT).create(); - - public final Field DISCUSSION_LOCKED = createField("discussion_locked", "Discussion locked", - TaskAttribute.TYPE_BOOLEAN, Flag.ATTRIBUTE); - - public final Field IID = createField("iid", "interne ID", TaskAttribute.TYPE_SHORT_TEXT, Flag.ATTRIBUTE); - public final Field OPERATION = createField(TaskAttribute.OPERATION, "Operation", TaskAttribute.TYPE_OPERATION); - public final Field CLOSED_BY = createField("closed_by", "closed by", TaskAttribute.TYPE_PERSON, Flag.PEOPLE, //$NON-NLS-1$ - Flag.READ_ONLY); - - public final Field ASSIGNED_TO = inheritFrom(parent.USER_ASSIGNED).label("Assigned to").create(); - - public final Field TYPE = createField("type", "Type", TaskAttribute.TYPE_SHORT_TEXT, Flag.ATTRIBUTE); - - public final Field TASK_STATUS = createField("task_status", "Task Status", TaskAttribute.TYPE_SHORT_TEXT, - Flag.ATTRIBUTE); - - public final Field DUE_DATE = createField("due_date", "Due date", TaskAttribute.TYPE_DATE, Flag.ATTRIBUTE); - private static ImmutableMap json2AttributeMapper = new ImmutableMap.Builder() - .put("project_id", getDefault().PRODUCT.getKey()) //$NON-NLS-1$ - .put("description", getDefault().DESCRIPTION.getKey()) //$NON-NLS-1$ - .put("title", getDefault().SUMMARY.getKey()) //$NON-NLS-1$ - .put("state", getDefault().STATUS.getKey()) //$NON-NLS-1$ - .put("assignee", getDefault().ASSIGNED_TO.getKey()) //$NON-NLS-1$ - .put("author", getDefault().AUTHOR.getKey()) //$NON-NLS-1$ - .put("id", getDefault().TASK_KEY.getKey()) //$NON-NLS-1$ - .put("severity", getDefault().PRIORITY.getKey()) //$NON-NLS-1$ - .put("created_at", getDefault().CREATED.getKey()) //$NON-NLS-1$ - .put("updated_at", getDefault().UPDATED.getKey()) //$NON-NLS-1$ - .put("closed_at", getDefault().COMPLETED.getKey()) //$NON-NLS-1$ - .put("web_url", getDefault().URL.getKey()) //$NON-NLS-1$ - - .build(); - - private static ImmutableMap attribute2jsonMapper = new ImmutableMap.Builder() - .put(getDefault().PRODUCT.getKey(), "project_id") //$NON-NLS-1$ - .put(getDefault().DESCRIPTION.getKey(), "description") //$NON-NLS-1$ - .put(getDefault().SUMMARY.getKey(), "title") //$NON-NLS-1$ - .put(getDefault().STATUS.getKey(), "state") //$NON-NLS-1$ - .put(getDefault().ASSIGNED_TO.getKey(), "assignee") //$NON-NLS-1$ - .put(getDefault().AUTHOR.getKey(), "author") //$NON-NLS-1$ - .put(getDefault().TASK_KEY.getKey(), "id") //$NON-NLS-1$ - .put(getDefault().PRIORITY.getKey(), "severity") //$NON-NLS-1$ - .put(getDefault().CREATED.getKey(), "created_at") //$NON-NLS-1$ - .put(getDefault().UPDATED.getKey(), "updated_at") //$NON-NLS-1$ - .put(getDefault().COMPLETED.getKey(), "closed_at") //$NON-NLS-1$ - .put(getDefault().URL.getKey(), "web_url") //$NON-NLS-1$ - .build(); - - public static String getAttributeNameFromJsonName(String fieldName) { - String result = json2AttributeMapper.get(fieldName); - if (result == null) { - result = fieldName; - } - return result; - } - - public static String getJsonNameFromAttributeName(String attributeName) { - String result = attribute2jsonMapper.get(attributeName); - if (result == null) { - result = attributeName; - } - return result; - } - -} diff --git a/mylyn.tasks/connectors/gitlab/org.eclipse.mylyn.gitlab.core/src/org/eclipse/mylyn/gitlab/core/GitlabJSonArrayOperation.java b/mylyn.tasks/connectors/gitlab/org.eclipse.mylyn.gitlab.core/src/org/eclipse/mylyn/internal/gitlab/core/GitlabJSonArrayOperation.java similarity index 60% rename from mylyn.tasks/connectors/gitlab/org.eclipse.mylyn.gitlab.core/src/org/eclipse/mylyn/gitlab/core/GitlabJSonArrayOperation.java rename to mylyn.tasks/connectors/gitlab/org.eclipse.mylyn.gitlab.core/src/org/eclipse/mylyn/internal/gitlab/core/GitlabJSonArrayOperation.java index cf19645204..61e991d110 100644 --- a/mylyn.tasks/connectors/gitlab/org.eclipse.mylyn.gitlab.core/src/org/eclipse/mylyn/gitlab/core/GitlabJSonArrayOperation.java +++ b/mylyn.tasks/connectors/gitlab/org.eclipse.mylyn.gitlab.core/src/org/eclipse/mylyn/internal/gitlab/core/GitlabJSonArrayOperation.java @@ -1,8 +1,18 @@ -package org.eclipse.mylyn.gitlab.core; +/******************************************************************************* + * Copyright (c) 2023 Frank Becker and others. + * + * This program and the accompanying materials are made available under the + * terms of the Eclipse Public License v. 2.0 which is available at + * https://www.eclipse.org/legal/epl-2.0 + * + * SPDX-License-Identifier: EPL-2.0 + * + * Contributors: + * Frank Becker - initial API and implementation + *******************************************************************************/ +package org.eclipse.mylyn.internal.gitlab.core; import java.io.IOException; -import java.io.InputStreamReader; -import java.util.ArrayList; import org.apache.http.Header; import org.apache.http.client.methods.HttpGet; @@ -10,6 +20,7 @@ import org.eclipse.mylyn.commons.core.operations.IOperationMonitor; import org.eclipse.mylyn.commons.repositories.http.core.CommonHttpClient; import org.eclipse.mylyn.commons.repositories.http.core.CommonHttpResponse; +import org.eclipse.mylyn.gitlab.core.GitlabException; import com.google.gson.JsonArray; @@ -25,21 +36,21 @@ protected JsonArray execute(IOperationMonitor monitor) throws IOException, Gitla addHttpRequestEntities(request); CommonHttpResponse response = execute(request, monitor); result = processAndRelease(response, monitor); - Header[] lh = response.getResponse().getHeaders("Link"); - if (lh.length > 0) { + Header[] linkHeader = response.getResponse().getHeaders("Link"); + if (linkHeader.length > 0) { // System.out.print("Page Act: "); // System.out.println(response.getResponse().getHeaders("X-Page")[0].getValue()); // System.out.print("Page Count: "); // System.out.println(response.getResponse().getHeaders("X-Total-Pages")[0].getValue()); - Header lh1 = lh[0]; - for (String lh2 : lh1.getValue().split(", ")) { - String[] lh3 = lh2.split("; "); + Header firstLinkHeader = linkHeader[0]; + for (String linkHeaderEntry : firstLinkHeader.getValue().split(", ")) { + String[] linkHeaderElements = linkHeaderEntry.split("; "); // System.out.print(lh3[1]); // System.out.print(" "); // System.out.println(lh3[0]); - if ("rel=\"next\"".equals(lh3[1])) { + if ("rel=\"next\"".equals(linkHeaderElements[1])) { // System.out.println("process "+lh3[0].substring(1, lh3[0].length()-1)); - HttpRequestBase looprequest = new HttpGet(lh3[0].substring(1, lh3[0].length()-1)); + HttpRequestBase looprequest = new HttpGet(linkHeaderElements[0].substring(1, linkHeaderElements[0].length()-1)); addHttpRequestEntities(looprequest); CommonHttpResponse loopresponse = execute(looprequest, monitor); JsonArray loopresult = processAndRelease(loopresponse, monitor); diff --git a/mylyn.tasks/connectors/gitlab/org.eclipse.mylyn.gitlab.core/src/org/eclipse/mylyn/gitlab/core/GitlabNewTaskSchema.java b/mylyn.tasks/connectors/gitlab/org.eclipse.mylyn.gitlab.core/src/org/eclipse/mylyn/internal/gitlab/core/GitlabNewTaskSchema.java similarity index 63% rename from mylyn.tasks/connectors/gitlab/org.eclipse.mylyn.gitlab.core/src/org/eclipse/mylyn/gitlab/core/GitlabNewTaskSchema.java rename to mylyn.tasks/connectors/gitlab/org.eclipse.mylyn.gitlab.core/src/org/eclipse/mylyn/internal/gitlab/core/GitlabNewTaskSchema.java index aa7edf35cf..f81e03c16f 100644 --- a/mylyn.tasks/connectors/gitlab/org.eclipse.mylyn.gitlab.core/src/org/eclipse/mylyn/gitlab/core/GitlabNewTaskSchema.java +++ b/mylyn.tasks/connectors/gitlab/org.eclipse.mylyn.gitlab.core/src/org/eclipse/mylyn/internal/gitlab/core/GitlabNewTaskSchema.java @@ -11,15 +11,13 @@ * Frank Becker - initial API and implementation *******************************************************************************/ -package org.eclipse.mylyn.gitlab.core; +package org.eclipse.mylyn.internal.gitlab.core; + +import java.util.Map; import org.eclipse.mylyn.tasks.core.data.AbstractTaskSchema; import org.eclipse.mylyn.tasks.core.data.DefaultTaskSchema; import org.eclipse.mylyn.tasks.core.data.TaskAttribute; -import org.eclipse.mylyn.tasks.core.data.AbstractTaskSchema.Field; -import org.eclipse.mylyn.tasks.core.data.AbstractTaskSchema.Flag; - -import com.google.common.collect.ImmutableMap; public class GitlabNewTaskSchema extends AbstractTaskSchema { @@ -44,22 +42,21 @@ public static GitlabNewTaskSchema getDefault() { public final Field ISSUE_TYPE = createField("issue_type", "Issue Type", TaskAttribute.TYPE_SINGLE_SELECT, Flag.ATTRIBUTE); - private static ImmutableMap json2AttributeMapper = new ImmutableMap.Builder() - .put("project_id", getDefault().PRODUCT.getKey()) //$NON-NLS-1$ - .put("description", getDefault().DESCRIPTION.getKey()) //$NON-NLS-1$ - .put("title", getDefault().SUMMARY.getKey()) //$NON-NLS-1$ - .put("state", getDefault().STATUS.getKey()) //$NON-NLS-1$ - .put("severity", getDefault().PRIORITY.getKey()) //$NON-NLS-1$ - - .build(); - - private static ImmutableMap attribute2jsonMapper = new ImmutableMap.Builder() - .put(getDefault().PRODUCT.getKey(), "project_id") //$NON-NLS-1$ - .put(getDefault().DESCRIPTION.getKey(), "description") //$NON-NLS-1$ - .put(getDefault().SUMMARY.getKey(), "title") //$NON-NLS-1$ - .put(getDefault().STATUS.getKey(), "state") //$NON-NLS-1$ - .put(getDefault().PRIORITY.getKey(), "severity") //$NON-NLS-1$ - .build(); + private static Map json2AttributeMapper = Map.ofEntries( + Map.entry("project_id", getDefault().PRODUCT.getKey()) //$NON-NLS-1 + ,Map.entry("description", getDefault().DESCRIPTION.getKey()) //$NON- + ,Map.entry("title", getDefault().SUMMARY.getKey()) //$NON-NLS-1$ + ,Map.entry("state", getDefault().STATUS.getKey()) //$NON-NLS-1$ + ,Map.entry("severity", getDefault().PRIORITY.getKey()) //$NON-NLS-1$ + ); + + private static Map attribute2jsonMapper = Map.ofEntries( + Map.entry(getDefault().PRODUCT.getKey(), "project_id") //$NON-NLS-1$ + ,Map.entry(getDefault().DESCRIPTION.getKey(), "description") //$NON-NLS-1$ + ,Map.entry(getDefault().SUMMARY.getKey(), "title") //$NON-NLS-1$ + ,Map.entry(getDefault().STATUS.getKey(), "state") //$NON-NLS-1$ + ,Map.entry(getDefault().PRIORITY.getKey(), "severity") //$NON-NLS-1$ + ); public static String getAttributeNameFromJsonName(String fieldName) { String result = json2AttributeMapper.get(fieldName); diff --git a/mylyn.tasks/connectors/gitlab/org.eclipse.mylyn.gitlab.core/src/org/eclipse/mylyn/internal/gitlab/core/GitlabOperation.java b/mylyn.tasks/connectors/gitlab/org.eclipse.mylyn.gitlab.core/src/org/eclipse/mylyn/internal/gitlab/core/GitlabOperation.java new file mode 100644 index 0000000000..227bb1063f --- /dev/null +++ b/mylyn.tasks/connectors/gitlab/org.eclipse.mylyn.gitlab.core/src/org/eclipse/mylyn/internal/gitlab/core/GitlabOperation.java @@ -0,0 +1,133 @@ +/******************************************************************************* + * Copyright (c) 2023 Frank Becker and others. + * + * This program and the accompanying materials are made available under the + * terms of the Eclipse Public License v. 2.0 which is available at + * https://www.eclipse.org/legal/epl-2.0 + * + * SPDX-License-Identifier: EPL-2.0 + * + * Contributors: + * Frank Becker - initial API and implementation + *******************************************************************************/ + +package org.eclipse.mylyn.internal.gitlab.core; + +import java.io.BufferedInputStream; +import java.io.IOException; +import java.io.InputStreamReader; + +import org.apache.http.HttpStatus; +import org.apache.http.client.methods.HttpRequestBase; +import org.eclipse.core.runtime.IStatus; +import org.eclipse.core.runtime.Status; +import org.eclipse.mylyn.commons.core.operations.IOperationMonitor; +import org.eclipse.mylyn.commons.repositories.http.core.CommonHttpClient; +import org.eclipse.mylyn.commons.repositories.http.core.CommonHttpOperation; +import org.eclipse.mylyn.commons.repositories.http.core.CommonHttpResponse; +import org.eclipse.mylyn.commons.repositories.http.core.HttpUtil; +import org.eclipse.mylyn.gitlab.core.GitlabCoreActivator; +import org.eclipse.mylyn.gitlab.core.GitlabException; +import org.eclipse.osgi.util.NLS; + +public abstract class GitlabOperation extends CommonHttpOperation { + + protected static final String ACCEPT = "Accept"; //$NON-NLS-1$ + + protected static final String CONTENT_TYPE = "Content-Type"; //$NON-NLS-1$ + + protected static final String APPLICATION_JSON = "application/json"; //$NON-NLS-1$ + + protected static final String TEXT_XML_CHARSET_UTF_8 = "text/xml; charset=UTF-8"; //$NON-NLS-1$ + + private final String urlSuffix; + + public GitlabOperation(CommonHttpClient client, String urlSuffix) { + super(client); + this.urlSuffix = urlSuffix; + } + + public T run(IOperationMonitor monitor) throws GitlabException { + try { + return execute(monitor); + } catch (IOException e) { + throw new GitlabException(new Status(IStatus.ERROR, GitlabCoreActivator.PLUGIN_ID, + "org.eclipse.mylyn.gitlab.core.GitlabOperation.run(IOperationMonitor)", e)); + } + } + + protected abstract HttpRequestBase createHttpRequestBase(String url); + + protected abstract T parseFromJson(InputStreamReader in) throws GitlabException; + + protected HttpRequestBase createHttpRequestBase() { + HttpRequestBase request = createHttpRequestBase(createHttpRequestURL()); + return request; + } + + protected void addHttpRequestEntities(HttpRequestBase request) throws GitlabException { + request.setHeader(ACCEPT, APPLICATION_JSON); + String accessToken = (String) getClient().getAttribute(GitlabRestClient.AUTHORIZATION_HEADER); + request.setHeader("Authorization", accessToken); + } + + protected T doProcess(CommonHttpResponse response, IOperationMonitor monitor) throws IOException, GitlabException { + try (BufferedInputStream is = new BufferedInputStream(response.getResponseEntityAsStream())) { + InputStreamReader in = new InputStreamReader(is); + return parseFromJson(in); + } + } + + protected T processAndRelease(CommonHttpResponse response, IOperationMonitor monitor) + throws IOException, GitlabException { + try { + doValidate(response, monitor); + return doProcess(response, monitor); + } finally { + response.release(); + } + } + + protected void doValidate(CommonHttpResponse response, IOperationMonitor monitor) + throws IOException, GitlabException { + validate(response, HttpStatus.SC_OK, monitor); + } + + protected void validate(CommonHttpResponse response, int expected, IOperationMonitor monitor) + throws GitlabException { + int statusCode = response.getStatusCode(); + if (statusCode != expected /* && statusCode != HttpStatus.SC_BAD_REQUEST */) { + if (statusCode == HttpStatus.SC_NOT_FOUND) { + throw new GitlabException(new Status(IStatus.ERROR, GitlabCoreActivator.PLUGIN_ID, + NLS.bind("Requested resource ''{0}'' does not exist", response.getRequestPath()))); + } + throw new GitlabException(new Status(IStatus.ERROR, GitlabCoreActivator.PLUGIN_ID, + NLS.bind("Unexpected response from Gitlab REST server for ''{0}'': {1}", response.getRequestPath(), + HttpUtil.getStatusText(statusCode)))); + } + } + + protected String baseUrl() { + String url = getClient().getLocation().getUrl(); + if (!url.endsWith(GitlabCoreActivator.API_VERSION)) { + url += GitlabCoreActivator.API_VERSION; + } + return url; + } + + protected T execute(IOperationMonitor monitor) throws IOException, GitlabException { + HttpRequestBase request = createHttpRequestBase(); + addHttpRequestEntities(request); + CommonHttpResponse response = execute(request, monitor); + return processAndRelease(response, monitor); + } + + protected String getUrlSuffix() { + return urlSuffix; + } + + protected String createHttpRequestURL() { + String urlSuffix = getUrlSuffix(); + return baseUrl() + urlSuffix; + } +} diff --git a/mylyn.tasks/connectors/gitlab/org.eclipse.mylyn.gitlab.core/src/org/eclipse/mylyn/gitlab/core/GitlabPostOperation.java b/mylyn.tasks/connectors/gitlab/org.eclipse.mylyn.gitlab.core/src/org/eclipse/mylyn/internal/gitlab/core/GitlabPostOperation.java similarity index 95% rename from mylyn.tasks/connectors/gitlab/org.eclipse.mylyn.gitlab.core/src/org/eclipse/mylyn/gitlab/core/GitlabPostOperation.java rename to mylyn.tasks/connectors/gitlab/org.eclipse.mylyn.gitlab.core/src/org/eclipse/mylyn/internal/gitlab/core/GitlabPostOperation.java index 05fc6f0bbb..cab28add5f 100644 --- a/mylyn.tasks/connectors/gitlab/org.eclipse.mylyn.gitlab.core/src/org/eclipse/mylyn/gitlab/core/GitlabPostOperation.java +++ b/mylyn.tasks/connectors/gitlab/org.eclipse.mylyn.gitlab.core/src/org/eclipse/mylyn/internal/gitlab/core/GitlabPostOperation.java @@ -11,7 +11,7 @@ * Frank Becker - initial API and implementation *******************************************************************************/ -package org.eclipse.mylyn.gitlab.core; +package org.eclipse.mylyn.internal.gitlab.core; import org.apache.http.client.methods.HttpPost; import org.apache.http.client.methods.HttpRequestBase; diff --git a/mylyn.tasks/connectors/gitlab/org.eclipse.mylyn.gitlab.core/src/org/eclipse/mylyn/gitlab/core/GitlabPutOperation.java b/mylyn.tasks/connectors/gitlab/org.eclipse.mylyn.gitlab.core/src/org/eclipse/mylyn/internal/gitlab/core/GitlabPutOperation.java similarity index 80% rename from mylyn.tasks/connectors/gitlab/org.eclipse.mylyn.gitlab.core/src/org/eclipse/mylyn/gitlab/core/GitlabPutOperation.java rename to mylyn.tasks/connectors/gitlab/org.eclipse.mylyn.gitlab.core/src/org/eclipse/mylyn/internal/gitlab/core/GitlabPutOperation.java index ff9fd4eeec..68f5e65391 100644 --- a/mylyn.tasks/connectors/gitlab/org.eclipse.mylyn.gitlab.core/src/org/eclipse/mylyn/gitlab/core/GitlabPutOperation.java +++ b/mylyn.tasks/connectors/gitlab/org.eclipse.mylyn.gitlab.core/src/org/eclipse/mylyn/internal/gitlab/core/GitlabPutOperation.java @@ -11,15 +11,19 @@ * Frank Becker - initial API and implementation *******************************************************************************/ -package org.eclipse.mylyn.gitlab.core; +package org.eclipse.mylyn.internal.gitlab.core; import java.io.UnsupportedEncodingException; -import org.apache.http.client.methods.HttpPost; import org.apache.http.client.methods.HttpPut; import org.apache.http.client.methods.HttpRequestBase; import org.apache.http.entity.StringEntity; +import org.eclipse.core.runtime.IStatus; +import org.eclipse.core.runtime.Status; import org.eclipse.mylyn.commons.repositories.http.core.CommonHttpClient; +import org.eclipse.mylyn.gitlab.core.GitlabCoreActivator; +import org.eclipse.mylyn.gitlab.core.GitlabException; + public abstract class GitlabPutOperation extends GitlabOperation { @@ -41,7 +45,7 @@ protected void addHttpRequestEntities(HttpRequestBase request) throws GitlabExce try { ((HttpPut) request).setEntity(new StringEntity(body)); } catch (UnsupportedEncodingException e) { - throw new GitlabException(e); + throw new GitlabException(new Status(IStatus.ERROR,GitlabCoreActivator.PLUGIN_ID,"UnsupportedEncodingException",e)); } }; diff --git a/mylyn.tasks/connectors/gitlab/org.eclipse.mylyn.gitlab.core/src/org/eclipse/mylyn/gitlab/core/GitlabRepositoryConnector.java b/mylyn.tasks/connectors/gitlab/org.eclipse.mylyn.gitlab.core/src/org/eclipse/mylyn/internal/gitlab/core/GitlabRepositoryConnector.java similarity index 95% rename from mylyn.tasks/connectors/gitlab/org.eclipse.mylyn.gitlab.core/src/org/eclipse/mylyn/gitlab/core/GitlabRepositoryConnector.java rename to mylyn.tasks/connectors/gitlab/org.eclipse.mylyn.gitlab.core/src/org/eclipse/mylyn/internal/gitlab/core/GitlabRepositoryConnector.java index ba67c94e0a..0cd46c12fb 100644 --- a/mylyn.tasks/connectors/gitlab/org.eclipse.mylyn.gitlab.core/src/org/eclipse/mylyn/gitlab/core/GitlabRepositoryConnector.java +++ b/mylyn.tasks/connectors/gitlab/org.eclipse.mylyn.gitlab.core/src/org/eclipse/mylyn/internal/gitlab/core/GitlabRepositoryConnector.java @@ -11,7 +11,7 @@ * Frank Becker - initial API and implementation *******************************************************************************/ -package org.eclipse.mylyn.gitlab.core; +package org.eclipse.mylyn.internal.gitlab.core; import java.beans.PropertyChangeEvent; import java.beans.PropertyChangeListener; @@ -47,6 +47,9 @@ import org.eclipse.mylyn.commons.repositories.core.RepositoryLocation; import org.eclipse.mylyn.commons.repositories.core.auth.AuthenticationType; import org.eclipse.mylyn.commons.repositories.core.auth.UserCredentials; +import org.eclipse.mylyn.gitlab.core.Duration; +import org.eclipse.mylyn.gitlab.core.GitlabConfiguration; +import org.eclipse.mylyn.gitlab.core.GitlabCoreActivator; import org.eclipse.mylyn.internal.commons.core.operations.NullOperationMonitor; import org.eclipse.mylyn.internal.tasks.core.IRepositoryConstants; import org.eclipse.mylyn.tasks.core.AbstractRepositoryConnector; @@ -68,6 +71,7 @@ import com.google.common.cache.CacheLoader; import com.google.common.cache.LoadingCache; import com.google.common.collect.Lists; +import com.google.common.util.concurrent.ExecutionError; import com.google.common.util.concurrent.ListenableFuture; import com.google.common.util.concurrent.UncheckedExecutionException; @@ -285,6 +289,8 @@ public GitlabConfiguration getRepositoryConfiguration(TaskRepository repository) throw new CoreException(new Status(IStatus.ERROR, GitlabCoreActivator.PLUGIN_ID, e.getMessage(), e)); } catch (ExecutionException e) { throw new CoreException(new Status(IStatus.ERROR, GitlabCoreActivator.PLUGIN_ID, e.getMessage(), e)); + } catch (ExecutionError e) { + throw new CoreException(new Status(IStatus.ERROR, GitlabCoreActivator.PLUGIN_ID, e.getMessage(), e)); } } @@ -384,9 +390,6 @@ public IStatus performQuery(TaskRepository repository, IRepositoryQuery query, T } catch (CoreException e) { return new Status(IStatus.ERROR, GitlabCoreActivator.PLUGIN_ID, IStatus.INFO, "CoreException from performQuery", e); - } catch (GitlabException e) { - return new Status(IStatus.ERROR, GitlabCoreActivator.PLUGIN_ID, IStatus.INFO, - "GitlabException from performQuery", e); } return Status.OK_STATUS; } @@ -419,9 +422,12 @@ public RepositoryInfo validateRepository(TaskRepository repository, IProgressMon public GitlabRestClient getClient(TaskRepository repository) throws CoreException { try { return clientCache.get(new RepositoryKey(repository)); + } catch (UncheckedExecutionException e) { + throw new CoreException(new Status(IStatus.ERROR, GitlabCoreActivator.PLUGIN_ID, e.getMessage(), e)); } catch (ExecutionException e) { - throw new CoreException( - new Status(IStatus.ERROR, GitlabCoreActivator.PLUGIN_ID, "TaskRepositoryManager is null")); + throw new CoreException(new Status(IStatus.ERROR, GitlabCoreActivator.PLUGIN_ID, e.getMessage(), e)); + } catch (ExecutionError e) { + throw new CoreException(new Status(IStatus.ERROR, GitlabCoreActivator.PLUGIN_ID, e.getMessage(), e)); } } diff --git a/mylyn.tasks/connectors/gitlab/org.eclipse.mylyn.gitlab.core/src/org/eclipse/mylyn/gitlab/core/GitlabRestClient.java b/mylyn.tasks/connectors/gitlab/org.eclipse.mylyn.gitlab.core/src/org/eclipse/mylyn/internal/gitlab/core/GitlabRestClient.java similarity index 96% rename from mylyn.tasks/connectors/gitlab/org.eclipse.mylyn.gitlab.core/src/org/eclipse/mylyn/gitlab/core/GitlabRestClient.java rename to mylyn.tasks/connectors/gitlab/org.eclipse.mylyn.gitlab.core/src/org/eclipse/mylyn/internal/gitlab/core/GitlabRestClient.java index d6d3c958ae..458d129238 100644 --- a/mylyn.tasks/connectors/gitlab/org.eclipse.mylyn.gitlab.core/src/org/eclipse/mylyn/gitlab/core/GitlabRestClient.java +++ b/mylyn.tasks/connectors/gitlab/org.eclipse.mylyn.gitlab.core/src/org/eclipse/mylyn/internal/gitlab/core/GitlabRestClient.java @@ -11,7 +11,7 @@ * Frank Becker - initial API and implementation *******************************************************************************/ -package org.eclipse.mylyn.gitlab.core; +package org.eclipse.mylyn.internal.gitlab.core; import java.io.BufferedReader; import java.io.IOException; @@ -25,6 +25,7 @@ import java.util.ArrayList; import java.util.Date; import java.util.List; +import java.util.Map; import java.util.Map.Entry; import java.util.Set; import java.util.regex.Matcher; @@ -49,7 +50,9 @@ import org.eclipse.mylyn.commons.repositories.core.RepositoryLocation; import org.eclipse.mylyn.commons.repositories.http.core.CommonHttpClient; import org.eclipse.mylyn.commons.repositories.http.core.CommonHttpResponse; -import org.eclipse.mylyn.internal.commons.core.operations.NullOperationMonitor; +import org.eclipse.mylyn.gitlab.core.GitlabConfiguration; +import org.eclipse.mylyn.gitlab.core.GitlabCoreActivator; +import org.eclipse.mylyn.gitlab.core.GitlabException; import org.eclipse.mylyn.tasks.core.IRepositoryPerson; import org.eclipse.mylyn.tasks.core.IRepositoryQuery; import org.eclipse.mylyn.tasks.core.RepositoryResponse; @@ -63,7 +66,6 @@ import org.eclipse.mylyn.tasks.core.data.TaskDataCollector; import org.eclipse.osgi.util.NLS; -import com.google.common.collect.ImmutableMap; import com.google.gson.Gson; import com.google.gson.GsonBuilder; import com.google.gson.JsonArray; @@ -752,7 +754,7 @@ protected void addHttpRequestEntities(HttpRequestBase request) throws GitlabExce try { ((HttpPost) request).setEntity(new StringEntity(body)); } catch (UnsupportedEncodingException e) { - throw new GitlabException(e); + throw new GitlabException(new Status(IStatus.ERROR,GitlabCoreActivator.PLUGIN_ID,"UnsupportedEncodingException",e)); } }; @@ -829,17 +831,16 @@ public GitlabConfiguration getConfiguration(TaskRepository repository, IOperatio return config; } - ImmutableMap updatable = new ImmutableMap.Builder() - .put(GitlabTaskSchema.getDefault().SUMMARY.getKey(), "title") - .put(GitlabTaskSchema.getDefault().DESCRIPTION.getKey(), "description") - .put(GitlabTaskSchema.getDefault().DISCUSSION_LOCKED.getKey(), + Map updatable= Map.ofEntries(Map.entry(GitlabTaskSchema.getDefault().SUMMARY.getKey(), "title") + ,Map.entry(GitlabTaskSchema.getDefault().DESCRIPTION.getKey(), "description") + ,Map.entry(GitlabTaskSchema.getDefault().DISCUSSION_LOCKED.getKey(), GitlabTaskSchema.getDefault().DISCUSSION_LOCKED.getKey()) - .put(GitlabTaskSchema.getDefault().CONFIDENTIAL.getKey(), + ,Map.entry(GitlabTaskSchema.getDefault().CONFIDENTIAL.getKey(), GitlabTaskSchema.getDefault().CONFIDENTIAL.getKey()) - .put(GitlabTaskSchema.getDefault().ISSUE_TYPE.getKey(), GitlabTaskSchema.getDefault().ISSUE_TYPE.getKey()) - .put(GitlabTaskSchema.getDefault().OPERATION.getKey(), "state_event") - .put(GitlabTaskSchema.getDefault().DUE_DATE.getKey(), GitlabTaskSchema.getDefault().DUE_DATE.getKey()) - .build(); + ,Map.entry(GitlabTaskSchema.getDefault().ISSUE_TYPE.getKey(), GitlabTaskSchema.getDefault().ISSUE_TYPE.getKey()) + ,Map.entry(GitlabTaskSchema.getDefault().OPERATION.getKey(), "state_event") + ,Map.entry(GitlabTaskSchema.getDefault().DUE_DATE.getKey(), GitlabTaskSchema.getDefault().DUE_DATE.getKey()) + ); private static SimpleDateFormat dmyFormat = new SimpleDateFormat("yyyy-MM-dd"); @@ -911,7 +912,7 @@ public JsonElement createNewIssue(TaskData taskData, IOperationMonitor monitor) TaskAttribute productAttribute = taskData.getRoot() .getAttribute(GitlabTaskSchema.getDefault().PRODUCT.getKey()); if (productAttribute == null || productAttribute.getValue().isEmpty()) { - throw new GitlabException("productAttribute should not be null"); + throw new GitlabException(new Status(IStatus.ERROR,GitlabCoreActivator.PLUGIN_ID,"productAttribute should not be null")); } JsonObject jsonElement; jsonElement = new GitlabPostOperation(client, @@ -926,7 +927,7 @@ protected void addHttpRequestEntities(HttpRequestBase request) throws GitlabExce try { ((HttpPost) request).setEntity(new StringEntity(jsondata)); } catch (UnsupportedEncodingException e) { - throw new GitlabException(e); + throw new GitlabException(new Status(IStatus.ERROR,GitlabCoreActivator.PLUGIN_ID,"UnsupportedEncodingException",e)); } }; diff --git a/mylyn.tasks/connectors/gitlab/org.eclipse.mylyn.gitlab.core/src/org/eclipse/mylyn/gitlab/core/GitlabTaskAttributeMapper.java b/mylyn.tasks/connectors/gitlab/org.eclipse.mylyn.gitlab.core/src/org/eclipse/mylyn/internal/gitlab/core/GitlabTaskAttributeMapper.java similarity index 52% rename from mylyn.tasks/connectors/gitlab/org.eclipse.mylyn.gitlab.core/src/org/eclipse/mylyn/gitlab/core/GitlabTaskAttributeMapper.java rename to mylyn.tasks/connectors/gitlab/org.eclipse.mylyn.gitlab.core/src/org/eclipse/mylyn/internal/gitlab/core/GitlabTaskAttributeMapper.java index 3ae1b503da..bbed2ab035 100644 --- a/mylyn.tasks/connectors/gitlab/org.eclipse.mylyn.gitlab.core/src/org/eclipse/mylyn/gitlab/core/GitlabTaskAttributeMapper.java +++ b/mylyn.tasks/connectors/gitlab/org.eclipse.mylyn.gitlab.core/src/org/eclipse/mylyn/internal/gitlab/core/GitlabTaskAttributeMapper.java @@ -11,12 +11,12 @@ * Frank Becker - initial API and implementation *******************************************************************************/ -package org.eclipse.mylyn.gitlab.core; +package org.eclipse.mylyn.internal.gitlab.core; -import java.text.ParseException; -import java.text.SimpleDateFormat; +import java.time.LocalDateTime; +import java.time.ZoneId; +import java.time.format.DateTimeFormatter; import java.util.Date; -import java.util.Map; import java.util.Map.Entry; import org.eclipse.jdt.annotation.NonNull; @@ -27,36 +27,17 @@ public class GitlabTaskAttributeMapper extends TaskAttributeMapper { - private final GitlabRepositoryConnector connector; - private static final String dateFormat_1 = "yyyy-MM-dd HH:mm:ss.sss"; //$NON-NLS-1$ + private static DateTimeFormatter formatter = DateTimeFormatter + .ofPattern("yyyy-MM-dd[' ']['T'][H:mm[:ss[.SSS]['Z']]]"); - private static final String dateFormat_2 = "yyyy-MM-dd HH:mm:ss"; //$NON-NLS-1$ - - private static final String dateFormat_3 = "yyyy-MM-dd HH:mm"; //$NON-NLS-1$ - - private static final String dateFormat_4 = "yyyy-MM-dd"; //$NON-NLS-1$ - - private static final String dateFormat_1_TimeZone = "yyyy-MM-dd'T'HH:mm:ss.SSS'Z'"; //$NON-NLS-1$ - - private static final String dateFormat_2_TimeZone = "yyyy-MM-dd'T'HH:mm:ss'Z'"; //$NON-NLS-1$ - - private static final String dateFormat_3_TimeZone = "yyyy-MM-dd'T'HH:mm'Z'"; //$NON-NLS-1$ - - private static final String dateFormat_4_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, dateFormat_4_TimeZone, dateFormat_4 }; - - public GitlabTaskAttributeMapper(TaskRepository taskRepository, GitlabRepositoryConnector connector) { + public GitlabTaskAttributeMapper(TaskRepository taskRepository) { super(taskRepository); - this.connector = connector; } @Override public Date getDateValue(TaskAttribute attribute) { - if (attribute == null) { + if (attribute == null || attribute.getValue().isBlank()) { return null; } Date parsedDate = parseDate(attribute.getValue()); @@ -70,24 +51,20 @@ public Date getDateValue(TaskAttribute attribute) { * 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) { - } + if (dateString.matches("[0-9]+")) { + return new Date(Long.parseLong(dateString)); + } else { + return Date.from(LocalDateTime.parse(dateString, formatter).atZone(ZoneId.systemDefault()).toInstant()); } - return null; } @Override public void setRepositoryPerson(@NonNull TaskAttribute taskAttribute, @NonNull IRepositoryPerson person) { super.setRepositoryPerson(taskAttribute, person); - if (person.getAttributes().size()>0) { - for ( Entry entry : person.getAttributes().entrySet()) { + if (person.getAttributes().size() > 0) { + for (Entry entry : person.getAttributes().entrySet()) { TaskAttribute taskAttrib = taskAttribute.getAttribute(entry.getKey()); - if (taskAttrib==null) + if (taskAttrib == null) taskAttrib = taskAttribute.createAttribute(entry.getKey()); taskAttrib.setValue(entry.getValue()); } diff --git a/mylyn.tasks/connectors/gitlab/org.eclipse.mylyn.gitlab.core/src/org/eclipse/mylyn/internal/gitlab/core/GitlabTaskDataHandler.java b/mylyn.tasks/connectors/gitlab/org.eclipse.mylyn.gitlab.core/src/org/eclipse/mylyn/internal/gitlab/core/GitlabTaskDataHandler.java new file mode 100644 index 0000000000..a6c5a7e6be --- /dev/null +++ b/mylyn.tasks/connectors/gitlab/org.eclipse.mylyn.gitlab.core/src/org/eclipse/mylyn/internal/gitlab/core/GitlabTaskDataHandler.java @@ -0,0 +1,113 @@ +/******************************************************************************* + * Copyright (c) 2023 Frank Becker and others. + * + * This program and the accompanying materials are made available under the + * terms of the Eclipse Public License v. 2.0 which is available at + * https://www.eclipse.org/legal/epl-2.0 + * + * SPDX-License-Identifier: EPL-2.0 + * + * Contributors: + * Frank Becker - initial API and implementation + *******************************************************************************/ + +package org.eclipse.mylyn.internal.gitlab.core; + +import java.util.Set; + +import org.eclipse.core.runtime.CoreException; +import org.eclipse.core.runtime.IProgressMonitor; +import org.eclipse.core.runtime.IStatus; +import org.eclipse.core.runtime.Status; +import org.eclipse.mylyn.commons.core.operations.IOperationMonitor; +import org.eclipse.mylyn.commons.core.operations.IOperationMonitor.OperationFlag; +import org.eclipse.mylyn.commons.core.operations.OperationUtil; +import org.eclipse.mylyn.commons.net.Policy; +import org.eclipse.mylyn.gitlab.core.GitlabConfiguration; +import org.eclipse.mylyn.gitlab.core.GitlabCoreActivator; +import org.eclipse.mylyn.gitlab.core.GitlabException; +import org.eclipse.mylyn.tasks.core.ITaskMapping; +import org.eclipse.mylyn.tasks.core.RepositoryResponse; +import org.eclipse.mylyn.tasks.core.TaskRepository; +import org.eclipse.mylyn.tasks.core.data.AbstractTaskDataHandler; +import org.eclipse.mylyn.tasks.core.data.TaskAttribute; +import org.eclipse.mylyn.tasks.core.data.TaskAttributeMapper; +import org.eclipse.mylyn.tasks.core.data.TaskData; +import org.eclipse.mylyn.tasks.core.data.TaskDataCollector; + +public class GitlabTaskDataHandler extends AbstractTaskDataHandler { + protected final GitlabRepositoryConnector connector; + + public GitlabTaskDataHandler(GitlabRepositoryConnector connector) { + super(); + this.connector = connector; + } + + @Override + public RepositoryResponse postTaskData(TaskRepository repository, TaskData taskData, + Set oldAttributes, IProgressMonitor monitor) throws CoreException { + monitor = Policy.monitorFor(monitor); + try { + monitor.beginTask("Submitting_task", IProgressMonitor.UNKNOWN); + GitlabRestClient client = connector.getClient(repository); + IOperationMonitor progress = OperationUtil.convert(monitor, "post taskdata", 3); + try { + return client.postTaskData(taskData, oldAttributes, progress); + } catch (GitlabException e) { + throw new CoreException(new Status(IStatus.ERROR, GitlabCoreActivator.PLUGIN_ID, 2, + "Error post taskdata.\n\n" + e.getMessage(), e)); + } + } finally { + monitor.done(); + } + } + + @Override + public boolean initializeTaskData(TaskRepository repository, TaskData data, ITaskMapping initializationData, + IProgressMonitor monitor) throws CoreException { + // Note: setting current version to latest assumes the data arriving + // here is either for a new task or is + // fresh from the repository (not locally stored data that may not have + // been migrated). + data.setVersion("0"); //$NON-NLS-1$ + if (data.isNew()) { + GitlabNewTaskSchema.getDefault().initialize(data); + } else { + GitlabTaskSchema.getDefault().initialize(data); + } + if (initializationData != null) { + connector.getTaskMapping(data).merge(initializationData); + } + GitlabConfiguration config = connector.getRepositoryConfiguration(repository); + if (config != null) { + config.updateProductOptions(data); + } + return true; + } + + @Override + public TaskAttributeMapper getAttributeMapper(TaskRepository repository) { + return new GitlabTaskAttributeMapper(repository); + } + + @Override + public void getMultiTaskData(final TaskRepository repository, Set taskIds, + final TaskDataCollector collector, IProgressMonitor monitor) throws CoreException { + monitor = Policy.monitorFor(monitor); + try { + monitor.beginTask("retrive_task", IProgressMonitor.UNKNOWN); + GitlabRestClient client = connector.getClient(repository); + try { + IOperationMonitor progress = OperationUtil.convert(monitor, "post taskdata", 3); + progress.addFlag(OperationFlag.BACKGROUND); + client.getTaskData(taskIds, repository, collector, progress); + } catch (GitlabException e) { + throw new CoreException(new Status(IStatus.ERROR, GitlabCoreActivator.PLUGIN_ID, 2, + "Error get taskdata.\n\n" + e.getMessage(), e)); + } + } finally { + monitor.done(); + } + } + +} diff --git a/mylyn.tasks/connectors/gitlab/org.eclipse.mylyn.gitlab.core/src/org/eclipse/mylyn/internal/gitlab/core/GitlabTaskSchema.java b/mylyn.tasks/connectors/gitlab/org.eclipse.mylyn.gitlab.core/src/org/eclipse/mylyn/internal/gitlab/core/GitlabTaskSchema.java new file mode 100644 index 0000000000..f91e694f48 --- /dev/null +++ b/mylyn.tasks/connectors/gitlab/org.eclipse.mylyn.gitlab.core/src/org/eclipse/mylyn/internal/gitlab/core/GitlabTaskSchema.java @@ -0,0 +1,129 @@ +/******************************************************************************* + * Copyright (c) 2023 Frank Becker and others. + * + * This program and the accompanying materials are made available under the + * terms of the Eclipse Public License v. 2.0 which is available at + * https://www.eclipse.org/legal/epl-2.0 + * + * SPDX-License-Identifier: EPL-2.0 + * + * Contributors: + * Frank Becker - initial API and implementation + *******************************************************************************/ + +package org.eclipse.mylyn.internal.gitlab.core; + +import java.util.Map; + +import org.eclipse.mylyn.tasks.core.data.DefaultTaskSchema; +import org.eclipse.mylyn.tasks.core.data.TaskAttribute; + +public class GitlabTaskSchema extends GitlabNewTaskSchema { + + private final DefaultTaskSchema parent = DefaultTaskSchema.getInstance(); + + private static final GitlabTaskSchema instance = new GitlabTaskSchema(); + + public static GitlabTaskSchema getDefault() { + return instance; + } + + public final Field CREATED = inheritFrom(parent.DATE_CREATION).create(); + + public final Field UPDATED = inheritFrom(parent.DATE_MODIFICATION).create(); + + public final Field COMPLETED = inheritFrom(parent.DATE_COMPLETION).create(); + + public final Field AUTHOR = inheritFrom(parent.USER_REPORTER).create(); + + public final Field TASK_KEY = inheritFrom(parent.TASK_KEY).create(); + + public final Field URL = inheritFrom(parent.TASK_URL).addFlags(Flag.ATTRIBUTE).create(); + + public final Field USER_NOTES_COUNT = createField("user_notes_count", "User Notes Count", + TaskAttribute.TYPE_INTEGER, Flag.ATTRIBUTE); + + public final Field BLOCKING_ISSUE_COUNT = createField("blocking_issues_count", "Blocking Issue Count", + TaskAttribute.TYPE_INTEGER, Flag.ATTRIBUTE); + + public final Field MERGE_REQUEST_COUNT = createField("merge_requests_count", "Merge Request Count", + TaskAttribute.TYPE_INTEGER, Flag.ATTRIBUTE); + + public final Field UPVOTES = createField("upvotes", "Up Votes", TaskAttribute.TYPE_INTEGER, Flag.ATTRIBUTE); + + public final Field DOWNVOTES = createField("downvotes", "Down Notes", TaskAttribute.TYPE_INTEGER, Flag.ATTRIBUTE); + +// public final Field WEB_URL = createField("web_url", "WEB URL", TaskAttribute.TYPE_SHORT_TEXT, Flag.ATTRIBUTE); + + public final Field HAS_TASKS = createField("has_tasks", "has Tasks", TaskAttribute.TYPE_BOOLEAN, Flag.ATTRIBUTE); + + public final Field SUBSCRIBED = createField("subscribed", "subscribed", TaskAttribute.TYPE_BOOLEAN, Flag.ATTRIBUTE); + + public final Field CONFIDENTIAL = createField("confidential", "confidential", TaskAttribute.TYPE_BOOLEAN, + Flag.ATTRIBUTE); + + public final Field NEW_COMMENT = inheritFrom(parent.NEW_COMMENT).create(); + + public final Field DISCUSSION_LOCKED = createField("discussion_locked", "Discussion locked", + TaskAttribute.TYPE_BOOLEAN, Flag.ATTRIBUTE); + + public final Field IID = createField("iid", "interne ID", TaskAttribute.TYPE_SHORT_TEXT, Flag.ATTRIBUTE); + public final Field OPERATION = createField(TaskAttribute.OPERATION, "Operation", TaskAttribute.TYPE_OPERATION); + public final Field CLOSED_BY = createField("closed_by", "closed by", TaskAttribute.TYPE_PERSON, Flag.PEOPLE, //$NON-NLS-1$ + Flag.READ_ONLY); + + public final Field ASSIGNED_TO = inheritFrom(parent.USER_ASSIGNED).label("Assigned to").create(); + + public final Field TYPE = createField("type", "Type", TaskAttribute.TYPE_SHORT_TEXT, Flag.ATTRIBUTE); + + public final Field TASK_STATUS = createField("task_status", "Task Status", TaskAttribute.TYPE_SHORT_TEXT, + Flag.ATTRIBUTE); + + public final Field DUE_DATE = createField("due_date", "Due date", TaskAttribute.TYPE_DATE, Flag.ATTRIBUTE); + private static Map json2AttributeMapper = Map + .ofEntries(Map.entry("project_id", getDefault().PRODUCT.getKey()) //$NON-NLS-1$ + , Map.entry("description", getDefault().DESCRIPTION.getKey()) //$NON-NLS-1$ + , Map.entry("title", getDefault().SUMMARY.getKey()) //$NON-NLS-1$ + , Map.entry("state", getDefault().STATUS.getKey()) //$NON-NLS-1$ + , Map.entry("assignee", getDefault().ASSIGNED_TO.getKey()) //$NON-NLS-1$ + , Map.entry("author", getDefault().AUTHOR.getKey()) //$NON-NLS-1$ + , Map.entry("id", getDefault().TASK_KEY.getKey()) //$NON-NLS-1$ + , Map.entry("severity", getDefault().PRIORITY.getKey()) //$NON-NLS-1$ + , Map.entry("created_at", getDefault().CREATED.getKey()) //$NON-NLS-1$ + , Map.entry("updated_at", getDefault().UPDATED.getKey()) //$NON-NLS-1$ + , Map.entry("closed_at", getDefault().COMPLETED.getKey()) //$NON-NLS-1$ + , Map.entry("web_url", getDefault().URL.getKey()) //$NON-NLS-1$ + ); + + private static Map attribute2jsonMapper = Map + .ofEntries(Map.entry(getDefault().PRODUCT.getKey(), "project_id") //$NON-NLS-1$ + , Map.entry(getDefault().DESCRIPTION.getKey(), "description") //$NON-NLS-1$ + , Map.entry(getDefault().SUMMARY.getKey(), "title") //$NON-NLS-1$ + , Map.entry(getDefault().STATUS.getKey(), "state") //$NON-NLS-1$ + , Map.entry(getDefault().ASSIGNED_TO.getKey(), "assignee") //$NON-NLS-1$ + , Map.entry(getDefault().AUTHOR.getKey(), "author") //$NON-NLS-1$ + , Map.entry(getDefault().TASK_KEY.getKey(), "id") //$NON-NLS-1$ + , Map.entry(getDefault().PRIORITY.getKey(), "severity") //$NON-NLS-1$ + , Map.entry(getDefault().CREATED.getKey(), "created_at") //$NON-NLS-1$ + , Map.entry(getDefault().UPDATED.getKey(), "updated_at") //$NON-NLS-1$ + , Map.entry(getDefault().COMPLETED.getKey(), "closed_at") //$NON-NLS-1$ + , Map.entry(getDefault().URL.getKey(), "web_url") //$NON-NLS-1$ + ); + + public static String getAttributeNameFromJsonName(String fieldName) { + String result = json2AttributeMapper.get(fieldName); + if (result == null) { + result = fieldName; + } + return result; + } + + public static String getJsonNameFromAttributeName(String attributeName) { + String result = attribute2jsonMapper.get(attributeName); + if (result == null) { + result = attributeName; + } + return result; + } + +} diff --git a/mylyn.tasks/connectors/gitlab/org.eclipse.mylyn.gitlab.feature/build.properties b/mylyn.tasks/connectors/gitlab/org.eclipse.mylyn.gitlab.feature/build.properties index 64f93a9f0b..560dde240e 100644 --- a/mylyn.tasks/connectors/gitlab/org.eclipse.mylyn.gitlab.feature/build.properties +++ b/mylyn.tasks/connectors/gitlab/org.eclipse.mylyn.gitlab.feature/build.properties @@ -1 +1,9 @@ -bin.includes = feature.xml +############################################################################### +# Copyright (c) 2023 Frank Becker and others. +# All rights reserved. This program and the accompanying materials +# are made available under the terms of the Eclipse Public License v2.0 +# which accompanies this distribution, and is available at +# http://www.eclipse.org/legal/epl-v20.html +############################################################################### +bin.includes = feature.xml,\ + feature.properties diff --git a/mylyn.tasks/connectors/gitlab/org.eclipse.mylyn.gitlab.feature/feature.properties b/mylyn.tasks/connectors/gitlab/org.eclipse.mylyn.gitlab.feature/feature.properties new file mode 100644 index 0000000000..da67b46acd --- /dev/null +++ b/mylyn.tasks/connectors/gitlab/org.eclipse.mylyn.gitlab.feature/feature.properties @@ -0,0 +1,178 @@ +############################################################################### +# Copyright (c) 2011, 2023 Chris Aniszczyk and others. +# All rights reserved. This program and the accompanying materials +# are made available under the terms of the Eclipse Public License 2.0 +# which accompanies this distribution, and is available at +# https://www.eclipse.org/legal/epl-2.0/ +# +# SPDX-License-Identifier: EPL-2.0 +############################################################################### + +featureName=Mylyn Tasks Connector: Gitlab Preview for gitlab.com only +providerName=Eclipse Mylyn + +updateSiteName=Eclipse Mylyn Update Site + +# description property - text of the "Feature Description" +description=Mylyn Task Connector for Gitlab +################ end of description property ################################## + +# "copyright" property - text of the "Feature Update Copyright" +copyright=\ +Copyright (c) 2023 Frank Becker, et.al.\n\ +All rights reserved. This program and the accompanying materials\n\ +are made available under the terms of the Eclipse Public License 2.0\n\ +which accompanies this distribution, and is available at\n\ +https://www.eclipse.org/legal/epl-2.0/\n\ +\n\ +SPDX-License-Identifier: EPL-2.0\n +################ end of copyright property #################################### + +# "licenseURL" property - URL of the "Feature License" +# do not translate value - just change to point to a locale-specific HTML page +licenseURL=license.html + +# "license" property - text of the "Feature Update License" +# should be plain text version of license agreement pointed to be "licenseURL" +license=\ +Eclipse Foundation Software User Agreement\n\ +\n\ +November 22, 2017\n\ +\n\ +Usage Of Content\n\ +\n\ +THE ECLIPSE FOUNDATION MAKES AVAILABLE SOFTWARE, DOCUMENTATION, INFORMATION\n\ +AND/OR OTHER MATERIALS FOR OPEN SOURCE PROJECTS (COLLECTIVELY "CONTENT"). USE OF\n\ +THE CONTENT IS GOVERNED BY THE TERMS AND CONDITIONS OF THIS AGREEMENT AND/OR THE\n\ +TERMS AND CONDITIONS OF LICENSE AGREEMENTS OR NOTICES INDICATED OR REFERENCED\n\ +BELOW. BY USING THE CONTENT, YOU AGREE THAT YOUR USE OF THE CONTENT IS GOVERNED\n\ +BY THIS AGREEMENT AND/OR THE TERMS AND CONDITIONS OF ANY APPLICABLE LICENSE\n\ +AGREEMENTS OR NOTICES INDICATED OR REFERENCED BELOW. IF YOU DO NOT AGREE TO THE\n\ +TERMS AND CONDITIONS OF THIS AGREEMENT AND THE TERMS AND CONDITIONS OF ANY\n\ +APPLICABLE LICENSE AGREEMENTS OR NOTICES INDICATED OR REFERENCED BELOW, THEN YOU\n\ +MAY NOT USE THE CONTENT.\n\ +\n\ +Applicable Licenses\n\ +\n\ +Unless otherwise indicated, all Content made available by the Eclipse Foundation\n\ +is provided to you under the terms and conditions of the Eclipse Public License\n\ +Version 2.0 ("EPL"). A copy of the EPL is provided with this Content and is also\n\ +available at http://www.eclipse.org/legal/epl-2.0. For purposes of the EPL,\n\ +"Program" will mean the Content.\n\ +\n\ +Content includes, but is not limited to, source code, object code, documentation\n\ +and other files maintained in the Eclipse Foundation source code repository\n\ +("Repository") in software modules ("Modules") and made available as\n\ +downloadable archives ("Downloads").\n\ +\n\ +- Content may be structured and packaged into modules to facilitate\n\ + delivering, extending, and upgrading the Content. Typical modules may\n\ + include plug-ins ("Plug-ins"), plug-in fragments ("Fragments"), and\n\ + features ("Features").\n\ +- Each Plug-in or Fragment may be packaged as a sub-directory or JAR\n\ + (Java\u2122 ARchive) in a directory named "plugins".\n\ +- A Feature is a bundle of one or more Plug-ins and/or Fragments and\n\ + associated material. Each Feature may be packaged as a sub-directory in a\n\ + directory named "features". Within a Feature, files named "feature.xml" may\n\ + contain a list of the names and version numbers of the Plug-ins and/or\n\ + Fragments associated with that Feature.\n\ +- Features may also include other Features ("Included Features"). Within a\n\ + Feature, files named "feature.xml" may contain a list of the names and\n\ + version numbers of Included Features.\n\ +\n\ +The terms and conditions governing Plug-ins and Fragments should be contained in\n\ +files named "about.html" ("Abouts"). The terms and conditions governing Features\n\ +and Included Features should be contained in files named "license.html"\n\ +("Feature Licenses"). Abouts and Feature Licenses may be located in any\n\ +directory of a Download or Module including, but not limited to the following\n\ +locations:\n\ +\n\ +- The top-level (root) directory\n\ +- Plug-in and Fragment directories\n\ +- Inside Plug-ins and Fragments packaged as JARs\n\ +- Sub-directories of the directory named "src" of certain Plug-ins\n\ +- Feature directories\n\ +\n\ +Note: if a Feature made available by the Eclipse Foundation is installed using\n\ +the Provisioning Technology (as defined below), you must agree to a license\n\ +("Feature Update License") during the installation process. If the Feature\n\ +contains Included Features, the Feature Update License should either provide you\n\ +with the terms and conditions governing the Included Features or inform you\n\ +where you can locate them. Feature Update Licenses may be found in the "license"\n\ +property of files named "feature.properties" found within a Feature. Such\n\ +Abouts, Feature Licenses, and Feature Update Licenses contain the terms and\n\ +conditions (or references to such terms and conditions) that govern your use of\n\ +the associated Content in that directory.\n\ +\n\ +THE ABOUTS, FEATURE LICENSES, AND FEATURE UPDATE LICENSES MAY REFER TO THE EPL\n\ +OR OTHER LICENSE AGREEMENTS, NOTICES OR TERMS AND CONDITIONS. SOME OF THESE\n\ +OTHER LICENSE AGREEMENTS MAY INCLUDE (BUT ARE NOT LIMITED TO):\n\ +\n\ +- Eclipse Public License Version 1.0 (available at\n\ + http://www.eclipse.org/legal/epl-v10.html)\n\ +- Eclipse Distribution License Version 1.0 (available at\n\ + http://www.eclipse.org/licenses/edl-v1.0.html)\n\ +- Common Public License Version 1.0 (available at\n\ + http://www.eclipse.org/legal/cpl-v10.html)\n\ +- Apache Software License 1.1 (available at\n\ + http://www.apache.org/licenses/LICENSE)\n\ +- Apache Software License 2.0 (available at\n\ + http://www.apache.org/licenses/LICENSE-2.0)\n\ +- Mozilla Public License Version 1.1 (available at\n\ + http://www.mozilla.org/MPL/MPL-1.1.html)\n\ +\n\ +IT IS YOUR OBLIGATION TO READ AND ACCEPT ALL SUCH TERMS AND CONDITIONS PRIOR TO\n\ +USE OF THE CONTENT. If no About, Feature License, or Feature Update License is\n\ +provided, please contact the Eclipse Foundation to determine what terms and\n\ +conditions govern that particular Content.\n\ +\n\ +Use of Provisioning Technology\n\ +\n\ +The Eclipse Foundation makes available provisioning software, examples of which\n\ +include, but are not limited to, p2 and the Eclipse Update Manager\n\ +("Provisioning Technology") for the purpose of allowing users to install\n\ +software, documentation, information and/or other materials (collectively\n\ +"Installable Software"). This capability is provided with the intent of allowing\n\ +such users to install, extend and update Eclipse-based products. Information\n\ +about packaging Installable Software is available at\n\ +http://eclipse.org/equinox/p2/repository_packaging.html ("Specification").\n\ +\n\ +You may use Provisioning Technology to allow other parties to install\n\ +Installable Software. You shall be responsible for enabling the applicable\n\ +license agreements relating to the Installable Software to be presented to, and\n\ +accepted by, the users of the Provisioning Technology in accordance with the\n\ +Specification. By using Provisioning Technology in such a manner and making it\n\ +available in accordance with the Specification, you further acknowledge your\n\ +agreement to, and the acquisition of all necessary rights to permit the\n\ +following:\n\ +\n\ +1. A series of actions may occur ("Provisioning Process") in which a user may\n\ + execute the Provisioning Technology on a machine ("Target Machine") with the\n\ + intent of installing, extending or updating the functionality of an\n\ + Eclipse-based product.\n\ +2. During the Provisioning Process, the Provisioning Technology may cause third\n\ + party Installable Software or a portion thereof to be accessed and copied to\n\ + the Target Machine.\n\ +3. Pursuant to the Specification, you will provide to the user the terms and\n\ + conditions that govern the use of the Installable Software ("Installable\n\ + Software Agreement") and such Installable Software Agreement shall be\n\ + accessed from the Target Machine in accordance with the Specification. Such\n\ + Installable Software Agreement must inform the user of the terms and\n\ + conditions that govern the Installable Software and must solicit acceptance\n\ + by the end user in the manner prescribed in such Installable\n\ + Software Agreement. Upon such indication of agreement by the user, the\n\ + provisioning Technology will complete installation of the\n\ + Installable Software.\n\ +\n\ +Cryptography\n\ +\n\ +Content may contain encryption software. The country in which you are currently\n\ +may have restrictions on the import, possession, and use, and/or re-export to\n\ +another country, of encryption software. BEFORE using any encryption software,\n\ +please check the country's laws, regulations and policies concerning the import,\n\ +possession, or use, and re-export of encryption software, to see if this is\n\ +permitted.\n\ +\n\ +Java and all Java-based trademarks are trademarks of Oracle Corporation in the\n\ +United States, other countries, or both.\n +########### end of license property ########################################## diff --git a/mylyn.tasks/connectors/gitlab/org.eclipse.mylyn.gitlab.feature/feature.xml b/mylyn.tasks/connectors/gitlab/org.eclipse.mylyn.gitlab.feature/feature.xml index 2979fcb16a..31a557e277 100644 --- a/mylyn.tasks/connectors/gitlab/org.eclipse.mylyn.gitlab.feature/feature.xml +++ b/mylyn.tasks/connectors/gitlab/org.eclipse.mylyn.gitlab.feature/feature.xml @@ -1,21 +1,33 @@ + - - [Enter Feature Description here.] + + %description - - [Enter Copyright Description here.] + + %copyright - - [Enter License Description here.] + + %license =UTF-8 diff --git a/mylyn.tasks/connectors/gitlab/org.eclipse.mylyn.gitlab.source.feature/build.properties b/mylyn.tasks/connectors/gitlab/org.eclipse.mylyn.gitlab.source.feature/build.properties new file mode 100644 index 0000000000..560dde240e --- /dev/null +++ b/mylyn.tasks/connectors/gitlab/org.eclipse.mylyn.gitlab.source.feature/build.properties @@ -0,0 +1,9 @@ +############################################################################### +# Copyright (c) 2023 Frank Becker and others. +# All rights reserved. This program and the accompanying materials +# are made available under the terms of the Eclipse Public License v2.0 +# which accompanies this distribution, and is available at +# http://www.eclipse.org/legal/epl-v20.html +############################################################################### +bin.includes = feature.xml,\ + feature.properties diff --git a/mylyn.tasks/connectors/gitlab/org.eclipse.mylyn.gitlab.source.feature/feature.properties b/mylyn.tasks/connectors/gitlab/org.eclipse.mylyn.gitlab.source.feature/feature.properties new file mode 100644 index 0000000000..9a6b78c3b0 --- /dev/null +++ b/mylyn.tasks/connectors/gitlab/org.eclipse.mylyn.gitlab.source.feature/feature.properties @@ -0,0 +1,178 @@ +############################################################################### +# Copyright (c) 2011, 2023 Chris Aniszczyk and others. +# All rights reserved. This program and the accompanying materials +# are made available under the terms of the Eclipse Public License 2.0 +# which accompanies this distribution, and is available at +# https://www.eclipse.org/legal/epl-2.0/ +# +# SPDX-License-Identifier: EPL-2.0 +############################################################################### + +featureName=Mylyn Tasks Connector: Gitlab SDK Preview for gitlab.com only +providerName=Eclipse Mylyn + +updateSiteName=Eclipse Mylyn Update Site + +# description property - text of the "Feature Description" +description=Mylyn Task Connector SDK for Gitlab +################ end of description property ################################## + +# "copyright" property - text of the "Feature Update Copyright" +copyright=\ +Copyright (c) 2023 Frank Becker, et.al.\n\ +All rights reserved. This program and the accompanying materials\n\ +are made available under the terms of the Eclipse Public License 2.0\n\ +which accompanies this distribution, and is available at\n\ +https://www.eclipse.org/legal/epl-2.0/\n\ +\n\ +SPDX-License-Identifier: EPL-2.0\n +################ end of copyright property #################################### + +# "licenseURL" property - URL of the "Feature License" +# do not translate value - just change to point to a locale-specific HTML page +licenseURL=license.html + +# "license" property - text of the "Feature Update License" +# should be plain text version of license agreement pointed to be "licenseURL" +license=\ +Eclipse Foundation Software User Agreement\n\ +\n\ +November 22, 2017\n\ +\n\ +Usage Of Content\n\ +\n\ +THE ECLIPSE FOUNDATION MAKES AVAILABLE SOFTWARE, DOCUMENTATION, INFORMATION\n\ +AND/OR OTHER MATERIALS FOR OPEN SOURCE PROJECTS (COLLECTIVELY "CONTENT"). USE OF\n\ +THE CONTENT IS GOVERNED BY THE TERMS AND CONDITIONS OF THIS AGREEMENT AND/OR THE\n\ +TERMS AND CONDITIONS OF LICENSE AGREEMENTS OR NOTICES INDICATED OR REFERENCED\n\ +BELOW. BY USING THE CONTENT, YOU AGREE THAT YOUR USE OF THE CONTENT IS GOVERNED\n\ +BY THIS AGREEMENT AND/OR THE TERMS AND CONDITIONS OF ANY APPLICABLE LICENSE\n\ +AGREEMENTS OR NOTICES INDICATED OR REFERENCED BELOW. IF YOU DO NOT AGREE TO THE\n\ +TERMS AND CONDITIONS OF THIS AGREEMENT AND THE TERMS AND CONDITIONS OF ANY\n\ +APPLICABLE LICENSE AGREEMENTS OR NOTICES INDICATED OR REFERENCED BELOW, THEN YOU\n\ +MAY NOT USE THE CONTENT.\n\ +\n\ +Applicable Licenses\n\ +\n\ +Unless otherwise indicated, all Content made available by the Eclipse Foundation\n\ +is provided to you under the terms and conditions of the Eclipse Public License\n\ +Version 2.0 ("EPL"). A copy of the EPL is provided with this Content and is also\n\ +available at http://www.eclipse.org/legal/epl-2.0. For purposes of the EPL,\n\ +"Program" will mean the Content.\n\ +\n\ +Content includes, but is not limited to, source code, object code, documentation\n\ +and other files maintained in the Eclipse Foundation source code repository\n\ +("Repository") in software modules ("Modules") and made available as\n\ +downloadable archives ("Downloads").\n\ +\n\ +- Content may be structured and packaged into modules to facilitate\n\ + delivering, extending, and upgrading the Content. Typical modules may\n\ + include plug-ins ("Plug-ins"), plug-in fragments ("Fragments"), and\n\ + features ("Features").\n\ +- Each Plug-in or Fragment may be packaged as a sub-directory or JAR\n\ + (Java\u2122 ARchive) in a directory named "plugins".\n\ +- A Feature is a bundle of one or more Plug-ins and/or Fragments and\n\ + associated material. Each Feature may be packaged as a sub-directory in a\n\ + directory named "features". Within a Feature, files named "feature.xml" may\n\ + contain a list of the names and version numbers of the Plug-ins and/or\n\ + Fragments associated with that Feature.\n\ +- Features may also include other Features ("Included Features"). Within a\n\ + Feature, files named "feature.xml" may contain a list of the names and\n\ + version numbers of Included Features.\n\ +\n\ +The terms and conditions governing Plug-ins and Fragments should be contained in\n\ +files named "about.html" ("Abouts"). The terms and conditions governing Features\n\ +and Included Features should be contained in files named "license.html"\n\ +("Feature Licenses"). Abouts and Feature Licenses may be located in any\n\ +directory of a Download or Module including, but not limited to the following\n\ +locations:\n\ +\n\ +- The top-level (root) directory\n\ +- Plug-in and Fragment directories\n\ +- Inside Plug-ins and Fragments packaged as JARs\n\ +- Sub-directories of the directory named "src" of certain Plug-ins\n\ +- Feature directories\n\ +\n\ +Note: if a Feature made available by the Eclipse Foundation is installed using\n\ +the Provisioning Technology (as defined below), you must agree to a license\n\ +("Feature Update License") during the installation process. If the Feature\n\ +contains Included Features, the Feature Update License should either provide you\n\ +with the terms and conditions governing the Included Features or inform you\n\ +where you can locate them. Feature Update Licenses may be found in the "license"\n\ +property of files named "feature.properties" found within a Feature. Such\n\ +Abouts, Feature Licenses, and Feature Update Licenses contain the terms and\n\ +conditions (or references to such terms and conditions) that govern your use of\n\ +the associated Content in that directory.\n\ +\n\ +THE ABOUTS, FEATURE LICENSES, AND FEATURE UPDATE LICENSES MAY REFER TO THE EPL\n\ +OR OTHER LICENSE AGREEMENTS, NOTICES OR TERMS AND CONDITIONS. SOME OF THESE\n\ +OTHER LICENSE AGREEMENTS MAY INCLUDE (BUT ARE NOT LIMITED TO):\n\ +\n\ +- Eclipse Public License Version 1.0 (available at\n\ + http://www.eclipse.org/legal/epl-v10.html)\n\ +- Eclipse Distribution License Version 1.0 (available at\n\ + http://www.eclipse.org/licenses/edl-v1.0.html)\n\ +- Common Public License Version 1.0 (available at\n\ + http://www.eclipse.org/legal/cpl-v10.html)\n\ +- Apache Software License 1.1 (available at\n\ + http://www.apache.org/licenses/LICENSE)\n\ +- Apache Software License 2.0 (available at\n\ + http://www.apache.org/licenses/LICENSE-2.0)\n\ +- Mozilla Public License Version 1.1 (available at\n\ + http://www.mozilla.org/MPL/MPL-1.1.html)\n\ +\n\ +IT IS YOUR OBLIGATION TO READ AND ACCEPT ALL SUCH TERMS AND CONDITIONS PRIOR TO\n\ +USE OF THE CONTENT. If no About, Feature License, or Feature Update License is\n\ +provided, please contact the Eclipse Foundation to determine what terms and\n\ +conditions govern that particular Content.\n\ +\n\ +Use of Provisioning Technology\n\ +\n\ +The Eclipse Foundation makes available provisioning software, examples of which\n\ +include, but are not limited to, p2 and the Eclipse Update Manager\n\ +("Provisioning Technology") for the purpose of allowing users to install\n\ +software, documentation, information and/or other materials (collectively\n\ +"Installable Software"). This capability is provided with the intent of allowing\n\ +such users to install, extend and update Eclipse-based products. Information\n\ +about packaging Installable Software is available at\n\ +http://eclipse.org/equinox/p2/repository_packaging.html ("Specification").\n\ +\n\ +You may use Provisioning Technology to allow other parties to install\n\ +Installable Software. You shall be responsible for enabling the applicable\n\ +license agreements relating to the Installable Software to be presented to, and\n\ +accepted by, the users of the Provisioning Technology in accordance with the\n\ +Specification. By using Provisioning Technology in such a manner and making it\n\ +available in accordance with the Specification, you further acknowledge your\n\ +agreement to, and the acquisition of all necessary rights to permit the\n\ +following:\n\ +\n\ +1. A series of actions may occur ("Provisioning Process") in which a user may\n\ + execute the Provisioning Technology on a machine ("Target Machine") with the\n\ + intent of installing, extending or updating the functionality of an\n\ + Eclipse-based product.\n\ +2. During the Provisioning Process, the Provisioning Technology may cause third\n\ + party Installable Software or a portion thereof to be accessed and copied to\n\ + the Target Machine.\n\ +3. Pursuant to the Specification, you will provide to the user the terms and\n\ + conditions that govern the use of the Installable Software ("Installable\n\ + Software Agreement") and such Installable Software Agreement shall be\n\ + accessed from the Target Machine in accordance with the Specification. Such\n\ + Installable Software Agreement must inform the user of the terms and\n\ + conditions that govern the Installable Software and must solicit acceptance\n\ + by the end user in the manner prescribed in such Installable\n\ + Software Agreement. Upon such indication of agreement by the user, the\n\ + provisioning Technology will complete installation of the\n\ + Installable Software.\n\ +\n\ +Cryptography\n\ +\n\ +Content may contain encryption software. The country in which you are currently\n\ +may have restrictions on the import, possession, and use, and/or re-export to\n\ +another country, of encryption software. BEFORE using any encryption software,\n\ +please check the country's laws, regulations and policies concerning the import,\n\ +possession, or use, and re-export of encryption software, to see if this is\n\ +permitted.\n\ +\n\ +Java and all Java-based trademarks are trademarks of Oracle Corporation in the\n\ +United States, other countries, or both.\n +########### end of license property ########################################## diff --git a/mylyn.tasks/connectors/gitlab/org.eclipse.mylyn.gitlab.source.feature/feature.xml b/mylyn.tasks/connectors/gitlab/org.eclipse.mylyn.gitlab.source.feature/feature.xml new file mode 100644 index 0000000000..0b3be1080f --- /dev/null +++ b/mylyn.tasks/connectors/gitlab/org.eclipse.mylyn.gitlab.source.feature/feature.xml @@ -0,0 +1,51 @@ + + + + + + %description + + + + %copyright + + + + %license + + + + + + + + + diff --git a/mylyn.tasks/connectors/gitlab/org.eclipse.mylyn.gitlab.ui/META-INF/MANIFEST.MF b/mylyn.tasks/connectors/gitlab/org.eclipse.mylyn.gitlab.ui/META-INF/MANIFEST.MF index b098064b1b..0b35ea0322 100644 --- a/mylyn.tasks/connectors/gitlab/org.eclipse.mylyn.gitlab.ui/META-INF/MANIFEST.MF +++ b/mylyn.tasks/connectors/gitlab/org.eclipse.mylyn.gitlab.ui/META-INF/MANIFEST.MF @@ -4,19 +4,19 @@ Bundle-Name: Gitlab Connector UI Bundle-SymbolicName: org.eclipse.mylyn.gitlab.ui;singleton:=true Bundle-Version: 4.0.0.qualifier Export-Package: org.eclipse.mylyn.gitlab.ui +Import-Package: org.apache.commons.lang Bundle-Activator: org.eclipse.mylyn.gitlab.ui.GitlabUiActivator -Require-Bundle: org.eclipse.ui, - org.eclipse.core.runtime, - org.eclipse.mylyn.tasks.ui, - org.eclipse.mylyn.tasks.core, - org.eclipse.ui.forms;bundle-version="3.11.500", - org.eclipse.mylyn.gitlab.core;bundle-version="1.0.0", - com.google.guava, - org.eclipse.mylyn.commons.workbench;bundle-version="4.0.0", - org.eclipse.mylyn.commons.ui;bundle-version="4.0.0", +Require-Bundle: org.eclipse.core.runtime, + org.eclipse.jdt.annotation, org.eclipse.mylyn.commons.core;bundle-version="4.0.0", org.eclipse.mylyn.commons.identity.core;bundle-version="4.0.0", - org.eclipse.jdt.annotation + org.eclipse.mylyn.commons.ui;bundle-version="4.0.0", + org.eclipse.mylyn.commons.workbench;bundle-version="4.0.0", + org.eclipse.mylyn.gitlab.core;bundle-version="1.0.0", + org.eclipse.mylyn.tasks.core, + org.eclipse.mylyn.tasks.ui, + org.eclipse.ui, + org.eclipse.ui.forms;bundle-version="3.11.500" Bundle-RequiredExecutionEnvironment: JavaSE-17 Automatic-Module-Name: org.eclipse.mylyn.gitlab.ui Bundle-ActivationPolicy: lazy diff --git a/mylyn.tasks/connectors/gitlab/org.eclipse.mylyn.gitlab.ui/build.properties b/mylyn.tasks/connectors/gitlab/org.eclipse.mylyn.gitlab.ui/build.properties index e9863e281e..632074d169 100644 --- a/mylyn.tasks/connectors/gitlab/org.eclipse.mylyn.gitlab.ui/build.properties +++ b/mylyn.tasks/connectors/gitlab/org.eclipse.mylyn.gitlab.ui/build.properties @@ -1,3 +1,10 @@ +############################################################################### +# Copyright (c) 2023 Frank Becker and others. +# All rights reserved. This program and the accompanying materials +# are made available under the terms of the Eclipse Public License v2.0 +# which accompanies this distribution, and is available at +# http://www.eclipse.org/legal/epl-v20.html +############################################################################### source.. = src/ output.. = bin/ bin.includes = META-INF/,\ diff --git a/mylyn.tasks/connectors/gitlab/org.eclipse.mylyn.gitlab.ui/icons/eview16/gitlab-icon.png b/mylyn.tasks/connectors/gitlab/org.eclipse.mylyn.gitlab.ui/icons/eview16/gitlab-icon.png deleted file mode 100644 index 27d96cd19201704c0217f8e1944a07a1b0709f33..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 1019 zcmVEX>4Tx04R}tkv&MmKp2MKrb>%c9qb_DkfDl$1yK=4twIqhgj%6h2a`*GgeDD1 zii@M*T5#}ZvFhOBtgC~oAPD||xVktgx=4xNC509--f`T+d*AzV_Z=YA%S^L6#sE#X z&2%y$W^*fI=oKM^(L-}YW|lE4Nh$b_uX_aeei!Fi{&jzjZZ&T)ARrRYFvGNo*NLY# zZG-bZag>#0mH3=^)T9d%KXP61_>FVXWr1f#%}jcZI7%!Q+gNF1Rx&l>N#dBQ>69;I zJytnyan{OJ*1RWwVI;3FFL9mLAd*J%U`Jj)1Rc* zT3YM~=-mb`u3MV22VCv|{ZEE$%B~coB@_z4`x$*x4(PiDx>miuHP3PS0A#3FsT<(n z5Ew2}_L|ST!|i?hx2D;@A3*nVlg?=w3;+NC24YJ`L;(K){{a7>y{D4^000SaNLh0L z01FZT01FZU(%pXi00007bV*G`2j>R}4=*g6nP%1i000?uMObu0Z*6U5Zgc=ca%Ew3 zWn>_CX>@2HM@dakSAh-}0005fNkl%s&v(LJL#bh?Rwvf}n-5P|*ApffOmy#lIkUg^-0{k0Oi0W?f(D~>|Hpj{u>GRFq6VRADl0ZsFF zLo|W+aTNZ@ap%q55Szdo;4~u`EUBoM$Z{_c(mnuH;Qo}hu^n)Iz3lor0zPM2b}D*( zW==`aPH|^7e}g-#3EC+$b4r|wULR{&gan{ehDJ+~R4sm;3+g)e*(LCr8vjPdDaqJS zv|@ks!mlgpErnClgLw)#HBG&x@atJIlRIXcBQ)>+hzhu#rarIm0*x08_O53N3|}_L zIm!zPz~$qccFEBXM0g7fEMo&prsQ`Z9eJ7N>2+WBDj&b4g@Qv|?R3_}<`q77XyH;b zj0@n59zQwODbLHh-LI2|Ciy`BS*K;Sd4kU)#Q08g&IO;;DIc8I-Lq*fkfPw#mrezX pdm`)tXw43agYv`fCI9iy@f(&XfvJ%Cy)6I$002ovPDHLkV1hK3!odIl diff --git a/mylyn.tasks/connectors/gitlab/org.eclipse.mylyn.gitlab.ui/icons/eview16/gitlab-icon38.png b/mylyn.tasks/connectors/gitlab/org.eclipse.mylyn.gitlab.ui/icons/eview16/gitlab-icon38.png deleted file mode 100644 index 8a7f2ce79218dee97db08b19d81cfe6ccaf3cd1e..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 1130 zcmV-w1eN=VP)EX>4Tx04R}tkv&MmKp2MKrb>%c9qb_DkfDl$1yK=4twIqhgj%6h2a`*GgeDD1 zii@M*T5#}ZvFhOBtgC~oAPD||xVktgx=4xNC509--f`T+d*AzV_Z=YA%S^L6#sE#X z&2%y$W^*fI=oKM^(L-}YW|lE4Nh$b_uX_aeei!Fi{&jzjZZ&T)ARrRYFvGNo*NLY# zZG-bZag>#0mH3=^)T9d%KXP61_>FVXWr1f#%}jcZI7%!Q+gNF1Rx&l>N#dBQ>69;I zJytnyan{OJ*1RWwVI;3FFL9mLAd*J%U`Jj)1Rc* zT3YM~=-mb`u3MV22VCv|{ZEE$%B~coB@_z4`x$*x4(PiDx>miuHP3PS0A#3FsT<(n z5Ew2}_L|ST!|i?hx2D;@A3*nVlg?=w3;+NC24YJ`L;(K){{a7>y{D4^000SaNLh0L z01FZT01FZU(%pXi00007bV*G`2j>R}4+9bUz(HvM000?uMObu0Z*6U5Zgc=ca%Ew3 zWn>_CX>@2HM@dakSAh-}0006(NklFU3xK)Q)+CQw5AqXu8B+6 zEJ7g;ZkdF(LUA!g1^)s63qgyOfQ#6nI=gfighHprpi5HJMG6M0z4YGKAs3q_sktOq z$Z+5Bx#!3C`Ek#42LS>E2oPX2P|0PcE4j?{Md>#Y8i3n7pbp&fsQ(r)fNVcOM4#1K z07`%auFvf3fA6861P%ZV$jt2Qm%PT(`mEM^i(TG>e!e9}p`SpWiB)dj)PdC&(OnN_ ztvai&51%WhR34aYkt|hmnTh|jaROLs5ly;2d>{U`E=fJDC@;_@{`bQ})9 zX&l$QZJMyD7@v}8dUI5eitsQok0A(oPu3DwiiOekWhQ&R1|hOU@&_@uQ>mw8oU zL?3^}#coHNB8vE&gAqL?U_=|TZlqA`+DH1fuP4cV zWF<7655Qu#=e3`W9L<B?o1gz&$PsU%{@7X;8k>Mg)Fl;eJ_No3zZ!*9lET>Y@>bs~X3$M}{Lo74Q*3dA z#SSkDsIuoAupHhfmj>~#4N5G$Q7+Z5h^&$nJ7!!`teYY`D5;?;cBZwjt$RY_rAumk w?0)&p$b53!MQheBTC>5=M}PnU0*pBR0#QSx$_X9%i~s-t07*qoM6N<$f=^NWX8-^I diff --git a/mylyn.tasks/connectors/gitlab/org.eclipse.mylyn.gitlab.ui/icons/eview16/gitlab-overlay.png b/mylyn.tasks/connectors/gitlab/org.eclipse.mylyn.gitlab.ui/icons/eview16/gitlab-overlay.png index 1db15b8676ff3af64ef773ad6858f03b7d037a54..893fd16d93a0077228f8ebca483c737231103ab7 100644 GIT binary patch literal 1230 zcmeAS@N?(olHy`uVBq!ia0vp^93afW3?x5a^xMh6z}S-M>>S|f?5t2wl%JNFlghxL zF|l@{t;b;pnWOQ+OBacXfreA# zM48ufEZ~ooIJDx7Pp#jiM;~P3zkm4nRqxQ|J?H;g?lO*?%xE{UV%p0#*FBCldoy3o z`QGWgMj^f9eCKhVT?!wSuZvEHX9? z<+S9v=s8z|T20@bjF&i*rF}YPxn+lh*hUskC6SN-7fvyyEm=!ucwDHva@hXC57i>g zCt6JtlNnQ2OpvwzA^+#ywKKkcJ3J3+T=de*kuH88P zl6k_Cb&t#s98@%zwERtJe|h?_*Pw^v~i0|QfffKP}kFnWOCk+bF_ zCymF>nvWecAG+v1cGZ0BqWREC^O=X{Gf&MwOVqvus(+1F|Fc-_HxMmS|Gh;0?_$+I zbJYG!Q~NVt?au4lc)A6R{e7v$ZLNVs{LtH`;o2&H0MtfSOG-YT(v({ zYJYOoUI%Kt2I`#$lbWvfr&#S{j5^Q+sDTjmK)dqQex#{Ab=UmU4^s@0TBP=;P3=#P z+AE+@ff|3>QDuQ@fPq=7_Ay%hQ;a&00Ss6alV^d9eF8MLTlpR4w}O6{ee1`q++e}GP1ruKKL+J^-7 z4~go3maF|+qxPjp{Y$YrB(8y>^s`9qXS&+Y3^kCA!0-vu07eAJz&wy2L7`oy_NQ6x z|NsBj?(zEp(-~t)kY6x^!?PP{AWo9Ey9+}HtE>l*!&%@FSbCYGe8D3oWGWGJ|M`UZqI@`(c# zX?wajhHzX@PH13OlVD7L^C&s#(QVe04w0QZL^>N<(skl&m>1Q2&tp?zVA!{TUG~}i R7FM7(22WQ%mvv4FO#t&sIwb%A delta 709 zcmV;$0y_Q93HAk$8Gi-<006`fzKZ|=0flKpLr_UWLm+T+Z)Rz1WdHyuk$sUpNW(xF zhTo=2i&P!#AmWgrih~7F5l5{;5h{dQp;ZTyOMiqW4M~cNqu^R_@Mp2=;Nq;SgR3A2 z{(!i;I4QbFiQgrK7BSv&+{1g{`*QakAk@oDvpU8AO}EW-GJhdvb1P!#6(NMtLvuuC zmN6?yDfo`Bdj$A?7w1|2b$^a-HE%H>AQI0o!?cOliKjMggY!Odl$B(a_?&puqze*1 za$WKGjdRgufoDd|OnQzuN-P%JSZQNcGBx5!;+U%GlrLmGRyl8R*2-1ZyeEHQB(EJ%U`Jj)1Rc*T3YM~=-mb`u3MV22VCv| z{ZEE$%B~coB@_z4`x$*x4(PiDx>miuHP3PS0A#3Fsa6}{;1C!tQudn9yTk2$`?sdq zzaK#Na+A(!84Lgb00v@9M??Vs0RI60puMM)00009a7bBm000XT000XT0n*)m`~Uy| z2XskIMF-~x2oEG3DYL&PlV$`cf6YlmK~xyiO^q>1!vGjY-=Cx@0VAZr$x@sm$s%6B zCDJVysC5t=yR}=c;3%#RqNnK83%Ds{DzRHJf)OE<o+~yYlE(#00oc=z-AJJ;_=K0=LoRmRST{< r_u2dZ@#Zn`#N-Y@Yi6CB>pPEl zQ}6%oQT}4*h!;C8_7^c2&Y@b=KWCM(V;v~JDj!#E_@(Kr(r2E}4^?(6vp#;)7R_xx zzU^65-L7md`+IvwANO#%z>)29|9GuYY&z4`95i6@(~;&6GK-EfH1&mEL6)uXO;3BM z?4hKQFs-Qn+}g}naq1%ytk&Ki$MADD&xf5AD>@hBqHn_=T}>i>$ByKbzq?9z59nC0 z&vt64Q@%l=-sQ~xj@Msx@+bUFKMl|K^tO&N3v2HTe)6QzdwX%+_{jo;;r{&m#Faf~ zgL3k9_wpNfH5g{6l}p2g=y=dGNRfjf#1KUe@yVA0{~;kcBp_dgki%kfSVF>DFss1l zqH%Z~SdrD>)>?e|x*x0r@G^j319%PCzVM?#{zpUf*4iN_gdC9)uV}UeB9HbF?UB92 zQUO@d;K*Of2Z%fx1g3y-B|-bhasf;P(}(eyBlKvn8o&%-(E@}6Gyf}CExQWfX#f+z zn1UEX|5m+Cl>?XxrlN3!um-qVk9s8mODuRLB4NSX;?-0QfENKg0scWy3Icw)K8tFQ znCW2Z5I!A+BL@k)4!MGcH6vI9fEDXgCBTYcpPEl zQ}6%oQT}4*h!;C8_7^c2&Y@b=KWCM(V;v~JDj!#E_@(Kr(r2E}4^?(6vp#;)7R_xx zzU^65-L7md`+IvwANO#%z>)29|9GuYY&z4`95i6@(~;&6GK-EfH1&mEL6)uXO;3BM z?4hKQFs-Qn+}g}naq1%ytk&Ki$MADD&xf5AD>@hBqHn_=T}>i>$ByKbzq?9z59nC0 z&vt64Q@%l=-sQ~xj@Msx@+bUFKMl|K^tO&N3v2HTe)6QzdwX%+_{jo;;r{&m#Faf~ zgL3k9_wpNfH5g{6l}p2g=y=dGNRfjf#1KUe@yVA0{~;kcBp_dgki%kfSVF>DFss1l zqH%Z~SdrD>)>?e|x*x0r@G^j319%PCzVM?#{zpUf*4iN_gdC9)uV}UeB9HbF?UB92 zQUO@d;K*Of2Z%fx1g3y-B|-bhasf;P(}(eyBlKvn8o&%-(E@}6Gyf}CExQWfX#f+z zn1UEX|5m+Cl>?XxrlN3!um-qVk9s8mODuRLB4NSX;?-0QfENKg0scWy3Icw)K8tFQ znCW2Z5I!A+BL@k)4!MGcH6vI9fEDXgCBTYc+0L>B0N90!gfcwSsbOP@|AiI1uHtE&G9V%VfOE!)NN$DKG@UF&0M7jC{FGuQ zh-47}WI+IOwgWJPw{kiG$RGiD76$--KL9hd2QNw&0$`CS36BiIgtkCtn}E?C$ZTKC zY!$NFgP83?W~+etSj2oB%0v~gPfGO15~v&w<2XtTR}iLhcXSY<5{QmKR0>Bnx>F+m zV_yC6!1ucC?G z80u=M45C~(poCZlZGB4^r5%DO3!)U*C1rHsvxonI_CchBJ!=W9@J?`)k85e*KoaZ- zVIt!{~7e-n!vIq+<{RiWmIP#1vB3*@%|w=oCTkX88~o`u+>Uv+6%kmh;BK7 zjzjZl*q2W9>4?#1jk`3M4hNNRPz9-qxIZ!meh`#kDs@My+v_3P21iClek3-0h2OIp zy-d6e&;R+0C?_84O*JV4V+l8LWKd5zBd!%N+-t^7bXfE& z!YH~s>+;T{fx)Y%hvw`F635V%=WabZ%|ozVx=LZ3chcg5|GXO_+a|BqswH!0Gf!Ly z37pNYyH;7HG@fxeZ{h#IKfCXqeC`+H^Ri#hbaL|`?_s2jwl?>KQ=uj`m;Akc8Y6Ce zueDqG{K88OH)fU9HQRn1f7xbg>)8vIX)os3+d97pn7h8(IgWk2s5i!5o0hT7VnycJ zoGR-XqQhS|=>9TWE^g^av9fv?LpPf@EvhjrwldUiwl+=4t!s75u4@s2{assb|2E?^ zo$OR;Z6qx#znLn`mEPsr`wXZgbP3HhcA&9*>K-~v+GuapD5b}Q|J+!9&S02iNb3nP zxB^109%5E(^)91p*yENpKPA1m*gyM^l(kj)Mw&;9!^0XyS2gR; zAni5F+|GhSm)7s(w$R!xW$yNrI04|_G;+S7%I+C{o80w5EA@$Ty@H>RuD}!Ekvx(` za#>t5lIzX)^y7Q-JV=sHl5_5e0>>Ok(Il#qHvad4V$Q4Z?+HHm*q$2kz79($-`CYQm!{$rPpiu98P9tCR)gY^7$%-TB*_lFD|d{wnU0KGv3pA z$629H)T=0pv%&H{rZ~MviBP8~^c%Gb@YWSao2vZue3bYDorp-x0$eX2UvHoJo<6)K z7d!Bm5IDT2vrL^uwVCZ5CJ^MkG!9@m{5^QNEEFWElNGoHY)*zYStC!>alE`azVYjI zp7JOTk4yS+C_*e{CRVA|C(Gkw)d`x^Sgt4O<>SZ3&J5)BTC58~gT%r!g1D`J1HqkV AhX4Qo literal 0 HcmV?d00001 diff --git a/mylyn.tasks/connectors/gitlab/org.eclipse.mylyn.gitlab.ui/plugin.xml b/mylyn.tasks/connectors/gitlab/org.eclipse.mylyn.gitlab.ui/plugin.xml index 4549ae35f2..3587144337 100644 --- a/mylyn.tasks/connectors/gitlab/org.eclipse.mylyn.gitlab.ui/plugin.xml +++ b/mylyn.tasks/connectors/gitlab/org.eclipse.mylyn.gitlab.ui/plugin.xml @@ -18,8 +18,8 @@ name="Gitlab Respository" point="org.eclipse.mylyn.tasks.ui.repositories"> @@ -27,7 +27,7 @@ diff --git a/mylyn.tasks/connectors/gitlab/org.eclipse.mylyn.gitlab.ui/src/org/eclipse/mylyn/gitlab/ui/GitlabImages.java b/mylyn.tasks/connectors/gitlab/org.eclipse.mylyn.gitlab.ui/src/org/eclipse/mylyn/gitlab/ui/GitlabImages.java index c2f63da30a..a771b73e22 100644 --- a/mylyn.tasks/connectors/gitlab/org.eclipse.mylyn.gitlab.ui/src/org/eclipse/mylyn/gitlab/ui/GitlabImages.java +++ b/mylyn.tasks/connectors/gitlab/org.eclipse.mylyn.gitlab.ui/src/org/eclipse/mylyn/gitlab/ui/GitlabImages.java @@ -1,85 +1,42 @@ +/******************************************************************************* + * Copyright (c) 2023 Frank Becker and others. + * + * This program and the accompanying materials are made available under the + * terms of the Eclipse Public License v. 2.0 which is available at + * https://www.eclipse.org/legal/epl-2.0 + * + * SPDX-License-Identifier: EPL-2.0 + * + * Contributors: + * Frank Becker - initial API and implementation + *******************************************************************************/ package org.eclipse.mylyn.gitlab.ui; -import java.net.MalformedURLException; -import java.net.URL; - -import org.eclipse.core.runtime.Platform; import org.eclipse.jface.resource.ImageDescriptor; import org.eclipse.jface.resource.ImageRegistry; -import org.eclipse.mylyn.commons.ui.CommonImages; -import org.eclipse.mylyn.internal.commons.ui.CommonsUiConstants; import org.eclipse.swt.graphics.Image; -import org.osgi.framework.Bundle; public class GitlabImages { - private static final URL baseUrl; - static { - Bundle bundle = Platform.getBundle(GitlabUiActivator.PLUGIN_ID); - if (bundle != null) { - baseUrl = bundle.getEntry("/icons/"); //$NON-NLS-1$ - } else { - URL iconsUrl = null; - try { - // lookup location of CommonImages class on disk - iconsUrl = new URL(GitlabImages.class.getResource("GitlabImages.class"), "../../../../../../icons/"); //$NON-NLS-1$ //$NON-NLS-2$ - } catch (MalformedURLException e) { - // ignore - } - baseUrl = iconsUrl; - } - } - - private static ImageRegistry imageRegistry; - - private static final String T_EVIEW = "eview16"; //$NON-NLS-1$ - private static final String T_OBJ = "obj16"; //$NON-NLS-1$ + // For the images + private static ImageRegistry fImageRegistry = new ImageRegistry(); - public static final ImageDescriptor GITLAB_ICON = create(T_EVIEW, "gitlab-icon.png"); //$NON-NLS-1$ + public static String GITLAB_PICTURE_FILE = "icons/obj16/gitlab.png"; //$NON-NLS-1$ - public static final ImageDescriptor GITLAB_OVERLAY = create(T_EVIEW, "gitlab-overlay.png"); //$NON-NLS-1$ - public static final ImageDescriptor GITLAB = create(T_OBJ, "gitlab.png"); //$NON-NLS-1$ + public static String GITLAB_OVERLAY_PICTURE_FILE = "icons/eview16/gitlab-overlay.png"; //$NON-NLS-1$ - private static ImageDescriptor create(String prefix, String name) { - try { - return ImageDescriptor.createFromURL(makeIconFileURL(prefix, name)); - } catch (MalformedURLException e) { - return ImageDescriptor.getMissingImageDescriptor(); - } + static { + fImageRegistry.put(GITLAB_PICTURE_FILE, GitlabUiActivator.getImageDescriptor(GITLAB_PICTURE_FILE)); + fImageRegistry.put(GITLAB_OVERLAY_PICTURE_FILE, + GitlabUiActivator.getImageDescriptor(GITLAB_OVERLAY_PICTURE_FILE)); } - private static URL makeIconFileURL(String prefix, String name) throws MalformedURLException { - if (baseUrl == null) { - throw new MalformedURLException(); - } - - StringBuffer buffer = new StringBuffer(prefix); - buffer.append('/'); - buffer.append(name); - return new URL(baseUrl, buffer.toString()); + public static ImageDescriptor getDescriptor(String key) { + return fImageRegistry.getDescriptor(key); } - private static ImageRegistry getImageRegistry() { - if (imageRegistry == null) { - imageRegistry = new ImageRegistry(); - } - - return imageRegistry; + public static Image getImage(String key) { + return fImageRegistry.get(key); } - /** - * Lazily initializes image map. - * - * @param imageDescriptor - * @return Image - */ - public static Image getImage(ImageDescriptor imageDescriptor) { - ImageRegistry imageRegistry = getImageRegistry(); - Image image = imageRegistry.get("" + imageDescriptor.hashCode()); //$NON-NLS-1$ - if (image == null) { - image = imageDescriptor.createImage(true); - imageRegistry.put("" + imageDescriptor.hashCode(), image); //$NON-NLS-1$ - } - return image; - } } diff --git a/mylyn.tasks/connectors/gitlab/org.eclipse.mylyn.gitlab.ui/src/org/eclipse/mylyn/gitlab/ui/GitlabUiActivator.java b/mylyn.tasks/connectors/gitlab/org.eclipse.mylyn.gitlab.ui/src/org/eclipse/mylyn/gitlab/ui/GitlabUiActivator.java index 0c28e06f19..24e1714ef7 100644 --- a/mylyn.tasks/connectors/gitlab/org.eclipse.mylyn.gitlab.ui/src/org/eclipse/mylyn/gitlab/ui/GitlabUiActivator.java +++ b/mylyn.tasks/connectors/gitlab/org.eclipse.mylyn.gitlab.ui/src/org/eclipse/mylyn/gitlab/ui/GitlabUiActivator.java @@ -15,6 +15,7 @@ import java.io.File; +import org.eclipse.jface.resource.ImageDescriptor; import org.eclipse.mylyn.internal.tasks.core.ITasksCoreConstants; import org.eclipse.mylyn.internal.tasks.ui.TasksUiPlugin; import org.eclipse.ui.plugin.AbstractUIPlugin; @@ -58,4 +59,15 @@ public static GitlabUiActivator getDefault() { return plugin; } + /** + * Returns an image descriptor for the image file at the given plug-in relative path + * + * @param path + * the path + * @return the image descriptor + */ + public static ImageDescriptor getImageDescriptor(String path) { + return imageDescriptorFromPlugin(PLUGIN_ID, path); + } + } diff --git a/mylyn.tasks/connectors/gitlab/org.eclipse.mylyn.gitlab.ui/src/org/eclipse/mylyn/gitlab/ui/GitlabConnectorUI.java b/mylyn.tasks/connectors/gitlab/org.eclipse.mylyn.gitlab.ui/src/org/eclipse/mylyn/internal/gitlab/ui/GitlabConnectorUI.java similarity index 93% rename from mylyn.tasks/connectors/gitlab/org.eclipse.mylyn.gitlab.ui/src/org/eclipse/mylyn/gitlab/ui/GitlabConnectorUI.java rename to mylyn.tasks/connectors/gitlab/org.eclipse.mylyn.gitlab.ui/src/org/eclipse/mylyn/internal/gitlab/ui/GitlabConnectorUI.java index 32ab512098..c111866260 100644 --- a/mylyn.tasks/connectors/gitlab/org.eclipse.mylyn.gitlab.ui/src/org/eclipse/mylyn/gitlab/ui/GitlabConnectorUI.java +++ b/mylyn.tasks/connectors/gitlab/org.eclipse.mylyn.gitlab.ui/src/org/eclipse/mylyn/internal/gitlab/ui/GitlabConnectorUI.java @@ -11,7 +11,7 @@ * Frank Becker - initial API and implementation *******************************************************************************/ -package org.eclipse.mylyn.gitlab.ui; +package org.eclipse.mylyn.internal.gitlab.ui; import java.text.MessageFormat; @@ -21,10 +21,9 @@ import org.eclipse.jface.wizard.IWizard; import org.eclipse.mylyn.gitlab.core.GitlabConfiguration; import org.eclipse.mylyn.gitlab.core.GitlabCoreActivator; -import org.eclipse.mylyn.gitlab.core.GitlabRepositoryConnector; -import org.eclipse.mylyn.gitlab.core.GitlabTaskAttributeMapper; +import org.eclipse.mylyn.internal.gitlab.core.GitlabRepositoryConnector; +import org.eclipse.mylyn.internal.gitlab.core.GitlabTaskAttributeMapper; import org.eclipse.mylyn.internal.provisional.tasks.ui.wizards.QueryPageDetails; -import org.eclipse.mylyn.internal.tasks.ui.Messages; import org.eclipse.mylyn.tasks.core.IRepositoryQuery; import org.eclipse.mylyn.tasks.core.ITask; import org.eclipse.mylyn.tasks.core.ITaskComment; @@ -54,7 +53,7 @@ public ITaskRepositoryPage getSettingsPage(TaskRepository repository) { public IWizard getQueryWizard(TaskRepository repository, IRepositoryQuery query) { RepositoryQueryWizard wizard = new RepositoryQueryWizard(repository); GitlabRepositoryConnector connector = (GitlabRepositoryConnector) getConnector(); - TaskData taskData = new TaskData(new GitlabTaskAttributeMapper(repository, connector), + TaskData taskData = new TaskData(new GitlabTaskAttributeMapper(repository), repository.getConnectorKind(), "Query", "Query"); //$NON-NLS-1$ //$NON-NLS-2$ GitlabSearchQueryPageSchema.getInstance().initialize(taskData); try { diff --git a/mylyn.tasks/connectors/gitlab/org.eclipse.mylyn.gitlab.ui/src/org/eclipse/mylyn/gitlab/ui/GitlabQuerySchemaPage.java b/mylyn.tasks/connectors/gitlab/org.eclipse.mylyn.gitlab.ui/src/org/eclipse/mylyn/internal/gitlab/ui/GitlabQuerySchemaPage.java similarity index 79% rename from mylyn.tasks/connectors/gitlab/org.eclipse.mylyn.gitlab.ui/src/org/eclipse/mylyn/gitlab/ui/GitlabQuerySchemaPage.java rename to mylyn.tasks/connectors/gitlab/org.eclipse.mylyn.gitlab.ui/src/org/eclipse/mylyn/internal/gitlab/ui/GitlabQuerySchemaPage.java index 42d4aa340a..2a8b7d5485 100644 --- a/mylyn.tasks/connectors/gitlab/org.eclipse.mylyn.gitlab.ui/src/org/eclipse/mylyn/gitlab/ui/GitlabQuerySchemaPage.java +++ b/mylyn.tasks/connectors/gitlab/org.eclipse.mylyn.gitlab.ui/src/org/eclipse/mylyn/internal/gitlab/ui/GitlabQuerySchemaPage.java @@ -1,4 +1,16 @@ -package org.eclipse.mylyn.gitlab.ui; +/******************************************************************************* + * Copyright (c) 2023 Frank Becker and others. + * + * This program and the accompanying materials are made available under the + * terms of the Eclipse Public License v. 2.0 which is available at + * https://www.eclipse.org/legal/epl-2.0 + * + * SPDX-License-Identifier: EPL-2.0 + * + * Contributors: + * Frank Becker - initial API and implementation + *******************************************************************************/ +package org.eclipse.mylyn.internal.gitlab.ui; import java.util.Arrays; import java.util.List; @@ -6,7 +18,7 @@ import java.util.Optional; import org.eclipse.jdt.annotation.NonNull; -import org.eclipse.mylyn.gitlab.core.GitlabTaskSchema; +import org.eclipse.mylyn.internal.gitlab.core.GitlabTaskSchema; import org.eclipse.mylyn.internal.provisional.tasks.ui.wizards.AbstractQueryPageSchema; import org.eclipse.mylyn.internal.provisional.tasks.ui.wizards.QueryPageDetails; import org.eclipse.mylyn.internal.provisional.tasks.ui.wizards.RepositoryQuerySchemaPage; diff --git a/mylyn.tasks/connectors/gitlab/org.eclipse.mylyn.gitlab.ui/src/org/eclipse/mylyn/gitlab/ui/GitlabQueryTypeWizardPage.java b/mylyn.tasks/connectors/gitlab/org.eclipse.mylyn.gitlab.ui/src/org/eclipse/mylyn/internal/gitlab/ui/GitlabQueryTypeWizardPage.java similarity index 98% rename from mylyn.tasks/connectors/gitlab/org.eclipse.mylyn.gitlab.ui/src/org/eclipse/mylyn/gitlab/ui/GitlabQueryTypeWizardPage.java rename to mylyn.tasks/connectors/gitlab/org.eclipse.mylyn.gitlab.ui/src/org/eclipse/mylyn/internal/gitlab/ui/GitlabQueryTypeWizardPage.java index c9fe8821f6..30ad00e997 100644 --- a/mylyn.tasks/connectors/gitlab/org.eclipse.mylyn.gitlab.ui/src/org/eclipse/mylyn/gitlab/ui/GitlabQueryTypeWizardPage.java +++ b/mylyn.tasks/connectors/gitlab/org.eclipse.mylyn.gitlab.ui/src/org/eclipse/mylyn/internal/gitlab/ui/GitlabQueryTypeWizardPage.java @@ -11,7 +11,7 @@ * Frank Becker - initial API and implementation *******************************************************************************/ -package org.eclipse.mylyn.gitlab.ui; +package org.eclipse.mylyn.internal.gitlab.ui; import org.eclipse.jface.dialogs.Dialog; import org.eclipse.jface.wizard.IWizardPage; diff --git a/mylyn.tasks/connectors/gitlab/org.eclipse.mylyn.gitlab.ui/src/org/eclipse/mylyn/gitlab/ui/GitlabRepositorySettingsPage.java b/mylyn.tasks/connectors/gitlab/org.eclipse.mylyn.gitlab.ui/src/org/eclipse/mylyn/internal/gitlab/ui/GitlabRepositorySettingsPage.java similarity index 94% rename from mylyn.tasks/connectors/gitlab/org.eclipse.mylyn.gitlab.ui/src/org/eclipse/mylyn/gitlab/ui/GitlabRepositorySettingsPage.java rename to mylyn.tasks/connectors/gitlab/org.eclipse.mylyn.gitlab.ui/src/org/eclipse/mylyn/internal/gitlab/ui/GitlabRepositorySettingsPage.java index e1042597a1..8e1666ccf2 100644 --- a/mylyn.tasks/connectors/gitlab/org.eclipse.mylyn.gitlab.ui/src/org/eclipse/mylyn/gitlab/ui/GitlabRepositorySettingsPage.java +++ b/mylyn.tasks/connectors/gitlab/org.eclipse.mylyn.gitlab.ui/src/org/eclipse/mylyn/internal/gitlab/ui/GitlabRepositorySettingsPage.java @@ -11,7 +11,7 @@ * Frank Becker - initial API and implementation *******************************************************************************/ -package org.eclipse.mylyn.gitlab.ui; +package org.eclipse.mylyn.internal.gitlab.ui; import java.util.ArrayList; import java.util.Arrays; @@ -60,15 +60,10 @@ public class GitlabRepositorySettingsPage extends AbstractRepositorySettingsPage public GitlabRepositorySettingsPage(String title, String description, TaskRepository taskRepository) { super(title, description, taskRepository); - setNeedsRepositoryCredentials(true); // setNeedsRepositoryCredentials(true); - setNeedsAnonymousLogin(false); // setNeedsAnonymousLogin(false); - setNeedsEncoding(false); // setNeedsEncoding(true); - setNeedsTimeZone(false); // setNeedsTimeZone(true); - setNeedsProxy(false); // setNeedsProxy(true); - setNeedsValidation(true); // setNeedsValidation(true); - setNeedsAdvanced(true); // setNeedsAdvanced(true); - setNeedsValidateOnFinish(false); // setNeedsValidateOnFinish(false); - } + setNeedsEncoding(false); + setNeedsTimeZone(false); + setNeedsProxy(false); + } @Override public String getConnectorKind() { @@ -81,7 +76,6 @@ protected void createAdditionalControls(Composite parent) { Composite aditionalContainer = new Composite(parent, SWT.NONE); GridLayoutFactory.fillDefaults().margins(0, 0).numColumns(3).applyTo(aditionalContainer); GridDataFactory.fillDefaults().grab(true, true).align(SWT.FILL, SWT.FILL).applyTo(aditionalContainer); -// aditionalContainer.setBackground(new Color(aditionalContainer.getDisplay(), 0, 255, 0)); Label groupsLabel = new Label(aditionalContainer, SWT.NONE); groupsLabel.setText("include Groups"); diff --git a/mylyn.tasks/connectors/gitlab/org.eclipse.mylyn.gitlab.ui/src/org/eclipse/mylyn/gitlab/ui/GitlabSearchQueryPageSchema.java b/mylyn.tasks/connectors/gitlab/org.eclipse.mylyn.gitlab.ui/src/org/eclipse/mylyn/internal/gitlab/ui/GitlabSearchQueryPageSchema.java similarity index 55% rename from mylyn.tasks/connectors/gitlab/org.eclipse.mylyn.gitlab.ui/src/org/eclipse/mylyn/gitlab/ui/GitlabSearchQueryPageSchema.java rename to mylyn.tasks/connectors/gitlab/org.eclipse.mylyn.gitlab.ui/src/org/eclipse/mylyn/internal/gitlab/ui/GitlabSearchQueryPageSchema.java index 92adfb856a..5f4b85ca99 100644 --- a/mylyn.tasks/connectors/gitlab/org.eclipse.mylyn.gitlab.ui/src/org/eclipse/mylyn/gitlab/ui/GitlabSearchQueryPageSchema.java +++ b/mylyn.tasks/connectors/gitlab/org.eclipse.mylyn.gitlab.ui/src/org/eclipse/mylyn/internal/gitlab/ui/GitlabSearchQueryPageSchema.java @@ -1,7 +1,19 @@ -package org.eclipse.mylyn.gitlab.ui; +/******************************************************************************* + * Copyright (c) 2023 Frank Becker and others. + * + * This program and the accompanying materials are made available under the + * terms of the Eclipse Public License v. 2.0 which is available at + * https://www.eclipse.org/legal/epl-2.0 + * + * SPDX-License-Identifier: EPL-2.0 + * + * Contributors: + * Frank Becker - initial API and implementation + *******************************************************************************/ +package org.eclipse.mylyn.internal.gitlab.ui; -import org.eclipse.mylyn.gitlab.core.GitlabNewTaskSchema; -import org.eclipse.mylyn.gitlab.core.GitlabTaskSchema; +import org.eclipse.mylyn.internal.gitlab.core.GitlabNewTaskSchema; +import org.eclipse.mylyn.internal.gitlab.core.GitlabTaskSchema; import org.eclipse.mylyn.internal.provisional.tasks.ui.wizards.AbstractQueryPageSchema; import org.eclipse.mylyn.tasks.core.data.TaskAttribute; diff --git a/mylyn.tasks/connectors/gitlab/org.eclipse.mylyn.gitlab.ui/src/org/eclipse/mylyn/gitlab/ui/GitlabTaskEditorCommentPart.java b/mylyn.tasks/connectors/gitlab/org.eclipse.mylyn.gitlab.ui/src/org/eclipse/mylyn/internal/gitlab/ui/GitlabTaskEditorCommentPart.java similarity index 95% rename from mylyn.tasks/connectors/gitlab/org.eclipse.mylyn.gitlab.ui/src/org/eclipse/mylyn/gitlab/ui/GitlabTaskEditorCommentPart.java rename to mylyn.tasks/connectors/gitlab/org.eclipse.mylyn.gitlab.ui/src/org/eclipse/mylyn/internal/gitlab/ui/GitlabTaskEditorCommentPart.java index e3d11e54b0..29b61b1a9f 100644 --- a/mylyn.tasks/connectors/gitlab/org.eclipse.mylyn.gitlab.ui/src/org/eclipse/mylyn/gitlab/ui/GitlabTaskEditorCommentPart.java +++ b/mylyn.tasks/connectors/gitlab/org.eclipse.mylyn.gitlab.ui/src/org/eclipse/mylyn/internal/gitlab/ui/GitlabTaskEditorCommentPart.java @@ -1,4 +1,16 @@ -package org.eclipse.mylyn.gitlab.ui; +/******************************************************************************* + * Copyright (c) 2023 Frank Becker and others. + * + * This program and the accompanying materials are made available under the + * terms of the Eclipse Public License v. 2.0 which is available at + * https://www.eclipse.org/legal/epl-2.0 + * + * SPDX-License-Identifier: EPL-2.0 + * + * Contributors: + * Frank Becker - initial API and implementation + *******************************************************************************/ +package org.eclipse.mylyn.internal.gitlab.ui; import java.util.ArrayList; import java.util.List; @@ -11,7 +23,8 @@ import org.eclipse.mylyn.commons.ui.FillWidthLayout; import org.eclipse.mylyn.commons.workbench.forms.CommonFormUtil; import org.eclipse.mylyn.gitlab.core.GitlabCoreActivator; -import org.eclipse.mylyn.gitlab.core.GitlabRepositoryConnector; +import org.eclipse.mylyn.gitlab.ui.GitlabImages; +import org.eclipse.mylyn.internal.gitlab.core.GitlabRepositoryConnector; import org.eclipse.mylyn.internal.tasks.core.CommentQuoter; import org.eclipse.mylyn.internal.tasks.core.TaskComment; import org.eclipse.mylyn.internal.tasks.ui.TasksUiPlugin; @@ -341,7 +354,7 @@ public void linkActivated(HyperlinkEvent e) { TaskAttribute systemAttribute = taskComment.getTaskAttribute().getAttribute("system"); String systemAttributeValue = systemAttribute != null ? systemAttribute.getValue() : "false"; if ("true".equals(systemAttributeValue)) { - expandCommentHyperlink.setImage(GitlabImages.getImage(GitlabImages.GITLAB)); + expandCommentHyperlink.setImage(GitlabImages.getImage(GitlabImages.GITLAB_PICTURE_FILE)); } ToolBarManager toolBarManagerTitle = new ToolBarManager(SWT.FLAT); diff --git a/mylyn.tasks/connectors/gitlab/org.eclipse.mylyn.gitlab.ui/src/org/eclipse/mylyn/gitlab/ui/GitlabTaskEditorPage.java b/mylyn.tasks/connectors/gitlab/org.eclipse.mylyn.gitlab.ui/src/org/eclipse/mylyn/internal/gitlab/ui/GitlabTaskEditorPage.java similarity index 98% rename from mylyn.tasks/connectors/gitlab/org.eclipse.mylyn.gitlab.ui/src/org/eclipse/mylyn/gitlab/ui/GitlabTaskEditorPage.java rename to mylyn.tasks/connectors/gitlab/org.eclipse.mylyn.gitlab.ui/src/org/eclipse/mylyn/internal/gitlab/ui/GitlabTaskEditorPage.java index 0fe398f422..9e99a8d791 100644 --- a/mylyn.tasks/connectors/gitlab/org.eclipse.mylyn.gitlab.ui/src/org/eclipse/mylyn/gitlab/ui/GitlabTaskEditorPage.java +++ b/mylyn.tasks/connectors/gitlab/org.eclipse.mylyn.gitlab.ui/src/org/eclipse/mylyn/internal/gitlab/ui/GitlabTaskEditorPage.java @@ -11,7 +11,7 @@ * Frank Becker - initial API and implementation *******************************************************************************/ -package org.eclipse.mylyn.gitlab.ui; +package org.eclipse.mylyn.internal.gitlab.ui; import java.util.ArrayList; import java.util.Set; diff --git a/mylyn.tasks/connectors/gitlab/org.eclipse.mylyn.gitlab.ui/src/org/eclipse/mylyn/gitlab/ui/GitlabTaskEditorPageFactory.java b/mylyn.tasks/connectors/gitlab/org.eclipse.mylyn.gitlab.ui/src/org/eclipse/mylyn/internal/gitlab/ui/GitlabTaskEditorPageFactory.java similarity index 97% rename from mylyn.tasks/connectors/gitlab/org.eclipse.mylyn.gitlab.ui/src/org/eclipse/mylyn/gitlab/ui/GitlabTaskEditorPageFactory.java rename to mylyn.tasks/connectors/gitlab/org.eclipse.mylyn.gitlab.ui/src/org/eclipse/mylyn/internal/gitlab/ui/GitlabTaskEditorPageFactory.java index b1b013ea9b..bf78aeab42 100644 --- a/mylyn.tasks/connectors/gitlab/org.eclipse.mylyn.gitlab.ui/src/org/eclipse/mylyn/gitlab/ui/GitlabTaskEditorPageFactory.java +++ b/mylyn.tasks/connectors/gitlab/org.eclipse.mylyn.gitlab.ui/src/org/eclipse/mylyn/internal/gitlab/ui/GitlabTaskEditorPageFactory.java @@ -11,7 +11,7 @@ * Frank Becker - initial API and implementation *******************************************************************************/ -package org.eclipse.mylyn.gitlab.ui; +package org.eclipse.mylyn.internal.gitlab.ui; import org.eclipse.mylyn.commons.ui.CommonImages; import org.eclipse.mylyn.gitlab.core.GitlabCoreActivator; diff --git a/mylyn.tasks/connectors/gitlab/org.eclipse.mylyn.gitlab.ui/src/org/eclipse/mylyn/gitlab/ui/GitlabTaskEditorSummaryPart.java b/mylyn.tasks/connectors/gitlab/org.eclipse.mylyn.gitlab.ui/src/org/eclipse/mylyn/internal/gitlab/ui/GitlabTaskEditorSummaryPart.java similarity index 75% rename from mylyn.tasks/connectors/gitlab/org.eclipse.mylyn.gitlab.ui/src/org/eclipse/mylyn/gitlab/ui/GitlabTaskEditorSummaryPart.java rename to mylyn.tasks/connectors/gitlab/org.eclipse.mylyn.gitlab.ui/src/org/eclipse/mylyn/internal/gitlab/ui/GitlabTaskEditorSummaryPart.java index dc64d0b0b1..891f73de28 100644 --- a/mylyn.tasks/connectors/gitlab/org.eclipse.mylyn.gitlab.ui/src/org/eclipse/mylyn/gitlab/ui/GitlabTaskEditorSummaryPart.java +++ b/mylyn.tasks/connectors/gitlab/org.eclipse.mylyn.gitlab.ui/src/org/eclipse/mylyn/internal/gitlab/ui/GitlabTaskEditorSummaryPart.java @@ -1,17 +1,26 @@ -package org.eclipse.mylyn.gitlab.ui; +/******************************************************************************* + * Copyright (c) 2023 Frank Becker and others. + * + * This program and the accompanying materials are made available under the + * terms of the Eclipse Public License v. 2.0 which is available at + * https://www.eclipse.org/legal/epl-2.0 + * + * SPDX-License-Identifier: EPL-2.0 + * + * Contributors: + * Frank Becker - initial API and implementation + *******************************************************************************/ +package org.eclipse.mylyn.internal.gitlab.ui; +import org.apache.commons.lang.StringUtils; import org.eclipse.jface.layout.GridDataFactory; import org.eclipse.mylyn.commons.identity.core.spi.ProfileImage; import org.eclipse.mylyn.gitlab.core.GitlabCoreActivator; -import org.eclipse.mylyn.gitlab.core.GitlabRepositoryConnector; -import org.eclipse.mylyn.internal.tasks.ui.TasksUiPlugin; +import org.eclipse.mylyn.internal.gitlab.core.GitlabRepositoryConnector; import org.eclipse.mylyn.internal.tasks.ui.editors.EditorUtil; -import org.eclipse.mylyn.internal.tasks.ui.editors.TaskEditorExtensions; import org.eclipse.mylyn.internal.tasks.ui.editors.TaskEditorSummaryPart; import org.eclipse.mylyn.internal.tasks.ui.editors.UserAttributeEditor; -import org.eclipse.mylyn.tasks.core.AbstractRepositoryConnector; import org.eclipse.mylyn.tasks.core.data.TaskAttribute; -import org.eclipse.mylyn.tasks.ui.AbstractRepositoryConnectorUi; import org.eclipse.mylyn.tasks.ui.TasksUi; import org.eclipse.swt.SWT; import org.eclipse.swt.events.FocusAdapter; @@ -21,8 +30,6 @@ import org.eclipse.swt.widgets.Control; import org.eclipse.ui.forms.widgets.FormToolkit; -import com.google.common.base.Strings; - public class GitlabTaskEditorSummaryPart extends TaskEditorSummaryPart { @Override @@ -60,20 +67,20 @@ public void focusGained(FocusEvent e) { if (Boolean.parseBoolean(getModel().getTaskRepository().getProperty(GitlabCoreActivator.AVANTAR))) { TaskAttribute userAssignedAttribute = getTaskData().getRoot() .getMappedAttribute(TaskAttribute.USER_ASSIGNED); - if (userAssignedAttribute != null && !Strings.isNullOrEmpty(userAssignedAttribute.getValue())) { + if (userAssignedAttribute != null && !StringUtils.isBlank(userAssignedAttribute.getValue())) { UserAttributeEditor editor = new UserAttributeEditor(getModel(), userAssignedAttribute); editor.createControl(composite, toolkit); GridDataFactory.fillDefaults().align(SWT.CENTER, SWT.CENTER).span(1, 2).indent(0, 2) .applyTo(editor.getControl()); layout.marginRight = 1; layout.numColumns++; - TaskAttribute avatar_url = userAssignedAttribute.getAttribute("avatar_url"); + TaskAttribute avatarURL = userAssignedAttribute.getAttribute("avatar_url"); - if (avatar_url != null) { + if (avatarURL != null) { GitlabRepositoryConnector gitlabConnector = (GitlabRepositoryConnector) TasksUi .getRepositoryManager() .getRepositoryConnector(userAssignedAttribute.getTaskData().getConnectorKind()); - byte[] avatarBytes = gitlabConnector.getAvatarData(avatar_url.getValue()); + byte[] avatarBytes = gitlabConnector.getAvatarData(avatarURL.getValue()); editor.updateImage(new ProfileImage(avatarBytes, 30, 30, "")); } } diff --git a/org.eclipse.mylyn-site/category.xml b/org.eclipse.mylyn-site/category.xml index f7eee52111..3a8c8dd96e 100644 --- a/org.eclipse.mylyn-site/category.xml +++ b/org.eclipse.mylyn-site/category.xml @@ -48,13 +48,13 @@ - + - + - + @@ -111,7 +111,10 @@ - + + + + @@ -143,7 +146,7 @@ Mylyn bridges that integrate with documents and programming languages. Mylyn connectors that integrate with task repositories. - + The Connectors for Task Repositories like Bugzilla and GitHub @@ -158,4 +161,5 @@ Source code for integrators building on Mylyn. + From d0a2f4d4f09db8bd7bb62d59115aecce6a4a51da Mon Sep 17 00:00:00 2001 From: Frank Becker Date: Fri, 28 Jul 2023 18:33:36 +0200 Subject: [PATCH 10/13] update the gitlab icons to match https://design.gitlab.com/brand-logo/logomark/?_gl=1%2a1ogab11%2a_ga%2aNzM1ODU1MzQuMTY4OTA3OTY1Ng..%2a_ga_ENFH3X7M5Y%2aMTY5MDM0MzkyMi43LjEuMTY5MDM0NDIwNC4wLjAuMA --- .../gitlab/core/GitlabCoreActivator.java | 1 + .../icons/eview16/gitlab-overlay.png | Bin 1230 -> 0 bytes .../icons/eview16/gitlab-overlay@2x.png | Bin 1298 -> 0 bytes .../icons/obj16/gitlab.png | Bin 1298 -> 0 bytes .../icons/obj16/gitlab@2x.png | Bin 2023 -> 0 bytes .../icons/obj20/gitlab.png | Bin 0 -> 851 bytes .../icons/obj20/gitlab@2x.png | Bin 0 -> 1171 bytes .../org.eclipse.mylyn.gitlab.ui/plugin.xml | 5 ++--- .../eclipse/mylyn/gitlab/ui/GitlabImages.java | 6 +---- .../ui/GitlabRepositorySettingsPage.java | 14 ++++++++++++ .../ui/GitlabTaskEditorCommentPart.java | 21 ++++++++++++++++-- 11 files changed, 37 insertions(+), 10 deletions(-) delete mode 100644 mylyn.tasks/connectors/gitlab/org.eclipse.mylyn.gitlab.ui/icons/eview16/gitlab-overlay.png delete mode 100644 mylyn.tasks/connectors/gitlab/org.eclipse.mylyn.gitlab.ui/icons/eview16/gitlab-overlay@2x.png delete mode 100644 mylyn.tasks/connectors/gitlab/org.eclipse.mylyn.gitlab.ui/icons/obj16/gitlab.png delete mode 100644 mylyn.tasks/connectors/gitlab/org.eclipse.mylyn.gitlab.ui/icons/obj16/gitlab@2x.png create mode 100644 mylyn.tasks/connectors/gitlab/org.eclipse.mylyn.gitlab.ui/icons/obj20/gitlab.png create mode 100644 mylyn.tasks/connectors/gitlab/org.eclipse.mylyn.gitlab.ui/icons/obj20/gitlab@2x.png diff --git a/mylyn.tasks/connectors/gitlab/org.eclipse.mylyn.gitlab.core/src/org/eclipse/mylyn/gitlab/core/GitlabCoreActivator.java b/mylyn.tasks/connectors/gitlab/org.eclipse.mylyn.gitlab.core/src/org/eclipse/mylyn/gitlab/core/GitlabCoreActivator.java index b316381768..13a05ea274 100644 --- a/mylyn.tasks/connectors/gitlab/org.eclipse.mylyn.gitlab.core/src/org/eclipse/mylyn/gitlab/core/GitlabCoreActivator.java +++ b/mylyn.tasks/connectors/gitlab/org.eclipse.mylyn.gitlab.core/src/org/eclipse/mylyn/gitlab/core/GitlabCoreActivator.java @@ -28,6 +28,7 @@ public final class GitlabCoreActivator extends Plugin { public static final String GROUPS = "gitlab.groups"; public static final String PROJECTS = "gitlab.projects"; public static final String AVANTAR = "gitlab.avantar"; + public static final String SHOW_COMMENT_ICONS = "gitlab.show.comment.icons"; public static final String API_VERSION = "/api/v4"; // The shared instance diff --git a/mylyn.tasks/connectors/gitlab/org.eclipse.mylyn.gitlab.ui/icons/eview16/gitlab-overlay.png b/mylyn.tasks/connectors/gitlab/org.eclipse.mylyn.gitlab.ui/icons/eview16/gitlab-overlay.png deleted file mode 100644 index 893fd16d93a0077228f8ebca483c737231103ab7..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 1230 zcmeAS@N?(olHy`uVBq!ia0vp^93afW3?x5a^xMh6z}S-M>>S|f?5t2wl%JNFlghxL zF|l@{t;b;pnWOQ+OBacXfreA# zM48ufEZ~ooIJDx7Pp#jiM;~P3zkm4nRqxQ|J?H;g?lO*?%xE{UV%p0#*FBCldoy3o z`QGWgMj^f9eCKhVT?!wSuZvEHX9? z<+S9v=s8z|T20@bjF&i*rF}YPxn+lh*hUskC6SN-7fvyyEm=!ucwDHva@hXC57i>g zCt6JtlNnQ2OpvwzA^+#ywKKkcJ3J3+T=de*kuH88P zl6k_Cb&t#s98@%zwERtJe|h?_*Pw^v~i0|QfffKP}kFnWOCk+bF_ zCymF>nvWecAG+v1cGZ0BqWREC^O=X{Gf&MwOVqvus(+1F|Fc-_HxMmS|Gh;0?_$+I zbJYG!Q~NVt?au4lc)A6R{e7v$ZLNVs{LtH`;o2&H0MtfSOG-YT(v({ zYJYOoUI%Kt2I`#$lbWvfr&#S{j5^Q+sDTjmK)dqQex#{Ab=UmU4^s@0TBP=;P3=#P z+AE+@ff|3>QDuQ@fPq=7_Ay%hQ;a&00Ss6alV^d9eF8MLTlpR4w}O6{ee1`q++e}GP1ruKKL+J^-7 z4~go3maF|+qxPjp{Y$YrB(8y>^s`9qXS&+Y3^kCA!0-vu07eAJz&wy2L7`oy_NQ6x z|NsBj?(zEp(-~t)kY6x^!?PP{AWo9Ey9+}HtE>l*!&%@FSbCYGe8D3oWGWGJ|M`UZqI@`(c# zX?wajhHzX@PH13OlVD7L^C&s#(QVe04w0QZL^>N<(skl&m>1Q2&tp?zVA!{TUG~}i R7FM7(22WQ%mvv4FO#t&sIwb%A diff --git a/mylyn.tasks/connectors/gitlab/org.eclipse.mylyn.gitlab.ui/icons/eview16/gitlab-overlay@2x.png b/mylyn.tasks/connectors/gitlab/org.eclipse.mylyn.gitlab.ui/icons/eview16/gitlab-overlay@2x.png deleted file mode 100644 index c04101348161b2593119a4408a38c5a67bd5e4f2..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 1298 zcmcgq|4&m_6n~{)1qPS}+G1oD2KT);192mBy3A2{t!-neZ6P9xQmUn3pPEl zQ}6%oQT}4*h!;C8_7^c2&Y@b=KWCM(V;v~JDj!#E_@(Kr(r2E}4^?(6vp#;)7R_xx zzU^65-L7md`+IvwANO#%z>)29|9GuYY&z4`95i6@(~;&6GK-EfH1&mEL6)uXO;3BM z?4hKQFs-Qn+}g}naq1%ytk&Ki$MADD&xf5AD>@hBqHn_=T}>i>$ByKbzq?9z59nC0 z&vt64Q@%l=-sQ~xj@Msx@+bUFKMl|K^tO&N3v2HTe)6QzdwX%+_{jo;;r{&m#Faf~ zgL3k9_wpNfH5g{6l}p2g=y=dGNRfjf#1KUe@yVA0{~;kcBp_dgki%kfSVF>DFss1l zqH%Z~SdrD>)>?e|x*x0r@G^j319%PCzVM?#{zpUf*4iN_gdC9)uV}UeB9HbF?UB92 zQUO@d;K*Of2Z%fx1g3y-B|-bhasf;P(}(eyBlKvn8o&%-(E@}6Gyf}CExQWfX#f+z zn1UEX|5m+Cl>?XxrlN3!um-qVk9s8mODuRLB4NSX;?-0QfENKg0scWy3Icw)K8tFQ znCW2Z5I!A+BL@k)4!MGcH6vI9fEDXgCBTYcpPEl zQ}6%oQT}4*h!;C8_7^c2&Y@b=KWCM(V;v~JDj!#E_@(Kr(r2E}4^?(6vp#;)7R_xx zzU^65-L7md`+IvwANO#%z>)29|9GuYY&z4`95i6@(~;&6GK-EfH1&mEL6)uXO;3BM z?4hKQFs-Qn+}g}naq1%ytk&Ki$MADD&xf5AD>@hBqHn_=T}>i>$ByKbzq?9z59nC0 z&vt64Q@%l=-sQ~xj@Msx@+bUFKMl|K^tO&N3v2HTe)6QzdwX%+_{jo;;r{&m#Faf~ zgL3k9_wpNfH5g{6l}p2g=y=dGNRfjf#1KUe@yVA0{~;kcBp_dgki%kfSVF>DFss1l zqH%Z~SdrD>)>?e|x*x0r@G^j319%PCzVM?#{zpUf*4iN_gdC9)uV}UeB9HbF?UB92 zQUO@d;K*Of2Z%fx1g3y-B|-bhasf;P(}(eyBlKvn8o&%-(E@}6Gyf}CExQWfX#f+z zn1UEX|5m+Cl>?XxrlN3!um-qVk9s8mODuRLB4NSX;?-0QfENKg0scWy3Icw)K8tFQ znCW2Z5I!A+BL@k)4!MGcH6vI9fEDXgCBTYc+0L>B0N90!gfcwSsbOP@|AiI1uHtE&G9V%VfOE!)NN$DKG@UF&0M7jC{FGuQ zh-47}WI+IOwgWJPw{kiG$RGiD76$--KL9hd2QNw&0$`CS36BiIgtkCtn}E?C$ZTKC zY!$NFgP83?W~+etSj2oB%0v~gPfGO15~v&w<2XtTR}iLhcXSY<5{QmKR0>Bnx>F+m zV_yC6!1ucC?G z80u=M45C~(poCZlZGB4^r5%DO3!)U*C1rHsvxonI_CchBJ!=W9@J?`)k85e*KoaZ- zVIt!{~7e-n!vIq+<{RiWmIP#1vB3*@%|w=oCTkX88~o`u+>Uv+6%kmh;BK7 zjzjZl*q2W9>4?#1jk`3M4hNNRPz9-qxIZ!meh`#kDs@My+v_3P21iClek3-0h2OIp zy-d6e&;R+0C?_84O*JV4V+l8LWKd5zBd!%N+-t^7bXfE& z!YH~s>+;T{fx)Y%hvw`F635V%=WabZ%|ozVx=LZ3chcg5|GXO_+a|BqswH!0Gf!Ly z37pNYyH;7HG@fxeZ{h#IKfCXqeC`+H^Ri#hbaL|`?_s2jwl?>KQ=uj`m;Akc8Y6Ce zueDqG{K88OH)fU9HQRn1f7xbg>)8vIX)os3+d97pn7h8(IgWk2s5i!5o0hT7VnycJ zoGR-XqQhS|=>9TWE^g^av9fv?LpPf@EvhjrwldUiwl+=4t!s75u4@s2{assb|2E?^ zo$OR;Z6qx#znLn`mEPsr`wXZgbP3HhcA&9*>K-~v+GuapD5b}Q|J+!9&S02iNb3nP zxB^109%5E(^)91p*yENpKPA1m*gyM^l(kj)Mw&;9!^0XyS2gR; zAni5F+|GhSm)7s(w$R!xW$yNrI04|_G;+S7%I+C{o80w5EA@$Ty@H>RuD}!Ekvx(` za#>t5lIzX)^y7Q-JV=sHl5_5e0>>Ok(Il#qHvad4V$Q4Z?+HHm*q$2kz79($-`CYQm!{$rPpiu98P9tCR)gY^7$%-TB*_lFD|d{wnU0KGv3pA z$629H)T=0pv%&H{rZ~MviBP8~^c%Gb@YWSao2vZue3bYDorp-x0$eX2UvHoJo<6)K z7d!Bm5IDT2vrL^uwVCZ5CJ^MkG!9@m{5^QNEEFWElNGoHY)*zYStC!>alE`azVYjI zp7JOTk4yS+C_*e{CRVA|C(Gkw)d`x^Sgt4O<>SZ3&J5)BTC58~gT%r!g1D`J1HqkV AhX4Qo diff --git a/mylyn.tasks/connectors/gitlab/org.eclipse.mylyn.gitlab.ui/icons/obj20/gitlab.png b/mylyn.tasks/connectors/gitlab/org.eclipse.mylyn.gitlab.ui/icons/obj20/gitlab.png new file mode 100644 index 0000000000000000000000000000000000000000..b07996a80aedc96c6efc6a1b53127da11632325e GIT binary patch literal 851 zcmV-Z1FZasP)EX>4Tx04R}tkv&MmKpe$i(@I4u4t9{@kfC+5AS%UCt5Adrp;l;tBaGOi?RNS*tc!=brq9p@P1$%ypWhNMR96kRU=q0~J(ZAx^7Kiir&ECq4WT$1jmfAy);A z91EyHgY5Xh|KNAGW^roLO$sG}z8Bm6hylS}pxw0X?_=9;p8)=6;7afMYb{{rlk{d+ ziyi?(+rY(jS5x+Y%N=0ksV*C`Bl&3x#Uk*2M&FbNhHrs^HMh6UK29HiEOnK>0S*p< zu@Yskd%U~9x3_=Kbo%=Nv0`$-nyeSad^gZEa<4bO1wgWnpw> zWFU8GbZ8()Nlj2!fese{00ApWL_t(I%k7iFN&-<7hQB*FlL}*oE?NY-GDd_pzQNGa zZA28lfPqj;mo016yg?E47(GHDL9>dXMT@{v5}VOEEt6n{&D6|9}2-ITuz~ z9(cCZ@@%Ubb6@prt2Ilf#hUF_6wn0fG3`3gj5v!K5{~wO98int)_`2ZnL=Vl^8Kh5 zJlnbh!m$8_G0yFza4L59sG^b?KkUCNdM_Fx69NV1W=MKn7<3ISbJdnV4FQIY(kBWd z@D-hBjo}~~CkY!{A-W+T_zA~dTj&i%I0MiPAzvJk$_lCM_gOdO7iaFsKL{G7L#4O` zvJ@lc6Ck{aaI8D-^}h@w)3PdagUJp6AKXiu1Kn{SW@*&C1@B*Mn|fZ(0fJX`nm&2# dt-k$|;R`D$S)f(k_ap!S002ovPDHLkV1nTVa6SM4 literal 0 HcmV?d00001 diff --git a/mylyn.tasks/connectors/gitlab/org.eclipse.mylyn.gitlab.ui/icons/obj20/gitlab@2x.png b/mylyn.tasks/connectors/gitlab/org.eclipse.mylyn.gitlab.ui/icons/obj20/gitlab@2x.png new file mode 100644 index 0000000000000000000000000000000000000000..1d2ec1949e32c337b24d94cedcf54c3455fc2aa9 GIT binary patch literal 1171 zcmV;E1Z?|>P)EX>4Tx04R}tkv&MmKpe$i(@I4u4t9{@kfC+5AS%UCt5Adrp;l;tBaGOi?RNS*tc!=brq9p@P1$%ypWhNMR96kRU=q0~J(ZAx^7Kiir&ECq4WT$1jmfAy);A z91EyHgY5Xh|KNAGW^roLO$sG}z8Bm6hylS}pxw0X?_=9;p8)=6;7afMYb{{rlk{d+ ziyi?(+rY(jS5x+Y%N=0ksV*C`Bl&3x#Uk*2M&FbNhHrs^HMh6UK29HiEOnK>0S*p< zu@Yskd%U~9x3_=Kbo%=Nv0`$-nyN8KX}|yg02y>eSad^gZEa<4bO1wgWnpw> zWFU8GbZ8()Nlj2!fese{00L`CL_t(o!|j*PPZLoP$3Jh^E-OC@OE958NHAt&(St|v z3I`5^Ac-1H)I>s%5cQ;gfhRqwX+mSXc+jZ-f?UO;7sYNoRTI566wyMnZ#;C3r7p6i zEnfC}*}OOVoj310JCj+65hF&77%>`ws+W+T7&Q@j3EUrES$i9aGoC&T+(xPM!>>R1 z^_*waeI=1;U=~=cgS80E23%SjAY2We)A@-}Gm_#kUBhinfcf!sKQI+6dk~q7p!g)v z6Rf5JA1zbxGElAB*$ABKcg(;?%L2Ssv!3}^ngiR+9zL2=#rg5{81N><^ceWI3#}iR z57|F6yt1|$<=jJ&Z(=YfI@B~@cW*P816G@+;Kr5Xrk&Kq@|J4fEGT{!6#KzpN9b^b zM4S956^&%q(~o{r6inDMpcL(vEm$d`!%-Bz82H=K0y8aehBTHfzqi^GwhREDn^Po; zV)fFpg(F9O>~7hUYIj%OtqLyGXF~zn+1xrpZU@nT-a$<=rNciI1<91AcTi*0o+9Mz zY;L`&ZANSEhV6GcLf?qSw05SnZ$#7SNL{`f9u~?=?gM3TGxSg&3STStby6B*m+mN< zhlz}Lt7X$ndC9$`43>eezl=jcPV(W+Ks47A8Shz3$1Q;ECD%0!UI3>mWeyyx3i&(m z3HVdx@3iKEmGQiTm}amto>wlZF%gzY0w-(q>5 + brandingIcon="icons/obj20/gitlab.png" + class="org.eclipse.mylyn.internal.gitlab.ui.GitlabConnectorUI"> diff --git a/mylyn.tasks/connectors/gitlab/org.eclipse.mylyn.gitlab.ui/src/org/eclipse/mylyn/gitlab/ui/GitlabImages.java b/mylyn.tasks/connectors/gitlab/org.eclipse.mylyn.gitlab.ui/src/org/eclipse/mylyn/gitlab/ui/GitlabImages.java index a771b73e22..80c7e8e549 100644 --- a/mylyn.tasks/connectors/gitlab/org.eclipse.mylyn.gitlab.ui/src/org/eclipse/mylyn/gitlab/ui/GitlabImages.java +++ b/mylyn.tasks/connectors/gitlab/org.eclipse.mylyn.gitlab.ui/src/org/eclipse/mylyn/gitlab/ui/GitlabImages.java @@ -21,14 +21,10 @@ public class GitlabImages { // For the images private static ImageRegistry fImageRegistry = new ImageRegistry(); - public static String GITLAB_PICTURE_FILE = "icons/obj16/gitlab.png"; //$NON-NLS-1$ - - public static String GITLAB_OVERLAY_PICTURE_FILE = "icons/eview16/gitlab-overlay.png"; //$NON-NLS-1$ + public static String GITLAB_PICTURE_FILE = "icons/obj20/gitlab.png"; //$NON-NLS-1$ static { fImageRegistry.put(GITLAB_PICTURE_FILE, GitlabUiActivator.getImageDescriptor(GITLAB_PICTURE_FILE)); - fImageRegistry.put(GITLAB_OVERLAY_PICTURE_FILE, - GitlabUiActivator.getImageDescriptor(GITLAB_OVERLAY_PICTURE_FILE)); } public static ImageDescriptor getDescriptor(String key) { diff --git a/mylyn.tasks/connectors/gitlab/org.eclipse.mylyn.gitlab.ui/src/org/eclipse/mylyn/internal/gitlab/ui/GitlabRepositorySettingsPage.java b/mylyn.tasks/connectors/gitlab/org.eclipse.mylyn.gitlab.ui/src/org/eclipse/mylyn/internal/gitlab/ui/GitlabRepositorySettingsPage.java index 8e1666ccf2..b9e34eabe5 100644 --- a/mylyn.tasks/connectors/gitlab/org.eclipse.mylyn.gitlab.ui/src/org/eclipse/mylyn/internal/gitlab/ui/GitlabRepositorySettingsPage.java +++ b/mylyn.tasks/connectors/gitlab/org.eclipse.mylyn.gitlab.ui/src/org/eclipse/mylyn/internal/gitlab/ui/GitlabRepositorySettingsPage.java @@ -57,6 +57,7 @@ public class GitlabRepositorySettingsPage extends AbstractRepositorySettingsPage private Button projectRemoveButton; private Button projectAddButton; private Button avatarSupportButton; + private Button showCommentIconsButton; public GitlabRepositorySettingsPage(String title, String description, TaskRepository taskRepository) { super(title, description, taskRepository); @@ -246,6 +247,18 @@ public void widgetSelected(SelectionEvent e) { gd.grabExcessHorizontalSpace = true; avatarSupportButton.setLayoutData(gd); + showCommentIconsButton = new Button(aditionalContainer, SWT.CHECK); + showCommentIconsButton.setText("Show Comment Icons images"); + showCommentIconsButton.setSelection(getRepository() != null + && Boolean.parseBoolean(getRepository().getProperty(GitlabCoreActivator.SHOW_COMMENT_ICONS))); + + gd = new GridData(GridData.FILL_BOTH); + gd.horizontalSpan = 2; + gd.verticalSpan = 1; + gd.grabExcessHorizontalSpace = true; + showCommentIconsButton.setLayoutData(gd); + + updateUIEnablement(); } @@ -264,6 +277,7 @@ public void applyTo(TaskRepository repository) { repository.setProperty(GitlabCoreActivator.GROUPS, String.join(",", groupList)); repository.setProperty(GitlabCoreActivator.PROJECTS, String.join(",", projectList)); repository.setProperty(GitlabCoreActivator.AVANTAR, Boolean.toString(avatarSupportButton.getSelection())); + repository.setProperty(GitlabCoreActivator.SHOW_COMMENT_ICONS, Boolean.toString(showCommentIconsButton.getSelection())); super.applyTo(repository); } diff --git a/mylyn.tasks/connectors/gitlab/org.eclipse.mylyn.gitlab.ui/src/org/eclipse/mylyn/internal/gitlab/ui/GitlabTaskEditorCommentPart.java b/mylyn.tasks/connectors/gitlab/org.eclipse.mylyn.gitlab.ui/src/org/eclipse/mylyn/internal/gitlab/ui/GitlabTaskEditorCommentPart.java index 29b61b1a9f..6850a05f71 100644 --- a/mylyn.tasks/connectors/gitlab/org.eclipse.mylyn.gitlab.ui/src/org/eclipse/mylyn/internal/gitlab/ui/GitlabTaskEditorCommentPart.java +++ b/mylyn.tasks/connectors/gitlab/org.eclipse.mylyn.gitlab.ui/src/org/eclipse/mylyn/internal/gitlab/ui/GitlabTaskEditorCommentPart.java @@ -20,6 +20,7 @@ import org.eclipse.jface.layout.GridDataFactory; import org.eclipse.jface.viewers.StructuredSelection; import org.eclipse.mylyn.commons.identity.core.spi.ProfileImage; +import org.eclipse.mylyn.commons.ui.CommonImages; import org.eclipse.mylyn.commons.ui.FillWidthLayout; import org.eclipse.mylyn.commons.workbench.forms.CommonFormUtil; import org.eclipse.mylyn.gitlab.core.GitlabCoreActivator; @@ -34,6 +35,7 @@ import org.eclipse.mylyn.internal.tasks.ui.editors.TaskEditorCommentPart; import org.eclipse.mylyn.internal.tasks.ui.editors.TaskEditorRichTextPart; import org.eclipse.mylyn.internal.tasks.ui.editors.UserAttributeEditor; +import org.eclipse.mylyn.tasks.core.IRepositoryPerson; import org.eclipse.mylyn.tasks.core.ITaskComment; import org.eclipse.mylyn.tasks.core.data.TaskAttribute; import org.eclipse.mylyn.tasks.ui.AbstractRepositoryConnectorUi; @@ -44,6 +46,7 @@ import org.eclipse.swt.SWT; import org.eclipse.swt.events.MouseAdapter; import org.eclipse.swt.events.MouseEvent; +import org.eclipse.swt.graphics.Color; import org.eclipse.swt.layout.GridData; import org.eclipse.swt.layout.GridLayout; import org.eclipse.swt.layout.RowLayout; @@ -353,8 +356,22 @@ public void linkActivated(HyperlinkEvent e) { }); TaskAttribute systemAttribute = taskComment.getTaskAttribute().getAttribute("system"); String systemAttributeValue = systemAttribute != null ? systemAttribute.getValue() : "false"; - if ("true".equals(systemAttributeValue)) { - expandCommentHyperlink.setImage(GitlabImages.getImage(GitlabImages.GITLAB_PICTURE_FILE)); + boolean showCommentIcons = Boolean + .parseBoolean(getModel().getTaskRepository().getProperty(GitlabCoreActivator.SHOW_COMMENT_ICONS)); + if (showCommentIcons) { + if ("true".equals(systemAttributeValue)) { + expandCommentHyperlink.setImage(GitlabImages.getImage(GitlabImages.GITLAB_PICTURE_FILE)); + } else { + IRepositoryPerson author = taskComment.getAuthor(); + if (author != null + && author.matchesUsername(getTaskEditorPage().getTaskRepository().getUserName())) { + expandCommentHyperlink.setImage(CommonImages.getImage(CommonImages.PERSON_ME)); + } else { + expandCommentHyperlink.setImage(CommonImages.getImage(CommonImages.PERSON)); + } + } + } else { + expandCommentHyperlink.setImage(null); } ToolBarManager toolBarManagerTitle = new ToolBarManager(SWT.FLAT); From 94ab3de105a244f2562d61b10251773debd15b73 Mon Sep 17 00:00:00 2001 From: Frank Becker Date: Wed, 2 Aug 2023 14:28:43 +0200 Subject: [PATCH 11/13] further small corrections from conversations --- .../META-INF/MANIFEST.MF | 2 + .../build.properties | 7 +- .../plugin.properties | 18 ++ .../org.eclipse.mylyn.gitlab.core/plugin.xml | 4 +- .../core/GitlabRepositoryConnector.java | 117 ------------ .../feature.properties | 169 +----------------- .../feature.xml | 4 +- .../.project | 17 ++ .../feature.properties | 167 +---------------- .../build.properties | 3 +- .../eclipse/mylyn/gitlab/ui/GitlabImages.java | 38 ---- .../mylyn/gitlab/ui/GitlabUiActivator.java | 91 +++++----- .../ui/GitlabTaskEditorCommentPart.java | 46 +---- .../ui/editors/TaskEditorCommentPart.java | 8 +- 14 files changed, 108 insertions(+), 583 deletions(-) create mode 100644 mylyn.tasks/connectors/gitlab/org.eclipse.mylyn.gitlab.core/plugin.properties create mode 100644 mylyn.tasks/connectors/gitlab/org.eclipse.mylyn.gitlab.source.feature/.project delete mode 100644 mylyn.tasks/connectors/gitlab/org.eclipse.mylyn.gitlab.ui/src/org/eclipse/mylyn/gitlab/ui/GitlabImages.java diff --git a/mylyn.tasks/connectors/gitlab/org.eclipse.mylyn.gitlab.core/META-INF/MANIFEST.MF b/mylyn.tasks/connectors/gitlab/org.eclipse.mylyn.gitlab.core/META-INF/MANIFEST.MF index 5d612a2870..2996ccc6cb 100644 --- a/mylyn.tasks/connectors/gitlab/org.eclipse.mylyn.gitlab.core/META-INF/MANIFEST.MF +++ b/mylyn.tasks/connectors/gitlab/org.eclipse.mylyn.gitlab.core/META-INF/MANIFEST.MF @@ -2,6 +2,7 @@ Manifest-Version: 1.0 Bundle-ManifestVersion: 2 Bundle-Name: Gitlab Connector Core Bundle-SymbolicName: org.eclipse.mylyn.gitlab.core;singleton:=true +Bundle-Vendor: %Bundle-Vendor Bundle-Version: 4.0.0.qualifier Export-Package: org.eclipse.mylyn.gitlab.core, org.eclipse.mylyn.internal.gitlab.core;x-internal:=true @@ -25,6 +26,7 @@ Import-Package: com.google.common.base;version="31.1.0", org.apache.http.entity;version="4.4.16", org.apache.http.message;version="4.4.16" Bundle-Activator: org.eclipse.mylyn.gitlab.core.GitlabCoreActivator +Bundle-ClassPath: . Require-Bundle: org.eclipse.core.runtime, org.eclipse.equinox.security;bundle-version="1.3.1000", org.eclipse.jdt.annotation, diff --git a/mylyn.tasks/connectors/gitlab/org.eclipse.mylyn.gitlab.core/build.properties b/mylyn.tasks/connectors/gitlab/org.eclipse.mylyn.gitlab.core/build.properties index b86c9791a6..8a7e72f455 100644 --- a/mylyn.tasks/connectors/gitlab/org.eclipse.mylyn.gitlab.core/build.properties +++ b/mylyn.tasks/connectors/gitlab/org.eclipse.mylyn.gitlab.core/build.properties @@ -5,7 +5,8 @@ # which accompanies this distribution, and is available at # http://www.eclipse.org/legal/epl-v20.html ############################################################################### -source.. = src/ -output.. = bin/ bin.includes = META-INF/,\ - . \ No newline at end of file + .,\ + plugin.properties,\ + plugin.xml +source.. = src/ diff --git a/mylyn.tasks/connectors/gitlab/org.eclipse.mylyn.gitlab.core/plugin.properties b/mylyn.tasks/connectors/gitlab/org.eclipse.mylyn.gitlab.core/plugin.properties new file mode 100644 index 0000000000..35c10546cb --- /dev/null +++ b/mylyn.tasks/connectors/gitlab/org.eclipse.mylyn.gitlab.core/plugin.properties @@ -0,0 +1,18 @@ +############################################################################### +# Copyright (c) 2009, 2013 Tasktop Technologies and others. +# +# This program and the accompanying materials are made available under the +# terms of the Eclipse Public License v. 2.0 which is available at +# https://www.eclipse.org/legal/epl-2.0 +# +# SPDX-License-Identifier: EPL-2.0 +# +# Contributors: +# Tasktop Technologies - initial API and implementation +############################################################################### +#Properties file for org.eclipse.mylyn.bugzilla.core +Bundle-Vendor = Eclipse Mylyn +Bundle-Name = Gitlab Connector Core + +gitlab.repository.name=Gitlab Repository +GitlabRepositoryConnector.name=Gitlab Repository Connector diff --git a/mylyn.tasks/connectors/gitlab/org.eclipse.mylyn.gitlab.core/plugin.xml b/mylyn.tasks/connectors/gitlab/org.eclipse.mylyn.gitlab.core/plugin.xml index 28cc426294..ad91ce5145 100644 --- a/mylyn.tasks/connectors/gitlab/org.eclipse.mylyn.gitlab.core/plugin.xml +++ b/mylyn.tasks/connectors/gitlab/org.eclipse.mylyn.gitlab.core/plugin.xml @@ -15,12 +15,12 @@ + name="%GitlabRepositoryConnector.name"> \ No newline at end of file diff --git a/mylyn.tasks/connectors/gitlab/org.eclipse.mylyn.gitlab.core/src/org/eclipse/mylyn/internal/gitlab/core/GitlabRepositoryConnector.java b/mylyn.tasks/connectors/gitlab/org.eclipse.mylyn.gitlab.core/src/org/eclipse/mylyn/internal/gitlab/core/GitlabRepositoryConnector.java index 0cd46c12fb..7ccc9878dc 100644 --- a/mylyn.tasks/connectors/gitlab/org.eclipse.mylyn.gitlab.core/src/org/eclipse/mylyn/internal/gitlab/core/GitlabRepositoryConnector.java +++ b/mylyn.tasks/connectors/gitlab/org.eclipse.mylyn.gitlab.core/src/org/eclipse/mylyn/internal/gitlab/core/GitlabRepositoryConnector.java @@ -21,24 +21,17 @@ import java.net.HttpURLConnection; import java.net.URL; import java.text.SimpleDateFormat; -import java.util.Collections; import java.util.HashSet; -import java.util.List; import java.util.Map; import java.util.Set; import java.util.concurrent.ExecutionException; -import java.util.concurrent.Executor; import java.util.concurrent.TimeUnit; -import java.util.concurrent.TimeoutException; import java.util.stream.Collectors; import org.eclipse.core.runtime.CoreException; import org.eclipse.core.runtime.IProgressMonitor; import org.eclipse.core.runtime.IStatus; import org.eclipse.core.runtime.Status; -import org.eclipse.core.runtime.jobs.IJobChangeEvent; -import org.eclipse.core.runtime.jobs.Job; -import org.eclipse.core.runtime.jobs.JobChangeAdapter; import org.eclipse.jdt.annotation.NonNull; import org.eclipse.jdt.annotation.Nullable; import org.eclipse.mylyn.commons.core.operations.IOperationMonitor; @@ -70,9 +63,7 @@ import com.google.common.cache.CacheBuilder; import com.google.common.cache.CacheLoader; import com.google.common.cache.LoadingCache; -import com.google.common.collect.Lists; import com.google.common.util.concurrent.ExecutionError; -import com.google.common.util.concurrent.ListenableFuture; import com.google.common.util.concurrent.UncheckedExecutionException; public class GitlabRepositoryConnector extends AbstractRepositoryConnector { @@ -129,89 +120,6 @@ private boolean ignoredProperty(String propertyName) { return false; } - abstract class ListenableFutureJob extends Job implements ListenableFuture { - - private class Listener { - - Runnable runnable; - - Executor executor; - - public Listener(Runnable runnable, Executor executor) { - this.runnable = runnable; - this.executor = executor; - } - - public void run() { - executor.execute(runnable); - } - } - - List listeners = Collections.synchronizedList(Lists.newArrayList()); - - private volatile boolean done; - - private V resultObject; - - public ListenableFutureJob(String name) { - super(name); - resultObject = null; - this.addJobChangeListener(new JobChangeAdapter() { - - @Override - public void done(IJobChangeEvent event) { - done = true; - synchronized (listeners) { - for (Listener listener : listeners) { - listener.run(); - } - } - } - }); - } - - @Override - public boolean cancel(boolean mayInterruptIfRunning) { - return this.cancel(); - } - - @Override - public V get() throws InterruptedException, ExecutionException { - this.join(); - return resultObject; - } - - @Override - public V get(long timeout, TimeUnit unit) throws InterruptedException, ExecutionException, TimeoutException { - long start = System.currentTimeMillis(); - while (!done && System.currentTimeMillis() - start < unit.toMillis(timeout)) { - Thread.sleep(250); - } - if (!done) { - throw new TimeoutException("ListenableFutureJob.get() could not get the result!"); - } - return resultObject; - } - - protected void set(V future) { - this.resultObject = future; - } - - @Override - public boolean isCancelled() { - return this.getResult().getSeverity() == IStatus.CANCEL; - } - - @Override - public boolean isDone() { - return done; - } - - @Override - public void addListener(Runnable listener, Executor executor) { - listeners.add(new Listener(listener, executor)); - } - } private final PropertyChangeListener repositoryChangeListener4ConfigurationCache = new PropertyChangeListener() { @@ -250,31 +158,6 @@ public Optional load(RepositoryKey key) throws Exception { return Optional.fromNullable(client.getConfiguration(key.getRepository(), context.get())); } - @Override - public ListenableFuture> reload(final RepositoryKey key, - Optional oldValue) throws Exception { - // asynchronous! - ListenableFutureJob> job = new ListenableFutureJob>( - "") { - - @Override - protected IStatus run(IProgressMonitor monitor) { - GitlabRestClient client; - try { - client = clientCache.get(key); - set(Optional - .fromNullable(client.getConfiguration(key.getRepository(), context.get()))); - } catch (ExecutionException e) { - e.printStackTrace(); - return new Status(IStatus.ERROR, GitlabCoreActivator.PLUGIN_ID, - "GitlabConnector reload Configuration", e); - } - return Status.OK_STATUS; - } - }; - job.schedule(); - return job; - } }); } diff --git a/mylyn.tasks/connectors/gitlab/org.eclipse.mylyn.gitlab.feature/feature.properties b/mylyn.tasks/connectors/gitlab/org.eclipse.mylyn.gitlab.feature/feature.properties index da67b46acd..230489a847 100644 --- a/mylyn.tasks/connectors/gitlab/org.eclipse.mylyn.gitlab.feature/feature.properties +++ b/mylyn.tasks/connectors/gitlab/org.eclipse.mylyn.gitlab.feature/feature.properties @@ -1,5 +1,5 @@ ############################################################################### -# Copyright (c) 2011, 2023 Chris Aniszczyk and others. +# Copyright (c) 2023 Frank Becker and others. # All rights reserved. This program and the accompanying materials # are made available under the terms of the Eclipse Public License 2.0 # which accompanies this distribution, and is available at @@ -10,169 +10,6 @@ featureName=Mylyn Tasks Connector: Gitlab Preview for gitlab.com only providerName=Eclipse Mylyn - -updateSiteName=Eclipse Mylyn Update Site - -# description property - text of the "Feature Description" description=Mylyn Task Connector for Gitlab -################ end of description property ################################## - -# "copyright" property - text of the "Feature Update Copyright" -copyright=\ -Copyright (c) 2023 Frank Becker, et.al.\n\ -All rights reserved. This program and the accompanying materials\n\ -are made available under the terms of the Eclipse Public License 2.0\n\ -which accompanies this distribution, and is available at\n\ -https://www.eclipse.org/legal/epl-2.0/\n\ -\n\ -SPDX-License-Identifier: EPL-2.0\n -################ end of copyright property #################################### - -# "licenseURL" property - URL of the "Feature License" -# do not translate value - just change to point to a locale-specific HTML page -licenseURL=license.html - -# "license" property - text of the "Feature Update License" -# should be plain text version of license agreement pointed to be "licenseURL" -license=\ -Eclipse Foundation Software User Agreement\n\ -\n\ -November 22, 2017\n\ -\n\ -Usage Of Content\n\ -\n\ -THE ECLIPSE FOUNDATION MAKES AVAILABLE SOFTWARE, DOCUMENTATION, INFORMATION\n\ -AND/OR OTHER MATERIALS FOR OPEN SOURCE PROJECTS (COLLECTIVELY "CONTENT"). USE OF\n\ -THE CONTENT IS GOVERNED BY THE TERMS AND CONDITIONS OF THIS AGREEMENT AND/OR THE\n\ -TERMS AND CONDITIONS OF LICENSE AGREEMENTS OR NOTICES INDICATED OR REFERENCED\n\ -BELOW. BY USING THE CONTENT, YOU AGREE THAT YOUR USE OF THE CONTENT IS GOVERNED\n\ -BY THIS AGREEMENT AND/OR THE TERMS AND CONDITIONS OF ANY APPLICABLE LICENSE\n\ -AGREEMENTS OR NOTICES INDICATED OR REFERENCED BELOW. IF YOU DO NOT AGREE TO THE\n\ -TERMS AND CONDITIONS OF THIS AGREEMENT AND THE TERMS AND CONDITIONS OF ANY\n\ -APPLICABLE LICENSE AGREEMENTS OR NOTICES INDICATED OR REFERENCED BELOW, THEN YOU\n\ -MAY NOT USE THE CONTENT.\n\ -\n\ -Applicable Licenses\n\ -\n\ -Unless otherwise indicated, all Content made available by the Eclipse Foundation\n\ -is provided to you under the terms and conditions of the Eclipse Public License\n\ -Version 2.0 ("EPL"). A copy of the EPL is provided with this Content and is also\n\ -available at http://www.eclipse.org/legal/epl-2.0. For purposes of the EPL,\n\ -"Program" will mean the Content.\n\ -\n\ -Content includes, but is not limited to, source code, object code, documentation\n\ -and other files maintained in the Eclipse Foundation source code repository\n\ -("Repository") in software modules ("Modules") and made available as\n\ -downloadable archives ("Downloads").\n\ -\n\ -- Content may be structured and packaged into modules to facilitate\n\ - delivering, extending, and upgrading the Content. Typical modules may\n\ - include plug-ins ("Plug-ins"), plug-in fragments ("Fragments"), and\n\ - features ("Features").\n\ -- Each Plug-in or Fragment may be packaged as a sub-directory or JAR\n\ - (Java\u2122 ARchive) in a directory named "plugins".\n\ -- A Feature is a bundle of one or more Plug-ins and/or Fragments and\n\ - associated material. Each Feature may be packaged as a sub-directory in a\n\ - directory named "features". Within a Feature, files named "feature.xml" may\n\ - contain a list of the names and version numbers of the Plug-ins and/or\n\ - Fragments associated with that Feature.\n\ -- Features may also include other Features ("Included Features"). Within a\n\ - Feature, files named "feature.xml" may contain a list of the names and\n\ - version numbers of Included Features.\n\ -\n\ -The terms and conditions governing Plug-ins and Fragments should be contained in\n\ -files named "about.html" ("Abouts"). The terms and conditions governing Features\n\ -and Included Features should be contained in files named "license.html"\n\ -("Feature Licenses"). Abouts and Feature Licenses may be located in any\n\ -directory of a Download or Module including, but not limited to the following\n\ -locations:\n\ -\n\ -- The top-level (root) directory\n\ -- Plug-in and Fragment directories\n\ -- Inside Plug-ins and Fragments packaged as JARs\n\ -- Sub-directories of the directory named "src" of certain Plug-ins\n\ -- Feature directories\n\ -\n\ -Note: if a Feature made available by the Eclipse Foundation is installed using\n\ -the Provisioning Technology (as defined below), you must agree to a license\n\ -("Feature Update License") during the installation process. If the Feature\n\ -contains Included Features, the Feature Update License should either provide you\n\ -with the terms and conditions governing the Included Features or inform you\n\ -where you can locate them. Feature Update Licenses may be found in the "license"\n\ -property of files named "feature.properties" found within a Feature. Such\n\ -Abouts, Feature Licenses, and Feature Update Licenses contain the terms and\n\ -conditions (or references to such terms and conditions) that govern your use of\n\ -the associated Content in that directory.\n\ -\n\ -THE ABOUTS, FEATURE LICENSES, AND FEATURE UPDATE LICENSES MAY REFER TO THE EPL\n\ -OR OTHER LICENSE AGREEMENTS, NOTICES OR TERMS AND CONDITIONS. SOME OF THESE\n\ -OTHER LICENSE AGREEMENTS MAY INCLUDE (BUT ARE NOT LIMITED TO):\n\ -\n\ -- Eclipse Public License Version 1.0 (available at\n\ - http://www.eclipse.org/legal/epl-v10.html)\n\ -- Eclipse Distribution License Version 1.0 (available at\n\ - http://www.eclipse.org/licenses/edl-v1.0.html)\n\ -- Common Public License Version 1.0 (available at\n\ - http://www.eclipse.org/legal/cpl-v10.html)\n\ -- Apache Software License 1.1 (available at\n\ - http://www.apache.org/licenses/LICENSE)\n\ -- Apache Software License 2.0 (available at\n\ - http://www.apache.org/licenses/LICENSE-2.0)\n\ -- Mozilla Public License Version 1.1 (available at\n\ - http://www.mozilla.org/MPL/MPL-1.1.html)\n\ -\n\ -IT IS YOUR OBLIGATION TO READ AND ACCEPT ALL SUCH TERMS AND CONDITIONS PRIOR TO\n\ -USE OF THE CONTENT. If no About, Feature License, or Feature Update License is\n\ -provided, please contact the Eclipse Foundation to determine what terms and\n\ -conditions govern that particular Content.\n\ -\n\ -Use of Provisioning Technology\n\ -\n\ -The Eclipse Foundation makes available provisioning software, examples of which\n\ -include, but are not limited to, p2 and the Eclipse Update Manager\n\ -("Provisioning Technology") for the purpose of allowing users to install\n\ -software, documentation, information and/or other materials (collectively\n\ -"Installable Software"). This capability is provided with the intent of allowing\n\ -such users to install, extend and update Eclipse-based products. Information\n\ -about packaging Installable Software is available at\n\ -http://eclipse.org/equinox/p2/repository_packaging.html ("Specification").\n\ -\n\ -You may use Provisioning Technology to allow other parties to install\n\ -Installable Software. You shall be responsible for enabling the applicable\n\ -license agreements relating to the Installable Software to be presented to, and\n\ -accepted by, the users of the Provisioning Technology in accordance with the\n\ -Specification. By using Provisioning Technology in such a manner and making it\n\ -available in accordance with the Specification, you further acknowledge your\n\ -agreement to, and the acquisition of all necessary rights to permit the\n\ -following:\n\ -\n\ -1. A series of actions may occur ("Provisioning Process") in which a user may\n\ - execute the Provisioning Technology on a machine ("Target Machine") with the\n\ - intent of installing, extending or updating the functionality of an\n\ - Eclipse-based product.\n\ -2. During the Provisioning Process, the Provisioning Technology may cause third\n\ - party Installable Software or a portion thereof to be accessed and copied to\n\ - the Target Machine.\n\ -3. Pursuant to the Specification, you will provide to the user the terms and\n\ - conditions that govern the use of the Installable Software ("Installable\n\ - Software Agreement") and such Installable Software Agreement shall be\n\ - accessed from the Target Machine in accordance with the Specification. Such\n\ - Installable Software Agreement must inform the user of the terms and\n\ - conditions that govern the Installable Software and must solicit acceptance\n\ - by the end user in the manner prescribed in such Installable\n\ - Software Agreement. Upon such indication of agreement by the user, the\n\ - provisioning Technology will complete installation of the\n\ - Installable Software.\n\ -\n\ -Cryptography\n\ -\n\ -Content may contain encryption software. The country in which you are currently\n\ -may have restrictions on the import, possession, and use, and/or re-export to\n\ -another country, of encryption software. BEFORE using any encryption software,\n\ -please check the country's laws, regulations and policies concerning the import,\n\ -possession, or use, and re-export of encryption software, to see if this is\n\ -permitted.\n\ -\n\ -Java and all Java-based trademarks are trademarks of Oracle Corporation in the\n\ -United States, other countries, or both.\n -########### end of license property ########################################## +copyright=Copyright (c) 2023 Frank Becker and others. All rights reserved. +updateSiteName=Eclipse Mylyn Update Site diff --git a/mylyn.tasks/connectors/gitlab/org.eclipse.mylyn.gitlab.feature/feature.xml b/mylyn.tasks/connectors/gitlab/org.eclipse.mylyn.gitlab.feature/feature.xml index 31a557e277..56dbf0acc5 100644 --- a/mylyn.tasks/connectors/gitlab/org.eclipse.mylyn.gitlab.feature/feature.xml +++ b/mylyn.tasks/connectors/gitlab/org.eclipse.mylyn.gitlab.feature/feature.xml @@ -16,7 +16,9 @@ label="%featureName" version="4.0.0.qualifier" provider-name="%providerName" - plugin="org.eclipse.mylyn.gitlab.core"> + plugin="org.eclipse.mylyn.gitlab.core" + license-feature="org.eclipse.license" + license-feature-version="0.0.0"> %description diff --git a/mylyn.tasks/connectors/gitlab/org.eclipse.mylyn.gitlab.source.feature/.project b/mylyn.tasks/connectors/gitlab/org.eclipse.mylyn.gitlab.source.feature/.project new file mode 100644 index 0000000000..e76ab5aca0 --- /dev/null +++ b/mylyn.tasks/connectors/gitlab/org.eclipse.mylyn.gitlab.source.feature/.project @@ -0,0 +1,17 @@ + + + org.eclipse.mylyn.gitlab.source.feature + + + + + + org.eclipse.pde.FeatureBuilder + + + + + + org.eclipse.pde.FeatureNature + + diff --git a/mylyn.tasks/connectors/gitlab/org.eclipse.mylyn.gitlab.source.feature/feature.properties b/mylyn.tasks/connectors/gitlab/org.eclipse.mylyn.gitlab.source.feature/feature.properties index 9a6b78c3b0..ac930e184e 100644 --- a/mylyn.tasks/connectors/gitlab/org.eclipse.mylyn.gitlab.source.feature/feature.properties +++ b/mylyn.tasks/connectors/gitlab/org.eclipse.mylyn.gitlab.source.feature/feature.properties @@ -10,169 +10,6 @@ featureName=Mylyn Tasks Connector: Gitlab SDK Preview for gitlab.com only providerName=Eclipse Mylyn - -updateSiteName=Eclipse Mylyn Update Site - -# description property - text of the "Feature Description" description=Mylyn Task Connector SDK for Gitlab -################ end of description property ################################## - -# "copyright" property - text of the "Feature Update Copyright" -copyright=\ -Copyright (c) 2023 Frank Becker, et.al.\n\ -All rights reserved. This program and the accompanying materials\n\ -are made available under the terms of the Eclipse Public License 2.0\n\ -which accompanies this distribution, and is available at\n\ -https://www.eclipse.org/legal/epl-2.0/\n\ -\n\ -SPDX-License-Identifier: EPL-2.0\n -################ end of copyright property #################################### - -# "licenseURL" property - URL of the "Feature License" -# do not translate value - just change to point to a locale-specific HTML page -licenseURL=license.html - -# "license" property - text of the "Feature Update License" -# should be plain text version of license agreement pointed to be "licenseURL" -license=\ -Eclipse Foundation Software User Agreement\n\ -\n\ -November 22, 2017\n\ -\n\ -Usage Of Content\n\ -\n\ -THE ECLIPSE FOUNDATION MAKES AVAILABLE SOFTWARE, DOCUMENTATION, INFORMATION\n\ -AND/OR OTHER MATERIALS FOR OPEN SOURCE PROJECTS (COLLECTIVELY "CONTENT"). USE OF\n\ -THE CONTENT IS GOVERNED BY THE TERMS AND CONDITIONS OF THIS AGREEMENT AND/OR THE\n\ -TERMS AND CONDITIONS OF LICENSE AGREEMENTS OR NOTICES INDICATED OR REFERENCED\n\ -BELOW. BY USING THE CONTENT, YOU AGREE THAT YOUR USE OF THE CONTENT IS GOVERNED\n\ -BY THIS AGREEMENT AND/OR THE TERMS AND CONDITIONS OF ANY APPLICABLE LICENSE\n\ -AGREEMENTS OR NOTICES INDICATED OR REFERENCED BELOW. IF YOU DO NOT AGREE TO THE\n\ -TERMS AND CONDITIONS OF THIS AGREEMENT AND THE TERMS AND CONDITIONS OF ANY\n\ -APPLICABLE LICENSE AGREEMENTS OR NOTICES INDICATED OR REFERENCED BELOW, THEN YOU\n\ -MAY NOT USE THE CONTENT.\n\ -\n\ -Applicable Licenses\n\ -\n\ -Unless otherwise indicated, all Content made available by the Eclipse Foundation\n\ -is provided to you under the terms and conditions of the Eclipse Public License\n\ -Version 2.0 ("EPL"). A copy of the EPL is provided with this Content and is also\n\ -available at http://www.eclipse.org/legal/epl-2.0. For purposes of the EPL,\n\ -"Program" will mean the Content.\n\ -\n\ -Content includes, but is not limited to, source code, object code, documentation\n\ -and other files maintained in the Eclipse Foundation source code repository\n\ -("Repository") in software modules ("Modules") and made available as\n\ -downloadable archives ("Downloads").\n\ -\n\ -- Content may be structured and packaged into modules to facilitate\n\ - delivering, extending, and upgrading the Content. Typical modules may\n\ - include plug-ins ("Plug-ins"), plug-in fragments ("Fragments"), and\n\ - features ("Features").\n\ -- Each Plug-in or Fragment may be packaged as a sub-directory or JAR\n\ - (Java\u2122 ARchive) in a directory named "plugins".\n\ -- A Feature is a bundle of one or more Plug-ins and/or Fragments and\n\ - associated material. Each Feature may be packaged as a sub-directory in a\n\ - directory named "features". Within a Feature, files named "feature.xml" may\n\ - contain a list of the names and version numbers of the Plug-ins and/or\n\ - Fragments associated with that Feature.\n\ -- Features may also include other Features ("Included Features"). Within a\n\ - Feature, files named "feature.xml" may contain a list of the names and\n\ - version numbers of Included Features.\n\ -\n\ -The terms and conditions governing Plug-ins and Fragments should be contained in\n\ -files named "about.html" ("Abouts"). The terms and conditions governing Features\n\ -and Included Features should be contained in files named "license.html"\n\ -("Feature Licenses"). Abouts and Feature Licenses may be located in any\n\ -directory of a Download or Module including, but not limited to the following\n\ -locations:\n\ -\n\ -- The top-level (root) directory\n\ -- Plug-in and Fragment directories\n\ -- Inside Plug-ins and Fragments packaged as JARs\n\ -- Sub-directories of the directory named "src" of certain Plug-ins\n\ -- Feature directories\n\ -\n\ -Note: if a Feature made available by the Eclipse Foundation is installed using\n\ -the Provisioning Technology (as defined below), you must agree to a license\n\ -("Feature Update License") during the installation process. If the Feature\n\ -contains Included Features, the Feature Update License should either provide you\n\ -with the terms and conditions governing the Included Features or inform you\n\ -where you can locate them. Feature Update Licenses may be found in the "license"\n\ -property of files named "feature.properties" found within a Feature. Such\n\ -Abouts, Feature Licenses, and Feature Update Licenses contain the terms and\n\ -conditions (or references to such terms and conditions) that govern your use of\n\ -the associated Content in that directory.\n\ -\n\ -THE ABOUTS, FEATURE LICENSES, AND FEATURE UPDATE LICENSES MAY REFER TO THE EPL\n\ -OR OTHER LICENSE AGREEMENTS, NOTICES OR TERMS AND CONDITIONS. SOME OF THESE\n\ -OTHER LICENSE AGREEMENTS MAY INCLUDE (BUT ARE NOT LIMITED TO):\n\ -\n\ -- Eclipse Public License Version 1.0 (available at\n\ - http://www.eclipse.org/legal/epl-v10.html)\n\ -- Eclipse Distribution License Version 1.0 (available at\n\ - http://www.eclipse.org/licenses/edl-v1.0.html)\n\ -- Common Public License Version 1.0 (available at\n\ - http://www.eclipse.org/legal/cpl-v10.html)\n\ -- Apache Software License 1.1 (available at\n\ - http://www.apache.org/licenses/LICENSE)\n\ -- Apache Software License 2.0 (available at\n\ - http://www.apache.org/licenses/LICENSE-2.0)\n\ -- Mozilla Public License Version 1.1 (available at\n\ - http://www.mozilla.org/MPL/MPL-1.1.html)\n\ -\n\ -IT IS YOUR OBLIGATION TO READ AND ACCEPT ALL SUCH TERMS AND CONDITIONS PRIOR TO\n\ -USE OF THE CONTENT. If no About, Feature License, or Feature Update License is\n\ -provided, please contact the Eclipse Foundation to determine what terms and\n\ -conditions govern that particular Content.\n\ -\n\ -Use of Provisioning Technology\n\ -\n\ -The Eclipse Foundation makes available provisioning software, examples of which\n\ -include, but are not limited to, p2 and the Eclipse Update Manager\n\ -("Provisioning Technology") for the purpose of allowing users to install\n\ -software, documentation, information and/or other materials (collectively\n\ -"Installable Software"). This capability is provided with the intent of allowing\n\ -such users to install, extend and update Eclipse-based products. Information\n\ -about packaging Installable Software is available at\n\ -http://eclipse.org/equinox/p2/repository_packaging.html ("Specification").\n\ -\n\ -You may use Provisioning Technology to allow other parties to install\n\ -Installable Software. You shall be responsible for enabling the applicable\n\ -license agreements relating to the Installable Software to be presented to, and\n\ -accepted by, the users of the Provisioning Technology in accordance with the\n\ -Specification. By using Provisioning Technology in such a manner and making it\n\ -available in accordance with the Specification, you further acknowledge your\n\ -agreement to, and the acquisition of all necessary rights to permit the\n\ -following:\n\ -\n\ -1. A series of actions may occur ("Provisioning Process") in which a user may\n\ - execute the Provisioning Technology on a machine ("Target Machine") with the\n\ - intent of installing, extending or updating the functionality of an\n\ - Eclipse-based product.\n\ -2. During the Provisioning Process, the Provisioning Technology may cause third\n\ - party Installable Software or a portion thereof to be accessed and copied to\n\ - the Target Machine.\n\ -3. Pursuant to the Specification, you will provide to the user the terms and\n\ - conditions that govern the use of the Installable Software ("Installable\n\ - Software Agreement") and such Installable Software Agreement shall be\n\ - accessed from the Target Machine in accordance with the Specification. Such\n\ - Installable Software Agreement must inform the user of the terms and\n\ - conditions that govern the Installable Software and must solicit acceptance\n\ - by the end user in the manner prescribed in such Installable\n\ - Software Agreement. Upon such indication of agreement by the user, the\n\ - provisioning Technology will complete installation of the\n\ - Installable Software.\n\ -\n\ -Cryptography\n\ -\n\ -Content may contain encryption software. The country in which you are currently\n\ -may have restrictions on the import, possession, and use, and/or re-export to\n\ -another country, of encryption software. BEFORE using any encryption software,\n\ -please check the country's laws, regulations and policies concerning the import,\n\ -possession, or use, and re-export of encryption software, to see if this is\n\ -permitted.\n\ -\n\ -Java and all Java-based trademarks are trademarks of Oracle Corporation in the\n\ -United States, other countries, or both.\n -########### end of license property ########################################## +copyright=Copyright (c) 2023 Frank Becker and others. All rights reserved. +updateSiteName=Eclipse Mylyn Update Site diff --git a/mylyn.tasks/connectors/gitlab/org.eclipse.mylyn.gitlab.ui/build.properties b/mylyn.tasks/connectors/gitlab/org.eclipse.mylyn.gitlab.ui/build.properties index 632074d169..cb730db533 100644 --- a/mylyn.tasks/connectors/gitlab/org.eclipse.mylyn.gitlab.ui/build.properties +++ b/mylyn.tasks/connectors/gitlab/org.eclipse.mylyn.gitlab.ui/build.properties @@ -9,4 +9,5 @@ source.. = src/ output.. = bin/ bin.includes = META-INF/,\ .,\ - plugin.xml + plugin.xml,\ + icons/ diff --git a/mylyn.tasks/connectors/gitlab/org.eclipse.mylyn.gitlab.ui/src/org/eclipse/mylyn/gitlab/ui/GitlabImages.java b/mylyn.tasks/connectors/gitlab/org.eclipse.mylyn.gitlab.ui/src/org/eclipse/mylyn/gitlab/ui/GitlabImages.java deleted file mode 100644 index 80c7e8e549..0000000000 --- a/mylyn.tasks/connectors/gitlab/org.eclipse.mylyn.gitlab.ui/src/org/eclipse/mylyn/gitlab/ui/GitlabImages.java +++ /dev/null @@ -1,38 +0,0 @@ -/******************************************************************************* - * Copyright (c) 2023 Frank Becker and others. - * - * This program and the accompanying materials are made available under the - * terms of the Eclipse Public License v. 2.0 which is available at - * https://www.eclipse.org/legal/epl-2.0 - * - * SPDX-License-Identifier: EPL-2.0 - * - * Contributors: - * Frank Becker - initial API and implementation - *******************************************************************************/ -package org.eclipse.mylyn.gitlab.ui; - -import org.eclipse.jface.resource.ImageDescriptor; -import org.eclipse.jface.resource.ImageRegistry; -import org.eclipse.swt.graphics.Image; - -public class GitlabImages { - - // For the images - private static ImageRegistry fImageRegistry = new ImageRegistry(); - - public static String GITLAB_PICTURE_FILE = "icons/obj20/gitlab.png"; //$NON-NLS-1$ - - static { - fImageRegistry.put(GITLAB_PICTURE_FILE, GitlabUiActivator.getImageDescriptor(GITLAB_PICTURE_FILE)); - } - - public static ImageDescriptor getDescriptor(String key) { - return fImageRegistry.getDescriptor(key); - } - - public static Image getImage(String key) { - return fImageRegistry.get(key); - } - -} diff --git a/mylyn.tasks/connectors/gitlab/org.eclipse.mylyn.gitlab.ui/src/org/eclipse/mylyn/gitlab/ui/GitlabUiActivator.java b/mylyn.tasks/connectors/gitlab/org.eclipse.mylyn.gitlab.ui/src/org/eclipse/mylyn/gitlab/ui/GitlabUiActivator.java index 24e1714ef7..5fb5c649a5 100644 --- a/mylyn.tasks/connectors/gitlab/org.eclipse.mylyn.gitlab.ui/src/org/eclipse/mylyn/gitlab/ui/GitlabUiActivator.java +++ b/mylyn.tasks/connectors/gitlab/org.eclipse.mylyn.gitlab.ui/src/org/eclipse/mylyn/gitlab/ui/GitlabUiActivator.java @@ -13,11 +13,8 @@ package org.eclipse.mylyn.gitlab.ui; -import java.io.File; - import org.eclipse.jface.resource.ImageDescriptor; -import org.eclipse.mylyn.internal.tasks.core.ITasksCoreConstants; -import org.eclipse.mylyn.internal.tasks.ui.TasksUiPlugin; +import org.eclipse.jface.resource.ImageRegistry; import org.eclipse.ui.plugin.AbstractUIPlugin; import org.osgi.framework.BundleContext; @@ -26,48 +23,58 @@ */ public class GitlabUiActivator extends AbstractUIPlugin { - // The plug-in ID - public static final String PLUGIN_ID = "org.eclipse.mylyn.gitlab.ui"; //$NON-NLS-1$ + // The plug-in ID + public static final String PLUGIN_ID = "org.eclipse.mylyn.gitlab.ui"; //$NON-NLS-1$ + + // The shared instance + private static GitlabUiActivator plugin; + + public static String GITLAB_PICTURE_FILE = "icons/obj20/gitlab.png"; //$NON-NLS-1$ + + /** + * The constructor + */ + public GitlabUiActivator() { + } - // The shared instance - private static GitlabUiActivator plugin; - - /** - * The constructor - */ - public GitlabUiActivator() { - } + @Override + public void start(BundleContext context) throws Exception { + super.start(context); + plugin = this; + } - @Override - public void start(BundleContext context) throws Exception { - super.start(context); - plugin = this; - } + @Override + public void stop(BundleContext context) throws Exception { + plugin = null; + super.stop(context); + } - @Override - public void stop(BundleContext context) throws Exception { - plugin = null; - super.stop(context); - } + /** + * Returns the shared instance + * + * @return the shared instance + */ + public static GitlabUiActivator getDefault() { + return plugin; + } - /** - * Returns the shared instance - * - * @return the shared instance - */ - public static GitlabUiActivator getDefault() { - return plugin; - } + /** + * @see AbstractUIPlugin#initializeImageRegistry(ImageRegistry) + */ + @Override + protected void initializeImageRegistry(ImageRegistry reg) { + reg.put(GITLAB_PICTURE_FILE, getImageDescriptor(GITLAB_PICTURE_FILE)); + } - /** - * Returns an image descriptor for the image file at the given plug-in relative path - * - * @param path - * the path - * @return the image descriptor - */ - public static ImageDescriptor getImageDescriptor(String path) { - return imageDescriptorFromPlugin(PLUGIN_ID, path); - } + /** + * Returns an image descriptor for the image file at the given plug-in relative + * path + * + * @param path the path + * @return the image descriptor + */ + public static ImageDescriptor getImageDescriptor(String path) { + return imageDescriptorFromPlugin(PLUGIN_ID, path); + } } diff --git a/mylyn.tasks/connectors/gitlab/org.eclipse.mylyn.gitlab.ui/src/org/eclipse/mylyn/internal/gitlab/ui/GitlabTaskEditorCommentPart.java b/mylyn.tasks/connectors/gitlab/org.eclipse.mylyn.gitlab.ui/src/org/eclipse/mylyn/internal/gitlab/ui/GitlabTaskEditorCommentPart.java index 6850a05f71..4ae7752a74 100644 --- a/mylyn.tasks/connectors/gitlab/org.eclipse.mylyn.gitlab.ui/src/org/eclipse/mylyn/internal/gitlab/ui/GitlabTaskEditorCommentPart.java +++ b/mylyn.tasks/connectors/gitlab/org.eclipse.mylyn.gitlab.ui/src/org/eclipse/mylyn/internal/gitlab/ui/GitlabTaskEditorCommentPart.java @@ -24,7 +24,7 @@ import org.eclipse.mylyn.commons.ui.FillWidthLayout; import org.eclipse.mylyn.commons.workbench.forms.CommonFormUtil; import org.eclipse.mylyn.gitlab.core.GitlabCoreActivator; -import org.eclipse.mylyn.gitlab.ui.GitlabImages; +import org.eclipse.mylyn.gitlab.ui.GitlabUiActivator; import org.eclipse.mylyn.internal.gitlab.core.GitlabRepositoryConnector; import org.eclipse.mylyn.internal.tasks.core.CommentQuoter; import org.eclipse.mylyn.internal.tasks.core.TaskComment; @@ -46,7 +46,6 @@ import org.eclipse.swt.SWT; import org.eclipse.swt.events.MouseAdapter; import org.eclipse.swt.events.MouseEvent; -import org.eclipse.swt.graphics.Color; import org.eclipse.swt.layout.GridData; import org.eclipse.swt.layout.GridLayout; import org.eclipse.swt.layout.RowLayout; @@ -182,47 +181,6 @@ public GitlabCommentViewer(TaskAttribute commentAttribute) { super(commentAttribute); } - public Control createControl(Composite composite, FormToolkit toolkit) { - boolean hasIncomingChanges = getModel().hasIncomingChanges(commentAttribute); - getTaskData().getAttributeMapper().updateTaskComment(taskComment, commentAttribute); - int style = ExpandableComposite.TREE_NODE | ExpandableComposite.LEFT_TEXT_CLIENT_ALIGNMENT - | ExpandableComposite.COMPACT; - if (hasIncomingChanges || (expandAllInProgress && !suppressExpandViewers)) { - style |= ExpandableComposite.EXPANDED; - } - composite.setMenu(null); - commentComposite = toolkit.createExpandableComposite(composite, style); - commentComposite.clientVerticalSpacing = 0; - commentComposite.setLayout(new GridLayout()); - commentComposite.setLayoutData(new GridData(GridData.FILL_HORIZONTAL)); - commentComposite.setTitleBarForeground(toolkit.getColors().getColor(IFormColors.TITLE)); - - buttonComposite = createTitle(commentComposite, toolkit); - - Composite commentViewerComposite = toolkit.createComposite(commentComposite); - commentComposite.setClient(commentViewerComposite); - commentViewerComposite - .setLayout(new FillWidthLayout(EditorUtil.getLayoutAdvisor(getTaskEditorPage()), 15, 0, 0, 3)); - - commentComposite.addExpansionListener(new ExpansionAdapter() { - @Override - public void expansionStateChanged(ExpansionEvent event) { - if (commentViewerComposite != null && !commentViewerComposite.isDisposed()) - expandComment(toolkit, commentViewerComposite, event.getState()); - } - }); - if (hasIncomingChanges) { - commentComposite.setBackground(getTaskEditorPage().getAttributeEditorToolkit().getColorIncoming()); - } - if (commentComposite.isExpanded()) { - if (commentViewerComposite != null && !commentViewerComposite.isDisposed()) - expandComment(toolkit, commentViewerComposite, true); - } - // for outline - EditorUtil.setMarker(commentComposite, commentAttribute.getId()); - return commentComposite; - } - @Override protected void expandComment(FormToolkit toolkit, Composite composite, boolean expanded) { buttonComposite.setVisible(expanded); @@ -360,7 +318,7 @@ public void linkActivated(HyperlinkEvent e) { .parseBoolean(getModel().getTaskRepository().getProperty(GitlabCoreActivator.SHOW_COMMENT_ICONS)); if (showCommentIcons) { if ("true".equals(systemAttributeValue)) { - expandCommentHyperlink.setImage(GitlabImages.getImage(GitlabImages.GITLAB_PICTURE_FILE)); + expandCommentHyperlink.setImage(GitlabUiActivator.getDefault().getImageRegistry().get(GitlabUiActivator.GITLAB_PICTURE_FILE)); } else { IRepositoryPerson author = taskComment.getAuthor(); if (author != null diff --git a/mylyn.tasks/org.eclipse.mylyn.tasks.ui/src/org/eclipse/mylyn/internal/tasks/ui/editors/TaskEditorCommentPart.java b/mylyn.tasks/org.eclipse.mylyn.tasks.ui/src/org/eclipse/mylyn/internal/tasks/ui/editors/TaskEditorCommentPart.java index 2289bbf510..d44a865278 100644 --- a/mylyn.tasks/org.eclipse.mylyn.tasks.ui/src/org/eclipse/mylyn/internal/tasks/ui/editors/TaskEditorCommentPart.java +++ b/mylyn.tasks/org.eclipse.mylyn.tasks.ui/src/org/eclipse/mylyn/internal/tasks/ui/editors/TaskEditorCommentPart.java @@ -84,9 +84,9 @@ public class CommentGroupViewer { protected final CommentGroup commentGroup; - protected ArrayList commentViewers; + private ArrayList commentViewers; - protected Section groupSection; + private Section groupSection; private boolean renderedInSubSection; @@ -94,7 +94,7 @@ public CommentGroupViewer(CommentGroup commentGroup) { this.commentGroup = commentGroup; } - protected Composite createCommentViewers(Composite parent, FormToolkit toolkit) { + private Composite createCommentViewers(Composite parent, FormToolkit toolkit) { List viewers = getCommentViewers(); Composite composite = toolkit.createComposite(parent); @@ -283,7 +283,7 @@ public class CommentViewer { protected final TaskAttribute commentAttribute; - protected ExpandableComposite commentComposite; + private ExpandableComposite commentComposite; protected final TaskComment taskComment; From fe50f4d2fc640fb3f223e230e85e95efa7f5c415 Mon Sep 17 00:00:00 2001 From: Frank Becker Date: Wed, 2 Aug 2023 18:22:17 +0200 Subject: [PATCH 12/13] resolve conflict for category.xml --- org.eclipse.mylyn-site/category.xml | 161 ++++++++++++++++++++-------- 1 file changed, 114 insertions(+), 47 deletions(-) diff --git a/org.eclipse.mylyn-site/category.xml b/org.eclipse.mylyn-site/category.xml index 3a8c8dd96e..b9890719db 100644 --- a/org.eclipse.mylyn-site/category.xml +++ b/org.eclipse.mylyn-site/category.xml @@ -14,128 +14,196 @@ ******************************************************************************* --> - + - + + + + + + + - + + + + - + + + + + + + + + + + + + + + + - + + + + - + + + + - + + + + - + + + + - + + + + + + + - + + + + - + + + + + + + - - + + - + - - + + - + - - + + - + - - + + - + - - + + - + - - + + - + - + - - + + - + - - + + - + - + + + + - - + + + + + + + + + + + - - + + + + + + + + + - - - - + + The Task List and the Task-Focused Interface. @@ -156,10 +224,9 @@ Source code and documentation for integrators building on Mylyn. - + Source code for integrators building on Mylyn. - From 660f810f058e543e21b60e77a5dac840fb065f5a Mon Sep 17 00:00:00 2001 From: Frank Becker Date: Wed, 2 Aug 2023 22:29:39 +0200 Subject: [PATCH 13/13] remove gitlab source feature --- .../.project | 17 ------- .../org.eclipse.core.resources.prefs | 2 - .../build.properties | 9 ---- .../feature.properties | 15 ------ .../feature.xml | 51 ------------------- 5 files changed, 94 deletions(-) delete mode 100644 mylyn.tasks/connectors/gitlab/org.eclipse.mylyn.gitlab.source.feature/.project delete mode 100644 mylyn.tasks/connectors/gitlab/org.eclipse.mylyn.gitlab.source.feature/.settings/org.eclipse.core.resources.prefs delete mode 100644 mylyn.tasks/connectors/gitlab/org.eclipse.mylyn.gitlab.source.feature/build.properties delete mode 100644 mylyn.tasks/connectors/gitlab/org.eclipse.mylyn.gitlab.source.feature/feature.properties delete mode 100644 mylyn.tasks/connectors/gitlab/org.eclipse.mylyn.gitlab.source.feature/feature.xml diff --git a/mylyn.tasks/connectors/gitlab/org.eclipse.mylyn.gitlab.source.feature/.project b/mylyn.tasks/connectors/gitlab/org.eclipse.mylyn.gitlab.source.feature/.project deleted file mode 100644 index e76ab5aca0..0000000000 --- a/mylyn.tasks/connectors/gitlab/org.eclipse.mylyn.gitlab.source.feature/.project +++ /dev/null @@ -1,17 +0,0 @@ - - - org.eclipse.mylyn.gitlab.source.feature - - - - - - org.eclipse.pde.FeatureBuilder - - - - - - org.eclipse.pde.FeatureNature - - diff --git a/mylyn.tasks/connectors/gitlab/org.eclipse.mylyn.gitlab.source.feature/.settings/org.eclipse.core.resources.prefs b/mylyn.tasks/connectors/gitlab/org.eclipse.mylyn.gitlab.source.feature/.settings/org.eclipse.core.resources.prefs deleted file mode 100644 index 99f26c0203..0000000000 --- a/mylyn.tasks/connectors/gitlab/org.eclipse.mylyn.gitlab.source.feature/.settings/org.eclipse.core.resources.prefs +++ /dev/null @@ -1,2 +0,0 @@ -eclipse.preferences.version=1 -encoding/=UTF-8 diff --git a/mylyn.tasks/connectors/gitlab/org.eclipse.mylyn.gitlab.source.feature/build.properties b/mylyn.tasks/connectors/gitlab/org.eclipse.mylyn.gitlab.source.feature/build.properties deleted file mode 100644 index 560dde240e..0000000000 --- a/mylyn.tasks/connectors/gitlab/org.eclipse.mylyn.gitlab.source.feature/build.properties +++ /dev/null @@ -1,9 +0,0 @@ -############################################################################### -# Copyright (c) 2023 Frank Becker and others. -# All rights reserved. This program and the accompanying materials -# are made available under the terms of the Eclipse Public License v2.0 -# which accompanies this distribution, and is available at -# http://www.eclipse.org/legal/epl-v20.html -############################################################################### -bin.includes = feature.xml,\ - feature.properties diff --git a/mylyn.tasks/connectors/gitlab/org.eclipse.mylyn.gitlab.source.feature/feature.properties b/mylyn.tasks/connectors/gitlab/org.eclipse.mylyn.gitlab.source.feature/feature.properties deleted file mode 100644 index ac930e184e..0000000000 --- a/mylyn.tasks/connectors/gitlab/org.eclipse.mylyn.gitlab.source.feature/feature.properties +++ /dev/null @@ -1,15 +0,0 @@ -############################################################################### -# Copyright (c) 2011, 2023 Chris Aniszczyk and others. -# All rights reserved. This program and the accompanying materials -# are made available under the terms of the Eclipse Public License 2.0 -# which accompanies this distribution, and is available at -# https://www.eclipse.org/legal/epl-2.0/ -# -# SPDX-License-Identifier: EPL-2.0 -############################################################################### - -featureName=Mylyn Tasks Connector: Gitlab SDK Preview for gitlab.com only -providerName=Eclipse Mylyn -description=Mylyn Task Connector SDK for Gitlab -copyright=Copyright (c) 2023 Frank Becker and others. All rights reserved. -updateSiteName=Eclipse Mylyn Update Site diff --git a/mylyn.tasks/connectors/gitlab/org.eclipse.mylyn.gitlab.source.feature/feature.xml b/mylyn.tasks/connectors/gitlab/org.eclipse.mylyn.gitlab.source.feature/feature.xml deleted file mode 100644 index 0b3be1080f..0000000000 --- a/mylyn.tasks/connectors/gitlab/org.eclipse.mylyn.gitlab.source.feature/feature.xml +++ /dev/null @@ -1,51 +0,0 @@ - - - - - - %description - - - - %copyright - - - - %license - - - - - - - - -