467 lines
No EOL
13 KiB
JavaScript
467 lines
No EOL
13 KiB
JavaScript
/*
|
|
BeyondRhino.JS
|
|
by Dan Shappir and Sjoerd Visscher
|
|
For more information see http://w3future.com/html/beyondJS
|
|
*/
|
|
load("beyond.js", "beyondLazy.js", "beyondStreams.js");
|
|
|
|
var beyondRhinoVer = 0.9;
|
|
var Beyond = {};
|
|
|
|
importPackage(java.util);
|
|
|
|
function javaArray(type, length) {
|
|
var alloc = new Function("length", "return java.lang.reflect.Array.newInstance(" + type + ", length)");
|
|
return alloc(length);
|
|
}
|
|
|
|
function alert(s) {
|
|
print(s);
|
|
}
|
|
|
|
function toJava(v, asObjects) {
|
|
return typeof(v.toJava) == "function" ? v.toJava(asObjects) : v;
|
|
}
|
|
|
|
_NP.toJava = function() {
|
|
var v = this.valueOf();
|
|
return v == Math.round(v) ? new java.lang.Integer(v) : new java.lang.Double(v);
|
|
};
|
|
_SP.toJava = function() {
|
|
var v = this.valueOf();
|
|
return new java.lang.String(v);
|
|
};
|
|
Boolean.prototype.toJava = function() {
|
|
var v = this.valueOf();
|
|
return new java.lang.Boolean(v);
|
|
};
|
|
|
|
function javaType(v) {
|
|
switch ( typeof(v) ) {
|
|
case "boolean":
|
|
return java.lang.Boolean.TYPE;
|
|
|
|
case "number":
|
|
return v == Math.round(v) ? java.lang.Integer.TYPE : java.lang.Double.TYPE;
|
|
|
|
case "string":
|
|
return java.lang.String;
|
|
}
|
|
return java.lang.Object;
|
|
}
|
|
_AP.toJava = function(asObjects) {
|
|
if ( !this.length )
|
|
return java.lang.reflect.Array.newInstance(java.lang.Object, 0);
|
|
var r;
|
|
if ( asObjects )
|
|
r = java.lang.reflect.Array.newInstance(java.lang.Object, this.length);
|
|
else {
|
|
var type = this.coalesce(function(type, v) {
|
|
var jt = javaType(v);
|
|
return isUndefined(type) || type == jt || ( type == java.lang.Integer.TYPE && jt == java.lang.Double.TYPE ) ?
|
|
jt : java.lang.Object;
|
|
});
|
|
r = java.lang.reflect.Array.newInstance(type, this.length);
|
|
}
|
|
this.foreach(function(v, i) {
|
|
r[i] = toJava(v);
|
|
});
|
|
return r;
|
|
};
|
|
|
|
function toJavaScript(v) {
|
|
if ( typeof(v) != "object" || v == null )
|
|
return v;
|
|
if ( typeof(v.getClass) != "function" ) {
|
|
if ( typeof(v.valueOf) == "function" )
|
|
v = v.valueOf();
|
|
return "undefined" != v ? v : undefined;
|
|
}
|
|
var cls = v.getClass();
|
|
switch ( String(cls.getName()) ) {
|
|
case "java.lang.Boolean":
|
|
return "true" == v;
|
|
|
|
case "java.lang.Byte":
|
|
case "java.lang.Short":
|
|
case "java.lang.Integer":
|
|
case "java.lang.Long":
|
|
return parseInt(v);
|
|
|
|
case "java.lang.Float":
|
|
case "java.lang.Double":
|
|
return parseFloat(v);
|
|
|
|
default:
|
|
var s = String(v);
|
|
return s == v ? s : v;
|
|
}
|
|
}
|
|
|
|
// Hack to enable use of Array.from() on Java arrays
|
|
_AP.toArray = null;
|
|
|
|
_AP.enumeration = function() {
|
|
var self = this;
|
|
var index = 0;
|
|
return new Enumeration() {
|
|
hasMoreElements : function() {
|
|
return index < self.length;
|
|
},
|
|
nextElement : function() {
|
|
return toJava(self[index++]);
|
|
}
|
|
};
|
|
};
|
|
_LP.enumeration = function() {
|
|
var self = this;
|
|
var item = [];
|
|
var cached = false;
|
|
var reuse = false;
|
|
return new Enumeration() {
|
|
hasMoreElements : function() {
|
|
if ( !cached ) {
|
|
cached = reuse = true;
|
|
item = self.generator(item);
|
|
}
|
|
return item.length;
|
|
},
|
|
nextElement : function() {
|
|
if ( !reuse )
|
|
item = self.generator(item);
|
|
cached = !cached;
|
|
reuse = false;
|
|
return toJava(item[0]);
|
|
}
|
|
};
|
|
};
|
|
Beyond.enumeration = function(e) {
|
|
return function() {
|
|
return e.hasMoreElements() ? [ toJavaScript(e.nextElement()) ] : [];
|
|
}.lazy();
|
|
};
|
|
|
|
_AP.iterator = function() {
|
|
var self = this;
|
|
var index = 0;
|
|
return new Iterator() {
|
|
hasNext : function() {
|
|
return index < self.length;
|
|
},
|
|
next : function() {
|
|
return toJava(self[index++]);
|
|
},
|
|
remove : function() {
|
|
if ( index > 0 )
|
|
self.splice(--index, 1);
|
|
}
|
|
};
|
|
};
|
|
_LP.iterator = function() {
|
|
var self = this;
|
|
var item = [];
|
|
var cached = false;
|
|
var reuse = false;
|
|
return new Iterator() {
|
|
hasNext : function() {
|
|
if ( !cached ) {
|
|
cached = reuse = true;
|
|
item = self.generator(item);
|
|
}
|
|
return item.length;
|
|
},
|
|
next : function() {
|
|
if ( !reuse )
|
|
item = self.generator(item);
|
|
cached = !cached;
|
|
reuse = false;
|
|
return toJava(item[0]);
|
|
}
|
|
};
|
|
};
|
|
Beyond.iterator = function(i) {
|
|
return function() {
|
|
return i.hasNext() ? [ toJavaScript(i.next()) ] : [];
|
|
}.lazy();
|
|
};
|
|
|
|
function isTypeOrDerived(v, type) {
|
|
for ( var c = v.getClass() ; c ; c = c.getSuperclass() )
|
|
if ( c.getName() == type )
|
|
return true;
|
|
return false;
|
|
}
|
|
|
|
_AP.listIterator = function() {
|
|
var self = this;
|
|
var index, prev;
|
|
return new ListIterator() {
|
|
hasNext : function() {
|
|
return isDefined(index) ? index < self.length : self.length > 0;
|
|
},
|
|
hasPrevious : function() {
|
|
return isDefined(index) ? index > 0 : self.length > 0;
|
|
},
|
|
next : function() {
|
|
if ( isUndefined(index) )
|
|
index = 0;
|
|
prev = index;
|
|
return toJava(self[index++]);
|
|
},
|
|
previous : function() {
|
|
if ( isUndefined(index) )
|
|
index = self.length;
|
|
prev = index;
|
|
return toJava(self[--index]);
|
|
},
|
|
nextIndex : function() {
|
|
return isUndefined(index) ? 0 : index;
|
|
},
|
|
previousIndex : function() {
|
|
return ( isUndefiend(index) ? self.length : index ) - 1;
|
|
},
|
|
set : function(element) {
|
|
if ( isDefined(prev) )
|
|
self.splice(prev, 1, toJavaScript(element));
|
|
},
|
|
add : function(element) {
|
|
prev = index;
|
|
self.splice(index++, 0, toJavaScript(element));
|
|
},
|
|
remove : function() {
|
|
if ( isDefined(prev) )
|
|
self.splice(prev, 1);
|
|
}
|
|
};
|
|
};
|
|
Beyond.reverseIterator = function(i) {
|
|
return function() {
|
|
return i.hasPrevious() ? [ toJavaScript(i.previous()) ] : [];
|
|
}.lazy();
|
|
};
|
|
|
|
_AP.collection = function() {
|
|
var self = this;
|
|
return new Collection() {
|
|
add : function(element) {
|
|
element = toJavaScript(element)
|
|
if ( self.search(element) != -1 )
|
|
return false;
|
|
self.push(element);
|
|
return true;
|
|
},
|
|
addAll : function(collection) {
|
|
var me = this;
|
|
return Beyond.iterator(collection.iterator()).coalesce(function(r, v) {
|
|
return me.add(v) || r;
|
|
});
|
|
},
|
|
clear : function() {
|
|
self.length = 0;
|
|
},
|
|
contains : function(element) {
|
|
return self.search(toJavaScript(element)) != -1;
|
|
},
|
|
containsAll : function(collection) {
|
|
var me = this;
|
|
return Beyond.iterator(collection.iterator()).coalesce(true, function(r, v) {
|
|
return r && me.contains(v);
|
|
});
|
|
},
|
|
isEmpty : function() {
|
|
return self.length == 0;
|
|
},
|
|
iterator : function() {
|
|
return self.iterator();
|
|
},
|
|
remove : function(element) {
|
|
element = toJavaScript(element)
|
|
var index = self.search(element);
|
|
if ( index == -1 )
|
|
return false;
|
|
self.splice(index, 1);
|
|
return true;
|
|
},
|
|
removeAll : function(collection) {
|
|
var me = this;
|
|
return Beyond.iterator(collection.iterator()).coalesce(function(r, v) { return me.remove(v) || r; });
|
|
},
|
|
retainAll : function(collection) {
|
|
var length = self.length;
|
|
var filtered = self.filter(function(v) { return collection.contains(toJava(v)); });
|
|
filtered.foreach(function(v, i) { self[i] = v; });
|
|
self.length = filtered.length;
|
|
return self.length != length;
|
|
},
|
|
size : function() {
|
|
return self.length;
|
|
},
|
|
toArray : function(a) {
|
|
if ( typeof(a) != "object" )
|
|
return self.toJava(true);
|
|
var type = a.getClass().getName().slice(2, -1);
|
|
var java = self.collect(function(v) { return toJava(v, true); }).
|
|
filter(function(v) { return isTypeOrDerived(v, type); });
|
|
if ( a.length < java.length )
|
|
a = javaArray(type, java.length);
|
|
java.foreach(function(v, i) { a[i] = v; });
|
|
if ( a.length > java.length )
|
|
Arrays.fill(a, java.length, a.length, null);
|
|
return a;
|
|
}
|
|
};
|
|
};
|
|
Beyond.collection = function(collection) {
|
|
return function(item) {
|
|
var i = item.length ? item[1] : collection.iterator();
|
|
return i.hasNext() ? [ toJavaScript(i.next()) , i ] : [];
|
|
}.lazy();
|
|
};
|
|
|
|
_AP.list = function() {
|
|
var self = this;
|
|
return new List() {
|
|
add : function(index, element) {
|
|
if ( isUndefined(element) )
|
|
self.push(toJavaScript(index));
|
|
else
|
|
self.splice(index, 0, toJavaScript(element));
|
|
return true;
|
|
},
|
|
addAll : function(index, collection) {
|
|
var me = this;
|
|
if ( isUndefined(collection) )
|
|
Beyond.iterator(index.iterator()).foreach(function(v) { me.add(v); });
|
|
else
|
|
Beyond.iterator(collection.iterator()).foreach(function(v) { me.add(index++, v); });
|
|
return true;
|
|
},
|
|
clear : function() {
|
|
self.length = 0;
|
|
},
|
|
contains : function(element) {
|
|
return self.search(toJavaScript(element)) != -1;
|
|
},
|
|
containsAll : function(collection) {
|
|
var me = this;
|
|
return Beyond.iterator(collection.iterator()).coalesce(true, function(r, v) { return r && me.contains(v); });
|
|
},
|
|
get : function(index) {
|
|
var x = toJava(self[index]);
|
|
return toJava(self[index]);
|
|
},
|
|
indexOf : function(element) {
|
|
return self.search(toJavaScript(element));
|
|
},
|
|
lastIndexOf : function(element) {
|
|
var index = self.reverese().search(toJavaScript(element));
|
|
return index == -1 ? -1 : self.length - index - 1;
|
|
},
|
|
isEmpty : function() {
|
|
return self.length == 0;
|
|
},
|
|
iterator : function() {
|
|
return self.iterator();
|
|
},
|
|
listIterator : function(index) {
|
|
var i = self.listIterator();
|
|
if ( isDefined(index) )
|
|
for ( ; i.hasNext() && i.nextIndex() < index ; i.next() );
|
|
return i;
|
|
},
|
|
remove : function(index) {
|
|
return self.splice(index, 1)[0];
|
|
},
|
|
removeAll : function(collection) {
|
|
var me = this;
|
|
return Beyond.iterator(collection.iterator()).coalesce(function(r, v) { return me.remove(v) || r; });
|
|
},
|
|
retainAll : function(collection) {
|
|
var length = self.length;
|
|
var filtered = self.filter(function(v) { return collection.contains(toJava(v)); });
|
|
filtered.foreach(function(v, i) { self[i] = v; });
|
|
self.length = filtered.length;
|
|
return self.length != length;
|
|
},
|
|
set : function(index, element) {
|
|
var prev = self[index];
|
|
self[index] = toJavaScript(element);
|
|
return toJava(prev, true);
|
|
},
|
|
size : function() {
|
|
return self.length;
|
|
},
|
|
subList : function(from, to) {
|
|
return self.slice(from, to).list();
|
|
},
|
|
toArray : function(a) {
|
|
if ( typeof(a) != "object" )
|
|
return self.toJava(true);
|
|
var type = a.getClass().getName().slice(2, -1);
|
|
var java = self.collect(function(v) { return toJava(v, true); }).
|
|
filter(function(v) { return isTypeOrDerived(v, type); });
|
|
if ( a.length < java.length )
|
|
a = javaArray(type, java.length);
|
|
java.foreach(function(v, i) { a[i] = v; });
|
|
if ( a.length > java.length )
|
|
Arrays.fill(a, java.length, a.length, null);
|
|
return a;
|
|
}
|
|
};
|
|
};
|
|
Beyond.list = Beyond.collection;
|
|
Beyond.reverseList = function(list) {
|
|
return function(item) {
|
|
var i = item.length ? item[1] : list.listIterator();
|
|
return i.hasPrevious() ? [ toJavaScript(i.previous()) , i ] : [];
|
|
}.lazy();
|
|
};
|
|
|
|
var File = {
|
|
|
|
read : function(file, cache, reader) {
|
|
var rf = function(item) {
|
|
var stream = item[1] ?
|
|
item[1] :
|
|
new java.io.BufferedReader(reader ? file : new java.io.FileReader(file));
|
|
var line = stream.readLine();
|
|
return line != null ? [ String(line), stream ] : [];
|
|
}.lazy();
|
|
if ( cache )
|
|
rf = rf.cached();
|
|
rf.file = file;
|
|
return rf;
|
|
},
|
|
write : function(file, overwrite, writer) {
|
|
var st = new Stream(writer ? file : new java.io.FileWriter(file, !overwrite));
|
|
var handle = st.foreach(function(v, stream) {
|
|
if ( isDefined(v) ) {
|
|
var s = String(v) + "\n";
|
|
stream.write(s, 0, s.length);
|
|
stream.flush();
|
|
}
|
|
});
|
|
st.stop = function() {
|
|
this.detach(handle);
|
|
this.owner.Close();
|
|
};
|
|
return st;
|
|
},
|
|
process : function(input, output, f, append) {
|
|
if ( !f )
|
|
f = Function.NOP;
|
|
else if ( f.constructor === RegExp ) {
|
|
var re = f;
|
|
f = function(line) {
|
|
if ( re.test(line) )
|
|
return line;
|
|
};
|
|
}
|
|
return this.write(output, !append).extend(this.read(input).collect(f));
|
|
}
|
|
|
|
};
|
|
|
|
File.StdIn = File.read(new java.io.InputStreamReader(java.lang.System["in"]), false, true);
|
|
File.StdOut = File.write(new java.io.OutputStreamWriter(java.lang.System["out"]), false, true);
|
|
File.StdErr = File.write(new java.io.OutputStreamWriter(java.lang.System["err"]), false, true); |