/edu/uncc/parsets/gui/DataWizard.java

https://code.google.com/p/parsets/ · Java · 397 lines · 301 code · 67 blank · 29 comment · 23 complexity · 379047bc9eab1e601290136485ea1b75 MD5 · raw file

  1. package edu.uncc.parsets.gui;
  2. import java.awt.BorderLayout;
  3. import java.awt.Dimension;
  4. import java.awt.FileDialog;
  5. import java.awt.event.ActionEvent;
  6. import java.awt.event.ActionListener;
  7. import java.awt.event.ItemEvent;
  8. import java.awt.event.ItemListener;
  9. import javax.swing.BorderFactory;
  10. import javax.swing.JButton;
  11. import javax.swing.JComboBox;
  12. import javax.swing.JComponent;
  13. import javax.swing.JFrame;
  14. import javax.swing.JLabel;
  15. import javax.swing.JOptionPane;
  16. import javax.swing.JPanel;
  17. import javax.swing.JProgressBar;
  18. import javax.swing.JScrollPane;
  19. import javax.swing.JTable;
  20. import javax.swing.JTextField;
  21. import javax.swing.ListSelectionModel;
  22. import javax.swing.SwingUtilities;
  23. import javax.swing.event.DocumentEvent;
  24. import javax.swing.event.DocumentListener;
  25. import javax.swing.event.ListSelectionEvent;
  26. import javax.swing.event.ListSelectionListener;
  27. import javax.swing.table.AbstractTableModel;
  28. import net.miginfocom.swing.MigLayout;
  29. import edu.uncc.parsets.data.DataType;
  30. import edu.uncc.parsets.data.LocalDB;
  31. import edu.uncc.parsets.data.old.CSVDataSet;
  32. import edu.uncc.parsets.data.old.CSVParser;
  33. import edu.uncc.parsets.data.old.CSVParserListener;
  34. import edu.uncc.parsets.data.old.DataDimension;
  35. import edu.uncc.parsets.gui.DBTab.CSVFileFilter;
  36. import edu.uncc.parsets.util.osabstraction.AbstractOS;
  37. /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *\
  38. * Copyright (c) 2009, Robert Kosara, Caroline Ziemkiewicz,
  39. * and others (see Authors.txt for full list)
  40. * All rights reserved.
  41. *
  42. * Redistribution and use in source and binary forms, with or without
  43. * modification, are permitted provided that the following conditions are met:
  44. *
  45. * * Redistributions of source code must retain the above copyright
  46. * notice, this list of conditions and the following disclaimer.
  47. * * Redistributions in binary form must reproduce the above copyright
  48. * notice, this list of conditions and the following disclaimer in the
  49. * documentation and/or other materials provided with the distribution.
  50. * * Neither the name of UNC Charlotte nor the names of its contributors
  51. * may be used to endorse or promote products derived from this software
  52. * without specific prior written permission.
  53. *
  54. * THIS SOFTWARE IS PROVIDED BY ITS AUTHORS ''AS IS'' AND ANY
  55. * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
  56. * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
  57. * DISCLAIMED. IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY
  58. * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
  59. * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
  60. * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
  61. * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
  62. * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
  63. * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  64. \* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
  65. @SuppressWarnings("serial")
  66. public class DataWizard implements CSVParserListener {
  67. private JTable table;
  68. CSVDataSet data;
  69. DataDimension currentDimension;
  70. private JTable categoriesTable;
  71. private JComboBox typeCB;
  72. private JLabel dimKeyLabel;
  73. private JTextField dimNameTF;
  74. private JButton closeBtn;
  75. private JFrame wizardFrame;
  76. private JTextField nameTF;
  77. private JProgressBar progressBar;
  78. private JLabel fileNameLabel;
  79. private JTextField sourceTF;
  80. private JTextField srcURLTF;
  81. private String fileName;
  82. private JTextField sectionTF;
  83. private JLabel statusLabel;
  84. private CSVParser csvParser;
  85. class DataTableModel extends AbstractTableModel implements ListSelectionListener {
  86. int numRows = 0;
  87. public int getColumnCount() {
  88. if (data != null)
  89. return data.getNumDimensions();
  90. else
  91. return 0;
  92. }
  93. public int getRowCount() {
  94. if (data != null) {
  95. numRows = Math.min(data.getNumRecords()-1, 100);
  96. return numRows+1;
  97. } else
  98. return 0;
  99. }
  100. public Object getValueAt(int row, int col) {
  101. if (row >= numRows)
  102. return "...";
  103. else {
  104. DataDimension d = data.getDimension(col);
  105. return d.getValues().get(row);
  106. }
  107. }
  108. public String getColumnName(int i) {
  109. return data.getDimension(i).getName();
  110. }
  111. public void valueChanged(ListSelectionEvent event) {
  112. if (data != null)
  113. if (!event.getValueIsAdjusting() && (table.getSelectedColumn() >= 0)) {
  114. setActiveDimension(data.getDimension(table.getSelectedColumn()));
  115. }
  116. }
  117. };
  118. class CategoryTableModel extends AbstractTableModel {
  119. public int getColumnCount() {
  120. return 2;
  121. }
  122. public int getRowCount() {
  123. if (currentDimension != null
  124. && currentDimension.getDataType() == DataType.categorical)
  125. return currentDimension.getNumCategories();
  126. else
  127. return 0;
  128. }
  129. public Object getValueAt(int row, int col) {
  130. if (col == 0)
  131. return currentDimension.getCategoryKey(row);
  132. else
  133. return currentDimension.getCategoryName(row);
  134. }
  135. public String getColumnName(int i) {
  136. if (i == 0)
  137. return "Key";
  138. else
  139. return "Name";
  140. }
  141. public boolean isCellEditable(int rowIndex, int columnIndex) {
  142. return columnIndex == 1;
  143. }
  144. public void setValueAt(Object aValue, int rowIndex, int columnIndex) {
  145. currentDimension.setCategoryName(rowIndex, (String) aValue);
  146. }
  147. };
  148. public DataWizard() {
  149. table = new JTable();
  150. table.setRowSelectionAllowed(false);
  151. table.setColumnSelectionAllowed(true);
  152. table.setSelectionMode(ListSelectionModel.SINGLE_SELECTION);
  153. table.setAutoResizeMode(JTable.AUTO_RESIZE_OFF);
  154. JScrollPane scrollPane = new JScrollPane(table);
  155. scrollPane.setOpaque(false);
  156. wizardFrame = new JFrame("CSV Import");
  157. wizardFrame.setSize(800, 800);
  158. wizardFrame.add(createDataSetPanel(), BorderLayout.NORTH);
  159. scrollPane.setBorder(BorderFactory.createTitledBorder("Data"));
  160. wizardFrame.add(scrollPane, BorderLayout.CENTER);
  161. wizardFrame.add(createDimensionPanel(), BorderLayout.EAST);
  162. wizardFrame.add(createButtonPanel(), BorderLayout.SOUTH);
  163. wizardFrame.setVisible(true);
  164. fileName = AbstractOS.getCurrentOS().showDialog(wizardFrame, new CSVFileFilter(), FileDialog.LOAD);
  165. if (fileName != null) {
  166. progressBar.setIndeterminate(true);
  167. statusLabel.setText("Analyzing CSV file ...");
  168. csvParser = new CSVParser(fileName, this);
  169. csvParser.analyzeCSVFile();
  170. } else {
  171. wizardFrame.setVisible(false);
  172. wizardFrame.dispose();
  173. }
  174. }
  175. private JComponent createButtonPanel() {
  176. JPanel p = new JPanel(new MigLayout("fillx, insets 0"));
  177. progressBar = new JProgressBar();
  178. p.add(progressBar, "gapleft 5, width 250, split 2");
  179. statusLabel = new JLabel();
  180. p.add(statusLabel, "gapleft 7");
  181. closeBtn = new JButton("Cancel");
  182. closeBtn.addActionListener(new ActionListener() {
  183. public void actionPerformed(ActionEvent e) {
  184. wizardFrame.setVisible(false);
  185. }
  186. });
  187. p.add(closeBtn, "split 2, right, tag cancel");
  188. JButton saveBtn = new JButton("Save to DB");
  189. saveBtn.addActionListener(new ActionListener() {
  190. public void actionPerformed(ActionEvent e) {
  191. data.setName(nameTF.getText());
  192. data.setSource(sourceTF.getText());
  193. data.setSourceURL(srcURLTF.getText());
  194. data.setSection(sectionTF.getText());
  195. progressBar.setIndeterminate(true);
  196. statusLabel.setText("Writing data to local database ...");
  197. new Thread(new Runnable() {
  198. @Override
  199. public void run() {
  200. csvParser.streamToDB(LocalDB.getDefaultDB());
  201. }
  202. }).start();
  203. }
  204. });
  205. p.add(saveBtn, "tag ok");
  206. return p;
  207. }
  208. private JComponent createDataSetPanel() {
  209. JPanel p = new JPanel(new MigLayout("fill, insets 0 5 0 5, wrap 6"));
  210. p.setBorder(BorderFactory.createTitledBorder("Dataset"));
  211. p.add(new JLabel("Name:"), "right");
  212. p.add(nameTF = new JTextField(), "gap related, width 25sp, growx");
  213. p.add(new JLabel("Section:"), "right, gap unrelated");
  214. p.add(sectionTF = new JTextField(), "gap related, width 25sp, growx");
  215. p.add(new JLabel("File:"), "right, gap unrelated");
  216. p.add(fileNameLabel = new JLabel(), "gap related, width 25sp");
  217. p.add(new JLabel("Source:"), "right");
  218. p.add(sourceTF = new JTextField(), "gap related, width 25sp, growx");
  219. p.add(new JLabel("URL:"), "right, gap unrelated");
  220. p.add(srcURLTF = new JTextField(), "gap related, span 3, growx");
  221. return p;
  222. }
  223. private JPanel createDimensionPanel() {
  224. JPanel p = new JPanel();
  225. p.setBorder(BorderFactory.createTitledBorder("Dimension"));
  226. p.setLayout(new MigLayout("wrap 2, insets 0 10 0 10, fill", "[right]r[left]", "[]r[]r[]r[]r[grow,fill]r"));
  227. // p.add(new JCheckBox("Include"), "span 2, left");
  228. p.add(new JLabel("Key:"));
  229. dimKeyLabel = new JLabel("");
  230. p.add(dimKeyLabel, "gap related");
  231. p.add(new JLabel("Name:"));
  232. dimNameTF = new JTextField(25);
  233. dimNameTF.getDocument().addDocumentListener(new DocumentListener() {
  234. @Override
  235. public void changedUpdate(DocumentEvent e) {
  236. currentDimension.setName(dimNameTF.getText());
  237. }
  238. @Override
  239. public void insertUpdate(DocumentEvent e) {
  240. currentDimension.setName(dimNameTF.getText());
  241. }
  242. @Override
  243. public void removeUpdate(DocumentEvent e) {
  244. currentDimension.setName(dimNameTF.getText());
  245. }
  246. });
  247. p.add(dimNameTF, "gap related");
  248. p.add(new JLabel("Type:"));
  249. DataType activeTypes[] = {DataType.categorical, DataType.numerical};
  250. typeCB = new JComboBox(activeTypes);
  251. typeCB.addItemListener(new ItemListener() {
  252. public void itemStateChanged(ItemEvent e) {
  253. currentDimension.setDataType(DataType.values()[typeCB
  254. .getSelectedIndex()]);
  255. categoriesTable.revalidate();
  256. }
  257. });
  258. p.add(typeCB, "gap related");
  259. categoriesTable = new JTable();
  260. JScrollPane scrollPane = new JScrollPane(categoriesTable);
  261. scrollPane.setOpaque(false);
  262. scrollPane.setBorder(BorderFactory.createTitledBorder("Categories"));
  263. p.add(scrollPane, "span 2");
  264. p.setPreferredSize(new Dimension(250, 1000));
  265. return p;
  266. }
  267. private void setActiveDimension(DataDimension d) {
  268. currentDimension = d;
  269. categoriesTable.setModel(new CategoryTableModel());
  270. dimKeyLabel.setText(d.getKey());
  271. dimNameTF.setText(d.getName());
  272. typeCB.setSelectedIndex(d.getDataType().ordinal());
  273. }
  274. public void setDataSet(final CSVDataSet data) {
  275. this.data = data;
  276. SwingUtilities.invokeLater(new Runnable() {
  277. @Override
  278. public void run() {
  279. statusLabel.setText("");
  280. progressBar.setIndeterminate(false);
  281. nameTF.setText(data.getName());
  282. sectionTF.setText(data.getSection());
  283. fileNameLabel.setText(data.getFileBaseName());
  284. sourceTF.setText(data.getSource());
  285. srcURLTF.setText(data.getSourceURL());
  286. DataTableModel m = new DataTableModel();
  287. table.setModel(m);
  288. table.getColumnModel().getSelectionModel().addListSelectionListener(m);
  289. progressBar.setValue(0);
  290. }
  291. });
  292. }
  293. @Override
  294. public void setProgress(final int progress) {
  295. SwingUtilities.invokeLater(new Runnable() {
  296. @Override
  297. public void run() {
  298. if (progress >= 0) {
  299. progressBar.setIndeterminate(false);
  300. progressBar.setValue(progress);
  301. } else
  302. progressBar.setIndeterminate(true);
  303. }
  304. });
  305. }
  306. @Override
  307. public void importDone() {
  308. SwingUtilities.invokeLater(new Runnable() {
  309. @Override
  310. public void run() {
  311. wizardFrame.setVisible(false);
  312. }
  313. });
  314. }
  315. @Override
  316. public void errorFileNotFound(String filename) {
  317. JOptionPane.showConfirmDialog(wizardFrame, "The program could not locate the file '"+filename+"'.", "File Not Found!", JOptionPane.OK_OPTION, JOptionPane.ERROR_MESSAGE);
  318. wizardFrame.setVisible(false);
  319. }
  320. @Override
  321. public void errorReadingFile(String filename) {
  322. JOptionPane.showConfirmDialog(wizardFrame, "An error occured while reading the file '"+filename+"'.", "Error Reading File!", JOptionPane.OK_OPTION, JOptionPane.ERROR_MESSAGE);
  323. wizardFrame.setVisible(false);
  324. }
  325. @Override
  326. public void errorWrongNumberOfColumns(int expected, int found, int line) {
  327. JOptionPane.showConfirmDialog(wizardFrame, "The parser encountered a line with the wrong number of columns ("+found+" instead of "+expected+").", "Wrong Number of Columns!", JOptionPane.OK_OPTION, JOptionPane.ERROR_MESSAGE);
  328. wizardFrame.setVisible(false);
  329. }
  330. }