Wednesday, July 15, 2009

Implementing Jtable Sorting + Currency Rounding + Comma Separation

Illustrating one of the test cases where you have to sort the currency values in the JTable without losing precision.

Some facts:
1. Double values rounds off decimal values leading to loss of precision in Currency values
2. Only Double can show numerics (having decimal points) in Currency format (Comma separated values)
3. JTable when given String representation of Double values cannot recognize it as Double by itself.
4. There are no direct apis in Double to control decimal limits and round off

Due to above list of limitations, it is bit complex to implement all the three functionalities together. But there is a workaround/solution for this. See the code below:


package testing;

import java.text.DecimalFormat;
import java.text.NumberFormat;
import java.util.Comparator;
import javax.swing.JFrame;
import javax.swing.JScrollPane;
import javax.swing.JTable;
import javax.swing.table.DefaultTableModel;
import javax.swing.table.TableModel;
import javax.swing.table.TableRowSorter;

/**
*
* @author vijay
*/
public class JTableSortDemo {

public static void main(String[] args) throws Exception {
// Decimal format to define the required format with #Fraction digits
DecimalFormat df = (DecimalFormat) NumberFormat.getInstance();
df.setMinimumFractionDigits(6);
df.setMaximumFractionDigits(10);

// Heeaders
String columnNames[] = {"Expected (String value)", "Double (Formatted Numeric) Value", "Double without formatting(has roundoff)"};

// Input values
String[] strKeys = {"6304482644123.000003", "6304482644.4012", "63044.00", "1235482644.95", "1235482644.10", "1235482644.00"};
double[] dDatas = {6304482644123.000003, 6304482644.4012, 63044.00, 1235482644.95, 1235482644.10, 1235482644.00};

Object[][] data = new Object[dDatas.length][columnNames.length];
String strDF = null;
for (int i = 0; i < dDatas.length; i++) {
strDF = df.format(dDatas[i]);
data[i] = new Object[]{strKeys[i], df.format(dDatas[i]), dDatas[i]};
}

// Creating tablemodel
TableModel model = new DefaultTableModel(data, columnNames) {

public Class getColumnClass(int column) {
return getValueAt(0, column).getClass();
}
};

Comparator comparator = new Comparator() {

public int compare(String s1, String s2) {
Double dbl1 = Double.valueOf(s1.replaceAll(",", ""));
Double dbl2 = Double.valueOf(s2.replaceAll(",", ""));
return dbl1.compareTo(dbl2);
}
};


// Create table and associate sorter
JTable table = new JTable(model);
TableRowSorter sorter = new TableRowSorter(model);

// 1 is the column where the fraction values are not lost
sorter.setComparator(1, comparator);
table.setRowSorter(sorter);

JScrollPane scrollPane = new JScrollPane(table);

// Add table to container
JFrame frame = new JFrame("Sorting Table");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.add(scrollPane);
frame.setSize(300, 200);
frame.setVisible(true);
frame.pack();
}
}


The solution incorporated in above code is to write user defined comparator which converts the String values to double (only during comparison).

In detail:

i) Use the DecimalFormat to retain the decimal values to 'n' number of digits using
setMinimumFractionDigits();
setMaximumFractionDigits();


ii) After applying the decimal format, we will have a string shown in the JTable (with comma).


iii) Now while sorting the particular column(2nd column in above sample), we can override the the default functionality of comparator of TableRowSorter class. Default behaviour is to sort it as String. The solution is to write a comparator like below and set it to the TableRowSorter.


Comparator comparator = new Comparator() {
public int compare(String s1, String s2) {
Double dbl1 = Double.valueOf(s1.replaceAll(",", ""));
Double dbl2 = Double.valueOf(s2.replaceAll(",", ""));
return dbl1.compareTo(dbl2);
}
};


Above code chunk, removes comma and converts it to double only for comparison and then returns the result.

Tuesday, July 14, 2009

OpenSSO and Agent Installation

Here is my blog post about OpenSSO and Agent Installation in Glassfish: http://blogs.sun.com/vijayanand/entry/opensso_and_agent_installation_in

Monday, July 13, 2009

Calculate Cipher Size

Calculating Cipher Size for Symmetric algo.:
If you are using "DES/CBC/PKCS5Padding" cipher instance, and using cipher api like:
int doFinal(byte[] input, int inputOffset, int inputLen, byte[] output, int outputOffset)
you may want to think about what cipher text size calculation should be used for this. Because the output byte require a fixed length before encrypt/decrypt.

Solution: If plain text size is x and Encryption block size is y then

Size of CipherText = x + y - (x mod y)

The resulting ciphertext size is computed as the size of the plaintext extended to the next block. If padding is used and the size of the plaintext is an exact multiple of the block size, one extra block containing padding information will be added.

Source: http://www.obviex.com/Articles/CiphertextSize.aspx

Tuesday, July 07, 2009

Fedora Linux Essential

Fedora Linux Essentials:

> You can open a terminal from the current directory (from GUI for browsing folders). "Open terminal here" Nautilius script:
http://www.cyberciti.biz/faq/linux-gnome-open-terminal-shell-prompt-here/

> Given a rpm file, can do Local install without checking for dependencies.
yum localinstall --nogpgcheck .rpm

> Power saving mode in linux:
http://lesswatts.org/tips/wireless.php#pm
http://lesswatts.org/tips/wireless.php#bt

> 64bit flash for linux:
http://download.macromedia.com/pub/labs/flashplayer10/libflashplayer-10.0.22.87.linux-x86_64.so.tar.gz

> Nero for linux
http://www.brothersoft.com/d.php?soft_id=59627&url=http%3A%2F%2Ffiles.brothersoft.com%2Fdvd_video%2Fdvd_burner%2Fneroforlinux3.zip

> Fedora wireless for dell inspiron 1525: http://www.cenolan.com/2008/11/rpm-install-broadcom-wireless-sta-driver-fedora/

> Audio packages:
yum install ffmpeg ffmpeg-libs ffmpeg2theora gstreamer-ffmpeg
http://techchorus.net/index.php?q=how-play-music-and-video-fedora-10

> Synchronize date from terminal: ntpdate 0.pool.ntp.org

> Enabling root login for fedora:
Edit /etc/pam.d/gdm file as root user and comment the below line
#auth required pam_succeed_if.so user != root quiet

> Install adobe reader in fedora:
yum install AdobeReader_enu.i486

> set proxy:

For convenience, put this line in a file, say "/usr/bin/setproxy" and do
chmod +x /usr/bin/setproxy
Next time you set this with command "setproxy"