Contructors and Inheritance in Javascript

 

There is a really great article on inheritance in Javascript tucked away in the Rochester Institute of Technology website :

http://www.cs.rit.edu/~atk/JavaScript/manuals/jsobj/

Dated from 1997 and very hard to find using Google, this article offered me the perfect solution to the problem I had in front of me, namely, having objects with constructors that also use inheritance.

Incorporating constructors in Javascript is usually done using the ‘static’ notation, where one method contains other methods :

function MyObject(myInitialData) {

  this.initalData = myInitialData;

  this.aMethod= new function() {
    getSoftware : null
  };

  this.anotherMethod = new function() {
    return this.initalData;
  }
}

Everything between the line :

function myObject(myInitialData) {

and the first method would be considered a constructor, and you can add as many parameters as you want to the outer method (in my case it is just one: myInitialData).

The only problem with this technique is that you can’t define the object as being of some other kind of object. In other words you can’t have MyObject be anything else.

Using the dynamic Javascript notation you can create an object to be of something else :


var b = Object.create(a);
b.x = function() {}
b.y = function() {}
b.z = function() {}

ie. b is an a;

you can also add a constructor-like method, called init().

Example :

var b = Object.create(Building);
b.init = function(name) {
  this.name = name;
  this.createFoundations();
};
b.createFoundations = function(){
  builder.buildFoundations();
}
b.printName= function(
  alert(this.name)
);

If you have something like this, you have inheritance (It inherits Building), and your init() becomes your constructor. But it is not a real constructor because you have to remember to call it after the create. Constructors are a way of forcing the programmer to execute some initial code.

From the above website, the solution would be to set the prototype after defining the method using the first technique :


function MyObject(myInitialData) {
  this.initalData = myInitialData;

  this.aMethod = new function(){
    getSoftware : null
  };

  this.anotherMethod = new function(){
    return this.initalData;
  }
}

MyObject.prototype = new Building;


Using this technique, we have inheritance, ie MyObject is a Building, and we have a constructor too.

This is how we do it now!

Posted in JavaScript | Tagged , | Leave a comment

Abstract Methods and Polymorphism in Javascript.

JavaScript doesn’t allow abstract methods. If you are developing JavaScript in an object-oriented style, you need to be aware of what methods your object should or should not have.

Inheritance allows for polymorphism, and achieving polymorphism is further enhanced by using abstract methods.

In Java :

    Class Abstract Bird {
        public void abstract makeSound();
    }

    Class Duck extends Bird() {
        public void makeSound() {
            print(‘Quack’)
        }
    }

Without declaring the makeSound() method as abstract, and implementing it instead at the super level, you will get some default sound instead from your feathered creation. The usefulness of abstract methods is that it forces the developer to implement some kind of behavior on a particular class they are implementing. Just simply implementing that method at the super level might not make sense. What sounds does a bird make? How long is a piece of string?

Removing the makeSound() method from the super class won’t allow you to use the method makeSound() polymorphically (in most standard OO languages). However in a dynamic language like JavaScript this is considered no problem. You can try calling any kind of method. But during runtime, if you call a method and it ain’t there, well you get :

Uncaught TypeError: Object #[HTMLTableElement] has no method 'makeSound'

Thats what duck-typing gives you. To make JavaScript more robust and to ‘fake’ abstract methods in the language I’ve had to turn to a pretty crude method : popping up alerts in empty methods defined in the super object.

A real world example :

Page = new Object();
Page.createView = function() {

    var div = document.createElement('div');
    div.className = 'Page';

    var h1 = document.createElement('h1');
    h1.id = 'panelTitle';
    h1.appendChild(document.createTextNode(this.getTitle())
    div.appendChild(h1);

    div.appendChild(this.createContentView());

    return div;
};

//abstract
Page.createContentView = function() {
    alert('createContentView in Page ‘ + name + ‘ not implemented');
};
//abstract
Page.getTitle = function() {
    alert('getTitle in Page ‘ + name + ‘ not implemented’);
};

In the Page object I have created a two methods which I want all derived objects to include. The Page object supplies HTML elements that frames a page object, eg header elements at the top, and maybe you could have footer elements defined as well.

Implementation :

TimeSheetPage = Object.create(Page);
TimeSheetPage.name = 'TimeSheet';

TimeSheetPage.createContentView = function() {
    var div = document.createElement('div');
    div.id = 'PageContent';

    //create some javascript generated HTML here

    return div;
};

DevicesPage.getTitle = function() {
return 'TimeSheet'
};

The implemented TimeSheetPage object needs to implement these methods or an alert message will pop up. This is nowhere near as good as a compile time error, but its unfortunately that best JavaScript can do.

I hope this helps. It has eased some of the pain of JavaScript developement for me. Its a shame Mozilla hasn’t built in a more elegant OO system for Javascript.

Posted in JavaScript | Tagged , , , | Leave a comment

MVC pattern in Javascript. An example..

If you are unfortunate enough to be a Java developer who has to develop in Javascript, you will want to start using design patterns, or your javascript code is quickly going to resemble a train wreck.

One of the most important graphical user interface patterns is the MVC (or Model-View-Controller) pattern. In Javascript it is possible to implement the MVC pattern, but it is not as clean as in Java Swing.

First we need to think of an example. Maybe we have a panel or screen that looks something like this :js_mvc3

 

Its basically a one to many relationship of Order to Order Items. You could represent the data part of this with this JSON code :

OrderModel = {

        order :  {
            id : 123,
            name : "Bill Gates",
            type : "Human",
            value : "Alive"
        },

        items: [
            { "id":"1" , "desc":"a book" },
            { "id":"2" , "desc":"a lamp" },
            { "id":"3" , "desc":"a mouse" }
            ]
    };

 

Lets turn now to the View. The View needs to be as dumb as possible. All it is doing is presenting HTML containing a bunch of components, the whole thing then usually wrapped up in a DIV. In the following example the  :

OrderView = Object.create(Viewable);

OrderView.createView = function() {

    var nameTextfield = document.createElement('input');

    var table = document.createElement('table');

    var row1 = document.createElement('tr');
    var row2 = document.createElement('tr');
    var row3 = document.createElement('tr');

    var td1 = document.createElement('td');
    var td2 = document.createElement('td');
    var td4 = document.createElement('td');
    var td5 = document.createElement('td');
    var td6 = document.createElement('td');
    var td7 = document.createElement('td');

    row1.appendChild(td1);
    row1.appendChild(td2);

    row2.appendChild(td3);
    row2.appendChild(td4);

    row3.appendChild(td5);
    row3.appendChild(td6);

    table.append(row1);
    table.append(row2);
    table.append(row3);

    this.append(nameTextfield);
    this.append(table);

}

I’ve omitted layout code for the sake of brevity.

Lastly the Controller. The controller contains an aggregate of all events concerning the view. This includes all event handling for the various components on the screen, and the initial load of the screen.

A method to fill the table with data has also been refactored out.

OrderController = new Object();

OrderController.setView = function(pView) {
    this.view = pView;

    this.model = Object.create(TicketViewModel);

    setUpEvents();

    onLoad(this.model);

};

OrderController.onLoad = function(data) {

    this.view.idTextfield = data.id;
    this.view.nameTextfield = data.name;
    this.view.typeTextfield = data.type;
    this.view.valueTextfield = data.value;

    setItemData(data)

}

OrderController.setItemData = function(data) {

    for(elem in data.items) {

        row1 = document.createElement('tr');

        var td1 = document.createElement('td');
        var td2 = document.createElement('td');

        td1.innerHTML = this.model.items[elem].id;
        td2.innerHTML = this.model.items[elem].desc;

        row1.appendChild(td1);
        row1.appendChild(td2);

        this.view.itemTable.append(row1);
    }
}

OrderController.setUpEvents = function() {

    var self = this;

    $(this.view.updateButton).click(function(e) {
        self.update();
    });
    $(this.view.nameTextfield).focusLost(function(e) {
        self.validateNameField();
    });
    $(this.view.exitButton).click(function(e) {
        self.exit();
    });
};

OrderController.update = function() {

    //update data to the backend
};

OrderController.validateNameField = function() {

    //do some fancy validation on the front end
};

OrderController.exit = function() {

    //navigate out of screen.
};

 

The controller you will notice a few things :

  • all GUI components are accesed through the View object
  • event code has been refactored into single methods. However that is not really necessary if the code is only one or two lines
  • implementation of the event methods are omitted for brevity.

Happy coding!

 

Posted in Design Pattern, RIA | Tagged , , , | Leave a comment

Selenium tests over Multiple Browsers

The Selenium API is great for writing Java tests for web applications. An important aspect of it is the ability to quickly regression test over multiple browsers.

A common pattern I ise is shown in the following code snippet. A common base method is called by various methods configured for different browsers (appended with “_FF” for Firefox for example).

public class PhoneDetailsTest extends MultibrowserSeleniumTest {

    @Test
    public void test_CheckPhoneDetails_FF() throws Exception {

        myWebPage = new MyWebPage(getFfWebDriver(), TestUtils.URL);
        test_CheckPhoneDetails();
    }

    @Test
    public void test_CheckPhoneDetails_Ch() throws Exception {

        myWebPage = new MyWebPage(getChromeWebDriver(), TestUtils.URL);
        test_CheckPhoneDetails();
    }

    @Test
    public void test_CheckPhoneDetails_IE() throws Exception {

        myWebPage = new MyWebPage(getIeWebDriver(), TestUtils.URL);
        test_CheckPhoneDetails();
    }

    @Test
    public void test_CheckPhoneDetailsNeg1_Ch() throws Exception {

        myWebPage = new MyWebPage(getChromeWebDriver(), TestUtils.URL);
        test_CheckPhoneDetails_Neg1();
    }

    @Test
    public void test_CheckPhoneDetailsNeg1_FF() throws Exception {

        myWebPage = new MyWebPage(getFfWebDriver(), TestUtils.URL);
        test_CheckPhoneDetails_Neg1();
    }

    @Test
    public void test_CheckPhoneDetailsNeg1_IE() throws Exception {

        myWebPage = new MyWebPage(getIeWebDriver(), TestUtils.URL);
        test_CheckPhoneDetails_Neg1();
    }

I want to test over three browsers so I create a method for each browser which all call the same method, the only difference being that a different web driver is configured. It may seem cumbersome to replicate the method over three browsers, but one of the main benefits is that I can individually test/debug a method specific to one browser and one method. Something I really do a lot of!

The “MyWebPage” class being created is just using the page object pattern to mask the web application I want to test. It holds a web driver, and the base URL. A load() method calls the initial load of the web page. In this class all other business logic can be found.

public class MyWebPage {

    private final WebDriver driver;
    private final String url;

    public MyWebPage (WebDriver driver, String url) {
        this.driver = driver;
        this.url = url;
    }

    public void load() throws Exception {

        driver.get(this.url);

…… etc

    }

More info here on page objects can be found here:
http://code.google.com/p/selenium/wiki/PageObjects

The super class for my tests called MultibrowserSeleniumTest really only initialises the web drivers and destroys them, as well as a references MyWebPage from the page object pattern.

public abstract class MultibrowserSeleniumTest {

    public static WebDriver ffWebDriver;
    public static WebDriver ieWebDriver;
    public static WebDriver chromeWebDriver;

    protected MyWebPage myWebPage = null;

    protected static WebDriver driver;

    public static WebDriver getFfWebDriver() {
        if (ffWebDriver == null) {
            ffWebDriver = new FirefoxDriver();
        }
        return ffWebDriver;
    }

    public static WebDriver getIeWebDriver() {
        if (ieWebDriver == null) {
            System.setProperty("webdriver.ie.driver", "src/main/selenium/IEDriverServer.exe");
            ieWebDriver = new InternetExplorerDriver();
        }
        return ieWebDriver;
    }

    public static WebDriver getChromeWebDriver() {
        if (chromeWebDriver == null) {
            System.setProperty("webdriver.chrome.driver", "src/main/selenium/chromedriver.exe");
            chromeWebDriver = new ChromeDriver();
        }
        return chromeWebDriver;
    }

    @AfterClass
    public static void afterClass() {

        if (ffWebDriver != null) {
            ffWebDriver.quit();
            ffWebDriver = null;
        }
        if (ieWebDriver != null) {
            ieWebDriver.quit();
            ieWebDriver = null;
        }
        if (chromeWebDriver != null) {
            chromeWebDriver.quit();
            chromeWebDriver = null;
        }
    }

Using lazy loading for the get****Driver methods, prevents having to load the driver for each method, which can become very tedious and time consuming. A browser instance should last over the life time of a test class.

It is important that we close off the browsers @AfterClass, and not after every method, otherwise what is the point of lazy loading the drivers?
Your test case method should then look something like this :

private void test_CheckPhoneDetails() throws Exception {

        MyWebPage.load();

        PhoneRow currentRow = MyWebPage.getPhoneRowFor("INVENTAR_TEST_POS",
                PhoneRow.PHONES_TABLE_HOSTNAME_CLASS);

        // click a row
        currentRow.click();

        Thread.sleep(100);

        List expandedSecs = MyWebPage.getAllExpandedSegments();

        // only one expanded section should be visitlbe
        assertEquals(1, expandedSecs.size());

        // get this web element
        ExpandedAreaSection expandedSegmentWebElement = expandedSecs.get(0);

        // applications invnetory table header should be there
        assertTrue(expandedSegmentWebElement.isCustomerHeaderShowing());

        // find all application rows in the expanded section.
        List customerItems = expandedSegmentWebElement.getCustomerRows();

        assertEquals(4, customerItems.size());

        InventoryRow customerRow = customerItems.get(0);
        assertEquals("John Smith", customerRow.getName());
        assertEquals("01234567889", customerRow.getPhoneNumber());
        assertEquals("Information Tablet", customerRow.getItemDesc());
        assertEquals("Tue Jan 01 00:00:00 CET 1980", customerRow.getItemDate());

        // find all application data rows in the expanded section.
        customerItems = expandedSegmentWebElement.getApplicationDataRows();

        assertEquals(1, customerItems.size());

        InventoryRow appDataRow = customerItems.get(0);
        assertEquals("Mr T", appDataRow.getName());
        assertEquals("1234567889", appDataRow.getPhoneNumber());
        assertEquals("Smart Phone", appDataRow.getItemDesc());
        assertEquals("Wed Sep 12 00:00:00 CEST 2012", appDataRow.getItemDate());
    }

TIPS

  • Always keep the test code as flat as possible. All complexity should be hidden inside the page object pattern classes.
  • User a pattern similar to my super class, that way only the browsers are loaded as needed.
  • Design the tests so that all the tests can share the same lifetime of the browser instance (which is why the browsers are closed off in the @afterClass method).

 

 

Posted in Design Pattern | Tagged , , , , | Leave a comment

Simple Pie Chart in Java Swing

I know there are a lot of Swing charting software libraries out there (JFreechart comes to mind). But a lot of them come across as too bloated and require a lot of time to become familiar with.
My own Piechart is as simple as it gets; collect your segments as percentages in a list, along with the corresponding colours :

ArrayList<Double> values = new ArrayList<Double>();
values.add(new Double(10));
values.add(new Double(20));
values.add(new Double(30));
values.add(new Double(15));
values.add(new Double(15));

ArrayList<Color> colors = new ArrayList<Color>();
colors.add(Color.gray);
colors.add(Color.green);
colors.add(Color.blue);
colors.add(Color.pink);
colors.add(Color.yellow);
 PieChart pieChart = new PieChart(values, colors);
myPanel.add(pieChart);

You can get something that looks like this :

Its really basic, but its also very minimalist and does away with a lot of noise that other charting programs offer.

Simple Indicator.

I thought I would also add a couple more modes to my pie chart. The second mode is what I would call a simple indicator mode. This displays just one percentage value as a slice of the pie.

PIeChart pieChart = new PieChart(70);

I find these indicators look very effective as small graphics next to numerical text, as the following example tries to show:

I’m not 100% sure this is the best way to visually enhance percentages, but I think it looks good in certain situations.

Graded Indicator.

Another visual approach to showing a percentage growing into a critical phase, is to somehow grade the colors as the percentage level gets higher. I decided to create a third mode which allows the user to set a number of gradings with corresponding colors. As the percentage gets close to 100% the pie sections get smaller and the colors get more prominent.

Here is an example :

To use the third mode simply add an array of percentages with an array of colours, plus an overall percentage, to a third constructor :

        ArrayList<Double> values = new ArrayList<Double>();

        values.add(new Double(60));
        values.add(new Double(20));
        values.add(new Double(10));
        values.add(new Double(7));
        values.add(new Double(3));

        ArrayList<Color> colors = new ArrayList<Color>();

        colors.add(new Color(255,255,255));
        colors.add(new Color(255,183,183));
        colors.add(new Color(255,6,6));
        colors.add(new Color(244,255,43));
        colors.add(Color.BLUE);

        PieChart pc = new PieChart(grade, values, colors);

Here is the source code to the pie chart with all three modes :

 

package com.gg.piechart;

import java.awt.Color;
import java.awt.GradientPaint;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.RenderingHints;
import java.awt.geom.Arc2D;
import java.awt.geom.Ellipse2D;
import java.awt.geom.Point2D;
import java.util.ArrayList;

import javax.swing.JPanel;

public class PieChart extends JPanel {

	enum Type {
		STANDARD, SIMPLE_INDICATOR, GRADED_INDICATOR
	}

	private Type type = null; //the type of pie chart

	private ArrayList values;
	private ArrayList colors;

	private ArrayList gradingValues;
	private ArrayList gradingColors;

	double percent = 0; //percent is used for simple indicator and graded indicator

	public PieChart(int percent) {

		type = Type.SIMPLE_INDICATOR;
		this.percent = percent;
	}

	public PieChart(ArrayList values, ArrayList colors) {

		type = Type.STANDARD;

		this.values = values;
		this.colors = colors;
	}

	public PieChart(int percent, ArrayList gradingValues, ArrayList gradingColors) {
		type = Type.GRADED_INDICATOR;

		this.gradingValues = gradingValues;
		this.gradingColors = gradingColors;
		this.percent = percent;

	}

	@Override
	protected void paintComponent(Graphics g) {

		int width = getSize().width;

		Graphics2D g2d = (Graphics2D) g;
		g2d.setRenderingHint(RenderingHints.KEY_ANTIALIASING, // Anti-alias!
				RenderingHints.VALUE_ANTIALIAS_ON);

		if (type == Type.SIMPLE_INDICATOR) {

			//colours used for simple indicator
			Color backgroundColor = Color.WHITE;
			Color mainColor = Color.BLUE;

			g2d.setColor(backgroundColor);
			g2d.fillOval(0, 0, width, width);
			g2d.setColor(mainColor);
			Double angle = (percent / 100) * 360;
			g2d.fillArc(0, 0, width, width, -270, -angle.intValue());

		} else if (type == Type.STANDARD) {

			int lastPoint = -270;

			for (int i = 0; i < values.size(); i++) {
				g2d.setColor(colors.get(i));

				Double val = values.get(i);
				Double angle = (val / 100) * 360;

				g2d.fillArc(0, 0, width, width, lastPoint, -angle.intValue());
				System.out.println("fill arc " + lastPoint + " "
						+ -angle.intValue());

				lastPoint = lastPoint + -angle.intValue();
			}
		} else if (type == Type.GRADED_INDICATOR) {

			int lastPoint = -270;

			double gradingAccum = 0;

			for (int i = 0; i < gradingValues.size(); i++) { 				g2d.setColor(gradingColors.get(i)); 				 				Double val = gradingValues.get(i); 				gradingAccum = gradingAccum + val; 				 				Double angle = null; 				 				/** 				 * If the sum of the gradings is greater than the percent, then we want to recalculate 				 * the last wedge, and break out of drawing. 				 */ 				 				if (gradingAccum > percent) {

					System.out.println("gradingAccum > percent");

					//get the previous accumulated segments. Segments minus last one
					double gradingAccumMinusOneSegment = gradingAccum - val;

					//make an adjusted calculation of the last wedge
					angle = ((percent - gradingAccumMinusOneSegment) / 100) * 360;

					g2d.fillArc(0, 0, width, width, lastPoint, -angle.intValue());

					lastPoint = lastPoint + -angle.intValue();

					break;

				}else {

					System.out.println("normal");
					angle = (val / 100) * 360;

					g2d.fillArc(0, 0, width, width, lastPoint, -angle.intValue());

					System.out.println("fill arc " + lastPoint + " "
							+ -angle.intValue());

					lastPoint = lastPoint + -angle.intValue();
				}
			}
		}
	}
}
Posted in Swing | Tagged , , , | 5 Comments

Database Performance Tip, using a delete table to improve network performance.

Sometimes you want to display a large amount of data from a database table in your client application. One example from my past was a trading system built in Swing. The center piece of which contained a huge scrollable table with hundreds of thousands of financial transactions, which needed to be updated every few seconds.

Now obviously you can’t just refresh the data every few seconds. Pulling those hundreds of thousands of rows over the network would be impossibly slow.

You are only interested in what has changed, and what has become ubiquitous in database table design is the inclusion of a CREATED_DATE and UPDATED_DATE column. This allows us to programmatically grab only the data which has changed.

SELECT *
FROM TRANSACTIONS
WHERE UPDATE_DATE > $MY_LAST_SELECT_TIMESTAMP$

We store the timestamp of the last time we performed out select, and use this timestamp to pull out only the rows that have changed. After we have these updated rows, we amalgamate them with our current client side data, using perhaps a huge Hashmap to store all out client side data.

This isn’t brain surgery, but what happens if, along with updates to the data rows, you also can have rows deleted in our database? If we just use the above SQL query we will not pick up on any rows that have been deleted, because the row physically just isn’t there. Therefore we cannot reflect the exact state of the database table in our update query.

One solution is to not allow any physical table row deletions. A row is only moved into a “deleted state”, but physically it still exists in the table.

What if you need to be able to delete rows anyway?

Well… you need a “Delete table”.

Table: TRANSACTIONS
TRANS_ID    TRANSACTION DESCRIPTION    CREATED DATE    UPDATED DATE
1    Something here    12.12.2011    13:22:03 12.12.2011
3    Something here    12.12.2011    14:54:11 12.12.2011
4    Something here    12.12.2011    8:33:23   12.12.2011
6    Something here    12.12.2011    8:33:27   12.12.2011

Table: DELETED_TRANSACTIONS
TRANS_ID    UPDATED DATE
2    8:33:23 12.12.2011
5    8:35:56 12.12.2011

Every time a row is deleted in our transaction table, we want to update the DELETED_TRANSACTIONS table, by noting the ID of the row that was deleted.
Now we need two queries. One to reflect the changes in the database, which is the same as before :

SELECT *
FROM TRANSACTIONS
WHERE UPDATE_DATE > $MY_LAST_SELECT_TIMESTAMP$

And then we need this query to find any rows that have been deleted in since the last query was executed :

SELECT *
FROM DELETED_TRANSACTIONS
WHERE UPDATE_DATE > $MY_LAST_SELECT_TIMESTAMP$

Hope this helps!

Posted in Uncategorized | Tagged , , , , | Leave a comment

Monty Hall Problem in Java

I recently stumbled across something called the Monty Hall Problem. It is a basic probability problem that seems mind blowingly non-intuative to most people.

There are a lot of descriptions on this on the web, but basically the problem is this: Three closed doors are in front of a game show contestant. Behind two doors is a goat, and behind the remaining door is a car. The contestant selects one of the doors, then the host opens one of the other two doors that contains a goat. The contestant is asked if he wants to switch with the other closed door. What should the contestant do?

To most people it seems that the probablitiy is 50% either way. One door contains a car, and the other a goat, so it seems natural to assume that there is a 50/50 chance either way. But its not… if the user switches it is 66% more likely to have the car, than if he stays on his first selection.

Anyway, I couldn’t get my head around it so I wrote a little Java application that shows this phenonomena :

package com.gg.piechart;

import java.util.ArrayList;
import java.util.Random;

public class MontyHallProblem {

	public static void main(String[] args) {

		int doorIsCarStay = 0;
		int doorIsCarSwitch = 0;

		Doors doors = new Doors();

		int noTries = 30;

		/**
		 * 30 tries. User stays with their initial choice
		 */
		for (int i = 0; i < noTries; i++) {

			doors.shuffle();

			//randomly pick a door

			Integer randomNumber = getRandomNumberBtn1and3();

			Door door = doors.getDoor(randomNumber);

			/**
			 * Host reveals one of the other two doors behind which there is a goat. But
			 * the user decided to stay with the door picked.
			 */
			System.out.println("door.isCar " + door.isCar);

			if (door.isCar)
				doorIsCarStay++;
		}

		/**
		 * 30 tries. User switches from their initial choice
		 */
		for (int i = 0; i < noTries; i++) {

			doors.shuffle();

			//randomly pick a door

			Integer randomNumber = getRandomNumberBtn1and3();

			Door door = doors.getDoor(randomNumber);

			/**
			 * Host reveals one of the other two doors behind which there is a goat.
			 */

			Door d = doors.getDoor(randomNumber);
			Door goatDoor = doors.getDoorFromRemainingTwoThatisGoat(d);

			/**
			 * User switches to remaining door
			 */
			Door remainingDoor = doors.getRemainingDoor(goatDoor, door);

			if (remainingDoor.isCar)
				doorIsCarSwitch++;
		}

		System.out.println("doorIsCarStay = " + doorIsCarStay);
		System.out.println("doorIsCarSwitch = " + doorIsCarSwitch);

	}

	private static Integer getRandomNumberBtn1and3() {
		Random r = new Random();
		Integer d = r.nextInt(3);
		return d;
	}
}

class Door {

	int doorNumber = -1;

	boolean isCar = false;

	public Door(int i) {
		doorNumber = i;
	}

	public void setCar(boolean b) {
		isCar = b;
	}

	@Override
	public boolean equals(Object obj) {
		if (this == obj)
			return true;
		if (obj == null)
			return false;
		if (getClass() != obj.getClass())
			return false;
		Door other = (Door) obj;
		if (doorNumber != other.doorNumber)
			return false;
		return true;
	}

}

/**
 * Doors object. Contains all doors and
 * @author Administrator
 *
 */
class Doors{

	Door door1 = new Door(1);
	Door door2 = new Door(2);
	Door door3 = new Door(3);

	public Doors() {
	}

	/**
	 * Give two doors, get the third.
	 *
	 * @param doorG
	 * @param door
	 * @return
	 */
	public Door getRemainingDoor(Door doorG, Door door) {

		if (!door1.equals(doorG) && !door1.equals(door))
			return door1;
		if (!door2.equals(doorG) && !door2.equals(door))
			return door2;
		if (!door3.equals(doorG) && !door3.equals(door))
			return door3;

		throw new RuntimeException("asd");
	}

	/**
	 * Get the door of the remaining two doors that has a Goat.
	 *
	 * @param chosenDoor
	 * @return
	 */
	public Door getDoorFromRemainingTwoThatisGoat(Door dr) {

		ArrayList al = new ArrayList();

		switch (dr.doorNumber) { //Just add remaining 2 to the array list.
		case 0:
			al.add(door2);
			al.add(door3);
			break;
		case 1:
			al.add(door1);
			al.add(door3);
			break;
		case 2:
			al.add(door1);
			al.add(door2);
			break;

		default:
			break;
		}

		//get the one that is the goat
		for (Door door : al) {
			if (!door.isCar) {
				return door;
			}
		}
		throw new RuntimeException("should not be here");
	}

	public Door getDoor(Integer d) {
		switch (d) {
		case 0:
			return door1;
		case 1:
			return door2;
		case 2:
			return door3;
		default:
			throw new RuntimeException("xx");
		}
	}

	/**
	 * Shuffle. Or pick a random permutation. There are only three possible
	 * combinations.
	 *
	 */
	public void shuffle() {

		Random r = new Random();
		Integer i = r.nextInt(3);
		System.out.println("" + i);

		switch (i) {
		case 0:
			door1.setCar(true);
			door2.setCar(false);
			door3.setCar(false);
			break;
		case 1:
			door1.setCar(false);
			door2.setCar(true);
			door3.setCar(false);
			break;
		case 2:
			door1.setCar(false);
			door2.setCar(false);
			door3.setCar(true);
			break;
		default:
			break;
		}
	}
}
Posted in Uncategorized | Tagged , , | Leave a comment

Setting a Conditional on a Breakpoint in Eclipse

Sometimes when you are debugging your program in Eclipse you will be using breakpoints within program loops. What can be really frustrating is when this loop is really large and the particular iteration you are interested is hundreds of iterations away.

Assume we are debugging the following program and we are only interested in stepping through the for loop when i==500.

The two most common naive approaches would be to step through the loop 500 times by pressing the green arrow 500 times, or you could add an if conditional statement directly into the code and shift the breakpoint onto this conditional.

However the first approach will give you repetitive strain injury and the second approach will make a mess of your code.

If you select your breakpoint in the breakpoints view in Eclipse you will see that a panel with options becomes visible for that particular breakpoint. You can select hit count, and add a numerical value into the text field. This means the breakpoint will be ignored this many times before being suspended again.

Another option is to enter in a conditional statement. Below the “Choose a previously entered condition” drop down, you should see a text area (You may need to make the view a bit bigger to see it). This text area is free text so you can enter anything you wish, although the debugger will complain if you enter in variables that don’t exist.

Now when this breakpoint is visited AND this condition is true, the breakpoint will be suspended.

 

 

 

 

 

 

 

Posted in Eclipse | Tagged , , , | Leave a comment

GridBagLayout Tutorial

This tutorial shows you how to construct a complex Java Swing GUI using the GridBagLayout.

Let’s assume you have received a protoype sketch of how an application screen should look like, which you have been assigned to create :

It is a fairly complex user interface screen with a number of different controls, and with different component regions. Let’s sketch some lines to represent grid lines. Our GridBagLayout has gridX and gridY constraints which can be associated with the components we have sketched in our grid.

If we think about it for a while, we can see that not all regions fit into a grid cell, some regions spread into two cells (marked in blue) :

 

We can make the GridBagLayout make these two blue regions cover more than one cell using the gridWidth and gridHeight constraint.

***

So… let’s create a basic first cut of our GUI. The following code sets up the main components in the frame using GridBagLayout. At the moment we don’t have any components in the details panel to the right, so we will add a border on an empty panel to get a visual on where it should be on the frame.

public class GridBagDemo1 extends JFrame {

	public GridBagDemo1(){
		initGUI();
	}

	public void initGUI() {

		setTitle("");

		JPanel panel = new JPanel(new GridBagLayout());
		this.getContentPane().add(panel);

		JTable t = new JTable(null);

		JLabel label = new JLabel("My Things");

		JPanel tableButtonPanel = new JPanel();
		tableButtonPanel.add(new JButton("Add Thing"));
		tableButtonPanel.add(new JButton("Delete Thing"));
		tableButtonPanel.add(new JButton("Modify Thing"));

		JPanel buttonPanel = new JPanel();
		buttonPanel.add(new JButton("Print"));
		buttonPanel.add(new JButton("History"));
		buttonPanel.add(new JButton("Preferences"));
		buttonPanel.add(new JButton("Another Button"));
		buttonPanel.add(new JButton("Add Another"));
		buttonPanel.add(new JButton("Yet Another"));

		JPanel detailsPanel = new JPanel();
		detailsPanel.setBorder(BorderFactory.createLineBorder(Color.BLACK));

		GridBagConstraints gbc = new GridBagConstraints();

		gbc.gridx = 0;
		gbc.gridy = 0;

		panel.add(label, gbc);

		gbc.gridx = 0;
		gbc.gridy = 1;
		panel.add(new JScrollPane(t), gbc);

		gbc.gridx = 0;
		gbc.gridy = 2;
		panel.add(tableButtonPanel, gbc);

		gbc.gridx = 0;
		gbc.gridy = 3;
		gbc.gridwidth = 2;
		panel.add(buttonPanel, gbc);

		gbc.gridx = 1;
		gbc.gridy = 1;
		gbc.gridwidth = 1;
		gbc.gridheight = 2;
		panel.add(detailsPanel, gbc);

		this.pack();

		this.setVisible(true);
	}

	public static void main(String[] args) {
		GridBagDemo1 frame = new GridBagDemo1();

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

Notice how one GridBagConstraint object is being created and being passed in with the component to the main panel? This constraint object holds all the information on how a component should be displayed. In our first cut, we are only interested in the X and Y placement, and spans, so we set gridX and gridY on all the first level components we are adding.

For our button panel at the bottom we set the gridWidth to 2, indicating that we want it to spread to the right by one more grid cell, and likewise with the details panel we want it to spill over into two cells. It is important to reset any constraint values (such as gridWidth) because we are dealing with only one constraints object.

Now when we run our program we will see this :

Well, it’s a start..

The two rows of buttons are looking good. Per default JPanels have a FlowLayout, laying out components from left to right in a centered fashion. This looks good for what our requirements are. Of course our label at the top needs to be left aligned, and our table would be good if it had some data in it.

We can anchor our label to the left quite easily by adding an anchor constraint.

 gbc.anchor = GridBagConstraints.WEST;

Lets move on to our details panel on the right. This panel will also use a GridBagLayout, so we will effectively have two nested GridBagLayouts in our application frame. We’ll create this panel in a separate method, and add this panel to where our empty panel with the border was. In this first cut lets just concern ourselves with gridX and gridY constraints :

	

private JPanel createDetailsPanel() {

		JPanel panel = new JPanel();

		JLabel thingNameLabel = new JLabel("Thing Name");
		JLabel anAttributeLabel = new JLabel("An Attribute");
		JLabel dateFieldLabel = new JLabel("Date Field");
		JLabel anAttLabel = new JLabel("An Att");
		JLabel anotherAttLabel = new JLabel("Another Att");
		JLabel anotherAtt2Label = new JLabel("Another Att");

		JTextField thingNameField = new JTextField("Thing Name");
		JTextField anAttributeField = new JTextField("An Attribute");
		JTextField dateFieldField = new JTextField("Date Field");
		JTextField anAttField = new JTextField("An Att");
		JTextArea anotherAttField = new JTextArea("Another Att");
		JTextField anotherAtt2Field = new JTextField("Another Att");

		JCheckBox checkbox1 = new JCheckBox("A Checkbox");
		JCheckBox checkbox2 = new JCheckBox("A Checkbox");

		panel.setLayout(new GridBagLayout());

		GridBagConstraints gbc = new GridBagConstraints();

		int i=0;

		gbc.gridx = 0;
		gbc.gridy = i;
		panel.add(thingNameLabel,  gbc);

		gbc.gridx = 1;
		gbc.gridy = i;
		panel.add(thingNameField,  gbc);		

		i++;

		gbc.gridx = 1;
		gbc.gridy = i;
		panel.add(checkbox1,  gbc);

		i++;

		gbc.gridx = 0;
		gbc.gridy = i;
		panel.add(anAttributeLabel,  gbc);

		gbc.gridx = 1;
		gbc.gridy = i;
		panel.add(anAttributeField,  gbc);		

		i++;

		gbc.gridx = 0;
		gbc.gridy = i;
		panel.add(dateFieldLabel,  gbc);

		gbc.gridx = 1;
		gbc.gridy = i;
		panel.add(dateFieldField,  gbc);		

		i++;

		gbc.gridx = 0;
		gbc.gridy = i;
		panel.add(anAttLabel,  gbc);

		gbc.gridx = 1;
		gbc.gridy = i;
		panel.add(anAttField,  gbc);		

		i++;

		gbc.gridx = 0;
		gbc.gridy = i;
		panel.add(anotherAttLabel,  gbc);

		gbc.gridx = 1;
		gbc.gridy = i;
		panel.add(anotherAttField,  gbc);

		i++;
		gbc.gridx = 0;
		gbc.gridy = i;
		panel.add(anotherAtt2Label,  gbc);

		gbc.gridx = 1;
		gbc.gridy = i;
		panel.add(anotherAtt2Field,  gbc);

		gbc.gridx = 2;
		gbc.gridy = i;
		panel.add(checkbox2,  gbc);

		return panel;
	}

A useful technique is to use variables for X and Y coordinates. In our details panel, I have used an ‘I’ variable for the Y position. This makes it extremely easy to add extra fields at a later point in time.

Now lets see what we get :

Pretty awful huh..

All the components are in their correct X and Y positions but the width has to be fixed. The checkbox at the bottom is in its own separate column, so we need to stretch the text fields over to the right. We do this by setting the gridWidth property to two for those fields that we want to stretch over.

Set the width like this

gbc.gridwidth = 2;

remembering to set it back when you get to the labels!

gbc.gridwidth = 1;

Remember also that both label and field at the bottom have to have a width of one.

Now if we run it, it still looks terrible, but at least we see that we have three columns with most of the text fields sitting over the last two columns. Our text fields also need to ‘fill’ their space, so let’s add horizontal fill to the text fields, remembering to reset when we come to the labels.

gbc.gridx = 1;
gbc.gridy = i;
gbc.gridwidth = 2;
gbc.fill = GridBagConstraints.HORIZONTAL;
panel.add(thingNameField,  gbc);

i++;
gbc.gridx = 0;
gbc.gridy = i;
gbc.gridwidth = 1;
gbc.fill = GridBagConstraints.NONE;
panel.add(anAttributeLabel,  gbc);

Lets put our TextArea in a Scrollpane and add some dimensions.

JTextField anAttField = new JTextField("An Att");

JTextArea anotherAttField = new JTextArea(2, 10); 
JTextField anotherAtt2Field = new JTextField("Another Att");

The columns dimension in our text area will be overridden by our GridBagLayout, however our rows value (of 2) will not.

Lets also add Insets :

gbc.insets = new Insets(2,2,2,2);

If we set them once at the top, they will flow through to all components.

Now the right side of our frame is starting to look much better :

All out labels should be aligned to the top-right (or NORTHEAST in gridbag speak)

gbc.insets = new Insets(2,2,2,2);
gbc.anchor = GridBagConstraints.NORTHEAST;

We can put this alongside the insets (to affect all components) because our anchor does not affect our text field components, only our labels, since they have no FILL set.

The details panel is also hovering vertically in the center which doesn’t really look that good. We need to anchor the details panel to the NORTH on the outer GridBagLayout.

gbc.gridx = 1;
gbc.gridy = 1;

gbc.gridwidth = 1;
gbc.gridheight = 2;
gbc.anchor = GridBagConstraints.NORTH;
panel.add(createDetailsPanel(), gbc);

Our table should also stretch out in both directions, effectively swallowing up any space that may be available.

gbc.anchor = GridBagConstraints.CENTER;

gbc.gridx = 0;
gbc.gridy = 1;
gbc.fill = GridBagConstraints.BOTH; 
gbc.weightx = 1.0;
gbc.weighty = 1.0;
panel.add(new JScrollPane(table), gbc);

Weight X and weight Y should be set to 1.0 to prevent the table from collapsing upon a resize event.

Refactor out the ScrollPane and give it a preferred size. This gives you a bit of control over the fill of the table and scrollpane.

JTable table = new JTable(data, columnNames);
JScrollPane tableScrollPane = new JScrollPane(table);
tableScrollPane.setPreferredSize(new Dimension(200, 50));

If you find some of the text fields on the right are collapsing, add some column width via the integer parameter when constructing text fields :

JTextField anAttField = new JTextField("");
JTextArea anotherAttField = new JTextArea(3, 1);
JTextField anotherAtt2Field = new JTextField("", 10);

You should end up with something like this :

 

TIPS.

  • Because of all the switching around from one column to the second column. Ie resetting things like fills and anchors, it could be good idea to have 2 GridBagConstraint objects, one for each column
  • Textfields, textareas and tables should never collapse after the frame has called pack(). The collapse happens when the components size switches from preferred to minimum. This can be caused by a number of reasons. If you find textfields collapsing after resize then you should set their mimimum size to its preferred size :
textField.setMinimumSize(textField.getPreferredSize());

source code

Posted in Swing | Tagged , , , , | 11 Comments

java.lang.VerifyError: Illegal target of jump or branch … possible cause!

I got this error the other day. It usually happens when you have crazy methods which are too long. But in my situation that wasn’t the case. I found out through trial and error that I was throwing a RuntimeException which it didn’t like.

All I had in my code was :

        if(true)
        	throw new RuntimeException("TODO implement this"); //TODO

This somehow confused my compiler, probably because it realised that there was unreachable code after throwing this runtime. You need to trick the compiler better by throwing a RuntimeException like this :

        if("string".equals("string"))
        	throw new RuntimeException("TODO implement this"); //TODO

This solved my VerifyError problem in my case anyway…

Posted in Uncategorized | Tagged | Leave a comment