Source Code Cross Referenced for DataTypeString.java in  » Database-Client » squirrel-sql-2.6.5a » net » sourceforge » squirrel_sql » fw » datasetviewer » cellcomponent » Java Source Code / Java DocumentationJava Source Code and Java Documentation

Java Source Code / Java Documentation
1. 6.0 JDK Core
2. 6.0 JDK Modules
3. 6.0 JDK Modules com.sun
4. 6.0 JDK Modules com.sun.java
5. 6.0 JDK Modules sun
6. 6.0 JDK Platform
7. Ajax
8. Apache Harmony Java SE
9. Aspect oriented
10. Authentication Authorization
11. Blogger System
12. Build
13. Byte Code
14. Cache
15. Chart
16. Chat
17. Code Analyzer
18. Collaboration
19. Content Management System
20. Database Client
21. Database DBMS
22. Database JDBC Connection Pool
23. Database ORM
24. Development
25. EJB Server geronimo
26. EJB Server GlassFish
27. EJB Server JBoss 4.2.1
28. EJB Server resin 3.1.5
29. ERP CRM Financial
30. ESB
31. Forum
32. GIS
33. Graphic Library
34. Groupware
35. HTML Parser
36. IDE
37. IDE Eclipse
38. IDE Netbeans
39. Installer
40. Internationalization Localization
41. Inversion of Control
42. Issue Tracking
43. J2EE
44. JBoss
45. JMS
46. JMX
47. Library
48. Mail Clients
49. Net
50. Parser
51. PDF
52. Portal
53. Profiler
54. Project Management
55. Report
56. RSS RDF
57. Rule Engine
58. Science
59. Scripting
60. Search Engine
61. Security
62. Sevlet Container
63. Source Control
64. Swing Library
65. Template Engine
66. Test Coverage
67. Testing
68. UML
69. Web Crawler
70. Web Framework
71. Web Mail
72. Web Server
73. Web Services
74. Web Services apache cxf 2.0.1
75. Web Services AXIS2
76. Wiki Engine
77. Workflow Engines
78. XML
79. XML UI
Java
Java Tutorial
Java Open Source
Jar File Download
Java Articles
Java Products
Java by API
Photoshop Tutorials
Maya Tutorials
Flash Tutorials
3ds-Max Tutorials
Illustrator Tutorials
GIMP Tutorials
C# / C Sharp
C# / CSharp Tutorial
C# / CSharp Open Source
ASP.Net
ASP.NET Tutorial
JavaScript DHTML
JavaScript Tutorial
JavaScript Reference
HTML / CSS
HTML CSS Reference
C / ANSI-C
C Tutorial
C++
C++ Tutorial
Ruby
PHP
Python
Python Tutorial
Python Open Source
SQL Server / T-SQL
SQL Server / T-SQL Tutorial
Oracle PL / SQL
Oracle PL/SQL Tutorial
PostgreSQL
SQL / MySQL
MySQL Tutorial
VB.Net
VB.Net Tutorial
Flash / Flex / ActionScript
VBA / Excel / Access / Word
XML
XML Tutorial
Microsoft Office PowerPoint 2007 Tutorial
Microsoft Office Excel 2007 Tutorial
Microsoft Office Word 2007 Tutorial
Java Source Code / Java Documentation » Database Client » squirrel sql 2.6.5a » net.sourceforge.squirrel_sql.fw.datasetviewer.cellcomponent 
Source Cross Referenced  Class Diagram Java Document (Java Doc) 


0001:        package net.sourceforge.squirrel_sql.fw.datasetviewer.cellcomponent;
0002:
0003:        /*
0004:         * Copyright (C) 2001-2003 Colin Bell
0005:         * colbell@users.sourceforge.net
0006:         *
0007:         * This library is free software; you can redistribute it and/or
0008:         * modify it under the terms of the GNU Lesser General Public
0009:         * License as published by the Free Software Foundation; either
0010:         * version 2.1 of the License, or (at your option) any later version.
0011:         *
0012:         * This library is distributed in the hope that it will be useful,
0013:         * but WITHOUT ANY WARRANTY; without even the implied warranty of
0014:         * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
0015:         * Lesser General Public License for more details.
0016:         *
0017:         * You should have received a copy of the GNU Lesser General Public
0018:         * License along with this library; if not, write to the Free Software
0019:         * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
0020:         */
0021:        import java.awt.GridBagConstraints;
0022:        import java.awt.GridBagLayout;
0023:        import java.awt.Insets;
0024:        import java.awt.event.KeyEvent;
0025:        import java.awt.event.MouseAdapter;
0026:        import java.awt.event.MouseEvent;
0027:        import java.io.FileInputStream;
0028:        import java.io.FileOutputStream;
0029:        import java.io.IOException;
0030:        import java.io.InputStreamReader;
0031:        import java.io.OutputStreamWriter;
0032:        import java.sql.PreparedStatement;
0033:        import java.sql.ResultSet;
0034:        import java.sql.Types;
0035:        import java.util.HashMap;
0036:        import java.util.Iterator;
0037:
0038:        import javax.swing.BorderFactory;
0039:        import javax.swing.JCheckBox;
0040:        import javax.swing.JScrollPane;
0041:        import javax.swing.JTable;
0042:        import javax.swing.JTextArea;
0043:        import javax.swing.JTextField;
0044:        import javax.swing.SwingUtilities;
0045:        import javax.swing.event.ChangeEvent;
0046:        import javax.swing.event.ChangeListener;
0047:        import javax.swing.text.JTextComponent;
0048:
0049:        import net.sourceforge.squirrel_sql.fw.datasetviewer.CellDataPopup;
0050:        import net.sourceforge.squirrel_sql.fw.datasetviewer.ColumnDisplayDefinition;
0051:        import net.sourceforge.squirrel_sql.fw.gui.IntegerField;
0052:        import net.sourceforge.squirrel_sql.fw.gui.OkJPanel;
0053:        import net.sourceforge.squirrel_sql.fw.sql.ISQLDatabaseMetaData;
0054:        import net.sourceforge.squirrel_sql.fw.util.StringManager;
0055:        import net.sourceforge.squirrel_sql.fw.util.StringManagerFactory;
0056:
0057:        /**
0058:         * @author gwg
0059:         *
0060:         * This class provides the display components for handling String data types,
0061:         * specifically SQL types CHAR, VARCHAR, and LONGVARCHAR.
0062:         * The display components are for:
0063:         * <UL>
0064:         * <LI> read-only display within a table cell
0065:         * <LI> editing within a table cell
0066:         * <LI> read-only or editing display within a separate window
0067:         * </UL>
0068:         * The class also contains 
0069:         * <UL>
0070:         * <LI> a function to compare two display values
0071:         * to see if they are equal.  This is needed because the display format
0072:         * may not be the same as the internal format, and all internal object
0073:         * types may not provide an appropriate equals() function.
0074:         * <LI> a function to return a printable text form of the cell contents,
0075:         * which is used in the text version of the table.
0076:         * </UL>
0077:         * <P>
0078:         * The components returned from this class extend RestorableJTextField
0079:         * and RestorableJTextArea for use in editing table cells that
0080:         * contain values of this data type.  It provides the special behavior for null
0081:         * handling and resetting the cell to the original value.
0082:         */
0083:        public class DataTypeString extends BaseDataTypeComponent implements 
0084:                IDataTypeComponent {
0085:            private static final StringManager s_stringMgr = StringManagerFactory
0086:                    .getStringManager(DataTypeString.class);
0087:
0088:            /* whether nulls are allowed or not */
0089:            private boolean _isNullable;
0090:
0091:            /* the number of characters allowed in this field */
0092:            private int _columnSize;
0093:
0094:            /* table of which we are part (needed for creating popup dialog) */
0095:            private JTable _table;
0096:
0097:            /* The JTextComponent that is being used for editing */
0098:            private IRestorableTextComponent _textComponent;
0099:
0100:            /* The CellRenderer used for this data type */
0101:            //??? For now, use the same renderer as everyone else.
0102:            //??
0103:            //?? IN FUTURE: change this to use a new instance of renederer
0104:            //?? for this data type.
0105:            private DefaultColumnRenderer _renderer = DefaultColumnRenderer
0106:                    .getInstance();
0107:
0108:            /**
0109:             * default length of strings when truncated
0110:             */
0111:            private final static int DEFAULT_LIMIT_READ_LENGTH = 100;
0112:
0113:            /**
0114:             * Name of this class, which is needed because the class name is needed
0115:             * by the static method getControlPanel, so we cannot use something
0116:             * like getClass() to find this name.
0117:             */
0118:            private static final String this ClassName = "net.sourceforge.squirrel_sql.fw.datasetviewer.cellcomponent.DataTypeString";
0119:
0120:            /*
0121:             * Properties settable by the user
0122:             */
0123:            // flag for whether we have already loaded the properties or not
0124:            private static boolean propertiesAlreadyLoaded = false;
0125:
0126:            /**
0127:             * If <tt>true</tt> then show newlines as "\n" for the in-cell display,
0128:             * otherwise do not display newlines in the in-cell display
0129:             * (i.e. they are thrown out by JTextField when it loads the text document behind the cell).
0130:             */
0131:            private static boolean _makeNewlinesVisibleInCell = true;
0132:
0133:            /**
0134:             * If <tt>true</tt> then use the LONGVARCHAR data type in the WHERE clause,
0135:             * otherwise do not include it.
0136:             * Oracle does not allow that type to be used in a WHERE clause
0137:             */
0138:            private static boolean _useLongInWhere = true;
0139:
0140:            /**
0141:             * If <tt>true</tt> then limit the size of string data that is read
0142:             * during the initial table load.
0143:             */
0144:            private static boolean _limitRead = false;
0145:
0146:            /**
0147:             * If <tt>_limitRead</tt> is <tt>true</tt> then this is how many characters
0148:             * to read during the initial table load.
0149:             */
0150:            private static int _limitReadLength = DEFAULT_LIMIT_READ_LENGTH;
0151:
0152:            /**
0153:             * If <tt>_limitRead</tt> is <tt>true</tt> and
0154:             * this is <tt>true</tt>, then only columns whose label is listed in
0155:             * <tt>_limitReadColumnList</tt> are limited.
0156:             */
0157:            private static boolean _limitReadOnSpecificColumns = false;
0158:
0159:            /**
0160:             * If <tt>_limitRead</tt> is <tt>true</tt> and
0161:             * <tt>_limitReadOnSpecificColumns is <tt>true</tt>, then only columns whose label is listed here.
0162:             * The column names are converted to ALL CAPS before being put on this list
0163:             * so that they will match the label retrieved from _colDef.
0164:             */
0165:            private static HashMap<String, String> _limitReadColumnNameMap = new HashMap<String, String>();
0166:
0167:            /**
0168:             * Constructor - save the data needed by this data type.
0169:             */
0170:            public DataTypeString(JTable table, ColumnDisplayDefinition colDef) {
0171:                _table = table;
0172:                _colDef = colDef;
0173:                _isNullable = colDef.isNullable();
0174:                _columnSize = colDef.getColumnSize();
0175:
0176:                loadProperties();
0177:            }
0178:
0179:            /**
0180:             * For sub-classes
0181:             */
0182:            protected DataTypeString() {
0183:
0184:            }
0185:
0186:            /** Internal function to get the user-settable properties from the DTProperties,
0187:             * if they exist, and to ensure that defaults are set if the properties have
0188:             * not yet been created.
0189:             * <P>
0190:             * This method may be called from different places depending on whether
0191:             * an instance of this class is created before the user brings up the Session
0192:             * Properties window.  In either case, the data is static and is set only
0193:             * the first time we are called.
0194:             */
0195:            private static void loadProperties() {
0196:
0197:                if (propertiesAlreadyLoaded == false) {
0198:                    // get parameters previously set by user, or set default values
0199:                    _makeNewlinesVisibleInCell = true; // set to the default
0200:                    String makeNewlinesVisibleString = DTProperties.get(
0201:                            this ClassName, "makeNewlinesVisibleInCell");
0202:                    if (makeNewlinesVisibleString != null
0203:                            && makeNewlinesVisibleString.equals("false"))
0204:                        _makeNewlinesVisibleInCell = false;
0205:
0206:                    _useLongInWhere = true; // set to the default
0207:                    String useLongInWhereString = DTProperties.get(
0208:                            this ClassName, "useLongInWhere");
0209:                    if (useLongInWhereString != null
0210:                            && useLongInWhereString.equals("false"))
0211:                        _useLongInWhere = false;
0212:
0213:                    _limitRead = false; // set to default
0214:                    String limitReadString = DTProperties.get(this ClassName,
0215:                            "limitRead");
0216:                    if (limitReadString != null
0217:                            && limitReadString.equals("true"))
0218:                        _limitRead = true;
0219:
0220:                    _limitReadLength = DEFAULT_LIMIT_READ_LENGTH; // set to default
0221:                    String limitReadLengthString = DTProperties.get(
0222:                            this ClassName, "limitReadLength");
0223:                    if (limitReadLengthString != null)
0224:                        _limitReadLength = Integer
0225:                                .parseInt(limitReadLengthString);
0226:
0227:                    _limitReadOnSpecificColumns = false; // set to default
0228:                    String limitReadOnSpecificColumnsString = DTProperties.get(
0229:                            this ClassName, "limitReadOnSpecificColumns");
0230:                    if (limitReadOnSpecificColumnsString != null
0231:                            && limitReadOnSpecificColumnsString.equals("true"))
0232:                        _limitReadOnSpecificColumns = true;
0233:
0234:                    // the list of specific column names is in comma-separated format
0235:                    // with a comma in front of the first entry as well
0236:                    _limitReadColumnNameMap.clear(); // empty the map of old values
0237:
0238:                    String nameString = DTProperties.get(this ClassName,
0239:                            "limitReadColumnNames");
0240:                    int start = 0;
0241:                    int end;
0242:                    String name;
0243:
0244:                    while (nameString != null && start < nameString.length()) {
0245:                        end = nameString.indexOf(',', start + 1);
0246:                        if (end > -1) {
0247:                            name = nameString.substring(start + 1, end);
0248:                            start = end;
0249:                        } else {
0250:                            name = nameString.substring(start + 1);
0251:                            start = nameString.length();
0252:                        }
0253:
0254:                        _limitReadColumnNameMap.put(name, null);
0255:                    }
0256:
0257:                    propertiesAlreadyLoaded = true;
0258:                }
0259:            }
0260:
0261:            /**
0262:             * Return the name of the java class used to hold this data type.
0263:             */
0264:            public String getClassName() {
0265:                return "java.lang.String";
0266:            }
0267:
0268:            /**
0269:             * Determine if two objects of this data type contain the same value.
0270:             * Neither of the objects is null
0271:             */
0272:            public boolean areEqual(Object obj1, Object obj2) {
0273:                return ((String) obj1).equals(obj2);
0274:            }
0275:
0276:            /*
0277:             * First we have the cell-related and Text-table operations.
0278:             */
0279:
0280:            /**
0281:             * Render a value into text for this DataType.
0282:             */
0283:            public String renderObject(Object value) {
0284:                String text = (String) _renderer.renderObject(value);
0285:                if (_makeNewlinesVisibleInCell) {
0286:                    text = text.replaceAll("\n", "/\\n");
0287:                }
0288:                return text;
0289:            }
0290:
0291:            /**
0292:             * This Data Type can be edited in a table cell.
0293:             * <P>
0294:             * If the data includes newlines, the user must not be allowed to edit it
0295:             * in the cell because the CellEditor uses a JTextField which filters out newlines.
0296:             * If we try to use anything other than a JTextField, or use a JTextField with no
0297:             * newline filtering, the text is not visible in the cell, so the user cannot even read
0298:             * the text, much less edit it.  The simplest solution is to allow editing of multi-line
0299:             * text only in the Popup window.
0300:             */
0301:            public boolean isEditableInCell(Object originalValue) {
0302:                //			prevent editing if text contains newlines
0303:                if (originalValue != null
0304:                        && ((String) originalValue).indexOf('\n') > -1)
0305:                    return false;
0306:                else
0307:                    return true;
0308:            }
0309:
0310:            /**
0311:             * See if a value in a column has been limited in some way and
0312:             * needs to be re-read before being used for editing.
0313:             * For read-only tables this may actually return true since we want
0314:             * to be able to view the entire contents of the cell even if it was not
0315:             * completely loaded during the initial table setup.
0316:             */
0317:            public boolean needToReRead(Object originalValue) {
0318:                // if we are not limiting anything, return false
0319:                if (_limitRead == false)
0320:                    return false;
0321:
0322:                // if the value is null, then it was read ok
0323:                if (originalValue == null)
0324:                    return false;
0325:
0326:                // we are limiting some things.
0327:                // if the string we have is less than the limit, then we are ok
0328:                // and do not need to re-read (because we already have the whole thing).
0329:                if (((String) originalValue).length() < _limitReadLength)
0330:                    return false;
0331:
0332:                // if the data is longer than the limit, then we have previously
0333:                // re-read the contents and we do not need to re-read it again
0334:                if (((String) originalValue).length() > _limitReadLength)
0335:                    return false;
0336:
0337:                // if we are limiting all columns, then we need to re-read
0338:                // because we do not know if we have all the data or not
0339:                if (_limitReadOnSpecificColumns == false)
0340:                    return true;
0341:
0342:                // check for the case where we are limiting some columns
0343:                // but not limiting this particular column
0344:                if (_limitReadColumnNameMap.containsKey(_colDef.getLabel()))
0345:                    return true; // column is limited and length == limit, so need to re-read
0346:                else
0347:                    return false; // column is not limited, so we have the whole thing
0348:            }
0349:
0350:            /**
0351:             * Return a JTextField usable in a CellEditor.
0352:             */
0353:            public JTextField getJTextField() {
0354:                _textComponent = new RestorableJTextField();
0355:
0356:                // special handling of operations while editing this data type
0357:                ((RestorableJTextField) _textComponent)
0358:                        .addKeyListener(new KeyTextHandler());
0359:
0360:                //
0361:                // handle mouse events for double-click creation of popup dialog.
0362:                // This happens only in the JTextField, not the JTextArea, so we can
0363:                // make this an inner class within this method rather than a separate
0364:                // inner class as is done with the KeyTextHandler class.
0365:                //
0366:                ((RestorableJTextField) _textComponent)
0367:                        .addMouseListener(new MouseAdapter() {
0368:                            public void mousePressed(MouseEvent evt) {
0369:                                if (evt.getClickCount() == 2) {
0370:                                    MouseEvent tableEvt = SwingUtilities
0371:                                            .convertMouseEvent(
0372:                                                    (RestorableJTextField) DataTypeString.this ._textComponent,
0373:                                                    evt,
0374:                                                    DataTypeString.this ._table);
0375:                                    CellDataPopup.showDialog(
0376:                                            DataTypeString.this ._table,
0377:                                            DataTypeString.this ._colDef,
0378:                                            tableEvt, true);
0379:                                }
0380:                            }
0381:                        }); // end of mouse listener
0382:
0383:                return (JTextField) _textComponent;
0384:            }
0385:
0386:            /**
0387:             * Implement the interface for validating and converting to internal object.
0388:             * Null is a valid successful return, so errors are indicated only by
0389:             * existance or not of a message in the messageBuffer.
0390:             */
0391:            public Object validateAndConvert(String value,
0392:                    Object originalValue, StringBuffer messageBuffer) {
0393:                // handle null, which is shown as the special string "<null>"
0394:                if (value.equals("<null>"))
0395:                    return null;
0396:
0397:                // Do the conversion into the object in a safe manner
0398:                return value; // Special case: the input is exactly the output
0399:            }
0400:
0401:            /**
0402:             * If true, this tells the PopupEditableIOPanel to use the
0403:             * binary editing panel rather than a pure text panel.
0404:             * The binary editing panel assumes the data is an array of bytes,
0405:             * converts it into text form, allows the user to change how that
0406:             * data is displayed (e.g. Hex, Decimal, etc.), and converts
0407:             * the data back from text to bytes when the user editing is completed.
0408:             * If this returns false, this DataType class must
0409:             * convert the internal data into a text string that
0410:             * can be displayed (and edited, if allowed) in a TextField
0411:             * or TextArea, and must handle all
0412:             * user key strokes related to editing of that data.
0413:             */
0414:            public boolean useBinaryEditingPanel() {
0415:                return false;
0416:            }
0417:
0418:            /*
0419:             * Now define the Popup-related operations.
0420:             */
0421:
0422:            /**
0423:             * Returns true if data type may be edited in the popup,
0424:             * false if not.
0425:             */
0426:            public boolean isEditableInPopup(Object originalValue) {
0427:                // The only thing that would prevent us from editing a string in the popup
0428:                // is if that string has been truncated when read from the DB.
0429:                // Thus, being able to edit the string is the same as not needing to re-read
0430:                // the data.
0431:                return !needToReRead(originalValue);
0432:            }
0433:
0434:            /*
0435:             * Return a JTextArea usable in the CellPopupDialog.
0436:             */
0437:            public JTextArea getJTextArea(Object value) {
0438:                _textComponent = new RestorableJTextArea();
0439:
0440:                // value is a simple string representation of the data,
0441:                // but NOT the same one used in the Text and in-cell operations.
0442:                // The in-cell version may replace newline chars with "\n" while this version
0443:                // does not.  In other respects it is the same as the in-cell version because both
0444:                // use the _renderer object to do the rendering.
0445:                ((RestorableJTextArea) _textComponent)
0446:                        .setText((String) _renderer.renderObject(value));
0447:
0448:                // special handling of operations while editing this data type
0449:                ((RestorableJTextArea) _textComponent)
0450:                        .addKeyListener(new KeyTextHandler());
0451:
0452:                return (RestorableJTextArea) _textComponent;
0453:            }
0454:
0455:            /**
0456:             * Validating and converting in Popup is identical to cell-related operation.
0457:             */
0458:            public Object validateAndConvertInPopup(String value,
0459:                    Object originalValue, StringBuffer messageBuffer) {
0460:                return validateAndConvert(value, originalValue, messageBuffer);
0461:            }
0462:
0463:            /*
0464:             * The following is used by both in-cell and Popup operations.
0465:             */
0466:
0467:            /*
0468:             * Internal class for handling key events during editing
0469:             * of both JTextField and JTextArea.
0470:             */
0471:            private class KeyTextHandler extends BaseKeyTextHandler {
0472:                // special handling of operations while editing Strings
0473:                public void keyTyped(KeyEvent e) {
0474:                    char c = e.getKeyChar();
0475:
0476:                    // as a coding convenience, create a reference to the text component
0477:                    // that is typecast to JTextComponent.  this is not essential, as we
0478:                    // could typecast every reference, but this makes the code cleaner
0479:                    JTextComponent _theComponent = (JTextComponent) DataTypeString.this ._textComponent;
0480:                    String text = _theComponent.getText();
0481:
0482:                    //?? Is there any way to check for invalid input?  Valid input includes
0483:                    //?? at least any printable character, but could it also include unprintable
0484:                    //?? characters?
0485:
0486:                    // check for max size reached (only works when DB provides non-zero scale info
0487:                    if (DataTypeString.this ._columnSize > 0
0488:                            && text.length() >= DataTypeString.this ._columnSize
0489:                            && c != KeyEvent.VK_BACK_SPACE
0490:                            && c != KeyEvent.VK_DELETE) {
0491:                        // max size reached
0492:                        e.consume();
0493:                        _theComponent.getToolkit().beep();
0494:
0495:                        // Note: tabs and newlines are allowed in string fields, even though they are unusual.
0496:                    }
0497:
0498:                    // handle cases of null
0499:                    // The processing is different when nulls are allowed and when they are not.
0500:                    //
0501:
0502:                    if (DataTypeString.this ._isNullable) {
0503:
0504:                        // user enters something when field is null
0505:                        if (text.equals("<null>")) {
0506:                            if ((c == KeyEvent.VK_BACK_SPACE)
0507:                                    || (c == KeyEvent.VK_DELETE)) {
0508:                                // delete when null => original value
0509:                                DataTypeString.this ._textComponent
0510:                                        .restoreText();
0511:                                e.consume();
0512:                            } else {
0513:                                // non-delete when null => clear field and add text
0514:                                DataTypeString.this ._textComponent
0515:                                        .updateText("");
0516:                                // fall through to normal processing of this key stroke
0517:                            }
0518:                        } else {
0519:                            // for strings, a "blank" field is allowed, so only
0520:                            // switch to null when there is nothing left in the field
0521:                            // and user does delete
0522:                            if ((c == KeyEvent.VK_BACK_SPACE)
0523:                                    || (c == KeyEvent.VK_DELETE)) {
0524:                                if (text.length() == 0) {
0525:                                    // about to delete last thing in field, so replace with null
0526:                                    DataTypeString.this ._textComponent
0527:                                            .updateText("<null>");
0528:                                    e.consume();
0529:                                }
0530:                            }
0531:                        }
0532:                    } else {
0533:                        // field is not nullable
0534:                        //
0535:                        handleNotNullableField(text, c, e, _textComponent);
0536:                    }
0537:                }
0538:            }
0539:
0540:            /*
0541:             * DataBase-related functions
0542:             */
0543:
0544:            /**
0545:             * On input from the DB, read the data from the ResultSet into the appropriate
0546:             * type of object to be stored in the table cell.
0547:             */
0548:            public Object readResultSet(ResultSet rs, int index,
0549:                    boolean limitDataRead) throws java.sql.SQLException {
0550:
0551:                String data = rs.getString(index);
0552:                if (rs.wasNull())
0553:                    return null;
0554:                else {
0555:                    // if this column is being limited, then truncate the data if needed
0556:                    // (start with a quick check for the data being shorter than the limit,
0557:                    // in which case we don't need to worry about it).
0558:                    if (limitDataRead == true && _limitRead == true
0559:                            && data.length() >= _limitReadLength) {
0560:
0561:                        // data is longer than the limit, so we need to do more checking
0562:                        if (_limitReadOnSpecificColumns == false
0563:                                || (_limitReadOnSpecificColumns == true && _limitReadColumnNameMap
0564:                                        .containsKey(_colDef.getLabel()))) {
0565:                            // this column is limited, so truncate the data
0566:                            data = data.substring(0, _limitReadLength);
0567:                        }
0568:
0569:                    }
0570:                    return data;
0571:
0572:                }
0573:            }
0574:
0575:            /**
0576:             * When updating the database, generate a string form of this object value
0577:             * that can be used in the WHERE clause to match the value in the database.
0578:             * A return value of null means that this column cannot be used in the WHERE
0579:             * clause, while a return of "null" (or "is null", etc) means that the column
0580:             * can be used in the WHERE clause and the value is actually a null value.
0581:             * This function must also include the column label so that its output
0582:             * is of the form:
0583:             * 	"columnName = value"
0584:             * or
0585:             * 	"columnName is null"
0586:             * or whatever is appropriate for this column in the database.
0587:             */
0588:            public String getWhereClauseValue(Object value,
0589:                    ISQLDatabaseMetaData md) {
0590:                // first do special check to see if we should use LONGVARCHAR
0591:                // in the WHERE clause.
0592:                // (Oracle does not allow this.)
0593:                if (_colDef.getSqlType() == Types.LONGVARCHAR
0594:                        && _useLongInWhere == false)
0595:                    return ""; // this column cannot be used in a WHERE clause
0596:
0597:                if (value == null || value.toString() == null)
0598:                    return _colDef.getLabel() + " IS NULL";
0599:                else {
0600:                    // We cannot use this data in the WHERE clause if it has been truncated.
0601:                    // Since being truncated is the same as needing to re-read,
0602:                    // only use this in the WHERE clause if we do not need to re-read
0603:                    if (!needToReRead(value))
0604:                        return _colDef.getLabel() + "='"
0605:                                + escapeLine(value.toString(), md) + "'";
0606:                    else
0607:                        return ""; // value is truncated, so do not use in WHERE clause
0608:                }
0609:            }
0610:
0611:            /**
0612:             * When updating the database, insert the appropriate datatype into the
0613:             * prepared statment at the given variable position.
0614:             */
0615:            public void setPreparedStatementValue(PreparedStatement pstmt,
0616:                    Object value, int position) throws java.sql.SQLException {
0617:                if (value == null) {
0618:                    pstmt.setNull(position, _colDef.getSqlType());
0619:                } else {
0620:                    pstmt.setString(position, ((String) value));
0621:                }
0622:            }
0623:
0624:            /**
0625:             * Get a default value for the table used to input data for a new row
0626:             * to be inserted into the DB.
0627:             */
0628:            public Object getDefaultValue(String dbDefaultValue) {
0629:                if (dbDefaultValue != null) {
0630:                    // try to use the DB default value
0631:                    StringBuffer mbuf = new StringBuffer();
0632:                    Object newObject = validateAndConvert(dbDefaultValue, null,
0633:                            mbuf);
0634:
0635:                    // if there was a problem with converting, then just fall through
0636:                    // and continue as if there was no default given in the DB.
0637:                    // Otherwise, use the converted object
0638:                    if (mbuf.length() == 0)
0639:                        return newObject;
0640:                }
0641:
0642:                // no default in DB.  If nullable, use null.
0643:                if (_isNullable)
0644:                    return null;
0645:
0646:                // field is not nullable, so create a reasonable default value
0647:                return "";
0648:            }
0649:
0650:            /**
0651:             * When strings are used in the WHERE clause, any single quote characters must be
0652:             * "escaped" so that they are not confused with the "end of string"
0653:             * single quote used by SQL.  The escape sequence is that a single quote
0654:             * is represented by two single quotes in a row.
0655:             */
0656:            static public String escapeLine(String s, ISQLDatabaseMetaData md) {
0657:                String retvalue = s;
0658:                if (s.indexOf("'") != -1) {
0659:                    StringBuffer hold = new StringBuffer();
0660:                    char c;
0661:                    for (int i = 0; i < s.length(); i++) {
0662:                        if ((c = s.charAt(i)) == '\'') {
0663:                            hold.append("''");
0664:                        } else {
0665:                            hold.append(c);
0666:                        }
0667:                    }
0668:                    retvalue = hold.toString();
0669:                }
0670:                return DatabaseSpecificEscape.escapeSQL(retvalue, md);
0671:            }
0672:
0673:            /*
0674:             * File IO related functions
0675:             */
0676:
0677:            /**
0678:             * Say whether or not object can be exported to and imported from
0679:             * a file.  We put both export and import together in one test
0680:             * on the assumption that all conversions can be done both ways.
0681:             */
0682:            public boolean canDoFileIO() {
0683:                return true;
0684:            }
0685:
0686:            /**
0687:             * Read a file and construct a valid object from its contents.
0688:             * Errors are returned by throwing an IOException containing the
0689:             * cause of the problem as its message.
0690:             * <P>
0691:             * DataType is responsible for validating that the imported
0692:             * data can be converted to an object, and then must return
0693:             * a text string that can be used in the Popup window text area.
0694:             * This object-to-text conversion is the same as is done by
0695:             * the DataType object internally in the getJTextArea() method.
0696:             * 
0697:             * <P>
0698:             * File is assumed to be printable text characters,
0699:             * possibly including newlines and tabs but not characters
0700:             * that would require a binary representation to display
0701:             * to user.
0702:             */
0703:            public String importObject(FileInputStream inStream)
0704:                    throws IOException {
0705:
0706:                InputStreamReader inReader = new InputStreamReader(inStream);
0707:
0708:                int fileSize = inStream.available();
0709:
0710:                char charBuf[] = new char[fileSize];
0711:
0712:                int count = inReader.read(charBuf, 0, fileSize);
0713:
0714:                if (count != fileSize)
0715:                    throw new IOException("Could read only " + count
0716:                            + " chars from a total file size of " + fileSize
0717:                            + ". Import failed.");
0718:
0719:                // convert to string
0720:                // Special case: some systems tack a newline at the end of
0721:                // the text read.  Assume that if last char is a newline that
0722:                // we want everything else in the line.
0723:                String fileText;
0724:                if (charBuf[count - 1] == KeyEvent.VK_ENTER)
0725:                    fileText = new String(charBuf, 0, count - 1);
0726:                else
0727:                    fileText = new String(charBuf);
0728:
0729:                // data must fit into the column's max size
0730:                if (_columnSize > 0 && fileText.length() > _columnSize)
0731:                    throw new IOException(
0732:                            "File contains "
0733:                                    + fileText.length()
0734:                                    + " characters which exceeds this column's limit of "
0735:                                    + _columnSize + ".\nImport Aborted.");
0736:
0737:                return fileText;
0738:            }
0739:
0740:            /**
0741:             * Construct an appropriate external representation of the object
0742:             * and write it to a file.
0743:             * Errors are returned by throwing an IOException containing the
0744:             * cause of the problem as its message.
0745:             * <P>
0746:             * DataType is responsible for validating that the given text
0747:             * text from a Popup JTextArea can be converted to an object.
0748:             * This text-to-object conversion is the same as validateAndConvertInPopup,
0749:             * which may be used internally by the object to do the validation.
0750:             * <P>
0751:             * The DataType object must flush and close the output stream before returning.
0752:             * Typically it will create another object (e.g. an OutputWriter), and
0753:             * that is the object that must be flushed and closed.
0754:             * 
0755:             * <P>
0756:             * File is assumed to be printable text characters,
0757:             * possibly including newlines and tabs but not characters
0758:             * that would require a binary representation to display
0759:             * to user.
0760:             */
0761:            public void exportObject(FileOutputStream outStream, String text)
0762:                    throws IOException {
0763:
0764:                OutputStreamWriter outWriter = new OutputStreamWriter(outStream);
0765:
0766:                // for string, just send the text to the output file
0767:                outWriter.write(text);
0768:                outWriter.flush();
0769:                outWriter.close();
0770:            }
0771:
0772:            /*
0773:             * Property change control panel
0774:             */
0775:
0776:            /**
0777:             * Generate a JPanel containing controls that allow the user
0778:             * to adjust the properties for this DataType.
0779:             * All properties are static accross all instances of this DataType. 
0780:             * However, the class may choose to apply the information differentially,
0781:             * such as keeping a list (also entered by the user) of table/column names
0782:             * for which certain properties should be used.
0783:             * <P>
0784:             * This is called ONLY if there is at least one property entered into the DTProperties
0785:             * for this class.
0786:             * <P>
0787:             * Since this method is called by reflection on the Method object derived from this class,
0788:             * it does not need to be included in the Interface.
0789:             * It would be nice to include this in the Interface for consistancy, documentation, etc,
0790:             * but the Interface does not seem to like static methods.
0791:             */
0792:            public static OkJPanel getControlPanel() {
0793:
0794:                /*
0795:                 * If you add this method to one of the standard DataTypes in the
0796:                 * fw/datasetviewer/cellcomponent directory, you must also add the name
0797:                 * of that DataType class to the list in CellComponentFactory, method
0798:                 * getControlPanels, variable named initialClassNameList.
0799:                 * If the class is being registered with the factory using registerDataType,
0800:                 * then you should not include the class name in the list (it will be found
0801:                 * automatically), but if the DataType is part of the case statement in the
0802:                 * factory method getDataTypeObject, then it does need to be explicitly listed
0803:                 * in the getControlPanels method also.
0804:                 */
0805:
0806:                // if this panel is called before any instances of the class have been
0807:                // created, we need to load the properties from the DTProperties.
0808:                loadProperties();
0809:
0810:                return new ClobOkJPanel();
0811:            }
0812:
0813:            /**
0814:             * Inner class that extends OkJPanel so that we can call the ok()
0815:             * method to save the data when the user is happy with it.
0816:             */
0817:            private static class ClobOkJPanel extends OkJPanel {
0818:                /*
0819:                 * GUI components - need to be here because they need to be
0820:                 * accessible from the event handlers to alter each other's state.
0821:                 */
0822:
0823:                private static final long serialVersionUID = -578848466466561988L;
0824:
0825:                // check box for whether to show newlines as "\n" for in-cell display
0826:                private JCheckBox _makeNewlinesVisibleInCellChk =
0827:                // i18n[dataTypeString.newlines=Show newlines as \\n within cells]
0828:                new JCheckBox(s_stringMgr.getString("dataTypeString.newlines"));
0829:
0830:                // check box for whether to use LONGVARCHAR in WHERE clause
0831:                // (Oracle does not allow that type in WHERE clause)
0832:                private JCheckBox _useLongInWhereChk =
0833:                // i18n[dataTypeString.allowLongVarchar=Allow LONGVARCHAR type to be used in WHERE clause]
0834:                new JCheckBox(s_stringMgr
0835:                        .getString("dataTypeString.allowLongVarchar"));
0836:
0837:                // check box for whether to do any limiting of the data read during initial table load
0838:                private JCheckBox _limitReadChk =
0839:                // i18n[dataTypeString.limitSize=Limit size of strings read during initial table load to max of:]
0840:                new JCheckBox(s_stringMgr.getString("dataTypeString.limitSize"));
0841:
0842:                // check box for whether to show newlines as "\n" for in-cell display
0843:                private IntegerField _limitReadLengthTextField = new IntegerField(
0844:                        5);
0845:
0846:                // check box for whether to show newlines as "\n" for in-cell display
0847:                private JCheckBox _limitReadOnSpecificColumnsChk =
0848:                // i18n[dataTypeString.limitReadOnly=Limit read only on columns with these names:]
0849:                new JCheckBox(s_stringMgr
0850:                        .getString("dataTypeString.limitReadOnly"));
0851:
0852:                // check box for whether to show newlines as "\n" for in-cell display
0853:                private JTextArea _limitReadColumnNameTextArea = new JTextArea(
0854:                        5, 12);
0855:
0856:                public ClobOkJPanel() {
0857:
0858:                    /* set up the controls */
0859:
0860:                    // checkbox for displaying newlines as \n in-cell
0861:                    _makeNewlinesVisibleInCellChk
0862:                            .setSelected(_makeNewlinesVisibleInCell);
0863:
0864:                    // checkbox for using LONG in WHERE clause
0865:                    _useLongInWhereChk.setSelected(_useLongInWhere);
0866:
0867:                    // checkbox for limit/no-limit on data read during initial table load
0868:                    _limitReadChk.setSelected(_limitRead);
0869:                    _limitReadChk.addChangeListener(new ChangeListener() {
0870:                        public void stateChanged(ChangeEvent e) {
0871:                            _limitReadLengthTextField.setEnabled(_limitReadChk
0872:                                    .isSelected());
0873:                            _limitReadOnSpecificColumnsChk
0874:                                    .setEnabled(_limitReadChk.isSelected());
0875:                            _limitReadColumnNameTextArea
0876:                                    .setEnabled(_limitReadChk.isSelected()
0877:                                            && (_limitReadOnSpecificColumnsChk
0878:                                                    .isSelected()));
0879:                        }
0880:                    });
0881:
0882:                    // fill in the current limit length
0883:                    _limitReadLengthTextField.setInt(_limitReadLength);
0884:
0885:                    // set the flag for whether or not to limit only on specific fields
0886:                    _limitReadOnSpecificColumnsChk
0887:                            .setSelected(_limitReadOnSpecificColumns);
0888:                    _limitReadOnSpecificColumnsChk
0889:                            .addChangeListener(new ChangeListener() {
0890:                                public void stateChanged(ChangeEvent e) {
0891:                                    _limitReadColumnNameTextArea
0892:                                            .setEnabled(_limitReadOnSpecificColumnsChk
0893:                                                    .isSelected());
0894:                                }
0895:                            });
0896:
0897:                    // fill in list of column names to check against
0898:                    Iterator<String> names = _limitReadColumnNameMap.keySet()
0899:                            .iterator();
0900:                    StringBuffer namesText = new StringBuffer();
0901:                    while (names.hasNext()) {
0902:                        if (namesText.length() > 0)
0903:                            namesText.append("\n" + names.next());
0904:                        else
0905:                            namesText.append(names.next());
0906:                    }
0907:                    _limitReadColumnNameTextArea.setText(namesText.toString());
0908:
0909:                    // handle cross-connection between fields
0910:                    _limitReadLengthTextField.setEnabled(_limitReadChk
0911:                            .isSelected());
0912:                    _limitReadOnSpecificColumnsChk.setEnabled(_limitReadChk
0913:                            .isSelected());
0914:                    _limitReadColumnNameTextArea.setEnabled(_limitReadChk
0915:                            .isSelected()
0916:                            && (_limitReadOnSpecificColumnsChk.isSelected()));
0917:                    ;
0918:
0919:                    /*
0920:                     * Create the panel and add the GUI items to it
0921:                     */
0922:
0923:                    setLayout(new GridBagLayout());
0924:
0925:                    setBorder(BorderFactory.createTitledBorder(
0926:                    // i18n[dataTypeString.typeChar=CHAR, VARCHAR, LONGVARCHAR   (SQL types 1, 12, -1)]
0927:                            s_stringMgr.getString("dataTypeString.typeChar")));
0928:                    final GridBagConstraints gbc = new GridBagConstraints();
0929:                    gbc.fill = GridBagConstraints.HORIZONTAL;
0930:                    gbc.insets = new Insets(4, 4, 4, 4);
0931:                    gbc.anchor = GridBagConstraints.WEST;
0932:
0933:                    gbc.gridx = 0;
0934:                    gbc.gridy = 0;
0935:
0936:                    gbc.gridwidth = GridBagConstraints.REMAINDER;
0937:                    add(_makeNewlinesVisibleInCellChk, gbc);
0938:
0939:                    gbc.gridx = 0;
0940:                    gbc.gridy++;
0941:                    gbc.gridwidth = GridBagConstraints.REMAINDER;
0942:                    add(_useLongInWhereChk, gbc);
0943:
0944:                    gbc.gridy++;
0945:                    gbc.gridx = 0;
0946:                    gbc.gridwidth = 1;
0947:                    add(_limitReadChk, gbc);
0948:
0949:                    gbc.gridx++;
0950:                    gbc.gridwidth = 1;
0951:                    add(_limitReadLengthTextField, gbc);
0952:
0953:                    gbc.gridy++;
0954:                    gbc.gridx = 0;
0955:                    gbc.gridwidth = 1;
0956:                    add(_limitReadOnSpecificColumnsChk, gbc);
0957:
0958:                    gbc.gridx++;
0959:                    gbc.gridwidth = GridBagConstraints.REMAINDER;
0960:                    JScrollPane scrollPane = new JScrollPane();
0961:
0962:                    // If we don't always show the scrollbars the whole DataTypePreferencesPanel is flickering like hell.
0963:                    scrollPane
0964:                            .setHorizontalScrollBarPolicy(JScrollPane.HORIZONTAL_SCROLLBAR_ALWAYS);
0965:                    scrollPane
0966:                            .setVerticalScrollBarPolicy(JScrollPane.VERTICAL_SCROLLBAR_ALWAYS);
0967:
0968:                    scrollPane.setViewportView(_limitReadColumnNameTextArea);
0969:                    add(scrollPane, gbc);
0970:
0971:                } // end of constructor for inner class
0972:
0973:                /**
0974:                 * User has clicked OK in the surrounding JPanel,
0975:                 * so save the current state of all variables
0976:                 */
0977:                public void ok() {
0978:                    // get the values from the controls and set them in the static properties
0979:                    _makeNewlinesVisibleInCell = _makeNewlinesVisibleInCellChk
0980:                            .isSelected();
0981:                    DTProperties.put(this ClassName,
0982:                            "makeNewlinesVisibleInCell", Boolean.valueOf(
0983:                                    _makeNewlinesVisibleInCell).toString());
0984:
0985:                    _useLongInWhere = _useLongInWhereChk.isSelected();
0986:                    DTProperties.put(this ClassName, "useLongInWhere", Boolean
0987:                            .valueOf(_useLongInWhere).toString());
0988:
0989:                    _limitRead = _limitReadChk.isSelected();
0990:                    DTProperties.put(this ClassName, "limitRead", Boolean
0991:                            .valueOf(_limitRead).toString());
0992:
0993:                    _limitReadLength = _limitReadLengthTextField.getInt();
0994:                    DTProperties.put(this ClassName, "limitReadLength", Integer
0995:                            .toString(_limitReadLength));
0996:
0997:                    _limitReadOnSpecificColumns = _limitReadOnSpecificColumnsChk
0998:                            .isSelected();
0999:                    DTProperties.put(this ClassName,
1000:                            "limitReadOnSpecificColumns", Boolean.valueOf(
1001:                                    _limitReadOnSpecificColumns).toString());
1002:
1003:                    // Handle list of column names
1004:
1005:                    // remove old name list from map
1006:                    _limitReadColumnNameMap.clear();
1007:                    // extract column names from text area
1008:                    String columnNameText = _limitReadColumnNameTextArea
1009:                            .getText();
1010:
1011:                    int start = 0;
1012:                    int end;
1013:                    String name;
1014:                    String propertyString = "";
1015:
1016:                    while (start < columnNameText.length()) {
1017:                        // find the next name in the text
1018:                        end = columnNameText.indexOf('\n', start + 1);
1019:                        if (end > -1) {
1020:                            name = columnNameText.substring(start, end);
1021:                            start = end;
1022:                        } else {
1023:                            name = columnNameText.substring(start);
1024:                            start = columnNameText.length();
1025:                        }
1026:
1027:                        // cleanup and standardize the name, and add it to the map
1028:                        name = name.trim().toUpperCase();
1029:                        if (name.length() == 0)
1030:                            continue; // skip blank lines
1031:
1032:                        _limitReadColumnNameMap.put(name.trim().toUpperCase(),
1033:                                null);
1034:
1035:                        // add name to comma-separated string for saving in properties
1036:                        propertyString += "," + name.trim().toUpperCase();
1037:                    } // end while
1038:
1039:                    DTProperties.put(this ClassName, "limitReadColumnNames",
1040:                            propertyString);
1041:
1042:                } // end ok
1043:
1044:            } // end of inner class
1045:
1046:        }
www.java2java.com | Contact Us
Copyright 2009 - 12 Demo Source and Support. All rights reserved.
All other trademarks are property of their respective owners.