Request for feedback

Anthony W. Juckel awj@digitalgreen.com
11 Nov 2001 00:00:37 -0600


Recently I've been mulling over a way to rework the current transaction
import code to make it a little more generic.  I noticed a comment in
src/import-export/qif-io-import/qif-objects.scm stating a desire to have
the code re-worked into GOOPS classes, so I've started with that.  My
hope is to add a layer of abstraction between the file type and the
gnc:xtn code to make it relatively easy to add a new import file type.  

I've got some very preliminary stuff going so far, but I'm looking for
some comments on the direction I'm heading, since I'm very new both to
GnuCash and scheme.

Here's what I have envisioned:

1)  A list of files is selected for import.
2)  A gnc:initialize-xtn-file method selects tests for the appropriate
file type and returns an instance of the appropriate <xtn-file> subclass
to parse the file.
3)  The <xtn-file> subclass provides methods for inspecting/parsing the
file, returning a list of gnc:xtns and accounts which are then fed
through the rest of the import engine (which I'm hoping to swipe from
the current qif-io-core) and checked for duplicates, etc.

Questions, comments, and suggestions are encouraged.

Here's the class choosing code skeleton that I've come up with so far:

;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;;  xtn-objects.scm
;;;  Initial object system for reading transactions from files
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;

(use-modules (oop goops))

(define-class <xtn-file> ()
  ;; slots yet to be defined
  (xtn-file-alist #:allocation #:class )
  )

;; I don't know how else to do this...
;;  Maybe this is the correct way?
(class-slot-set! <xtn-file> 'xtn-file-alist ())

(define-method (gnc:xtn-file-parse (f <xtn-file>))
  (error "Must be defined by a subclass"))
(define-method (gnc:xtn-file-next-xtn (f <xtn-file>))
  (error "Must be defined by a subclass"))
;; More methods for inspecting/parsing the input file

;; A method to register (file-test . <class>) pairs
;; with the system.
(define-method (gnc:xtn-file-register-test (c <class>) f)
  (class-slot-set! <xtn-file> 'xtn-file-alist
	     (cons (cons f c) (class-slot-ref <xtn-file> 'xtn-file-alist))))

;; Skeleton for two different input file types
;; class needs to be fleshed out with slots/method
;; definitions, etc, and the qif-file procedure would
;; actually read the file f to check whether or not it
;; was a qif file, returning #t or #f
(define-class <gnc:qif-file> (<xtn-file>))
(define-method (gnc:xtn-file-parse (f <qif-file>))
  (display "Importing QIF"))
(define (qif-file f) #f)
(gnc:xtn-file-register-test <gnc:qif-file> qif-file)

;; Same as above, except this would define how to read an xml file
(define-class <gnc:xml-file> (<xtn-file>))
(define-method (gnc:xtn-file-parse (f <gnc:xml-file>))
  (display "Importing XML"))
(define (xml-file f) #f)
(gnc:xtn-file-register-test <gnc:xml-file> xml-file)

;; A factory-type method that returns a <xtn-file> subclass suitable for
;; importing file f (I'm not quite sure how to pass filehandles around
;; yet...).  Basically, it returns an instance of the first class for
;; whose file test operator returns true.

(define-method (initialize-xtn-file f)
  (let init ((t (caar (class-slot-ref <xtn-file> 'xtn-file-alist)))
	     (c (cdar (class-slot-ref <xtn-file> 'xtn-file-alist)))
	     (l (class-slot-ref <xtn-file> 'xtn-file-alist)))
    (if (t f)
       (make c)
       (if (= (length l) 0 )
	   (error "No matching files registered")
	   (init (caadr l) (cdadr l) (cdr l)))))) 

;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;;  EOF
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;

Anthony W. Juckel