All Downloads are FREE. Search and download functionalities are using the official Maven repository.

net.rcarz.jiraclient.Field Maven / Gradle / Ivy

There is a newer version: 0.5
Show newest version
/**
 * jira-client - a simple JIRA REST client
 * Copyright (c) 2013 Bob Carroll ([email protected])
 * 
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation; either version 2 of the License, or
 * (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program; if not, write to the Free Software
 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
 */

package net.rcarz.jiraclient;

import java.lang.Iterable;
import java.lang.UnsupportedOperationException;
import java.text.ParsePosition;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
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;

/**
 * Utility functions for translating between JSON and fields.
 */
public final class Field {

    /**
     * Field metadata structure.
     */
    public static final class Meta {
        public boolean required;
        public String type;
        public String items;
        public String name;
        public String system;
        public String custom;
        public int customId;
    }

    public static final String ASSIGNEE = "assignee";
    public static final String ATTACHMENT = "attachment";
    public static final String COMMENT = "comment";
    public static final String COMPONENTS = "components";
    public static final String DESCRIPTION = "description";
    public static final String DUE_DATE = "duedate";
    public static final String FIX_VERSIONS = "fixVersions";
    public static final String ISSUE_LINKS = "issuelinks";
    public static final String ISSUE_TYPE = "issuetype";
    public static final String LABELS = "labels";
    public static final String PRIORITY = "priority";
    public static final String PROJECT = "project";
    public static final String REPORTER = "reporter";
    public static final String RESOLUTION = "resolution";
    public static final String RESOLUTION_DATE = "resolutiondate";
    public static final String STATUS = "status";
    public static final String SUBTASKS = "subtasks";
    public static final String SUMMARY = "summary";
    public static final String TIME_TRACKING = "timetracking";
    public static final String VERSIONS = "versions";
    public static final String VOTES = "votes";
    public static final String WATCHES = "watches";
    public static final String WORKLOG = "worklog";

    public static final String DATE_FORMAT = "yyyy-MM-dd";

    private Field() { }

    /**
     * Gets a boolean value from the given object.
     *
     * @param b a Boolean instance
     *
     * @return a boolean primitive or false if b isn't a Boolean instance
     */
    public static boolean getBoolean(Object b) {
        boolean result = false;

        if (b instanceof Boolean)
            result = ((Boolean)b).booleanValue();

        return result;
    }

    /**
     * Gets a list of comments from the given object.
     *
     * @param c a JSONObject instance
     * @param restclient REST client instance
     *
     * @return a list of comments found in c
     */
    public static List getComments(Object c, RestClient restclient) {
        List results = new ArrayList();

        if (c instanceof JSONObject && !((JSONObject)c).isNullObject())
            results = getResourceArray(Comment.class, ((Map)c).get("comments"), restclient);

        return results;
    }

    /**
     * Gets a list of work logs from the given object.
     *
     * @param c a JSONObject instance
     * @param restclient REST client instance
     *
     * @return a list of work logs found in c
     */
    public static List getWorkLogs(Object c, RestClient restclient) {
        List results = new ArrayList();

        if (c instanceof JSONObject && !((JSONObject)c).isNullObject())
            results = getResourceArray(WorkLog.class, ((Map)c).get("worklogs"), restclient);

        return results;
    }

    /**
     * Gets a date from the given object.
     *
     * @param d a string representation of a date
     *
     * @return a Date instance or null if d isn't a string
     */
    public static Date getDate(Object d) {
        Date result = null;

        if (d instanceof String) {
            SimpleDateFormat df = new SimpleDateFormat(DATE_FORMAT);
            result = df.parse((String)d, new ParsePosition(0));
        }

        return result;
    }

    /**
     * Gets an integer from the given object.
     *
     * @param i an Integer instance
     *
     * @return an integer primitive or 0 if i isn't an Integer instance
     */
    public static int getInteger(Object i) {
        int result = 0;

        if (i instanceof Integer)
            result = ((Integer)i).intValue();

        return result;
    }

    /**
     * Gets a generic map from the given object.
     *
     * @param keytype Map key data type
     * @param valtype Map value data type
     * @param m a JSONObject instance
     *
     * @return a Map instance with all entries found in m
     */
    public static  Map getMap(
        Class keytype, Class valtype, Object m) {

        Map result = new HashMap();

        if (m instanceof JSONObject && !((JSONObject)m).isNullObject()) {
            for (Object k : ((Map)m).keySet()) {
                Object v = ((Map)m).get(k);

                if (k.getClass() == keytype && v.getClass() == valtype)
                    result.put((TK)k, (TV)v);
            }
        }

        return result;
    }

    /**
     * Gets a JIRA resource from the given object.
     *
     * @param type Resource data type
     * @param r a JSONObject instance
     * @param restclient REST client instance
     *
     * @return a Resource instance or null if r isn't a JSONObject instance
     */
    public static  T getResource(
        Class type, Object r, RestClient restclient) {

        T result = null;

        if (r instanceof JSONObject && !((JSONObject)r).isNullObject()) {
            if (type == Attachment.class)
                result = (T)new Attachment(restclient, (JSONObject)r);
            else if (type == Comment.class)
                result = (T)new Comment(restclient, (JSONObject)r);
            else if (type == Component.class)
                result = (T)new Component(restclient, (JSONObject)r);
            else if (type == CustomFieldOption.class)
                result = (T)new CustomFieldOption(restclient, (JSONObject)r);
            else if (type == Issue.class)
                result = (T)new Issue(restclient, (JSONObject)r);
            else if (type == IssueLink.class)
                result = (T)new IssueLink(restclient, (JSONObject)r);
            else if (type == IssueType.class)
                result = (T)new IssueType(restclient, (JSONObject)r);
            else if (type == LinkType.class)
                result = (T)new LinkType(restclient, (JSONObject)r);
            else if (type == Priority.class)
                result = (T)new Priority(restclient, (JSONObject)r);
            else if (type == Project.class)
                result = (T)new Project(restclient, (JSONObject)r);
            else if (type == Resolution.class)
                result = (T)new Resolution(restclient, (JSONObject)r);
            else if (type == Status.class)
                result = (T)new Status(restclient, (JSONObject)r);
            else if (type == User.class)
                result = (T)new User(restclient, (JSONObject)r);
            else if (type == Version.class)
                result = (T)new Version(restclient, (JSONObject)r);
            else if (type == Votes.class)
                result = (T)new Votes(restclient, (JSONObject)r);
            else if (type == Watches.class)
                result = (T)new Watches(restclient, (JSONObject)r);
            else if (type == WorkLog.class)
                result = (T)new WorkLog(restclient, (JSONObject)r);
        }

        return result;
    }

    /**
     * Gets a string from the given object.
     *
     * @param s a String instance
     *
     * @return a String or null if s isn't a String instance
     */
    public static String getString(Object s) {
        String result = null;

        if (s instanceof String)
            result = (String)s;

        return result;
    }

    /**
     * Gets a list of strings from the given object.
     *
     * @param sa a JSONArray instance
     *
     * @return a list of strings found in sa
     */
    public static List getStringArray(Object sa) {
        List results = new ArrayList();

        if (sa instanceof JSONArray) {
            for (Object s : (JSONArray)sa) {
                if (s instanceof String)
                    results.add((String)s);
            }
        }

        return results;
    }

    /**
     * Gets a list of JIRA resources from the given object.
     *
     * @param type Resource data type
     * @param ra a JSONArray instance
     * @param restclient REST client instance
     *
     * @return a list of Resources found in ra
     */
    public static  List getResourceArray(
        Class type, Object ra, RestClient restclient) {

        List results = new ArrayList();

        if (ra instanceof JSONArray) {
            for (Object v : (JSONArray)ra)
                if (type == Attachment.class)
                    results.add((T)new Attachment(restclient, (JSONObject)v));
                else if (type == Comment.class)
                    results.add((T)new Comment(restclient, (JSONObject)v));
                else if (type == Component.class)
                    results.add((T)new Component(restclient, (JSONObject)v));
                else if (type == CustomFieldOption.class)
                    results.add((T)new CustomFieldOption(restclient, (JSONObject)v));
                else if (type == Issue.class)
                    results.add((T)new Issue(restclient, (JSONObject)v));
                else if (type == IssueLink.class)
                    results.add((T)new IssueLink(restclient, (JSONObject)v));
                else if (type == IssueType.class)
                    results.add((T)new IssueType(restclient, (JSONObject)v));
                else if (type == LinkType.class)
                    results.add((T)new LinkType(restclient, (JSONObject)v));
                else if (type == Priority.class)
                    results.add((T)new Priority(restclient, (JSONObject)v));
                else if (type == Project.class)
                    results.add((T)new Project(restclient, (JSONObject)v));
                else if (type == Resolution.class)
                    results.add((T)new Resolution(restclient, (JSONObject)v));
                else if (type == Status.class)
                    results.add((T)new Status(restclient, (JSONObject)v));
                else if (type == User.class)
                    results.add((T)new User(restclient, (JSONObject)v));
                else if (type == Version.class)
                    results.add((T)new Version(restclient, (JSONObject)v));
                else if (type == Votes.class)
                    results.add((T)new Votes(restclient, (JSONObject)v));
                else if (type == Watches.class)
                    results.add((T)new Watches(restclient, (JSONObject)v));
                else if (type == WorkLog.class)
                    results.add((T)new WorkLog(restclient, (JSONObject)v));
        }

        return results;
    }

    /**
     * Gets a time tracking object from the given object.
     *
     * @param tt a JSONObject instance
     *
     * @return a TimeTracking instance or null if tt isn't a JSONObject instance
     */
    public static TimeTracking getTimeTracking(Object tt) {
        TimeTracking result = null;

        if (tt instanceof JSONObject && !((JSONObject)tt).isNullObject())
            result = new TimeTracking((JSONObject)tt);

        return result;
    }

    /**
     * Extracts field metadata from an editmeta JSON object.
     *
     * @param name Field name
     * @param editmeta Edit metadata JSON object
     *
     * @return a Meta instance with field metadata
     *
     * @throws JiraException when the field is missing or metadata is bad
     */
    public static Meta getFieldMetadata(String name, JSONObject editmeta)
        throws JiraException {

        if (editmeta.isNullObject() || !editmeta.containsKey(name))
            throw new JiraException("Field '" + name + "' does not exist or read-only");

        Map f = (Map)editmeta.get(name);
        Meta m = new Meta();

        m.required = Field.getBoolean(f.get("required"));
        m.name = Field.getString(f.get("name"));

        if (!f.containsKey("schema"))
            throw new JiraException("Field '" + name + "' is missing schema metadata");

        Map schema = (Map)f.get("schema");

        m.type = Field.getString(schema.get("type"));
        m.items = Field.getString(schema.get("items"));
        m.system = Field.getString(schema.get("system"));
        m.custom = Field.getString(schema.get("custom"));
        m.customId = Field.getInteger(schema.get("customId"));

        return m;
    }

    /**
     * Converts the given value to a date.
     *
     * @param value New field value
     *
     * @return a Date instance or null
     */
    public static Date toDate(Object value) {
        if (value instanceof Date || value == null)
            return (Date)value;

        SimpleDateFormat df = new SimpleDateFormat(DATE_FORMAT);
        return df.parse(value.toString(), new ParsePosition(0));
    }

    /**
     * Converts an iterable type to a JSON array.
     *
     * @param iter Iterable type containing field values
     * @param type Name of the item type
     *
     * @return a JSON-encoded array of items
     */
    public static JSONArray toArray(Iterable iter, String type) throws JiraException {
        JSONArray result = new JSONArray();

        if (type == null)
            throw new JiraException("Array field metadata is missing item type");

        for (Object val : iter) {
            if (type.equals("component") || type.equals("group") ||
                type.equals("user") || type.equals("version")) {

                JSONObject json = new JSONObject();
                json.put("name", val.toString());

                result.add(json.toString());
            } else if (type.equals("string"))
                result.add(val.toString());
        }

        return result;
    }

    /**
     * Converts the given value to a JSON object.
     *
     * @param name Field name
     * @param value New field value
     * @param editmeta Edit metadata JSON object
     *
     * @return a JSON-encoded field value
     *
     * @throws JiraException when a value is bad or field has invalid metadata
     * @throws UnsupportedOperationException when a field type isn't supported
     */
    public static Object toJson(String name, Object value, JSONObject editmeta)
        throws JiraException, UnsupportedOperationException {

        if (value == null)
            return null;

        Meta m = getFieldMetadata(name, editmeta);

        if (m.type == null)
            throw new JiraException("Field metadata is missing a type");

        if (m.type.equals("array")) {
            if (!(value instanceof Iterable))
                throw new JiraException("Field expects an Iterable value");

            return toArray((Iterable)value, m.items);
        } else if (m.type.equals("date")) {
            Date d = toDate(value);

            if (d == null)
                throw new JiraException("Field expects a date value or format is invalid");

            SimpleDateFormat df = new SimpleDateFormat(DATE_FORMAT);
            return df.format(d);
        } else if (m.type.equals("issuetype") || m.type.equals("priority") ||
                m.type.equals("user") || m.type.equals("resolution")) {
            JSONObject json = new JSONObject();
            json.put("name", value.toString());

            return json.toString();
        } else if (m.type.equals("project") || m.type.equals("issuelink")) {
            JSONObject json = new JSONObject();
            json.put("key", value.toString());

            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();
    }
}





© 2015 - 2024 Weber Informatics LLC | Privacy Policy