1package autotest.tko;
2
3import autotest.common.Utils;
4import autotest.common.ui.ExtendedListBox;
5import autotest.tko.FilterStringViewer.EditListener;
6
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.ui.Anchor;
12import com.google.gwt.user.client.ui.Composite;
13import com.google.gwt.user.client.ui.FlexTable;
14import com.google.gwt.user.client.ui.HasHorizontalAlignment;
15import com.google.gwt.user.client.ui.HorizontalPanel;
16import com.google.gwt.user.client.ui.Panel;
17import com.google.gwt.user.client.ui.RadioButton;
18import com.google.gwt.user.client.ui.TextBox;
19import com.google.gwt.user.client.ui.VerticalPanel;
20
21import java.util.ArrayList;
22import java.util.List;
23import java.util.Map;
24
25public class FilterSelector extends Composite {
26
27    public class DatabaseFilter extends Composite implements ChangeHandler {
28
29        private ExtendedListBox dbColumnSelector = new DBColumnSelector(dbView);
30        private TextBox condition = new TextBox();
31        private FlexTable flexTable = new FlexTable();
32        private Anchor deleteLink = new Anchor("[X]");
33
34        private DatabaseFilter() {
35            dbColumnSelector.addChangeHandler(this);
36            condition.addChangeHandler(this);
37
38            deleteLink.addClickHandler(new ClickHandler() {
39                public void onClick(ClickEvent event) {
40                    if (enabled) {
41                        deleteFilter(DatabaseFilter.this);
42                        buildFilterString();
43                    }
44                }
45            });
46
47            flexTable.setWidget(0, 0, dbColumnSelector);
48            flexTable.setWidget(0, 1, condition);
49            flexTable.setWidget(0, 2, deleteLink);
50
51            initWidget(flexTable);
52        }
53
54        @Override
55        public void onChange(ChangeEvent event) {
56            buildFilterString();
57        }
58
59        public void setEnabled(boolean enabled) {
60            dbColumnSelector.setEnabled(enabled);
61            condition.setEnabled(enabled);
62        }
63
64        public boolean isEmpty() {
65            return condition.getText().equals("");
66        }
67
68        public String getFilterString() {
69            return dbColumnSelector.getSelectedValue() + " " + condition.getText();
70        }
71    }
72
73    private FlexTable table = new FlexTable();
74    private Panel filtersPanel = new VerticalPanel();
75    private List<DatabaseFilter> filters = new ArrayList<DatabaseFilter>();
76    private RadioButton all;
77    private RadioButton any;
78    private Anchor addLink = new Anchor("[Add Filter]");
79    private FilterStringViewer viewer = new FilterStringViewer();
80    private boolean enabled = true;
81    private String dbView;
82    private static int filterSelectorId;
83
84    public FilterSelector(String dbView) {
85        this.dbView = dbView;
86        int id = filterSelectorId;
87        filterSelectorId++;
88
89        all = new RadioButton("booleanOp" + id, "all of");
90        any = new RadioButton("booleanOp" + id, "any of");
91
92        ClickHandler booleanOpListener = new ClickHandler() {
93            public void onClick(ClickEvent event) {
94                buildFilterString();
95            }
96        };
97        all.addClickHandler(booleanOpListener);
98        any.addClickHandler(booleanOpListener);
99        all.setValue(true);
100
101        addLink.addClickHandler(new ClickHandler() {
102            public void onClick(ClickEvent event) {
103                if (enabled) {
104                    addFilter();
105                }
106            }
107        });
108
109        viewer.addEditListener(new EditListener() {
110            public void onEdit() {
111                setEnabled(false);
112            }
113
114            public void onRevert() {
115                setEnabled(true);
116                buildFilterString();
117            }
118        });
119
120        Panel booleanOpPanel = new HorizontalPanel();
121        booleanOpPanel.add(all);
122        booleanOpPanel.add(any);
123        table.setWidget(0, 0, booleanOpPanel);
124        table.setWidget(1, 0, filtersPanel);
125        table.getFlexCellFormatter().setColSpan(1, 0, 2);
126        table.setWidget(2, 1, addLink);
127        table.getFlexCellFormatter().setHorizontalAlignment(
128                2, 1, HasHorizontalAlignment.ALIGN_RIGHT);
129        table.setWidget(3, 0, viewer);
130        table.getFlexCellFormatter().setColSpan(3, 0, 2);
131        table.setStylePrimaryName("box");
132
133        addFilter();
134
135        initWidget(table);
136    }
137
138    public String getFilterString() {
139        return viewer.getText();
140    }
141
142    public void reset() {
143        filtersPanel.clear();
144        filters.clear();
145        addFilter();
146    }
147
148    protected void addToHistory(Map<String, String> args, String prefix) {
149        // Get all the filters/conditions
150        for (int index = 0; index < filters.size(); index++) {
151            args.put(prefix + "[" + index + "][db]",
152                    filters.get(index).dbColumnSelector.getSelectedValue());
153            args.put(prefix + "[" + index + "][condition]", filters.get(index).condition.getText());
154        }
155
156        // Get whether the filter should be "all" or "any"
157        args.put(prefix + "_all", Boolean.toString(all.getValue()));
158
159        viewer.addToHistory(args, prefix);
160    }
161
162    protected void handleHistoryArguments(Map<String, String> args, String prefix) {
163        int index = 0;
164        String db, condition;
165
166        // Restore all the filters/conditions
167        while ((db = args.get(prefix + "[" + index + "][db]")) != null) {
168            condition = args.get(prefix + "[" + index + "][condition]");
169            DatabaseFilter filter;
170            if (index == 0) {
171                filter = filters.get(0);
172            } else {
173                filter = addFilter();
174            }
175            filter.dbColumnSelector.selectByValue(db);
176            filter.condition.setText(condition);
177            index++;
178        }
179
180        // Restore the "all" or "any" selection
181        boolean allChecked = Boolean.parseBoolean(args.get(prefix + "_all"));
182        if (allChecked) {
183            all.setValue(true);
184        } else {
185            any.setValue(true);
186        }
187
188        buildFilterString();
189        viewer.handleHistoryArguments(args, prefix);
190    }
191
192    private DatabaseFilter addFilter() {
193        DatabaseFilter nextFilter = new DatabaseFilter();
194        filters.add(nextFilter);
195        filtersPanel.add(nextFilter);
196        return nextFilter;
197    }
198
199    private void deleteFilter(DatabaseFilter filter) {
200        // If there's only one filter, clear it
201        if (filters.size() == 1) {
202            reset();
203            return;
204        }
205
206        filters.remove(filter);
207        filtersPanel.remove(filter);
208    }
209
210    private void setEnabled(boolean enabled) {
211        this.enabled = enabled;
212        all.setEnabled(enabled);
213        any.setEnabled(enabled);
214        for (DatabaseFilter filter : filters) {
215            filter.setEnabled(enabled);
216        }
217    }
218
219    private void buildFilterString() {
220        List<String> filterParts = new ArrayList<String>();
221        for (DatabaseFilter filter : filters) {
222            if (!filter.isEmpty()) {
223                filterParts.add(filter.getFilterString());
224            }
225        }
226
227        String joiner = all.getValue() ? " AND " : " OR ";
228        String fullFilterString = Utils.joinStrings(joiner, filterParts);
229        viewer.setText(fullFilterString);
230    }
231}
232