CLASS objContact
  PUBLIC:
    local IsOpen, LockTimeout, errmsg, db
    local age, city, fname, homephone, lname, state, street, workphone
    local zip

    METHOD New( )
        ::IsOpen = 0
        ::errmsg = ""
        ::LockTimeout = 2
        ::db = 0
        ::Init( )
        return( 1 )
    END

    METHOD Init( )
        ::age = 0
        ::city = ""
        ::fname = ""
        ::homephone = ""
        ::lname = ""
        ::state = ""
        ::street = ""
        ::workphone = ""
        ::zip = ""
        return( 1 )
    END

    ACCESS dbFileName
        return( 'c:\fgl\data\contacts.db' )
    END

    ACCESS dbIndexName
        return( 'c:\fgl\data\contacts.dx' )
    END

    METHOD create( )
        local db_struct = {
            { "fname", "C", 30, 0 },
            { "lname", "C", 40, 0 },
            { "street", "C", 60, 0 },
            { "city", "C", 30, 0 },
            { "state", "C", 2, 0 },
            { "zip", "C", 10, 0 },
            { "workphone", "C", 10, 0 },
            { "homephone", "C", 10, 0 },
            { "age", "N", 3, 0 }
        }
        return( dbcreate( ::dbFileName, db_struct ) )
    END

    METHOD open( )
        if ( ::IsOpen )
            ::IsOpen++
            return( 1 )
        end

        if ( ! fileExists( ::dbFileName ) )
            ::create( )
        end

        ::IsOpen = 1

        ::db = dbuse( ::dbFileName, "objContact", 1 )
        if ( ! fileExists( ::dbIndexName ) )
            (::db)->dbCreateIndex( ::dbIndexName, "upper( field->lname + field->fname )", 0 )
        end
        (::db)->dbOpenIndex( ::dbIndexName )

        return( 1 )
    END

    METHOD close( )
        if ( ::IsOpen == 1 )
            (::db)->dbClose( )
        end
        ::IsOpen--
        return( 1 )
    END

    METHOD seek( item )
        (::db)->dbSeek( upper( item ) )
        return( (::db)->dbFound( ) )
    END

    METHOD reindex( )
        return( (::db)->dbReindex( ) )
    END

    METHOD get( )
        ::age = (::db)->age
        ::city = alltrim( (::db)->city )
        ::fname = alltrim( (::db)->fname )
        ::homephone = alltrim( (::db)->homephone )
        ::lname = alltrim( (::db)->lname )
        ::state = alltrim( (::db)->state )
        ::street = alltrim( (::db)->street )
        ::workphone = alltrim( (::db)->workphone )
        ::zip = alltrim( (::db)->zip )
        return( 1 )
    END

    METHOD put( )
        (::db)->age = ::age
        (::db)->city = ::city
        (::db)->fname = ::fname
        (::db)->homephone = ::homephone
        (::db)->lname = ::lname
        (::db)->state = ::state
        (::db)->street = ::street
        (::db)->workphone = ::workphone
        (::db)->zip = ::zip
        return( 1 )
    END

    METHOD validate( )
        return( 1 )
    END

    METHOD CreateNewRecord( key )
        if ( ! ::validate( ) )
            return( 0 )
        end

        ::open( )
        if ( ::seek( key ) )
            ::errmsg = "Record (" + key + ") already exists!"
            ::close( )
            return( 0 )
        end

        (::db)->dbAppend( )
        ::put( )
        ::unlock( )

        ::close( )
        return( 1 )
    END

    METHOD GetRecord( key )
        ::open( )

        ::init( )
        if ( ! ::seek( key ) )
            ::errmsg = "Unable to locate record (" + key + ")"
            ::close( )
            return( 0 )
        end

        ::get( )
        ::close( )

        return( 1 )
    END

    METHOD SetRecord( key )
        if ( ! ::validate( ) )
            return( 0 )
        end

        ::open( )

        if ( ! ::seek( key ) )
            ::errmsg = "Unable to locate record (" + key + ")"
            ::close( )
            return( 0 )
        end

        if ( ::rlock( ) )
            ::put( )
            ::unlock( )
        end
        ::close( )

        return( 1 )
    END

    METHOD dbOrder( val )
        (::db)->dbOrder( val )
    END
    METHOD dbGoto( val )
        (::db)->dbGoto( val )
    END
    METHOD dbGoTop( )
        (::db)->dbGoTop( )
    END
    METHOD dbGoBottom( )
        (::db)->dbGoBottom( )
    END
    METHOD dbEOF( )
        return( (::db)->dbEOF( ) )
    END
    METHOD dbBOF( )
        return( (::db)->dbBOF( ) )
    END
    METHOD dbseek( id )
        return( ::seek( id ) )
    END
    METHOD dbSkip( index )
        if ( type( index ) == 'N' )
            (::db)->dbSkip( index )
        else
            (::db)->dbSkip( )
        end
        return( 1 )
    END

    METHOD rlock( )
        local EndTime
        if ( ! ::IsOpen )
            ::errmsg = 'Database must be open to lock record'
            return( 0 )
        end
        EndTime = seconds( ) + ::LockTimeout
        while ( ! (::db)->dbRLock( ) )
            if ( ( seconds( ) > EndTime ) || ( ( seconds( ) + ::LockTimeout ) < EndTime ) )
                ::errmsg ='Unable to lock database record'
                return( 0 )
            end
        end
        return( 1 )
    END

    METHOD unlock( )
        if ( ! ::IsOpen )
            ::errmsg = 'Database must be open to unlock record'
            return( 0 )
        end
        (::db)->dbUnLock( )
        return( 1 )
    END

END