1
0
Fork 0

implemented transitions

master
Bob Carroll 2013-05-21 21:21:36 -07:00
parent a02ac414c1
commit 4521a149ae
3 changed files with 226 additions and 9 deletions

View File

@ -301,15 +301,10 @@ public final class Field {
public static Meta getFieldMetadata(String name, JSONObject editmeta)
throws JiraException {
if (editmeta.isNullObject() || !editmeta.containsKey("fields"))
throw new JiraException("Edit metadata is malformed");
Map fields = (Map)editmeta.get("fields");
if (!fields.containsKey(name))
if (editmeta.isNullObject() || !editmeta.containsKey(name))
throw new JiraException("Field '" + name + "' does not exist or read-only");
Map f = (Map)fields.get(name);
Map f = (Map)editmeta.get(name);
Meta m = new Meta();
m.required = Field.getBoolean(f.get("required"));
@ -415,10 +410,29 @@ public final class Field {
return json.toString();
} else if (m.type.equals("string")) {
if (value instanceof Map)
return toJsonMap((Map)value);
return value.toString();
}
throw new UnsupportedOperationException(m.type + " is not a supported field type");
}
/**
* Converts the given map to a JSON object.
*
* @param map Map to be converted
*
* @return a JSON-encoded map
*/
public static Object toJsonMap(Map map) {
JSONObject json = new JSONObject();
for (Object k : map.keySet())
json.put(k, map.get(k));
return json.toString();
}
}

View File

@ -19,11 +19,13 @@
package net.rcarz.jiraclient;
import java.net.URI;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import net.sf.json.JSONArray;
import net.sf.json.JSONObject;
/**
@ -83,6 +85,108 @@ public final class Issue extends Resource {
}
}
/**
* Used to chain fields to an transition action.
*/
public final class FluentTransition {
Map<String, Object> fields = new HashMap<String, Object>();
JSONArray transitions = null;
private FluentTransition(JSONArray transitions) {
this.transitions = transitions;
}
private JSONObject getTransition(String id, boolean name) throws JiraException {
JSONObject result = null;
for (Object item : transitions) {
if (!(item instanceof JSONObject) || !((JSONObject)item).containsKey("id"))
throw new JiraException("Transition metadata is malformed");
JSONObject t = (JSONObject)item;
if ((!name && Field.getString(t.get("id")).equals(id)) ||
(name && Field.getString(t.get("name")).equals(id))) {
result = t;
break;
}
}
if (result == null)
throw new JiraException("Transition was not found in metadata");
return result;
}
private void realExecute(JSONObject trans) throws JiraException {
if (trans.isNullObject() || !trans.containsKey("fields") ||
!(trans.get("fields") instanceof JSONObject))
throw new JiraException("Transition metadata is missing fields");
JSONObject editmeta = (JSONObject)trans.get("fields");
JSONObject fieldmap = new JSONObject();
for (Map.Entry<String, Object> ent : fields.entrySet()) {
Object newval = Field.toJson(ent.getKey(), ent.getValue(), editmeta);
fieldmap.put(ent.getKey(), newval);
}
JSONObject req = new JSONObject();
if (fieldmap.size() > 0)
req.put("fields", fieldmap);
JSONObject t = new JSONObject();
t.put("id", Field.getString(trans.get("id")));
req.put("transition", t);
try {
restclient.post(getRestUri(key) + "/transitions", req);
} catch (Exception ex) {
throw new JiraException("Failed to transition issue " + key, ex);
}
}
/**
* Executes the transition action.
*
* @param id Internal transition ID
*
* @throws JiraException when the transition fails
*/
public void execute(int id) throws JiraException {
realExecute(getTransition(Integer.toString(id), false));
}
/**
* Executes the transition action.
*
* @param name Transition name
*
* @throws JiraException when the transition fails
*/
public void execute(String name) throws JiraException {
realExecute(getTransition(name, true));
}
/**
* Appends a field to the transition action.
*
* @param name Name of the field
* @param value New field value
*
* @return the current fluent transition instance
*/
public FluentTransition field(String name, Object value) {
fields.put(name, value);
return this;
}
}
private String key = null;
/* system fields */
@ -154,7 +258,32 @@ public final class Issue extends Resource {
throw new JiraException("Failed to retrieve issue metadata", ex);
}
return result;
if (result.isNullObject() || !result.containsKey("fields") ||
!(result.get("fields") instanceof JSONObject))
throw new JiraException("Edit metadata is malformed");
return (JSONObject)result.get("fields");
}
private JSONArray getTransitions() throws JiraException {
JSONObject result = null;
try {
URI transuri = restclient.buildURI(
getRestUri(key) + "/transitions",
new HashMap<String, String>() {{
put("expand", "transitions.fields");
}});
result = restclient.get(transuri);
} catch (Exception ex) {
throw new JiraException("Failed to retrieve transitions", ex);
}
if (result.isNullObject() || !result.containsKey("transitions") ||
!(result.get("transitions") instanceof JSONArray))
throw new JiraException("Transition metadata is missing from results");
return (JSONArray)result.get("transitions");
}
/**
@ -181,6 +310,17 @@ public final class Issue extends Resource {
return new Issue(restclient, result);
}
/**
* Begins a transition field chain.
*
* @return a fluent transition instance
*
* @throws JiraException when the client fails to retrieve issue metadata
*/
public FluentTransition transition() throws JiraException {
return new FluentTransition(getTransitions());
}
/**
* Begins an update field chain.
*

View File

@ -27,6 +27,7 @@ import java.io.UnsupportedEncodingException;
import java.lang.StringBuilder;
import java.net.URI;
import java.net.URISyntaxException;
import java.util.Map;
import org.apache.http.HttpEntity;
import org.apache.http.HttpResponse;
@ -34,6 +35,7 @@ import org.apache.http.StatusLine;
import org.apache.http.client.HttpClient;
import org.apache.http.client.methods.HttpEntityEnclosingRequestBase;
import org.apache.http.client.methods.HttpGet;
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.client.utils.URIBuilder;
@ -60,10 +62,38 @@ public class RestClient {
this.uri = uri;
}
private URI buildURI(String path) throws URISyntaxException {
/**
* Build a URI from a path.
*
* @param path Path to append to the base URI
*
* @return the full URI
*
* @throws URISyntaxException when the path is invalid
*/
public URI buildURI(String path) throws URISyntaxException {
return buildURI(path, null);
}
/**
* Build a URI from a path and query parmeters.
*
* @param path Path to append to the base URI
* @param params Map of key value pairs
*
* @return the full URI
*
* @throws URISyntaxException when the path is invalid
*/
public URI buildURI(String path, Map<String, String> params) throws URISyntaxException {
URIBuilder ub = new URIBuilder(uri);
ub.setPath(ub.getPath() + path);
if (params != null) {
for (Map.Entry<String, String> ent : params.entrySet())
ub.addParameter(ent.getKey(), ent.getValue());
}
return ub.build();
}
@ -137,6 +167,39 @@ public class RestClient {
return get(buildURI(path));
}
/**
* Executes an HTTP POST with the given URI and payload.
*
* @param uri Full URI of the remote endpoint
* @param payload JSON-encoded data to send to the remote service
*
* @return JSON-encoded result or null when there's no content returned
*
* @throws RestException when an HTTP-level error occurs
* @throws IOException when an error reading the response occurs
*/
public JSONObject post(URI uri, JSONObject payload) throws RestException, IOException {
return request(new HttpPost(uri), payload);
}
/**
* Executes an HTTP POST with the given path and payload.
*
* @param path Path to be appended to the URI supplied in the construtor
* @param payload JSON-encoded data to send to the remote service
*
* @return JSON-encoded result or null when there's no content returned
*
* @throws RestException when an HTTP-level error occurs
* @throws IOException when an error reading the response occurs
* @throws URISyntaxException when an error occurred appending the path to the URI
*/
public JSONObject post(String path, JSONObject payload)
throws RestException, IOException, URISyntaxException {
return post(buildURI(path), payload);
}
/**
* Executes an HTTP PUT with the given URI and payload.
*