Licorice the cat
and the other beasts at the Bestiary. With this Java tutorial, you will literally be studying the language with the help of Java natives. They will react to your efforts, and will tell you when you've made a mistake.To visit and awaken the Bestiary world and its Java language school:
System.out.println("Let's get started");then the actual text in the console will be:
<script implName="lang:beanshell:inline:"><![CDATA[ System.out.println("Let's get started"); null;]]></script>
The plan is to have Licorice lead you through the following paw prints.
Ken Webb Sun, 01 Aug 2010 22:42:23 +0000
A good place to start with Java programming is learning how to display information. Try these examples by typing them into the Bestiary console panel. Or you can just copy and paste, or drag and drop, them into the console. Then press the Submit button on the same page. To see the results, you will need to have the Java console enabled.
System.out.println is the standard Java method for displaying information to a user. In the first set of examples below, Java prints a string of text, adds and prints two integers, and then adds and prints two floating point numbers.
System.out.println("Hello Licorice!");
System.out.println(123 + 321);
System.out.println(123.0 + 321.456);
contextNodeKey is a Java attribute that already exists within the Bestiary environment. It's the currently selected node in the app.
System.out.println(contextNodeKey);
Programming in any computer language, including Java, is error-prone. There is no attribute called error. Look in the Java Console for more details about the error after you Submit the following example. You will need to use the Pause button to freeze the app while you examine the error message.
System.out.println(error);
Ken Webb Mon, 02 Aug 2010 02:42:05 +0000
Computer programs are full of attributes (also called variables) that contain values. An attribute is just something with a name that stores text, a number, or some other value. The following example includes three attributes.
int x = 2000; int y = 10; int z = x + y; System.out.println("The answer is: " + z);
In the next example, the Bestiary internal attribute contextNodeKey is rather long, so it can be useful to create a separate internal attribute that's shorter. In Java, the type of information must be specified for each attribute. cnode is an IXholon type. The import statement at the top is required to tell the system where the IXholon class (type) is located.
import org.primordion.xholon.base.IXholon; IXholon cnode = contextNodeKey; System.out.println("The current context node is: " + cnode);
Ken Webb Mon, 02 Aug 2010 03:01:21 +0000
Each row in the original version of the Bestiary has 100 habitat cells. Change the current context node to a row, for example to row 1.
xpath /descendant::Row
The following script should confirm that the row has 100 child nodes.
import org.primordion.xholon.base.IXholon; IXholon contextNode = contextNodeKey; int sum = 0; public void count(IXholon node) { node = node.getFirstChild(); while (node != null) { sum++; node = node.getNextSibling(); } } count(contextNode); System.out.println("Node " + contextNode + " has " + sum + " child nodes.");
Ken Webb Mon, 02 Aug 2010 12:32:31 +0000
A for loop is a very common programming statement. In the following example, the variable i is iterated from a value of 1 to 10. System.out.print displays each of these values. This is how you get your computer to count from 1 to 10.
for (int i = 1; i < 11; i++) { System.out.print(i + " ");} System.out.println();
Especially in the summer, Licorice hates to come back into the house. Sometimes I can coax him by holding a tasty treat under his nose. To try this, first you'll have to catch him. Enter the following in the console, to make Licorice (cat 2) the current context node:
xpath /descendant-or-self::*[@name='cat_2']
If the current context node is a cat, human, or other beast, then the following script will boost him or her a specific distance in a specified direction. Set myDistance to some value between 1 and 100, and myDirection to one of the eight choices. Note the use of the for loop to advance the destination by the desired distance.
import org.primordion.xholon.base.AbstractGrid; import org.primordion.xholon.base.IGrid; import org.primordion.xholon.base.IXholon; IXholon myBeast = contextNodeKey; int myDistance = 5; // choices: P_NORTH P_NORTHEAST P_EAST P_SOUTHEAST P_SOUTH P_SOUTHWEST P_WEST P_NORTHWEST int myDirection = IGrid.P_NORTH; public void boost(IXholon beast, int distance, int direction) { AbstractGrid destination = (AbstractGrid)beast.getParentNode(); for (int i = 0; i < distance; i++) { destination = (AbstractGrid)destination.port[direction]; } beast.removeChild(); beast.appendChild(destination); } boost(myBeast, myDistance, myDirection);
Ken Webb Mon, 02 Aug 2010 12:33:12 +0000
Licorice and company live in a hierarchically structured world, much like the universe that you and I inhabit. There are things inside of things, that in turn are inside of other things, and so on. Java can easily navigate this type of structured world, by using recursion.
If you haven't made any changes to the Bestiary, and if the current context node is Bestiary/Grid, then the following script should report that there are 10591 nodes:
Node Type | Number of Instances |
---|---|
Grid | 1 |
Row (100 rows in the grid) | 100 |
HabitatCell (100 cells per row) | 10000 |
Cat | 100 |
Cat behaviors (3 behaviors per cat) | 300 |
Human | 30 |
Human behaviors (2 behaviors per human) | 60 |
import org.primordion.xholon.base.IXholon; IXholon contextNode = contextNodeKey; int sum = 0; public void count(IXholon node) { sum++; node = node.getFirstChild(); while (node != null) { count(node); node = node.getNextSibling(); } } count(contextNode); System.out.println("There are " + sum + " nodes in the subtree rooted by " + contextNode + ".");
Ken Webb Mon, 02 Aug 2010 12:34:02 +0000
A method is a named piece of code that does something specific. Ideally, it should only do one thing, and its name should strongly suggest what that thing is. A method may accept parameters, and it may return a value. In the following simple example, the method name is add, the input parameters are 17 and 25, and an int result is returned and printed. Try various values, both positive and negative integers.
public int add(int a, int b) { return a + b; } System.out.println(add(17, 25));
Licorice loves methods. He's got a method to avoid being found, methods to demand food, and any number of other methods designed to reinforce my role as servant. The following example has three methods, one of which will be randomly called each time the script is run.
public void feedMeNow() {System.out.println("MEOW (FEED ME NOW!)");} public void pleaseFeedMe() {System.out.println("miew (please feed me)");} public void imSoHungry() {System.out.println("meouch (I'm so hungry)");} double rnum = Math.random(); if (rnum < 0.25) {feedMeNow();} else if (rnum < 0.5) {imSoHungry();} else {pleaseFeedMe();}
Ken Webb Mon, 02 Aug 2010 12:34:40 +0000
Conditional logic is an essential part of any software. The if statement makes a decision based on current conditions, and follows the path dictated by the decision.
double rnum = Math.random(); if (rnum < 0.5) { System.out.println("Heads I win."); } else { System.out.println("Tails you lose."); }
In the section on while loops Licorice was boosted toward a destination. But if you specify an invalid value for myDistance or myDirection, the program could crash or could go into an infinite loop, which could lock up your applet or application. It's good practice to always verify human input. The if statement is typically used to do this. The following is an updated version of the boost method, with validation. Try it out.
import org.primordion.xholon.base.AbstractGrid; import org.primordion.xholon.base.IGrid; import org.primordion.xholon.base.IXholon; IXholon myBeast = contextNodeKey; int myDistance = 5; // choices: P_NORTH P_NORTHEAST P_EAST P_SOUTHEAST P_SOUTH P_SOUTHWEST P_WEST P_NORTHWEST int myDirection = IGrid.P_NORTH; public boolean isOk(IXholon beast, int distance, int direction) { boolean ok; if (beast == null) {ok = false;} else if ((distance <= 0) || (distance > 100)) {ok = false;} else if ((direction < 0) || (direction > 7)) {ok = false;} else {ok = true;} return ok; } public void boost(IXholon beast, int distance, int direction) { AbstractGrid destination = (AbstractGrid)beast.getParentNode(); for (int i = 0; i < distance; i++) { destination = (AbstractGrid)destination.port[direction]; } beast.removeChild(); beast.appendChild(destination); } if (isOk(myBeast, myDistance, myDirection)) { boost(myBeast, myDistance, myDirection); }
Ken Webb Mon, 02 Aug 2010 12:35:08 +0000
The switch statement is an efficient way to handle a decision that has more than 2 choices, but only if the conditions involve integer values.
int choice = 17; String desert; switch (choice) { case 1: desert = "ice cream"; break; case 17: desert = "chocolate cake"; break; case 1776: desert = "apple pie"; break; default: desert = "stale bread"; break; } System.out.println("We're having " + desert + " for desert!");
Licorice doesn't like any of these deserts, so we'll have to find something else for him to do.
// TODO
Ken Webb Thu, 09 Sep 2010 22:45:29 +0000
Swing is the name of the default graphics/GUI library included with Java. This is a simple example of a Swing GUI that can be pasted into the Bestiary or other Xholon app. You can try any number of variations of this code, until you arrive at the content and look that you want.
import javax.swing.JFrame; import javax.swing.JLabel; import javax.swing.JButton; JFrame frame = new JFrame("Hello Licorice"); JPanel panel = new JPanel(); JLabel label = new JLabel("Buenos Dias Regaliz"); JButton button = new JButton("Bonjour Réglisse"); panel.add(label); panel.add(button); frame.getContentPane().add(panel); frame.pack(); frame.setVisible(true);