Tuesday, September 8, 2015

GeoCoding API - Google Integration


GeoCoding API - Google Integration




1.) Google provides lot of API's, with GeoCoding one of them.

Complete documentation can be read from here

You need a key to access the API's. GeoCoding Api is available for both Developers(Free version) and Commercial purpose (License version).

For Free version, go to Google Developers Console

Create a project by choosing GeoCoding API, and generate the key.

 Integration through HttpClient with Google Maps dependency

Piece of Code to start with

URIBuilder url = new URIBuilder(
                    "https://maps.googleapis.com/maps/api/geocode/json?")
                    .addParameter("components", "country:IN")
                    .addParameter("address", searchText)
                    .addParameter("key", apiKey);


where components  is for filtering, is available in the documentation.
           searchText is what user wants to search
           Key is what you have generated, has to be a part of url.
           Json is specified for the output form, can be XML also


RequestConfig requestConfig = RequestConfig.custom().setConnectTimeout(connectionTimeout).build();
            HttpClient client = HttpClientBuilder.create().setDefaultRequestConfig(requestConfig).build();
           
            HttpGet httpRequest;
            httpRequest = new HttpGet(url.build());

            HttpResponse response = client.execute(httpRequest);
            HttpEntity responseEntity = response.getEntity();

String responseText = EntityUtils.toString(responseEntity);

Output responseTextis in the form of json, you can now filter out the results.


Using Google Maps Dependency

Add below in your Pom.xml


       <dependency>

              <groupId>com.google.maps</groupId>
              <artifactId>google-maps-services</artifactId>
              <version>0.1.7</version>
       </dependency> 


AreaZipcodeCityState.java


package com.project;

public class    {
    private Long zipCode;
    private String areaName;
    private String cityName;
    private String stateName;
    public Long getZipCode() {
        return zipCode;
    }
    public void setZipCode(Long zipCode) {
        this.zipCode = zipCode;
    }
    public String getAreaName() {
        return areaName;
    }
    public void setAreaName(String areaName) {
        this.areaName = areaName;
    }
    public String getCityName() {
        return cityName;
    }
    public void setCityName(String cityName) {
        this.cityName = cityName;
    }
    public String getStateName() {
        return stateName;
    }
    public void setStateName(String stateName) {
        this.stateName = stateName;
    }
    public AreaZipcodeCityState(Long zipCode, String areaName, String cityName, String stateName) {
        this.zipCode = zipCode;
        this.areaName = areaName;
        this.cityName = cityName;
        this.stateName = stateName;
    }
    public AreaZipcodeCityState() {
    }
   
}
 



GoogleIntegration.java

package com.project;


import java.util.ArrayList;
import java.util.List;
import com.google.maps.GeoApiContext;
import com.google.maps.GeocodingApi;
import com.google.maps.GeocodingApi.ComponentFilter;
import com.google.maps.GeocodingApiRequest;
import com.google.maps.model.AddressComponent;
import com.google.maps.model.GeocodingResult;
import com.google.maps.model.LatLng;

public class GoogleIntegration {
    private static String API_KEY="";
    private static String COUNTRY_FILTER="IN";
    private static Long DEFAULT_ZIPCODE=Long.valueOf(0);
    private static String DEFAULT_CITY="";
    private static String DEFAULT_AREA="";
    private static String DEFAULT_STATE="";
   
    private static String city = "administrative_area_level_2";
    private static String state = "administrative_area_level_1";
    private static String locality = "locality";
    private static String zipCode = "postal_code";
    private static String neighborhood = "neighborhood";
    private static String premise = "premise";
    private static String sublocality = "sublocality";
    private static String sublocality_level_4 = "sublocality_level_4";
    private static String sublocality_level_3 = "sublocality_level_3";
    private static String sublocality_level_2 = "sublocality_level_2";
    private static String sublocality_level_1 = "sublocality_level_1";
    private static String street_address = "street_address";
    public static List<AreaZipcodeCityState> getGoogleResult(String inputAddress) {
        String address = inputAddress.toLowerCase();
        GeoApiContext context = new GeoApiContext().setApiKey(API_KEY);
        GeocodingApiRequest request = GeocodingApi.newRequest(context);
        request.components(ComponentFilter.country(COUNTRY_FILTER));
        // request.resultType(AddressType.LOCALITY);
        // request.resultType(AddressType.PREMISE);
        request.address(address);

        try {
            ArrayList<AreaZipcodeCityState> resultList = new ArrayList<AreaZipcodeCityState>();
            GeocodingResult[] results = request.await();
            // AddressComponentType type=enum ADMINISTRATIVE_AREA_LEVEL_1;
            for (GeocodingResult result : results) {
                    AreaZipcodeCityState areaZipcodeCityState = new AreaZipcodeCityState(DEFAULT_ZIPCODE,DEFAULT_AREA,DEFAULT_CITY,DEFAULT_STATE);
                    Long zipCode=getZipcodeFromLatLon(context, result.geometry.location);
                    if(zipCode!=null)
                            areaZipcodeCityState.setZipCode(zipCode);
                    for (AddressComponent addressComponent : result.addressComponents) {
                       
                        if (addressComponent.types[0].name().equalsIgnoreCase(city)) {
                            areaZipcodeCityState.setCityName(addressComponent.longName);
                       
                        } else if (addressComponent.types[0].name().equalsIgnoreCase(state)) {
                            areaZipcodeCityState.setStateName(addressComponent.longName);
                       
                        } else if (
                                (addressComponent.types[0].name().equalsIgnoreCase(locality) && addressComponent.longName
                                .toLowerCase().contains(address))
                                || (addressComponent.types[0].name().equalsIgnoreCase(neighborhood)
                                && addressComponent.longName.toLowerCase().contains(address))
                                ||(addressComponent.types[0].name().equalsIgnoreCase(premise)
                                && addressComponent.longName.toLowerCase().contains(address))
                                || (addressComponent.types[0].name().equalsIgnoreCase(sublocality)
                                && addressComponent.longName.toLowerCase().contains(address))
                                || (addressComponent.types[0].name().equalsIgnoreCase(sublocality_level_4)
                                && addressComponent.longName.toLowerCase().contains(address))
                                || (addressComponent.types[0].name().equalsIgnoreCase(sublocality_level_3)
                                && addressComponent.longName.toLowerCase().contains(address))
                                || (addressComponent.types[0].name().equalsIgnoreCase(sublocality_level_2)
                                && addressComponent.longName.toLowerCase().contains(address))
                                || (addressComponent.types[0].name().equalsIgnoreCase(sublocality_level_1)
                                && addressComponent.longName.toLowerCase().contains(address))
                                || (addressComponent.types[0].name().equalsIgnoreCase(street_address)
                                && addressComponent.longName.toLowerCase().contains(address))
                                ) {
                            areaZipcodeCityState.setAreaName(addressComponent.longName);
                        }
                    }
                    resultList.add(areaZipcodeCityState);
            }
            return resultList;
        } catch (Exception e) {
            System.out.println(e.getMessage());
            return null;
        }
       
    }

    public static Long getZipcodeFromLatLon(GeoApiContext context, LatLng latLon) {
        GeocodingApiRequest request = GeocodingApi.reverseGeocode(context, latLon);
        try {
            GeocodingResult[] results = request.await();
            for (GeocodingResult reverseGeocodingResult : results) {
                for (AddressComponent addressComponent : reverseGeocodingResult.addressComponents) {
                    if (addressComponent.types[0].name().equalsIgnoreCase(zipCode)) {
                        return Long.valueOf(addressComponent.longName);
                    }
                }
            }
        } catch (Exception e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
        return null;

    }

   
}



Concept of reverse GeoCoding

If the search results returned does not contain the zipcodes, then we can make use of Reverse GeoCoding, using lat/long's.

public static Long getZipcodeFromLatLon(GeoApiContext context, LatLng latLon) {
        GeocodingApiRequest request = GeocodingApi.reverseGeocode(context, latLon);
        try {
            GeocodingResult[] results = request.await();
            for (GeocodingResult reverseGeocodingResult : results) {
                for (AddressComponent addressComponent : reverseGeocodingResult.addressComponents) {
                    if (addressComponent.types[0].name().equalsIgnoreCase(zipCode)) {
                        return Long.valueOf(addressComponent.longName);
                    }
                }
            }
        } catch (Exception e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
        return null;

    }

Sunday, November 23, 2014

Java Objects to XML and XML to Java Objects - XStream

Java Objects to XML and XML to Java Objects with XStream

 

 import java.io.File; 
 import java.io.FileReader; 
 import java.io.FileWriter; 
 import java.io.IOException; 
 import java.util.Iterator; 
 import java.util.List; 
 import com.thoughtworks.xstream.XStream; 

 public final class XStreamTranslator { 
     private XStream xstream = null; 
     private XStreamTranslator(){ 
         xstream = new XStream(); 
         xstream.ignoreUnknownElements(); 

     /** 
      * Convert a any given Object to a XML String 
      * @param object 
      * @return 
      */ 
     public String toXMLString(Object object) { 
         return xstream.toXML(object);  
     } 
     /** 
      * Convert given XML to an Object 
      * @param xml 
      * @return 
      */ 
     public Object toObject(String xml) { 
         return (Object) xstream.fromXML(xml); 
     } 
     /** 
      * return this class instance 
      * @return 
      */ 
     public static XStreamTranslator getInstance(){ 
         return new XStreamTranslator(); 
     } 
     /** 
      * convert to Object from given File  
      * @param xmlFile 
      * @return 
      * @throws IOException  
      */ 
     public Object toObject(File xmlFile) throws IOException { 
         return xstream.fromXML(new FileReader(xmlFile)); 
     } 
     /** 
      * create XML file from the given object with custom file name 
      * @param fileName  
      * @param file 
      * @throws IOException  
      */ 
     public void toXMLFile(Object objTobeXMLTranslated, String fileName ) throws IOException { 
         FileWriter writer = new FileWriter(fileName); 
         xstream.toXML(objTobeXMLTranslated, writer); 
         writer.close(); 
     } 
     public void toXMLFile(Object objTobeXMLTranslated, String fileName, List omitFieldsRegXList) throws IOException { 
         xstreamInitializeSettings(objTobeXMLTranslated, omitFieldsRegXList); 
         toXMLFile(objTobeXMLTranslated, fileName);     
     }     
     /** 
      * @ 
      * @param objTobeXMLTranslated 
      */ 
     public void xstreamInitializeSettings(Object objTobeXMLTranslated, List omitFieldsRegXList) { 
         if(omitFieldsRegXList != null && omitFieldsRegXList.size() > 0){ 
             Iterator itr = omitFieldsRegXList.iterator(); 
             while(itr.hasNext()){ 
                 String omitEx = itr.next(); 
                 xstream.omitField(objTobeXMLTranslated.getClass(), omitEx); 
             } 
         }  
     } 
     /** 
      * create XML file from the given object, file name is generated automatically (class name) 
      * @param objTobeXMLTranslated 
      * @throws IOException 
      * @throws XStreamTranslateException  
      */ 
     public void toXMLFile(Object objTobeXMLTranslated) throws IOException { 
         toXMLFile(objTobeXMLTranslated,objTobeXMLTranslated.getClass().getName()+".xml"); 
     }

 

  public static Document readFromXml(String input) throws InvalidDataException {
        try {
            return DocumentBuilderFactory.newInstance().newDocumentBuilder().parse(IOUtils.toInputStream(input));
        } catch (Exception e) {
            throw new
Exception("Exception occured while converting input String into document", e);
        }
    }  

// Intialize Java object and create XML

 public static String initializeAndWriteToXml(Object objectToWrite) {
        final XStream xstream = new XStream() {
            @Override
            protected MapperWrapper wrapMapper(final MapperWrapper next) {
                return new HibernateMapper(next);
            }
        };
        xstream.registerConverter(new HibernateProxyConverter());
        xstream.registerConverter(new HibernatePersistentCollectionConverter(xstream.getMapper()));
        xstream.registerConverter(new HibernatePersistentMapConverter(xstream.getMapper()));
        xstream.registerConverter(new HibernatePersistentSortedMapConverter(xstream.getMapper()));
        xstream.registerConverter(new HibernatePersistentSortedSetConverter(xstream.getMapper()));

        return xstream.toXML(objectToWrite);
    }

// Return class object

  public static <T> T readFromXml(String xmlContent, Class<T> targetObjectClass) {
        return targetObjectClass.cast(xstream.fromXML(xmlContent));
    }

 }

Thursday, November 20, 2014

JSON to HashMap - Parsing JSON String

Recursivey Parsing JSON String to HashMap


Json String can contain JsonArray, JsonObject etc.

package com.test;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;

import org.codehaus.jettison.json.JSONArray;
import org.codehaus.jettison.json.JSONObject;

public class TestJson{

    public static void main(String args[]) throws Exception {
        JSONObject jsonObject = new JSONObject(
                "{\"A\":\"M1\",\"Data\":[ {\"B\":[{ \"B1\":\"111\",\"B2\":\"Warning \"},{ \"B1\":\"222\",\"B2\":\"Warning \"}],\"C\":[{\"c1\":\"IL2\",\"c2\":\"[0.750183,0.00933380975964486]\"},{\"c1\":\"IL1b\",\"c2\":\"[0.750183,-1.5216938335421]\"}]}]}");
        System.out.println(getMap(jsonObject));
    }

    private static Map getMap(JSONObject object) {
        Map<String, Object> map = new HashMap<String, Object>();

        Object jsonObject = null;
        String key = null;
        Object value = null;

        try {
            Iterator<String> keys = object.keys();
            while (keys.hasNext()) {

                key = null;
                value = null;

                key = keys.next();

                if (null != key && !object.isNull(key)) {
                    value = object.get(key);
                }

                if (value instanceof JSONObject) {
                    map.put(key, getMap((JSONObject) value));
                    continue;
                }

                if (value instanceof JSONArray) {
                    JSONArray array = ((JSONArray) value);
                    List list = new ArrayList();
                    for (int i = 0 ; i < array.length() ; i++) {
                        jsonObject = array.get(i);
                        if (jsonObject instanceof JSONObject) {
                            list.add(getMap((JSONObject) jsonObject));
                        } else {
                            list.add(jsonObject);
                        }
                    }
                    map.put(key, list);
                    continue;
                }

                map.put(key, value);
            }
        } catch (Exception e) {
            System.out.println(e);
        }
        return map;
    }
}


How to avoid extra POJO's / Classes

package com.package;

import java.io.IOException;
import java.util.ArrayList;
import java.util.List;

import org.codehaus.jackson.JsonParseException;
import org.codehaus.jackson.map.JsonMappingException;
import org.codehaus.jackson.map.ObjectMapper;
import org.codehaus.jackson.map.type.TypeFactory;

public class Test{

    public static void main(String[] args) {

        String json = "[{\"givenName\": \"Adrienne H.\",\"surname\": \"Kovacs\"},{\"givenName\": \"Philip\",\"surname\": \"Moons\"}]";
        ObjectMapper mapper = new ObjectMapper();
        List<Author> list = new ArrayList<Author>();
        try {
            list = mapper.readValue(json, TypeFactory.defaultInstance().constructCollectionType(List.class, Author.class));
        } catch (JsonParseException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        } catch (JsonMappingException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        } catch (IOException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }

        System.out.println(list);
    }
}
 
So here i do not need to map List<Author> inside any other class.

Tuesday, November 18, 2014

Validate Date against given Date Format

How to validate given Date against Date Format.

SO there are two approaches,

1.) Using SimpleDateFormat

2.) Using Regex.


Basic Example.

SimpleDateFormat 
 
Date date = null;
    boolean checkformat;
    try {
        SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy/dd/MM");
        dateFormat.setLenient(false);
        date = dateFormat.parse("2013/25/09");
    } catch (ParseException ex) {
        ex.printStackTrace();
    }
    if (date == null) {
        checkformat = false;
    } else {
        checkformat = true;
    }

    System.out.println(checkformat);
 
 
Regex based  
 
public static void main(String[] args) throws ParseException {
        String input = "2014/12/31";
        boolean checkformat;
        if (input.matches("([0-9]{4})/([0-9]{2})/([0-9]{2})")) // for yyyy/MM/dd format
            checkformat = true;
        else
            checkformat = false;

        System.out.println(checkformat);
    } 
 
Play around the {2}, {2}, {4} values inside curly braces to prepare regex.
 
Complexity Increases, let say i have many Date Formats.
 
 
public class DateUtil {
 
    // List of all date formats that we want to parse.
    // Add your own format here.
    private static List<SimpleDateFormat>;
            dateFormats = new ArrayList<SimpleDateFormat>() {{
            add(new SimpleDateFormat("M/dd/yyyy"));
            add(new SimpleDateFormat("dd.M.yyyy"));
            add(new SimpleDateFormat("M/dd/yyyy hh:mm:ss a"));
            add(new SimpleDateFormat("dd.M.yyyy hh:mm:ss a"));
            add(new SimpleDateFormat("dd.MMM.yyyy"));
            add(new SimpleDateFormat("dd-MMM-yyyy"));
        }
    };
 
   /**
     * Convert String with various formats into java.util.Date
     *
     * @param input
     *            Date as a string
     * @return java.util.Date object if input string is parsed
     *          successfully else returns null
     */
 
 
public static Date convertToDate(String input) {
        Date date = null;
        if(null == input) {
            return null;
        }
        for (SimpleDateFormat format : dateFormats) {
            try {
                format.setLenient(false);
                date = format.parse(input);
            } catch (ParseException e) {
                //Shhh.. try other formats
            }
            if (date != null) {
                break;
            }
        }
 
        return date;
    }
 


// Test class to test out
public class TestDateUtil {
 
    public static void main(String[] args) {
        System.out.println("10/14/2012" + " = " + DateUtil.convertToDate("10/14/2012"));
        System.out.println("10-Jan-2012" + " = " + DateUtil.convertToDate("10-Jan-2012"));
        System.out.println("01.03.2002" + " = " + DateUtil.convertToDate("01.03.2002"));
        System.out.println("12/03/2010" + " = " + DateUtil.convertToDate("12/03/2010"));
        System.out.println("19.Feb.2011" + " = " + DateUtil.convertToDate("19.Feb.2011" ));
        System.out.println("4/20/2012" + " = " + DateUtil.convertToDate("4/20/2012"));
        System.out.println("some string" + " = " + DateUtil.convertToDate("some string"));
        System.out.println("123456" + " = " + DateUtil.convertToDate("123456"));
        System.out.println("null" + " = " + DateUtil.convertToDate(null));
 
    }  
}
 

Java Design Pattern - Factory pattern

Background information

This pattern introduces loose coupling between classes which is the most important principle one should consider and apply while designing the application architecture. Loose coupling can be introduced in application architecture by programming against abstract entities rather than concrete implementations. This not only makes our architecture more flexible but also less fragile.
A picture is worth thousand words. Lets see how a factory implementation will look like.

Above class diagram depicts a common scenario using example of car factory which is able to build 3 types of cars i.e. small, sedan and luxury. Building a car requires many steps from allocating accessories to final makeup. These steps can be written in programming as methods and should be called while creating an instance of a specific car type.
If we are unfortunate then we will create instances of car types (e.g. SmallCar) in our application classes and thus we will expose the car building logic to outside world and this is certainly not good. It also prevents us in making changes to car making process because code in not centralized, and making changes in all composing classes seems not feasible.

Implementation

So far we have seen the classes need to be designed for making a CarFactory. Lets hit the keyboard now and start composing our classes.
CarType.java will hold the types of car and will provide car types to all other classes

package designPatterns.factory;

public enum CarType {
    SMALL, SEDAN, LUXURY
}

Car.java is parent class of all car instances and it will also contain the common logic applicable in car making of all types.

package designPatterns.factory;

public abstract class Car {

    public Car(CarType model) {
        this.model = model;
        arrangeParts();
    }

    private void arrangeParts() {
        // Do one time processing here
    }

    // Do subclass level processing in this method
    protected abstract void construct();

    private CarType model = null;

    public CarType getModel() {
        return model;
    }

    public void setModel(CarType model) {
        this.model = model;
    }
}

 LuxuryCar.java is concrete implementation of car type LUXURY

package designPatterns.factory;

public class LuxuryCar extends Car {

    LuxuryCar() {
        super(CarType.LUXURY);
        construct();
    }

    @Override
    protected void construct() {
        System.out.println("Building luxury car");
        // add accessories
    }
}

SmallCar.java is concrete implementation of car type SMALL

package designPatterns.factory;

public class SmallCar extends Car {

    SmallCar() {
        super(CarType.SMALL);
        construct();
    }

    @Override
    protected void construct() {
        System.out.println("Building small car");
        // add accessories
    }
}

SedanCar.java is concrete implementation of car type SEDAN

package designPatterns.factory;

public class SedanCar extends Car {

    SedanCar() {
        super(CarType.SEDAN);
        construct();
    }

    @Override
    protected void construct() {
        System.out.println("Building sedan car");
        // add accessories
    }
}

CarFactory.java is our main class implemented using factory pattern. It instantiates a car instance only after determining its type.

package designPatterns.factory;

public class CarFactory {
    public static Car buildCar(CarType model) {
        Car car = null;
        switch (model) {
        case SMALL:
            car = new SmallCar();
            break;

        case SEDAN:
            car = new SedanCar();
            break;

        case LUXURY:
            car = new LuxuryCar();
            break;

        default:
            // throw some exception
            break;
        }
        return car;
    }
}

 In TestFactoryPattern.java, we will test our factory code. Lets run this class.

package designPatterns.factory;

public class TestFactoryPattern {
    public static void main(String[] args) {
        System.out.println(CarFactory.buildCar(CarType.SMALL));
        System.out.println(CarFactory.buildCar(CarType.SEDAN));
        System.out.println(CarFactory.buildCar(CarType.LUXURY));
    }
}

Output:

Building small car
designPatterns.factory.SmallCar@7c230be4
Building sedan car
designPatterns.factory.SedanCar@60e1e567
Building luxury car
designPatterns.factory.LuxuryCar@e9bfee2

As you can see, factory is able to return any type of car instance it is requested for. It will help us in making any kind of changes in car making process without even touching the composing classes i.e. classes using CarFactory.

Advantages of factory pattern

By now, you should be able to count the main advantages of using factory pattern. Lets note down:
  • The creation of an object precludes its reuse without significant duplication of code.
  • The creation of an object requires access to information or resources that should not be contained within the composing class.
  • The lifetime management of the generated objects must be centralized to ensure a consistent behavior within the application.