1 ######################################################################
2 ## Copyright (C) 2006, Roger D. Peng <rpeng@jhsph.edu>
4 ## This program is free software; you can redistribute it and/or modify
5 ## it under the terms of the GNU General Public License as published by
6 ## the Free Software Foundation; either version 2 of the License, or
7 ## (at your option) any later version.
9 ## This program is distributed in the hope that it will be useful,
10 ## but WITHOUT ANY WARRANTY; without even the implied warranty of
11 ## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 ## GNU General Public License for more details.
14 ## You should have received a copy of the GNU General Public License
15 ## along with this program; if not, write to the Free Software
16 ## Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
18 #####################################################################
20 ######################################################################
23 setClass("filehash", representation(name = "character"))
25 setValidity("filehash", function(object) {
26 if(length(object@name) == 0)
27 "database name has length 0"
32 setGeneric("dbName", function(db) standardGeneric("dbName"))
33 setMethod("dbName", "filehash", function(db) db@name)
35 setMethod("show", "filehash",
37 if(length(object@name) == 0)
38 stop("database does not have a name")
39 cat(gettextf("'%s' database '%s'\n", as.character(class(object)),
44 ######################################################################
46 registerFormatDB <- function(name, funlist) {
47 if(!all(c("initialize", "create") %in% names(funlist)))
48 stop("need both 'initialize' and 'create' functions in 'funlist'")
49 r <- list(list(create = funlist[["create"]],
50 initialize = funlist[["initialize"]]))
52 do.call("filehashFormats", r)
56 filehashFormats <- function(...) {
61 assign(n, args[[n]], .filehashFormats)
62 current <- as.list(.filehashFormats)
70 ######################################################################
71 ## Create necessary database files. On successful creation, return
72 ## TRUE. If the database already exists, don't do anything but return
73 ## TRUE (and print a message). If there's any other strange
74 ## condition, return FALSE.
76 dbStartup <- function(dbName, type, action = c("initialize", "create")) {
77 action <- match.arg(action)
78 validFormat <- type %in% names(filehashFormats())
81 stop(gettextf("'%s' not a valid database format", type))
82 formatList <- filehashFormats()[[type]]
83 doFUN <- formatList[[action]]
85 if(!is.function(doFUN))
86 stop(gettextf("'%s' function for database format '%s' is not valid",
91 setGeneric("dbCreate", function(db, ...) standardGeneric("dbCreate"))
93 setMethod("dbCreate", "ANY",
94 function(db, type = NULL, ...) {
96 type <- filehashOption()$defaultType
98 dbStartup(db, type, "create")
102 setGeneric("dbInit", function(db, ...) standardGeneric("dbInit"))
104 setMethod("dbInit", "ANY",
105 function(db, type = NULL, ...) {
107 type <- filehashOption()$defaultType
108 dbStartup(db, type, "initialize")
111 ######################################################################
112 ## Set options and retrieve list of options
114 filehashOption <- function(...) {
118 for(n in names(args))
119 assign(n, args[[n]], .filehashOptions)
120 current <- as.list(.filehashOptions)
122 if(length(args) == 0)
128 ######################################################################
129 ## Load active bindings into an environment
131 setGeneric("dbLoad", function(db, ...) standardGeneric("dbLoad"))
133 setMethod("dbLoad", "filehash",
134 function(db, env = parent.frame(2), keys = NULL, ...) {
137 else if(!is.character(keys))
138 stop("'keys' should be a character vector")
139 active <- sapply(keys, function(k) {
140 exists(k, env, inherits = FALSE)
143 warning("keys with active/regular bindings ignored: ",
144 paste(sQuote(keys[active]), collapse = ", "))
145 keys <- keys[!active]
147 make.f <- function(k) {
150 if(!missing(value)) {
151 dbInsert(db, key, value)
155 obj <- dbFetch(db, key)
161 makeActiveBinding(k, make.f(k), env)
165 setGeneric("dbLazyLoad", function(db, ...) standardGeneric("dbLazyLoad"))
167 setMethod("dbLazyLoad", "filehash",
168 function(db, env = parent.frame(2), keys = NULL, ...) {
171 else if(!is.character(keys))
172 stop("'keys' should be a character vector")
174 wrap <- function(x, env) {
176 delayedAssign(x, dbFetch(db, key), environment(), env)
183 ## Load active bindings into an environment and return the environment
185 db2env <- function(db) {
187 db <- dbInit(db) ## use the default type
188 env <- new.env(hash = TRUE)
193 ######################################################################
197 setMethod("with", "filehash",
198 function(data, expr, ...) {
200 eval(substitute(expr), env, enclos = parent.frame())
204 setMethod("lapply", signature(X = "filehash"),
205 function(X, FUN, ..., keep.names = TRUE) {
206 FUN <- match.fun(FUN)
208 rval <- vector("list", length = length(keys))
210 for(i in seq(along = keys)) {
211 obj <- dbFetch(X, keys[i])
212 rval[[i]] <- FUN(obj, ...)
219 ######################################################################
220 ## Database interface
222 setGeneric("dbMultiFetch", function(db, key, ...) standardGeneric("dbMultiFetch"))
223 setGeneric("dbInsert", function(db, key, value, ...) standardGeneric("dbInsert"))
224 setGeneric("dbFetch", function(db, key, ...) standardGeneric("dbFetch"))
225 setGeneric("dbExists", function(db, key, ...) standardGeneric("dbExists"))
226 setGeneric("dbList", function(db, ...) standardGeneric("dbList"))
227 setGeneric("dbDelete", function(db, key, ...) standardGeneric("dbDelete"))
228 setGeneric("dbReorganize", function(db, ...) standardGeneric("dbReorganize"))
229 setGeneric("dbUnlink", function(db, ...) standardGeneric("dbUnlink"))
231 ######################################################################
232 ## Extractor/replacement
234 setMethod("[[", signature(x = "filehash", i = "character", j = "missing"),
239 setMethod("$", signature(x = "filehash", name = "character"),
244 setReplaceMethod("[[", signature(x = "filehash", i = "character", j = "missing"),
245 function(x, i, j, value) {
246 dbInsert(x, i, value)
250 setReplaceMethod("$", signature(x = "filehash", name = "character"),
251 function(x, name, value) {
252 dbInsert(x, name, value)
257 ## Need to define these because they're not automatically caught.
258 ## Don't need this if R >= 2.4.0.
260 setReplaceMethod("[[", signature(x = "filehash", i = "numeric", j = "missing"),
261 function(x, i, j, value) {
262 stop("numeric indices not allowed")
265 setMethod("[[", signature(x = "filehash", i = "numeric", j = "missing"),
267 stop("numeric indices not allowed")
270 setMethod("[", signature(x = "filehash", i = "ANY", j = "ANY", drop = "missing"),
271 function(x, i, j, drop) {
272 stop("multiple indices via '[' not allowed")