Package net.sourceforge.squirrel_sql.fw.datasetviewer.cellcomponent

Source Code of net.sourceforge.squirrel_sql.fw.datasetviewer.cellcomponent.DataTypeJavaObject

package net.sourceforge.squirrel_sql.fw.datasetviewer.cellcomponent;
/*
* Copyright (C) 2001-2003 Colin Bell
* colbell@users.sourceforge.net
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
*/
import java.awt.event.*;

import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;

import javax.swing.JTextField;
import javax.swing.JTextArea;
import javax.swing.JTable;
import javax.swing.SwingUtilities;
import javax.swing.BorderFactory;
import javax.swing.text.JTextComponent;
import javax.swing.JCheckBox;
import java.sql.PreparedStatement;
import java.sql.ResultSet;

import net.sourceforge.squirrel_sql.fw.sql.ISQLDatabaseMetaData;
import net.sourceforge.squirrel_sql.fw.util.StringManager;
import net.sourceforge.squirrel_sql.fw.util.StringManagerFactory;
import net.sourceforge.squirrel_sql.fw.datasetviewer.CellDataPopup;
import net.sourceforge.squirrel_sql.fw.datasetviewer.ColumnDisplayDefinition;
import net.sourceforge.squirrel_sql.fw.datasetviewer.cellcomponent.IDataTypeComponent;
import net.sourceforge.squirrel_sql.fw.gui.OkJPanel;

/**
* @author gwg
*
* This class provides the display components for handling SQL JAVA_OBJECT data types,
* specifically SQL type JAVA_OBJECT.
* <P>
* The default SQuirreL code can handle only JDBC-standard defined data types.
* Since this data type represents DBMS-specific enhancements or
* user-defined data types, we cannot do anything intelligent with the data.
* We allow the user to select one of two modes of operation:
* <DL>
* <LI>
* we can try to get the contents of the DB element and print it as a string, or,
* <LI>
* we will display an appropriately internationalized version of "<JAVA_OBJECT>".
* </DL>
* In either case, the data will be stored and processed as a String.
* <P>
* The user may not edit the contents of this field in either the cell or popup
* because we do not understand the structure or limitations of the contents,
* and therefore cannot validate it or put it back into the DB.
* The field is not used in the WHERE clause because we do not know whether
* or not it might contain binary data, and because we do not know how to
* format the data for SQL operations.
* <P>
* To handle these data types more intelligently and allow editing on them,
* DBMS-specific plug-ins will need to be developed to register handlers
* for instances of this type.
*/
public class DataTypeJavaObject extends BaseDataTypeComponent
  implements IDataTypeComponent
{
  /* whether nulls are allowed or not */
  private boolean _isNullable;

  /* table of which we are part (needed for creating popup dialog) */
  private JTable _table;

  /* The JTextComponent that is being used for editing */
  private IRestorableTextComponent _textComponent;

  /** Internationalized strings for this class, shared/copied from ResultSetReader. */
  private static final StringManager s_stringMgr =
    StringManagerFactory.getStringManager(DataTypeJavaObject.class);

  /* The CellRenderer used for this data type */
  //??? For now, use the same renderer as everyone else.
  //??
  //?? IN FUTURE: change this to use a new instance of renederer
  //?? for this data type.
  private DefaultColumnRenderer _renderer = DefaultColumnRenderer.getInstance();


  /**
   * Name of this class, which is needed because the class name is needed
   * by the static method getControlPanel, so we cannot use something
   * like getClass() to find this name.
   */
  private static final String thisClassName =
    "net.sourceforge.squirrel_sql.fw.datasetviewer.cellcomponent.DataTypeJavaObject";

  /*
   * Properties settable by the user
   */
   // flag for whether we have already loaded the properties or not
   private static boolean propertiesAlreadyLoaded = false;


  /** Read the contents of JavaObject from Result sets when first loading the tables. */
  private static boolean _readSQLJavaObject = true;


  /**
   * Constructor - save the data needed by this data type.
   */
  public DataTypeJavaObject(JTable table, ColumnDisplayDefinition colDef) {
    _table = table;
    _colDef = colDef;
    _isNullable = colDef.isNullable();

    loadProperties();
  }

  /** Internal function to get the user-settable properties from the DTProperties,
   * if they exist, and to ensure that defaults are set if the properties have
   * not yet been created.
   * <P>
   * This method may be called from different places depending on whether
   * an instance of this class is created before the user brings up the Session
   * Properties window.  In either case, the data is static and is set only
   * the first time we are called.
   */
  private static void loadProperties() {

    //set the property values
    // Note: this may have already been done by another instance of
    // this DataType created to handle a different column.
    if (propertiesAlreadyLoaded == false) {
      // get parameters previously set by user, or set default values
      _readSQLJavaObject = true// set to the default
      String readSQLJavaObjectString = DTProperties.get(
        thisClassName, "readSQLJavaObject");
      if (readSQLJavaObjectString != null && readSQLJavaObjectString.equals("false"))
        _readSQLJavaObject = false;

      propertiesAlreadyLoaded = true;
    }
  }

  /**
   * Return the name of the java class used to hold this data type.
   * For JavaObject, this will always be a string.
   */
  public String getClassName() {
    return "java.lang.String";
  }

  /*
   * First we have the cell-related and Text-table operations.
   */


  /**
   * Render a value into text for this DataType.
   */
  public String renderObject(Object value) {
    return (String)_renderer.renderObject(value);
  }

  /**
   * This Data Type can be edited in a table cell.
   */
  public boolean isEditableInCell(Object originalValue) {
    return false;
  }

  /**
   * See if a value in a column has been limited in some way and
   * needs to be re-read before being used for editing.
   * For read-only tables this may actually return true since we want
   * to be able to view the entire contents of the cell even if it was not
   * completely loaded during the initial table setup.
   */
  public boolean needToReRead(Object originalValue) {
    // this DataType does not limit the data read during the initial load of the table,
    // so there is no need to re-read the complete data later
    return false;
  }

  /**
   * Return a JTextField usable in a CellEditor.
   */
  public JTextField getJTextField() {
    _textComponent = new RestorableJTextField();

    // special handling of operations while editing this data type
    ((RestorableJTextField)_textComponent).addKeyListener(new KeyTextHandler());

    //
    // handle mouse events for double-click creation of popup dialog.
    // This happens only in the JTextField, not the JTextArea, so we can
    // make this an inner class within this method rather than a separate
    // inner class as is done with the KeyTextHandler class.
    //
    ((RestorableJTextField)_textComponent).addMouseListener(new MouseAdapter()
    {
      public void mousePressed(MouseEvent evt)
      {
        if (evt.getClickCount() == 2)
        {
          MouseEvent tableEvt = SwingUtilities.convertMouseEvent(
            (RestorableJTextField)DataTypeJavaObject.this._textComponent,
            evt, DataTypeJavaObject.this._table);
          CellDataPopup.showDialog(DataTypeJavaObject.this._table,
            DataTypeJavaObject.this._colDef, tableEvt, true);
        }
      }
    })// end of mouse listener

    return (JTextField)_textComponent;
  }

  /**
   * Implement the interface for validating and converting to internal object.
   * Since we do not know how to convert JavaObject objects,
   * just return null with no error in the messageBuffer
   */
  public Object validateAndConvert(String value, Object originalValue, StringBuffer messageBuffer) {
    return null;
  }

  /**
   * If true, this tells the PopupEditableIOPanel to use the
   * binary editing panel rather than a pure text panel.
   * The binary editing panel assumes the data is an array of bytes,
   * converts it into text form, allows the user to change how that
   * data is displayed (e.g. Hex, Decimal, etc.), and converts
   * the data back from text to bytes when the user editing is completed.
   * If this returns false, this DataType class must
   * convert the internal data into a text string that
   * can be displayed (and edited, if allowed) in a TextField
   * or TextArea, and must handle all
   * user key strokes related to editing of that data.
   */
  public boolean useBinaryEditingPanel() {
    return false;
  }



  /*
   * Now define the Popup-related operations.
   */


  /**
   * Returns true if data type may be edited in the popup,
   * false if not.
   */
  public boolean isEditableInPopup(Object originalValue) {
    return false;
  }

  /*
   * Return a JTextArea usable in the CellPopupDialog.
   */
   public JTextArea getJTextArea(Object value) {
    _textComponent = new RestorableJTextArea();

    // value is a simple string representation of the data,
    // the same one used in the Text and in-cell operations.
    ((RestorableJTextArea)_textComponent).setText(renderObject(value));

    // special handling of operations while editing this data type
    ((RestorableJTextArea)_textComponent).addKeyListener(new KeyTextHandler());

    return (RestorableJTextArea)_textComponent;
   }

  /**
   * Validating and converting in Popup is identical to cell-related operation.
   */
  public Object validateAndConvertInPopup(String value, Object originalValue, StringBuffer messageBuffer) {
    return validateAndConvert(value, originalValue, messageBuffer);
  }


  /*
   * The following is used by both in-cell and Popup operations.
   */


  /*
   * Internal class for handling key events during editing
   * of both JTextField and JTextArea.
   * Since neither cell nor popup are allowed to edit, just ignore
   * anything seen here.
   */
   private class KeyTextHandler extends KeyAdapter {
    // special handling of operations while editing Strings
    public void keyTyped(KeyEvent e) {

      // as a coding convenience, create a reference to the text component
      // that is typecast to JTextComponent.  this is not essential, as we
      // could typecast every reference, but this makes the code cleaner
      JTextComponent _theComponent = (JTextComponent)DataTypeJavaObject.this._textComponent;
      e.consume();
      _beepHelper.beep(_theComponent);
    }
  }




  /*
   * DataBase-related functions
   */

   /**
    * On input from the DB, read the data from the ResultSet into the appropriate
    * type of object to be stored in the table cell.
    */
  public Object readResultSet(ResultSet rs, int index, boolean limitDataRead)
    throws java.sql.SQLException {

    String data = null;
    if (_readSQLJavaObject)
    {
      // Running getObject on a java class attempts
      // to load the class in memory which we don't want.
      // getString() just gets the value without loading
      // the class (at least under PostgreSQL).
      //row[i] = _rs.getObject(index);
      //data = rs.getString(index);
        try{
            Object value = rs.getObject(index);
            if(value==null
                    || value instanceof Number
                    || value instanceof String
                    || value instanceof java.util.Date
                    || value instanceof java.net.URL
            ){
                data=value+"";
            }
        }catch(Exception e){
        }
        if(data==null){
            data = s_stringMgr.getString("DataTypeUnknown.unknown",
                    Integer.valueOf(_colDef.getSqlType()));
        }
    }
    else
    {
                  data = s_stringMgr.getString("DataTypeUnknown.unknown",
                                               Integer.valueOf(_colDef.getSqlType()));
    }

    if (rs.wasNull())
      return null;
    else return data;

//    String data = rs.getString(index);
//    if (rs.wasNull())
//      return null;
//    else return data;
  }

  /**
   * When updating the database, generate a string form of this object value
   * that can be used in the WHERE clause to match the value in the database.
   * A return value of null means that this column cannot be used in the WHERE
   * clause, while a return of "null" (or "is null", etc) means that the column
   * can be used in the WHERE clause and the value is actually a null value.
   * This function must also include the column label so that its output
   * is of the form:
   *   "columnName = value"
   * or
   *   "columnName is null"
   * or whatever is appropriate for this column in the database.
   */
  public String getWhereClauseValue(Object value, ISQLDatabaseMetaData md) {
    if (value == null || value.toString() == null )
      return _colDef.getColumnName() + " IS NULL";
    else
      return _colDef.getColumnName() + "='" + value.toString() + "'";
  }


  /**
   * When updating the database, insert the appropriate datatype into the
   * prepared statment at the given variable position.
   */
  public void setPreparedStatementValue(PreparedStatement pstmt, Object value, int position)
    throws java.sql.SQLException {
    if (value == null) {
      pstmt.setNull(position, _colDef.getSqlType());
    }
    else {
      pstmt.setString(position, ((String)value));
    }
  }

  /**
   * Get a default value for the table used to input data for a new row
   * to be inserted into the DB.
   */
  public Object getDefaultValue(String dbDefaultValue) {
    if (dbDefaultValue != null) {
      // try to use the DB default value
      StringBuffer mbuf = new StringBuffer();
      Object newObject = validateAndConvert(dbDefaultValue, null, mbuf);

      // if there was a problem with converting, then just fall through
      // and continue as if there was no default given in the DB.
      // Otherwise, use the converted object
      if (mbuf.length() == 0)
        return newObject;
    }

    // no default in DB.  If nullable, use null.
    if (_isNullable)
      return null;

    // field is not nullable, so create a reasonable default value
    // cannot create default value for unknown data type
    return null;
  }


  /*
   * File IO related functions
   */


   /**
    * Say whether or not object can be exported to and imported from
    * a file.  We put both export and import together in one test
    * on the assumption that all conversions can be done both ways.
    */
   public boolean canDoFileIO() {
     return false;
   }

   /**
    * Read a file and construct a valid object from its contents.
    * Errors are returned by throwing an IOException containing the
    * cause of the problem as its message.
    * <P>
    * DataType is responsible for validating that the imported
    * data can be converted to an object, and then must return
    * a text string that can be used in the Popup window text area.
    * This object-to-text conversion is the same as is done by
    * the DataType object internally in the getJTextArea() method.
    *
    * <P>
    * File is assumed to be printable text characters,
    * possibly including newlines and tabs but not characters
    * that would require a binary representation to display
    * to user.
    */
  public String importObject(FileInputStream inStream)
     throws IOException {

/*               You can try those code:
               java.io.ObjectInputStream objectInputStream = null;
               try {
                   objectInputStream = new java.io.ObjectInputStream(inStream);
                   return objectInputStream.readObject()+"";
               }catch (ClassNotFoundException cnfe) {
//                 throw new IOException("Class not found: "+ cnfe.toString()+" while reading serialized object");
                 throw new IOException("Can not import data type JAVA_OBJECT");
               }catch (IOException ioe) {
//                 throw new IOException( ioe.toString() +" while reading serialized object");
                 throw new IOException("Can not import data type JAVA_OBJECT");
               }               */

               throw new IOException("Can not import data type JAVA_OBJECT");
  }


   /**
    * Construct an appropriate external representation of the object
    * and write it to a file.
    * Errors are returned by throwing an IOException containing the
    * cause of the problem as its message.
    * <P>
    * DataType is responsible for validating that the given text
    * text from a Popup JTextArea can be converted to an object.
    * This text-to-object conversion is the same as validateAndConvertInPopup,
    * which may be used internally by the object to do the validation.
    * <P>
    * The DataType object must flush and close the output stream before returning.
    * Typically it will create another object (e.g. an OutputWriter), and
    * that is the object that must be flushed and closed.
    *
    * <P>
    * File is assumed to be printable text characters,
    * possibly including newlines and tabs but not characters
    * that would require a binary representation to display
    * to user.
    */
   public void exportObject(FileOutputStream outStream, String text)
     throws IOException    {

/* You can try those code:
               java.io.ObjectOutputStream objectOutputStream=null;
               try {
                   objectOutputStream = new java.io.ObjectOutputStream(outStream);
                   objectOutputStream.writeObject(text);
                   objectOutputStream.flush();
               }catch (IOException e) {
                 throw new IOException("Can not export data type JAVA_OBJECT");
               }     */
               throw new IOException("Can not export data type JAVA_OBJECT");
   }


  /*
   * Property change control panel
   */

   /**
    * Generate a JPanel containing controls that allow the user
    * to adjust the properties for this DataType.
    * All properties are static accross all instances of this DataType.
    * However, the class may choose to apply the information differentially,
    * such as keeping a list (also entered by the user) of table/column names
    * for which certain properties should be used.
    * <P>
    * This is called ONLY if there is at least one property entered into the DTProperties
    * for this class.
    * <P>
    * Since this method is called by reflection on the Method object derived from this class,
    * it does not need to be included in the Interface.
    * It would be nice to include this in the Interface for consistancy, documentation, etc,
    * but the Interface does not seem to like static methods.
    */
   public static OkJPanel getControlPanel() {

    /*
     * If you add this method to one of the standard DataTypes in the
     * fw/datasetviewer/cellcomponent directory, you must also add the name
     * of that DataType class to the list in CellComponentFactory, method
     * getControlPanels, variable named initialClassNameList.
     * If the class is being registered with the factory using registerDataType,
     * then you should not include the class name in the list (it will be found
     * automatically), but if the DataType is part of the case statement in the
     * factory method getDataTypeObject, then it does need to be explicitly listed
     * in the getControlPanels method also.
     */

     // if this panel is called before any instances of the class have been
     // created, we need to load the properties from the DTProperties.
     loadProperties();

    return new SQLJavaObjectOkJPanel();
   }



   /**
    * Inner class that extends OkJPanel so that we can call the ok()
    * method to save the data when the user is happy with it.
    */
   private static class SQLJavaObjectOkJPanel extends OkJPanel {

      private static final long serialVersionUID = 1353928067985854545L;
        /*
     * GUI components - need to be here because they need to be
     * accessible from the event handlers to alter each other's state.
     */
    // check box for whether to read contents during table load or not
    private JCheckBox _showSQLJavaObjectChk = new JCheckBox(
      // i18n[dataTypeJavaObject.readContentsWhenLoaded=Read contents when table is first loaded and display as string]
      s_stringMgr.getString("dataTypeJavaObject.readContentsWhenLoaded"));


    public SQLJavaObjectOkJPanel() {

      /* set up the controls */
      // checkbox for read/not-read on table load
      _showSQLJavaObjectChk.setSelected(_readSQLJavaObject);

      /*
       * Create the panel and add the GUI items to it
       */

      // i18n[dataTypeJavaObject.sqlJavaObjectType=SQL JavaObject   (SQL type 2000)]
      setBorder(BorderFactory.createTitledBorder(s_stringMgr.getString("dataTypeJavaObject.sqlJavaObjectType")));

      add(_showSQLJavaObjectChk);

    } // end of constructor for inner class


    /**
     * User has clicked OK in the surrounding JPanel,
     * so save the current state of all variables
     */
    public void ok() {
      // get the values from the controls and set them in the static properties
      _readSQLJavaObject = _showSQLJavaObjectChk.isSelected();
      DTProperties.put(
        thisClassName,
        "readSQLJavaObject", Boolean.valueOf(_readSQLJavaObject).toString());
    }

   } // end of inner class
}
TOP

Related Classes of net.sourceforge.squirrel_sql.fw.datasetviewer.cellcomponent.DataTypeJavaObject

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.