Friday, September 12, 2008

Rappresentazione di un numero in lettere

Oggi mi sono trovato a dover stampare un bollettino postale per un pagamento... per cui ho avuto il solito problema di rappresentare un valore numerico in lettere, cosa che serve anche per rappresentare l'importo su assegni bancari.

Ecco qua il codice Java che realizza la cosa...

Nota: la classe org.apache.commons.lang.StringUtils; e' fornita dalla libreria
di utilita' Apache Commons Lang (http://commons.apache.org/lang/)
per cui per compilare e eseguire la classe ricordatevi di aggiungere commons-lang.jar
al vostro classpath.



import java.io.BufferedReader;
import java.io.InputStreamReader;
import java.math.BigDecimal;

import org.apache.commons.lang.StringUtils;

public class CharsNumber {

private BigDecimal v;


public CharsNumber(BigDecimal v) {
super();
this.v = v;
}

@Override
public String toString() {
return toString(v);
}

private static String toString(BigDecimal Valore) {
String result = ""; // risultato
String[] lettere = { "", "uno", "due", "tre", "quattro", "cinque",
"sei", "sette", "otto", "nove", "dieci", "undici", "dodici",
"tredici", "quattordici", "quindici", "sedici", "diciassette",
"diciotto", "diciannove", "venti", "trenta", "quaranta",
"cinquanta", "sessanta", "settanta", "ottanta", "novanta" };

String valore = "" + Valore.abs();
String resto = "/00";
valore = valore.replace(',', '.');
int k = valore.indexOf('.');
if (k >= 0) // l'importo รจ decimale
{
resto = "/" + valore.substring(k + 1);
if (resto.length() == 2) resto += "0";
if (resto.length() > 3) resto = resto.substring(0, 3);
valore = valore.substring(0, k);
}
if (valore == "0") // importo zero finisce subito
{
result += "zero";
valore = "";
}
k = valore.length() % 3;
// normalizzo la cifra in modo da poter avere dei gruppi di tre
if (k > 0) {
valore = StringUtils.leftPad(valore, valore.length() + (3 - k), '0');
}
k = -1;
while (valore.length() > 0) {
String parziale = "";
// mangia tre caratteri a destra
char[] c = valore.substring(valore.length() - 3,valore.length()).toCharArray();
valore = valore.substring(0, valore.length() - 3);
k++;
for (int j = 0; j < 3; j++) {
int x = Integer.parseInt(new Character(c[j]).toString());
if (x != 0) {
if (j == 0)
parziale += (x == 1) ? "cento" : lettere[x] + "cento";
if (j == 1)
parziale += (x < 3) ? lettere[x * 10] : lettere[x + 18];
if (j == 2) {
boolean dieci = (!parziale.endsWith("dieci"));
if (!dieci) {
parziale = parziale.substring(0, parziale.length() - 5);
}
parziale += (dieci) ? lettere[x] : lettere[x + 10];
if (dieci) {

for (String s : new String[] { "ao", "au", "io",
"iu" }) {
int i = parziale.indexOf(s);
String t = s.substring(1);
while (i >= 0) {
parziale = parziale.substring(0, i)
+ parziale.substring(i + 1);
i = parziale.indexOf(s);
}
}
} // if (dieci)
} // if (j==2)
} // if (j != 0)
} // for j
if (parziale.length() > 0) {
String[] mille = { "uno", "mille", "unmilione", "unmiliardo",
"millemiliardi", "unmilionedimiliardi",
"unmiliardodimiliardi", "", "mila", "milioni",
"miliardi", "milamiliardi", "milionidimiliardi",
"miliardidimiliardi" };
int j = k + 7;
if (parziale.equals("uno")) {
parziale = "";
j = k;
}
if (j > mille.length - 1)
result = "valore fuori dei limiti";
else
result = (k == 0) ? mille[j] + parziale : parziale
+ mille[j] + result;
}
} // while
result += resto;
if (Valore.doubleValue() < 0)
result = "meno" + result;
return result;

}

public static void main(String[] args) throws Exception {

BufferedReader console = new BufferedReader(
new InputStreamReader(java.lang.System.in)
);

java.lang.System.out.println("Numero: ");

String line = "";
while ((line = console.readLine()) != null) {
BigDecimal d = new BigDecimal(line);
java.lang.System.out.println("Lettere: " + new CharsNumber(d));
java.lang.System.out.print("Numero: ");
}

}

}


Monday, July 28, 2008

JavaCC Maven Plugin and JJTree User definied Node Classes

Well I'm using JJTree (the Javacc preprocessor) to build a parsed tree model of the language that I'm implementing.

I also use maven to manage my project as usually and so I use the javacc maven plugin JavaCC Maven Plugin to integrate the jjtree and javacc commands into the project build lifecycle.

All worked fine until I start to provide my own defined node classes for the JJTree model.
In this case I experienced same unpleasant behaviors of jjtree about mixing generated and user provided java sources.

In fact I could not maintain well divided my sources implementing tree nodes from jjtree generated ones.

In particularity with the javacc maven plugin default configuration, the sources generation process ignores my java classes located in the default sources directory src/main/java and at the end of the process I obtain a compilation error of duplicate class. In fact for each classes I define I find also the generated one into the directory target/generated-sources/javacc.

So I decide to remove the java files from the generated sources directory in the case I had yet provided it.

Here the pom file with the ant code passed to maven-antrun-plugin to do this dirty work




Wednesday, May 28, 2008

Blite-SE was just born!!

I have just founded a new project at Google Code, Blite-SE.
This new project aims to implement the Blite language as JBI component. The language has bean created at University of Florence by Prof. R. Pugliese and his research group.
In this project we chose as JBI target platform the Fuji implementation. Fuji is the new open source JBI enviroment based on OSGi, and it's the next JBI implemetation in the GlassFish v3.

Please check it out and report here your impression about the project and its intentions.
Thank you.
Panks

Tuesday, April 1, 2008

Linux File Locks: Java and the others...

Since Java 1.4, it's possible to locks file using the underline o.s. facilities through the standard API; in this way we can safe share external files with non-Java applications or among multiple Java applications (on different JVM) without writing native and unportable code.

The FileLock class, which is part of the java.nio.channels package, represents a file lock. You can use a file lock to restrict access to a file from multiple processes. In addition, you have the option of restricting access to an entire file or just a small region of it. A file lock is either shared or exclusive as usually. If you use a file lock in multiple threads, none of the threads would be restricted from accessing the file, because they run in the same VM and share the same system process. Only external processes are restricted.

To use file locking, you need to get a file channel, that is an instance of the FileChannel class. You can get a file channel through the getChannel method of any of the following I/O classes:
  • FileInputstream
  • FileOutputStream
  • RandomAccessFile
After you get a file channel, you can use either of two pairs of methods that it offers for working with locks: lock and tryLock.

FileLock lock()
FileLock tryLock()
In this post I show an example how use this api to lock a file under Linux (Ubuntu 7.10) and to synchronize a Java program with C native program to access a shared file.

Here the Java code, it asks the user for a file to open and than it writes to it the successive user input lines. Before starting to write to the file the Java Program try to get an exclusive lock on the file.

import java.io.BufferedReader;
import java.io.File;
import java.io.FilenameFilter;
import java.io.InputStreamReader;
import java.io.RandomAccessFile;
import java.nio.channels.FileLock;
import java.util.regex.Pattern;

/**
* @author panks
*
*/
public class Main {

/**
* @param args
* @throws Exception
*/
public static void main(String[] args) throws Exception {

RandomAccessFile file = null;
FileLock lock = null;
try {
BufferedReader console =
new BufferedReader(new InputStreamReader(System.in));
System.out.println("Inserisci nome file:");

String name = console.readLine();
file = new RandomAccessFile(name, "rwd");

System.out.println("locking file " + name);

lock = file.getChannel().tryLock();

if (lock == null) {
System.out.println("NO LOCK :( bye bye...");
return;
}
System.out.println("!!LOCKED!!");

String line = "";
while ((line = console.readLine()) != null) {
file.writeBytes(line + "\n");
}
} finally {
if (lock != null) lock.release();
if (file != null) file.close();
}
}

}

Ok then let's try the program
java Main
Inserisci nome file:
file
locking file file
!!LOCKED!!
hello world!!
...
leave the program running and open a new console to the same working directory and try

cat file
hello world!!
...


oopss... we can access the locked file!! ... does it seam strange? Do worry your linux station is working perfectly and this the normal specificated behavior. In fact we have to remember normally file locks on unix operation system are advisory locks, then programs must collaborate to share files, they must use the same lock strategy to be blocked each others.

Ok, the try with and well advised startegy

flock file ls
file Main.class

Whats?!?! So... That seams really strange. Wait a moment try this

flock file cat
blabla blabla
blabla blabla
uhuh uuhh uhh
uhuh uuhh uhh

open a new console to the same directory and type

flock -n file cat

this return 1 because it can't lock the file.
Then the flock works fine, but it doesn't work with Java locks.
In this situation we have only one thing to do... "let's open the box and take a look inside"...
we need to directly explore our great resource... the LINUX KERNEL and his system calls .

Ok in the flock man 1 page we can read:
"This utility manages flock(2) locks from within shell scripts or the command line"
so the flock shell command use the flock syscall, in fact in man 2 flock we can read

"... Since kernel 2.0, flock() is implemented as a system call in its own right rather than being emulated in the GNU C library as a call to fcntl(2). This yields true BSD semantics: there is no interaction between the types of lock placed by flock() and fcntl(2), and flock() does not detect deadlock. ..."

Now the situation becomes to be clearer, probably the Java Api are implemented by fcntl and so they can't share locks with flock. By the way we can explore this possibility.

We start to write a simple C program that uses the flock syscall directly.


#include
#include
#include

#include
#include

#include
#include

int main(void) {
char filepath[100];

puts("Please insert the file path:");
gets(filepath); //don't use gets, only here for simplicty ;)

int fd = open(filepath, O_CREAT | O_RDWR | O_SYNC
, S_IRUSR | S_IWUSR | S_IROTH | S_IRGRP);
if (fd < 0) perror("open");

printf("opened file %s \n", filepath);

puts("tring to lock file...");

if (flock(fd, LOCK_EX) < 0)
perror("fcntl");
else
puts("file !!LOCKED!!");

char line[1000];

while (fgets(line, 1000, stdin) != NULL) {
int n = write(fd, line, strlen(line));
if (n < 0) perror("write");
}


puts("release lock ...");

if (flock(fd, LOCK_UN) < 0)
perror("flock");
else
puts("file !!RELEASED!!");

puts("closing file...");

if (close(fd) < 0)
perror("close");
else
puts("file !!CLOSED!!");

return 0;
}


Ok now we test this program compiled to the executable file named as exs.

In one terminal we execute:


./exs
Please insert the file path:
file
opened file file
tring to lock file...
file !!LOCKED!!
Hello Word!
:)


We have the file file opened and locked in exclusive way and we are writing into it.

On one other terminal in the same dir we can try this:


flock file cat file


the terminal is blocked because the flock can't acquire the lock the file.
If we go back to the first terminal and we give the Crt+D

release lock ...
file !!RELEASED!!
closing file...
file !!CLOSED!!

on the second terminal we have


Hello Word!
:)


so our c program shares file lock with the shell command flock in the right way.

let's try it with the Java program.


java Main
Inserisci nome file:
file
locking file file
!!LOCKED!!
Ciao
Mondo!
by panks


I lock the file file and I start writing to it by Java code.
On the other terminal I try the c program


./exs
Please insert the file path:
file
opened file file
tring to lock file...
file !!LOCKED!!
Bella
Ciao!
release lock ...
file !!RELEASED!!
closing file...
file !!CLOSED!!

..mmm yes the two program seams absolutely ignore themselves...


Inserisci nome file:
file
locking file file
!!LOCKED!!
Ciao
Mondo!
by panks
"CRTL+D"
cat file
Bella
Ciao!
by panks


The c program rewrote what Java one has written before...





Well now we can try using the fcntl syscall from our c code.
Here the exs program modified with fcntl.


...
int main(void) {
char filepath[100];

puts("Please insert the file path:");
gets(filepath); //don't use gets, only here for simplicty ;)

struct flock lock;
/* Initialize the flock structure. */
memset (&lock, 0, sizeof(lock));
lock.l_type = F_WRLCK;

int fd = open(filepath, O_CREAT | O_RDWR | O_SYNC
, S_IRUSR | S_IWUSR | S_IROTH | S_IRGRP);
if (fd < 0) perror("open");

printf("opened file %s \n", filepath);
puts("tring to lock file...");

if (fcntl(fd, F_SETLKW, &lock) < 0)
perror("fcntl");
else
puts("file !!LOCKED!!");

char line[1000];

while (fgets(line, 1000, stdin) != NULL) {
int n = write(fd, line, strlen(line));
if (n < 0) perror("write");
}


puts("release lock ...");
lock.l_type = F_UNLCK;

if (fcntl(fd, F_SETLKW, &lock) < 0)
perror("fcntl");
else
puts("file !!RELEASED!!");

puts("closing file...");

if (close(fd) < 0)
perror("close");
else
puts("file !!CLOSED!!");

return 0;
}


ok now let's to try it with the Java one.

In the first terminal


./exs
Please insert the file path:
file
opened file file
tring to lock file...
file !!LOCKED!!
Come e' dura
l'avventura...


we lock the file file by the c code using the fcntl directly.
On the second terminal we execute the Java program:


java Main
Inserisci nome file:
file
locking file file
NO LOCK :( bye bye...


YES!!!! IT WORKS... we synchronized the Java program with linux C native code on a file.





Same conclusions:

The FileLock class is absolutely useful but probably better to use it to synchronize Java Processes running on different JVM of the same version (in fact different implementations could give unexpected behaviour). When we really need to synchronize on a file a Java program with same native one probably better to use other strategy:


  • One of most appropriate enterprise scale mechanism, database lock, queues ecc...
  • Advisory file locks by same external and well documented conventional mechanism, for example symbolic links in /var/lock as anyway all unix daemons usually do.

Friday, December 7, 2007

Hello...
I'm Panks... and by now I want to share my software developing experience with you...

About Me

Milano, Italy
Software Architect and Software Solution Advisor