View Javadoc

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