HomeDigital EditionSys-Con RadioSearch Java Cd
Advanced Java AWT Book Reviews/Excerpts Client Server Corba Editorials Embedded Java Enterprise Java IDE's Industry Watch Integration Interviews Java Applet Java & Databases Java & Web Services Java Fundamentals Java Native Interface Java Servlets Java Beans J2ME Libraries .NET Object Orientation Observations/IMHO Product Reviews Scalability & Performance Security Server Side Source Code Straight Talking Swing Threads Using Java with others Wireless XML
 

What This Series Is About
This article is Part 2 of a series that discusses the many languages that compile and/or run on the Java platform. This is an interactive series. Java Developer's Journal invites you to vote for your favorite non-Java programming language in the JDJ Forum. Your vote will decide which languages will be covered by the series, and in what order. The last time I checked, JPython and NetRexx were neck and neck. NetRexx, though not mentioned previously, will be covered in the next article.

There are some great languages that I didn't mention last month, but as I stated, the list wasn't comprehensive - I named less than 10% of all the languages for the JVM. And received my fair share of "Why didn't you mention language X?'

Most of the languages covered by this series are scripting languages that are dynamic, interpreted and easy to program. For this article and the ones that follow, Java will be presented as the system language and the higher-level language will be presented as the "glue' language. Thus you define frameworks, libraries and components in Java and glue them together to make applications. This was described in detail in JDJ , Vol. 5, issue 2.

The series will focus on topics such as other languages for the JVM; integrating Java with mainstream scripting languages like Perl and Python; special-purpose languages (rules, etc.); creating JavaServer Pages (JSP) in JavaScript, Webl and Python; SWIG; open-source Java initiatives; COM/DCOM from pure Java; and CORBA to legacy integration.

JPython is the 100% Pure Java version of Python and is freely available - source code and all. An extremely dynamic, object-oriented language, JPython is in its second major release - JPython 1.1. Since JPython is the same syntax and language as Python, I'll use the terms interchangeably for the rest of this article.

You've heard Java called a dynamic, object-oriented language. Well, JPython is more dynamic and more object-oriented than Java. In Python, unlike Java, everything is an object - classes, methods, namespaces are objects. Also, Python doesn't have any primitive types, and it supports multiple inheritance. In many ways Python is closer to Smalltalk than to Java - syntactically, however, Python is closer to Java than to Smalltalk.

This isn't a case of my-language-can-beat-up-your-language syndrome. JPython doesn't replace Java; it augments it. Java and JPython have complementary roles - sometimes they overlap.

JPython facilitates the following:

  • Embedded scripting language: You can add JPython to your application to enable those pesky, demanding end users to extend your applications through scripts. Thus your end users can extend your application to add functionality that only a domain expert could dream of.
  • Interactive experimentation: JPython, like many scripting languages, provides an interactive interpreter. I use this to try out new APIs and for prototyping. Also, this is a great debugging tool - you can execute methods in any order, not in the normal sequence. Since the syntax is close to Java, it's easy to prototype.
  • Rapid application development: Python programs are shorter than the equivalent Java programs, as I'll show in the Rosetta stone examples.
Python is a lot easier to learn than Java. A novice programmer can learn enough Python in half a day (or sometimes in a few hours) to write effective scripts. In addition to being good for programming-in-the-small, you can use it for larger programs. Python has advance namespace management that makes programming-in-the-large feasible - many scripting languages don't. For example, Python has packages similar to Java's.

Python's ease of use is on a par with Visual Basic. Some say Python even surpasses Visual Basic because the syntax is more consistent and designed. However, unlike Visual Basic, Python is truly object-oriented. Others say that Python closely resembles a nonverbose version of Pascal or C++. The ease-of-use syntax is good, and the dynamic capabilities are extremely powerful. Put a Python in your toolbox.

Rosetta Stone
For comparison, each JPython sample application will have a corresponding Java implementation. This article covers the following sample applications.

  • A simple GUI application
  • A simple statistics application
  • Embedding the script into an application (if applicable)
  • A simple example parsing text
Before we go into the first example, let's cover the basics of JPython. If you've installed JPython, please follow along in the interactive interpreter.

A Simple Class
Python has classes. Listing 1 is a sample Python class; the Java equivalent appears in Listing 2. (The remainder of the Listings, through Listing 16, can be downloaded at www.javaDevelopersJournal.com.)

Notice that the use of self is similar to the use of this in a Java class - self is the reference to the instance. The first argument to each method is a reference to self. Also note that there's no separate declaration for member variables, that is, they're declared when they're assigned a value. (You can declare class variables as well as instance variables.) The _str_method is a special method that acts like the toString method in Java. Compare the Python Employee class to the roughly equivalent Java class in Listing 2.

To create an instance of an Employee and print it to the screen you'd do the following:

print Employee()

The equivalent Java statement would be:

System.out.println(new Employee());

Next we create two instances of Employee called joe and ron, and print those employees to the console. We print joe, who is ron's manager, by invoking the getManager method of ron - first in JPython, then in Java

Python
joe = Employee("Joe", "Batista", 100)
ron = Employee(manager=joe, id=101, lname="Furgeson", fname="Ron")
print ron
print ron.getManager()

Java
Employee joe = new Employee("Joe", "Batista", 100, null, 1);
Employee ron = new Employee("Ron", "Furgeson", 101, joe, 1);
System.out.println(ron);
System.out.println(ron.getManager());

As I said, the syntax is similar. One feature that JPython has is named arguments and default values. Notice that when the ron instance is created, the arguments are called out of order. If you've programmed in Visual Basic or VBScript, this concept should be familiar. If not, think of it this way: you can call methods as you normally do with Java, or you can pass name, value pairs to the method as shown above. This feature can save some coding effort, not to mention some headaches. Have you ever had several versions of the same method? And you just wanted to have different default values? Every default value is another overloaded method. It can get messy.

A good example of using named arguments is the GridBag utility class that the JPython distribution provides. This utility helps you manage the infamous GridBagLayout. I've created something similar in Java that used overloaded methods to create GridBag constraints. I was amazed how short the GridBag utility was in Python. (It's in the pawt package, if anyone wants to check it out.)

A Simple GUI
Now that we've created a simple class, we'll create a simple GUI. I admit that the class and the GUI are nonsensical - the idea is to demonstrate and compare the language to Java.

If you have JPython installed, let's pretend that we're prototyping this GUI. Fire up the interactive interpreter by typing jpython as the system prompt. (This assumes that you've downloaded, installed and put JPython home directory on your Path. Follow the install instruction at www.jpython.org.)

Import the JFrame from the javax.swing package.

>>> from javax.swing import JFrame

Create an instance of the frame, set its size to 200 by 200, then make it visible.

>>> frame = JFrame("My Prototype", visible=1, size=(200,200))

You probably weren't expecting this to be only one line of code. In JPython any bean property of a class can be set during the call to the constructor using named arguments. By bean property I mean a property as defined by a getter and a setter method, that is, the bean "design pattern" for properties.

At this point our frame is pretty boring. A stupid-looking gray box. Let's add some components to our stupid-looking gray box. We need to add some labels, text fields and an okay button. As we develop this GUI application I'll point out some of the features of JPython. As it's a nonsensical demo, we aren't going to meet any GUI style guidelines. First we need to import a few classes from javax.swing.

>>> from javax.swing import JButton, JTextField, JLabel, JPanel

Notice that we didn't use the * syntax. For example, we could have said "from javax.swing import * as you'd do in Java. But that would have imported every class into our namespace - in Python that would be considered bad style. In Python you can view and manipulate the namespace. For example, to see all of the variables in the current namespace, you can do the following:

>>> dir() ['JButton', 'JFrame', 'JLabel', 'JTextField', '__name__', 'frame']

Thus, if we imported *, we'd have a lot of classes in our namespace, and that would be less than ideal.

First create a pane. (Notice how the frame's contentPane property is handled; in Java you'd have to call frame.getContentPane() to get the contentPane. Bean properties are treated like instance variables.)

>>> pane = JPanel()
>>> frame.contentPane.add(pane)
javax.swing.JPanel[,0,0,0x0,invalid,layout=java.awt.FlowLayout,align-
mentX=null,alignmentY=null,border=,flags=34,maximumSize=,minimumSize=,preferredSize=,default
Layout=java.awt.FlowLayout[hgap=5,vgap=5,align=center]]

For this example we'll use the GridBag utility class that's provided with JPython. GridBag makes using GridBagLayout easy. The amazing thing about GridBag is how few lines of code it took to write it - again, check it out.

First we import the GridBag helper class, then create an instance of GridBag and associate it with the Pane. Please follow along in the interactive interpreter.

>>> from pawt import GridBag
>>> bag = GridBag(pane)

Now add the first component to the grid bag - a JLabel. This will use all of the default values of the GridBagConstraints (see Figure 1).

Figure 1
Figure 1:

>>> bag.add(JLabel("Name"))
>>> frame.validate()

Now add another JLabel. This time we add the label on the second row of the grid.

>>> bag.add(JLabel("ID"), gridy=1)
>>> frame.validate()

Now add a text field on the first row in the second column. Then pack the frame (see Figure 2).

Figure 2
Figure 2:

>>> name = JTextField(25)
>>> bag.add(name, gridx=1, weightx=80.0)
>>> frame.pack()

Now add a second text field for the employee ID, this time to the right on the second row. Then pack the frame (see Figure 3).

Figure 3
Figure 3:

>>> id = JTextField(10)
>>> bag.add(id, gridx=1, gridy=1, weightx=80.0)
>>> frame.pack()

As you can see, this isn't what we want. The text field components are centered and look quite silly. I forgot to align the text field to the left in their cells (not really - I forgot on purpose).

Let's remove the components and add them again with the proper alignment. Hopefully, you'll see how useful it is to be able to experiment with the layout in the interactive interpreter (see Figure 4).

Figure 4
Figure 4:

Remove the ID and name.

>>> pane.remove(id)
>>> pane.remove(name)

Now re-add the ID and name with the proper alignment.

>>> bag.add(name, gridx=1, weightx=80.00, anchor='WEST')
>>> bag.add(id, gridx=1, gridy=1, weightx=80.0, anchor='WEST')
>>> frame.pack()

The above demonstrates the interactive, experimental environment. You can explore cause and effect without the normal recompile, retest environment.

Bean events are handled easily in JPython. As with bean properties, JPython adds features to make event handling easier. First, JPython uses introspection and reflection to make event properties. Event properties equate to the names of the methods in the event listener interface for a given method using the event "design pattern" for JavaBeans.

You can assign an event property a function or method. To demonstrate this, let's set up an okay button. When the okay button gets clicked, this prototype application will print out the employee's name and ID.

First create and add a button to our GUI (see Figure 5).

Figure 5
Figure 5:

>>> okay = JButton("Okay")
>>> bag.add(okay, gridx=1, gridy=2, anchor='CENTER')
>>> frame.pack()

Next create a function. The function prints out the value of the name and ID text.

>>> def handleOkay(event):
... print "Name " + name.text
... print "ID " + id.text
...
>>> okay.actionPerformed=handleOkay

Enter some text in the Name and ID field and hit the okay button. This is a simple session, creating a simple GUI. For those of you who followed along with JPython, let me know what you think of JPython. I like it and use it often.

Rosetta Stone GUI
The foregoing was to show the interactive interpreter that comes with JPython. Now let's create a GUI based on the one we created above in both JPython and Java. In subsequent articles we'll write the same GUI in NetRexx, JavaScript, BeanShell, and others, enabling you to compare the JPython example with an example in NetRexx.

Listing 3 shows the employee form that we prototyped in the interactive interpreter. Listing 4 shows the employee form in Java. The Java version is 2,139 characters while the JPython version is 1,290 characters; thus the Java version is 66% larger.

Rosetta Stone Statistics
Just to highlight how well the language can do simple, common things, we'll create a simple application that calculates statistics for house prices in a neighborhood. Thus we'll create a program that, given a list of numbers, finds the averages (mean, mode, median) and range. We'll list each function's code and then break it down and describe the function line by line.

Implementing getRange
Since getRange is the easiest, we'll do it first. Essentially, we want a function that returns the minimum and maximum values in a list, and the range of values in the list (see Listing 5).

First Try Implementing getRange
Range iterates through a set of numbers passed to it and calculates the minimum and maximum values. When it's done, it returns the min, max and the range in a tuple.

Let's break getRange down bit by bit. First getRange declares two variables called min and max. The min is to hold the minimum value. The max is to hold the maximum value.

min = 300000000
max = -300000000

The min variable refers to a very large number so that the first item extracted from the list will be less than the large number and get assigned to the min value. The max value contains a very negative number so that the first item that gets extracted will be more than the large negative value and get assigned to min variable.

Technical Note:
The foregoing example will work only if the numbers passed to it are in the range of min and max.

A better way to implement this code would have been to use the following:

from java.lang import Double

or:

from java.lang import Integer

and then:

min = Double.MAX_VALUE
max = Double.MIN_VALUE

or:

min = Integer.MAX_VALUE
max = Integer.MIN_VALUE

This would make the function work well with IntTypes or Double- Types, but what about LongTypes? Well, there's a more Python way of doing things, which will be explained shortly.

Next, to figure the minimum and maximum number, the getRange function iterates through the nums sequence.

for item in nums:

if (item > max): max = item
if (item < min): min = item

Notice the JPython for loop iterates through a sequence. A sequence is like a cross between a Java Array and a Java Vector - well, not exactly.

The expression item > max determines if the item's value is greater then the value of max. If it is, it's assigned to the value of the item. This, so far, is a lot like Java.

When the loop stops iterating the values, the getRange function returns the min, max and range (max - min) as:

return (min, max, max-min)

This may be odd. Essentially, it appears that we're returning three values. Actually, we're returning a tuple of values. A tuple is an immutable sequence.

Well, that was easy enough. If you read the technical note, you know this approach has some flaws.

We're getting a variable called nums. The nums variable is a sequence. In Python, sequences have intrinsic operations (built-in functions) for finding the min and max values in a list. Therefore, we should have used the built-in function.

The Python Way of getRange
This is an improvement of getRange, because it's a lot shorter and it can work with all numeric types, longs, floats and doubles at their maximum range of precision (see Listing 6).

There's no more for loop, no more figuring out what the minimum or maximum variable should be initialized to. The built-in intrinsic functions in Python are very useful. Now this will work with longs, integers and floats. (Read the technical note under the first implementation for a description of the getRange problem).

Implementing getMean
The getMean function figures out the mean of a sequence of numbers. It iterates through the list, adds all the values together and stores them in sum. It then figures the mean by dividing the sum divided by the length of the sequence of numbers. The getMean sample uses an argument called sample to determine if this is a sample mean or a population mean (see Listing 7).

This example shows example use of:

  • For loop
  • If and else statements
  • The built-in function called len
Let's break down the getMean function step by step.
First create a variable called sum that holds the sum.

sum = 0.0

Then iterate through the nums sequence accumulating the value of the item x.

for x in nums:
sum = sum + x

Next we check to see if this is a sample mean. If it is, we figure the average by dividing the sum by the number of items in nums less one, else we divide the sum by the number of items in the nums sequence.

if(sample):
average = sum / (len(nums)-1)

# Else it is a population mean
else:
average = sum / len(nums)

Last, we return the average.

return average

The foregoing is not much different from what you'd do in Java. You could say that it's very similar.

The Python Way of getMean
There's another way to calculate the average. It's quite different from what you may be used to.

Examine the following code.

def getMean (nums, sample):
sum = reduce(lambda a, b: a+b, nums)

if sample: average = sum / (len(nums)-1)
else: average = sum / len(nums)

return average

This approach uses a built-in function called reduce, which takes two arguments - a function object and a sequence object. The former is specified with the lambda keyword, which defines an anonymous function, that is, a function without a name.

Thus:

lambda a, b: a+b

is equivalent to

def add(a,b):
return a + b

The reduce function applies the function argument to two items in the sequence argument cumulatively from left to right, which reduces the sequence to a single value that in our case is a sum.

Thus the foregoing method is equivalent to the former getMean method, but a lot shorter. There are other built-in functions like reduce that provide functional programming features to Python.

Implementing getMode
The getMode function finds the value that repeats the most. (Note: This isn't a complete implementation of mode - it would work only with discrete values.) The first thing this function does is duplicate the sequence, because it's going to modify it. Then we iterate through the items in the nums sequence, and count the numbers occurrences of the current items (we use the built-in sequence method count). Once we count an item, we remove it from the duplicated sequence (see Listing 8).

This example shows example use of:

  • For loop
  • While loop
  • If statement
  • Built-in intrinsic operation count
  • Also uses a nested for loop
Because of space considerations, we won't cover getMode step by step.

Implementing getMedian
The getMedian function finds the middle-most value once the sequence is sorted (see Listing 9).

This example shows example use of:

  • The modulus operator (%)
  • If and else statements
  • Built-in intrinsic operation sort
Also because of space considerations we won't cover the getMedian function step by step. Let's highlight some of the getMedian functionality. First we duplicate the nums sequence. Then we sort the duplicate (the duplicate is named seq):

seq.sort()

Next we get the length of the sequence and check to see if it's an even number with the expression length % 2. (Remember that the modulus operator - % - returns the remainder, so if length is even, the expression length % 2 will return a 0.) If the length is even, we calculate the median by adding the two most central numbers and figuring their average.

length = len(seq)

if ( ( length % 2) == 0):
index = length / 2
median = (seq[index-1] + seq[index]) /2.0

If the length is odd, we grab the middle value:

else:

index = (length / 2)
median = seq[index]

Last, we return the median.

return median

Implementing reportStatistics
Last, we want to print out the statistics we collected. The reportStatistics calls all of the functions; we implement and store their return values in two dictionaries called averages and ranges. It then puts the two dictionaries in another dictionary called report. It returns report (see Listing 10).

This example shows example use of:

  • getMean, getMode, getRange, getMedian
  • Nested dictionaries

Let's cover the reportStatistics function step by step.
Get the averages - namely, the mean, median and mode. Use the getMean, getMedian and getMode functions that we defined. Note that "mean":getMedian defines a key value pair.

averages = {
"mean":getMean(nums,0),
"median":getMedian(nums),
"mode":getMode(nums)
}

Get the range parameters - namely, the min, max and range - from the getRange function. Use the range[0], range[1] and range[2] items in the sequence returned from the function getRange. Note that "min":range[0] defines a key value pair in the ranges dictionary. Unlike Java, Python has built-in support for collections. Thus you can specify a dictionary, which is like a java.util.Hashtable, with a literal.

# get range
range = getRange(nums)

# put ranges in a dictionary
ranges = {
"min":range[0],
"max":range[1],
"range":range[2]
}

Now define a dictionary called report that contains the averages and ranges dictionary:

report = {
"averages": averages,
"ranges": ranges
}

Last, let's return the report dictionary

return report

Using reportStatistics
The runReport module uses the reportStatistics to get the report dictionary that it uses to print out the report (see Listing 11).

This example shows example use of:

  • The string format operator (%)
  • the %f format directive
  • Using nested dictionaries
  • Using a dictionary with the format operator
The string formatter (%) operator is like the printf function in C except that the % operator can work with dictionaries of data (see Listing 12). I've used the string formatter to generate Java code. It's one of my favorite Python features and really makes text reporting easy.

As you can see, there are a lot of built-in functions and built-in collection types that make easy tasks easier and hard tasks possible. Now compare this to the Java version of this application in Listing 13. Notice how much shorter the Python version is.

Rosetta Stone String Parsing
This example will continue where the other one left off. We'll add reading the house prices from a file. The file will consist of a comma-delimited list of house prices.

For example, the file will contain:

100000,100000,120000,150000,170000,170000,80000,50000

The Python code to read this file in would be as follows:
Open the file.

>>> file = open("data.txt")

Read in the file data.

>>> data = file.read()

Import the split function to parse the data.

>>> from string import split
>>> housePrices = split(data, ",")

For demonstration purposes show that the split function split the data string into a list of strings.

>>> housePrices
['100000', '100000', '120000', '150000', '170000', '170000', '80000', '50000\n'

Convert the housePrices list from a list of strings to a list of floating point values.

>>> housePrices = map(float, housePrices)

Show that the list is now a list of floating point values.

>>> housePrices
[100000.0, 100000.0, 120000.0, 150000.0, 170000.0, 170000.0, 80000.0, 50000.0]

Listing 14 is the listing for the foregoing prototype.

Compare the JPython listing for runReport2 (Listing 14) and the Java listing (Listing 15) for runReport2. As before, the JPython version is much shorter.

Rosetta Stone Embedding JPython in Java
A good example of embedding JPython in Java ships with the standard JPython distribution (see Listing 16). I've added comments to the example.

As you can see, it's relatively easy to embed JPython into a Java program. The example doesn't do the subject justice. In my book, Programming the Java APIs with JPython, there's an example that dynamically loads JPython servlets from a Java servlet using the embedding technique shown.

Vote for Your Favorite
A lot of 100% pure programming languages work in the JVM, and JDJ wants your opinion of which are the best, and why. An example list follows: JPython, NetRexx, Rhino, Instant Basic, Jacl, BeanShell, Pnuts, Bistro, Kawa (Lisp/Scheme like).

Scorecard
How does JPython score? The table below shows my opinion - 90%. Drop by the JDJ Forum and put in your own two cents' worth!

Let's drill down a bit on the criteria I rated.

  • Ease of use: Python, written by Guido Van Rossum, was based on ABC, which was developed to make programming easy for beginners. Python is easy to use and easy to learn. In Virginia they're using Python as a first programming language to teach high school students how to program. Score 10 of 10
  • Embeddability: Python is easy to embed. Score 10 of 10
  • Resemblance to parent language: JPython strives to be syntactically identical to Python. Score 10 of 10
  • Unique features: Python has some of the best features of Smalltalk, Scheme, Icon and Java. Score 10 of 10
  • String parsing: In addition to the string parsing that we've shown in this article, Python has libraries for regular expression string parsing, slice-notation syntax and other great features that make string parsing easy. Score 10 of 10
  • Productivity: Python has an extensive class library that makes doing common tasks easy. In addition, Python has built-in language support for collection objects including collection literals that let you define a collection. These language constructs and class libraries make programming strikingly productive. Score 10 of 10
  • Working well with Java classes and APIs: In JPython you can instantiate Java classes, invoke Java methods, subclass Java classes and interfaces, and easily set up bean events. In addition, JPython has support to work with JavaBean properties and you can compile JPython into Java classes. Thus you can create JavaBeans, servlets and applets in JPython. Score 10 of 10
  • Development environment/debugging: It's good to have an interactive interpreter, and JPython has a good one. However, if you're used to having GUI builders, debugging in an IDE, setting watches, and so forth, forget about it. The development environment for JPython is its Achilles' heel. Unlike Python, which has some mature IDEs, JPython has nothing. If JPython had an IDE like JBuilder or Visual Basic, Java would have a serious competitor for the most popular language for the JVM. Hey, Java IDE makers - Borland, Symantec, NetBeans (or should I say Corel, BEA, Sun) - get busy. (Rumor mill: There's one major IDE maker already considering supporting JPython.) Score 2 of 10

Parting Shots
Python, a high-level, dynamic, object-oriented language, is the easiest language to learn - easier than Visual Basic. JPython, which is very close to Python, has been certified 100% Pure Java.

JPython has a lot of momentum, and its syntax is mean and lean. It's to JavaBeans what Visual Basic is to ActiveX, and interest in it is growing. A recent poll at the NetBean's Web site showed JPython as the leading Java scripting language. In our poll at JDJ, JPython is neck and neck with NetRexx.

Components have a symbiotic relationship with high-level languages. For example, Visual Basic did well because of ActiveX components. And ActiveX did well because of tools like Visual Basic. On the Java platform we have the component models; we need the glue, that is, tools for the high-level languages - debuggers, IDEs, and the like. JPython makes good glue, and it transcends the role of a glue language.

For more information on JPython see Guido Van Rossum's article at www.developer.com/journal/techfocus/081798_jpython.html. See also www.jpython.org/ and www.python.org/.

Many of the examples in this article were based on examples in my book, which is scheduled for publication in April from Addison Wesley Longman.

Author Bio
Rick Hightower currently works at Buzzeo Corporation (www.buzzeo.com), the maker of ZEOLogix, an EJB application server, rules engine and workflow. He is a principal software engineer working on an EJB container implementation and distributed event management. In addition, he is author of a book, Programming the Java APIs with JPython, to be published by Addison Wesley.
Rick may be contacted at: [email protected]

	

Listing 1: Python Employee Class

class Employee:
        def __init__(self, fname="John", lname="Doe", id=1, manager=None, dept=1):
                self.__firstName        =       fname
                self.__lastName =       lname
                self.__id               =       id
                self.__manager          =       manager
                self.__dept             =       dept

        def getManager(self):
                return self.__manager

        def __str__(self):
                values = self.__lastName, 
self.__firstName, self.__id
                return join(values,',')



Listing 2: Java Employee Class

public class Employee{
        private String firstName, lastName;
        private int id, dept;
        private Employee manager;
        

        public Employee(){
                firstName = "John";
                lastName = "Doe";
                id = 1;
                manager=null;
                dept=1;
        }

        public Employee(String fname, String lname, int id, Employee manager, int dept){
                firstName       =       fname;
                lastName        =       lname;
                this.id         =       id;
                this.manager    =       manager;
                this.dept       =       dept;
        }

        public Employee getManager(){
                return manager;
        }

        public String toString(){
                StringBuffer buf = new StringBuffer();
                buf.append(lastName+',');
                buf.append(firstName+',');
                buf.append(""+id);
                return buf.toString();
        }
        ...
        ...
}


Listing 3: Jpython Employee Form

from javax.swing import JFrame, JButton, JTextField, JLabel, JPanel
from string import split
from pawt import GridBag
from Employee import Employee


class EmployeeForm(JFrame):
        def __init__(self):
                JFrame.__init__(self, "Employee Form")
                pane = JPanel()
                self.contentPane.add(pane)
                bag = GridBag(pane)
                
                        
                        #Create a name, and id text field.
                self.__name = JTextField(25)
                self.__id = JTextField(10)
                
                        #Create and add a "Name" and "ID" label.
                name = JLabel("Name", labelFor=self.__name, displayedMnemonic=ord('N'))
                bag.add(name)
                id = JLabel("ID", labelFor=self.__id, displayedMnemonic=ord('I'))
                bag.add(id, gridy=1)
                
                        # Add the name and ID text field to the form.
                bag.add(self.__name, gridx=1, weightx=80.00, anchor='WEST')
                bag.add(self.__id, gridx=1, gridy=1, anchor='WEST')
                

                        #Create an okay button, add it, and set up its event handler.
                okay = JButton("Okay", mnemonic=ord('O'))
                bag.add(okay, gridx=1, gridy=2, anchor='EAST')
                okay.actionPerformed=self.handleOkay

                self.visible=1
                self.pack()

        def handleOkay(self, event):
                fname, lname = split(self.__name.text, " ")
                id = int(self.__id.text)
                employee = Employee(fname, lname, id)
                print employee

                
if __name__=="__main__":EmployeeForm()


Listing 4 :Java EmployeeForm

import javax.swing.*;
import java.awt.GridBagLayout;
import java.awt.GridBagConstraints;
import java.awt.event.ActionListener;
import java.awt.event.ActionEvent;
import employee.Employee;


public class EmployeeForm extends JFrame{
        private JTextField name;
        private JTextField id;

        public EmployeeForm(){
                super("Employee Form");
                JPanel pane = new JPanel();
                getContentPane().add(pane);

                pane.setLayout(new GridBagLayout());


                        // Create a name, and id text field.
                name = new JTextField(25);
                id = new JTextField(10);

                        // Create and add a "Name" and "ID" label.
                JLabel nameLabel = new JLabel("Name");
                nameLabel.setLabelFor(name);
                nameLabel.setDisplayedMnemonic('N');
                GridBagConstraints constraint = new GridBagConstraints();
                pane.add(nameLabel, constraint);

                JLabel idLabel = new JLabel("ID");
                idLabel.setLabelFor(id);
                idLabel.setDisplayedMnemonic('I');
                constraint.gridy=1;
                pane.add(idLabel, constraint);

                        // Add the name and ID text field to the form.
                constraint.gridy=0; constraint.gridx=1;
                constraint.weightx=80.00;
                constraint.anchor=GridBagConstraints.WEST;
                pane.add(name, constraint);
                constraint.gridy=1;
                pane.add(id, constraint);








                        // Create an okay button, add it, and set up its event handler.
                JButton okay = new JButton("Okay");
                okay.setMnemonic('O');
                constraint.gridx=1; constraint.gridy=2;
                constraint.anchor=GridBagConstraints.EAST;
                pane.add(okay, constraint);
                okay.addActionListener(new ActionListener(){
                        public void actionPerformed(ActionEvent event){
                                handleOkay();
                        }
                });

                this.setVisible(true);
                this.pack();
        }

        public void handleOkay(){

                String name, fname, lname;
                int index=0;
                int id =0;

                name = this.name.getText();
                index = name.indexOf(" ");
                fname = name.substring(0, index);
                lname = name.substring(index+1, name.length());

                id = Integer.parseInt(this.id.getText());

                Employee employee = new Employee(fname, lname, id, null, 100);
                System.out.println(""+employee);
        }

        public static void main(String [] args){
                new EmployeeForm();
        }
}


Listing 5: getRange

def getRange (nums):

        min = 300000000
        max = -300000000
        
        for item in nums:
                if (item > max): max = item
                if (item < min): min = item

        return (min, max, max-min)


Listing 6: getRange

def getRange (nums):
        return (min(nums), max(nums), max(nums)-min(nums))


Listing 7: getMean

def getMean (nums, sample):
        sum = 0.0      # holds the value of sum
                
                # iterate through the sequence of numbers and sum them
        for x in nums:
                sum = sum + x
                
                # Check to see if this is a sample mean 
        if(sample):
                average = sum / (len(nums)-1)
                
                # Else it is a population mean
        else:
                average = sum / len(nums)
        return average


Listing 8: getMode

def getMode (nums):
                #
                # make a duplicate copy of the nums argument
        duplicate = nums[:]
        highest_count = -100
        mode = None
                #
                # calculate the highest_count and the mode
        for item in nums:

                count = duplicate.count(item)
                if (count == 0): continue

                if (count > highest_count):
                        highest_count = count
                        mode = item

                while(duplicate.count(item) > 0):
                        duplicate.remove(item)

        return mode


Listing 9: getMedian

def getMedian (nums):
        "Find the Median number"

                #create a duplicate since we are going to modify t
        seq = nums[:]

                #sort the list of numbers
        seq.sort()

        median = None # to hold the median value

        length = len(seq) # to hold the length of the seq

                # Check to see if the length is an even number
        if ( ( length % 2) == 0):
                        # since it is an even number 
                        # add the two middle number together
                index = length / 2
                median = (seq[index-1] + seq[index]) /2.0
        else:
                        # since it is an odd number
                        # just grab the middle number
                index = (length / 2) 
                median = seq[index]
        return median


Listing 10 getMedian

def reportStatistics (nums):
                # get central tendencies
        averages = {
                "mean":getMean(nums,0),
                "median":getMedian(nums),
                "mode":getMode(nums)
                }

                # get range
        range = getRange(nums)

                # put ranges in a dictionary
        ranges = {
                "min":range[0],
                "max":range[1],
                "range":range[2]
                }

        report = {
                "averages": averages,
                "ranges": ranges
                }
                
        return report


Listing 11: runReport.py

from stat import reportStatistics
house_in_awahtukee = [100000, 120000, 150000, 200000, 65000, 100000]
report = reportStatistics(house_in_awahtukee)

range_format = """
Range:
The least expensive house is %(min)20.2f
The most expensive house is  %(max)20.2f
The range of house price is  %(range)20.2f
"""
average_format = """
Averages:
The mean house price is        %(mean)20.2f
The mode for house price is    %(mode)20.2f
The median house price is      %(median)20.2f
"""

print range_format   % report["ranges"]
print average_format % report["averages"]


Listing 12: runReport.py Output 

Range:
The least expensive house is             65000.00
The most expensive house is             200000.00
The range of house price is             135000.00


Averages:
The mean house price is                   122500.00
The mode for house price is               100000.00
The median house price is                 110000.00


Listing 13: Complete Java Version

---- Stats.java ---
package stat;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.Collections;
import java.util.HashMap;

public class Stats {

        public static double getMean (ArrayList nums, boolean sample){
                // Define mean that finds two types of mean, namely:
                // population mean and sample mean
                double sum=0.0;
                double average=0.0;
                Iterator iterator = nums.iterator();

                while(iterator.hasNext())
                        sum = sum + ((Double)iterator.next()).doubleValue();


                        // Check to see if this is a sample mean
                if(sample)
                        average = sum / nums.size()-1;
                else
                        average = sum / nums.size();

                return average;
        }

        public static ArrayList getRange (ArrayList nums){
                        // Find the range. Returns a tuple with the minimum,
                        // maximum, and range value
                double min, max;
                ArrayList ranges;

                min = ((Double)Collections.min(nums)).doubleValue();
                max = ((Double)Collections.max(nums)).doubleValue();


                ranges = new ArrayList();
                ranges.add(new Double (min));
                ranges.add(new Double (max));
                ranges.add(new Double (max-min));

                return ranges;
        }

        public static double getMedian (ArrayList nums){
                // Find the Median number

                        // create a duplicate since we are going to modify the sequence
                ArrayList seq = new ArrayList(nums);


                        // sort the list of numbers
                Collections.sort(seq);

                double median = 0.0; // to hold the median value

                int length = seq.size(); // to hold the length of the sequence
                int index=0;

                        // Check to see if the length is an even number
                if ( ( length % 2) == 0){
                                // since it is an even number
                                // add the two middle number together
                        index = length / 2;
                        double m1 = ((Double)seq.get(index-1)).doubleValue();
                        double m2 = ((Double)seq.get(index)).doubleValue();
                        median = (m1 + m2) /2.0;
                }
                else{
                                // since it is an odd number
                                // just grab the middle number
                        index = (length / 2);
                        median = ((Double)seq.get(index)).doubleValue();
                }
                return median;

        }

        private static int countMode(Object object, ArrayList list){
                int index = 0;
                int count = 0;
                do {
                        index = Collections.binarySearch(list, object);
                        if(index >=0)list.remove(index);
                        count++;
                }
                while (index >=0);
                return count;
        }

        public static double getMode (ArrayList nums){
                // Find the number that repeats the most.

                        // make a duplicate copy of the nums argument
                ArrayList duplicate = new ArrayList(nums);

                Collections.sort(duplicate);
                double highest_count = -100;
                double mode = -100;


  Iterator iterator = nums.iterator();
  // iterate through nums removing each item out of the duplicate
  // calculate the highest_count and the mode
  while(iterator.hasNext()){
  double count = 0;
  Object  item = iterator.next();

  // Count the number of times the item occurs in the list
  // If Count is 0 go to the next iteration
  count = countMode(item, duplicate);
    if (count == 0) continue;

 // determine the highest count. The highest counted item is the mode.
   if (count > highest_count)
   {
   highest_count = count;
   mode = ((Double)item).doubleValue();
                        }
                }


                return mode;
        }

        public static HashMap reportStatistics (ArrayList nums){

                        // get central tendencies
                HashMap averages = new HashMap();

                averages.put("mean",new Double(getMean(nums,false)));
                averages.put("median",new Double(getMedian(nums)));
                averages.put("mode",new Double(getMode(nums)));

                        // get range
                ArrayList range = getRange(nums);
                HashMap ranges = new HashMap();

                        // put ranges in a dictionary
                ranges.put("min",  range.get(0));
                ranges.put("max",  range.get(1));
                ranges.put("range",range.get(2));


                HashMap report = new HashMap();
                report = new HashMap();
                report.put("averages", averages);
                report.put("ranges", ranges);

                return report;

        }
}

--- RunReport.java ---
package stat;

import java.util.ArrayList;
import java.text.MessageFormat;
import java.util.HashMap;

public class RunReport{
        public static String range_format = "" +
        "Range: \n"+
        "The least expensive house is  {0,number,currency}\n" +
        "The most expensive house is   {1,number,currency} \n" +
        "The range of house price is   {2,number,currency} \n";

        public static String average_format = "" +
        "Averages: \n" +
        "The mean house price is        {0,number,currency}\n" +
        "The mode for house price is    {1,number,currency}\n" +
        "The median house price is      {2,number,currency}\n";

        public static void main(String [] args){

                ArrayList houses_in_awahtukee = new ArrayList();
                houses_in_awahtukee.add(new Double(110000));
                houses_in_awahtukee.add(new Double(190000));
                houses_in_awahtukee.add(new Double(140000));
                houses_in_awahtukee.add(new Double(120000));
                houses_in_awahtukee.add(new Double(190000));
                houses_in_awahtukee.add(new Double(180000));
                houses_in_awahtukee.add(new Double(170000));
                houses_in_awahtukee.add(new Double(180000));
                houses_in_awahtukee.add(new Double(180000));
                houses_in_awahtukee.add(new Double(190000));
                houses_in_awahtukee.add(new Double(190000));
                houses_in_awahtukee.add(new Double(250000));

                HashMap report = Stats.reportStatistics(houses_in_awahtukee);
                HashMap ranges = (HashMap)report.get("ranges");
                HashMap averages = (HashMap)report.get("averages");

                Object [] m_args = new Object[]{        averages.get("mean"),
                                                averages.get("mode"),
                                                averages.get("median")};

                Object [] r_args = new Object []{        ranges.get("min"),
                                                 ranges.get("max"),
                                                 ranges.get("range")};

                System.out.println(MessageFormat.format(range_format,r_args));
                System.out.println(MessageFormat.format(average_format,m_args));
        }
}


Listing 14 for runReport2

from stat import reportStatistics
from string import split

file = open("data.txt")
data = file.read()

housePrices = split(data, ",")
housePrices = map(float, housePrices)
report = reportStatistics(housePrices)


range_format = """
Range:
The least expensive house is %(min)20.2f
The most expensive house is  %(max)20.2f
The range of house price is  %(range)20.2f
"""

average_format = """
Averages:
The mean house price is        %(mean)20.2f
The mode for house price is    %(mode)20.2f
The median house price is      %(median)20.2f
"""print range_format   % report["ranges"]

print average_format % report["averages"]


Listing 15: RunReport2

package stat;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.StringTokenizer;

import java.text.MessageFormat;

import java.io.FileReader;
import java.io.BufferedReader;



public class RunReport2{
        public static String range_format = "" +
        "Range: \n"+
        "The least expensive house is  {0,number,currency}\n" +
        "The most expensive house is   {1,number,currency} \n" +
        "The range of house price is   {2,number,currency} \n";

        public static String average_format = "" +
        "Averages: \n" +
        "The mean house price is        {0,number,currency}\n" +
        "The mode for house price is    {1,number,currency}\n" +
        "The median house price is      {2,number,currency}\n";

        public static void main(String [] args){

                ArrayList houses_in_awahtukee = new ArrayList();

                try {
 BufferedReader reader = new BufferedReader(new FileReader("data.txt"));
 String data = reader.readLine();
 StringTokenizer tokens = new StringTokenizer(data, ",\t\n\r ");
 while (tokens.hasMoreTokens()){
 houses_in_awahtukee.add(Double.valueOf(tokens.nextToken()));

                        }

                }
                catch(Exception e){
                        e.printStackTrace();
                }


                HashMap report = Stats.reportStatistics(houses_in_awahtukee);
                HashMap ranges = (HashMap)report.get("ranges");
                HashMap averages = (HashMap)report.get("averages");

                Object [] m_args = new Object[]{        averages.get("mean"),
                                                averages.get("mode"),
                                                averages.get("median")};

                Object [] r_args = new Object []{        ranges.get("min"),
                                                 ranges.get("max"),
                                                 ranges.get("range")};

                System.out.println(MessageFormat.format(range_format,r_args));
                System.out.println(MessageFormat.format(average_format,m_args));
        }
}


Listing 16: Embedding JPython in Java

import org.python.util.PythonInterpreter;
import org.python.core.*;

public class SimpleEmbedded {
    public static void main(String []args) throws PyException {

                // Create a Python interpreter.
        PythonInterpreter interp = new PythonInterpreter();

        System.out.println("Hello, brave new world");

                // Execute an import statement and a print statement.
        interp.exec("import sys");
        interp.exec("print sys");

                // Create a variable by assuaging it the value 42. 
// PyInterger is a Python integer.
        interp.set("a", new PyInteger(42));

                // Execute the print statement to print out the value of a.
        interp.exec("print a");

                // Assign x to equal the expression 2 + 2.
        interp.exec("x = 2+2");

                // Get the value associated with x.
        PyObject x = interp.get("x");

                // Print the value of x.
        System.out.println("x: "+x);
   }
}





 

All Rights Reserved
Copyright ©  2004 SYS-CON Media, Inc.
  E-mail: [email protected]

Java and Java-based marks are trademarks or registered trademarks of Sun Microsystems, Inc. in the United States and other countries. SYS-CON Publications, Inc. is independent of Sun Microsystems, Inc.