From 712eb51facc0ce4567caafef230cdc8cdc0b057f Mon Sep 17 00:00:00 2001 From: Eric van der Vlist Date: Sat, 1 May 2021 12:34:21 +0200 Subject: [PATCH] js-options: refactoring and implementation of housekeeping tasks --- oxygen/js-options/hello.js | 22 ++++- oxygen/js-options/options.js | 168 +++++++++++++++++++++++------------ 2 files changed, 130 insertions(+), 60 deletions(-) diff --git a/oxygen/js-options/hello.js b/oxygen/js-options/hello.js index 1eb57d3..584f212 100644 --- a/oxygen/js-options/hello.js +++ b/oxygen/js-options/hello.js @@ -18,9 +18,9 @@ hello = function () { } // Do the same with file specific options - Packages.java.lang.System.out.println(""); - options.setSystemId(undefined, 1); - Packages.java.lang.System.out.println(""); + Packages.java.lang.System.out.println(""); + options.setSystemId(null, 2); + Packages.java.lang.System.out.println(""); options.setSystemIdOption('Hello', 'aligator'); options.setSystemIdOption('See you later', 'World'); var myOptions = options.getSystemIdOptions(); @@ -32,4 +32,20 @@ hello = function () { // Display some file specific properties Packages.java.lang.System.out.println('options.systemId: ' + options.systemId); Packages.java.lang.System.out.println('options.systemIdDigest: ' + options.systemIdDigest); + + + Packages.java.lang.System.out.println(""); + var options = new Options(authorAccess, 'hello2', 20); + Packages.java.lang.System.out.println(""); + + // Delete options + + // Packages.java.lang.System.out.println('Deleting options'); + // options.deleteOption ('Hello'); + // options.deleteOption ('See you later'); + // myOptions = options.getOptions(); + // for (var key in myOptions) { + // var value = myOptions[key]; + // Packages.java.lang.System.out.println(key + ' ' + value); + // } } \ No newline at end of file diff --git a/oxygen/js-options/options.js b/oxygen/js-options/options.js index 2e431d1..41374db 100644 --- a/oxygen/js-options/options.js +++ b/oxygen/js-options/options.js @@ -1,22 +1,31 @@ /* - * Main features + * + * Shortcuts + * */ -Options = function (authorAccess, namespace, lifetime, __system__) { +const out = Packages.java.lang.System.out; + +/* + * Main features + * + */ + +Options = function (authorAccess, namespace, lifetime, dontUpdateNsExpiration) { this.namespace = namespace; this.authorAccess = authorAccess; this.optionsStorage = this.authorAccess.getOptionsStorage(); this.lifetime = lifetime; this.expiration = Options.getExpiration(lifetime); - // Consider namespaces as a SYSTEM option - if ( __system__ !== true ) { + // Create an Options object in the SYSTEM namespace for internal use + if (this.namespace != Options.SYSTEM) { this.systemOptions = new Options(authorAccess, Options.SYSTEM, null, true); + } + // Update NS expiration unless told otherwise (used for cleanup) + if (dontUpdateNsExpiration != true) { this.__cleanup__(); - var namespaces = JSON.parse(this.systemOptions.getOption(Options.NAMESPACES, '{}')); - namespaces[ this.namespace] = this.expiration; - Packages.java.lang.System.out.println('Namespaces update for ' + this.namespace ); - this.systemOptions.setOption(Options.NAMESPACES, JSON.stringify(namespaces)); + this.systemOptions.setValueInOption(Options.NAMESPACES, this.namespace, this.expiration); } } @@ -25,6 +34,10 @@ Options.NAMESPACES = '__namespaces__'; Options.HOUSEKEEPING = '__housekeeping__'; Options.HOUSEKEEPING_PERIOD = 1; +/* + * Static method to convert a lifetime into an expiration date + * + */ Options.getExpiration = function (lifetime) { if (lifetime == undefined) { return null; @@ -35,32 +48,48 @@ Options.getExpiration = function (lifetime) { } } +/* + * Setter, getter and friends + * + */ Options.prototype.getOption = function (key, defaultValue) { this.optionsStorage.setOptionsDoctypePrefix(this.namespace); return this.optionsStorage.getOption(key, defaultValue); } +Options.prototype.getOptionObject = function (key) { + return JSON.parse(this.getOption(key, '{}')); +} + +Options.prototype.setValueInOption = function (key, objectKey, value) { + var object = this.getOptionObject(key); + if (value == null) { + delete object[objectKey]; + } else { + object[objectKey] = value; + } + if (Object.keys(object).length == 0) { + object = null; + } + this.setOptionObject(key, object); + return object; +} + Options.prototype.setOption = function (key, value) { - this.optionsStorage.setOptionsDoctypePrefix(Options.SYSTEM); - var options = JSON.parse(this.optionsStorage.getOption(this.namespace, '{}')); - options[key] = this.expiration; - this.optionsStorage.setOption(this.namespace, JSON.stringify(options)); + if (this.namespace != Options.SYSTEM) { + this.systemOptions.setValueInOption(this.namespace, key, value == null ? null: this.expiration) + } this.optionsStorage.setOptionsDoctypePrefix(this.namespace); this.optionsStorage.setOption(key, value); } +Options.prototype.setOptionObject = function (key, value) { + this.setOption(key, value == null ? null: JSON.stringify(value)); +} + Options.prototype.deleteOption = function (key) { - this.optionsStorage.setOptionsDoctypePrefix(Options.SYSTEM); - var options = JSON.parse(this.optionsStorage.getOption(this.namespace, '{}')); - delete options[key]; - if (Object.keys(options).length > 0 ){ - this.optionsStorage.setOption(this.namespace, JSON.stringify(options)); - } else { - this.optionsStorage.setOption(this.namespace, null); - } - this.optionsStorage.setOptionsDoctypePrefix(this.namespace); - this.optionsStorage.setOption(key, null); + this.setOption(key, null); } Options.prototype.getOptionKeys = function () { @@ -92,13 +121,17 @@ Options.prototype.getOptions = function () { Options.SYSTEMIDS = '__systemIds__'; +/* + * Set the system Id (current file by default, current lifetime by default) + * + */ Options.prototype.setSystemId = function (systemID, lifetime) { - if (systemID === undefined) { + if (systemID == undefined) { this.systemId = String(this.authorAccess.getDocumentController().getAuthorDocumentNode().getSystemID()); } else { this.systemId = String(systemID); } - if (lifetime === undefined) { + if (lifetime == undefined) { this.systemIdLifetime = this.lifetime; } else { this.systemIdLifetime = lifetime; @@ -106,15 +139,42 @@ Options.prototype.setSystemId = function (systemID, lifetime) { var md = java.security.MessageDigest.getInstance("SHA-1"); var digestBytes = md.digest(java.lang.String(this.systemId).getBytes(java.nio.charset.Charset.forName("UTF-8"))); this.systemIdDigest = javax.xml.bind.DatatypeConverter.printHexBinary(digestBytes); - var systemIds = JSON.parse(this.systemOptions.getOption(Options.SYSTEMIDS, '{}')); - systemIds[ this.systemIdDigest] = { - date: (new Date()).toISOString(), - systemId: this.systemId - } - this.systemOptions.setOption(Options.SYSTEMIDS, JSON.stringify(systemIds)); + // Uncomment to store inverse matching + // var systemIds = JSON.parse(this.systemOptions.getOption(Options.SYSTEMIDS, '{}')); + // systemIds[ this.systemIdDigest] = { + // date: (new Date()).toISOString(), + // systemId: this.systemId + // } + // this.systemOptions.setOption(Options.SYSTEMIDS, JSON.stringify(systemIds)); this.systemIdOptions = new Options(this.authorAccess, this.namespace + '.' + this.systemIdDigest, this.systemIdLifetime); } +/* + * Setter, getter and friends + * + */ +Options.prototype.getSystemIdOption = function (key, defaultValue) { + if (this.systemIdOptions == undefined) { + this.setSystemId(); + } + return this.systemIdOptions.getOption(key, defaultValue); +} + +Options.prototype.getSystemIdOptionObject = function (key) { + if (this.systemIdOptions == undefined) { + this.setSystemId(); + } + return this.systemIdOptions.getOptionObject(key); +} + +Options.prototype.setSystemIdValueInOption = function (key, objectKey, value) { + if (this.systemIdOptions == undefined) { + this.setSystemId(); + } + return this.systemIdOptions.setValueInOption(key, objectKey, value); +} + + Options.prototype.setSystemIdOption = function (key, value) { if (this.systemIdOptions == undefined) { this.setSystemId(); @@ -122,6 +182,13 @@ Options.prototype.setSystemIdOption = function (key, value) { this.systemIdOptions.setOption(key, value); } +Options.prototype.setSystemIdOptionObject = function (key, value) { + if (this.systemIdOptions == undefined) { + this.setSystemId(); + } + this.systemIdOptions.setOptionObject(key, value); +} + Options.prototype.deleteSystemIdOption = function (key) { if (this.systemIdOptions == undefined) { this.setSystemId(); @@ -129,13 +196,6 @@ Options.prototype.deleteSystemIdOption = function (key) { this.systemIdOptions.deleteOption(key); } -Options.prototype.getSystemIdOption = function (key, defaultValue) { - if (this.systemIdOptions == undefined) { - this.setSystemId(); - } - return this.systemIdOptions.getOption(key, defaultValue); -} - Options.prototype.getSystemIdOptions = function () { if (this.systemIdOptions == undefined) { this.setSystemId(); @@ -163,26 +223,25 @@ Options.prototype.getSystemOptions = function () { * */ +/* + * + * General cleanup + * + */ Options.prototype.__cleanup__ = function () { -// TODO: delete systemIds var nextCleanup = this.systemOptions.getOption(Options.HOUSEKEEPING, null); - Packages.java.lang.System.out.println('nextCleanup: ' + nextCleanup); if (nextCleanup == null) { this.systemOptions.setOption(Options.HOUSEKEEPING, Options.getExpiration(Options.HOUSEKEEPING_PERIOD)); } else { - this.currentDate = (new Date()).toISOString(); - //this.currentDate = Options.getExpiration(10); - Packages.java.lang.System.out.println('currentDate: ' + this.currentDate); + this.currentDate = Options.getExpiration(0); if (nextCleanup <= this.currentDate) { - Packages.java.lang.System.out.println('Time to clean !'); var namespaces = JSON.parse(this.systemOptions.getOption(Options.NAMESPACES, '{}')); for (var name in namespaces) { - if ( ! this.__cleanupNamespace__(name, namespaces[name])) { - delete namespaces[name]; - Packages.java.lang.System.out.println('deleting empty namespace ' + name); - }; + if (! this.__cleanupNamespace__(name, namespaces[name])) { + delete namespaces[name]; + }; } this.systemOptions.setOption(Options.NAMESPACES, JSON.stringify(namespaces)); this.systemOptions.setOption(Options.HOUSEKEEPING, Options.getExpiration(Options.HOUSEKEEPING_PERIOD)); @@ -190,26 +249,21 @@ Options.prototype.__cleanup__ = function () { } } -/* - * +/* + * * Cleanup a namespace, return true if there are still keys in the namespace - * + * */ Options.prototype.__cleanupNamespace__ = function (name, namespaceExpiration, currentDate) { - Packages.java.lang.System.out.println('Cleanup for namespace ' + name + ' / ' + namespaceExpiration); var namespaceExpired = namespaceExpiration != null && namespaceExpiration <= this.currentDate; var options = new Options(this.authorAccess, name, undefined, true); var nsOptions = options.getOptionKeys(); for (var key in nsOptions) { var keyExpiration = nsOptions[key]; - Packages.java.lang.System.out.println(' Cleanup for option ' + key + ' / ' + keyExpiration); - if ( namespaceExpired || (keyExpiration != null && keyExpiration <= this.currentDate) ) { + if (namespaceExpired || (keyExpiration != null && keyExpiration <= this.currentDate)) { options.deleteOption(key); - Packages.java.lang.System.out.println(' deleting key ' + key); } } nsOptions = options.getOptionKeys(); return Object.keys(nsOptions).length > 0; - - -} +} \ No newline at end of file