Sunday, December 18, 2011

SWT JFace

Finally finished writing SWT simple application. The PDF and source code compressed in rar are provided below:

Friday, December 16, 2011

Subversion

I had problem with XCode 4.2 source control recently. It just keeps saying "Host unreachable". It worked perfect in XCode 3.2.5. Spending some time just to figure out what happened was completely waste of time as the Subversion Server host is 100% reachable. So I decided to download separate subversion client for mac. There are some subversion clients out there for mac but finally I choose RapidSVN and SmartSVN. Both are good and has friendly user interface.

RapidSVN can be found here. For the server I prefer VisualSVN for windows. For subversion client at windows the one and only TortoiseSVN is still unbeatable.

Tuesday, November 8, 2011

GWT 2

Finally finished writing GWT simple application. There are four docs here.
1. GWT Getting Started shows you how to create a GWT app in Eclipse.
2. GWT Client Example shows you how to create client side code in GWT.
3. GWT Server Example shows you how to create server side code in GWT.
4. GWT Advance Example shows you how to integrate GWT and some other Google libs.

Tuesday, October 18, 2011

Generic

Generic can be placed in class/interface declaration, variable declaration, method parameter or method return value.

In method return value :
public static <B> List<B> aMethod() {...} // any reference can replace B.

In method parameter :
public static <B> List<B> aMethod(B b) {...} // any reference can replace B.
public <B> void aMethod(B b) {...} // any reference can replace B
public <B extends Number> void aMethod(B b) {...} // B must be subclass of Number

In variable declaration :
List<String> list = new ArrayList<String>(); // list of String, no other type

In interface or class declaration :
interface IDao <X extends IEntity> {...} // X must be subclass of IEntity
interface IBidDao extends IDao<Bid> // Bid replaces X and Bid is subclass of IEntity
class BaseDao<X extends IEntity> implements IDao<X> // BaseDao takes X which is then substitutes X in IDao

We can put ? to replace B or X above, which also means any but with restrictions:

List<?> list = new ArrayList<Integer>(); means any class can fit in, and as for List, we can't add object to the list. In general, all of the methods in List that take the generic object as parameter are not applicable (compile error as in add, addAll, etc).

List<? extends Number> list = new ArrayList<Integer>(); means any class that extends Number can fit in, and as for List, we can't add object to the list. In general, all of the methods in List that take the generic object as parameter are not applicable (compile error as in add, addAll, etc).

List<? super Number> list = new ArrayList<Object>(); means any class on top of Number inheritance hierarchy can fit in, and as for List, we can add object to the list as opposed to <?> or <? extends Number>.

The ? and super keyword in generic only apply to variable declaration or method parameter not to class declaration:
List<? extends Number> list = new ArrayList<Integer>();
public void aMethod(List<? extends Number> list) {...}

Monday, October 10, 2011

Java Collection



List
- List of things.
1. ArrayList -> Growable array. Good for fast iteration but not for a lot of insertion and deletion.
2. Vector -> Same as ArrayList but its methods are synchronized for thread safety.
3. LinkedList -> Same as ArrayList. Good for fast insertion and deletion but not for iteration.

Set - Unique things
1. HashSet -> Collection with no duplicate objects and unpredictable iteration order.
2. LinkedHashSet -> Ordered version of HashSet, ordered in which they are inserted.
3. TreeSet -> Sorted Set by natural order using Red-Black tree structure.

Map - Things with unique ID
1. HashMap -> The simplest map class.
2. Hashtable -> Same as HashMap but its methods are synchronized for thread safety.
3. LinkedHashMap -> Ordered version of HashMap, ordered in which they are inserted.
4. TreeMap -> Sorted Map by natural order.

Queue - Things arranged by the order in which they are to be processed
1. PriorityQueue

Comparable & Comparator

When we add two objects in a collection that doesn't allow duplication as in Set, we have to override the Objet.equals() method as well as Object.hashCode() method. But now we want to make all objects in a List or array sortable, that's why we have to deal with two interfaces: Comparable and Comparator.

Comparable

Implements Comparable interface in the bean class to make the bean comparable:

public class SerializableBean implements Comparable {

private String name;

public String getName() {
return name;
}

public void setName(String name) {
this.name = name;
}

@Override
public int compareTo(SerializableBean o) {
return name.compareTo(o.name);
}
}

Now we can sort the list or array containing the beans using:

Collections.sort(list);
Arrays.sort(arr);

We can also find an index of an object inside the collection using binary search tree after sorting it:

Collections.binarySearch(list, key);
Arrays.binarySearch(arr, key);

Comparator

Create a new class that implements Comparator interface:

public class CompareByName implements Comparator {

@Override
public int compare(SerializableBean bean1, SerializableBean bean2) {
return bean1.getName().compareTo(bean2.getName());
}

}

Now we can use it to sort a list or array:

Collections.sort(list, new CompareByName());
Arrays.sort(arr, new CompareByName());

We can also find an index of an object inside the collection using binary search tree after sorting it:

Collections.binarySearch(list, key, new CompareByName());
Arrays.binarySearch(arr, key, new CompareByName());

Thursday, October 6, 2011

SCJP 6 Part IX - Formatting String with Formatter

Here is the format
%[arg_index$][flags][width][.precision]conversion_char

arg_index
An integer followed directly by a $, this indicates which argument should be printed in this position.

flags
"-" Left justify this argument
"+" Include a sign (+ or -) with this argument
"0" Pad this argument with zeroes
"," Use locale-specific grouping separators
"(" Enclose negative numbers in parentheses

width
This value indicates the minimum number of characters to print.

precision
When formatting a floating-point number, precision indicates the number of digits to print after the decimal point.

conversion_char
The type of argument we'll be formatting.
b boolean
c char
d integer
f floating point
s string

Formatter formatter = new Formatter(System.out);

// format int and use italian switzerland separator
formatter.format(new Locale("it", "ch"), "%,d", 1000000); // 1'000'000

// format int, use italian switzerland separator, and give parentheses for negative int
formatter.format(new Locale("it", "ch"), "%(,d", -1000000); // (1'000'000)

// format int, use italian switzerland separator, and put a sign on it
formatter.format(new Locale("it", "ch"), "%,+d", 1000000); // +1'000'000

SCJP 6 Part VIII - Regex With Scanner

// split string by a dot
Scanner scanner = new Scanner("my.name.is.budi");
scanner.useDelimiter("\\.");
while (scanner.hasNext()) {
System.out.println(scanner.next());
}

result:

my
name
is
budi

// split string by regex (zero or one comma) and a space
Scanner scanner1 = new Scanner("1 isn't true, 0 isn't false, 2.0 is double");
scanner1.useDelimiter("[,]? ");
while (scanner1.hasNext()) {
// is the next token can be converted to int
if (scanner1.hasNextInt()) {
System.out.println("Found int : " + scanner1.nextInt());
// is the next token can be converted to boolean
} else if (scanner1.hasNextBoolean()) {
System.out.println("Found boolean : " + scanner1.nextBoolean());
// is the next token can be converted to double
} else if (scanner1.hasNextDouble()) {
System.out.println("Found double : " + scanner1.nextDouble());
} else {
System.out.println(scanner1.next());
}
}

result:

Found int : 1
isn't
Found boolean : true
Found int : 0
isn't
Found boolean : false
Found double : 2.0
is
double

SCJP 6 Part VII - Regex

Pattern pattern = Pattern.compile("aba");
Matcher matcher = pattern.matcher("abababababababa");
while (matcher.find()) {
System.out.println("aba has been found at index : " + matcher.start() + " " + matcher.group());
}

result:

aba has been found at index : 0 aba
aba has been found at index : 4 aba
aba has been found at index : 8 aba
aba has been found at index : 12 aba

Pattern pattern1 = Pattern.compile("\\d");
Matcher matcher1 = pattern1.matcher("jatim1");
while (matcher1.find()) {
System.out.println("a digit has been found at index : " + matcher1.start() + " " + matcher1.group());
}

result:

a digit has been found at index : 5 1

Pattern pattern2 = Pattern.compile("\\s");
Matcher matcher2 = pattern2.matcher("my name is ...");
while (matcher2.find()) {
System.out.println("a space has been found at index : " + matcher2.start());
}

result:

a space has been found at index : 2
a space has been found at index : 7
a space has been found at index : 10

Pattern pattern3 = Pattern.compile("\\w");
Matcher matcher3 = pattern3.matcher("123 -> lets go");
while (matcher3.find()) {
System.out.println("a letter or a digit or an underscore has been found at index : " + matcher3.start() + " " + matcher3.group());
}

result:

a letter or a digit or an underscore has been found at index : 0 1
a letter or a digit or an underscore has been found at index : 1 2
a letter or a digit or an underscore has been found at index : 2 3
a letter or a digit or an underscore has been found at index : 7 l
a letter or a digit or an underscore has been found at index : 8 e
a letter or a digit or an underscore has been found at index : 9 t
a letter or a digit or an underscore has been found at index : 10 s
a letter or a digit or an underscore has been found at index : 12 g
a letter or a digit or an underscore has been found at index : 13 o

Pattern pattern4 = Pattern.compile("[ap]");
Matcher matcher4 = pattern4.matcher("al pacino");
while (matcher4.find()) {
System.out.println("character 'a' or 'p' has been found at index : " + matcher4.start() + " " + matcher4.group());
}


result:

character 'a' or 'p' has been found at index : 0 a
character 'a' or 'p' has been found at index : 3 p
character 'a' or 'p' has been found at index : 4 a

Pattern pattern5 = Pattern.compile("[a-l]");
Matcher matcher5 = pattern5.matcher("al pacino");
while (matcher5.find()) {
System.out.println("character 'a' until 'l' has been found at index : " + matcher5.start() + " " + matcher5.group());
}


result:

character 'a' until 'l' has been found at index : 0 a
character 'a' until 'l' has been found at index : 1 l
character 'a' until 'l' has been found at index : 4 a
character 'a' until 'l' has been found at index : 5 c
character 'a' until 'l' has been found at index : 6 i

Pattern pattern6 = Pattern.compile("[a-lA-L]");
Matcher matcher6 = pattern6.matcher("aL PaCiNo");

while (matcher6.find()) {
System.out.println("character 'a' until 'l' OR 'A' until 'L' has been found at index : " + matcher6.start() + " " + matcher6.group());
}


return:

character 'a' until 'l' OR 'A' until 'L' has been found at index : 0 a
character 'a' until 'l' OR 'A' until 'L' has been found at index : 1 L
character 'a' until 'l' OR 'A' until 'L' has been found at index : 4 a
character 'a' until 'l' OR 'A' until 'L' has been found at index : 5 C
character 'a' until 'l' OR 'A' until 'L' has been found at index : 6 i

Pattern pattern7 = Pattern.compile("\\d+");
Matcher matcher7 = pattern7.matcher("(031) 531 4249");
while (matcher7.find()) {
System.out.println("a group of digit has been found at index : " + matcher7.start() + " " + matcher7.group());
}

result (+ means one or more, \\d+ means one or more digit):

a group of digit has been found at index : 1 031
a group of digit has been found at index : 6 531
a group of digit has been found at index : 10 4249

Pattern pattern8 = Pattern.compile("0[xX]([0-9a-fA-F])+");
Matcher matcher8 = pattern8.matcher("0xffffff 0X778899 0X1 0XXX");
while (matcher8.find()) {
System.out.println("a hexadecimal has been found at index : " + matcher8.start() + " " + matcher8.group());
}

result:

a hexadecimal has been found at index : 0 0xffffff
a hexadecimal has been found at index : 9 0X778899
a hexadecimal has been found at index : 18 0X1

Pattern pattern9 = Pattern.compile("\\(\\d\\d\\d\\)([-\\s])?\\d\\d\\d([-\\s]?)\\d\\d\\d\\d");
Matcher matcher9 = pattern9.matcher("(031)-5314249, (031) 5314249, (031)5314249, (031)-531-4249, (031)-531 4249, (031) 531-42490000");
while (matcher9.find()) {
System.out.println("a valid phone number has been found at index : " + matcher9.start() + " " + matcher9.group());
}

result (? means zero or one,
([-\\s])? means zero or one either - or space):

a valid phone number has been found at index : 0 (031)-5314249
a valid phone number has been found at index : 15 (031) 5314249
a valid phone number has been found at index : 30 (031)5314249
a valid phone number has been found at index : 44 (031)-531-4249
a valid phone number has been found at index : 60 (031)-531 4249
a valid phone number has been found at index : 76 (031) 531-4249

Pattern pattern10 = Pattern.compile("[iI][nN][dD][oO]([a-zA-Z])*");
Matcher matcher10 = pattern10.matcher("Indonesia India indo123 indochina indo");
while (matcher10.find()) {
System.out.println("a string start with indo has been found at index : " + matcher10.start() + " " + matcher10.group());
}

result (* means zero or more):

a string start with indo has been found at index : 0 Indonesia
a string start with indo has been found at index : 16 indo
a string start with indo has been found at index : 24 indochina
a string start with indo has been found at index : 34 indo

Pattern pattern11 = Pattern.compile("f...");
Matcher matcher11 = pattern11.matcher("fool feel fast fame fee flash");
while (matcher11.find()) {
System.out.println(". is used to find any single char : " + matcher11.start() + " " + matcher11.group());
}

result:

. is used to find any single char : 0 fool
. is used to find any single char : 5 feel
. is used to find any single char : 10 fast
. is used to find any single char : 15 fame
. is used to find any single char : 20 fee
. is used to find any single char : 24 flas

Wednesday, October 5, 2011

SCJP 6 Part VI - Locale - NumberFormat - DateFormat

// locale italy language in country switzerland
Locale localeItalyInSwitzerland = new Locale("it", "ch");

// default DateFormat using SHORT format
DateFormat format = DateFormat.getInstance();
System.out.println("Default format : " + format.format(new Date()));

// format using date and time format.
DateFormat dateTimeFormat = DateFormat.getDateTimeInstance(DateFormat.LONG, DateFormat.MEDIUM, localeItalyInSwitzerland);
System.out.println("Date & time format : " + dateTimeFormat.format(new Date()));

// format date only
DateFormat dateFormat = DateFormat.getDateInstance(DateFormat.LONG, localeItalyInSwitzerland);
System.out.println("Date format : " + dateFormat.format(new Date()));

// format time only
DateFormat timeFormat = DateFormat.getTimeInstance(DateFormat.MEDIUM, localeItalyInSwitzerland);
System.out.println("Time format : " + timeFormat.format(new Date()));

// general-purpose number format
NumberFormat format1 = NumberFormat.getInstance(localeItalyInSwitzerland);
System.out.println("General purpose format : " + format1.format(1000000));

// general-purpose number format
NumberFormat format2 = NumberFormat.getNumberInstance(localeItalyInSwitzerland);
System.out.println("General purpose format : " + format2.format(1000000));

// currency format
NumberFormat currencyFormat = NumberFormat.getCurrencyInstance(localeItalyInSwitzerland);
System.out.println("Currency format : " + currencyFormat.format(1000000));

// integer format
NumberFormat integerFormat = NumberFormat.getIntegerInstance(localeItalyInSwitzerland);
System.out.println("Integer format : " + integerFormat.format(1000000));

// percent format
NumberFormat percentFormat = NumberFormat.getPercentInstance(localeItalyInSwitzerland);
System.out.println("Percent format : " + percentFormat.format(1000000));

Tuesday, October 4, 2011

SCJP 6 Part V - Serialization

public class SerializableBean implements Serializable {

private String name;
private Date birthDate;
private Double money;

public void setName(String name) {
this.name = name;
}

public void setBirthDate(Date birthDate) {
this.birthDate = birthDate;
}

public void setMoney(Double money) {
this.money = money;
}

public String toString() {
SimpleDateFormat format = new SimpleDateFormat("dd/MMMM/yyyy");
return name + " " + format.format(birthDate) + " " + money;
}

}

// data to be serialized
SerializableBean bean = new SerializableBean();
bean.setBirthDate(new Date());
bean.setMoney(10000000d);
bean.setName("Rochmat Santoso");

// create new file if one doesn't exist
File file = new File("myTextFile.txt");

// serialize data
FileOutputStream fileOutputStream = new FileOutputStream(file);
ObjectOutputStream objectOutputStream = new ObjectOutputStream(fileOutputStream);

objectOutputStream.writeObject(bean);
objectOutputStream.flush();
objectOutputStream.close();

fileOutputStream.flush();
fileOutputStream.close();

// deserialize data
FileInputStream fileInputStream = new FileInputStream(file);
ObjectInputStream objectInputStream = new ObjectInputStream(fileInputStream);

SerializableBean bean1 = (SerializableBean) objectInputStream.readObject();
System.out.println(bean1);
objectInputStream.close();

fileInputStream.close();

SCJP 6 Part IV - File IO

// create new file if one doesn't exist
File file = new File("myTextFile.txt");
boolean isSuccessfullyCreated = file.createNewFile();
if (isSuccessfullyCreated) {
System.out.println("File has been created successfully!");
} else {
System.out.println("Failed creating file!");
}

// create an object to write to the file, remove the old content
FileWriter fileWriter = new FileWriter(file);
fileWriter.write("New Content");
fileWriter.write("\n");
fileWriter.write("Added String");
fileWriter.flush();
fileWriter.close();

// another way to write to the file, remove the old content
PrintWriter printWriter = new PrintWriter(file);
printWriter.println("Another content");
printWriter.println("Another added content");
printWriter.flush();
printWriter.close();

// advanced way to write to the file, remove the old content
BufferedWriter bufferedWriter = new BufferedWriter(new FileWriter(file));
bufferedWriter.write("The new content");
bufferedWriter.newLine();
bufferedWriter.write("The added content");
bufferedWriter.flush();
bufferedWriter.close();

// create an object to read from the file
FileReader fileReader = new FileReader(file);
StringBuilder sb = new StringBuilder();
while (true) {
int content = fileReader.read();

if (content == -1) {
System.out.println("The content is : " + sb);
break;
} else {
sb.append((char) content);
}
}
fileReader.close();

// advanced way to read from the file
BufferedReader bufferedReader = new BufferedReader(new FileReader(file));
StringBuilder sb1 = new StringBuilder();
while (true) {
String content = bufferedReader.readLine();

if (content == null) {
System.out.println("The content is : " + sb1);
break;
} else {
sb1.append(content);
sb1.append("\n");
}
}
bufferedReader.close();

// console
Console console = System.console();

System.out.print("Type something : ");
String typed = console.readLine();
System.out.println("You typed : " + typed);

System.out.print("Type your secret : ");
String secret = String.valueOf(console.readPassword());
System.out.println("Your secret was : " + secret);

Thursday, September 29, 2011

SCJP 6 Part III

Constructor
  • Character, Byte, Short
Any integer that is passed as constructor parameter must be casted because int require memory space bigger than char, byte, or short so there could be some bits loss.
Character c1 = new Character((char) 19);
  • Long, Float, Double
Any integer can be passed to long, float, or double constructor without casting because int always fits memory of long, float, or double.
Long l1 = new Long(18);

We then can conclude that if the being passed primitive is bigger, it needs casting.
new Integer(shortObject.shortValue());
new Integer((int) shortObject.doubleValue());

Primitive
  • Character, Byte, Short
Any integer that can fit char, byte, or short memory can be referenced without casting.
char c3 = 127;
Any integer that can not fit char, byte, or short memory must be casted because there could be some bits loss.
char c5 = (char) 123456;
  • Long, Float, Double
Any integer can be referenced to long, float, or double.
long l5 = 128;

We then can conclude that if the being passed primitive is bigger, it needs casting.
float f = 90;
long l = 90;
double d = 90;
int i = (int) d;
short s = (short) f;
long l = (long) f;

Autoboxing
  • Character, Byte, Short
Any integer that can fit char, byte, or short memory can be referenced without casting.
Character c3 = 127;
Any integer that is greater than char, byte, or short bits must be casted because there could be some bits loss.
Character c5 = (char) 123456;
  • Long, Float, Double
Any integer must be casted to be referenced by long, float, or double because long has l, float has f, and double has d after int.
Long l5 = (long) 128;
Long l5 = 128l;

From autoboxing example above we can conclude that we must always cast the primitive to the appropriate format. This applies for char, byte, short, int, long, float, and double.

private void m(Double d) {...}

m(anIntObject); // compile error. Integer is not a Double
m(anIntObject.intValue); // compile error. Equal to Double d = 123;
m((double)
anIntObject.intValue); // OK
m(anIntObject.doubleValue); // OK

SCJP 6 Part II

Character c3 = 127;
Character c4 = 127;

if (c3 == c4) {
System.out.println("Literals Character less than 127 is the same character");
}

Byte b3 = 127;
Byte b4 = 127;

if (b3 == b4) {
System.out.println("Literals Byte less than 127 is the same byte");
}

Short sh3 = 127;
Short sh4 = 127;

if (sh3 == sh4) {
System.out.println("Literals Short less than 127 is the same short");
}

Integer int5 = 100;
Integer int6 = 100;

if (int5 == int6) {
System.out.println("Literals Integer less than 127 is the same integer");
}

Long l3 = (long) 127;
Long l4 = (long) 127;

if (l3 == l4) {
System.out.println("Literals Long less than 127 is the same long");
}

Float f3 = (float) 66;
Float f4 = (float) 66;

if (f3 ==f4) {
System.out.println("Literals Float is the same float");
}

Double d3 = (double) 6;
Double d4 = (double) 6;

if (d3 == d4) {
System.out.println("Literals Double is the same double");
}

Boolean bol3 = true;
Boolean bol4 = true;

if (bol3 == bol4) {
System.out.println("Literals Boolean is the same boolean");
}

Result :

Literals Character less than 127 is the same character
Literals Byte less than 127 is the same byte
Literals Short less than 127 is the same short
Literals Integer less than 127 is the same integer
Literals Long less than 127 is the same long
Literals Boolean is the same boolean

We can conclude that two different objects created by assigning primitive to it, if the primitive is between -128 and 127, they are equal object for Charater, Byte, Short, Integer, and Long but not equal for Float and Double.

Obviously, if the primitives are not between -128 and 127, they are two different objects.

SCJP 6 Part I

String str1 = new String("My name is Budi");
String str2 = new String("My name is Budi");

if (str1 == str2) {
System.out.println("Object String is the same string");
}

String str3 = "Your name is Budi";
String str4 = "Your name is Budi";

if (str3 == str4) {
System.out.println("Literals String is the same string");
}

Character c1 = new Character((char) 19);
Character c2 = new Character((char) 19);

if (c1 == c2) {
System.out.println("Object Character is the same character");
}

Byte b1 = new Byte((byte) 8);
Byte b2 = new Byte((byte) 8);

if (b1 == b2) {
System.out.println("Object Byte is the same byte");
}

Short sh1 = new Short((short) 9);
Short sh2 = new Short((short) 9);

if (sh1 == sh2) {
System.out.println("Object Short is the same short");
}

Integer int1 = new Integer(1000);
Integer int2 = new Integer(1000);

if (int1 == int2) {
System.out.println("Object Integer is the same integer");
}

Long l1 = new Long(18);
Long l2 = new Long(18);

if (l1 == l2) {
System.out.println("Object Long is the same long");
}

Float f1 = new Float(17);
Float f2 = new Float(17);

if (f1 == f2) {
System.out.println("Object Float is the same float");
}

Double d1 = new Double(5000);
Double d2 = new Double(5000);

if (d1 == d2) {
System.out.println("Object Double is the same double");
}

Boolean bol1 = new Boolean(true);
Boolean bol2 = new Boolean(true);

if (bol1 == bol2) {
System.out.println("Object Boolean is the same boolean");
}

Result : Literals String is the same string

We can conclude that two different objects with same literals are always two different objects.

Thursday, September 15, 2011

Useful Java util Classes

There are some useful classes defined in java util package. Lets visit them:

Arrays

This class contains methods for manipulating arrays (such as sorting and searching). This class also contains a static factory that allows arrays to be viewed as lists.

Integer[] array = new Integer[] {5, 3, 1, 4, 2, 4, 9};

// sort array
Arrays.sort(array);

// search integer 4 in the array and return the index using binary search algorithm
// note that the array must be in sort
int index = Arrays.binarySearch(array, 4);

// fill or replace index 2 (inclusive) until index 5 (exclusive) with integer 100
Arrays.fill(array, 2, 5, 100);

// create a List from an array
List list = Arrays.asList(array);

Collections

This class consists of methods that operate on or return collections.

List src = new ArrayList();
src.add(new Integer(5));
src.add(new Integer(3));
src.add(new Integer(1));
src.add(new Integer(4));
src.add(new Integer(2));
src.add(new Integer(4));
src.add(new Integer(9));

// reverse the order of the elements in the list
Collections.reverse(src);

// get max Integer element in the list
Integer result = Collections.max(src);

// get min Integer element in the list
Integer result = Collections.min(src);

// replace all integer 4 with integer 1000 in the list
Collections.replaceAll(src, new Integer(4), new Integer(1000));

// replace oldBean with newBean, they are compared using Object.equals() method
Collections.replaceAll(src, oldBean, newBean);

// swap objects in index 0 and 6
Collections.swap(src, 0, 6);

// replace all objects in the list with the new integer object
Collections.fill(src, new Integer(1999));

// sort objects in the list
Collections.sort(src);

// search an element in the list. The list must be sorted first
Collections.binarySearch(src, key);

// shuffle the list
Collections.shuffle(src);

StringBuffer & StringBuilder

Both classes are used to deal with string, however, StringBuffer is thread-safe because it performs thread synchronization. StringBuilder should be used when we don't need thread synchronization.

SimpleDateFormat

SimpleDateFormat is a class for formatting and parsing date (date to text and vice versa). Date and time formats are specified by date and time pattern strings.



// create SimpleDateFormat object
SimpleDateFormat format = new SimpleDateFormat("'on' dd/MMMM/yyyy");

// format date to string
String formattedDate = format.format(new Date()); // result: on 19/September/2011

// format string to date
Date date = format.parse("on 12/August/2001");

Properties

This class represents a persistent set of properties. The Properties can be saved to a stream or loaded from a stream. Each key and its corresponding value in the property list is a string.

// create Properties object
Properties properties = new Properties();

// load Properties from input stream
InputStream inStream = new FileInputStream("properties.properties");
properties.load(inStream);

// get property
String name = properties.getProperty("property.name");
String size = properties.getProperty("property.size");

// set property
properties.setProperty("property.size", "101");

// persistent property
OutputStream out = new FileOutputStream("properties.properties");
properties.store(out, "Comments here");

The content of properties file:

property.name=Rochmat Santoso
property.size=101

equals, hashCode, and toString with Apache Commons

Lets now play a little bit with Apache Commons EqualsBuilder, HashCodeBuilder, and ToStringBuilder.

ToStringBuilder

When we print an object to console, something not meaningful like [Ljava.lang.String;@a90653 will be printed. If we have an entity bean, most likely we prefer printing all of its properties in a formatted string to previous string. To achieve that, we can use ToStringBuilder class in Apache Commons Lang library.

public class MyBean {

private String name;
private String address;
private String email;

@Override
public String toString() {
return new ToStringBuilder(this).append("name", name).append("address", address).append("email", email).build();
}

}

And the result will be MyBean@a62fc3[name=Al Pacino,address=Surabaya,email=gmail].

EqualsBuilder

When we want to compare two entity beans, most likely we want to compare by properties. If both entity holds same properties, they are equal. We can use EqualsBuilder to do this.

@Override
public boolean equals(Object obj) {
if(this == obj) {
return true;
}

if((obj == null) || (obj.getClass() != this.getClass())) {
return false;
}

MyBean target = (MyBean) obj;
return new EqualsBuilder().append(this.name, target.name).append(this.address, target.address).append(this.email, target.email).isEquals();
}

HashCodeBuilder

Note that we must override the Object.hashCode() if we override Object.equals(). We can use HashCodeBuilder to create hash code for an object.

@Override
public int hashCode() {
return new HashCodeBuilder().append(this.name).append(this.address).append(this.email).toHashCode();
}

Wednesday, September 14, 2011

Enum

Since version 1.5.0, Java introduced enum as a special kind of class. It lets us to rewrite our static final constants to enum class. Here is a simple example:

public enum OrderStatus {
NEW,
COMPLETE,
BILLING_FAILED,
SHIPPED;
}

It is pretty straightforward, isn't it? Now lets put constructor, methods, and variables in it:

public enum OrderStatus {

NEW(20),
COMPLETE(100),
BILLING_FAILED(-1),
SHIPPED(80);

private int percent;

private OrderStatus(int paramPercent) {
this.percent = paramPercent;
}

public int getPercent() {
return percent;
}

}

Now what happens if we print it on console?

System.out.println(OrderStatus.NEW.name()); // this will print NEW
System.out.println(OrderStatus.NEW.getPercent()); // this will print 20
System.out.println(OrderStatus.NEW.ordinal()); // this will print 0

Note that the first statement must be the constant (NEW, COMPLETE, etc in our example), otherwise the compiler will generate error messages. In addition, the constructor can't be declared as public (that's why I declare it as private).

To get a list of all constants of the enum we can use OrderStatus.values() and it will return an array of {NEW, COMPLETE, BILLING_FAILED, SHIPPED} in that order.

Wednesday, August 24, 2011

Java Access Modifier

While waiting for the lunch time lets do something very basic but quiet interesting; Java access modifier.

There are four access modifiers in Java: public, protected, private, and package access. Suppose we have a project with package structure as below:



There are four classes:
1. A superclass for other classes named SuperClass
2. A subclass of class SuperClass named SubClassA which resides at the same package as its superclass.
3. A subclass of class SuperClass named SubClassB which resides at different package as its superclass.
4. Another class at different package named Main.



The SuperClass has all four different level access method. We will see which methods are visible at any of the other three classes.



We can see that the public, protected, and package access level methods are visible in class SubClassA through both inheritance and reference.



Now we can see that there are only public and protected methods visible to class SubClassB through inheritance and only public method visible through reference. This happens because package level access, as its name suggest, only applies for classes reside at same package. Whereas protected applies for all of its subclasses.

There is a note here regarding overriding protected method. As we can see in class SubClassB, we override method protectedMethod from its superclass. Therefore, all classes at the same package with class SubClassB can access SubClassB's protectedMethod through reference. However, if we didn't override the protectedMethod, all other classes at the same package wouldn't be able to access it at all because protectedMethod would become private in SubClassB.



For a class at another package, as we can see in class Main, can only access public methods.

The access levels are simple and clear, aren't they? All method modifiers also apply to instance variables as well. OK, now it's time to go out for lunch.

Monday, August 22, 2011

Cassandra Architecture

Apache Cassandra is not another relational database in market. Instead of using relational model, it uses key-value map to store its data. The structure is more or less can be explain as in the following picture:



Cluster: Cassandra is designed to be distributed over several nodes/machines. A cluster consists of several nodes. I've only ever used Cassandra in a single node which is my computer.

Keyspace: A cluster consists of several keyspaces. Keyspace is the place where our data reside. A keyspace could have several Column Family or Super Column Family.

Column Family and Super Column Family: Both Column Family and Super Column Family is a collection of rows, just like a table is a collection of rows in relational database.

Row: A row consists of columns; key-value columns for a row in Column Family, or Super Columns for a row in Super Column Family.

Super Column: It is sort of container of sub-columns (which are of type Key-value Column).

Key-value Column: The most basic data structure in Cassandra where the actual data is saved as byte. The behavior is a lot like Java Hash data type.

Here are examples of Cassandra data retention and retrieval:

COLUMN_FAMILY_NAME[ROW_KEY_NAME][COLUMN]

User['user1']['name'] = 'Rochmat Santoso';
User['user1']['address'] = 'Surabaya';
User['user2']['name'] = 'Barbie';
User['user2']['address'] = 'Malibu';

SUPER_COLUMN_FAMILY_NAME[ROW_KEY_NAME][SUPER_COLUMN_NAME][COLUMN]

Province['province1']['info']['name'] = 'East Java';
Province['province1']['info']['capital'] = 'Surabaya';
Province['province1']['city']['sby'] = 'Surabaya';
Province['province1']['city']['mlg'] = 'Malang';
Province['province1']['city']['sda'] = 'Sidoarjo';

Province['province2']['info']['name'] = 'West Java';
Province['province2']['info']['capital'] = 'Bandung';
Province['province2']['city']['bdg'] = 'Bandung';
Province['province2']['city']['tgr'] = 'Tangerang';

Wednesday, August 10, 2011

Annotation

Setelah sekian lama akhirnya punya waktu juga untuk mencoba annotation. Beberapa catatan untuk annotation ini adalah:
- Tambahkan @Documented agar annotation ini bisa di-generate saat membuat javadoc karena defaultnya sebuah annotation tidak di-generate oleh javadoc tool.
- Tambahkan @Retention(RetentionPolicy.RUNTIME) untuk menyimpan data-data annotation pada saat kompilasi sehingga bisa dibaca saat runtime. Jika tidak disimpan maka kita tidak bisa membacanya.
- Ada beberapa macam tipe annotation tergantung tempat di mana annotation itu akan ditempatkan misalnya di class, method, field, parameter, konstruktor, dll. Gunakan @Target(value = ElementType.TYPE) untuk annotation yang diletakkan di Class atau interface. Beberapa tipe yang lain adalah @Target(value = ElementType.METHOD) untuk annotation pada method, @Target(value = ElementType.FIELD) untuk annotation pada field, @Target(value = ElementType.PARAMETER) untuk annotation pada method parameter, dll.

Berikut ini adalah contoh annotation dan cara mengaksesnya

Friday, August 5, 2011

Lucene Analyzer

There are several analyzer available in Lucene:

WhitespaceAnalyzer: It splits text into tokens on whitespace characters. It doesn't normalize the tokens and doesn't lowercase each token.

SimpleAnalyzer: It splits tokens at non letter characters and lowercases each token. It discards numeric characters but keeps all other characters.

StopAnalyzer: It acts almost same as SimpleAnalyzer except it removes common words. By default, it removes common words specific to English (the, a, etc).

StandardAnalyzer: It is the most sophisticated core analyzer. It has quite a bit of logic to identify certain kinds of tokens such as company names, email addresses, and hostnames. It lowercases each token and removes stop words and punctuation.

KeywordAnalyzer: It treats entire text as a single token.

Monday, August 1, 2011

Lucene Field Options

Field Indexing Option

Field.Index.ANALYZED : Use analyzer to break the field's value into separate tokens and make each token searchable. This option is useful for body, title, abstract text.

Field.Index.NOT_ANALYZED : Index the field but don't analyze the string value. Instead, treat the field's value as a single token and make the token searchable. This option is useful for URL, file system path, dates, personal names, card number, phone number. This option is useful for enabling "exact match" searching.

Field.Index.NO : Don't make the field's value available for searching

Field Storing Option

Field.Store.YES : Store field's value in the index. This option is useful for fields that we want to display along with the search result such as URL, title, database primary key. Without storing the field's value, we won't be able to retrieve it using document.get("fieldname") on searching.

Field.Store.NO : Don't store the field's value in the index. This option is often used along with Field.Index.ANALYZED to index large text field such as text body.

Here are some example of field indexing and field storing option:

Analyzed & Stored : title, abstract text
Analyzed & Not Stored : body
Not Analyzed & Stored : URL, file system path, dates, personal names, card number, phone number
No Index & Stored : database primary key
Not Analyzed & Not Stored : hidden keywords

Code Example:

Document document = new Document();
document.add(new Field("filename", file.getName(), Field.Store.YES, Field.Index.NOT_ANALYZED));
indexWriter.addDocument(document );

Tuesday, July 19, 2011

AI and Thread Pool Code Example

Finally uploaded some examples of Breadth-first search, Depth-first search, Best-first search, Genetic Algorithm, Binary search tree, Backward and forward chaining code. Also, I tried to create simple thread pool because I found this pooling idea is very interesting and widely used.

Monday, July 18, 2011

Is it crossroad?

Recently, I have been watching Al Pacino's speech when he won the Academy Award in 1992. He said "I've been very lucky I've found desire for what I do early in my life and have people who encourage that desire."

I also kept Johnny Carson's farewell statement on final Tonight Show. He said "I am one of the lucky people in the world, I found something I always wanted to do, and I have enjoyed every single minute of it."

Steve Jobs also said the same thing. He gave a speech at Stanford Commencement, he said "I was lucky I found what I loved to do early in life... Your work is going to fill a large part of your life, and the only way to be truly satisfied is to do what you believe is great work. And the only way to do great work is to love what you do. If you haven't found it yet, keep looking. Don't settle. As with all matters of the heart, you'll know when you find it. And, like any great relationship, it just gets better and better as the years roll on. So keep looking until you find it. Don't settle."

They got me thinking about my life too, about what my desire is. I have to admit that being a software engineer was not my desire (there was no kid back in 1990s in my school who wanted to be a software engineer I suppose, we usually want to be doctor, pilot, president, etc :p). Software engineering was popular when I was at high school, computers and cellphones were becoming trend back in old days (I'm feeling so old when writing this hahaha...). I then chose to enter Informatics because I want to learn more about computer science. I knew I love math and science, and because I knew that the basic of computer is math logical expression, I thought it shouldn't be a big deal. But I realize it is not my desire to be a software engineer.

I know that great people are them who always follow their hearth and do what they love because you have to love what you do to be great. I wonder if Al Pacino, Steve Jobs, or Johnny Carson ever came to this point of life, at the searching point of their desire. Anyway, what ever it is I am now, all I know is that I always have passion in learning anything new. I always do the best for my job. I learn many new Java frameworks. I love writing and sharing thought and knowledge with others, and I still hope someday I will find what my desire is, either it is in IT field or something else.

Thursday, July 14, 2011

AOP - Notes on Advice

An advice has the following syntax:
advice_type([arg]) : pointcut_name { advice_body }

There are three types of Advice
1. Before, the advice is executed right before the join point code is executed.

Example of a before advice:

/** pointcut */
private pointcut getNameField() : get(private String edu.mat.hello.MessageCommunicator.name);

/** advice */
before() : getNameField() {
System.out.println("Getter method is about to call.");
}

2. After, the advice is executed right after the join point code is executed.

/** pointcut */
private pointcut setNameField() : set(private String edu.mat.hello.MessageCommunicator.name);

/** advice: this advise is executed whether setNameField() returns normally or throwing exception */
after() : setNameField() {
System.out.println("Name has been set.");
}

/** advice: this advise is executed only when setNameField() returns successfully */
after() returning : setNameField() {
System.out.println("Name has been set.");
}

To get the returned object, we can use after() returning(Integer count) : calculateRevenue() {...}

/** advice: this advise is executed only when setNameField() throws exception */
after() throwing : setNameField() {
System.out.println("Name has not been set.");
}

To get the thrown exception, we can use after() throwing (Exception e) : calculateRevenue() {...}

3. Around, this advice is useful to intercept an execution of a join point.

Suppose we have the following pointcut:

private pointcut sayHello(edu.mat.hello.MessageCommunicator caller, String person) : call(* edu.mat.hello.MessageCommunicator.sayHello(String, String)) && args(person, String) && target(caller);

The above pointcut says that we will capture all join points in sayHello(String, String) method of class MessageCommunicator, capture the method caller (target object as shown in target(caller)) and first parameter of the method (as shown in args(person, String)) as stated in pointcut's arguments.

Then we have an advice as in:

void around(edu.mat.hello.MessageCommunicator caller, String person) : sayHello(caller, person) {
try {
proceed(caller, "Pak " + person);
} catch (Exception e) {

} finally {
System.out.println("Say hello finally finished.");
}
}

there, we execute the real join point code in proceed(caller, "Pak " + person); and surround it with try-catch block. The arguments in proceed must match arguments in around().

Tuesday, July 12, 2011

AOP - Notes on Pointcuts

A pointcut has the following syntax: [access specifier] pointcut pointcut-name([args]) : pointcut-definition.

There are five parts of a pointcut as shown above:
1. access specifier
2. pointcut keyword
3. pointcut name
4. pointcut arguments
5. pointcut definition

Pointcut definition consists of pointcut type and pointcut signature, it can be seen as defined-join-point to be captured. To keep things simple, lets list some of the most commonly used pointcut type:

1. execution(MethodSignature) : Method or constructor execution, i.e. execution(public void edu.mat.hello.MessageCommunicator.deliverGlobalMessage(String)) which means capture all join point on the execution of method deliverGlobalMessage in class MessageCommunicator.

2. call(MethodSignature) : Method or constructor call, i.e. call(public void edu.mat.hello.MessageCommunicator.deliverGlobalMessage(String)) which means capture all join points on the calling of method deliverGlobalMessage in class MessageCommunicator.

3. staticinitialization(TypeSignature) : Class initialization, i.e. staticinitialization(edu.mat.hello.MessageCommunicator) which means capture all join points on MessageCommunicator class loading.

4. get(FieldSignature) : Field read access, i.e. get(private String edu.mat.hello.MessageCommunicator.name) which means capture all join points on getter method of private variable name in class MessageCommunicator.

5. set(FieldSignature) : Field write access, i.e. set(private String edu.mat.hello.MessageCommunicator.name) which means capture all join points on setter method of private variable name in class MessageCommunicator.

6. handler(TypeSignature) : Exception handler execution.

7. initialization(ConstructorSignature) : Object initialization, i.e. initialization(public edu.mat.hello.MessageCommunicator.new()) which means capture all join points on object MessageCommunicator creation.

8. within(TypePattern) : Capture join points in a scope, i.e. !within(AccountAspect) && !within(edu.mat.hello.MessageCommunicator) && !within(MessageCommunicatorAspect) which means capture all join points outside AccountAspect aspect and MessageCommunicator class and also outside MessageCommunicatorAspect aspect.

A pointcut could have arguments as shown in the pointcut syntax above. We can capture the values of the arguments using args. For example: private pointcut sayMyName(String person) : call(* edu.mat.hello.MessageCommunicator.sayMyName(String, String)) && args(person, String); which means capture all pointcuts in sayMyName method of class MessageCommunicator and grab first argument (named person) as shown in args(person, String).

We can also capture the caller of being executed join point using target. For example we have the following pointcut private pointcut setNameField() : set(private String edu.mat.hello.MessageCommunicator.name); and private pointcut targetObject(edu.mat.hello.MessageCommunicator object) : target(object) && setNameField();.

In the first pointcut we want to capture all join points on setter method of name variable on class MessageCommunicator. In the second pointcut, we want to capture all join points on previous pointcut (when name variable is set) and grab the MessageCommunicator object which calls that setter method, that is the target.

Database Index, a little action leads to better performance

When you run a query and it happens to run very slow against a certain table, you start thinking that your fellow who created the query must have created a buggy query. Later, when you scan your database tables, you then find that the table has no index at all. Take a deep breath and start creating indexes on columns which are accessed a lot in queries, for example, primary keys, foreign keys, and columns that are used often in the where and order clauses. After that, don't forget to say sorry for blaming your fellow and start complaining your DBA :D.

Monday, July 11, 2011

Entity Object Locking

Object locking is required to avoid concurrency problem in an application. Generally speaking, there are two types of object locking: Pessimistic Locking and Optimistic Locking.

Pessimistic locking is a locking strategy where we prevent users from doing certain things. Here is an example of pessimistic locking:

User A performs update action on an entity object, then user A gets write lock on the being updated entity object. At almost concurrent time, user B performs update action on the same entity object, then user B's action is rejected since the entity object's write lock is being hold by user A.

JPA doesn't support this strategy because it has many disadvantages. It can make the application slower because certain action have to wait for entity object's lock to be released.

Optimistic locking is a locking strategy where we will use object comparison to decide whether a certain transaction will be committed or rolled back. Here is an example of optimistic locking:

When a user performs update action on an entity object, he/she will retrieve a copy of that entity object. Changes are made to the copy object, not the original. When the user is about to save it to database, application checks whether data have been updated since the user retrieved it. If no update has been made, the user gets entity object's write lock, then the data is committed. Otherwise, it is rejected.

JPA support this strategy. It is implemented by adding a column to the table for the entity to save a version number. Every time the row is updated, the version number is incremented. It is by comparing that version number the update action is committed or rejected.

Monday, July 4, 2011

Oracle Toplink + PostgreSQL = nightmare

Banyak masalah yang muncul ketika memakai Oracle Toplink sebagai persistence provider dan PostgreSQL sebagai databasenya, antara lain:
1. Tidak mau menjalankan sequence. Solusi:

package edu.mat.client;

import oracle.toplink.essentials.platform.database.PostgreSQLPlatform;
import oracle.toplink.essentials.queryframework.ValueReadQuery;
import oracle.toplink.essentials.sessions.DatabaseSession;

public class PostgreSQLPlatformSupportingSequences extends PostgreSQLPlatform {

/**
*
*/
private static final long serialVersionUID = -2637524409846222203L;

public boolean shouldNativeSequenceAcquireValueAfterInsert() {
return false;
}

public void platformSpecificSequencingInitialization(DatabaseSession session) {
}

public ValueReadQuery buildSelectQueryForNativeSequence(String seqName,
Integer size) {
ValueReadQuery selectQuery = new ValueReadQuery();
selectQuery.setSQLString("select nextval(\'" + seqName + "\')");
return selectQuery;
}

}

Terus tambahkan di persistence.xml <property name="toplink.target-database" value="edu.mat.client.PostgreSQLPlatformSupportingSequences"/>

2. Muncul error Problem with sequence setup increment does not match its pre-allocation size. Solusi: Ubah current-value di sequence menjadi 100, dan increment-value menjadi genap semisal dua.

3. Data byte dengan annotation @Lob seperti

@Column(name = "PICTURE", table = "USER_PICTURES")
@Lob
@Basic(fetch = FetchType.LAZY)
public final byte[] getPicture() {
return picture;
}

harus didefinisikan dengan tipe oid di PostgreSQL

Thursday, May 19, 2011

JAXP & JAXB

JAXP = Java API for XML Processing (SAX, DOM, StaX)

JAXP is for processing XML data using applications written in Java. JAXP leverages the parser standards Simple API for XML Parsing (SAX) and Document Object Model (DOM) so that you can choose to parse your data as a stream of events or to build an object representation of it. JAXP also implements the Streaming API for XML (StAX) standard.

SAX is a standard interface for event-based XML parsing. It reports parsing events (such as the start and end of elements) directly to the application through callbacks, the application implements handlers to deal with the different events. It supports read-only access, that is, SAX is designed only for reading XML documents. Of course, we could write a new document out as a result of event, but we cannot change the document being processed.

SAX is fast and efficient, but its event model makes it most useful for such state-independent filtering. For example, a SAX parser calls one method in your application when an element tag is encountered and calls a different method when text is found. If the processing you are doing is state-independent (meaning that it does not depend on the elements that have come before), then SAX works fine.

On the other hand, for state-dependent processing, where the program needs to do one thing with the data under element A but something different with the data under element B, then a pull parser such as the Streaming API for XML (StAX) would be a better choice.

StAX provides a streaming, event-driven, pull-parsing API for reading and writing XML documents. StAX offers a simpler programming model than SAX and more efficient memory management than DOM.

Pull Parsing versus Push Parsing

Streaming pull parsing refers to a programming model in which a client application calls methods on an XML parsing library when it needs to interact with an XML infoset—that is, the client only gets (pulls) XML data when it explicitly asks for it.

Streaming push parsing refers to a programming model in which an XML parser sends (pushes) XML data to the client as the parser encounters elements in an XML infoset—that is, the parser sends the data whether or not the client is ready to use it at that time.

Pull parsers and the SAX API both act like a serial I/O stream. You see the data as it streams in, but you cannot go back to an earlier position or leap ahead to a different position. In general, such parsers work well when you simply want to read data and have the application act on it.
But when you need to modify an XML structure - especially when you need to modify it interactively - an in-memory structure makes more sense. DOM is one such model.

Generally speaking, there are two programming models for working with XML infosets: streaming and the document object model (DOM).

The DOM model involves creating in-memory objects representing an entire document tree and the complete infoset state for an XML document. Once in memory, DOM trees can be navigated freely and parsed arbitrarily, and as such provide maximum flexibility for developers. However, the cost of this flexibility is a potentially large memory footprint and significant processor requirements, because the entire representation of the document must be held in memory as objects for the duration of the document processing. This may not be an issue when working with small documents, but memory and processor requirements can escalate quickly with document size.

Streaming refers to a programming model in which XML infosets are transmitted and parsed serially at application runtime, often in real time, and often from dynamic sources whose contents are not precisely known beforehand. Moreover, stream-based parsers can start generating output immediately, and infoset elements can be discarded and garbage collected immediately after they are used. While providing a smaller memory footprint, reduced processor requirements, and higher performance in certain situations, the primary trade-off with stream processing is that you can only see the infoset state at one location at a time in the document.

Streaming models for XML processing are particularly useful when your application has strict memory limitations, as with a cellphone running the Java Platform, Micro Edition (Java ME platform), or when your application needs to process several requests simultaneously, as with an application server.

JAXB = Java API for XML Binding

JAXB provides a fast and convenient way to create a two-way mapping between XML documents and Java objects. What XML data-binding does is to create Java classes from schema definition. That is, the XML schema can be compiled to generate corresponding Java classes.And once the class is generated for the XML schema, a XML document which follows the syntax of the schema can be represented as an instance of the generated class. The process of converting XML document to a corresponding high-level Java object is called "un-marshalling" while the reverse is called "marshalling".

Here is some example I provide:

Wednesday, April 6, 2011

Encode URL and Decode Google Translate's Response in Objective C

I've been working on a project that needs to get a translation from google translate web service. There are some codes in google code that can help you doing this. However, I found some problems regarding string encoding.

I used to encode the string with NSUTF8StringEncoding, but it doesn't encode character & into %26 or + into %2B so I had to encode it manually.

NSString* urlEncodedText = [text stringByAddingPercentEscapesUsingEncoding:NSUTF8StringEncoding];
urlEncodedText = [CommonUtil encodeCharacters:urlEncodedText];

+ (NSString*) encodeCharacters:(NSString*) string {
NSMutableDictionary* dict = [[NSMutableDictionary alloc] init];
[dict setObject:@"%26" forKey:@"&"];
[dict setObject:@"%2B" forKey:@"+"];

NSArray* keys = [dict allKeys];
for (int i = 0; i < [keys count]; i++) {
NSString* key = [keys objectAtIndex:i];
string = [string stringByReplacingOccurrencesOfString:key withString:[dict objectForKey:key]];
}

return string;
}

The same thing happens when I get the translation. I get &amp; instead of &, &quot; instead of " (double quote), etc so I had to manually decode it.

+ (NSString *) decodeCharacters:(NSString *)string {
NSMutableDictionary* dict = [[NSMutableDictionary alloc] init];
[dict setObject:@"&" forKey:@"&amp;"];
[dict setObject:@"\"" forKey:@"
&quot;"];
[dict setObject:@"'" forKey:@"
&#39;"];
[dict setObject:@"<" forKey:@"
&lt;"];
[dict setObject:@">" forKey:@"
&gt;"];

NSArray* keys = [dict allKeys];
for (int i = 0; i < [keys count]; i++) {
NSString* key = [keys objectAtIndex:i];
string = [string stringByReplacingOccurrencesOfString:key withString:[dict objectForKey:key]];
}

return string;
}
 

©2009 Stay the Same | by TNB