• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 // Copyright 2014 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4 
5 package org.chromium.chrome.browser.omnibox;
6 
7 import android.util.Log;
8 
9 import org.json.JSONArray;
10 import org.json.JSONException;
11 import org.json.JSONObject;
12 
13 import java.util.ArrayList;
14 import java.util.List;
15 
16 /**
17  * Structured representation of the JSON payload of a suggestion with an answer.  An answer has
18  * exactly two image lines, so called because they are a combination of text and an optional
19  * image.  Each image line has 0 or more text fields, each of which is required to contain a string
20  * and an integer type.  The text fields are contained in a list and two optional named properties,
21  * referred to as "additional text" and "status text".  The image, if present, contains a single
22  * string, which may be a URL or base64-encoded image data.
23  *
24  * When represented in the UI, these elements should be styled and layed out according to the
25  * specification at http://goto.google.com/ais_api.
26  */
27 public class SuggestionAnswer {
28     private static final String TAG = "SuggestionAnswer";
29 
30     private ImageLine mFirstLine;
31     private ImageLine mSecondLine;
32 
33     private static final String ANSWERS_JSON_LINE = "l";
34     private static final String ANSWERS_JSON_IMAGE_LINE = "il";
35     private static final String ANSWERS_JSON_TEXT = "t";
36     private static final String ANSWERS_JSON_ADDITIONAL_TEXT = "at";
37     private static final String ANSWERS_JSON_STATUS_TEXT = "st";
38     private static final String ANSWERS_JSON_TEXT_TYPE = "tt";
39     private static final String ANSWERS_JSON_IMAGE = "i";
40     private static final String ANSWERS_JSON_IMAGE_DATA = "d";
41 
SuggestionAnswer()42     private SuggestionAnswer() {
43     }
44 
45     /**
46      * Parses the JSON representation of an answer and constructs a SuggestionAnswer from the
47      * contents.
48      *
49      * @param answerContents The JSON representation of an answer.
50      * @return A SuggestionAnswer with the answer contents or null if the contents are malformed or
51      *         missing required elements.
52      */
parseAnswerContents(String answerContents)53     public static SuggestionAnswer parseAnswerContents(String answerContents) {
54         SuggestionAnswer answer = new SuggestionAnswer();
55 
56         try {
57             JSONObject jsonAnswer = new JSONObject(answerContents);
58             JSONArray jsonLines = jsonAnswer.getJSONArray(ANSWERS_JSON_LINE);
59 
60             if (jsonLines.length() != 2) {
61                 Log.e(TAG, "Answer JSON doesn't contain exactly two lines: " + jsonAnswer);
62                 return null;
63             }
64 
65             answer.mFirstLine = new SuggestionAnswer.ImageLine(
66                     jsonLines.getJSONObject(0).getJSONObject(ANSWERS_JSON_IMAGE_LINE));
67             answer.mSecondLine = new SuggestionAnswer.ImageLine(
68                     jsonLines.getJSONObject(1).getJSONObject(ANSWERS_JSON_IMAGE_LINE));
69         } catch (JSONException e) {
70             Log.e(TAG, "Problem parsing answer JSON: " + e.getMessage());
71             return null;
72         }
73 
74         return answer;
75     }
76 
77     /**
78      * Returns the first of the two required image lines.
79      */
getFirstLine()80     public ImageLine getFirstLine() {
81         return mFirstLine;
82     }
83 
84     /**
85      * Returns the second of the two required image lines.
86      */
getSecondLine()87     public ImageLine getSecondLine() {
88         return mSecondLine;
89     }
90 
91     /**
92      * Represents a single line of an answer, containing any number of typed text fields and an
93      * optional image.
94      */
95     public static class ImageLine {
96         private final List<TextField> mTextFields;
97         private final TextField mAdditionalText;
98         private final TextField mStatusText;
99         private final String mImage;
100 
ImageLine(JSONObject jsonLine)101         ImageLine(JSONObject jsonLine) throws JSONException {
102             mTextFields = new ArrayList<TextField>();
103 
104             JSONArray textValues = jsonLine.getJSONArray(ANSWERS_JSON_TEXT);
105             for (int i = 0; i < textValues.length(); i++) {
106                 mTextFields.add(new TextField(textValues.getJSONObject(i)));
107             }
108 
109             mAdditionalText = jsonLine.has(ANSWERS_JSON_ADDITIONAL_TEXT) ?
110                     new TextField(jsonLine.getJSONObject(ANSWERS_JSON_ADDITIONAL_TEXT)) :
111                     null;
112 
113             mStatusText = jsonLine.has(ANSWERS_JSON_STATUS_TEXT) ?
114                     new TextField(jsonLine.getJSONObject(ANSWERS_JSON_STATUS_TEXT)) :
115                     null;
116 
117             mImage = jsonLine.has(ANSWERS_JSON_IMAGE) ?
118                     jsonLine.getJSONObject(ANSWERS_JSON_IMAGE).getString(ANSWERS_JSON_IMAGE_DATA) :
119                     null;
120         }
121 
122         /**
123          * Return an unnamed list of text fields.  These represent the main content of the line.
124          */
getTextFields()125         public List<TextField> getTextFields() {
126             return mTextFields;
127         }
128 
129         /**
130          * Returns true if the line contains an "additional text" field.
131          */
hasAdditionalText()132         public boolean hasAdditionalText() {
133             return mAdditionalText != null;
134         }
135 
136         /**
137          * Return the "additional text" field.
138          */
getAdditionalText()139         public TextField getAdditionalText() {
140             return mAdditionalText;
141         }
142 
143         /**
144          * Returns true if the line contains an "status text" field.
145          */
hasStatusText()146         public boolean hasStatusText() {
147             return mStatusText != null;
148         }
149 
150         /**
151          * Return the "status text" field.
152          */
getStatusText()153         public TextField getStatusText() {
154             return mStatusText;
155         }
156 
157         /**
158          * Returns true if the line contains an image.
159          */
hasImage()160         public boolean hasImage() {
161             return mImage != null;
162         }
163 
164         /**
165          * Return the optional image (URL or base64-encoded image data).
166          */
getImage()167         public String getImage() {
168             return mImage;
169         }
170     }
171 
172     /**
173      * Represents one text field of an answer, containing a integer type and a string.
174      */
175     public static class TextField {
176         private final int mType;
177         private final String mText;
178 
TextField(JSONObject jsonTextField)179         TextField(JSONObject jsonTextField) throws JSONException {
180             mType = jsonTextField.getInt(ANSWERS_JSON_TEXT_TYPE);
181             mText = jsonTextField.getString(ANSWERS_JSON_TEXT);
182         }
183 
getType()184         public int getType() {
185             return mType;
186         }
187 
getText()188         public String getText() {
189             return mText;
190         }
191     }
192 }