001package com.hfg.sql.table.field;
002
003
004import java.lang.reflect.Constructor;
005import java.sql.PreparedStatement;
006import java.sql.ResultSet;
007import java.sql.SQLException;
008
009import com.hfg.exception.ProgrammingException;
010import com.hfg.sql.jdbc.JDBCException;
011import com.hfg.sql.jdbc.JDBCResultSet;
012import com.hfg.sql.table.DatabaseCol;
013import com.hfg.sql.table.DatabaseTable;
014import com.hfg.sql.table.DatabaseXML;
015import com.hfg.xml.XMLTag;
016
017
018//------------------------------------------------------------------------------
019/**
020 Base class for a database field.
021 <div>
022 @author J. Alex Taylor, hairyfatguy.com
023 </div>
024 */
025//------------------------------------------------------------------------------
026// com.hfg XML/HTML Coding Library
027//
028// This library is free software; you can redistribute it and/or
029// modify it under the terms of the GNU Lesser General Public
030// License as published by the Free Software Foundation; either
031// version 2.1 of the License, or (at your option) any later version.
032//
033// This library is distributed in the hope that it will be useful,
034// but WITHOUT ANY WARRANTY; without even the implied warranty of
035// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
036// Lesser General Public License for more details.
037//
038// You should have received a copy of the GNU Lesser General Public
039// License along with this library; if not, write to the Free Software
040// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
041//
042// J. Alex Taylor, President, Founder, CEO, COO, CFO, OOPS hairyfatguy.com
043// jataylor@hairyfatguy.com
044//------------------------------------------------------------------------------
045
046public abstract class DatabaseField<T> implements Cloneable
047{
048   private DatabaseCol   mCol;
049   private T             mValue;
050   private boolean       mIsDirty;
051
052   //###########################################################################
053   // CONSTRUCTORS
054   //###########################################################################
055
056   //---------------------------------------------------------------------------
057   public DatabaseField(DatabaseCol inCol, T inValue)
058   {
059      mCol   = inCol;
060      mValue = inValue;
061   }
062
063   //---------------------------------------------------------------------------
064   public DatabaseField(DatabaseCol inCol, ResultSet inResultSet)
065   {
066      mCol   = inCol;
067      if (inResultSet != null)
068      {
069         setValueFromResultSet(inResultSet);
070      }
071   }
072
073   //---------------------------------------------------------------------------
074   public DatabaseField(XMLTag inXMLTag, DatabaseTable inTable)
075   {
076      inXMLTag.verifyTagName(DatabaseXML.FIELD);
077
078      mCol = inTable.getCol(inXMLTag.getAttributeValue(DatabaseXML.NAME_ATT));
079
080      if (! inXMLTag.hasAttribute(DatabaseXML.IS_NULL_ATT))
081      {
082         setValueFromString(inXMLTag.getUnescapedContent());
083         mIsDirty = false;
084      }
085   }
086
087   //###########################################################################
088   // PUBLIC METHODS
089   //###########################################################################
090
091   //---------------------------------------------------------------------------
092   public static DatabaseField instantiate(XMLTag inXMLTag, DatabaseTable inTable)
093   {
094      DatabaseField field;
095      try
096      {
097         Class clazz = Class.forName(inXMLTag.getAttributeValue(DatabaseXML.CLASS_ATT));
098         Constructor constructor = clazz.getConstructor(XMLTag.class, DatabaseTable.class);
099         field = (DatabaseField) constructor.newInstance(inXMLTag, inTable);
100      }
101      catch (Exception e)
102      {
103         throw new JDBCException(e);
104      }
105
106      return field;
107   }
108
109   //---------------------------------------------------------------------------
110   @Override
111   public String toString()
112   {
113      return isNull() ? "null" : getValue().toString();
114   }
115
116   //---------------------------------------------------------------------------
117   public XMLTag toXMLTag()
118   {
119      XMLTag tag = new XMLTag(DatabaseXML.FIELD);
120
121      tag.setAttribute(DatabaseXML.CLASS_ATT, getClass().getName());
122      tag.setAttribute(DatabaseXML.NAME_ATT, getCol().name());
123
124      if (isNull())
125      {
126         tag.setAttribute(DatabaseXML.IS_NULL_ATT, true);
127      }
128      else
129      {
130         tag.setContent(getStringValue());
131      }
132
133      return tag;
134   }
135
136   //---------------------------------------------------------------------------
137   protected String getStringValue()
138   {
139      return (getValue() != null ? getValue().toString() : null);
140   }
141
142   //---------------------------------------------------------------------------
143   @Override
144   public DatabaseField<T> clone()
145   {
146      DatabaseField<T> cloneObj;
147      try
148      {
149         cloneObj = (DatabaseField<T>) super.clone();
150      }
151      catch (CloneNotSupportedException e)
152      {
153         throw new ProgrammingException(e);
154      }
155
156      return cloneObj;
157   }
158
159   //---------------------------------------------------------------------------
160   public DatabaseCol getCol()
161   {
162      return mCol;
163   }
164
165   //---------------------------------------------------------------------------
166   public abstract void setValueInPreparedStatement(PreparedStatement inPreparedStatement, int inIndex);
167
168   //---------------------------------------------------------------------------
169   public abstract void setValueFromString(String inValue);
170
171   //---------------------------------------------------------------------------
172   public void setValue(T inValue)
173   {
174      if ((null == inValue
175           && mValue != null)
176          || (inValue != null
177              && ! inValue.equals(mValue)))
178      {
179         mIsDirty = true;
180      }
181
182      mValue = inValue;
183   }
184
185   //---------------------------------------------------------------------------
186   public T getValue()
187   {
188      return mValue;
189   }
190
191   //---------------------------------------------------------------------------
192   public String getSQLValue()
193   {
194      return mValue != null ? mValue.toString() : "null";
195   }
196
197   //---------------------------------------------------------------------------
198   public boolean isNull()
199   {
200      return null == mValue;
201   }
202
203   //---------------------------------------------------------------------------
204   public boolean isDirty()
205   {
206      return mIsDirty;
207   }
208
209   //---------------------------------------------------------------------------
210   public DatabaseField setIsDirty(boolean inValue)
211   {
212      mIsDirty = inValue;
213      return this;
214   }
215
216   //###########################################################################
217   // PROTECTED METHODS
218   //###########################################################################
219
220   //---------------------------------------------------------------------------
221   protected abstract void setValueFromResultSet(ResultSet inResultSet);
222
223   //---------------------------------------------------------------------------
224   protected void setInitialValue(T inValue)
225   {
226      mValue = inValue;
227   }
228
229   //---------------------------------------------------------------------------
230   protected Integer getColIndex(ResultSet inResultSet)
231   {
232      Integer index = null;
233
234      try
235      {
236         // If the ResultSet has been wrapped with a JDBCResultSet,
237         // use the more performant version of findColumn().
238         if (inResultSet instanceof JDBCResultSet)
239         {
240            index = ((JDBCResultSet) inResultSet).findColumn(getCol());
241         }
242         else
243         {
244            index = inResultSet.findColumn(getCol().name());
245
246         }
247      }
248      catch (SQLException e)
249      {
250         // Ignore
251      }
252
253      return index;
254   }
255}