1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17 package com.atlassian.jira.rest.client.internal.json;
18
19 import com.atlassian.jira.rest.client.api.domain.CimFieldInfo;
20 import com.atlassian.jira.rest.client.api.domain.FieldSchema;
21 import com.atlassian.jira.rest.client.api.domain.StandardOperation;
22 import com.google.common.collect.ImmutableSet;
23 import com.google.common.collect.Lists;
24 import com.google.common.collect.Maps;
25 import com.google.common.collect.Sets;
26 import org.codehaus.jettison.json.JSONArray;
27 import org.codehaus.jettison.json.JSONException;
28 import org.codehaus.jettison.json.JSONObject;
29
30 import javax.annotation.Nullable;
31 import java.net.URI;
32 import java.util.Collections;
33 import java.util.HashMap;
34 import java.util.Iterator;
35 import java.util.List;
36 import java.util.Map;
37 import java.util.Set;
38
39
40
41
42
43
44 public class CimFieldsInfoMapJsonParser implements JsonObjectParser<Map<String, CimFieldInfo>> {
45
46 private final FieldSchemaJsonParser fieldSchemaJsonParser = new FieldSchemaJsonParser();
47
48 protected final Map<String, JsonObjectParser> registeredAllowedValueParsers = new HashMap<String, JsonObjectParser>() {{
49 put("project", new BasicProjectJsonParser());
50 put("version", new VersionJsonParser());
51 put("issuetype", new IssueTypeJsonParser());
52 put("priority", new BasicPriorityJsonParser());
53 put("customFieldOption", new CustomFieldOptionJsonParser());
54 put("component", new BasicComponentJsonParser());
55 put("resolution", new ResolutionJsonParser());
56 put("securitylevel", new SecurityLevelJsonParser());
57 }};
58
59 @Override
60 public Map<String, CimFieldInfo> parse(JSONObject json) throws JSONException {
61 final Map<String, CimFieldInfo> res = Maps.newHashMapWithExpectedSize(json.length());
62 final Iterator keysIterator = json.keys();
63 while (keysIterator.hasNext()) {
64 final String id = (String) keysIterator.next();
65 res.put(id, parseIssueFieldInfo(json.getJSONObject(id), id));
66 }
67 return res;
68 }
69
70 private CimFieldInfo parseIssueFieldInfo(JSONObject json, String id) throws JSONException {
71 final boolean required = json.getBoolean("required");
72 final String name = JsonParseUtil.getOptionalString(json, "name");
73 final FieldSchema schema = fieldSchemaJsonParser.parse(json.getJSONObject("schema"));
74 final Set<StandardOperation> operations = parseOperations(json.getJSONArray("operations"));
75 final Iterable<Object> allowedValues = parseAllowedValues(json.optJSONArray("allowedValues"), schema);
76 final URI autoCompleteUri = JsonParseUtil.parseOptionalURI(json, "autoCompleteUrl");
77
78 return new CimFieldInfo(id, required, name, schema, operations, allowedValues, autoCompleteUri);
79 }
80
81 private Iterable<Object> parseAllowedValues(@Nullable JSONArray allowedValues, FieldSchema fieldSchema) throws JSONException {
82 if (allowedValues == null || allowedValues.equals(JSONObject.NULL)) {
83 return null;
84 }
85
86 if (allowedValues.length() == 0) {
87 return Collections.emptyList();
88 }
89
90 final JsonObjectParser<Object> allowedValuesJsonParser = getParserFor(fieldSchema);
91 if (allowedValuesJsonParser != null) {
92 JSONArray valuesToParse;
93
94 final boolean isProjectCF = "project".equals(fieldSchema.getType())
95 && "com.atlassian.jira.plugin.system.customfieldtypes:project".equals(fieldSchema.getCustom());
96 final boolean isVersionCF = "version".equals(fieldSchema.getType())
97 && "com.atlassian.jira.plugin.system.customfieldtypes:version".equals(fieldSchema.getCustom());
98 final boolean isMultiVersionCF = "array".equals(fieldSchema.getType())
99 && "version".equals(fieldSchema.getItems())
100 && "com.atlassian.jira.plugin.system.customfieldtypes:multiversion".equals(fieldSchema.getCustom());
101
102 if ((isProjectCF || isVersionCF || isMultiVersionCF) && allowedValues.get(0) instanceof JSONArray) {
103 valuesToParse = allowedValues.getJSONArray(0);
104 } else {
105 valuesToParse = allowedValues;
106 }
107 return GenericJsonArrayParser.create(allowedValuesJsonParser).parse(valuesToParse);
108 } else {
109
110 final int itemsLength = allowedValues.length();
111 final List<Object> res = Lists.newArrayListWithExpectedSize(itemsLength);
112 for (int i = 0; i < itemsLength; i++) {
113 res.add(allowedValues.get(i));
114 }
115 return res;
116 }
117 }
118
119 private Set<StandardOperation> parseOperations(JSONArray operations) throws JSONException {
120 final int operationsCount = operations.length();
121 final Set<StandardOperation> res = Sets.newHashSetWithExpectedSize(operationsCount);
122 for (int i = 0; i < operationsCount; i++) {
123 String opName = operations.getString(i);
124 StandardOperation op = StandardOperation.valueOf(opName.toUpperCase());
125 res.add(op);
126 }
127 return res;
128 }
129
130 @Nullable
131 private JsonObjectParser<Object> getParserFor(FieldSchema fieldSchema) throws JSONException {
132 final Set<String> customFieldsTypesWithFieldOption = ImmutableSet.of(
133 "com.atlassian.jira.plugin.system.customfieldtypes:multicheckboxes",
134 "com.atlassian.jira.plugin.system.customfieldtypes:radiobuttons",
135 "com.atlassian.jira.plugin.system.customfieldtypes:select",
136 "com.atlassian.jira.plugin.system.customfieldtypes:cascadingselect",
137 "com.atlassian.jira.plugin.system.customfieldtypes:multiselect"
138 );
139 String type = "array".equals(fieldSchema.getType()) ? fieldSchema.getItems() : fieldSchema.getType();
140 final String custom = fieldSchema.getCustom();
141 if (custom != null && customFieldsTypesWithFieldOption.contains(custom)) {
142 type = "customFieldOption";
143 }
144 @SuppressWarnings("unchecked") final JsonObjectParser<Object> jsonParser = registeredAllowedValueParsers.get(type);
145 if (jsonParser == null) {
146 return null;
147 } else {
148 return jsonParser;
149 }
150 }
151 }