1package autotest.moblab;
2
3import autotest.common.ui.TabView;
4import autotest.moblab.rpc.ConnectedDutInfo;
5import autotest.moblab.rpc.MoblabRpcCallbacks;
6import autotest.moblab.rpc.MoblabRpcHelper;
7import com.google.gwt.event.dom.client.ChangeEvent;
8import com.google.gwt.event.dom.client.ChangeHandler;
9import com.google.gwt.event.dom.client.ClickEvent;
10import com.google.gwt.event.dom.client.ClickHandler;
11import com.google.gwt.user.client.Window;
12import com.google.gwt.user.client.ui.Button;
13import com.google.gwt.user.client.ui.CheckBox;
14import com.google.gwt.user.client.ui.FlexTable;
15import com.google.gwt.user.client.ui.HasVerticalAlignment;
16import com.google.gwt.user.client.ui.HorizontalPanel;
17import com.google.gwt.user.client.ui.Label;
18import com.google.gwt.user.client.ui.ListBox;
19import com.google.gwt.user.client.ui.TextArea;
20import com.google.gwt.user.client.ui.TextBox;
21import com.google.gwt.user.client.ui.VerticalPanel;
22
23/**
24 * Implement a tab that makes it easier to add/remove/maintain duts.
25 */
26public class DutManagementView extends TabView {
27
28  private FlexTable dutInfoTable;
29  private VerticalPanel dutSetupPanel;
30  private ListBox options;
31  private TextArea informationArea;
32  private Button actionButton;
33  private CheckBox poolCheckBox;
34  private TextBox poolLabelName;
35  private Label poolLabel;
36
37  private static final int DHCP_IP_COLUMN = 0;
38  private static final int DHCP_MAC_COLUMN = 1;
39  private static final int SELECTION_COLUMN = 2;
40  private static final int LABELS_COLUMN = 3;
41
42  @Override
43  public String getElementId() {
44    return "dut_manage";
45  }
46
47  @Override
48  public void refresh() {
49    super.refresh();
50    dutInfoTable.removeAllRows();
51    poolCheckBox.setValue(false);
52    poolLabelName.setText("");
53    loadData();
54  }
55
56  @Override
57  public void initialize() {
58    super.initialize();
59    // Main table of connected DUT information.
60    dutInfoTable = new FlexTable();
61
62    // The row of controls underneath the main data table.
63    dutSetupPanel = new VerticalPanel();
64
65    // List of actions to be applied to connected DUT's.
66    options = new ListBox();
67    options.addItem("Add Selected DUT's");
68    options.addItem("Remove Selected DUT's");
69    options.addItem("Add Label Selected DUT's");
70    options.addItem("Remove Label Selected DUT's");
71    options.setStyleName("dut_manage_action_row");
72    options.addChangeHandler(new ChangeHandler() {
73      @Override
74      public void onChange(ChangeEvent event) {
75        if (options.getSelectedIndex() == 2 || options.getSelectedIndex() == 3) {
76          poolCheckBox.setEnabled(true);
77          poolCheckBox.setValue(false);
78          poolLabelName.setEnabled(true);
79          poolLabelName.setText("");
80        } else {
81          poolCheckBox.setEnabled(false);
82          poolLabelName.setEnabled(false);
83        }
84      }
85    });
86
87    // Logging area at the end of the screen that gives status messages about bulk
88    // actions requested.
89    informationArea = new TextArea();
90    informationArea.setVisibleLines(10);
91    informationArea.setCharacterWidth(80);
92    informationArea.setReadOnly(true);
93
94    // Apply button, each action needs to be applied after selecting the devices and
95    // the action to be performed.
96    actionButton = new Button("Apply", new ClickHandler() {
97      public void onClick(ClickEvent event) {
98        ((Button)event.getSource()).setEnabled(false);
99        int action = options.getSelectedIndex();
100        try {
101          for (int i = 1; i < dutInfoTable.getRowCount(); i++) {
102            if (((CheckBox)dutInfoTable.getWidget(i, SELECTION_COLUMN)).getValue()) {
103              if (action == 0) {
104                  addDut(i);
105              } else if (action == 1) {
106                removeDut(i);
107              } else if (action == 2) {
108                addLabel(i, getLabelString());
109              } else if (action == 3) {
110                removeLabel(i, getLabelString());
111              }
112            }
113          }
114        } finally {
115          ((Button)event.getSource()).setEnabled(true);
116        }
117      }});
118
119
120    // For adding and removing labels a text input of the label is required.
121    poolCheckBox = new CheckBox();
122
123    // Pools are just special labels, this is just a helper to so users get
124    // it correct more of the time.
125    poolCheckBox.setText("Is pool label ?");
126    poolCheckBox.setStyleName("dut_manage_action_row_item");
127
128    // The text label explaining the text box is for entering the label.
129    poolLabel = new Label();
130    poolLabel.setText("Label name:");
131    poolLabel.setStyleName("dut_manage_action_row_item");
132
133    // The text entry of the label to add or remove.
134    poolLabelName = new TextBox();
135    poolLabelName.setStyleName("dut_manage_action_row_item");
136    poolCheckBox.setEnabled(false);
137
138   // Assemble the display panels in the correct order.
139    dutSetupPanel.add(dutInfoTable);
140    HorizontalPanel actionRow = new HorizontalPanel();
141    actionRow.setStyleName("dut_manage_action_row");
142    actionRow.setVerticalAlignment(HasVerticalAlignment.ALIGN_MIDDLE);
143    actionRow.add(options);
144    actionRow.add(poolCheckBox);
145    actionRow.add(poolLabel);
146    actionRow.add(poolLabelName);
147    actionRow.add(actionButton);
148    dutSetupPanel.add(actionRow);
149    dutSetupPanel.add(informationArea);
150    addWidget(dutSetupPanel, "view_dut_manage");
151    poolLabelName.setEnabled(false);
152  }
153
154  private String getLabelString() {
155    StringBuilder builder = new StringBuilder(poolLabelName.getText());
156    if (poolCheckBox.getValue()) {
157      builder.insert(0, "pool:");
158    }
159    return builder.toString();
160  }
161
162  private void loadData() {
163    MoblabRpcHelper.fetchDutInformation(new MoblabRpcCallbacks.FetchConnectedDutInfoCallback() {
164      @Override
165      public void onFetchConnectedDutInfoSubmitted(ConnectedDutInfo info) {
166        addTableHeader();
167        // The header is row 0
168        int row = 1;
169        for (final String dutIpAddress : info.getConnectedIpsToMacAddress().keySet()) {
170          addRowStyles(row);
171          String labelString;
172          if (info.getConfiguredIpsToLabels().keySet().contains(dutIpAddress)) {
173            labelString = info.getConfiguredIpsToLabels().get(dutIpAddress);
174          } else {
175            labelString = "DUT Not Configured in Autotest";
176          }
177          addRow(row, dutIpAddress, info.getConnectedIpsToMacAddress().get(dutIpAddress), labelString);
178          row++;
179        }
180        for (final String dutIpAddress : info.getConfiguredIpsToLabels().keySet()) {
181          if (!info.getConnectedIpsToMacAddress().keySet().contains(dutIpAddress)) {
182            // Device is in AFE but not detected in the DHCP table.
183            addRowStyles(row);
184            addRow(row, dutIpAddress, "",
185                "DUT Configured in Autotest but does not appear to be attached.");
186            row++;
187          }
188        }
189      }
190    });
191  }
192
193  /**
194   * Add the correct css styles for each data row.
195   * @param row index of the row to apply the styles for, first data row is 1.
196   */
197  private void addRowStyles(int row) {
198    dutInfoTable.getCellFormatter().addStyleName(row, DHCP_IP_COLUMN,"ip_cell");
199    dutInfoTable.getCellFormatter().addStyleName(row,DHCP_MAC_COLUMN,"mac_cell");
200    dutInfoTable.getCellFormatter().addStyleName(row,SELECTION_COLUMN,"selection_cell");
201    dutInfoTable.getCellFormatter().addStyleName(row,LABELS_COLUMN,"labels_cell");
202  }
203
204  /**
205   * Insert or update the data in the table for a given row.
206   * @param row  The row index to update, first data row is 1.
207   * @param ipColumn String to be added into the first column.
208   * @param macColumn String to be added to the second column.
209   * @param labelsColumn String to be added to the fourth column.
210   */
211  private void addRow(int row, String ipColumn, String macColumn, String labelsColumn) {
212    dutInfoTable.setWidget(row, DHCP_IP_COLUMN, new Label(ipColumn));
213    dutInfoTable.setWidget(row, DHCP_MAC_COLUMN, new Label(macColumn));
214    dutInfoTable.setWidget(row, SELECTION_COLUMN, new CheckBox());
215    dutInfoTable.setWidget(row, LABELS_COLUMN, new Label(labelsColumn));
216  }
217
218  /**
219   * Add the column headers with the correct css styling into the data table.
220   */
221  private void addTableHeader() {
222    dutInfoTable.addStyleName("dut_info_table");
223    dutInfoTable.getCellFormatter().addStyleName(0, DHCP_IP_COLUMN,
224        "dut_manage_column_label_c");
225    dutInfoTable.getCellFormatter().addStyleName(0, DHCP_MAC_COLUMN,
226        "dut_manage_column_label_c");
227    dutInfoTable.getCellFormatter().addStyleName(0, SELECTION_COLUMN,
228        "dut_manage_column_label_c");
229    dutInfoTable.getCellFormatter().addStyleName(0, LABELS_COLUMN,
230        "dut_manage_column_label_c");
231    dutInfoTable.setWidget(0, DHCP_IP_COLUMN, new Label("DCHP Lease Address"));
232    dutInfoTable.setWidget(0, DHCP_MAC_COLUMN, new Label("DCHP MAC Address"));
233    dutInfoTable.setWidget(0, LABELS_COLUMN, new Label("DUT Labels"));
234  }
235
236  /**
237   * Make an RPC call to the autotest system to enroll the DUT listed at the given row number.
238   * @param row_number the row number in the table that has details of the device to enroll.
239   */
240  private void addDut(int row_number) {
241    String ipAddress = ((Label)dutInfoTable.getWidget(row_number, DHCP_IP_COLUMN)).getText();
242    MoblabRpcHelper.addMoblabDut(ipAddress, new LogAction(informationArea));
243  }
244
245  /**
246   * Make an RPC to to the autotest system to delete information about the DUT listed at the given
247   * row.
248   * @param row_number the row number in the table that has details of the device to remove.
249   */
250  private void removeDut(int row_number) {
251    String ipAddress = ((Label)dutInfoTable.getWidget(row_number, DHCP_IP_COLUMN)).getText();
252    MoblabRpcHelper.removeMoblabDut(ipAddress, new LogAction(informationArea));
253  }
254
255  /**
256   * Make an RPC to to the autotest system to add a label to a DUT whoes details are in the given
257   * row.
258   * @param row_number row in the data table that has the information about the DUT
259   * @param labelName the label string to be added.
260   */
261  private void addLabel(int row_number, String labelName) {
262    String ipAddress = ((Label)dutInfoTable.getWidget(row_number, DHCP_IP_COLUMN)).getText();
263    MoblabRpcHelper.addMoblabLabel(ipAddress, labelName, new LogAction(informationArea));
264  }
265
266  /**
267   * Make an RPC to to the autotest system to remove a label to a DUT whoes details are in the
268   * given row.
269   * @param row_number row in the data table that has the information about the DUT
270   * @param labelName the label string to be removed.
271   */
272  private void removeLabel(int row_number, String labelName) {
273    String ipAddress = ((Label)dutInfoTable.getWidget(row_number, DHCP_IP_COLUMN)).getText();
274    MoblabRpcHelper.removeMoblabLabel(ipAddress, labelName, new LogAction(informationArea));
275  }
276
277  /**
278   * Call back that inserts a string from an completed RPC into the UI.
279   */
280  private static class LogAction implements MoblabRpcCallbacks.LogActionCompleteCallback {
281    private TextArea informationArea;
282
283    LogAction(TextArea informationArea){
284      this.informationArea = informationArea;
285    }
286    @Override
287    public void onLogActionComplete(boolean status, String information) {
288      String currentText = informationArea.getText();
289      informationArea
290          .setText(new StringBuilder().append(information).append(
291              "\n").append(currentText).toString());
292    }
293  }
294}
295