001: package com.vividsolutions.jump.workbench.ui.plugin.datastore;
002:
003: import java.awt.Component;
004: import java.awt.Dimension;
005: import java.awt.GridBagConstraints;
006: import java.awt.GridBagLayout;
007: import java.awt.Insets;
008: import java.awt.event.ActionEvent;
009: import java.awt.event.ActionListener;
010: import java.awt.event.FocusEvent;
011: import java.awt.event.FocusListener;
012: import java.io.File;
013: import java.util.ArrayList;
014: import java.util.Collections;
015: import java.util.Comparator;
016: import java.util.List;
017: import java.util.Map;
018: import java.util.Vector;
019:
020: import javax.swing.BorderFactory;
021: import javax.swing.DefaultComboBoxModel;
022: import javax.swing.DefaultListCellRenderer;
023: import javax.swing.JButton;
024: import javax.swing.JComboBox;
025: import javax.swing.JFileChooser;
026: import javax.swing.JLabel;
027: import javax.swing.JList;
028: import javax.swing.JPanel;
029: import javax.swing.JPasswordField;
030: import javax.swing.JTextField;
031: import javax.swing.filechooser.FileFilter;
032:
033: import com.vividsolutions.jump.I18N;
034: import com.vividsolutions.jump.datastore.DataStoreDriver;
035: import com.vividsolutions.jump.parameter.ParameterList;
036: import com.vividsolutions.jump.parameter.ParameterListSchema;
037: import com.vividsolutions.jump.util.Blackboard;
038: import com.vividsolutions.jump.util.CollectionUtil;
039: import com.vividsolutions.jump.workbench.WorkbenchContext;
040: import com.vividsolutions.jump.workbench.datasource.LoadFileDataSourceQueryChooser;
041: import com.vividsolutions.jump.workbench.datastore.ConnectionDescriptor;
042: import com.vividsolutions.jump.workbench.registry.Registry;
043: import com.vividsolutions.jump.workbench.ui.ValidatingTextField;
044: import com.vividsolutions.jump.workbench.ui.plugin.PersistentBlackboardPlugIn;
045:
046: public class ConnectionDescriptorPanel extends JPanel {
047: private WorkbenchContext context;
048: private ParameterListSchema schema = new ParameterListSchema(
049: new String[] {}, new Class[] {});
050:
051: private static int createdConnectionCount = 0;
052:
053: private JTextField nameText = new JTextField();
054: private JComboBox driverComboBox = null;
055:
056: private List editComponentList = new ArrayList();
057:
058: private void updateMainPanel(ParameterList parameterList,
059: Blackboard bb) {
060: mainPanel.removeAll();
061: editComponentList.clear();
062: addEditComponent(
063: 0,
064: I18N
065: .get("jump.workbench.ui.plugin.datastore.ConnectionDescriptorPanel.Name"),
066: nameText);
067: addEditComponent(
068: 1,
069: I18N
070: .get("jump.workbench.ui.plugin.datastore.ConnectionDescriptorPanel.Driver"),
071: driverComboBox);
072: for (int i = 0; i < schema.getNames().length; i++) {
073: String name = schema.getNames()[i];
074: editComponentList.add(createEditComponent(name, schema
075: .getClasses()[i], parameterList.getParameter(name),
076: bb));
077: addEditComponent(i + 2, name, (Component) editComponentList
078: .get(editComponentList.size() - 1));
079: }
080: revalidate();
081: repaint();
082: }
083:
084: private void addEditComponent(int i, String name,
085: Component editComponent) {
086: mainPanel.add(new JLabel(name), new GridBagConstraints(0, i, 1,
087: 1, 0, 0, GridBagConstraints.WEST,
088: GridBagConstraints.NONE, new Insets(2, 2, 2, 2), 0, 0));
089: mainPanel.add(editComponent, new GridBagConstraints(1, i, 1, 1,
090: 0, 0, GridBagConstraints.WEST, GridBagConstraints.NONE,
091: new Insets(2, 2, 2, 2), 0, 0));
092: }
093:
094: private Component createEditComponent(String name,
095: Class parameterClass, Object parameter, Blackboard bb) {
096: Component editComponent = parameterClassHandler(name,
097: parameterClass).createEditComponent(bb);
098: if (parameter != null) {
099: parameterClassHandler(name, parameterClass).setParameter(
100: editComponent, parameter);
101: }
102: return editComponent;
103: }
104:
105: private ParameterClassHandler parameterClassHandler(String name,
106: Class parameterClass) {
107: if (name.equalsIgnoreCase("Password")) {
108: return PASSWORD_HANDLER;
109: }
110: return (ParameterClassHandler) parameterClassToHandlerMap
111: .get(parameterClass);
112: }
113:
114: private interface ParameterClassHandler {
115:
116: Component createEditComponent(Blackboard bb);
117:
118: void setParameter(Component component, Object parameter);
119:
120: Object getParameter(Component component);
121: }
122:
123: private static final ParameterClassHandler PASSWORD_HANDLER = new ParameterClassHandler() {
124: public Component createEditComponent(Blackboard bb) {
125: return new JPasswordField(20);
126: }
127:
128: public void setParameter(Component component, Object parameter) {
129: ((JPasswordField) component).setText((String) parameter);
130: }
131:
132: public Object getParameter(Component component) {
133: // The JavaDoc is not clear about *how* #getPassword is any more
134: // secure than #getText [Jon Aquino 2005-03-07]
135: return new String(((JPasswordField) component)
136: .getPassword());
137: }
138: };
139:
140: private static class JMPFileChooser extends JPanel {
141: Blackboard bb;
142: JFileChooser chooser;
143: File f = null;
144:
145: public JMPFileChooser(Blackboard bb) {
146: this .bb = bb;
147: chooser = new JFileChooser();
148:
149: final JMPFileChooser th = this ;
150:
151: final JTextField strFile = new JTextField(20);
152: JButton open = new JButton();
153: open.setText("...");
154: open.setMargin(new Insets(0, 0, 0, 0));
155:
156: strFile.addFocusListener(new FocusListener() {
157:
158: public void focusGained(FocusEvent e) {
159: // do nothing
160: }
161:
162: public void focusLost(FocusEvent e) {
163: // check for a new value ...
164: String t = strFile.getText();
165: if (t == null) {
166: th.f = null;
167: return;
168: }
169: t = t.trim();
170: if (t == null || "".equals(t)) {
171: th.f = null;
172: return;
173: }
174:
175: th.f = new File(t);
176: }
177:
178: });
179:
180: open.addActionListener(new ActionListener() {
181: public void actionPerformed(ActionEvent e) {
182: if (f != null) {
183: chooser.setSelectedFile(f);
184: th.setToolTipText(f.toString());
185: }
186: int selection = chooser.showOpenDialog(th);
187: if (selection == JFileChooser.APPROVE_OPTION) {
188: th.f = chooser.getSelectedFile();
189: if (th.f == null) {
190: strFile.setText("");
191: } else {
192: strFile.setText(th.f.toString());
193: }
194: }
195: }
196: });
197:
198: setBorder(BorderFactory
199: .createLineBorder(getBackground(), 0));
200: GridBagLayout gl = new GridBagLayout();
201: setLayout(gl);
202: setAlignmentX(0);
203:
204: GridBagConstraints c = new GridBagConstraints(0, 0, 1, 1,
205: 0, 0, GridBagConstraints.WEST,
206: GridBagConstraints.NONE, new Insets(0, 0, 0, 0), 0,
207: 0);
208:
209: add(strFile, c);
210: gl.setConstraints(strFile, c);
211:
212: c = new GridBagConstraints(1, 0, 1, 1, 0, 0,
213: GridBagConstraints.WEST, GridBagConstraints.NONE,
214: new Insets(2, 2, 2, 2), 0, 0);
215: add(open, c);
216: gl.setConstraints(open, c);
217:
218: }
219:
220: }
221:
222: private Map parameterClassToHandlerMap = CollectionUtil
223: .createMap(new Object[] { String.class,
224: new ParameterClassHandler() {
225:
226: public Component createEditComponent(
227: Blackboard bb) {
228: return new JTextField(20);
229: }
230:
231: public void setParameter(Component component,
232: Object parameter) {
233: ((JTextField) component)
234: .setText((String) parameter);
235: }
236:
237: public Object getParameter(Component component) {
238: return ((JTextField) component).getText();
239: }
240: }, File.class, new ParameterClassHandler() {
241:
242: public Component createEditComponent(
243: Blackboard bb) {
244: JMPFileChooser fileChooser = new JMPFileChooser(
245: bb);
246: if (bb
247: .get(LoadFileDataSourceQueryChooser.FILE_CHOOSER_DIRECTORY_KEY) != null) {
248: fileChooser.f = new File(
249: (String) bb
250: .get(LoadFileDataSourceQueryChooser.FILE_CHOOSER_DIRECTORY_KEY));
251: }
252: return fileChooser;
253: }
254:
255: public void setParameter(Component component,
256: Object parameter) {
257: if (parameter != null) {
258: File f = (File) parameter;
259: ((JMPFileChooser) component).f = f;
260: if (f != null && f.getParent() != null) {
261: ((JMPFileChooser) component).bb
262: .put(
263: LoadFileDataSourceQueryChooser.FILE_CHOOSER_DIRECTORY_KEY,
264: f.getParent());
265: if (f.isFile()) {
266: int index = f.getName()
267: .lastIndexOf('.') + 1;
268: if (index > -1) {
269: final String suffix = f
270: .getName()
271: .substring(index);
272: if (suffix != null
273: && !""
274: .equals(suffix
275: .trim()))
276: ((JMPFileChooser) component).chooser
277: .setFileFilter(new FileFilter() {
278: public boolean accept(
279: File f) {
280: return f != null
281: && (f
282: .isDirectory() || (f
283: .isFile() && f
284: .getName()
285: .endsWith(
286: suffix)));
287: }
288:
289: public String getDescription() {
290: return "";
291: }
292: });
293: }
294: }
295: }
296: }
297: ((JTextField) component)
298: .setText(parameter == null ? ""
299: : ((File) parameter)
300: .toString());
301: }
302:
303: public Object getParameter(Component component) {
304: File f = ((JMPFileChooser) component).f;
305: if (f != null && f.getParent() != null)
306: ((JMPFileChooser) component).bb
307: .put(
308: LoadFileDataSourceQueryChooser.FILE_CHOOSER_DIRECTORY_KEY,
309: f.getParent());
310: return f;
311: }
312:
313: }, Integer.class, new ParameterClassHandler() {
314:
315: public Component createEditComponent(
316: Blackboard bb) {
317: return new ValidatingTextField(
318: "",
319: 5,
320: ValidatingTextField.INTEGER_VALIDATOR);
321: }
322:
323: public void setParameter(Component component,
324: Object parameter) {
325: ((JTextField) component)
326: .setText(((Integer) parameter)
327: .toString());
328: }
329:
330: public Object getParameter(Component component) {
331: return ((JTextField) component).getText()
332: .length() > 0 ? new Integer(
333: ((JTextField) component).getText())
334: : null;
335: }
336: } });
337:
338: private JPanel mainPanel = new JPanel(new GridBagLayout());
339:
340: public ConnectionDescriptorPanel(Registry registry,
341: final WorkbenchContext context) {
342: super (new GridBagLayout());
343: this .context = context;
344:
345: nameText = new JTextField("", 20);
346: //nameText.setPreferredSize(new Dimension());
347:
348: driverComboBox = new JComboBox() {
349: {
350: addActionListener(new ActionListener() {
351: public void actionPerformed(ActionEvent e) {
352: ParameterList oldParameterList = createParameterList();
353: schema = ((DataStoreDriver) getSelectedItem())
354: .getParameterListSchema();
355: updateMainPanel(copyWherePossible(
356: oldParameterList, schema),
357: PersistentBlackboardPlugIn.get(context));
358: }
359: });
360: setRenderer(new DefaultListCellRenderer() {
361: public Component getListCellRendererComponent(
362: JList list, Object value, int index,
363: boolean isSelected, boolean cellHasFocus) {
364: return super .getListCellRendererComponent(list,
365: ((DataStoreDriver) value).getName(),
366: index, isSelected, cellHasFocus);
367: }
368: });
369: }
370: };
371:
372: add(mainPanel, new GridBagConstraints(0, 0, 1, 1, 0, 0,
373: GridBagConstraints.NORTHWEST, GridBagConstraints.NONE,
374: new Insets(2, 2, 2, 2), 0, 0));
375: add(new JPanel(new GridBagLayout()), new GridBagConstraints(1,
376: 1, 1, 1, 1, 1, GridBagConstraints.NORTHWEST,
377: GridBagConstraints.NONE, new Insets(0, 0, 0, 0), 0, 0));
378: driverComboBox
379: .setModel(new DefaultComboBoxModel(
380: sort(
381: new Vector(
382: registry
383: .getEntries(DataStoreDriver.REGISTRY_CLASSIFICATION)),
384: new Comparator() {
385: public int compare(Object o1,
386: Object o2) {
387: return compare(
388: (DataStoreDriver) o1,
389: (DataStoreDriver) o2);
390: }
391:
392: public int compare(
393: DataStoreDriver a,
394: DataStoreDriver b) {
395: return a.getName().compareTo(
396: b.getName());
397: }
398: })));
399: initializePreferredSize();
400: driverComboBox.setSelectedIndex(0);
401: }
402:
403: private void initializePreferredSize() {
404: int maxWidth = 0;
405: int maxHeight = 0;
406: for (int i = 0; i < driverComboBox.getItemCount(); i++) {
407: driverComboBox.setSelectedIndex(i);
408: maxWidth = Math.max(maxWidth, (int) getPreferredSize()
409: .getWidth());
410: maxHeight = Math.max(maxHeight, (int) getPreferredSize()
411: .getHeight());
412: }
413: setPreferredSize(new Dimension(maxWidth, maxHeight));
414: }
415:
416: private Vector sort(Vector collection, Comparator comparator) {
417: Collections.sort(collection, comparator);
418: return collection;
419: }
420:
421: private String getValidConnectionName() {
422: String fieldName = nameText.getText();
423: if (fieldName == null || fieldName.trim().length() == 0) {
424: return ((DataStoreDriver) driverComboBox.getSelectedItem())
425: .getName()
426: + " " + ++createdConnectionCount;
427: }
428: return fieldName.trim();
429: }
430:
431: public ConnectionDescriptor getConnectionDescriptor() {
432: return new ConnectionDescriptor(getValidConnectionName(),
433: driverComboBox.getSelectedItem().getClass(),
434: createParameterList());
435: }
436:
437: private ParameterList createParameterList() {
438: ParameterList parameterList = new ParameterList(schema);
439: for (int i = 0; i < editComponentList.size(); i++) {
440: parameterList.setParameter(schema.getNames()[i],
441: parameterClassHandler(schema.getNames()[i],
442: schema.getClasses()[i]).getParameter(
443: (Component) editComponentList.get(i)));
444: }
445: return parameterList;
446: }
447:
448: public void setParameters(ConnectionDescriptor connDesc) {
449: nameText.setText(connDesc.getName());
450: int driverComboIndex = getDriverComboBoxIndex(connDesc
451: .getDataStoreDriverClassName());
452: if (driverComboIndex >= 0) {
453: driverComboBox.setSelectedIndex(driverComboIndex);
454: schema = ((DataStoreDriver) driverComboBox
455: .getSelectedItem()).getParameterListSchema();
456: }
457: updateMainPanel(connDesc.getParameterList(),
458: PersistentBlackboardPlugIn.get(context));
459: }
460:
461: private int getDriverComboBoxIndex(String driverClassName) {
462: for (int i = 0; i < driverComboBox.getItemCount(); i++) {
463: DataStoreDriver driver = (DataStoreDriver) driverComboBox
464: .getItemAt(i);
465: if (driver.getClass().getName().equals(driverClassName)) {
466: return i;
467: }
468: }
469: return -1;
470: }
471:
472: /*
473: public static void main(String[] args) throws Exception {
474: UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
475: JFrame frame = new JFrame();
476: frame.getContentPane().add(
477: new ConnectionDescriptorPanel(new Registry().createEntry(
478: DataStoreDriver.REGISTRY_CLASSIFICATION,
479: new PostgisDataStoreDriver()),null));
480: frame.pack();
481: frame.setVisible(true);
482: }
483: //*/
484:
485: public String validateInput() {
486: for (int i = 0; i < editComponentList.size(); i++) {
487: Object parameter = parameterClassHandler(
488: schema.getNames()[i], schema.getClasses()[i])
489: .getParameter((Component) editComponentList.get(i));
490: if (parameter == null || parameter.equals("")) {
491: return (I18N
492: .get("jump.workbench.ui.plugin.datastore.ConnectionDescriptorPanel.Required-field-missing")
493: + " " + schema.getNames()[i]);
494: }
495: }
496: return null;
497: }
498:
499: private ParameterList copyWherePossible(
500: ParameterList oldParameterList,
501: ParameterListSchema newSchema) {
502: ParameterList newParameterList = new ParameterList(newSchema);
503: for (int i = 0; i < newSchema.getNames().length; i++) {
504: String name = newSchema.getNames()[i];
505: newParameterList
506: .setParameter(
507: name,
508: oldParameterList.getSchema().isValidName(
509: name)
510: && newSchema.getClasses()[i] == oldParameterList
511: .getSchema().getClass(name) ? oldParameterList
512: .getParameter(name)
513: : null);
514: }
515: return newParameterList;
516: }
517: }
|