DumontEXE 0.0.1
cmcItem.cpp
00001 
00002 #include "cmcCursor.h"
00003 #include "cmcItem.h"
00004 #include "cmcFieldDefs.h"
00005 #include "cmcConnectionDef.h"
00006 #include "cmcConnectionDefs.h"
00007 #include "cmcField.h"
00008 #include "cmcSubField.h"
00009 
00010 namespace cmcDatabaseApi {
00011 
00012 cmcItem::cmcItem( const cmcItem & copy )
00013 {
00014 }
00015 
00016 cmcItem::cmcItem
00017 (
00018   const QString & categoryName,
00019   long flags,
00020   cmcApplication * application,
00021   QObject * parent
00022 )
00023 : cmcObject( "cmcItem", application, parent )
00024 {
00025 //  TRACE_FUNCTION
00026 
00027   /*
00028   ** remember the flags
00029   **
00030   */
00031   m_flags = flags;
00032 
00033   m_categoryName = categoryName;
00034 
00035   /*
00036   ** fetch a cursor and reparent it.  This is an important (technical internal)
00037   **  step.  Since, generally, we're wrapping objects for vbScript, when 
00038   **  vbScript is done using them they get automatically destroyed.  This only
00039   **  happens, though, when the objects aren't already parented by another 
00040   **  object.  Therefore, what we do is override the parent of the cursor, and
00041   **  if vbScript comes along and tries to access our cursor, our cursor will
00042   **  already have a parent, and when vbScript is done with our cursor it
00043   **  will *not* destroy it, which is what we want.
00044   **
00045   ** Also, since we are creating the cursor, and reparenting the cursor to us,
00046   **  when we are destroyed the cursor for us will be destroyed also.  This
00047   **  is also what we want.  Because there's another scenario whereby we will
00048   **  be created by a different collection, and we all will be sharig that same
00049   **  cursor.  In that instance we don't want to destroy that cursor, but, 
00050   **  rather we want that collection to take care of destroying the cursor for
00051   **  us.
00052   **
00053   */
00054   m_cursor = app()-> db()-> getCursor( categoryName );
00055   m_cursor-> setParent( this );
00056 
00057   /*
00058   ** By default we are the first row.
00059   **
00060   */
00061   m_row = 0;
00062 
00063 }
00064 
00065 cmcItem::cmcItem
00066 (
00067   cmcRowSet * _rowset,
00068   long index,
00069   cmcApplication * application,
00070   QObject * parent
00071 )
00072 : cmcObject( "cmcItem", application, parent )
00073 {
00074 //  TRACE_FUNCTION
00075   m_rowset = _rowset;
00076   m_cursor = _rowset-> cursor();
00077   m_row = index;
00078 }
00079 
00080 
00081 cmcItem::~cmcItem()
00082 {
00083 //  TRACE_FUNCTION
00084 }
00085 
00086 
00087 cmcCursor * cmcItem::cursor()
00088 {
00089   return( m_cursor );
00090 }
00091 
00092 void cmcItem::setColumnDefault()
00093 {
00094   /*
00095   ** If no columns have been defined, then do nothing here
00096   **  If no columns have been defined, then we don't want
00097   **  to assume he wants any columns defined at all, in which
00098   **  case we'll just go with the full column list.  However,
00099   **  if he has defined a column, then let's just make sure
00100   **  some of these other columns already exist.
00101   **
00102   */
00103   if( cursor()-> colCount() == cursor()-> categoryDef()-> colCount() )
00104       return;
00105 
00106   /*
00107   ** Make sure the key field is set
00108   */
00109   setColumn( cursor()-> categoryDef()-> keyFieldName() );
00110 
00111   /*
00112   ** If there's a clarify field, set that also.
00113   **
00114   */
00115   if( cursor()-> categoryDef()-> hasClarifyField() )
00116       setColumn( cursor()-> categoryDef()-> cfyFieldName() );
00117 
00118   /*
00119   ** If there's a var field, set that also.
00120   **
00121   */
00122   if( cursor()-> categoryDef()-> hasVarField() )
00123       setColumn( cursor()-> categoryDef()-> varFieldName() );
00124 
00125   /*
00126   ** If there's a separate guid field, set that also.
00127   **
00128   */
00129   if( cursor()-> categoryDef()-> hasGuidField() )
00130       setColumn( cursor()-> categoryDef()-> guidFieldName() );
00131 
00132 }
00133 
00134 long cmcItem::setColumn( const QString & fieldName )
00135 {
00136   return( cursor()-> setColumn( fieldName ) );
00137 }
00138 
00139 long cmcItem::setColumn
00140 (
00141   const QString & connectionName,
00142   const QString & categoryName,
00143   const QString & fieldName
00144 )
00145 {
00146   return( cursor()-> setColumn( connectionName, categoryName, fieldName ) );
00147 }
00148 
00149 cmcRowSet * cmcItem::rowset()
00150 {
00151   if( !m_rowset )
00152   {
00153     setColumnDefault();
00154     if( cursor()-> rowCount() == 0 )
00155     {
00156       m_rowset = cursor()-> getAddRowSet();
00157       rowset()-> modifyRow( 0, keyField()-> name(), objectName() );
00158       itemGuid();
00159     }
00160     else
00161     {
00162       m_rowset = cursor()-> getEditRowSet();
00163     }
00164     m_rowset-> setParent( this );
00165   }
00166 
00167   if( !m_rowset )
00168   {
00169     CMC_ERROR( 1, "cannot get a rowset" );
00170   }
00171 
00172   return( m_rowset );
00173 }
00174 
00175 
00176 bool cmcItem::loadByKey
00177 (
00178   const QString & itemKey
00179 )
00180 {
00181   /*
00182   ** Make the object name equal to item name.  We do this
00183   **  right up front to get the item named.  That way if 
00184   **  there's an error we can know what item is responsible
00185   **  for it.
00186   **
00187   */
00188   setObjectName( itemKey );
00189 
00190   /*
00191   ** If the item name wasn't provided, then just return.  This
00192   **  might seem like an error, but it's not.
00193   **
00194   */
00195   if( itemKey == "" )
00196     return(false);
00197 
00198   /*
00199   ** cannot proceed without a cursor
00200   **
00201   */
00202   if( !cursor() ) 
00203   {
00204     CMC_ERROR( 2, "no cursor" )
00205     return(false);
00206   }
00207 
00208   /*
00209   ** cannot proceed without a category definition
00210   **
00211   */
00212   if( !cursor()-> categoryDef() )
00213   {
00214     CMC_ERROR( 3, "no category def" )
00215     return(false);
00216   }
00217 
00218   /*
00219   ** Remove any existing filters.
00220   **
00221   */
00222   cursor()-> clearFilter();
00223 
00224   /*
00225   ** try to filter for this item name
00226   **
00227   */
00228   if( !cursor()-> setFilter
00229       (
00230         "[ViewFilter(1,F,," + cursor()-> categoryDef()-> keyFieldName() +
00231         ",Equal to,"        + dq(itemKey) +
00232         ")]")
00233       )
00234   {
00235     CMC_ERROR( 4, "cannnot set filter: " + cursor()-> filters() )
00236     return(false);
00237   }
00238 
00239   /*
00240   ** Check the row count.  We're loading by item name so we should
00241   **  only get one row.
00242   **
00243   */
00244   if( cursor()-> rowCount() != 1 )
00245   {
00246     CMC_ERROR( 5, QString("wrong row count: %1").arg(cursor()->rowCount()) )
00247   }
00248 
00249   /*
00250   ** If we get here, then we got the one row that we wanted.
00251   **
00252   */
00253   return( true );
00254 
00255 } // endbool cmcItem::loadByName( const QString & itemName )
00256 
00257 
00258 bool cmcItem::loadByGuid
00259 (
00260   const QString & itemGuid
00261 )
00262 {
00263   /*
00264   ** Make the object name equal to item name.  We do this
00265   **  right up front to get the item named.  That way if 
00266   **  there's an error we can know what item is responsible
00267   **  for it.
00268   **
00269   */
00270   setObjectName( itemGuid );
00271 
00272   /*
00273   ** If the item name wasn't provided, then just return.  This
00274   **  might seem like an error, but it's not.
00275   **
00276   */
00277   if( itemGuid == "" )
00278     return(false);
00279 
00280   /*
00281   ** cannot proceed without a cursor
00282   **
00283   */
00284   if( !cursor() ) 
00285   {
00286     CMC_ERROR( 2, "no cursor" )
00287     return(false);
00288   }
00289 
00290   /*
00291   ** cannot proceed without a category definition
00292   **
00293   */
00294   if( !cursor()-> categoryDef() )
00295   {
00296     CMC_ERROR( 3, "no category def" )
00297     return(false);
00298   }
00299 
00300   /*
00301   ** Remove any existing filters.
00302   **
00303   */
00304   cursor()-> clearFilter();
00305 
00306   /*
00307   ** try to filter for this item name
00308   **
00309   */
00310   if( !cursor()-> setFilter
00311       (
00312         "[ViewFilter(1,F,," + cursor()-> categoryDef()-> guidFieldName() +
00313         ",Equal to,"        + dq(itemGuid) +
00314         ")]")
00315       )
00316   {
00317     CMC_ERROR( 4, "cannnot set filter: " + cursor()-> filters() )
00318     return(false);
00319   }
00320 
00321   /*
00322   ** Check the row count.  We're loading by item name so we should
00323   **  only get one row.
00324   **
00325   */
00326   if( cursor()-> rowCount() != 1 )
00327   {
00328     CMC_ERROR( 5, QString("wrong row count: %1").arg(cursor()->rowCount()) )
00329   }
00330 
00331   /*
00332   ** If we get here, then we got the one row that we wanted.
00333   **
00334   */
00335   return( true );
00336 
00337 } // endbool cmcItem::loadByName( const QString & itemName )
00338 
00339 
00340 
00341 bool cmcItem::loadByField
00342 (
00343   const QString & fieldName,
00344   const QString & qualifier,
00345   const QString & value,
00346   bool notFlag,
00347   bool caseSensitive
00348 )
00349 {
00350   /*
00351   ** cannot proceed without a cursor
00352   **
00353   */
00354   if( !cursor() ) 
00355   {
00356     CMC_ERROR( 2, "no cursor" )
00357     return(false);
00358   }
00359 
00360   /*
00361   ** cannot proceed without a category definition
00362   **
00363   */
00364   if( !cursor()-> categoryDef() )
00365   {
00366     CMC_ERROR( 3, "no category def" )
00367     return(false);
00368   }
00369 
00370   /*
00371   ** Remove any existing filters.
00372   **
00373   */
00374   cursor()-> clearFilter();
00375 
00376   /*
00377   ** try to filter for this item name
00378   **
00379   */
00380   if( !cursor()-> setFilter
00381       (
00382         "[ViewFilter(1,F,"                + 
00383         QString(notFlag? "Not":"")        + "," + 
00384         fieldName                         + "," +
00385         qualifier                         + "," +
00386         dq(value)                         +
00387         QString(caseSensitive? ",yes":"") +
00388         ")]"
00389       )
00390     )
00391   {
00392     CMC_ERROR( 4, "cannnot set filter: " + cursor()-> filters() )
00393     return(false);
00394   }
00395 
00396   /*
00397   ** Check the row count.  We're loading by item name so we should
00398   **  only get one row.
00399   **
00400   */
00401   if( cursor()-> rowCount() != 1 )
00402   {
00403     CMC_ERROR( 5, QString("wrong row count: %1").arg(cursor()->rowCount()) )
00404   }
00405 
00406   /*
00407   ** If we get here, then we got the one row that we wanted.
00408   **
00409   */
00410   return( true );
00411 
00412 }
00413 
00414 bool cmcItem::save()
00415 {
00416   if( !cursor() ) 
00417   {
00418     CMC_ERROR( 6, "no cursor" );
00419     return( false );
00420   }
00421 
00422   if( !rowset() )
00423   {
00424     CMC_ERROR( 7, "no edit row set" );
00425     return( false );
00426   }
00427 
00428   itemGuid();
00429 
00430   /*
00431   ** If this category has a var field, then there
00432   **  are a few things we want to store in it
00433   **
00434   */
00435   if( categoryDef()-> hasVarField() )
00436   {
00437     if( showWarnings() )
00438       qDebug( "saving creation info" );
00439 
00440     if( rowset()-> type() == cmcRowSet::RowSetAdd )
00441     {
00442       varField()-> var( "createdOn", dateTimeStamp()        );
00443       varField()-> var( "createdBy", db()-> meInfo()-> id() );
00444     }
00445 
00446     varField()-> var( "changedOn", dateTimeStamp()          );
00447     varField()-> var( "changedBy", db()-> meInfo()-> id()   );
00448 
00449     /*
00450     ** Make sure the guid value is properly stored
00451     **
00452     */
00453     varField()-> var( "guid", itemGuid() );
00454 
00455   }
00456 
00457   if( m_isShared ) rowset()-> setShared(row());
00458 
00459   return( rowset()-> commit() == 0? true:false );
00460 }
00461 
00462 long cmcItem::row()
00463 {
00464   return( m_row );
00465 }
00466 
00467 cmcRowSet * cmcItem::getChangeLogAddRowSet()
00468 {
00469   return( NULL );
00470 }
00471 
00472 QString cmcItem::changeLog()
00473 {
00474   return( "" );
00475 }
00476 
00477 bool cmcItem::isField( const QString & fieldName )
00478 {
00479   return( categoryDef()-> fieldDefs()-> contains( fieldName ) );
00480 }
00481 
00482 bool cmcItem::isConnection( QString const & connectionName )
00483 {
00484   return( categoryDef()-> connectionDefs()-> contains( connectionName ) );
00485 }
00486 
00487 cmcItems * cmcItem::connection( long index )
00488 {
00489   return( connection( categoryDef()-> connectionDef(index)-> name() ) );
00490 }
00491 
00492 cmcItems * cmcItem::con( const QString & connectionName )
00493 {
00494   return( connection( connectionName ) );
00495 }
00496 
00497 cmcItems * cmcItem::connection(QString const&)
00498 {
00499   return( NULL );
00500 }
00501 
00502 cmcItems * cmcItem::con
00503 (
00504   const QString & connectionName,
00505   const QString & targetCategoryName,
00506   const QString & reverseConnectionName
00507 )
00508 {
00509   return( connection( connectionName, targetCategoryName, reverseConnectionName ) );
00510 }
00511 
00512 
00513 cmcItems * cmcItem::connection
00514 (
00515   const QString & connectionName,
00516   const QString & targetCategoryName,
00517   const QString & reverseConnectionName
00518 )
00519 {
00520   /*
00521   ** If nothing gets passed in then we must quit.
00522   **
00523   */
00524   if( connectionName     == "" ||
00525       targetCategoryName == ""    )
00526   {
00527     return( NULL );
00528   }
00529 
00530   cmcItems * retVal = findChild<cmcItems*>(connectionName + " -> " + targetCategoryName);
00531 
00532   if( !retVal )
00533   {
00534     retVal = new cmcItems( connectionName, targetCategoryName, reverseConnectionName, app(), this );
00535   }
00536 
00537   return( retVal );
00538 }
00539 
00540 cmcItemField * cmcItem::field( const QString & fieldName )
00541 {
00542   if( fieldName == "" )
00543   {
00544     return( NULL );
00545   }
00546 
00547   /*
00548   ** Fields have the unique quality that if a single field is created
00549   **  then that same field pointer is handed out to any other request
00550   **  for the same field.
00551   **
00552   ** However, this is troublesome since if someone else acquires a handle
00553   **  to a field and then destroys it, it will go out of existance for
00554   **  the first handle.  It seems we need some sort of reference counting
00555   **  in order to be able to handle multiple clients of a Qt object.  It is
00556   **  potentially a problem to have a field object deleted before its time
00557   **  since the field object, itself, carries undo and change info.
00558   **
00559   */
00560   cmcItemField * retVal = findChild<cmcItemField *>(fieldName);
00561 
00562   /*
00563   ** If the field is not already created then we need to create one.
00564   **
00565   */
00566   if( !retVal )
00567   {
00568     retVal = new cmcItemField( fieldName, app(), this );
00569   }
00570 
00571   return( retVal );
00572 
00573 }
00574 
00575 cmcItemField * cmcItem::fld( long index )
00576 {
00577   return( field(index) );
00578 }
00579 
00580 cmcItemField * cmcItem::field( long index )
00581 {
00582   return( field( categoryDef()-> fieldDef(index)-> name() ) );
00583 }
00584 
00585 cmcItemField * cmcItem::fld( const QString & fieldName )
00586 {
00587   return( field(fieldName) );
00588 }
00589 
00590 cmcSubField * cmcItem::extField( QString subFieldName )
00591 {
00592   cmcSubField * retVal = NULL;
00593 
00594   if( categoryDef()-> hasVarField() )
00595   {
00596     retVal = varField()-> subField( subFieldName );
00597   }
00598 
00599   return( retVal );
00600 }
00601 
00602 cmcCategoryDef * cmcItem::categoryDef()
00603 {
00604   if( !m_categoryDef )
00605        m_categoryDef = app()-> categoryDef( categoryName() );
00606 
00607   return( m_categoryDef );
00608 }
00609 
00610 void cmcItem::undo()
00611 {
00612 }
00613 
00614 bool cmcItem::isDirty()
00615 {
00616   return( m_isDirty );
00617 }
00618 
00619 bool cmcItem::deleteItem()
00620 {
00621   return( false );
00622 }
00623 
00624 void cmcItem::setShared( bool value )
00625 {
00626   m_isShared = value;
00627 }
00628 
00629 bool cmcItem::isShared()
00630 {
00631   return( m_isShared );
00632 }
00633 
00634 bool cmcItem::isDelete()
00635 {
00636   return( m_isDelete );
00637 }
00638 
00639 bool cmcItem::isAdd()
00640 {
00641   return( rowset()-> type() == cmcRowSet::RowSetAdd );
00642 }
00643 
00644 QString cmcItem::itemGuid()
00645 {
00646   static bool newGuidNeeded = true;
00647   static QString retVal;
00648 
00649   if( categoryDef()-> hasGuidField() )
00650   {
00651     retVal = guidField()-> value();
00652     if( retVal == "" || ( isAdd() && newGuidNeeded ) )
00653     {
00654       retVal = QUuid().createUuid().toString();
00655       guidField()-> value( retVal );
00656       newGuidNeeded = false;
00657     }
00658   }
00659   else if( categoryDef()-> hasVarField() )
00660   {
00661     retVal = varField()-> var("guid");
00662     if( retVal == "" || ( isAdd() && newGuidNeeded ) )
00663     {
00664       retVal = QUuid().createUuid().toString();
00665       varField()-> var("guid", retVal );
00666       newGuidNeeded = false;
00667     }
00668   }
00669   else
00670   {
00671     if( showWarnings() )
00672       qDebug( "on %s, no field to store guid", categoryName().toAscii().data()  );
00673   }
00674 
00675   if( retVal == "" || ( isAdd() && newGuidNeeded ) )
00676   {
00677     retVal = QUuid().createUuid().toString();
00678   }
00679 
00680   return( retVal );
00681 
00682 }
00683 
00684 QString cmcItem::itemThid()
00685 {
00686   QString retVal = "unknown";
00687 
00688   if( categoryDef()-> hasThidField() )
00689   {
00690     retVal = thidField()-> value();
00691 
00692     if( retVal == "" || isAdd() )
00693     {
00694       thidField()-> value( "nothing" );
00695     }
00696   }
00697   else if( categoryDef()-> hasVarField() )
00698   {
00699     retVal = varField()-> var("thid");
00700 
00701     if( retVal == "" || isAdd() )
00702     {
00703       varField()-> var("thid","nothing");
00704     }
00705   }
00706   else
00707   {
00708     if( showWarnings() )
00709       qDebug( "on %s, no field to store THID", categoryName().toAscii().data()  );
00710   }
00711 
00712   return( retVal );
00713 }
00714 
00715 cmcItemField * cmcItem::thidField()
00716 {
00717   return( field( categoryDef()-> thidFieldName() ) );
00718 }
00719 
00720 cmcItemField * cmcItem::guidField()
00721 {
00722   return( field( categoryDef()-> guidFieldName() ) );
00723 }
00724 
00725 cmcItemField * cmcItem::varField()
00726 {
00727   return( field( categoryDef()-> varFieldName() ) );
00728 }
00729 
00730 cmcItemField * cmcItem::cfyField()
00731 {
00732   return( field( categoryDef()-> cfyFieldName() ) );
00733 }
00734 
00735 cmcItemField * cmcItem::keyField()
00736 {
00737   return( field( categoryDef()-> keyFieldName() ) );
00738 }
00739 
00740 QString cmcItem::itemClarify()
00741 {
00742   QString retVal;
00743 
00744   if( cfyField() )
00745     retVal = cfyField()-> value();
00746 
00747   return( retVal );
00748 }
00749 
00750 QString cmcItem::itemName()
00751 {
00752   return( keyField()-> value() );
00753 }
00754 
00755 QString cmcItem::clarifiedItemName( bool fullPad )
00756 {
00757   QString retVal = keyField()-> value();
00758 
00759   if( categoryDef()-> hasClarifyField() )
00760   {
00761     retVal  = pad( retVal, " ", 50 );
00762     retVal += categoryDef()-> clarifySeparator();
00763     if( fullPad )
00764       retVal += pad( itemClarify().left(40), " ", 40 );
00765     else
00766       retVal += itemClarify().left(40);
00767   }
00768 
00769   return( retVal );
00770 }
00771 
00772 
00773 QString cmcItem::categoryName()
00774 {
00775   return( rowset()-> categoryName() );
00776 }
00777 
00778 } // endnamespace cmcDatabaseApi
00779 
 All Classes Namespaces Functions Variables Enumerations Enumerator Properties




~ ~ ~ ~ ~ ~
Source Code without Comments is like a Cranberry Garland
without the berries. Comment your Code!
 
Commence Database User Support Group Forum
http://newsgroup.showoff-db.org/
~ ~ ~ ~ ~ ~
Author: Mark Petryk
Lorimark Solutions, LLC
mark@lorimarksolutions.com