Outdated egg!
This is an egg for CHICKEN 4, the unsupported old release. You're almost certainly looking for the CHICKEN 5 version of this egg, if it exists.
If it does not exist, there may be equivalent functionality provided by another egg; have a look at the egg index. Otherwise, please consider porting this egg to the current version of CHICKEN.
gromit
- Outdated egg!
- gromit
- Description
- Source Code
- Author
- Requirements
- API
- make-object-id
- define-attribute-type
- define-property-type
- define-property-constructor
- create-table-%metadata
- object-metadata-name
- object-metadata-description
- object-metadata-version
- object-metadata-created
- object-metadata-created-by
- object-metadata-last-modified
- object-metadata-last-modified-by
- object-id
- object-type
- define-object-type
- define-object-constructor
- define-object-finder
- current-gromit-db
- open-gromit-database
- current-gromit-user
- Built-in Field Types
- License
- Version History
Description
gromit - A Graph-like Object Persistence Toolkit.
Source Code
https://github.com/register-dynamics/gromit
Author
Requirements
API
make-object-id
[procedure] (make-object-id node-id seqno)define-attribute-type
[syntax] (make-object-id type 'SQL-TYPE serialiser: serialiser deserialiser: deserialiser initialiser: initialiser setter: setter getter: getter)Creates a new type of attribute.
column-type : The type of the underlying column that is used for the serialised value when it is stored in the database. serialiser : Called when an object or property is being saved back to the database. A procedure of one argument that receives the current value of the attribute in memory and returns a serialised version of the attribute suitable for storing in SQLite. Each time an attempt is made to write the object or property back to the database, this is called no more than once. deserialiser : Called when an object or property is being read from the database. A procedure of one argument that receives the value of the attribute from the database and returns a deserialied version of the attribute suitable for storing in memory. Each time an attempt is makde to read the object or property back from the database, this is called no more than once. initialiser : Called when a new object that contains this attribute is being allocated. A procedure of no arguments that must return the initial value for the attribute. The value returned must be a deserialised value suitable for storing in memory. Defaults to #f. This is called the first time an attempt is made to allocate the object or property. If the allocation subsequently fails, it will not be called again. setter : Called when user code tries to set the value of an attribute. A procedure of one argument that receives the value supplied by the user as used in CHICKEN code and returns the value suitable for storing in memory. Usually the identity procedure or a guard. If the attribute is marked as constant by the structure that uses it then the setter procedure is only called before the structure has been written to disk for the first time. Defaults to the identity procedure. getter : Called when user code tries to get the value of an attribute. A procedure of one argument that receives the value stored in memory and returns a value for the user, suitable for use in CHICKEN code. Defaults to the identity procedure.
The built-in attribute types are:
- integer
- text
- blob
- boolean
- symbol
- wallclock
- node-id/current-node
- timestamp/next
- current-user/node-id
- current-user/seqno
See `gromit-types.scm` for more examples.
(define constantly-NULL (constantly NULL)) (define (value-or-NULL v) (if v v NULL)) (define-attribute-type integer 'INTEGER serialiser: value-or-NULL deserialiser: value-or-false initialiser: constantly-NULL setter: (lambda (i) (cond ((integer? i) i) ((eq? #f i) i) (else (assert #f (conc "integer field expected an integer or #f. We got " i "!"))))) getter: identity)
define-property-type
[syntax] (define-property-type name table fields...)Creates a property type. An Object's field list can consist of attribute types or property types. Attributes are simple types that are stored in a single column in the object's database table. Properties are more complex types that are stored in their own database table. A property's field list can consist of attribute types only: property types cannot be nested. An Object's property fields can have zero or more values. If an Object needs to have a property field with more than one value then you must denote some of the property fields as keys. The key, which may consist of several fields, must be unique for each property of that type for a particular Object.
(define-property-type password 'prop_password
(set wallclock required constant (key 0))
(algorithm symbol required constant)
(iterations integer required constant)
(salt text required constant)
(crypt blob required constant))
define-property-constructor
[syntax] (define-property-constructor name type proc)Defines a constructor, `proc`, for a property type. `proc` takes a freshly made, but uninitialised, property as its first argument. Any subsequent arguments are user defined. `proc` then manipulates the provided property using the regular property accessors. When `proc` has finished executing, the constructed property is returned to the user. The return value of `proc` is ignored.
(define-property-constructor make-password* password
(lambda (p plaintext)
; https://ruby-doc.org/stdlib-2.0.0/libdoc/openssl/rdoc/OpenSSL/PKCS5.html
(let ((iterations 10000)
(salt (make-salt 32)) ; 256 bits matching 256 bit digest function.
(dklen 32)) ; (/ 256 8)
(password-algorithm p 'pbkdf2-hmac-sha256)
(password-iterations p iterations)
(password-salt p salt)
(password-crypt p (pbkdf2-hmac-sha256 plaintext salt iterations dklen 'blob)))))
create-table-%metadata
<symbol>create-table-%metadata</symbol>
The create table statement for the object metadata table:
#;2> create-table-%metadata "CREATE TABLE objects (\"node-id\" INTEGER NOT NULL, \"seqno\" INTEGER NOT NULL, \"name\" TEXT, \"description\" TEXT, \"version-ts\" INTEGER NOT NULL, \"version-node-id\" INTEGER NOT NULL, \"created\" INTEGER NOT NULL, \"created-by-node-id\" INTEGER NOT NULL, \"created-by-seqno\" INTEGER NOT NULL, \"last-modified\" INTEGER NOT NULL, \"last-modified-by-node-id\" INTEGER NOT NULL, \"last-modified-by-seqno\" INTEGER NOT NULL, PRIMARY KEY (\"node-id\", \"seqno\"))"
object-metadata-name
object-metadata-description
object-metadata-version
object-metadata-created
object-metadata-created-by
object-metadata-last-modified
object-metadata-last-modified-by
[procedure] (object-metadata-name object [value])[procedure] (object-metadata-description object [value])
[procedure] (object-metadata-version object [value])
[procedure] (object-metadata-created object [value])
[procedure] (object-metadata-created-by object [value])
[procedure] (object-metadata-last-modified object [value])
[procedure] (object-metadata-last-modified-by object [value])
Getters/setters for the object metadata.
object-id
[procedure] (object-id object)Gets the object ID of the object if it has been allocated in the database, otherwise #f.
object-type
[procedure] (object-type object)Returns a symbol denoting the type of the object, as declared in `define-object-type`.
define-object-type
[syntax] (define-object-type name table fields...)Creates an object type. An Object's field list can consist of attribute types or property types. Attributes are simple types that are stored in a single column in the object's database table. Properties are more complex types that are stored in their own database table. An Object's property fields can have zero or more values.
(define-object-type email-address 'attrib_email_address
(domain-part text required constant)
(local-part text required constant)
(local-part-ci text required constant)
(use-for-notifications boolean required)
(verified integer)
(preferred-content-type symbol required))
...or one that has a field that's a property (as defined with `define-property-type`) rather than an attribute:
(define-object-type account 'attrib_account
(onboarding integer)
(password password))
define-object-constructor
[syntax] (define-object-constructor name type proc)Defines a constructor, `proc`, for an object type. `proc` takes a freshly made, but uninitialised, object as its first argument. Any subsequent arguments are user defined. `proc` then manipulates the provided object using the regular object accessors. When `proc` has finished executing, the constructed object is returned to the user. The return value of `proc` is ignored.
(define-object-constructor make-email-address* email-address
(lambda (e address use-for-notifications)
(assert (string? address))
(let ((addr (x-email-address address)))
(assert addr (conc "mail-email-address*: Expected a valid eMail address. We got " address "!"))
(email-address-domain-part e (domain-part->string addr))
(email-address-local-part e (local-part->string addr))
(email-address-local-part-ci e (local-part->string-ci addr))
(email-address-use-for-notifications e use-for-notifications)
(email-address-verified e #f)
(email-address-preferred-content-type e 'fancy-html))))
define-object-finder
[syntax] (define-object-finder signature type conditions)Defines a procedure that finds an object of the specified type using the condition specified. The argument list in the signature consists of argument names and argument types. The argument names can then be used in the conditions.
(define-object-finder (find-email-address
(local-part text)
(domain-part text))
email-address
`(and (= (@ domain-part) ,domain-part)
(= (@ local-part) ,local-part)
(> (@ verified) ,*some-time*)))
current-gromit-db
[parameter] current-gromit-dbMust be set to something returned by `open-gromit-database`.
open-gromit-database
[procedure] (open-gromit-database filename)filename is an SQLite database file.
current-gromit-user
[parameter] current-gromit-userAn object id created with `make-object-id`. Operations performed on the database are done as this user. i.e this ID is stamped into the created-by and last-modified-by fields of objects that are created or save!ed.
Built-in Field Types
- integer
- text
- blob
- boolean
- symbol
- wallclock
- node-id/current-node
- timestamp/next
- current-user/node-id
- current-user/seqno
See `gromit-types.scm` for details.
License
Copyright (C) 2019, Andy Bennett, Register Dynamics Limited. All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. Neither the name of the author nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
Version History
- 0.1, (2019/08/09) : Preliminary support for defining object models and manipulating instances of those objects. Includes persistence to an SQLite database.