1package autotest.afe;
2
3import autotest.afe.create.CreateJobViewPresenter.JobCreateListener;
4import autotest.common.JSONArrayList;
5import autotest.common.JsonRpcCallback;
6import autotest.common.JsonRpcProxy;
7import autotest.common.SimpleCallback;
8import autotest.common.StaticDataRepository;
9import autotest.common.Utils;
10import autotest.common.table.JSONObjectSet;
11import autotest.common.ui.NotifyManager;
12import autotest.common.ui.SimplifiedList;
13
14import com.google.gwt.json.client.JSONArray;
15import com.google.gwt.json.client.JSONBoolean;
16import com.google.gwt.json.client.JSONObject;
17import com.google.gwt.json.client.JSONString;
18import com.google.gwt.json.client.JSONValue;
19import com.google.gwt.user.client.DOM;
20import com.google.gwt.user.client.Element;
21import com.google.gwt.user.client.ui.ListBox;
22
23import java.util.ArrayList;
24import java.util.Collection;
25import java.util.Iterator;
26import java.util.List;
27import java.util.Set;
28
29/**
30 * Utility methods.
31 */
32public class AfeUtils {
33    public static final String PLATFORM_SUFFIX = " (platform)";
34    public static final String ATOMIC_GROUP_SUFFIX = " (atomic group)";
35    public static final String REINSTALL_TEST_NAME = "autoupdate:repair";
36
37    public static final ClassFactory factory = new SiteClassFactory();
38
39    private static StaticDataRepository staticData = StaticDataRepository.getRepository();
40
41    public static String formatStatusCounts(JSONObject counts, String joinWith) {
42        StringBuilder result = new StringBuilder();
43        Set<String> statusSet = counts.keySet();
44        for (Iterator<String> i = statusSet.iterator(); i.hasNext();) {
45            String status = i.next();
46            int count = (int) counts.get(status).isNumber().doubleValue();
47            result.append(Integer.toString(count));
48            result.append(" ");
49            result.append(status);
50            if (i.hasNext()) {
51                result.append(joinWith);
52            }
53        }
54        return result.toString();
55    }
56
57    public static String[] getLabelStrings() {
58        return getFilteredLabelStrings(false, false);
59    }
60
61    protected static String[] getFilteredLabelStrings(boolean onlyPlatforms,
62                                                      boolean onlyNonPlatforms) {
63        assert !(onlyPlatforms && onlyNonPlatforms);
64        JSONArray labels = staticData.getData("labels").isArray();
65        List<String> result = new ArrayList<String>();
66        for (int i = 0; i < labels.size(); i++) {
67            JSONObject label = labels.get(i).isObject();
68            String name = label.get("name").isString().stringValue();
69            boolean labelIsPlatform = label.get("platform").isBoolean().booleanValue();
70            JSONObject atomicGroup = label.get("atomic_group").isObject();
71            if (atomicGroup != null) {
72                name += ATOMIC_GROUP_SUFFIX;
73            }
74            if (onlyPlatforms && labelIsPlatform ||
75                onlyNonPlatforms && !labelIsPlatform) {
76                    result.add(name);
77            } else if (!onlyPlatforms && !onlyNonPlatforms) {
78                if (labelIsPlatform) {
79                    name += PLATFORM_SUFFIX;
80                }
81                result.add(name);
82            }
83        }
84        return result.toArray(new String[result.size()]);
85    }
86
87    public static String[] getPlatformStrings() {
88        return getFilteredLabelStrings(true, false);
89    }
90
91    public static String[] getNonPlatformLabelStrings() {
92        return getFilteredLabelStrings(false, true);
93    }
94
95    public static String decodeLabelName(String labelName) {
96        String name = labelName;
97        if (name.endsWith(PLATFORM_SUFFIX)) {
98            int nameLength = name.length() - PLATFORM_SUFFIX.length();
99            name = name.substring(0, nameLength);
100        }
101        if (name.endsWith(ATOMIC_GROUP_SUFFIX)) {
102            int nameLength = name.length() - ATOMIC_GROUP_SUFFIX.length();
103            name = name.substring(0, nameLength);
104        }
105        return name;
106    }
107
108    public static JSONString getLockedText(JSONObject host) {
109        boolean locked = host.get("locked").isBoolean().booleanValue();
110        return new JSONString(locked ? "Yes" : "No");
111    }
112
113    public static void abortHostQueueEntries(Collection<JSONObject> entries,
114                                             final SimpleCallback onSuccess) {
115        if (entries.isEmpty()) {
116            NotifyManager.getInstance().showError("No entries selected to abort");
117            return;
118        }
119
120        final JSONArray asynchronousEntryIds = new JSONArray();
121        Set<JSONObject> synchronousEntries = new JSONObjectSet<JSONObject>();
122        for (JSONObject entry : entries) {
123            JSONObject job = entry.get("job").isObject();
124            int synchCount = (int) job.get("synch_count").isNumber().doubleValue();
125            boolean hasExecutionSubdir =
126                entry.containsKey("execution_subdir") &&
127                !Utils.jsonToString(entry.get("execution_subdir")).equals("");
128            if (synchCount > 1 && hasExecutionSubdir) {
129                synchronousEntries.add(entry);
130                continue;
131            }
132
133            JSONValue idListValue = entry.get("id_list");
134            if (idListValue != null) {
135                // metahost row
136                extendJsonArray(asynchronousEntryIds, idListValue.isArray());
137            } else {
138                JSONValue id = entry.get("id");
139                if (entry.containsKey("oid"))
140                    id = entry.get("oid");
141                asynchronousEntryIds.set(asynchronousEntryIds.size(), id);
142            }
143        }
144
145        SimpleCallback abortAsynchronousEntries = new SimpleCallback() {
146            public void doCallback(Object source) {
147                JSONObject params = new JSONObject();
148                params.put("id__in", asynchronousEntryIds);
149                AfeUtils.callAbort(params, onSuccess);
150            }
151        };
152
153        if (synchronousEntries.size() == 0) {
154            abortAsynchronousEntries.doCallback(null);
155        } else {
156            AbortSynchronousDialog dialog = new AbortSynchronousDialog(
157                abortAsynchronousEntries, synchronousEntries, asynchronousEntryIds.size() != 0);
158            dialog.center();
159        }
160    }
161
162    public static void abortSpecialTasks(final JSONArray specialTaskIds,
163                                         final SimpleCallback onSuccess) {
164        if (specialTaskIds.size() == 0) {
165            NotifyManager.getInstance().showError("No entries selected to abort");
166            return;
167        }
168
169        SimpleCallback abortSpecialTasks = new SimpleCallback() {
170            public void doCallback(Object source) {
171                JSONObject params = new JSONObject();
172                params.put("id__in", specialTaskIds);
173                AfeUtils.callAbortSpecialTasks(params, onSuccess);
174            }
175        };
176
177        abortSpecialTasks.doCallback(null);
178    }
179
180    private static void extendJsonArray(JSONArray array, JSONArray newValues) {
181        for (JSONValue value : new JSONArrayList<JSONValue>(newValues)) {
182            array.set(array.size(), value);
183        }
184    }
185
186    public static void callAbort(JSONObject params, final SimpleCallback onSuccess,
187                                 final boolean showMessage) {
188        JsonRpcProxy rpcProxy = JsonRpcProxy.getProxy();
189        rpcProxy.rpcCall("abort_host_queue_entries", params, new JsonRpcCallback() {
190            @Override
191            public void onSuccess(JSONValue result) {
192                if (showMessage) {
193                    NotifyManager.getInstance().showMessage("Jobs aborted");
194                }
195                if (onSuccess != null) {
196                    onSuccess.doCallback(null);
197                }
198            }
199        });
200    }
201
202    public static void callAbort(JSONObject params, final SimpleCallback onSuccess) {
203        callAbort(params, onSuccess, true);
204    }
205
206    public static void callAbortSpecialTasks(JSONObject params, final SimpleCallback onSuccess,
207                                 final boolean showMessage) {
208        JsonRpcProxy rpcProxy = JsonRpcProxy.getProxy();
209        rpcProxy.rpcCall("abort_special_tasks", params, new JsonRpcCallback() {
210            @Override
211            public void onSuccess(JSONValue result) {
212                if (showMessage) {
213                    NotifyManager.getInstance().showMessage("Special tasks aborted");
214                }
215                if (onSuccess != null) {
216                    onSuccess.doCallback(null);
217                }
218            }
219        });
220    }
221
222    public static void callAbortSpecialTasks(JSONObject params, final SimpleCallback onSuccess) {
223        callAbortSpecialTasks(params, onSuccess, true);
224    }
225
226    public static void callReverify(JSONObject params, final SimpleCallback onSuccess,
227                                    final String messagePrefix) {
228        JsonRpcProxy rpcProxy = JsonRpcProxy.getProxy();
229        rpcProxy.rpcCall("reverify_hosts", params, new JsonRpcCallback() {
230            @Override
231            public void onSuccess(JSONValue result) {
232
233                NotifyManager.getInstance().showMessage(
234                        messagePrefix + " scheduled for reverification");
235
236                if (onSuccess != null) {
237                    onSuccess.doCallback(null);
238                }
239            }
240        });
241    }
242
243    public static void callRepair(JSONObject params, final SimpleCallback onSuccess,
244                                  final String messagePrefix) {
245        JsonRpcProxy rpcProxy = JsonRpcProxy.getProxy();
246        rpcProxy.rpcCall("repair_hosts", params, new JsonRpcCallback() {
247            @Override
248            public void onSuccess(JSONValue result) {
249
250                NotifyManager.getInstance().showMessage(
251                        messagePrefix + " scheduled for repair");
252
253                if (onSuccess != null) {
254                    onSuccess.doCallback(null);
255                }
256            }
257        });
258    }
259
260    private static void scheduleReinstallHelper(JSONArray hosts, JSONObject controlInfo,
261                                                final String messagePrefix,
262                                                final JobCreateListener listener) {
263        String name = "reinstall_" + hosts.get(0).isString().stringValue();
264        if (hosts.size() > 1) {
265            name += "_etc";
266        }
267
268        // Get the option for "Never"
269        JSONValue rebootBefore = staticData.getData("reboot_before_options").isArray().get(0);
270        JSONValue rebootAfter = staticData.getData("reboot_after_options").isArray().get(0);
271
272        JSONObject args = new JSONObject();
273        args.put("name", new JSONString(name));
274        args.put("priority", staticData.getData("default_priority"));
275        args.put("control_file", controlInfo.get("control_file"));
276        args.put("control_type", new JSONString(TestSelector.SERVER_TYPE));
277        args.put("synch_count", controlInfo.get("synch_count"));
278        args.put("timeout_mins", staticData.getData("job_timeout_mins_default"));
279        args.put("max_runtime_mins", staticData.getData("job_max_runtime_mins_default"));
280        args.put("run_verify", JSONBoolean.getInstance(false));
281        args.put("parse_failed_repair", JSONBoolean.getInstance(true));
282        args.put("reboot_before", rebootBefore);
283        args.put("reboot_after", rebootAfter);
284        args.put("hosts", hosts);
285
286        JsonRpcProxy rpcProxy = JsonRpcProxy.getProxy();
287        rpcProxy.rpcCall("create_job", args, new JsonRpcCallback() {
288            @Override
289            public void onSuccess(JSONValue result) {
290                NotifyManager.getInstance().showMessage(messagePrefix + " scheduled for reinstall");
291                if (listener != null) {
292                    listener.onJobCreated((int) result.isNumber().doubleValue());
293                }
294            }
295        });
296    }
297
298    public static void scheduleReinstall(final JSONArray hosts, final String messagePrefix,
299                                         final JobCreateListener listener) {
300        // Find the test
301        JSONArray tests = staticData.getData("tests").isArray();
302        JSONObject reinstallTest = null;
303        for (int i = 0; i < tests.size(); i++) {
304            JSONObject test = tests.get(i).isObject();
305            if (test.get("name").isString().stringValue().equals(REINSTALL_TEST_NAME)) {
306                reinstallTest = test;
307                break;
308            }
309        }
310
311        if (reinstallTest == null) {
312            NotifyManager.getInstance().showError("No test found: " + REINSTALL_TEST_NAME);
313            return;
314        }
315
316        JSONObject params = new JSONObject();
317        JSONArray array = new JSONArray();
318        JsonRpcProxy rpcProxy = JsonRpcProxy.getProxy();
319
320        array.set(0, reinstallTest.get("id"));
321        params.put("tests", array);
322        rpcProxy.rpcCall("generate_control_file", params, new JsonRpcCallback() {
323            @Override
324            public void onSuccess(JSONValue controlInfo) {
325                scheduleReinstallHelper(hosts, controlInfo.isObject(),
326                                        messagePrefix, listener);
327            }
328        });
329    }
330
331    public static void callModifyHosts(JSONObject params, final SimpleCallback onSuccess) {
332        JsonRpcProxy rpcProxy = JsonRpcProxy.getProxy();
333        rpcProxy.rpcCall("modify_hosts", params, new JsonRpcCallback() {
334            @Override
335            public void onSuccess(JSONValue result) {
336                if (onSuccess != null) {
337                    onSuccess.doCallback(null);
338                }
339            }
340        });
341    }
342
343    public static void changeHostLocks(JSONArray hostIds, final boolean lock,
344                                       String lockReason, final String messagePrefix,
345                                       final SimpleCallback callback) {
346        JSONObject hostFilterData = new JSONObject();
347        JSONObject updateData = new JSONObject();
348        JSONObject params = new JSONObject();
349
350        hostFilterData.put("id__in", hostIds);
351        updateData.put("locked", JSONBoolean.getInstance(lock));
352        updateData.put("lock_reason", new JSONString(""));
353
354        if (lockReason != null && !lockReason.trim().isEmpty()) {
355            updateData.put("lock_reason", new JSONString(lockReason.trim()));
356        }
357
358        params.put("host_filter_data", hostFilterData);
359        params.put("update_data", updateData);
360
361        callModifyHosts(params, new SimpleCallback() {
362            public void doCallback(Object source) {
363                String message = messagePrefix + " ";
364                if (!lock) {
365                    message += "un";
366                }
367                message += "locked";
368
369                NotifyManager.getInstance().showMessage(message);
370
371                callback.doCallback(source);
372            }
373        });
374    }
375
376    public static String getJobTag(JSONObject job) {
377        return Utils.jsonToString(job.get("id")) + "-" + Utils.jsonToString(job.get("owner"));
378    }
379
380    public static void populateRadioChooser(RadioChooser chooser, String name) {
381        JSONArray options = staticData.getData(name + "_options").isArray();
382        for (JSONString jsonOption : new JSONArrayList<JSONString>(options)) {
383            chooser.addChoice(Utils.jsonToString(jsonOption));
384        }
385    }
386
387    public static void populateListBox(ListBox box, String staticDataKey) {
388        JSONArray options = staticData.getData(staticDataKey).isArray();
389        for (JSONString jsonOption : new JSONArrayList<JSONString>(options)) {
390            box.addItem(Utils.jsonToString(jsonOption));
391        }
392    }
393
394    public static void populateListBox(SimplifiedList box, String staticDataKey) {
395        JSONArray options = staticData.getData(staticDataKey).isArray();
396        for (JSONString jsonOption : new JSONArrayList<JSONString>(options)) {
397            String option = Utils.jsonToString(jsonOption);
398            box.addItem(option, option);
399        }
400    }
401
402    public static void setSelectedItem(ListBox box, String item) {
403        box.setSelectedIndex(0);
404        for (int i = 0; i < box.getItemCount(); i++) {
405            if (box.getItemText(i).equals(item)) {
406                box.setSelectedIndex(i);
407                break;
408            }
409        }
410    }
411
412    public static void removeElement(String id) {
413        Element element = DOM.getElementById(id);
414        element.getParentElement().removeChild(element);
415    }
416
417    public static int parsePositiveIntegerInput(String input, String fieldName) {
418        final int parsedInt;
419        try {
420            if (input.equals("") ||
421                (parsedInt = Integer.parseInt(input)) <= 0) {
422                    String error = "Please enter a positive " + fieldName;
423                    NotifyManager.getInstance().showError(error);
424                    throw new IllegalArgumentException();
425            }
426        } catch (NumberFormatException e) {
427            String error = "Invalid " + fieldName + ": \"" + input + "\"";
428            NotifyManager.getInstance().showError(error);
429            throw new IllegalArgumentException();
430        }
431        return parsedInt;
432    }
433
434    public static void removeSecondsFromDateField(JSONObject row,
435                                                  String sourceFieldName,
436                                                  String targetFieldName) {
437        JSONValue dateValue = row.get(sourceFieldName);
438        String date = "";
439        if (dateValue.isNull() == null) {
440            date = dateValue.isString().stringValue();
441            date = date.substring(0, date.length() - 3);
442        }
443        row.put(targetFieldName, new JSONString(date));
444    }
445
446    public static void callGetJobHistory(JSONObject params,
447                                         final SimpleCallback onSuccess,
448                                         final boolean showMessage) {
449        JsonRpcProxy rpcProxy = JsonRpcProxy.getProxy();
450        rpcProxy.rpcCall("get_job_history", params, new JsonRpcCallback() {
451            @Override
452            public void onSuccess(JSONValue result) {
453                if (showMessage) {
454                    NotifyManager.getInstance().showMessage("Get job history succeeded.");
455                }
456                if (onSuccess != null) {
457                    onSuccess.doCallback(result);
458                }
459            }
460        });
461    }
462}
463