Deprecated: Function set_magic_quotes_runtime() is deprecated in /home/mwexler/public_html/tp/textpattern/lib/txplib_db.php on line 14
The Net Takeaway: JudoScript


Danny Flamberg's Blog
Danny has been marketing for a while, and his articles and work reflect great understanding of data driven marketing.

Eric Peterson the Demystifier
Eric gets metrics, analytics, interactive, and the real world. His advice is worth taking...

Geeking with Greg
Greg Linden created Amazon's recommendation system, so imagine what can write about...

Ned Batchelder's Blog
Ned just finds and writes interesting things. I don't know how he does it.

R at LoyaltyMatrix
Jim Porzak tells of his real-life use of R for marketing analysis.







Judoscript 0.9 comments and notes: · 5932 days ago,

What is Judoscript?

(First off, if you found this page via a web search or bookmark, you may be much happier in the JudoScript Section of this site to see the multiple articles about Judoscript, including this one, but also about Databases, Graphics, Files, etc. Secondly, the Yahoo Groups is also a great source of help, don’t forget about it!

Judoscript is an open-source Java scripting language written primarily by James Huang (most recently an IT Developer with BEA Systems. Previously, he was a lecturer in the Department of Electric and Computer Engineering at East China Normal University. He’s also a really, really nice guy.)

The language is very similar to Javascript with lots of syntactic sugar to ease Java programming.

Many of the notes below come from his site but I’ve added my own spin to point out some of the really useful stuff. I’ve also glossed over things that he presents really well in the Articles section of his site

Oh, one more thing: James is a frequent updater… when he or the group finds a bug, its often fixed within days with a new jar release. So, always check the date version of your judoscript jar and make sure you have the latest; chances are, your bug is already fixed!

For example, as of this writing, the current version is v0.9, 2005-02-25 (Feb 25, 2005). You can always check the live up-to-date version at the Download page.

More info may wind up at the Judoscript Wiki at some point…

Latest Features
Always check the release notes at; you’ll be amazed at what’s new!

For example, Judoscript now relies heavily on namespaces. This means, for example, using “db::” namespace for all SQL scripting statements. Check the release notes now for the rest of the myriad changes…

Getting Judoscript is the home of Judoscript, including articles, code samples, docs, source, and (of course) the binaries.

Running Judoscript
The easiest way is like this:

 java -jar judo.jar some_program.judo

However, when run with java -jar, the environment classpath is not in effect, i.e., you are only using the classes in the jar file. So, if you have any other classes involved (such as external jars), you shouldn’t use -jar option. Instead, try this (for Windows): java -cp classpath;judo.jar judo test.judo

So, in my case:

 java -cp %classpath%;../judoscript.v0.9/judo.jar judo sw1.judo

or (just including the current dir, ignoring previous classpath)

 java -classpath .;../judoscript.v0.9/judo.jar judo showcp.judo

Note that you still need to either add each jar manually to the classpath this way, or add the to general environment variable. This can be long and annoying if you are using, say, Hsql, or you need additional functionality from existing java code distributed in a jar.

But, if you want to use a java class from within Judoscript, one option is to use “dynamic classpath”:

j = new java::pippo;

java judo [option] filename_or_code
where option is one of these:
-h or —help: this help screeen
-c or —compile: compile
-d or —dump: dump
-q or —quiet: quiet
-x or —exec: commandline arguments as program
-l=level or —logger=level:
start the program with a given logging level.
Valid levels are: ‘trace’, ‘debug’, ‘info’, ‘warn’, ‘error’, ‘fatal’,
from most verbose to least.

When running judoscript, most of the time it prints a copyright banner. Here are some options to control that:
* -c: to compile the script only to check for the syntax.
* -q: quiet mode, run the script without displaying the copyright notice.
* -x: to execute the code specified on the command line. Everything on the command line is concatenated, and an extra ; is appended. For instance, the following are some sample command lines:
java judo -x “println #versionInfo”
java judo -x “println (1234).fmtRoman(‘M’)”
java judo -x “println (1234).fmtHex()”
java judo -x “println 0x4D2”
java judo -x “println 49.95 * 1.0825”


Judoscript is now integrated with Apache commons-logging. This means that lots of additional “INFO” lines get printed by default. If you want, you can set up your logging options by copying judoscript-0.9.jar/ or into your classpath. is in effect if the log4j.jar file is in the classpath; otherwise, if you are runing jdk1.4, then is used (meaning the built in logging from the more recent JVMs). In either of these, you can set the logging level to higher severity (to view less messages).

You can start judo with -l=warn (or -l=error, -l=fatal, or even -l=off) to supress the INFO messages like this:

 java judo -l=error my_script.judo a b c

I’ve also been including these lines in the top of my files, and they seem to help reduce that annoying logging output as well.

 !pragma logger.judo = 'fatal'
 !pragma logger.judo.user = 'fatal'
 !pragma logger.judo.jdbc = 'fatal'
 !pragma logger.judo.hibernate = 'fatal'

Techie Alert: James mentioned this on the groups: To completely turn off the logging messages, you can do this when running judo: java -Drg.apache.commons.logging.Log=org.apache.commons.logging.impl.NoOpLog judo .. Also, it is also recommended to have log4j.jar in your classpath to override the JDK1.4 logging, whose default logging message format is funny. Finally, feel free to edit the properties files, but note that they can affect all logging, so be careful.

Basic Syntax Tips
Comments: //, /* … */, /? … ?/, #! (for unix autorun)
// is for single line, and by convention, /* */ is more for regular comments, and /? ?/ is for disabling code. BTW, in SQL statements, the “traditional” — comment is also allowed.

Variables in JudoScript are dynamically typed which means that even though a variable doesn’t have a specific type, the value in it does.

#varname (variable beginning with a pound sign) means constant, immutable variable. However, you do need the “const” decorator:

  const #PI = 3.1415926536;

You can use defined to detect whether a constant has been defined or not. Alternatively, you can compare a constant against the undefined value.

There are actually 4 “null” type values:
null, undefined, eof, and nl

$$varname are internal Judoscript variables (similar to how perl handles things) $_ is another special variable; include “last line read”, etc. just like perl. Its used for when a result is expected but no explicit variable reference is given. Such $_ variables are always in the local scope

Older JudoScript versions required a single $ for variables; that is no longer necessary (but doesn’t hurt). You could also use the var keyword (as in const above), but not really needed.

Scoping works as you’d expect; Variables in the global scope can be accessed explicitly via the :: decorator for the variable name. See “” : for lots of details.

Other special variables
JudoScript has defined a few special variables, like the global variable $$con that holds the default database connection and $$args in a function that is an array that holds all the passed-in parameters. These variables are generally read-only by the application code.

Handy Constants:
#script = Script path
#prog = script name
#cmd_args = an array that contains all the command line arguments; #args is same but without options, #options has the options
#sysprops = the system properties of the currenv JVM
#classpath = the classpath object

Btw, can add to the classpath in script: #classpath.add(‘c:/temp’);

${:} = the platform-dependent path separator. On Unix it is :; on Windows it is ;. This character is frequently used in constructing classpaths.
${/} = the platform-dependent file name separator, that is, the character that separates the file name and directory names in a path. On Unix it is /; on Windows it is \.
${.} = the current directory. This can be changed by the cd command, so it is not strictly a constant value; it starts with the current directory when the script is being run
${~} = the home directory of the user running the script.

If you are a “reflective” programmer, you can create variables programmatically via setVariable() and convertToVariables()

Println formatting codes
Aligned left, right or centered with >, < or * and a width
ex. :>3 means the value printed right-aligned to 3 letters. If the text is longer than 3, it is printed as-is (i.e., no truncation). To truncate any long text to 3 letters, use :>3!

nl means newline.

Format functions include formatBool(), etc.

Can use REPEAT 16 to repeat sequences (or just {16})

Note that print does not put newlines, and flush can clear buffers.

print, println and flush can write text to any of Java’s objects. The built-in print targets include out, err, log and pipe; variables of open text files can be used, too. You can also print into a string.

You can set print flags like debug flags:

 verbose = true;
 println {verbose} 'If you see this, verbose is on.';

The operator @ is string concatenation. (It is not + because that is used for numeric addition. Since JudoScript is a
weakly-typed language, this is necessary.) (And, actually, from v0.9 on, + can be used for strings…)

(Trying to be ECMAScript 4/javascript compliant, as time goes on)

Data Structures
In JudoScript, a variable is a container for any value. A value is either of a simple type (number or string) or an object of some kind. For objects, the value is weakly typed, so the uses determine what type is intended (i.e., lots of implicit coercion, very handy). Constants start with #.

JudoScript supports these primitive data types: integer, floating-point number, string and date/time

Numerically, true is 1 and false is 0 = Boolean.
Otherwise, follows all the standard Java definitions of integer and floating point.

There is no “character” type; characters are strings of 1 character. Otherwise, follows all the usual Java string issues (always creating new ones, etc.)

Can use either double or single quotes to assign strings; if double quotes are used, single quotes are legitimate characters, and vice versa. If both double quotes and single quotes appear in the text, one of them has to be escaped. The escape sequences are the same as in Java. JudoScript supports unicode escape sequence as well.

JudoScript supports two forms of multi-line text literals,==[[* *]]== and [[[* *]]. Both formats quote a chunk of text, which may include new-lines. The [[* *]] is used more often; it allows the chunk of text to be indented, resulting in code that is nicely aligned. In other words, the leading number of whitespace characters at the beginning of each line are stripped. For this reason, it is better not to use tabs to avoid potential confusions. The [[* *]] also trims the leading and trailing whitespace characters. The [[[* *]] format simply quotes the chunk of text as-is. Similar to a “here-doc” from PERL. BTW, in mutli-line text literals, expressions can be embedded with the (* *) syntax. The embedded expressions will be evaluated to string values and concatenated to the rest of the text. Strictly speaking, the text is not a literal any more, but rather, a template.

Embedding works elsewhere as well. Variables (including environment variables) can be embedded all forms of string literals via the ${varname} syntax.

The csv() method turns a character-separated value into an array. It takes a string as its parameter, all “character”s are separators; if missing, uses comma. This method returns null for two consecutive separators; this is different than java.util.StringTokenizer which discards such values. Note that \t can be used for tab (single backslash t)!

  s = '2001/10/01||XYZ|12.00|10000';

  a = s.csv('|');
  println 'Date:   ',a[0];

(Also, \r (carriage return) and \n (linefeed) have their usual meanings, and can be used in searches and such to simulate PERL’s chomp:

DOS: CarriageReturn/LineFeed (“\r\n”)
Unix: LineFeed (“\n”)
Mac: CarriageReturn (“\r”)

Useful methods include isEmpty() and others, Replace() and replaceIgnoreCase(), endsWith(). count() counts the occurrences of a character within the string. Regionmatches allow full regexes.

IgnoreCase() does the same as in java.lang.String. getReader() returns a reader that uses the string as its input. Programs can, for instance, read lines from a string.

Regular expressions
JudoScript uses the regex built into Java 1.4 and above, specifically the java.util.regex classes. The patterns are documented here.

The string data type has these regex methods: matches(), matchesStart(), replaceAll(), replaceFirst(), split() and match(). All these methods take a pattern as their first parameter. The pattern can be a single string, or an array of two strings: the first one is the pattern and the second is the modes.

A nice short PDF explaining how to use Jave regex is here: Java Regex Primer

Here is an example of extracting a pattern and printing it, direct from James and the Judoscript Yahoo group:

  text = '<head><title>Judo</title></head>';
  m = text.matcher('(<title>)(.*)(</title>)');
  while m.find() {
    . m.groupCount();
    . ' : ',;
    . '0: ',;
    . '1: ',;
    . '2: ',;
    . '3: ',;

The result is:

  : <title>Judo</title>
  0: <title>Judo</title>
  1: <title>
  2: Judo
  3: </title>

For those not up with Regex, the parens tell regex to match in groups; the overall found pattern is an implicit group. The first with no index prints the entire overall found pattern; the 0-based indexes print each of the groups in turn.

Note that when we use the matcher() function, the returned object is an instance of java.util.regex.Matcher and can use any of its associated functions. For example, .start() and .end() can print the first and last character position of a group, so strings can be truncated and such…

Date(year, month, day, hour, minute, second, milli-second) where month is an integer between 1 and 12. Date() with no parameters is current date/time.

time() creates a date object with year, month and day fields all initialized to 0. timeToday() is a convenience method that creates a time in today’s date. Also has formatDate() or fmtDate() convenience functions.

System functions

Built In DataTypes:

Arrayone- or multi-dimensional linear container
LinkedListSame as array but is implemented as a linked list.
StructA map (aka Hash); is the root of all user-defined classes. User-defined classes can extend this.
OrderedMapSame as struct except the order in which keys are added is retained. User-defined classes can extend this, too.
SortedMapsimilar to OrderedMap except the keys added are sorted. User-defined classes can NOT extend this.
Stacka first-in-last-out container.
Queuea first-in-first-out container.
Set and Sorted Seta one-dimensional container with no duplicate elements, optimized for testing of the existance of an element.
TableDataa two-dimensional array with column captions and methods for retrieving rows or columns.
TreeNodea convenience for building a tree. User-defined classes can extend this.

Can also use java data:

  hash = new java::Hashtable;
  ba = new java::byte[]{ 0, 1, 2 };

And the “for…in” and “keys=hash.keys; while keys.hasMoreElements()” type loops work on these as well

In fact, can link lots to java:
Nice mention of array usage and access.

Can also Extend Java Classes..

Like perl: The built-in variable $_ representes the current event. In the case of HTML or XML, it represents the tag itself. In GUI programs, it is the event object in various listener methods.


 arr = [ [ 1, 2 ], [ 3, 4 ] ]; // multi-dimension
 arr = new Array( 1, 'abc', date(2001,10,1) );

or linked list…

 lst = linkedList[ 1, 'abc', 
                       new java::Hashtable() ];
 lst = [ linkedList[ 1, 2 ], linkedList[ 3, 4 ] ];

Ways to access arrays:

  zodiacs = [ 'mouse',  'ox',  'tiger', 
                  'rabbit', 'dragon', 'snake', 
                  'horse',  'sheep', 'monkey',
                   'rooster', 'dog',   'pig'];
  for i=0; i<zodiacs.size()-1; ++i { . zodiacs[i]; }
  for i from 0 to zodiacs.lastIndex() { . zodiacs[i]; }
  for x in arr { . x; }

Arrays are 0-base indexed.
.length() or .size() gives number of elements
.append() or .add() adds elements; .prepend() adds to front; .insert() at a specific position

.appendArray() or prependArray() to merge arrays
.subarray() to pull out a chunk
.clear() clears array; .remove() removes a specific element.
.indexof() gives index of an element; .reverse() can reverse the elements

Three ways to enumerate an array:

1. You can iterate “manually” with an index:

 for idx=0; idx < arr.length; ++idx {
   local x = arr[idx];
   println idx, '  ', x;


2. You can let the loop handle the iteration for you:

 for idx from 0 to arr.lastIndex() {
    local x = arr[idx];

    println idx, '  ', x;

3. Or, you can ignore the index entirely and let the loop be both iterator and accessor:

 for x in arr {
    println x;

Can use aggregate functions on array: sum(), max(), min(), average() or avg(), and range()

Can use .sort() (with customized comparator using & as a lambda function), but JudoScript has already included sortAsNumber(), sortAtDate() and sortAsString() methods.

Array has .filter() that takes a user-defined filter function. It can return a new array for the qualified elements, or change the array locally. See

Array .convert() also uses a & (lambda) function to convert.

Multi-dimensional arrays, stacking, and accessing: From the mailing list…

  a = { 'a', 'b', 'c' };
  b = { 'A', 'B', 'C' };
  arr = { a, b, 'hello' };
  println arr[0][1]; // => 'b'

Structs (maps) and Ordered Maps (aka Hashtables)
A struct is nothing but a map.

 names = new struct( Gustavo = 'Kuerton',
                        Paradorn = 'Srichaphan',
                        Conchita = 'Martinez' );
 names.Venus = 'Williams';
 names.('Marat') = 'Safin';

Accessing maps:

 for firstName in names.keys() 
    { . names.(firstName), ', ', firstName; }
 // Remember, . is shortcut for println
 // Result:
 //  Martinez, Conchita, etc.

Can also sort by Values!

 for firstName in names.keysByValue() 
   { . names.(firstName), ', ', firstName; }
 // Result:
 //  Kuerton, Gustavo, etc.

An orderedMap is exactly the same as a struct except the order of the added elements is retained as the order of the keys. Ordered map also has an indexOf() method that works the same way as for arrays. An ordered map essentially serves the use of an array (for the names) along with a name-value mapping, which can be very handy in some situations.

To access an attribute, use the dot operator; if the attribute name has non-identifier characters, have it quoted. If an attribute is not defined, a null is returned.

 println a.'first name';      // access by name
 field = 'first name';        // access by expression
 println a.(field);

To remove an attribute, use .remove() or .delete(). Method .size() returns the number of attributes, and clear() removes them all.

Method .keys() returns all the keys in an array. It is used to enumerate all attributes. Method values() returns an array
of all values.

 a = new Struct( alfa = 'A', beta = 'B', 
                         gamma = 'C', delta = 'D' );
 for x in a.keys() {
       println x, ' => ', a.(x);

Keys and values can be sorted. keysSorted(), keysFiltered(), keysSortedByValue(), keysFilteredByValue() and
keysSortedAndFilteredByValue(). All of them may take a comparator function and/or filter function.
Nice example on using Lambda

BTW, this all works pretty similarly with Java native Hashtables:

 a = new java::java.util.Hashtable;
 a.put('date',      Date(2001,1,1));
 a.put('integer',   1);

 a.put('double',    10.01);
 a.put('string',    'Hello, World!');
 a.put('Dimension', new java::java.awt.Dimension(10,20));
 for k in a.keys() { // for-in statement handles  Enumeration/Iterator
   println k:>10, ' = ', a.get(k);

Stacks and Queues

Java Objects/Arrays
In older versions of Judoscript, the “javanew” command was used to create Java objects or arrays. However, since the 2004-06-20 release, things have changed. Java classes are now just a namespace.

So the new way:

 a = new java::Hashtable;
 b = new java::int[4];
 c = java::Map;

 class MyClass extends java::HashMap { ... }

vs. the old way was:

 a = javanew java.util.Hashtable;
 b = javanew int[4];
 c = javaclass java.util.Map;

 class MyClass extendsjava HashMap { ... }

To access a static member in a Java class, use :: A Java class object can be used to create instances and access/invoke static members/methods. Static members are accessed like normal members.

Control Structures: Loops and Branches
Blocks in JudoScript are formed with { and } (Braces). These control (to some extent) variable scoping as well. Blocks can also have catch and finally clauses for exception handling (more below)

Do As: This is actually one of the most impressive things about JudoScript…. when it works. This “event-driven” statement style allows one to walk a data structure and react to events.

 do 'file' as lines
 do 'http:' as sgml

So, an HTML example:

 do '' as sgml {
  <a>:   if $_.href != null { println $_.href; }
  <img>: println $_.src;

Literally, you can walk a file or a URL in an event driven mode like a SAX parser and pull out tags or other useful stuff.

An XML example:

 do 'data.xml' as xml {
   <order>:       println '==============';
   TEXT<number>:  println 'Order #:   ', $_;
   TEXT<invoice>: println 'Invoice #: ', $_;

If Else
Big tricky thing here: the blocks following if, elif and else expressions do not define new scopes

 if foo() {
     println 'Foo is true!';
 }  elif foo()=TRUE and x=y {  /*Could also be Else If, your choice */
      println 'Foo is true, but there is more afoot...';
 } else {
       println 'Forget it, Foo is just not true.'

Note that you do not need an end if as in other scripting languages.

Case statement here is the SWITCH command. Only one clause can be true. The “else” here is default, which is the fallthrough.

Note that if case 0 is true, you NEED the break to get out of the loop, otherwise you will execute case 1 as well!!! (Yes, this is by design, as annoying as it is. Well, there are times when multiple cases share code, so I guess its handy… but just be careful!)

  switch x {
    case 0:  println 'zero'; break;
    case 1:  println 'uno';  break;
    default: println x;      break;

For statements
There are 3 kinds:
The Java/C++ kind:
for init(); cond(); postproc() {

for a=0; a<3; ++a {
println a;

The for-from-to loop:
for a from 3 to 5 { print a, ’ ‘; }
for a from 10 downto 5 step 2 { print a, ’ ‘; }

And the ever-handy for-in statement to iterate through collections, both JudoScript specific as well as Java natives.

 a = [ 1, 2, 3 ];
 for x in a {
   println loopIndex(), ': ', x;

 /* remember, nl is a newline */ 
 println nl, 'Iterating Java array:'; 
 a = new java::int[]{ 10, 20, 30 };
 for x in a {
   println loopIndex(), ': ', x;
 println nl, 'Iterating java.util.ArrayList:';
 a = new java::ArrayList;
 a.add(100); a.add(200); a.add(300);
 for x in a {
   println loopIndex(), ': ', x;
 a = [ 'elem1', 'elem2', 'elem3', 'elem4' ];
 for e in a                 { println e; }
 for e in a backward        { println e; }
 for e in a from 1          { println e; }
 for e in a to 1            { println e; }
 for e in a from 1 to 2     { println e; }
 for e in a from 2 downto 1 { println e; }
 for e in a downto 1        { println e; }

Sometimes the indices may be indented in addition to the elements, then use the for from to|downto step family statements:

 for a to 3                    { println a; }
 for a from 3 to 5             { println a; }
 for a from 3 to 10 step 2     { println a; }
 for a from 10 downto 5 step 2 { println a; 

And the repeat statement simply repeats a block:
repeat 16 {println ‘Hi!’};

While and Do-While

 a = 3;
 while a >= 0 {
   println a;

 do {
   println a;
 } while a < 2;

As seen with the Switch statement, you can use break and continue to skip out of loops. Continue is like a named goto; the name is a label with a colon…

   for i from 0 to 5 {
     for j from 1 to 5 {
       if i+j < 5 {
         continue aloop;
       } else if i+j >= 10 {
         break aloop;
       println i, '-', j;

If you need to know your current loop index, use loopIndex(). Give it a negative integer to discover the loop index of an outer loop.

Exception Handling
Instead of try/catch, implicit try. Catch, Resume, Finally, and throw. In the catch segment, the exception, whether from the JudoScript engine or Java, is stored in variable $_. It has these members: $_.message or $_.msg, $_.type (an integer), $, $_.line and $_.file. If type is 9, it is a Java exception,
and name is the Java class name of the exception.

Good example at

Functions are basically method calls on the implicit object that is the JudoScript script. That’s the “java-ish” explanation; functions are the missing way to simply change a variable.

Basically, function name parameters. The parentheses around parameters are not required; if parentheses are used, the right parenthesis must match the left one. Functions always return a value; the return statement can return a value and exit the function. If no return statements are called, the function code will fall out of scope and exit, returning undefined. Functions, like any declarations in JudoScript, can appear anywhere, that is, you can call a function before it is declared.

 cnt = 0;
 hanoiTower(4, 'A', 'B', 'C');
 function hanoiTower N, src, aux, dst {
   if N == 0 { return; }
   hanoiTower(N-1, src, dst, aux);
   println 'step ', ++cnt :>2, ':  ', src, ' => ', dst;
   hanoiTower(N-1, aux, src, dst);

BTW: Lambas, a big Groovy thing, are basically anonymous functions, and are here as well. Check it out.

A tableData is an m-by-n, two-dimensional data structure. It has column titles. Each row is referenced as if it’s an array element, but the data in that row can be accessed either via the column index (0-based) or via the column name. It has operations to sort, filter and get data in a column.

  // This makes a tableData with 2 columns, name and age.
  a = new tableData('name', 'age'); 

This is different from a nested array. That is,

  a[0] = [ 'Young Man', 28 ]; 

is the same as

  a[0,0] = 'Young Man';    // Adding in two steps
  a[0,1] = 28;                 // Is this same as the above?

Just printing a row (println ‘a3 = ‘, a3;) yields [Younger Daughter,2]

Data rows can easily be added, and specific cells can be set directly. TableData is particularly useful for short database query results, such as the database meta data. The query result object has a method, .getTableData(), that saves the returned query data into a tableData; a limit can be specified.

 // B becomes an array of column 2 
 //  (0 indexed, remember?)

 b = a.getColumn(1);

What’s the title of a column?

 a.getTitle(0);  // This is the title of the first column, the 0th column)

Which column is which?

  println 'Index for "name" is: ', a.getColumnIndex('name');  

Note that if you don’t use a.setTitleCaseSensitive(false); then the titles become case sensitive!!!

Filtering is using a lambda…

  println '------ Filter for Old and < 100 --------';
  filter = lambda x {
                 return'Old') && x.age < 100;
  printTD a.filter(filter);

  println '------ Sort on column-1 as number ------';
  printTD a.sortByColumnAsNumber(1,false); // false: descending

Printing a TableData is annoying, mostly because the built in functions cannot automatically populate the headings. So, here is a function I wrote to “do it right”. Our own printer function:WexPrint

 function printTD td {
   // Note that this version prints a row number.  That may be annoying.
   // Titles
   print '    ';
   for y to colcnt{
     print td.getTitle(y) :<20!;
   // Separator
   print '    ';
   for x to td.getTitles().length-1 {
     print '------------------- ';
   // Data
   for thisrow to rowcnt  {
     println 'Entering Data Loop';
     print thisrow:>3, ' ';
     rowvals = td[x];
     for y in rowvals {
        print y :<20!;
 } // end of function printTD

(One confusing thing:

    row = td[x]; // Row is now an array, 2 items, right?
    for y in row {
     print y :<20!;}  // What does this for do?  It doesn't separate the array!

Or, use the Judoscript built-in Table printer, printTable. This command winds up being more hassle than its worth b/c it requires manual creation of the column titles. Table data and query results can be easily printed in tabular format with the printTable statement. It does not print the column titles, since they are static and can be embelished to your hearts’ content. The headers should be visually consistent with the data formats for. The columns in this print statment can be the table data columns or expressions thereof and other expressions used as dividers.

 a = new tableData('Name', 'Language Type', 'Birthday');
 a.add('Java',       'System',    date(1996,5,23))
  .add('JudoScript', 'Scripting', date(2001,11,16));

 println 'Language  | Type      | Birthday';
 println '----------+-----------+---------';
 printTable a for column(0) :<10!, '| ',
                  column('Language Type') :<10!, '| ',

For large query results, you may not want to print them all. printTable allows you to skip certain number of rows and limit the numbers of rows printed:

printTable resultSet skip 1000 limit 250
  for ......

Can also print into a string:

 printTable <$myTableStr> myTable for
   column('name') :<20!,
   column('age') :>5!;

 println $myTableStr;

*ActiveX (Excel) Scripting *

Lots of functions on Built-In Object Type: simple

 Instead of lines, can do the usual:
 lineCnt = 0;
 f = openTextFile('');
 while true {
   if (line = f.readLine()) == eof { break; }
   . ++lineCnt :>3, ' ', line;

System Properties
In the class java.lang.System, its static method getProperties() returns a java.util.Properties, which is essentially a name-value pair map, that includes all the system properties. JudoScript’s built-in constant, #sysprops, refers to the system properties. JVM system properties are different from environment variables. The environment variables are for the operating system process that runs the current JVM. In JudoScript, there are two system functions, getenvs() and getenv(name). Alternatively, you can use the ${name} notation in place of getenv(name); tells more about this feature.

Much more detail at
When JudoScript starts, the JVM has an initial classpath called the system classpath. JudoScript also allows additional user classpaths. This is done through the predefined constant, #classpath object.

To add a user classpath component, which can be either a file system directory name or a zip or jar file, use the add() method of #classpath, which can add individual class path name or an array of them. When JudoScript tries to load a Java class or a resource, the classpaths are searched first; if the class or resource is not found, JudoScript tries the system classpath.

 println '---- User classpath components ----';
 for x in #classpath.userClasspaths {
   println x;
 println nl, '---- System classpath components ----';

 for x in #classpath.systemClasspaths {
   println x;


To print to a file, use the same print-family statements:

 function convertToHtml fileName
   outFile = openTextFile(fileName @ '.html', 'w'); // for write.
   . <outFile> '<html><body><pre>';
   do fileName as lines {
     . <outFile> $_.replace('&', '&')
                   .replace('<', '<');
   . <outFile> '
</body></html>'; outFile.close(); } </pre>

This is a function that creates an HTML file for any text file, typically source code. To print into a text file, first open it for write, then use that open file variable in the print statements. We used the string value’s replace() method to escape ‘&’ and ‘<’. String and numbers are simple values. They can be used interchangeably


!include ‘common.judi’
You can even use if to include different programs based on runtime values:
!include if ${LOCALE}==null ‘messages_en.judi’


Declared like functions:

  thread httpHandler req {
  while {
    start thread httpHandler(acceptHttp(ss));



 x = [[*
  Scripting is to do things easily, intuitively, obviously and
  accurately, so much so that when another person with the same
  domain knowledge sees a chunk of code, he immediately
  understands it without even a hint of reasoning (ideally). 

This example puts a chunk of text into a variable. The leading indentations are stripped, so the code can look nice and neat.



  do '' as sgml {
    <a>:   println 'web link: ', $_.href;
    <img>: println 'img link: ', $_.source;

Also, strings have urlEncode() (encodeUrl()), urlDecode() (decodeUrl()) methods.
parseUrl() method that parses a string into a number of URL parts, returned in a struct. Parts include: b.root; b.protocol; b.domain;;b.port; b.path; b.file_name; b.query_string; b.ref;

To send authorization, you’ll have to set the HTTP headers yourself like this:

 $http = httpGet($yourURL);
 $basic_cookie = encode('base64', 'myuser:mypass');
 $http.Authorization = 'Basic ' @ $basic_cookie);
 do $http.getInputStream() as html
  TEXT: flush $_;
  <>: flush $_; // all HTML tags
  <!>: flush $_; // comments, ...
  <?>: flush $_;

manually set a cookie = http.”cookie” = “COOKIE_LOGIN=1;COOKIE_GROUPID=management”;

To view headers:
run snooper.judo and access via http://localhost:8088/snoop: (examples/2.4-apps-internet/http_server/snooper.judo)
(this has other nice utilities…)


Program arguments are stored in the constant array #args. JudoScript supports a predefined format for command-line ptions.
If a parameter starts with / or -, then the rest of it becomes a name=value option pair; if no =, the value is defaulted to true.
When options are present on the command line, they are collected and put in a constant struct #options. The other
paremeters are stored in #args. #options may not be defined. In case you don’t like this format, the complete raw command line parameters are always in a constant array #cmd_args. The program name itself is in a constant string #prog.

Also, can access the classpath with #classpath
Also, can access system properties with #sysprops

 for x in #sysprops {println x;};

to see the properties, or to really see the names=values,

 for x in #sysprops.keys()
   { .x,' = ',#sysprops.(x);}


From the mailing list:
The “for in” statement handles 3 types of “arrays”: JudoScript
arrays, Java arrays (of Object’s or primitive types) and
java.util.List instances. That gives the impression that Java arrays
and List’s behave just like, well, arrays. Unfortunately it is not
the case outside of the “for in” statement AS YET. I will make this
behavior consistent in v1.0, i.e., any Java arrays and Lists should
share all the features of JudoScript arrays, not just the “for in”
statement. Thanks for pointing this out.


Scripting Apps
Nice examination of how to use Judoscript to script Excel

Additional Info:
(translation of page


* * *


Judoscript and Databases · 5939 days ago,

First off, if you found this page via a web search or bookmark, you may be much happier in the JudoScript Section of this site to see the multiple articles about Judoscript, including this one, but also about Databases, Graphics, Files, etc.

Database Access
Primary docs at including good example of batch updating. Note that I am using the namespace style syntax, new to recent versions of Judoscript, which uses ::.

Lots of detail at the JDBC Book Chapter

You probably need your JDBC files in your classpath for this to work. On Windows, I added an environment variable like this:
System Properties (or My Computer Properties); Advanced tab; Environment Variables.
I added:

C:\Program Files\judoscript-0.9\judo.jar;c:\oracle\ora92\jdbc\lib\;c:\oracle\ora92\jdbc\lib\;


 const #dbUrl  = 'jdbc:oracle:thin:@localhost:1521:crescent';
 const #dbUser = 'jamesh';
 const #dbPass = secret('guess');
 db::connect conny to #dbUrl, #dbUser, #dbPass;

“conny” here is a connection object. If it is not present, the default connection object, named $$con, is used, and its methods can be invoked directly. .describe() describes a database table and returns the information in a tableData structure (a proprietary and pretty handy Judoscript feature).

  tableInfo = describe(table);
  println tableInfo.getTitles(); //prints the columns in the table

Can also use .getMetaData(). It returns an extended object of java.sql.DatabaseMetaData class, except that any of its methods that returns a result set are overridden and return a tableData instead.

        md = getMetaData();
        tables = md.getTables('PROJ_%');
        println tables;

(Note that, if your database is not in the known list that is hardcoded into Judoscript, then the JDBC driver has to be loaded explicitly like you would in Java: java.lang.Class::forName(‘your.jdbc.driver.Name’); Then continue with the connect to …. command.)


Before querying, you can actually check to see if your table is present:

  if tableExists('EMP') {
      DROP TABLE emp /* 'emp' is case-insensitive */ ;

A query looks like this:

        db::query qry:
          select * from table1
          where seq < 5;
        while {

          println '--------';
          println qry[1];            // column 1
          println qry."Record Type"; // column by that name

Remember that result sets are 1 based, but TableData results are arrays and so are 0 based.

Another way to get columns, besides the above is, assuming you have query a:


  //  The below prints each column header 
  for i from 1 to colcount {
    println i,'=',aMetaData.getColumnLabel(i);

Now, there are different kinds of SQL statements. Queries which return rows are db::query things. But CREATE, DROP and INSERTs either work or they don’t, and you don’t walk their results. These are db::sql things.

These can be either db::sql: single statment; or db::sql{ statement; statement; statement; }

Can also have prepared statements:

        prepare a:
          select * from people order by alias
        executeQuery a;


        preparedExecuteQuery a:
          select * from people order by alias

The “query” object changes depending on where you are in the process. When a query is executed or prepared, this query object represents the query itself. After execution, it also represents the result set.

The result set has a number of methods, and one of the most important ones is .next(), which allows JudoScript code to traverse the results. For each iteration, the query object represents the current row, too! Each column in the row can be accessed either via an index (the first column has index 1) or via the column name. In this example, we use qry1 to reference the column named “emp_no”, and other columns are referenced by their names. (so, how do get get the count of columns? How do we get the column names?)

James uses examples like this. Note that he is hand formatting the column types, b/c he hard coded them in the query:

 !include 'setup/connect.judi'
 executeQuery qry:
   SELECT emp_no, first_name, last_name, birth_date, salary
   FROM emp
 println 'ID   First-Name  Last-Name    Salary    Birth-Date', nl
         '---  ----------  -----------  --------  ----------';
 while {
   println qry[1].int()   :<5,
           qry.first_name :<12,
           qry.last_name  :<12,
           qry.salary     :*7.1, '  ',


Because these are basically all cursors, they can have the usual JDBC options:

I’ve found, however, that Judoscript doesn’t have a simple “print the query output” routine, so I’ve been using code like this:

 //  for info on building connect string 

 const #dbUrl='';
 const #dbUser='AUser';
 const #dbPass='APassword';

 connect to #dbUrl, #dbUser, #dbPass;

 executeQuery a:
    select * from tablespace.t_url 
    where client_id=developer.clientid('clientname')
        and rownum < 100 and url_Id>30000
 // How many columns did we get?

 // Print a header
 for i from 1 to colcount {
 	println i,'=',aMetaData.getColumnLabel(i);

 // Print the output
 while {
   for i from 1 to colcount { 
     print a[i];
     if i != colcount {print '\t';} 
 // We're Done.

Advanced Queries
You can actually pass code in as a bundle, say, to make stored procedures and such. SQL statements in the block are delimited by a semicolon (;). However, sometimes you need to send a semicolon to the db: so, use the executeAny statement. In executeAny, all text is sent to the database server as-is. Note the use of the [[**]] “here-doc” styling:

executeAny [[*
    param_io IN OUT NUMBER,
    param_i  IN     VARCHAR,
    param_o  OUT    VARCHAR)
    param_o := param_i;
    IF param_io IS NOT NULL THEN

      param_io := param_io + 1;
      param_io := -1000;
    END IF;

You can use Parameterized SQL through the db::prepare statement.

Stored Procedures can be tricky. Here is an example from James’ site:

include 'setup/connect.judi'

// create the stored procedure
executeAny [[*
  create package types
    type cursortype is ref cursor;

executeAny [[*
  create function ListPeople return types.cursortype
    l_cursor types.cursorType;
    open l_cursor for
      select emp_no, first_name, last_name, birth_date, salary
      from emp;
    return l_cursor;

// test it
prepareCall: { :ret = call ListPeople };

executeSQL with @ret:oracle_cursor => res;

while {
  println res[3] :<12, res[4].fmtDate('yyyy-MM-dd');


As he says, “The Oracle function, ListPeople, returns a “cursortype” which is a ref cursor defined in a package named types. The JudoScript executeSQL statement returns this as a oracle_cursor into variable res, which is used in the subsequent loop to print out some results.”. More details here

Using HSQL
From a user on Yahoo Groups:

1. Make sure that you have hsqldb.jar in your classpath.
2. Create a directory anywhere, such as d:mydata, and create a batch file such as startdb.bat like this:

 cd mydata
 java org.hsqldb.Server -database mydb

You don’t have to do anything to create the database. The first time it runs and does not see a database, it creates one for you (with user name as “sa” and no password).

3. Connect to it via JDBC.

 connect to 'jdbc:hsqldb:hsql://localhost', 'sa', '';

 CREATE TABLE my_table (

        name VARCHAR NOT NULL,
        password VARCHAR,
        email VARCHAR NOT NULL,
        country_id INTEGER,
        active BIT,
        create_time DATE NOT NULL,
        UNIQUE (email),
        FOREIGN KEY (country_id) REFERENCES country(id)


And from now on, business as usual…

4. In the data directory, 2 files seem to be important: and mydb.script. But seems always of 0 bytes, where mydb.script keeps all the SQL statements! Kinda like Oracle REDO log, which allows you to reproduce the whole database.
Near the top, it has a line:


I changed the admin user/password by editing this file! Don’t
forget to also change the following statement, otherwise it won’t


Original Source = about HSQLDB and org.hsqldb.util.DatabaseManager.

Database Metadata

How is aFields = a.getColumnAttributes(); different from a “desc()” function?
describe() describes a database table, appears to return the following:

Column Type Precision Scale Nullable’;

As in:

 connect to url, username, password;
 tableInfo = describe(table);

 println 'Table: ', table, nl;
 println 'Column         Type            Precision   Scale Nullable';
 println '-------------- ------------ ------------ ------- ----------';
 printTable tableInfo for
   column('name')      :<15!,
   column('type')      :<13!,
   column('precision') :>12,
   column('scale')     :>8, ' ',

Is it possible that a.getColumnAttributes(); returns the same thing?
column(0) appears to be same as column 1, col 7 (0 counting) is Null, and then false and blank?

.transpose method?


* * *


Judoscript and Files · 5939 days ago,

First off, if you found this page via a web search or bookmark, you may be much happier in the JudoScript Section of this site to see the multiple articles about Judoscript, including this one, but also about Databases, Graphics, Files, etc.

Reading and Writing Files
Documented at

Finding Them
To get a list of files and directories, use the listFiles command.

 listFiles '*.judo' in 'C:/Documents and Settings/Michael/My Documents';
 for x in $_ {
   println x;

Note the use of single quotes and forward slashes! Windows people are used to the backward slash and double quotes around filenames with spaces in them; break that habit here. An alternative is to use double backslashes (\\) instead of single ones (\) in Windows.

The listFiles command can also look inside Zip and Tar files, as well as run recursively (and you can limit the recursion). You can order by different file attributes, exclude files by name (or use “dirOnly” to just list directories), and also gather counts and total size while reading the tree. Speaking of trees, listFiles can also return its findings as a Tree (collection of TreeNodes, JudoScript specific datastructure).

Finally, note that listFiles can also use the “addToClasspath” action to add its findings right to the (current and temporary) classpath.

BTW, JudoScript can also mkdir, rmdir, rename/move files, change file attributes, execute shell commands on files, and work with archives. If you are interested, read the chapter.

Oh, one more little trick: copy can use URLs. You can save results of a link like this:

 copy '' to 'i.html';

If the file name is not specified in the URL, JudoScript provides a default file name, “default.htm”. (This works fine for text html; I haven’t tested for binary files… but should work just as well, I bet).

Working with Them
Methods include .fileExists, .isDir(); .isFile(); .fileTime(); .fileSize()

To read from or write to a file, it must be opened first in binary stream mode, binary random access mode or text mode. The open file is stored as a handle, and closed when done.

Text Files
Following the Judoscript example program, the following program adds line numbers and prints on the standard output:

  if #args.length() == 0 {
    println 'Usage: java judo ', #prog, ' <filename>';
    exit 0;
  file = openTextFile(#args[0]);
  for lineNum=1; (line=file.readLine()) != eof; ++lineNum {
    println lineNum : >3, ': ', line;


Can skip characters with file.skip(5); .read() reads a single character as ascii: ch =;

So, the do … as lines mechanism makes it easy to walk through a file line by line. If you don’t give a variable, it uses the _$ default variable. the loopIndex() function lets you know where you are in the implicit loop, acting as a “line counter” in this case.

  // Read file, split each line on its tabs, etc.
  do afile as lines {
    if (loopIndex() < 10) continue;
    fields = $_.csv('t');
  // ....

To write, use println, print, or flush. flush does exactly the same as print except it flushes the output stream.
println always flushes. The target can be out (the default), err, log, pipe or a variable that denotes an open text file. Here is an example:

  dat = openTextFile('important.dat', 'w'); // 'w': write.
  dat.println  '2001/10/1,XYZ,12.00,100000';

So, the JudoScriptish way to handle looping, though, is pretty cool. Here’s a sample from James on the Yahoo Groups list. It uses a local “heredoc” to keep the data in the script (and read from $$local), but same idea. Note how he uses an if to skip the header if it exists by testing for it. Also, this one splits on spaces, but it could just have easily split on \t tabs

  usage {
  minArgs = 3;
  args = 'dbUrl, dbUser, dbPassword';
  desc = 'Inserting records into a db table';

  db::connect to #args[0], #args[1], #args[2];

  var started = false;
  do $$local as lines {
    if started {
      var fields = $_.csv(" ");
      insert into t_wd_ratings(userid, itemid, ratingvalue)
                     values ( (* fields[0] *), (* fields[1] *), 1)
    elif $_.startsWith('MKCCUSID_C ') {
      started = true;

  db::disconnect a;

  EndScript ===============================

136 1008363 1
137 1008363 C 1
138 1008363 P 1
631 1009537 2
632 1009537 C 2
633 1009537 P 2
634 1008410 FRA 1
635 1008411 1
636 1008411 C 1

Binary Files
Binary files are opened with openFile() system function. Usually, a Java byte array is used to read chunks of the file. See:


* * *


Judoscript and Graphics · 6044 days ago,

First off, if you found this page via a web search or bookmark, you may be much happier in the JudoScript Section of this site to see the multiple articles about Judoscript, including this one, but also about Databases, Graphics, Files, etc.

Basic info at though Listing 2 is completely wrong.

Probably need to update all of this with namespace issues (i.e., use gui::events instead of guiEvents, etc.)

Basic shell resembles this:

 const #JFrame = javaclass javax.swing.JFrame;
 frame = javanew #JFrame("Simplest GUI");
 guiEvents {
   <frame:Window:windowClosing> :  exit(0);

The Frame-Window thing basically reads as component frame which listens for Window events and handles the windowClosing message.

Buttons get <b1,b3: Action : actionPerformed> : with behaviors following the colon. More at

From the Docs: GUI programs typically involve large number of Java classes. Declaring them one by one is tedious, because they are spread across many different packages. JudoScript provides a mechanism called standard Java class declaration shortcut, which are three directives used to easily declare a large number of standard J2SE and J2EE classes:

 !JavaBaseClass  =     #System, #Hashtable, #Dimension
 !JavaGuiClass   =     #JFrame, #JPanel, #Color, #ActionListener
 !JavaEnterpriseClass = #HttpServletRequest, #EJBObject, #EJBContext

Look out for the Extra Paren on formatbool()),

Additional sample code, this from the mailing list:

 !JavaBaseClass #Object, #String, #Integer, #Boolean
 !JavaGuiClass #BorderLayout, #JTable, #JScrollPane,
                       #JPanel,#JFrame, #Dimension
 $h = new array();
 $t = new tableData();
 $file = openTextFile("data.txt");
 $fc = new array();
 while (($line=$file.readLine()) != eof )
         $t = new tableData($h = $line.csv() );
         while (($line=$file.readLine()) != eof )
                  $t.add( $line.csv() );
 $columnNames = $h.toStringArray();
 $data = $t.getData();
 $table = javanew #JTable($data, $columnNames);

And, from a mailing list commentary:
Since you are watching for a click on a button, you should be using Action : actionPerformed. This is standard Java. Second, you should place the code executed by the GUI event inside a function and call the function instead. Using a function in the event handler instead of free-flowing code in the event handler is a technique used by most professional programmers. It allows you to keep your code modular and makes it easier to make modifications later if the need arises. The code is also easier to read.

More sample code:

 !JavaBaseClass #String
 !JavaGuiClass #JFrame, #JPanel, #JButton
 frame = javanew #JFrame("FRAME");
 button = javanew #JButton("Click me!");
 panel = javanew #JPanel;
 str = javanew #String("On ButtonClick, this string should be produced 10 times on the prompt.");
 var = 9;
 guiEvents {
     < button : Action : actionPerformed> :
     <frame : Window : windowClosing> : exit;
 function print_String_Ten_Times {
         for i from 0 to var { flush i; . "-> ",str; 

A popular way to create a GUI is through an XML description file and handing that to a display library. The family of these programs is called XUL (based on the Mozilla XML programming specification), but there are a few which are more or less popular. Also, not everyone follows the XUL XML format; some make their own extensions or XML standards… but XUL seems to be winning out.

One version is a quick and easy set of widgets which work well on applets, mobile and underpowered devices, as well as requiring less overhead than Swing or SWT. Thinlets is basically one class, is LGPL, and only 38k. It basically uses the AWT widget set. SwiXml is sort of parallel project to Thinlets, and gives access to the entire Swing library. This latter is a more expandable option, but of course, its also larger and fatter (at runtime, of course; the library is still very small!).

The groups had some discussion on how to use Thinlets with Judoscript; look here

Also, if you are a XUL person, there are lots of others. For example, Ultrid has a BSF interface and so can link to Judoscript. If you are married to the Mozilla XUL, btw, then you want Luxor (No idea if the latter will work with Judoscript, btw.) is a nice summary of current options for Guis. Xul Alliance tries to organize all the XUL specific ones.


* * *


powered by Textpattern 4.0.4 (r1956)