2004-12-17

"The State of Fear" by Michael Crichton

Right now, I am reading this marvelous book by Michael Crichton. I am almost through half of it, and I should say it is even much better than Prey. Sort of like Deception Point by Dan Brown. Something icy like that :-), but full of scientific jargon and things I really like. I recommend it to everybody. It rocks.

2004-12-03

To say goodbye is to die a little. -- Raymond Chandler

Recently, I have read numerous novels and science fiction works, including books by Dan Brown, Michael Crichton, Laurell K. Hamilton, and Patricia Cornwell. There are also many books by Agatha Christie, Herbert George Wells, Phyllis Whitney, Walter Gibson, etc., which I have read a few years ago. But one or two months ago, I decided to read works by Raymond Chandler. I had heard his name as a detective storywriter. Now, I have just finished reading "The Long Goodbye" and I can't help but wonder how to express my feelings. It was such a terrific piece of art and story telling. And much more, in fact.

After reading a book, that is when some time passes by, I usually do not remember the story itself or the plots and events in it. But what stays in my mind and makes me think about it now and then, are the characters, the feelings, and the thoughts.

What you find in "The Long Goodbye" is not a series of events designed ingeniously to entertain you; it does entertain you all right, but it has much more to offer. The personality of Philip Marlowe, IMHO, tries to show the multidimensional and multifaceted nature of a human being, bringing into light the inevitable fact that there are dimensions, which are more genuine to being human than others. There are things that are more important, and there are ideas and motives that, even though scarcely expressible, are the characteristics of a lovable and good person.

2004-10-28

The Power of Simple Tags

Simple tags, in contrast to classic tags, are a new feature in JSP 2.0 with a huge positive impact on the usefulness of this technology. In short, simple tags allow you to abstract functionality and refactor template data in JSP, and undoubtedly, refactoring and abstraction is what programming is all about. Since simple tags are nothing but JSP files (or even better, XML documents, if you are wise enough to always use JSP documents based on XML technology), they allow page authors who are not familiar with the Java programming language to use the vast capabilities of Java and JSP.

Here I am going to explain simple tags through an example. I will present a complete JSP application (though very simplistic) to visualize the use of simple tags. In this example, I presume we use Tomcat 5.5 (based on JDK 5.0). The test application is placed in TOMCAT/webapps/test/ (or TOMCAT/webapps/newtest/) directory and its subdirectories, where TOMCAT must be replaced with the directory where you have installed Tomcat. The two simple examples presented here can be viewed at URLs: http://localhost/test and http://localhost/newtest, provided you have configured Tomcat to use port 80. It should be remembered that JSTL JAR files (standard.jar and jstl.jar) must be accessible to this application, e.g. must be placed in TOMCAT/webapps/test/WEB-INF/lib.

Consider the first version of this simplistic application:

TOMCAT/webapps/test/index.jspx

<?xml version="1.0" encoding="windows-1256" ?>

<jsp:root version="2.0" xmlns:jsp="http://java.sun.com/JSP/Page" xmlns:c="http://java.sun.com/jsp/jstl/core">

<jsp:directive.page contentType="text/html; charset=UTF-8" />

<html>

<head>

<meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />

<meta http-equiv="Content-Language" content="fa" />

<title>سلام</title>

</head>

<body style="direction: rtl;">

<h1>سلام</h1>

<c:url scope="page" var="mylink" value="/user/index.jspx">

<c:param name="dummy" value="3" />

</c:url>

<p>

این صفحه‌ی اول پایگاه ما است. برای اطلاعات بیشتر به

<a href="${mylink}">این صفحه</a>

مراجعه کنید.

</p>

</body>

</html>

</jsp:root>

TOMCAT/webapps/test/user/index.jspx

<?xml version="1.0" encoding="windows-1256" ?>

<jsp:root version="2.0" xmlns:jsp="http://java.sun.com/JSP/Page" xmlns:c="http://java.sun.com/jsp/jstl/core" xmlns:h="urn:jsptagdir:/WEB-INF/tags/html">

<jsp:directive.page contentType="text/html; charset=UTF-8" />

<html>

<head>

<meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />

<meta http-equiv="Content-Language" content="fa" />

<title>اطلاعات</title>

</head>

<body style="direction: rtl;">

<h1>اطلاعات</h1>

<c:url scope="page" var="mylink" value="/index.jspx" />

<p>

مقدار پارامتر داده شده

<c:out value="${param.dummy}" />

است، ولی واقعاً اهمیتی ندارد. حالا می‌توانید به

<a href="${mylink}">صفحه‌ی اول</a>

بر گردید.

</p>

</body>

</html>

</jsp:root>

TOMCAT/webapps/test/WEB-INF/web.xml

<?xml version="1.0" encoding="windows-1256" ?>

<web-app xmlns="http://java.sun.com/xml/ns/j2ee" xsi:schemaLocation="http://java.sun.com/xml/ns/j2ee web-app_2_4.xsd" version="2.4" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">

<description>Test application to show use of simple tags.</description>

<display-name>TestApp</display-name>

<welcome-file-list>

<welcome-file>index.jspx</welcome-file>

<welcome-file>index.html</welcome-file>

</welcome-file-list>

</web-app>

Now, simple tags can do 2 things for us here:

  1. Abstracting functionality. Consider creating a hyperlink. First you create the URL using <c:url /> tag from JSTL core library, and store it in a variable. Then you use the value of that variable in an HTML <a /> tag. This can be made easier using simple tags, as you will see briefly.
  2. Refactoring template data. Both pages contain some common static text data that can be refactored using simple tags.

The new version of our program uses simple tags to solve these two problems conveniently.

TOMCAT/webapps/newtest/index.jspx

<?xml version="1.0" encoding="windows-1256" ?>

<jsp:root version="2.0" xmlns:jsp="http://java.sun.com/JSP/Page" xmlns:c="http://java.sun.com/jsp/jstl/core" xmlns:h="urn:jsptagdir:/WEB-INF/tags/html">

<jsp:directive.page contentType="text/html; charset=UTF-8" />

<h:page title="سلام">

<h1>سلام</h1>

<p>

این صفحه‌ی اول پایگاه ما است. برای اطلاعات بیشتر به

<h:a href="/user/index.jspx?dummy=3">این صفحه</h:a>

مراجعه کنید.

</p>

</h:page>

</jsp:root>

TOMCAT/webapps/newtest/user/index.jspx

<?xml version="1.0" encoding="windows-1256" ?>

<jsp:root version="2.0" xmlns:jsp="http://java.sun.com/JSP/Page" xmlns:c="http://java.sun.com/jsp/jstl/core" xmlns:h="urn:jsptagdir:/WEB-INF/tags/html">

<jsp:directive.page contentType="text/html; charset=UTF-8" />

<h:page title="اطلاعات">

<h1>اطلاعات</h1>

<p>

مقدار پارامتر داده شده

<c:out value="${param.dummy}" />

است، ولی واقعاً اهمیتی ندارد. حالا می‌توانید به

<h:a href="/index.jspx">صفحه‌ی اول</h:a>

بر گردید.

</p>

</h:page>

</jsp:root>

TOMCAT/webapps/newtest/WEB-INF/tags/html/page.tagx

<?xml version="1.0" encoding="windows-1256" ?>

<jsp:root version="2.0" xmlns:jsp="http://java.sun.com/JSP/Page" xmlns:c="http://java.sun.com/jsp/jstl/core">

<jsp:directive.tag body-content="scriptless" />

<jsp:directive.attribute name="title" required="false" rtexprvalue="true" />

<html>

<head>

<meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />

<meta http-equiv="Content-Language" content="fa" />

<c:if test="${not empty title}">

<title>${title}</title>

</c:if>

</head>

<body style="direction: rtl;">

<jsp:doBody />

</body>

</html>

</jsp:root>

TOMCAT/webapps/newtest/WEB-INF/tags/html/a.tagx

<?xml version="1.0" encoding="windows-1256" ?>

<jsp:root version="2.0" xmlns:jsp="http://java.sun.com/JSP/Page" xmlns:c="http://java.sun.com/jsp/jstl/core">

<jsp:directive.tag body-content="scriptless" />

<jsp:directive.attribute name="href" required="false" rtexprvalue="true" />

<c:url scope="page" var="mylink" value="${href}" />

<a href="${mylink}">

<jsp:doBody />

</a>

</jsp:root>

TOMCAT/webapps/newtest/WEB-INF/web.xml

<?xml version="1.0" encoding="windows-1256" ?>

<web-app xmlns="http://java.sun.com/xml/ns/j2ee" xsi:schemaLocation="http://java.sun.com/xml/ns/j2ee web-app_2_4.xsd" version="2.4" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">

<description>Test application to show use of simple tags.</description>

<display-name>TestApp</display-name>

<welcome-file-list>

<welcome-file>index.jspx</welcome-file>

<welcome-file>index.html</welcome-file>

</welcome-file-list>

</web-app>

This was barely more than a "Hello World!" app, but here are two screenshots of the pages to show that it works properly:

TOMCAT/webapps/newtest/index.jspx

 

TOMCAT/webapps/newtest/user/index.jspx

The code archive for this example can be found here.

P.S.

  1. Even though I don't have plenty of visitors, but the few people who have been visiting this page are always a source of encouragement for me. I am especially grateful to those few who have written comments or have sent me emails in this regard. But some of these folks have been asking me questions about the Java programming language to whom I have barely had time to respond. It should be noted that I do not claim to teach Java -- in fact, I think I have an innate deficiency in teaching abilities! As a pediatric practitioner, I scarcely have time to do that. This is in fact an apology to all of those who have written to me and have not received any response yet. I do appreciate your interest and correspondence, but I may not be able to reply to your emails in the near future.
  2. Recently, I was informed that SustainableGIS company has created a testing page for my persiancalendar Java program. This is the first use of this program in the real world that I am aware of.

2004-09-16

Book Links

Do you know how many books are there on the Internet? There are numerous movements for scanning and OCRing books around the world (besides older initiatives like the Project Gutenberg and sites like BlackMask). So I estimate that currently, there are in excess of 100,000-500,000 books on the Internet. (Of course, this is a wide range, but I can't be any more exact.) Also, please note that I mean publicly available books (though not all legal), since there may be thousands of books in the publishers' sites that are not available to the public.

Recently, I have spent a lot of time in extracting book links from the Internet. As an example, the links for the book "Flatland" by Edwin A Abbott are given below (not all the links may be active now):

Online versions of Flatland by Abbott, Edwin A
http://download.usenet-replayer.com/L/H/9/0/5/3/1055393509.351.zip
http://download.usenet-replayer.com/L/H/9/3/8/0/1067860839.1.zip
http://dwalin.ru/books/Abbott, Edwin/Flatland.txt.gz
http://www.portal5.co.uk/books/Abbott/Flatland.txt
http://www.blackmask.com/cgi-bin/links/jump.cgi?ID=d1453
http://groups.yahoo.com/group/lg-ay/files/Planilandia.zip

Note: I am not sure if downloading these links is legal. Giving these links is for informational purposes only.

Now, I thought of an interesting thing to do. I have a collection of ca. 40,000 book links. I counted the number of occurrences for each author among them. This is a partial result of this statistics (some books, like Star Trek series, with indeterminate authors have been omitted):

Author stats
Author Count
King, Stephen 553
Asimov, Isaac 524
Lovecraft, HP 379
Heinlein, Robert A 349
Lem, Stanislaw 334
Grant, Maxwell 292
Simak, Clifford D 284
Clarke, Arthur C 239
Harrison, Harry 231
Bradbury, Ray 224
Sheckley, Robert 221
Balzac, Honoré de 208
McCaffrey, Anne 193
Niven, Larry 185
Andersen, Hans Chiristian 182
Fitzgerald, F Scott 180
Grimm, Hermanos 178
Doyle, Sir Arthur Conan 163
Zelazny, Roger 158
Pohl, Frederik 145
Asprin, Robert Lynn 138
Silverberg, Robert 136
Anderson, Poul 133
Borges, Jorge Luis 133
Dick, Philip K 132
Foster, Alan Dean 132
Burroughs, Edgar Rice 127
Norton, André 119
Le Guin, Ursula Kroeber 115
Card, Orson Scott 111
Twain, Mark 108
Dickens, Charles 106
Ellison, Harlan 103
Shakespeare, William 103
Dumas, Alexandre 102
Farmer, Philip José 101
Christie, Agatha 99

I wonder if this list also reflects the global trend of reading authors, or if it is affected by other factors, as well. Of course, in collections like the Project Gutenberg, only books with expired copyright span are published. But sporadic scanners do not obey laws as rigidly, so that the newest books of famous authors are published on the Web after only a few days of their publication (e.g., "Harry Potter and the Order of the Phoenix" by JK Rowling was published on the Internet just a few days after its official release date).

2004-08-19

Layout Change

I am making some changes in the template just now. Also, I am going to start using the commenting facility of Blogger.com. There may some problems for a while.

Using Reflection for Actions

There is no doubt that inner classes are an important aspect of the Java programming language. The easiest way to define an action in a GUI application is to subclass the javax.swing.AbstractAction class and override its actionPerformed method, usually in an inner class. Yet, actions are so frequent in these applications that it would be nice to simplify the process further. Here, I suggest a way that I have found very useful.

If we have an action named "Open", we might expect it to call a method like "onOpenExecute" without creating a specific class for it. This can be done, using the Java Reflection API.

The ReflectiveAction class, whose code is presented below, uses the reflection API to find its relevant execute method in the owner object. The method's name is constructed using the "key" property of the ReflectiveAction instance. For example, if a ReflectiveAction has a key value of "open", it will reflect on the owner object's class, to see if it contains a public method called "onOpenExecute". If this method is found, it will be called upon firing of this action. For a key value of "file.print", the execute method must be named onFilePrintExecute. Period character is ignored, so a key value of "Choose..." needs a method called onChooseExecute. Other special characters should not be used in the key field (I have done my best to keep the code as simple as possible).

The source code for the ReflectiveAction class is presented below. It must be taken in mind that in this example, an enhanced for loop has been used, which is a feature recently added to Java since JDK 1.5. When compiling this file with javac, a -source 1.5 parameter must be supplied to show that the source is compliant with JDK 1.5 and not the earlier versions. Interestingly, when I used the -target 1.5 parameter in addition to that, the reflection stuff kept hanging the JVM when running. I don't know if this bug is still there or has been corrected in later SDKs (I have build 1.5.0-beta-b31), but anyway, without this option, everything goes well, and I am not in the mood of keeping track of bugs!

Listing 1. Source code of ReflectiveAction.java
/* 
 * ReflectiveAction.java 
 * (c) Ghasem Kiani 
 * 18/08/2004 06:33:49 PM 
 * ghasemkiani@yahoo.com 
 */ 
 
package com.ghasemkiani.temp; 
 
import java.awt.*; 
import java.awt.event.*; 
import javax.swing.*; 
import java.lang.reflect.Method; 
 
public class ReflectiveAction extends AbstractAction 
{ 
  private Method executeMethod; 
  private String key; 
  public void setKey(String key) 
  { 
    this.key = key; 
  } 
  public String getKey() 
  { 
    if(key == null) key = new String(); 
    return key; 
  } 
  private String getKeyAsTitleCase() 
  { 
    String[] parts = getKey().split("\\."); 
    String result = ""; 
    for(String part: parts) 
    { 
      if(part != null) 
      { 
        if(part.length() > 0) 
          result += part.substring(0, 1).toUpperCase(); 
        if(part.length() > 1) 
          result += part.substring(1); 
      } 
    } 
    return result; 
  } 
  private Object owner; 
  public void setOwner(Object owner) 
  { 
    this.owner = owner; 
    if(owner != null) 
    { 
      Class oc = owner.getClass(); 
      String em = "on" + getKeyAsTitleCase() + "Execute"; 
      try 
      { 
        executeMethod = oc.getMethod(em, new Class[0]); 
      } 
      catch(Exception e) 
      { 
        executeMethod = null; 
      } 
    } 
    else 
    { 
      executeMethod = null; 
    } 
  } 
  public Object getOwner() 
  { 
    return owner; 
  } 
  public ReflectiveAction() 
  { 
    super(); 
  } 
  public ReflectiveAction(Object owner, String key) 
  { 
    super(key); 
    setKey(key); 
    setOwner(owner); 
  } 
  public ReflectiveAction(Object owner, String key, String name) 
  { 
    super(name); 
    setKey(key); 
    setOwner(owner); 
  } 
  public ReflectiveAction(Object owner, String key, Icon icon) 
  { 
    super(key, icon); 
    setKey(key); 
    setOwner(owner); 
  } 
  public ReflectiveAction(Object owner, String key, 
    String name, Icon icon) 
  { 
    super(name, icon); 
    setKey(key); 
    setOwner(owner); 
  } 
  public void actionPerformed(ActionEvent ae) 
  { 
    try 
    { 
      if(executeMethod != null) 
        executeMethod.invoke(owner, new Object[0]); 
    } 
    catch(Exception e) 
    { 
      e.printStackTrace(); 
    } 
  } 
} 

Here is a sample application using the ReflectiveAction class. I think that the code is self-descriptive. Also, be warned that I hate comments in my code. As unacceptable as it may be, I use them very rarely.

Listing 2. Source code of TestApplication.java
/* 
 * TestApplication.java 
 * (c) Ghasem Kiani 
 * 18/08/2004 06:58:34 PM 
 * ghasemkiani@yahoo.com 
 */ 
 
package com.ghasemkiani.temp; 
 
import java.awt.*; 
import javax.swing.*; 
import com.ghasemkiani.temp.ReflectiveAction; 
 
public class TestApplication extends JFrame 
{ 
  JPanel jp; 
  public TestApplication() 
  { 
    super("Test Application"); 
    setDefaultCloseOperation(DISPOSE_ON_CLOSE); 
    JToolBar jtb = new JToolBar(); 
    getContentPane().add(jtb, BorderLayout.NORTH); 
    jp = new JPanel(); 
    getContentPane().add(jp); 
    jtb.add(new ReflectiveAction(this, "Green")); 
    jtb.add(new ReflectiveAction(this, "Blue")); 
    jtb.add(new ReflectiveAction(this, "Red")); 
    jtb.add(new ReflectiveAction(this, "Choose...")); 
    jtb.add(new ReflectiveAction(this, "Dummy")); 
    jtb.add(new ReflectiveAction(this, "Exit")); 
    setBounds(new Rectangle(100, 100, 400, 240)); 
    setVisible(true); 
  } 
  public void onGreenExecute() 
  { 
    JOptionPane.showMessageDialog(this, 
      "I don't actually become green!"); 
  } 
  public void onBlueExecute() 
  { 
    JOptionPane.showMessageDialog(this, 
      "I don't actually become blue!"); 
  } 
  public void onRedExecute() 
  { 
    jp.setBackground(Color.red); 
  } 
  public void onChooseExecute() 
  { 
    Color c = JColorChooser.showDialog(this, 
      "Choose a color", jp.getBackground()); 
    if(c != null) jp.setBackground(c); 
  } 
  public void onExitExecute() 
  { 
    dispose(); 
  } 
  public static void main(String[] args) 
  { 
    JFrame.setDefaultLookAndFeelDecorated(true); 
    JDialog.setDefaultLookAndFeelDecorated(true); 
    new TestApplication(); 
  } 
} 

Since I am willing to see the result of a code when I read an example code in an article, I present here a few screenshots of the TestApplication class running.

Figure 1 This is a picture of the application window.

This figure shows that the reflection has actually taken place, and the right method hase been called after clicking the Red and Green button.

Figure 2 This is what happens after clicking the Green button.

Another screenshot, just to make it a little saltier! (I don't know if you can take the Persian nuances of words.)

Figure 3 This is what has happened after clicking the Choose... button.

Some may understandably argue that this is againtst the spirit of the Java programming language, having a strong object-oriented orientation. But, it is an equally important argument that such an attitude is the rule in languages like Delphi and lisp (from a totally different point of view relative to Delphi -- here I mean lexical closures and metaprogramming, if I use the right terms).

The source and compiled classes of this example can be downloaded from here.