@Nullable private <T> Collection<T> parseOptionalArray( boolean shouldUseNestedValueJson, JSONObject json, JsonWeakParser<T> jsonParser, String... path) throws JSONException { if (shouldUseNestedValueJson) { final JSONObject js = JsonParseUtil.getNestedOptionalObject(json, path); if (js == null) { return null; } return parseArray(js, jsonParser, VALUE_ATTR); } else { final JSONArray jsonArray = JsonParseUtil.getNestedOptionalArray(json, path); if (jsonArray == null) { return null; } final Collection<T> res = new ArrayList<T>(jsonArray.length()); for (int i = 0; i < jsonArray.length(); i++) { res.add(jsonParser.parse(jsonArray.get(i))); } return res; } }
@Nullable private <T> T getOptionalField( boolean shouldUseNestedValue, JSONObject s, final String fieldId, JsonParser<T> jsonParser) throws JSONException { final JSONObject fieldJson = JsonParseUtil.getNestedOptionalObject(s, FIELDS, fieldId); // for fields like assignee (when unassigned) value attribute may be missing completely if (fieldJson != null) { if (shouldUseNestedValue) { final JSONObject valueJsonObject = fieldJson.optJSONObject(VALUE_ATTR); if (valueJsonObject != null) { return jsonParser.parse(valueJsonObject); } } else { return jsonParser.parse(fieldJson); } } return null; }
@Override public Issue parse(JSONObject s) throws JSONException { final Iterable<String> expandos = parseExpandos(s); final boolean isJira5x0OrNewer = Iterables.contains(expandos, SCHEMA_SECTION) || this.types != null; final boolean shouldUseNestedValueAttribute = !isJira5x0OrNewer; final Collection<Comment> comments; if (isJira5x0OrNewer) { final JSONObject commentsJson = s.getJSONObject(FIELDS).getJSONObject(COMMENT_FIELD.id); comments = parseArray( commentsJson, new JsonWeakParserForJsonObject<Comment>(commentJsonParser), "comments"); } else { final Collection<Comment> commentsTmp = parseOptionalArray( shouldUseNestedValueAttribute, s, new JsonWeakParserForJsonObject<Comment>(commentJsonParser), FIELDS, COMMENT_FIELD.id); comments = commentsTmp != null ? commentsTmp : Lists.<Comment>newArrayList(); } final String summary = getFieldStringValue(s, SUMMARY_FIELD.id); final String description = getOptionalFieldStringUnisex(shouldUseNestedValueAttribute, s, DESCRIPTION_FIELD.id); final Collection<Attachment> attachments = parseOptionalArray( shouldUseNestedValueAttribute, s, new JsonWeakParserForJsonObject<Attachment>(attachmentJsonParser), FIELDS, ATTACHMENT_FIELD.id); final Collection<Field> fields = isJira5x0OrNewer ? parseFieldsJira5x0(s) : parseFields(s.getJSONObject(FIELDS)); final BasicIssueType issueType = issueTypeJsonParser.parse(getFieldUnisex(s, ISSUE_TYPE_FIELD.id)); final DateTime creationDate = JsonParseUtil.parseDateTime(getFieldStringUnisex(s, CREATED_FIELD.id)); final DateTime updateDate = JsonParseUtil.parseDateTime(getFieldStringUnisex(s, UPDATED_FIELD.id)); final String dueDateString = getOptionalFieldStringUnisex(shouldUseNestedValueAttribute, s, DUE_DATE_FIELD.id); final DateTime dueDate = dueDateString == null ? null : JsonParseUtil.parseDateTimeOrDate(dueDateString); final BasicPriority priority = getOptionalField(shouldUseNestedValueAttribute, s, PRIORITY_FIELD.id, priorityJsonParser); final BasicResolution resolution = getOptionalField( shouldUseNestedValueAttribute, s, RESOLUTION_FIELD.id, resolutionJsonParser); final BasicUser assignee = getOptionalField(shouldUseNestedValueAttribute, s, ASSIGNEE_FIELD.id, userJsonParser); final BasicUser reporter = getOptionalField(shouldUseNestedValueAttribute, s, REPORTER_FIELD.id, userJsonParser); final String transitionsUri = getOptionalFieldStringUnisex(shouldUseNestedValueAttribute, s, TRANSITIONS_FIELD.id); final BasicProject project = projectJsonParser.parse(getFieldUnisex(s, PROJECT_FIELD.id)); final Collection<IssueLink> issueLinks; if (isJira5x0OrNewer) { issueLinks = parseOptionalArray( shouldUseNestedValueAttribute, s, new JsonWeakParserForJsonObject<IssueLink>(issueLinkJsonParserV5), FIELDS, LINKS_FIELD.id); } else { issueLinks = parseOptionalArray( shouldUseNestedValueAttribute, s, new JsonWeakParserForJsonObject<IssueLink>(issueLinkJsonParser), FIELDS, LINKS_PRE_5_0_FIELD.id); } Collection<Subtask> subtasks = null; if (isJira5x0OrNewer) { subtasks = parseOptionalArray( shouldUseNestedValueAttribute, s, new JsonWeakParserForJsonObject<Subtask>(subtaskJsonParser), FIELDS, SUBTASKS_FIELD.id); } final BasicVotes votes = getOptionalField(shouldUseNestedValueAttribute, s, VOTES_FIELD.id, votesJsonParser); final BasicStatus status = statusJsonParser.parse(getFieldUnisex(s, STATUS_FIELD.id)); final Collection<Version> fixVersions = parseOptionalArray( shouldUseNestedValueAttribute, s, new JsonWeakParserForJsonObject<Version>(versionJsonParser), FIELDS, FIX_VERSIONS_FIELD.id); final Collection<Version> affectedVersions = parseOptionalArray( shouldUseNestedValueAttribute, s, new JsonWeakParserForJsonObject<Version>(versionJsonParser), FIELDS, AFFECTS_VERSIONS_FIELD.id); final Collection<BasicComponent> components = parseOptionalArray( shouldUseNestedValueAttribute, s, new JsonWeakParserForJsonObject<BasicComponent>(basicComponentJsonParser), FIELDS, COMPONENTS_FIELD.id); final Collection<Worklog> worklogs; if (isJira5x0OrNewer) { if (JsonParseUtil.getNestedOptionalObject(s, FIELDS, WORKLOG_FIELD.id) != null) { worklogs = parseOptionalArray( shouldUseNestedValueAttribute, s, new JsonWeakParserForJsonObject<Worklog>( new WorklogJsonParserV5(JsonParseUtil.getSelfUri(s))), FIELDS, WORKLOG_FIELD.id, WORKLOGS_FIELD.id); } else { worklogs = Collections.emptyList(); } } else { worklogs = parseOptionalArray( shouldUseNestedValueAttribute, s, new JsonWeakParserForJsonObject<Worklog>(worklogJsonParser), FIELDS, WORKLOG_FIELD.id); } final BasicWatchers watchers = getOptionalField( shouldUseNestedValueAttribute, s, isJira5x0OrNewer ? WATCHER_FIELD.id : WATCHER_PRE_5_0_FIELD.id, watchersJsonParser); final TimeTracking timeTracking = getOptionalField( shouldUseNestedValueAttribute, s, TIMETRACKING_FIELD.id, isJira5x0OrNewer ? new TimeTrackingJsonParserV5() : new TimeTrackingJsonParser()); final Set<String> labels = Sets.newHashSet( parseOptionalArrayNotNullable( shouldUseNestedValueAttribute, s, jsonWeakParserForString, FIELDS, LABELS_FIELD.id)); final Collection<ChangelogGroup> changelog = parseOptionalArray( false, s, new JsonWeakParserForJsonObject<ChangelogGroup>(changelogJsonParser), "changelog", "histories"); return new Issue( summary, JsonParseUtil.getSelfUri(s), s.getString("key"), project, issueType, status, description, priority, resolution, attachments, reporter, assignee, creationDate, updateDate, dueDate, affectedVersions, fixVersions, components, timeTracking, fields, comments, transitionsUri != null ? JsonParseUtil.parseURI(transitionsUri) : null, issueLinks, votes, worklogs, watchers, expandos, subtasks, changelog, labels); }