View Javadoc

1   /*
2    * Copyright (C) 2012-2013 Atlassian
3    *
4    * Licensed under the Apache License, Version 2.0 (the "License");
5    * you may not use this file except in compliance with the License.
6    * You may obtain a copy of the License at
7    *
8    *     http://www.apache.org/licenses/LICENSE-2.0
9    *
10   * Unless required by applicable law or agreed to in writing, software
11   * distributed under the License is distributed on an "AS IS" BASIS,
12   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13   * See the License for the specific language governing permissions and
14   * limitations under the License.
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   * JSON parser that produces Map of String => CimFieldInfo
41   *
42   * @since v1.0
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              // fixes for JRADEV-12999
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             // fallback - just return collection of JSONObjects
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 }