515333: [refactor] BugzillaRestPutUpdateTask -> BugzillaRestPutRequest

Change-Id: I0ff3e13d5164c0af0d84720ddbc198a720d7fd85
Task-Url: https://bugs.eclipse.org/bugs/show_bug.cgi?id=515333
diff --git a/connector-bugzilla-rest/org.eclipse.mylyn.bugzilla.rest.core/src/org/eclipse/mylyn/internal/bugzilla/rest/core/BugzillaRestPutRequest.java b/connector-bugzilla-rest/org.eclipse.mylyn.bugzilla.rest.core/src/org/eclipse/mylyn/internal/bugzilla/rest/core/BugzillaRestPutRequest.java
index 4699cb9..4a1447d 100644
--- a/connector-bugzilla-rest/org.eclipse.mylyn.bugzilla.rest.core/src/org/eclipse/mylyn/internal/bugzilla/rest/core/BugzillaRestPutRequest.java
+++ b/connector-bugzilla-rest/org.eclipse.mylyn.bugzilla.rest.core/src/org/eclipse/mylyn/internal/bugzilla/rest/core/BugzillaRestPutRequest.java
@@ -11,14 +11,92 @@
 
 package org.eclipse.mylyn.internal.bugzilla.rest.core;
 
+import java.io.IOException;
+import java.io.UnsupportedEncodingException;
+import java.util.Set;
+
 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.Assert;
+import org.eclipse.core.runtime.CoreException;
+import org.eclipse.core.runtime.IStatus;
+import org.eclipse.core.runtime.Status;
+import org.eclipse.jdt.annotation.NonNull;
+import org.eclipse.mylyn.commons.repositories.core.RepositoryLocation;
 import org.eclipse.mylyn.commons.repositories.http.core.CommonHttpClient;
+import org.eclipse.mylyn.tasks.core.data.TaskAttribute;
+
+import com.google.common.base.Function;
+import com.google.common.base.Throwables;
+import com.google.gson.Gson;
+import com.google.gson.GsonBuilder;
+import com.google.gson.TypeAdapter;
+import com.google.gson.stream.JsonReader;
+import com.google.gson.stream.JsonWriter;
 
 public abstract class BugzillaRestPutRequest<T> extends BugzillaRestRequest<T> {
 
-	public BugzillaRestPutRequest(CommonHttpClient client, String urlSuffix, boolean authenticationRequired) {
+	class TaskAttributes {
+		private final Set<TaskAttribute> taskAttributes;
+
+		public TaskAttributes(Set<TaskAttribute> taskAttributes) {
+			super();
+			this.taskAttributes = taskAttributes;
+		}
+
+		public Set<TaskAttribute> getTaskAttributes() {
+			return taskAttributes;
+		}
+
+		public boolean contains(TaskAttribute taskAttribute) {
+			return taskAttributes.contains(taskAttribute);
+		}
+
+	}
+
+	protected TaskAttributes taskAttributes;
+
+	protected final Function<String, String> function = new Function<String, String>() {
+
+		@Override
+		public String apply(String input) {
+			return BugzillaRestGsonUtil.convertString2GSonString(input);
+		}
+	};
+
+	class TaskAttributesTypeAdapter extends TypeAdapter<TaskAttributes> {
+		RepositoryLocation location;
+
+		public TaskAttributesTypeAdapter(RepositoryLocation location) {
+			super();
+			this.location = location;
+		}
+
+		@Override
+		public void write(JsonWriter out, TaskAttributes taskAttributes) throws IOException {
+			out.beginObject();
+			addAuthenticationToGson(out, location);
+			addPrefixToOutput(out);
+			for (TaskAttribute element : taskAttributes.taskAttributes) {
+				addAttributeToOutput(out, element);
+			}
+			addSuffixToOutput(out);
+			out.endObject();
+		}
+
+		@Override
+		public TaskAttributes read(JsonReader in) throws IOException {
+			throw new UnsupportedOperationException(
+					"TaskAttributeTypeAdapter in BugzillaRestPutUpdateTask only supports write"); //$NON-NLS-1$
+		}
+	}
+
+	public BugzillaRestPutRequest(CommonHttpClient client, String urlSuffix, boolean authenticationRequired,
+			@NonNull Set<TaskAttribute> taskAttributes) {
 		super(client, urlSuffix, authenticationRequired);
+		Assert.isNotNull(taskAttributes);
+		this.taskAttributes = new TaskAttributes(taskAttributes);
 	}
 
 	@Override
@@ -28,4 +106,25 @@
 		return request;
 	}
 
+	@Override
+	protected void addHttpRequestEntities(HttpRequestBase request) throws BugzillaRestException {
+		super.addHttpRequestEntities(request);
+		try {
+			Gson gson = new GsonBuilder()
+					.registerTypeAdapter(TaskAttributes.class, new TaskAttributesTypeAdapter(getClient().getLocation()))
+					.create();
+			StringEntity requestEntity = new StringEntity(gson.toJson(taskAttributes));
+			((HttpPut) request).setEntity(requestEntity);
+		} catch (UnsupportedEncodingException e) {
+			Throwables.propagate(new CoreException(
+					new Status(IStatus.ERROR, BugzillaRestCore.ID_PLUGIN, "Can not build HttpRequest", e))); //$NON-NLS-1$
+		}
+	}
+
+	public abstract void addPrefixToOutput(JsonWriter out) throws IOException;
+
+	public abstract void addAttributeToOutput(JsonWriter out, TaskAttribute element) throws IOException;
+
+	public abstract void addSuffixToOutput(JsonWriter out) throws IOException;
+
 }
\ No newline at end of file
diff --git a/connector-bugzilla-rest/org.eclipse.mylyn.bugzilla.rest.core/src/org/eclipse/mylyn/internal/bugzilla/rest/core/BugzillaRestPutUpdateTask.java b/connector-bugzilla-rest/org.eclipse.mylyn.bugzilla.rest.core/src/org/eclipse/mylyn/internal/bugzilla/rest/core/BugzillaRestPutUpdateTask.java
index bda2e8d..81d22a9 100644
--- a/connector-bugzilla-rest/org.eclipse.mylyn.bugzilla.rest.core/src/org/eclipse/mylyn/internal/bugzilla/rest/core/BugzillaRestPutUpdateTask.java
+++ b/connector-bugzilla-rest/org.eclipse.mylyn.bugzilla.rest.core/src/org/eclipse/mylyn/internal/bugzilla/rest/core/BugzillaRestPutUpdateTask.java
@@ -13,52 +13,28 @@
 
 import java.io.IOException;
 import java.io.InputStreamReader;
-import java.io.UnsupportedEncodingException;
 import java.util.Arrays;
 import java.util.HashSet;
 import java.util.List;
 import java.util.Set;
 
-import org.apache.http.NameValuePair;
-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.CoreException;
-import org.eclipse.core.runtime.IStatus;
-import org.eclipse.core.runtime.Status;
-import org.eclipse.mylyn.commons.repositories.core.RepositoryLocation;
+import org.eclipse.core.runtime.Assert;
+import org.eclipse.jdt.annotation.NonNull;
 import org.eclipse.mylyn.commons.repositories.http.core.CommonHttpClient;
 import org.eclipse.mylyn.internal.bugzilla.rest.core.response.data.PutUpdateResult;
 import org.eclipse.mylyn.tasks.core.data.TaskAttribute;
 import org.eclipse.mylyn.tasks.core.data.TaskData;
 
-import com.google.common.base.Function;
 import com.google.common.base.Joiner;
-import com.google.common.base.Throwables;
 import com.google.common.collect.ImmutableList;
 import com.google.common.collect.Iterables;
 import com.google.gson.Gson;
-import com.google.gson.GsonBuilder;
-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 BugzillaRestPutUpdateTask extends BugzillaRestPutRequest<PutUpdateResult> {
 	private final TaskData taskData;
 
-	class OldAttributes {
-		private final Set<TaskAttribute> oldAttributes;
-
-		public OldAttributes(Set<TaskAttribute> oldAttributes) {
-			super();
-			this.oldAttributes = oldAttributes;
-		}
-
-	}
-
-	OldAttributes oldAttributes;
-
 	ImmutableList<String> legalUpdateAttributes = new ImmutableList.Builder<String>()
 			.add(BugzillaRestTaskSchema.getDefault().PRODUCT.getKey())
 			.add(BugzillaRestTaskSchema.getDefault().COMPONENT.getKey())
@@ -85,149 +61,11 @@
 			.add(BugzillaRestTaskSchema.getDefault().RESET_ASSIGNED_TO.getKey())
 			.build();
 
-	class TaskAttributeTypeAdapter extends TypeAdapter<OldAttributes> {
-		RepositoryLocation location;
-
-		public TaskAttributeTypeAdapter(RepositoryLocation location) {
-			super();
-			this.location = location;
-		}
-
-		private final Function<String, String> function = new Function<String, String>() {
-
-			@Override
-			public String apply(String input) {
-				return BugzillaRestGsonUtil.convertString2GSonString(input);
-			}
-		};
-
-		@Override
-		public void write(JsonWriter out, OldAttributes oldValues) throws IOException {
-			out.beginObject();
-			addAuthenticationToGson(out, location);
-			for (TaskAttribute element : oldValues.oldAttributes) {
-				TaskAttribute taskAttribute = taskData.getRoot().getAttribute(element.getId());
-				String id = taskAttribute.getId();
-				String value = BugzillaRestGsonUtil.convertString2GSonString(taskAttribute.getValue());
-				if ((legalUpdateAttributes.contains(id) || id.startsWith("cf_")) && value != null) { //$NON-NLS-1$
-					id = BugzillaRestTaskSchema.getFieldNameFromAttributeName(id);
-					if (id.equals("status")) { //$NON-NLS-1$
-						if (value != null && value.equals(TaskAttribute.PREFIX_OPERATION + "default")) { //$NON-NLS-1$
-							continue;
-						}
-						if (value.equals("duplicate")) { //$NON-NLS-1$
-							TaskAttribute res = element.getParentAttribute()
-									.getAttribute(BugzillaRestTaskSchema.getDefault().RESOLUTION.getKey());
-							if (!oldAttributes.oldAttributes.contains(res)) {
-								out.name("resolution").value("DUPLICATE"); //$NON-NLS-1$ //$NON-NLS-2$
-							} else {
-								TaskAttribute res1 = taskData.getRoot()
-										.getAttribute(BugzillaRestTaskSchema.getDefault().RESOLUTION.getKey());
-								res1.setValue("DUPLICATE"); //$NON-NLS-1$
-							}
-							value = "RESOLVED"; //$NON-NLS-1$
-						}
-					}
-					if (taskAttribute.getMetaData().getType() != null
-							&& taskAttribute.getMetaData().getType().equals(TaskAttribute.TYPE_MULTI_SELECT)) {
-						Iterable<String> taskIdsTemp = Iterables.transform(taskAttribute.getValues(), function);
-						Joiner joiner = Joiner.on(",").skipNulls(); //$NON-NLS-1$
-						value = joiner.join(taskIdsTemp);
-					}
-					if (id.equals(BugzillaRestTaskSchema.getDefault().NEW_COMMENT.getKey())) {
-						out.name("comment").beginObject(); //$NON-NLS-1$
-						out.name("body").value(value); //$NON-NLS-1$
-						out.endObject();
-					} else if (id.equals(BugzillaRestTaskSchema.getDefault().BLOCKS.getKey())
-							|| id.equals(BugzillaRestTaskSchema.getDefault().DEPENDS_ON.getKey())) {
-						Set<String> setOld;
-						if (element.getValues().size() > 1) {
-							setOld = new HashSet<String>(element.getValues());
-						} else {
-							setOld = new HashSet<String>(Arrays.asList(element.getValue().split("\\s*,\\s*"))); //$NON-NLS-1$
-						}
-						Set<String> setNew;
-						if (taskAttribute.getValues().size() > 1) {
-							setNew = new HashSet<String>(taskAttribute.getValues());
-						} else {
-							setNew = new HashSet<String>(Arrays.asList(taskAttribute.getValue().split("\\s*,\\s*"))); //$NON-NLS-1$
-						}
-						BugzillaRestGsonUtil.getDefault().buildAddRemoveIntegerHash(out, id, setOld, setNew);
-					} else if (id.equals(BugzillaRestTaskSchema.getDefault().KEYWORDS.getKey())) {
-						Set<String> setOld = new HashSet<String>(element.getValues());
-						Set<String> setNew = new HashSet<String>(taskAttribute.getValues());
-						BugzillaRestGsonUtil.getDefault().buildAddRemoveHash(out, id, setOld, setNew);
-					} else {
-						out.name(id).value(value);
-						if (id.equals("description")) { //$NON-NLS-1$
-							TaskAttribute descriptionpri = taskAttribute
-									.getAttribute(BugzillaRestTaskSchema.getDefault().COMMENT_ISPRIVATE.getKey());
-							Boolean descriptionprivalue = (descriptionpri != null)
-									? (descriptionpri.getValue().equals("1")) //$NON-NLS-1$
-									: false;
-							out.name("comment_is_private").value(Boolean.toString(descriptionprivalue)); //$NON-NLS-1$
-						}
-					}
-				}
-			}
-			TaskAttribute cc = taskData.getRoot().getAttribute(BugzillaRestTaskSchema.getDefault().CC.getKey());
-			TaskAttribute addCC = taskData.getRoot().getAttribute(BugzillaRestTaskSchema.getDefault().ADD_CC.getKey());
-			TaskAttribute removeCC = taskData.getRoot()
-					.getAttribute(BugzillaRestTaskSchema.getDefault().REMOVE_CC.getKey());
-			TaskAttribute addSelfCC = taskData.getRoot()
-					.getAttribute(BugzillaRestTaskSchema.getDefault().ADD_SELF_CC.getKey());
-			if (Boolean.valueOf(addSelfCC.getValue())) {
-				String userName = addSelfCC.getMetaData().getValue("UserName"); //$NON-NLS-1$
-				if (userName != null) {
-					if (removeCC.getValues().contains(userName)) {
-						removeCC.removeValue(userName);
-					} else if (!cc.getValues().contains(userName)) {
-						List<String> addCCList = Arrays.asList(addCC.getValue().split("\\s*,\\s*")); //$NON-NLS-1$
-						if (!addCCList.contains(userName)) {
-							addCC.setValue(userName + (addCCList.size() > 0 && !addCCList.get(0).equals("") ? ", " : "") //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
-									+ addCC.getValue());
-						}
-					}
-				}
-			}
-			if (addCC.getValues().size() > 0 || removeCC.getValues().size() > 0) {
-				Set<String> setOld = new HashSet<String>(removeCC.getValues());
-				HashSet<String> setNew = new HashSet<String>(Arrays.asList(addCC.getValue().split("\\s*,\\s*"))); //$NON-NLS-1$
-				BugzillaRestGsonUtil.getDefault().buildAddRemoveHash(out, "cc", setOld, setNew); //$NON-NLS-1$
-			}
-			BugzillaRestGsonUtil.buildFlags(out, oldValues.oldAttributes, taskData.getRoot());
-			out.endObject();
-		}
-
-		@Override
-		public OldAttributes read(JsonReader in) throws IOException {
-			throw new UnsupportedOperationException(
-					"TaskAttributeTypeAdapter in BugzillaRestPutUpdateTask only supports write"); //$NON-NLS-1$
-		}
-
-	}
-
-	public BugzillaRestPutUpdateTask(CommonHttpClient client, TaskData taskData, Set<TaskAttribute> oldAttributes) {
-		super(client, "/bug/" + taskData.getTaskId(), false); //$NON-NLS-1$
+	public BugzillaRestPutUpdateTask(CommonHttpClient client, @NonNull TaskData taskData,
+			@NonNull Set<TaskAttribute> oldAttributes) {
+		super(client, "/bug/" + taskData.getTaskId(), false, oldAttributes); //$NON-NLS-1$
+		Assert.isNotNull(taskData);
 		this.taskData = taskData;
-		this.oldAttributes = new OldAttributes(oldAttributes);
-	}
-
-	List<NameValuePair> requestParameters;
-
-	@Override
-	protected void addHttpRequestEntities(HttpRequestBase request) throws BugzillaRestException {
-		super.addHttpRequestEntities(request);
-		try {
-			Gson gson = new GsonBuilder()
-					.registerTypeAdapter(OldAttributes.class, new TaskAttributeTypeAdapter(getClient().getLocation()))
-					.create();
-			StringEntity requestEntity = new StringEntity(gson.toJson(oldAttributes));
-			((HttpPut) request).setEntity(requestEntity);
-		} catch (UnsupportedEncodingException e) {
-			Throwables.propagate(new CoreException(
-					new Status(IStatus.ERROR, BugzillaRestCore.ID_PLUGIN, "Can not build HttpRequest", e))); //$NON-NLS-1$
-		}
 	}
 
 	public static String convert(String str) {
@@ -256,4 +94,106 @@
 		return new Gson().fromJson(in, type.getType());
 	}
 
+	@Override
+	public void addPrefixToOutput(JsonWriter out) throws IOException {
+		// not needed
+	}
+
+	@Override
+	public void addAttributeToOutput(JsonWriter out, TaskAttribute element) throws IOException {
+		TaskAttribute taskAttribute = taskData.getRoot().getAttribute(element.getId());
+		String id = taskAttribute.getId();
+		String value = BugzillaRestGsonUtil.convertString2GSonString(taskAttribute.getValue());
+		if ((legalUpdateAttributes.contains(id) || id.startsWith("cf_")) && value != null) { //$NON-NLS-1$
+			id = BugzillaRestTaskSchema.getFieldNameFromAttributeName(id);
+			if (id.equals("status")) { //$NON-NLS-1$
+				if (value != null && value.equals(TaskAttribute.PREFIX_OPERATION + "default")) { //$NON-NLS-1$
+					return;
+				}
+				if (value.equals("duplicate")) { //$NON-NLS-1$
+					TaskAttribute res = element.getParentAttribute()
+							.getAttribute(BugzillaRestTaskSchema.getDefault().RESOLUTION.getKey());
+					if (!taskAttributes.contains(res)) {
+						out.name("resolution").value("DUPLICATE"); //$NON-NLS-1$ //$NON-NLS-2$
+					} else {
+						TaskAttribute res1 = taskData.getRoot()
+								.getAttribute(BugzillaRestTaskSchema.getDefault().RESOLUTION.getKey());
+						res1.setValue("DUPLICATE"); //$NON-NLS-1$
+					}
+					value = "RESOLVED"; //$NON-NLS-1$
+				}
+			}
+			if (taskAttribute.getMetaData().getType() != null
+					&& taskAttribute.getMetaData().getType().equals(TaskAttribute.TYPE_MULTI_SELECT)) {
+				Iterable<String> taskIdsTemp = Iterables.transform(taskAttribute.getValues(), function);
+				Joiner joiner = Joiner.on(",").skipNulls(); //$NON-NLS-1$
+				value = joiner.join(taskIdsTemp);
+			}
+			if (id.equals(BugzillaRestTaskSchema.getDefault().NEW_COMMENT.getKey())) {
+				out.name("comment").beginObject(); //$NON-NLS-1$
+				out.name("body").value(value); //$NON-NLS-1$
+				out.endObject();
+			} else if (id.equals(BugzillaRestTaskSchema.getDefault().BLOCKS.getKey())
+					|| id.equals(BugzillaRestTaskSchema.getDefault().DEPENDS_ON.getKey())) {
+				Set<String> setOld;
+				if (element.getValues().size() > 1) {
+					setOld = new HashSet<String>(element.getValues());
+				} else {
+					setOld = new HashSet<String>(Arrays.asList(element.getValue().split("\\s*,\\s*"))); //$NON-NLS-1$
+				}
+				Set<String> setNew;
+				if (taskAttribute.getValues().size() > 1) {
+					setNew = new HashSet<String>(taskAttribute.getValues());
+				} else {
+					setNew = new HashSet<String>(Arrays.asList(taskAttribute.getValue().split("\\s*,\\s*"))); //$NON-NLS-1$
+				}
+				BugzillaRestGsonUtil.getDefault().buildAddRemoveIntegerHash(out, id, setOld, setNew);
+			} else if (id.equals(BugzillaRestTaskSchema.getDefault().KEYWORDS.getKey())) {
+				Set<String> setOld = new HashSet<String>(element.getValues());
+				Set<String> setNew = new HashSet<String>(taskAttribute.getValues());
+				BugzillaRestGsonUtil.getDefault().buildAddRemoveHash(out, id, setOld, setNew);
+			} else {
+				out.name(id).value(value);
+				if (id.equals("description")) { //$NON-NLS-1$
+					TaskAttribute descriptionpri = taskAttribute
+							.getAttribute(BugzillaRestTaskSchema.getDefault().COMMENT_ISPRIVATE.getKey());
+					Boolean descriptionprivalue = (descriptionpri != null)
+							? (descriptionpri.getValue().equals("1")) //$NON-NLS-1$
+							: false;
+					out.name("comment_is_private").value(Boolean.toString(descriptionprivalue)); //$NON-NLS-1$
+				}
+			}
+		}
+	}
+
+	@Override
+	public void addSuffixToOutput(JsonWriter out) throws IOException {
+		TaskAttribute cc = taskData.getRoot().getAttribute(BugzillaRestTaskSchema.getDefault().CC.getKey());
+		TaskAttribute addCC = taskData.getRoot().getAttribute(BugzillaRestTaskSchema.getDefault().ADD_CC.getKey());
+		TaskAttribute removeCC = taskData.getRoot()
+				.getAttribute(BugzillaRestTaskSchema.getDefault().REMOVE_CC.getKey());
+		TaskAttribute addSelfCC = taskData.getRoot()
+				.getAttribute(BugzillaRestTaskSchema.getDefault().ADD_SELF_CC.getKey());
+		if (Boolean.valueOf(addSelfCC.getValue())) {
+			String userName = addSelfCC.getMetaData().getValue("UserName"); //$NON-NLS-1$
+			if (userName != null) {
+				if (removeCC.getValues().contains(userName)) {
+					removeCC.removeValue(userName);
+				} else if (!cc.getValues().contains(userName)) {
+					List<String> addCCList = Arrays.asList(addCC.getValue().split("\\s*,\\s*")); //$NON-NLS-1$
+					if (!addCCList.contains(userName)) {
+						addCC.setValue(userName + (addCCList.size() > 0 && !addCCList.get(0).equals("") ? ", " : "") //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
+								+ addCC.getValue());
+					}
+				}
+			}
+		}
+		if (addCC.getValues().size() > 0 || removeCC.getValues().size() > 0) {
+			Set<String> setOld = new HashSet<String>(removeCC.getValues());
+			HashSet<String> setNew = new HashSet<String>(Arrays.asList(addCC.getValue().split("\\s*,\\s*"))); //$NON-NLS-1$
+			BugzillaRestGsonUtil.getDefault().buildAddRemoveHash(out, "cc", setOld, setNew); //$NON-NLS-1$
+		}
+		BugzillaRestGsonUtil.buildFlags(out, taskAttributes.getTaskAttributes(), taskData.getRoot());
+	}
+
 }
\ No newline at end of file