mirror of https://github.com/Gnucash/gnucash
You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
198 lines
9.9 KiB
198 lines
9.9 KiB
Date: Mon, 19 Oct 1998 11:08:53 +0200
|
|
From: Stephan Lichtenauer <s_lichtenauer@muenchen.org>
|
|
To: linas@linas.org
|
|
Subject: [Fwd: ANNOUNCE version 1.1.20]
|
|
|
|
DESIGN PROPOSAL (ROUGH OUTLINE)
|
|
-----------------------------
|
|
|
|
I thought that there is only one engine that manages runtime data, but
|
|
to store and read it it uses the i/o-plugins that handle the data in a very
|
|
abstract way, ie they know only as much about it as absolutely necessary so
|
|
changes of data representation only affects the engine and not the plugins (in
|
|
most cases). Nevertheless i would say that they are backend since they do not
|
|
need an ui. Necessary addresses/file names can be obtained in a standardized way
|
|
through the application. It could work with the CORBA persistence framework if I
|
|
remember right and the GNOME VFS.
|
|
|
|
Engine
|
|
--------
|
|
|
|
Split the existing engine in the following classes that match the existing data
|
|
structures:
|
|
|
|
- GcAccountGroup
|
|
- GcAccount
|
|
- GcSplit
|
|
- GcTransaction
|
|
- GcEngine
|
|
|
|
These five classes first of all simply use the design already used in the
|
|
engine. Additionally I would introduce a class
|
|
|
|
- GcRegistry
|
|
|
|
that is used to store some metadata that is used by e.g. plug ins or the user
|
|
interface. Since there is in my eyes need for two different classes of metadata,
|
|
global and account-group related one, I would give GcAccountGroup as well as
|
|
GcEngine a gcGetRegistry method that returns the local and the global registry
|
|
object. The registry can store its data in the account database and (global
|
|
data) in the config file in the user's root directory. An example for global
|
|
metadata of my plugin would be a database of all REUTERS codes of stocks
|
|
available, in the local registry (the account-group related one) the plug in can
|
|
save e.g. what codes have been selected to be updated etc. An ui could store
|
|
general options (e.g. user preferences) in the global registry and e.g. last
|
|
position of windows in the local registry.
|
|
GcEngine could as well be a metaclass since it only has to represent the engine
|
|
as such, with methods like gcReadAccountGroup.
|
|
GcSplit could be an abstract class whose functionality can be implemented
|
|
in derived concrete classes, e.g. for simple money transfers, buy of securities
|
|
(which will be further divided in stocks, futures, bonds) etc. Alternatively
|
|
additional
|
|
data could be stored in an extended comment field with every split in MIME format.
|
|
Infrastructure for that is already partially implemented but is (in my eyes) no
|
|
perfectly
|
|
clear OOP design.
|
|
|
|
One GcSplit subclass is GcComment that can store general data like company
|
|
statements. Since this could be data that affects more than one account (e.g.
|
|
general economical data), it is stored centralized and the GcComment object in
|
|
the different accounts only point on this data. GcSplit subclasses that
|
|
represent any type of securities will have to have additional fields, e.g. to
|
|
store maturities, volume (for special price quotes) etc.
|
|
|
|
In the design outline on the webpage a transparent mechanism to read data from
|
|
different sources is proposed. I would realize this completely with plug in
|
|
objects. So I would introduce
|
|
|
|
- GcPlugIn
|
|
|
|
to be the base class of all plug ins. How to make plugins independent from ui
|
|
toolkits (GTK, QT/KDE), I do not know since they will need an ui in many cases.
|
|
|
|
- GcIOPlugIn
|
|
|
|
is derived from it and will be the base class for all i/o plugins, e.g.
|
|
GcIOXacc, GcIOQif, GcIOSql, GcIOOnlineBanking, GcIOReadWww (yeah, my plugin!)
|
|
etc. Since some of the media is non-persistent, ie it is not sure if you will
|
|
get the data again in the future (e.g. from web pages), GcIOPlugIn has a method
|
|
gcIsPersistentMedia that returns FALSE in such cases. Then the data obtained
|
|
from this source can be copied to a persistent media (e.g. the SQL database).
|
|
An IO plugin has a limited lifespan and is only used to read/write data from/to
|
|
accounts/account groups/splits resp. create these objects as appropriate when
|
|
reading data.
|
|
|
|
One example:
|
|
You make a bank transfer in your account. The data is written to the
|
|
GcIOOnlineBanking object that uses the WWW-interface of your bank to give the
|
|
data to your bank. Then it reads the state of the transfer (via an online
|
|
request to your bank account balance) what will then appear in your account.
|
|
Possibly the GcIOOnlineBanking plugin is not persistent, i.e. you will not get a
|
|
full track of all of your transactions of the past via online banking, then the
|
|
data is stored locally (e.g. via GcIOPlugInXacc).
|
|
|
|
One account group so can use many IO plugins at the same to get its data.
|
|
Perhaps the IO plugins could be based on the GNOME VFS (virtual file system), if
|
|
this is not an unwanted dependency.
|
|
|
|
In this system of course there is one big problem: How to map the data obtained
|
|
from a source to the accounts. If you read it from your account group file of
|
|
course you have account ids and account name, but if you read from www stock
|
|
quotes or MetaStock data or online banking interfaces that is not that simple;
|
|
and it also has to work the other way round. So we need a
|
|
|
|
- GcDataMapper
|
|
|
|
class that has at least two methods gcFindAccounts and gcFindSources. Both get a
|
|
|
|
- GcMapInfo
|
|
|
|
struct as parameter that contains information on how to find the account or the
|
|
source. Both return a vector of GcMapInfos that contain information about
|
|
the matches. When you call gcFindAccounts you normally fill the fields with data
|
|
like the banking account number, REUTERS codes etc. and the method returns a
|
|
list of accounts that could match. If there is more or less then one account the
|
|
user could be prompted to help; the data obtained from a succesful match will be
|
|
stored in the registry by the GcDataMapper so it can be used in the future and
|
|
to do reverse mapping. Reverse mapping is what gcFindSources is for. There you
|
|
fill the GcMapInfo with the things like accountId, account name, comments etc.
|
|
and the GcDataMapper tries to find (with the help of its registry if there is
|
|
already some data available) some sources (e.g. quotes web pages, online banking
|
|
interfaces, company web pages etc.) and the IO plugins for this account. Again
|
|
user help could be involved the first time or later again if the user wants to
|
|
modify the matches. How to actually do the mapping is job of the GcDataMapper,
|
|
it could use regexp libraries etc. The most simple implementation would to be a
|
|
simple user query where the user has to find the matches.
|
|
|
|
Example:
|
|
When I have an account called "Silicon Graphics stocks" and I want to obtain
|
|
stock quotes from the web I have to find a web page where to get them from. When
|
|
I have a plug in for that I could deliver it with a database containing some
|
|
addresses for stock quotes for REUTERS-code "SGI" (or in Germany we have the
|
|
very easy-to-remember six-digit numbers, eg 872981 for SGI), this database will
|
|
be appended to the data mapper database. But now we have to find out that "SGI"
|
|
is what we are searching for, this is the mapper doing with eg regexp. He now
|
|
finds "SGI" beside some other sources, now the user could select the one(s) he
|
|
wants. The mapper stores the selection so he can do this automatically in the
|
|
future and also in reverse. If the quotes plugin has a cron-mechanism to update
|
|
some selected quotes every 1.5 seconds, the data mapper knows where the "SGI"
|
|
data goes to now. The same with online banking: map the accountId/-name on the
|
|
bank code/account number etc. if I have a remittance, and get accountId/-name
|
|
when there comes in a bank statement. So the mapper is a kind of "dynamic
|
|
linking" mechnism (with memory, so a little bit static, too, yes) to allow the
|
|
engine to search and parametrize the necessary plugins and to find out what to
|
|
do with the data they deliver.
|
|
|
|
A second type would be the
|
|
|
|
- GcReportPlugIn
|
|
|
|
that is used for report generation/data analyzing. A report interface that
|
|
generates HTML code (that can then be translated to SGML, PS, TeX etc. via an
|
|
additional tool) is proposed on the developers web page. So I would propose an
|
|
ui that is an HTML designer, very much like a wordprocessor or the Mathematica
|
|
frontend, and include automatically generated reports (tables for account
|
|
balances, graphs etc) with a reserved HTML keyword that also allows you to
|
|
specify some layout parameters like size and position. When the document finally
|
|
is generated, a parser calls for every of these keywords the appropriate report
|
|
plugin and replaces it with the output of the plugin (that has to be pure HTML
|
|
code with embedded images etc.). Chaining of report plug ins could be helpful,
|
|
e.g. first filter stock quotes from noise with a plugin before they are used in
|
|
a technical analysis tool.
|
|
|
|
Finding and linking the plugins to the engine could esaily be done via the CORBA
|
|
repository.
|
|
|
|
Report plugins first of all have to have a kind of
|
|
string gcMakeReport(string params);
|
|
method that gets the parameters stored in the HTML command (e.g. accoundId, data
|
|
range, graph type etc.), this has to be obtained through dialogs that are
|
|
maintained by the plugin itself, this is why I have said I do not know how to
|
|
make plugins toolkit-independent) and returns the generated HTML-code. They
|
|
have to have a second method to display this dialog and a
|
|
general plug-in mechanism that allows to find and load GnuCash corba plugins;
|
|
this of course is already introduced in the GcPlugIn class.
|
|
If plugins are chainable the gcMakeReport has to be modified/extended that they
|
|
get can get an account(-group) as input and return a new, modified
|
|
account(-group) that could be then input for a second plugin (eg the one that
|
|
finally creates the HTML-code). A usage for that could be a filter that eliminates
|
|
noise in stock quotes and so generates new quotes that are then used as input to a
|
|
Chaikin
|
|
Oscillator plugin.
|
|
|
|
|
|
I hope it is in line with all the other proposals (e.g. scripting, budget engine
|
|
etc).
|
|
I did not mention script languages in this document, I think it should be
|
|
possible to access the engine via CORBA bindings for all these languages and to
|
|
even create new classes or derive them, so writing plugins should be easily
|
|
possible with compiled languages as well as with interpreted ones.
|
|
|
|
|
|
Stephan Lichtenauer
|
|
Rassosiedlung 25
|
|
82284 Grafrath
|
|
s_lichtenauer@muenchen.org
|
|
|
|
|