Wednesday 29 December 2010

Parsing and Standardizing an Address using GeoGoogle API

Google provides an API to address standardization. It standardizes addresses by utilizing google's geocoding service.
GeoGoogle is a client API to google's geocoding service, if you are looking for a offline solution (which has no usage limit), take a look at http://jgeocoder.sourceforge.net

To use geocoding web service, you need sign-up for your own API key at http://www.google.com/apis/maps/signup.html

more information on http://geo-google.sourceforge.net/usage.html

here is a sample:


Friday 24 December 2010

Read a Text File from Resource JAR or Disk (Override resources with a custom file)

this sample shows how to implement a read text file in Java, the Program will first try to load file from resource jar (classes in path) and if it could not find it, then load it from given path on disk.
this is very useful if you want to implement a solution to override a resource with a customized one.

here is the program:



public class LoadFile {

    public void doLoadFile(final String fileNamethrows IOException {
        InputStream inputStream;


        //try to load file from disk
        try {
            inputStream = new FileInputStream(fileName);
        }
        catch (FileNotFoundException fe) {
            //failed, so try to load it from resources in class path
            inputStream = LoadFile.class.getClassLoader().getResourceAsStream(fileName);
            if (inputStream == null)
                throw new FileNotFoundException("could not find file: " + fileName);
        }

        // Get the object of InputStreamReader
        final InputStreamReader inputStreamReader = new InputStreamReader(inputStream);
        final BufferedReader bufferReader = new BufferedReader(inputStreamReader);

        String strLine;
        while ((strLine = bufferReader.readLine()) != null) {
            // Print the content on the console
            System.out.println(strLine);
        }

        // Close the input stream
        inputStreamReader.close();
    }
}


Wednesday 15 December 2010

Very simple Form submitting using AJAX

I wrote this module very long time ago, but I find it very simple and useful for people that want to build ajax applications quickly in their application, so I decided to publish it.

this module will be used mainly to post the content of a form and receive the response from server. it recognizes the fields and parses the server response automatically.

all you need is to include the javascript code to your page:


<script language="javascript" src="js/ajaxClass.js"></script>


and call the function at the end of your page:


function submitForm() {
ajaxObject.submitForm('myForm', 'spanResponseContainer', 'ajax-loader.gif');
}

myForm: your Form's id or name
spanResponseContainer: an Span as container for server response
ajax-loader.gif: the path to an image to show while waiting for server response, see this post if you don't know, where to get such an image.

here is the whole sample:


<html>

<head>
    <title>.:: Simple Ajax Test ::.</title>
  <script language="javascript" src="js/ajaxClass.js"></script>
</head>


<body>

<form action="/myserver/sayHello.jsp" name="myForm" method="post" onsubmit="submitForm(); return false;">
        <table>
            <tr>
                <td>Enter your name:</td>
                <td align="left">
                    <input type="text" name="textName" size="20" value="" />
                </td>
            </tr>
        </table>
      
        <input type="submit" value="send">
</form>
<br />
<br />
<span id="spanResponseContainer"></span>

<script language="JavaScript">
function submitForm() {
ajaxObject.submitForm('myForm', 'spanResponseContainer', 'ajax-loader.gif');
}
</script>

</body>
</html>


you can download the script from here

Monday 6 December 2010

Optimized search for enum lookup values

if you are mirroring Database Lookup tables in Enums in your code, you must also have a mechanism to search for those values effectively.
the first idea would be iterating the values and find the desired Enum value, but as you see below, you can optimize your code if you use a BidiMap to keep Enums and their lookup values.
Note that it is still recommended to iterate members instead of using this method, if you have less than 5 elements in your Enum.
to have a better time measurement, I used an Enum of Country names and their ISO2 Code.
the first Enum uses Iteration to find our requested ISO2 Code:



public enum CountryEnum {


Click to expand:


    EGYPT("AF"),
    EQUATORIAL_GUINEA("AF"),
    ETHIOPIA("AF"),
    AFGHANISTAN("AS"),
    ALBANIA("EU"),
    ALGERIA("AF"),
    ANGOLA("AF"),
    ANTIGUA_AND_BARBUDA("NA"),
    ARGENTINA("SA"),
    AUSTRALIA("OC"),
    BAHAMAS("NA"),
    BAHRAIN("AS"),
    BANGLADESH("AS"),
    BARBADOS("NA"),
    BELGIUM("EU"),
    BELIZE("NA"),
    BENIN("AF"),
    BERMUDA("NA"),
    BHUTAN("AS"),
    MYANMAR("AS"),
    BOLIVIA("SA"),
    BOTSWANA("AF"),
    BRAZIL("SA"),
    BRUNEI_DARUSSALAM("AS"),
    BULGARIA("EU"),
    BURKINA_FASO("AF"),
    BURUNDI("AF"),
    CHILE("SA"),
    CHINA("AS"),
    TAIWAN("AS"),
    COSTA_RICA("NA"),
    DENMARK("EU"),
    GERMANY("EU"),
    DOMINICA("NA"),
    DOMINICAN_REPUBLIC("NA"),
    DJIBOUTI("AF"),
    ECUADOR("SA"),
    COTE_D_IVOIRE("AF"),
    EL_SALVADOR("NA"),
    FALKLAND_ISLANDS("SA"),
    FIJI("OC"),
    FINLAND("EU"),
    FRANCE("EU"),
    GABON("AF"),
    GAMBIA("AF"),
    GHANA("AF"),
    GIBRALTAR("EU"),
    GRENADA("NA"),
    GREECE("EU"),
    GREAT_BRITAIN("EU"),
    GUATEMALA("NA"),
    GUINEA("AF"),
    GUINEA_BISSAU("AF"),
    GUYANA("SA"),
    HAITI("NA"),
    HONDURAS("NA"),
    INDIA("AS"),
    INDONESIA("AS"),
    IRAQ("AS"),
    IRAN("AS"),
    IRELAND("EU"),
    ICELAND("EU"),
    ISRAEL("AS"),
    ITALY("EU"),
    JAMAICA("NA"),
    JAPAN("AS"),
    YEMEN("AS"),
    TIMOR_LESTE("AS"),
    JORDAN("AS"),
    CAYMAN_ISLANDS("NA"),
    CAMEROON("AF"),
    CAMBODIA("AS"),
    CANADA("NA"),
    CAPE_VERDE("AF"),
    QATAR("AS"),
    KENYA("AF"),
    COLOMBIA("SA"),
    COMOROS("AF"),
    CONGO("AF"),
    NORTH_KOREA("AS"),
    SOUTH_KOREA("AS"),
    CUBA("NA"),
    KUWAIT("AS"),
    LAOS("AS"),
    LESOTHO("AF"),
    LEBANON("AS"),
    LIBERIA("AF"),
    LYBIA("AF"),
    LUXEMBOURG("EU"),
    MACAO("AS"),
    MADAGASCAR("AF"),
    MALAWI("AF"),
    MALAYSIA("AS"),
    MALDIVES("AS"),
    MALI("AF"),
    MALTA("EU"),
    MOROCCO("AF"),
    MAURITANIA("AF"),
    MAURITIUS("AF"),
    MEXICO("NA"),
    MONGOLIA("AS"),
    MOZAMBIQUE("AF"),
    NEPAL("AS"),
    NEW_CALEDONIA("OC"),
    NEW_ZEALAND("OC"),
    NICARAGUA("NA"),
    NETHERLANDS_ANTILLES("NA"),
    NETHERLANDS("EU"),
    NIGER("AF"),
    NIGERIA("AF"),
    NORWAY("EU"),
    AUSTRIA("EU"),
    OMAN("AS"),
    PAKISTAN("AS"),
    PANAMA("NA"),
    PAPUA_NEW_GUINEA("OC"),
    PARAGUAY("SA"),
    PERU("SA"),
    PHILIPPINES("AS"),
    POLAND("EU"),
    PORTUGAL("EU"),
    RWANDA("AF"),
    ROMANIA("EU"),
    SOLOMON_ISLANDS("OC"),
    ZAMBIA("AF"),
    SAMOA("OC"),
    SAO_TOME_AND_PRINCIPE("AF"),
    SAUDI_ARABIA("AS"),
    SWEDEN("EU"),
    SWITZERLAND("EU"),
    SENEGAL("AF"),
    SEYCHELLES("AF"),
    SIERRA_LEONE("AF"),
    ZIMBABWE("AF"),
    SINGAPORE("AS"),
    SOMALIA("AF"),
    MICRONESIA("OC"),
    SPAIN("EU"),
    SRI_LANKA("AS"),
    SAINT_KITTS_AND_NEVIS("NA"),
    SAINT_LUCIA("NA"),
    SAINT_VINCENT_AND_THE_GRENADINES("NA"),
    SUDAN("AF"),
    SOUTH_AFRICA("AF"),
    SURINAME("SA"),
    SWAZILAND("AF"),
    SYRIAN_ARAB_REPUBLIC("AS"),
    TANZANIA("AF"),
    THAILAND("AS"),
    TOGO("AF"),
    TONGA("OC"),
    TRINIDAD_AND_TOBAGO("NA"),
    CHAD("AF"),
    CZECH_REPUBLIC("EU"),
    TURKEY("AS"),
    TUNISIA("AF"),
    UGANDA("AF"),
    HUNGARY("EU"),
    URUGUAY("SA"),
    FAROE_ISLANDS("EU"),
    VENEZUELA("SA"),
    UNITED_ARAB_EMIRATES("AS"),
    USA("NA"),
    VIETNAM("AS"),
    CENTRAL_AFRICAN_REPUBLIC("AF"),
    CYPRUS("AS"),
    FRENCH_POLYNESIA("OC"),
    SAN_MARINO("EU"),
    VATICAN("EU"),
    LIECHTENSTEIN("EU"),
    MARTINIQUE("NA"),
    GUADELOUPE("NA"),
    ANDORRA("EU"),
    MONACO("EU"),
    PUERTO_RICO("NA"),
    UNITED_STATES_VIRGIN_ISLANDS("NA"),
    COOK_ISLANDS("OC"),
    VANUATU("OC"),
    NORTHERN_MARIANA_ISLANDS("OC"),
    REUNION("AF"),
    FRENCH_GUIANA("SA"),
    NAMIBIA("AF"),
    UKRAINE("EU"),
    SLOVENIA("EU"),
    CROATIA("EU"),
    SLOVAKIA("EU"),
    ESTONIA("EU"),
    RUSSIAN_FEDERATION("EU"),
    LATVIA("EU"),
    UZBEKISTAN("AS"),
    ARMENIA("AS"),
    AZERBAIJAN("AS"),
    BELARUS("EU"),
    BOSNIA_AND_HERZEGOVINA("EU"),
    ERITREA("AF"),
    GEORGIA("AS"),
    KAZAKHSTAN("AS"),
    KYRGYZ_REPUBLIC("AS"),
    KIRIBATI("OC"),
    LITHUANIA("EU"),
    MARSHALL_ISLANDS("OC"),
    MACEDONIA("EU"),
    MOLDOVA("EU"),
    NAURU("OC"),
    PALAU("OC"),
    TAJIKISTAN("AS"),
    TURKMENISTAN("AS"),
    TUVALU("OC"),
    ANGUILLA("NA"),
    MONTSERRAT("NA"),
    ARUBA("NA"),
    TURKS_AND_CAICOS_ISLANDS("NA"),
    BRITISH_VIRGIN_ISLANDS("NA"),
    GREENLAND("NA"),
    ALAND_ISLANDS("EU"),
    AMERICAN_SAMOA("OC"),
    WESTERN_SAHARA("AF"),
    GUAM("OC"),
    MONTENEGRO("EU"),
    MAYOTTE("AF"),
    NORFOLK_ISLAND("OC"),
    NIUE("OC"),
    PITCAIRN_ISLANDS("OC"),
    PALESTINIAN_TERRITORY("AS"),
    SAINT_HELENA("AF"),
    SVALBARD_AND_JAN_MAYEN_ISLANDS("EU"),
    SAINT_PIERRE_AND_MIQUELON("NA"),
    SERBIA("EU"),
    TOKELAU("OC"),
    WALLIS_AND_FUTUNA("OC"),
    ANTARCTICA("AN"),
    COCOS_ISLANDS("AS"),
    DEMOCRATIC_REPUBLIC_CONGO("AF"),
    CHRISTMAS_ISLAND("AS"),
    SOUTH_GEORGIA_AND_THE_SOUTH_SANDWICH_ISLANDS("AN"),
    FRENCH_SOUTHERN_TERRITORIES("AN");





    private final String lookupValue;

    private CountryEnum(final String idValue) {
        lookupValue = idValue;
    }

    public String getCountryValue() {
        return lookupValue;
    }

    public static CountryEnum getCountry(final String country) {
        for (final CountryEnum countryEnum : CountryEnum.values())
            if (countryEnum.getCountryValue().equalsIgnoreCase(country))
                return countryEnum;

        return null;
    }
}



here is the optimized Version which uses BidiMap to hold Enums and their lookup values:



public enum Country {


Click to expand:


    EGYPT("AF"),
    EQUATORIAL_GUINEA("AF"),
    ETHIOPIA("AF"),
    AFGHANISTAN("AS"),
    ALBANIA("EU"),
    ALGERIA("AF"),
    ANGOLA("AF"),
    ANTIGUA_AND_BARBUDA("NA"),
    ARGENTINA("SA"),
    AUSTRALIA("OC"),
    BAHAMAS("NA"),
    BAHRAIN("AS"),
    BANGLADESH("AS"),
    BARBADOS("NA"),
    BELGIUM("EU"),
    BELIZE("NA"),
    BENIN("AF"),
    BERMUDA("NA"),
    BHUTAN("AS"),
    MYANMAR("AS"),
    BOLIVIA("SA"),
    BOTSWANA("AF"),
    BRAZIL("SA"),
    BRUNEI_DARUSSALAM("AS"),
    BULGARIA("EU"),
    BURKINA_FASO("AF"),
    BURUNDI("AF"),
    CHILE("SA"),
    CHINA("AS"),
    TAIWAN("AS"),
    COSTA_RICA("NA"),
    DENMARK("EU"),
    GERMANY("EU"),
    DOMINICA("NA"),
    DOMINICAN_REPUBLIC("NA"),
    DJIBOUTI("AF"),
    ECUADOR("SA"),
    COTE_D_IVOIRE("AF"),
    EL_SALVADOR("NA"),
    FALKLAND_ISLANDS("SA"),
    FIJI("OC"),
    FINLAND("EU"),
    FRANCE("EU"),
    GABON("AF"),
    GAMBIA("AF"),
    GHANA("AF"),
    GIBRALTAR("EU"),
    GRENADA("NA"),
    GREECE("EU"),
    GREAT_BRITAIN("EU"),
    GUATEMALA("NA"),
    GUINEA("AF"),
    GUINEA_BISSAU("AF"),
    GUYANA("SA"),
    HAITI("NA"),
    HONDURAS("NA"),
    INDIA("AS"),
    INDONESIA("AS"),
    IRAQ("AS"),
    IRAN("AS"),
    IRELAND("EU"),
    ICELAND("EU"),
    ISRAEL("AS"),
    ITALY("EU"),
    JAMAICA("NA"),
    JAPAN("AS"),
    YEMEN("AS"),
    TIMOR_LESTE("AS"),
    JORDAN("AS"),
    CAYMAN_ISLANDS("NA"),
    CAMEROON("AF"),
    CAMBODIA("AS"),
    CANADA("NA"),
    CAPE_VERDE("AF"),
    QATAR("AS"),
    KENYA("AF"),
    COLOMBIA("SA"),
    COMOROS("AF"),
    CONGO("AF"),
    NORTH_KOREA("AS"),
    SOUTH_KOREA("AS"),
    CUBA("NA"),
    KUWAIT("AS"),
    LAOS("AS"),
    LESOTHO("AF"),
    LEBANON("AS"),
    LIBERIA("AF"),
    LYBIA("AF"),
    LUXEMBOURG("EU"),
    MACAO("AS"),
    MADAGASCAR("AF"),
    MALAWI("AF"),
    MALAYSIA("AS"),
    MALDIVES("AS"),
    MALI("AF"),
    MALTA("EU"),
    MOROCCO("AF"),
    MAURITANIA("AF"),
    MAURITIUS("AF"),
    MEXICO("NA"),
    MONGOLIA("AS"),
    MOZAMBIQUE("AF"),
    NEPAL("AS"),
    NEW_CALEDONIA("OC"),
    NEW_ZEALAND("OC"),
    NICARAGUA("NA"),
    NETHERLANDS_ANTILLES("NA"),
    NETHERLANDS("EU"),
    NIGER("AF"),
    NIGERIA("AF"),
    NORWAY("EU"),
    AUSTRIA("EU"),
    OMAN("AS"),
    PAKISTAN("AS"),
    PANAMA("NA"),
    PAPUA_NEW_GUINEA("OC"),
    PARAGUAY("SA"),
    PERU("SA"),
    PHILIPPINES("AS"),
    POLAND("EU"),
    PORTUGAL("EU"),
    RWANDA("AF"),
    ROMANIA("EU"),
    SOLOMON_ISLANDS("OC"),
    ZAMBIA("AF"),
    SAMOA("OC"),
    SAO_TOME_AND_PRINCIPE("AF"),
    SAUDI_ARABIA("AS"),
    SWEDEN("EU"),
    SWITZERLAND("EU"),
    SENEGAL("AF"),
    SEYCHELLES("AF"),
    SIERRA_LEONE("AF"),
    ZIMBABWE("AF"),
    SINGAPORE("AS"),
    SOMALIA("AF"),
    MICRONESIA("OC"),
    SPAIN("EU"),
    SRI_LANKA("AS"),
    SAINT_KITTS_AND_NEVIS("NA"),
    SAINT_LUCIA("NA"),
    SAINT_VINCENT_AND_THE_GRENADINES("NA"),
    SUDAN("AF"),
    SOUTH_AFRICA("AF"),
    SURINAME("SA"),
    SWAZILAND("AF"),
    SYRIAN_ARAB_REPUBLIC("AS"),
    TANZANIA("AF"),
    THAILAND("AS"),
    TOGO("AF"),
    TONGA("OC"),
    TRINIDAD_AND_TOBAGO("NA"),
    CHAD("AF"),
    CZECH_REPUBLIC("EU"),
    TURKEY("AS"),
    TUNISIA("AF"),
    UGANDA("AF"),
    HUNGARY("EU"),
    URUGUAY("SA"),
    FAROE_ISLANDS("EU"),
    VENEZUELA("SA"),
    UNITED_ARAB_EMIRATES("AS"),
    USA("NA"),
    VIETNAM("AS"),
    CENTRAL_AFRICAN_REPUBLIC("AF"),
    CYPRUS("AS"),
    FRENCH_POLYNESIA("OC"),
    SAN_MARINO("EU"),
    VATICAN("EU"),
    LIECHTENSTEIN("EU"),
    MARTINIQUE("NA"),
    GUADELOUPE("NA"),
    ANDORRA("EU"),
    MONACO("EU"),
    PUERTO_RICO("NA"),
    UNITED_STATES_VIRGIN_ISLANDS("NA"),
    COOK_ISLANDS("OC"),
    VANUATU("OC"),
    NORTHERN_MARIANA_ISLANDS("OC"),
    REUNION("AF"),
    FRENCH_GUIANA("SA"),
    NAMIBIA("AF"),
    UKRAINE("EU"),
    SLOVENIA("EU"),
    CROATIA("EU"),
    SLOVAKIA("EU"),
    ESTONIA("EU"),
    RUSSIAN_FEDERATION("EU"),
    LATVIA("EU"),
    UZBEKISTAN("AS"),
    ARMENIA("AS"),
    AZERBAIJAN("AS"),
    BELARUS("EU"),
    BOSNIA_AND_HERZEGOVINA("EU"),
    ERITREA("AF"),
    GEORGIA("AS"),
    KAZAKHSTAN("AS"),
    KYRGYZ_REPUBLIC("AS"),
    KIRIBATI("OC"),
    LITHUANIA("EU"),
    MARSHALL_ISLANDS("OC"),
    MACEDONIA("EU"),
    MOLDOVA("EU"),
    NAURU("OC"),
    PALAU("OC"),
    TAJIKISTAN("AS"),
    TURKMENISTAN("AS"),
    TUVALU("OC"),
    ANGUILLA("NA"),
    MONTSERRAT("NA"),
    ARUBA("NA"),
    TURKS_AND_CAICOS_ISLANDS("NA"),
    BRITISH_VIRGIN_ISLANDS("NA"),
    GREENLAND("NA"),
    ALAND_ISLANDS("EU"),
    AMERICAN_SAMOA("OC"),
    WESTERN_SAHARA("AF"),
    GUAM("OC"),
    MONTENEGRO("EU"),
    MAYOTTE("AF"),
    NORFOLK_ISLAND("OC"),
    NIUE("OC"),
    PITCAIRN_ISLANDS("OC"),
    PALESTINIAN_TERRITORY("AS"),
    SAINT_HELENA("AF"),
    SVALBARD_AND_JAN_MAYEN_ISLANDS("EU"),
    SAINT_PIERRE_AND_MIQUELON("NA"),
    SERBIA("EU"),
    TOKELAU("OC"),
    WALLIS_AND_FUTUNA("OC"),
    ANTARCTICA("AN"),
    COCOS_ISLANDS("AS"),
    DEMOCRATIC_REPUBLIC_CONGO("AF"),
    CHRISTMAS_ISLAND("AS"),
    SOUTH_GEORGIA_AND_THE_SOUTH_SANDWICH_ISLANDS("AN"),
    FRENCH_SOUTHERN_TERRITORIES("AN");
     



     private final String lookupValue;
     private static final BidiMap VALUE_TYPE_MAPPING = new DualHashBidiMap();

     static {
         for (final Country value : Country.values()) {
             Country.VALUE_TYPE_MAPPING.put(Country.valueOf(value.name()), value.getCountryValue());
         }
     }

     private Country(final String idValue) {
         lookupValue = idValue;
     }

     public String getCountryValue() {
         return lookupValue;
     }

     public static Country getCountry(final String country) {
         return (CountryCountry.VALUE_TYPE_MAPPING.getKey(country);
     }
}



and here is a test to compare results:



public class CountryEnumTest {

    private final static int DATA_SIZE = 1000000;
    private final static List<String> testStrings = new ArrayList<String>(DATA_SIZE);
    
    @BeforeClass
    public static void initMap() {
        System.out.println("Initializing test data ...");
        
        final Random random = new Random();
        for (int i = 0; i < DATA_SIZE; i ++) {
            final int index = random.nextInt(CountryEnum.values().length);
            final CountryEnum randomEntry = CountryEnum.values()[index];
            
            testStrings.add(randomEntry.getCountryValue());
        }
    }
    
    @Test
    public void testEnum() {
        final long startTime = System.currentTimeMillis();

        //Search values using iteration
        for (final String entry : testStrings)
            CountryEnum.getCountry(entry);
        final long elapsedTime = System.currentTimeMillis();
        System.out.println("testEnum, search by strings -> Time elapsed: " (System.currentTimeMillis() - startTime));

        //Search values using map
        for (final String entry : testStrings)
            Country.getCountry(entry);
        System.out.println("testOptimizedEnum, search by strings -> Time elapsed: " (System.currentTimeMillis() - elapsedTime));
    }
}




the optimization difference is huge, 63 milliseconds against 1015 !!


Initializing test data ...
testEnum, search by strings -> Time elapsed: 1015
testOptimizedEnum, search by strings -> Time elapsed: 63