Friday, May 30, 2008

Write Java Application Using JavaScript

JDK 6.0 introduces the Java Scripting API and includes a Javascript scripting engine adapted from Mozilla Rhino project. With Scripting API, it is possible to write applications that end users can extend and customize. Java program can invoke scripting code and vice versa. Here I show an simple application that is primarily written in Javascript.

The application consists of two parts, one is written in Java and the other in Javascript. Here is the Java source code:

import javax.script.ScriptEngineManager;
import javax.script.ScriptEngine;
import javax.script.ScriptException;
import javax.swing.AbstractAction;

import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.io.FileReader;
import java.io.IOException;

public class test
{
public static void main(String[] args)
{
ScriptEngineManager manager = new ScriptEngineManager();
ScriptEngine engine = manager.getEngineByName("js");
if (engine != null) {
try {
engine.eval(new FileReader("test.js"));
} catch (IOException e) {
e.printStackTrace();
} catch (ScriptException e) {
e.printStackTrace();
}
}
}
}

class JSAction extends AbstractAction
{
private ActionListener actionListener;
public JSAction(ActionListener listener, String name)
{
super(name);
actionListener = listener;
}

public void actionPerformed(ActionEvent e)
{
actionListener.actionPerformed(e);
}
}

The code in main is straitforward. It simply find the Javascript scripting engine and run the script. I will explain the purpose JSAction later. The following the Javascript code:

importPackage(java.lang);
importClass(java.awt.event.ActionListener);
importClass(java.awt.BorderLayout);
importClass(javax.swing.JFrame);
importClass(javax.swing.JTextArea);
importClass(javax.swing.JMenuBar);
importClass(javax.swing.JMenu);
importClass(javax.swing.text.DefaultEditorKit);
importClass(Packages.JSAction);

frame = new JFrame;
frame.setSize(320, 240);

text = new JTextArea;
text.setLineWrap(true);

content = frame.getContentPane();
content.add(text, BorderLayout.CENTER);

menubar = new JMenuBar();
file = new JMenu("File");

method = {
actionPerformed: function() { System.exit(0); }
}
exitAction = ActionListener(method);
// JSAction extends AbstractAction. See Java code above.
file.add(new JSAction(exitAction, "Exit"));

edit = new JMenu("Edit");
edit.add(text.getActionMap().get(DefaultEditorKit.cutAction));
edit.add(text.getActionMap().get(DefaultEditorKit.copyAction));
edit.add(text.getActionMap().get(DefaultEditorKit.pasteAction));

menubar.add(file);
menubar.add(edit);
frame.setJMenuBar(menubar);

frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setVisible(true);

The importPackage function imports a package, while the importClass function imports a Java class. To import an non-JDK class, prefix it with Packages, e.g., Packages.JSAction. As one can see from the example, calling Java APIs from JavaScript is quite easy. The only tricky part is to implement a Java interface or extend a Java class in JavaScript. While Rhino engine allows the JavaScript to implement interface and extend class, JDK 6 JavaScript engine only allows the implementation of a single interface using the syntax:

InterfaceName(MethodMap)

The MethodMap is a JavaScript associate array, with the method names of the interface as the keys, and the function definitions as values. The above JavaScript code shows how to implement an ActionListener interface.

The problem here is that we need to add an extended class of AbstractAction to the file menu with our own actionPerformed method to exit the application. However, it is impossible to do so in JDK 6 scripting engine. The hack here is to implement a Java class JSAction that extends AbstractAction, with the actionPerformed method delegated to an instance of ActionListener implemented by JavaScript. According to Sun, the need to extend a class or implement multiple interface is very rare, which I do not necessary agree. I hope this restriction can be relieved in the future release.

Wednesday, May 28, 2008

C++ Regular Expression for Perl Programmer

Boost Libraries are probably the best things happened to C++ after STL. With a great emphasis on generic programming and heavy use of templates, Boost allows C++ to be used as a higher level language than it used to be. Although the implementation of Boost libraries is somewhat complex, using them is actually quite easy.

One of the potentially useful libraries is the regular expression library, which provides Perl-like regular expression support. The following is a Perl script to extract the host name from an URL:
my $url = "http://www.mywebsite.com/index.html";
if ($url =~ /http:\/\/((\w+\.)+\w+)/) {
print "$1\n";
}
Here is a C++ program doing similar thing using Boost regular expression library:
#include <iostream>
#include <string>
// Boost regular expression header file
#include <boost/regex.hpp>

using namespace std;
using namespace boost;

int main()
{
string url = "http://www.mywebsite.com/index.html";
regex re("http://((\\w+\\.)+\\w+)/");
smatch what;
if (regex_search(url, what, re)) {
cout << what[1] << endl;
}
}
The regular expression used in Boost is very similar to Perl's. However, the escaping of characters is somewhat different. For example, in Boost, there is no need to escape '/' (doing so will cause a "unrecognized escape character" compiler error). While the '\' for special notations like "\w", "\s" must be escaped in Boost, so it looks like "\\w".

The line:
smatch what;
defines a variable what to store the matching results. what[1] is equivalent to $1, what[2] is to $2, and so on.

As you can see, the use of regular expression in Boost is quite straightforward for Perl programmer.

Tuesday, May 27, 2008

A Simple Sudoku Solver in C

Here is a simple Sudoku solver in C. It uses backtracking technique to find all possible solutions.
#include <stdio.h>

/* Display the result. */
void display(const int grid[][9])
{
int i,j;
for (i=0; i<9; i++) {
for (j=0; j<9; j++) {
printf("%d ", grid[i][j]);
}
printf("\n");
}
}

/* Verify the grid is in valid state */
int verify(const int grid[][9], int c, int x, int y)
{
int i, j;
int xs, ys;
for (i=0; i<9; i++) {
if (grid[i][y] == c || grid[x][i] == c)
return 0;
}
xs = x/3;
ys = y/3;
for (i = xs*3; i<(xs+1)*3; i++) {
for (j = ys*3; j< (ys+1)*3; j++) {
if (grid[i][j] == c)
return 0;
}
}
return 1;
}

/* The core of the solver. */
void solve(int grid[][9], int x, int y)
{
if (grid[x][y] != 0) {
if (x==8 && y==8) {
display(grid);
} else {
solve(grid, (x+1)%9, (x==8) ? (y+1) : y);
}
} else {
int c;
for (c=1; c <= 9; c++) {
if (verify(grid, c, x, y)) {
grid[x][y] = c;
solve(grid, x, y);
}
}
grid[x][y] = 0;
}
}

int main()
{
int c[9][9];
int i,j;
for (i=0; i<9; i++) {
for (j=0; j<9; j++) {
scanf("%d ", &(c[i][j]));
}
}
solve(c, 0, 0);
return 0;
}
Compile the program:
cl sudoku.c

Run the program:
sudoku < in.txt

Where in.txt the input file. Here is a sample input file:
(I found it here.)

0 0 1 0 0 5 3 0 0
0 5 0 4 9 0 0 0 0
0 0 0 1 0 2 0 6 4
0 0 0 0 0 0 7 5 0
6 0 0 0 0 0 0 0 1
0 3 5 0 0 0 0 0 0
4 6 0 9 0 3 0 0 0
0 0 0 0 2 4 0 9 0
0 0 3 6 0 0 1 0 0