Created
February 12, 2020 03:19
-
-
Save IvanaGyro/92d31f3e5c05e38ac2be8036a228ffaa to your computer and use it in GitHub Desktop.
Wrap java objects to get the properties with the dot operator.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
const java = require('java'); | |
const path = require('path'); | |
const JAVA_DIR = path.resolve(__dirname, '../libs/java/'); | |
java.options = [ '-Xms3072m' , '-Xmx3072m', '-Xmn1152m' ]; | |
java.asyncOptions = { | |
asyncSuffix: 'Async', | |
syncSuffix: '', // For readability, remove the convetional suffix of sync | |
// functions. | |
ifReadOnlySuffix: '_alt', | |
}; | |
java.classpath.push(path.resolve(JAVA_DIR, 'hanlp/hanlp-1.7.3.jar')); | |
java.classpath.push(path.resolve(JAVA_DIR, 'gson/gson-2.8.5.jar')); | |
const gson = java.newInstanceSync('com.google.gson.Gson'); | |
/** | |
* I do not know where is the current working directory of JMV, so set the | |
* properties path of HanLP mannually. | |
*/ | |
const Predefine = java.import('com.hankcs.hanlp.utility.Predefine'); | |
Predefine.HANLP_PROPERTIES_PATH = | |
path.resolve(__dirname, '../libs/java/hanlp/hanlp.properties'); | |
/** | |
* Cache the classes object imported from Java. | |
*/ | |
var classes = {}; | |
var newClassTarget = function (javaClass, className) { | |
// To enable handling construct operattor, `new`, the target must have a | |
// `[[Construct]]` internal method (i.e. `new target` must be valid). | |
// Please refer to: | |
// https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Proxy/handler/construct | |
var r = function () {}; | |
r.javaClass = javaClass; | |
r.className = className; | |
return r; | |
}; | |
var ImporterTarget = function (prefix) { | |
this.prefix = prefix; | |
}; | |
var instanceHandler = { | |
get: function (target, name) { | |
var r = target[name]; | |
if (r === undefined) return undefined; | |
if (r.constructor === Function) { | |
return (...args) => { | |
// `r(...args)` will crash the java bridge, I don't know why | |
// var res = r(...args); | |
var res = java.callMethodSync(target, name, ...args); | |
return JSON.parse(gson.toJson(res)); | |
} | |
} else if (r.constructor.name.startsWith('nodeJava')) { // is a Java object | |
return new Proxy(r, instanceHandler); | |
} else { | |
return r; | |
} | |
}, | |
}; | |
var classHandler = { | |
get: function (target, name) { | |
var r = target.javaClass[name]; | |
if (r === undefined) return r; | |
if (r.constructor === Function) { | |
if (Object.keys(r).length != 0) { | |
// If `r` has keys, it may be a subclass. | |
let subClassName = target.className + '$' + name; | |
let klass = hasClass(subClassName); | |
if (klass) return klass; | |
} | |
return (...args) => { | |
// `apply` is not work because accessing the function `r` by `apply` may | |
// skip the proxy set by the module, `java`. | |
// var res = r.apply(null, arguments); | |
var res = r(...args); | |
return gson.toJson(res); | |
} | |
} else if (r.constructor.name == 'nodeJava_java_lang_Class') { | |
// The first argument of `java.import()` must be an object, so comparing | |
// the name of constructor is more general. | |
return new Proxy( | |
newClassTarget(r, target.name + '.' + name), | |
classHandler); | |
} else if (r.constructor.name.startsWith('nodeJava')) { // is a Java object | |
return new Proxy(r, instanceHandler); | |
} else { | |
return r; | |
} | |
}, | |
set: function (target, name, value) { | |
target.javaClass[name] = value; | |
}, | |
construct: function (target, args) { | |
var instance = java.newInstanceSync(target.className, ...args); | |
return new Proxy(instance, instanceHandler); | |
} | |
}; | |
var hasClass = function (fullClassName) { | |
if (fullClassName in classes) return classes[fullClassName]; | |
try { | |
let javaClass = java.import(fullClassName); | |
classes[fullClassName] = | |
new Proxy( | |
newClassTarget(javaClass, fullClassName), | |
classHandler); | |
return classes[fullClassName]; | |
} catch (err) { | |
if (err.cause && | |
java.instanceOf(err.cause, 'java.lang.NoClassDefFoundError')) { | |
// not found | |
return false; | |
} else { | |
// unknown error | |
throw err; | |
} | |
} | |
}; | |
var importerHandler = { | |
get: function(target, name) { | |
var fullClassName = 'com.hankcs.hanlp' + target.prefix + '.' + name; | |
var klass = hasClass(fullClassName); | |
if (klass) return klass; | |
return new Proxy( | |
new ImporterTarget(target.prefix + '.' + name), | |
importerHandler, | |
); | |
} | |
}; | |
var HanLP = new Proxy(new ImporterTarget(''), importerHandler); | |
module.exports = HanLP; |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment