Sunday, May 20, 2007

Scala




What is scala? Well folks, it is a statically typed programming language. It is based on OOP paradigm, and it's pretty pure on that - everything is an object, it smells like java here. But java is cheating, and as for now, I can't see any cheating from scala's syntax point of view. What's on my mind is that java distinguishes primitive types from reference types, and also functions are not objects. Right, what is so great about scala? Well, you can run scala from your java and .NET code! Can you see that, this is true write once run everywhere, you don't have to choose between .NET and Java anymore. Scala was pretty much at the end of the list of stuff that I was going to write about, but recently it was used on JavaOne, so I thought that it might be good to write about it now. Scala was developed by Martin Odersky's group. Before that time Martin was the author of current java compiler. Some people saids that this language is the java of the 21 century, SUN cannot change java syntax to scala cause it has to keep the backwards compatibility with java.

You can import any java library to scala and you can import any scala library to java. That's a big plus. It reminds me some presentation from JavaOne in 2006 when somebody said that SUN is promoting java not as a language but as a framework. It means that java has a huge number of frameworks that one can use, it also have many tools, and apps already written - just look at those application servers. What it really sucks on is the language itself - it miss so many things. Lets' go back to scala.

Scala has some functional language specific features but it is NOT a functional language. I've read in a few places that it is, but it is not. Scala is an imperative language!!! If you are interested of what it exactly has, be sure to read this short summary.

Personally I do not like the syntax of it sometimes. For example functions:


def foo(callback: () => unit) {
...
}


what's that, just look at this thing. Why not call callback a function, or do something like this:

def foo(function bar){
...
}


I know, it's because we want to show what we are returning. It's all because of strong typing. Otherwise strong typing purists would scream that it might be confusing, just like they did with type inference in java. But why not to do a literal for that? Or some AI for the compiler - actually this kind of AI is already implemented, cause compiler can guess a return type for methods:


class Foo(bar: double) {
def buzz() = bar
}


Here, I don't have to specify a return type. For those of you who didn't cache that one I'm a week type languages supporter, I just hate to write more than I really have to. And this syntax is quite alike anonymous function syntax so I won't say any bad word anymore.

Let's rock and roll
First thing to do is to configure your favorite environment. Scala's distribution ships with modes for many general use apps. As for 2.4.0 version it binds to: a2ps, emacs, gedit, intellij, jedit, kate, scite, vim, xcode. They are installed in the ${SCALLA_INSTALL_DIR}/share/scala/misc/scala-tool-support. Notice that it's not very common that a tool supports intellij in a standard distribution and not eclipse. Fear not, eclipse plugin is located here. Here is my configuration for GNU/Emacs.

(defvar utils-dir "/home/sagasu/worek")
(setenv "SCALA_HOME" (concat utils-dir "/scala"))
(setenv "PATH" (concat (getenv "PATH")
":" (getenv "SCALA_HOME") "/bin"))
(require 'scala-mode-auto)


Scala and Maven
As for now there is no scala plugin for maven that is ready to use. Google is sponsoring creation of a plugin. So, it's not in any maven repository but you can build it yourself. Grab it from subversion repository:

svn checkout http://maven-scala-plugin.googlecode.com/svn/trunk/ maven-scala-plugin

and build

cd maven-scala-plugin
mvn install


now we can add following lines to our maven project (pom.xml file) in order to compile any scala program:


<build>
<plugins>
<plugin>
<groupId>scala</groupId>
<artifactId>maven-scala-plugin</artifactId>
<executions>
<execution>
<id>scala-compile</id>
<phase>compile</phase>
<goals>
<goal>compile</goal>
</goals>
<configuration>
<uncheckedWarnings>true</uncheckedWarnings>
<deprecationWarnings>true</deprecationWarnings>
</configuration>
</execution>
</executions>
</plugin>

<plugin>
<groupId>scala</groupId>
<artifactId>maven-scala-plugin</artifactId>
<executions>
<execution>
<id>scala-compile</id>
<phase>process-test-sources</phase>
<goals>
<goal>testCompile</goal>
</goals>
</execution>
</executions>
</plugin>
</plugins>
</build>

Thursday, May 10, 2007

Date Parsing and Formating in Java




Sounds simple. There is SimpleDateFormat you may say, or GenericTypeValidator. What's the problem then? Well folks, both libraries are not good enough to parse/format dates.

So we want to allowed users to input dates only in a format "yyyy-MM-dd" or "yyy-MM-dd HH:mm".

Let’s write a unit test for that:


import java.util.Date;

import junit.framework.TestCase;

public class DateTimeFormatTest extends TestCase{
public void testParseDate() throws Exception {
Date date = DateTimeFormat.parseDate("2005-01-01", DateTimeFormat.getDateFormat());
assertNotNull(date);

}
}


OK, now let's write a class:

import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Date;

import org.apache.commons.validator.GenericTypeValidator;

public class DateTimeFormat {
private static final String DATE_TIME_FORMAT = "yyyy-MM-dd HH:mm";
private static final String DATE_FORMAT = "yyyy-MM-dd";

public static Date parseDate(String dateValue, String format) {
SimpleDateFormat simpleDateFormat = new SimpleDateFormat(format);
Date aParsedDate = null;
try {
aParsedDate = simpleDateFormat.parse(dateValue);
} catch (ParseException e) {
return null;
}
return aParsedDate;
}

public static String getDateFormat() {
return DATE_FORMAT;
}

public static String getDateTimeFormat() {
return DATE_TIME_FORMAT;
}

}


So now if we run a test it succeeds. Let's add additional tests.

date = DateTimeFormat.parseDate("2005-01-aa", DateTimeFormat.getDateFormat());
assertNull(date);

date = DateTimeFormat.parseDate("2005/01/01", DateTimeFormat.getDateFormat());
assertNull(date);



Hey, it's working again. But wait, what about this one:


date = DateTimeFormat.parseDate("2005-01-01 12:12", DateTimeFormat.getDateFormat());
assertNull(date);

Ups, tests don’t pass. Now there is a way that we can tell SimpleDateFormat to be more strict, just add this line

simpleDateFormat.setLenient(false);

unfortunately it won't work. I guess using this kind of parsing is not a good idea :>

But now let's use GenericTypeValidator. We write a test:

public void testValidatorParseDate() throws Exception {
Date date = DateTimeFormat.validatorParseDate("2005-01-01", DateTimeFormat.getDateFormat());
assertNotNull(date);

date = DateTimeFormat.validatorParseDate("2005-01-aa", DateTimeFormat.getDateFormat());
assertNull(date);

date = DateTimeFormat.validatorParseDate("2005/01/01", DateTimeFormat.getDateFormat());
assertNull(date);

date = DateTimeFormat.validatorParseDate("2005-01-01 12:12", DateTimeFormat.getDateFormat());
assertNull(date);
}



and we add a method to the class:


public static Date validatorParseDate(String dateValue, String format) {
Date aParsedDate = GenericTypeValidator.formatDate(dateValue, format, true);
return aParsedDate;
}



Hey this one works. Now add additional test case:


date = DateTimeFormat.validatorParseDate("2005-1-1-1", DateTimeFormat.getDateFormat());
assertNull(date);


Ups again failure. This same thing happens to the next test:


date = DateTimeFormat.validatorParseDate("2005-11-11 1:1:1", DateTimeFormat.getDateTimeFormat());
assertNull(date);


Again using this parser is not a good idea, but it's better then SimpleDateFormat. What to do then? I use regexps, but by using them I force myself to write additional regexp for every date pattern that I allow. In showed example I've only used two date patterns "yyyy-MM-dd HH:mm" and "yyyy-MM-dd" but I used to deal with systems with more then 8 date patterns and it gets pretty messy their, witch means that I have to use some more complicated techniques in order to create a good looking code. Now after refactoring, both classes looks as follow:

import java.util.Date;

import junit.framework.TestCase;

public class DateTimeFormatTest extends TestCase{

public void testValidatorParse() throws Exception {
String dateFormat = DateTimeFormat.getDateFormat();
String dateFormatRegexp = DateTimeFormat.getDateFormatRegexp();

Date date = DateTimeFormat.validatorParse("2005-01-01", dateFormat, dateFormatRegexp);
assertNotNull(date);

date = DateTimeFormat.validatorParse("2005-01-1", dateFormat, dateFormatRegexp);
assertNull(date);

date = DateTimeFormat.validatorParse("2005-01-01", DateTimeFormat.getDateTimeFormat(), dateFormatRegexp);
assertNull(date);

date = DateTimeFormat.validatorParse("2005-01-01", dateFormat, DateTimeFormat.getDateTimeFormatRegexp());
assertNull(date);

date = DateTimeFormat.validatorParse("2005-01-01 12:12", DateTimeFormat.getDateTimeFormat(), DateTimeFormat.getDateTimeFormatRegexp());
assertNotNull(date);
}

public void testParse() throws Exception {
String dateFormat = DateTimeFormat.getDateFormat();
String dateFormatRegexp = DateTimeFormat.getDateFormatRegexp();

Date date = DateTimeFormat.parse("2005-01-01", dateFormat, dateFormatRegexp);
assertNotNull(date);

date = DateTimeFormat.parse("2005-01-1", dateFormat, dateFormatRegexp);
assertNull(date);

date = DateTimeFormat.parse("2005-01-01", DateTimeFormat.getDateTimeFormat(), dateFormatRegexp);
assertNull(date);

date = DateTimeFormat.parse("2005-01-01", dateFormat, DateTimeFormat.getDateTimeFormatRegexp());
assertNull(date);

date = DateTimeFormat.parse("2005-01-01 12:12", DateTimeFormat.getDateTimeFormat(), DateTimeFormat.getDateTimeFormatRegexp());
assertNotNull(date);
}

public void testParseDate() throws Exception {
Date date = DateTimeFormat.parseDate("2005-01-01");
assertNotNull(date);

date = DateTimeFormat.parseDate("2005-01-aa");
assertNull(date);

date = DateTimeFormat.parseDate("2005/01/01");
assertNull(date);

date = DateTimeFormat.parseDate("2005-01-01 12:12");
assertNull(date);

date = DateTimeFormat.parseDate("2005-01-01 12:12");
assertNull(date);

date = DateTimeFormat.parseDate("2005-1-1-1");
assertNull(date);
}

public void testParseDateTime() throws Exception {
Date date = DateTimeFormat.parseDateTime("2005-01-01 11:11");
assertNotNull(date);

date = DateTimeFormat.parseDateTime("2005-11-11 1:1:1");
assertNull(date);

date = DateTimeFormat.parseDateTime("2005-11-11 9:11");
assertNull(date);

date = DateTimeFormat.parseDateTime("2005-11-11");
assertNull(date);
}

public void testValidatorParseDate() throws Exception {
Date date = DateTimeFormat.parseDate("2005-01-01");
assertNotNull(date);

date = DateTimeFormat.validatorParseDate("2005-01-aa");
assertNull(date);

date = DateTimeFormat.validatorParseDate("2005/01/01");
assertNull(date);

date = DateTimeFormat.validatorParseDate("2005-01-01 12:12");
assertNull(date);

date = DateTimeFormat.validatorParseDate("2005-1-1-1");
assertNull(date);

date = DateTimeFormat.validatorParseDateTime("2005-11-11 1:1:1");
assertNull(date);

date = DateTimeFormat.validatorParseDateTime("2005-11-11 11:11");
assertNotNull(date);
}

public void testValidatorParseDateTime() throws Exception {
Date date = DateTimeFormat.validatorParseDateTime("2005-01-01 11:11");
assertNotNull(date);

date = DateTimeFormat.validatorParseDateTime("2005-11-11 1:1:1");
assertNull(date);

date = DateTimeFormat.validatorParseDateTime("2005-11-11 9:11");
assertNull(date);

date = DateTimeFormat.validatorParseDateTime("2005-11-11");
assertNull(date);
}
}



And the main class

import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Date;

import org.apache.commons.validator.GenericTypeValidator;

public class DateTimeFormat {
private static final String DATE_TIME_FORMAT = "yyyy-MM-dd HH:mm";
private static final String DATE_FORMAT = "yyyy-MM-dd";
private static final String DATE_FORMAT_REGEXP = "^[0-9]{4}-[0-9]{2}-[0-9]{2}$";
private static final String DATE_TIME_FORMAT_REGEXP = "^[0-9]{4}-[0-9]{2}-[0-9]{2} [0-9]{2}:[0-9]{2}$";

/**
* @param dateValue
* @param format
* @param regexp
* @return parsed date if dateValue matches format and regexp, else null
*/
public static Date validatorParse(String dateValue, String format, String regexp) {
Date parsedDate = GenericTypeValidator.formatDate(dateValue, format, true);
return matchRegexp(dateValue, regexp, parsedDate);
}

/**
* @param dateValue
* @param regexp
* @param parsedDate
* @return parsedDate if dateValue matches regexp, else null
*/
private static Date matchRegexp(String dateValue, String regexp, Date parsedDate) {
if(!dateValue.matches(regexp)){
return null;
}
return parsedDate;
}

/**
* @param dateValue
* @return date parsed by SimpleDateFormat
*/
public static Date parseDate(String dateValue) {
return parse(dateValue, getDateFormat(), getDateFormatRegexp());
}

/**
* @param dateTimeValue
* @return date parsed by SimpleDateFormat
*/
public static Date parseDateTime(String dateTimeValue) {
return parse(dateTimeValue, getDateTimeFormat(), getDateTimeFormatRegexp());
}

/**
* @param dateTimeValue
* @return date parsed by GenericTypeValidator
*/
public static Date validatorParseDateTime(String dateTimeValue) {
return validatorParse(dateTimeValue, getDateTimeFormat(), getDateTimeFormatRegexp());
}

/**
* @param dateValue
* @return date parsed by GenericTypeValidator
*/
public static Date validatorParseDate(String dateValue) {
return validatorParse(dateValue, getDateFormat(), getDateFormatRegexp());
}

/**
* @param dateValue
* @param format
* @param regexp
* @return parsed date if dateValue matches format and regexp, else null
*/
public static Date parse(String dateValue, String format, String regexp) {
SimpleDateFormat simpleDateFormat = new SimpleDateFormat(format);
simpleDateFormat.setLenient(false);
Date parsedDate = null;
try {
parsedDate = simpleDateFormat.parse(dateValue);
} catch (ParseException e) {
return null;
}
return matchRegexp(dateValue, regexp, parsedDate);
}

public static String getDateFormat() {
return DATE_FORMAT;
}

public static String getDateTimeFormat() {
return DATE_TIME_FORMAT;
}

public static String getDateFormatRegexp() {
return DATE_FORMAT_REGEXP;
}

public static String getDateTimeFormatRegexp() {
return DATE_TIME_FORMAT_REGEXP;
}

}


Because both SimpleDateFormat and GenericTypeValidator need to be enhanced in order to work properly I'll stick with SimpleDateFormat, mainly because I don't have to use huge apache library in order to parse anything. Two things bother me. Why do I have to write my own validator, and why there is no way in java to remove this redundancy that I see in tests. I'll live it for the future investigation.

Saturday, May 5, 2007

Ruby and GTK2




I've been using for a while Zenity as a simple framework to provide user interaction on my local machine. Few of my family members also use my computer and it is easier for them to use UI, then to remember all the magic words, not to mention terminal. So, my Internet provider likes to drop the connection, maybe not very often but it happens. It's really suspicious when you are doing some research and it's 2:30 am and then suddenly your ISP declines your connections. Perhaps they are doing some cleaning at that hour, maybe it is worth investigating, but as for now never mind. Right, clearly I need a tool that will show what's the status of the connection - do I need to reconnect or I'm connected but the traffic is really bad. Zenity happens to be a great tool, it's easy to use and you can create some user interaction really easy. Because I like to do new things I've decided to check out ruby GTK2 library for that. And Yes I was inspired by the recent news that Microsoft is going to include Iron Ruby in .NET framework. Here is my impression of that.

Because it is my first post about ruby let me just remind you that there is a mod for GNU Emacs. Now, you have to install additional libraries in order to use GKT2 from a ruby. I'm using Ubuntu and dependencies are pretty big, but it's as easy to install additional stuff as typing


sudo apt-get install ruby-gnome2


If you are not familiar with ruby and GTK2 a great tutorial can be found here. And in terms of API documentation be sure to try rbbr or web API documentation.

In terms of code ruby bindings to GTK are like any other bindings to GTK. This is definitely not the best way of creating UI. In terms of UI i strongly agree with Steve Yegge. Now let's get back to the ruby. Here is a code that I came up with:


require 'gtk2'

class InternetConnection


def initialize()
@connection_status = "You a_re not connected to the Internet"
end

def checkStatus()
commandOutput = `ifconfig`
if commandOutput.index("ppp0") != nil then
@connection_status = "You a_re connected to the Internet"
else
@connection_status = "You a_re not connected to the Internet"
end
end

def disconnect()
command = `xterm -e "sudo killall pppd"`
checkStatus()
end

def connect()
command = `xterm -e "sudo pppd call speedtch"`
checkStatus()
end

def run()
table = Gtk::Table.new(3, 4, true);


image_apple_green = Gtk::Image.new("apple-green.png")
image_apple_red = Gtk::Image.new("apple-red.png")
image_status = Gtk::Image.new("tennis-ball.png")

checkStatus()
b_status = Gtk::Button.new(@connection_status, use_underline = true)
b_status.set_image(image_status)
b_status.signal_connect("clicked"){
checkStatus()
}

b_connect = Gtk::Button.new("C_onnect to the Internet", use_underline = true)
b_connect.set_image(image_apple_green)
b_connect.signal_connect("clicked") {
connect()
}

b_disconnect = Gtk::Button.new("_Disconnect from the Internet", use_underline = true)
b_disconnect.set_image(image_apple_red)
b_disconnect.signal_connect("clicked") {
disconnect()
}

b_close = Gtk::Button.new(Gtk::Stock::CLOSE)
b_close.signal_connect("clicked") {
Gtk.main_quit
}

window = Gtk::Window.new
window.signal_connect("delete_event") {
Gtk.main_quit
false
}

table.attach_defaults(b_status, 0, 4, 0, 1 )
table.attach_defaults(b_connect, 0, 2, 1, 2 )
table.attach_defaults(b_disconnect, 2, 4, 1, 2 )
table.attach_defaults(b_close, 1, 3, 2, 3 )

window.border_width = 10
window.add(table)
window.show_all

Gtk.main
end

end



And it looks like that:

Thursday, May 3, 2007

Unit Testing with Groovy




So we know what the Groovy is and how to eat it. Now it is time to do something useful in terms of methodology. I'm agilist and the thing that I do after knowing constructors and reductors is how to test it. Again Groovy is really helpful, and easy to use. So, you don't need to add additional libraries or do some hacking to use tests in Groovy - they are provided in a default installation. By the default installation i mean get a Groovy from local ftp untar it and there it is ready to be used. So here is a simple example:

Create a class Square.groovy

class Square{
def square(x) {x*x}
}


Create a class SquareTest.groovy

import Square

class SquareTest extends GroovyTestCase{

void testSquare(){
Square square = new Square()
assertEquals( square.square(3),9)
}
}


be sure that both classes are in one catalog. In a command line just type:

groovy SquareTest.groovy


and see the result - everything is fine. It is the easiest xUnit framework that I've seen.
One thing about classes in Groovy - they are public by default, same as methods.

Now let's say that we want to create a framework in maven or we already have one and we want to add some Groovy classes or Groovy test classes. This task is more complicated - because of maven, it is a good tool but sometimes when you search in a xml files for a bug it it terrible, I hate it, but again it is like 200 times better then ant.

so to create a maven project (I'm using maven 2.*) just type:

mvn archetype:create -DgroupId=com.mycompany.app -DartifactId=my-app


Now goto my-app and edit pom.xml add:

<dependency>
<groupid>groovy</groupid>
<artifactid>groovy-all</artifactid>
<version>1.0</version>
<scope>test</scope>
</dependency>


create a folder groovy in my-app/src/main directory and in the my-app/src/test. In other words just in this same place as java folder. And put a *.groovy class there. Go back to the my-app directory, and run:

mvn groovy:compile


to compile main classes.

mvn groovy:testCompile


to compile test classes.

You might ask "Cool, but is there a way to compile classes just by calling normal mvn install or mvn compile?". Yes there is, just add this code to your pom.xml file:


<build>
<plugins>
<plugin>
<groupid>org.codehaus.mojo</groupid>
<artifactid>groovy-maven-plugin</artifactid>
<executions>
<execution>
<goals>
<goal>compile</goal>
<goal>testCompile</goal>
</goals>
</execution>
</executions>
</plugin>
</plugins>
</build>


Now every time you compile or run tests also groovy classes are going to be included.