Link to home
Start Free TrialLog in
Avatar of CyanBlue
CyanBlueFlag for United States of America

asked on

Help me understand this class so that I can modify it?

Hi...  :)

I am following this blog post and try to update the class to get different data from the XML file...
   http://www.smnirven.com/?p=39

This is the actual call to the Geocoder class from the ReverseGeocodeLookupTask class...
localityName = Geocoder.reverseGeocode(currentLocation);

Open in new window

The Geocoder class then calls Google Maps API to get the XML back...
InputStreamReader isr =  new InputStreamReader(connection.getInputStream());
InputSource source = new InputSource(isr);
SAXParserFactory factory = SAXParserFactory.newInstance();
SAXParser parser = factory.newSAXParser();
XMLReader xr = parser.getXMLReader();
GoogleReverseGeocodeXmlHandler handler = new GoogleReverseGeocodeXmlHandler();

xr.setContentHandler(handler);
xr.parse(source);

localityName = handler.getLocalityName();

Open in new window

I see that it is calling GoogleReverseGeocodeXmlHandler class, which is shown below, but I don't really understand how this class works...
public class GoogleReverseGeocodeXmlHandler extends DefaultHandler
{
    private boolean inLocalityName = false;
    private boolean finished = false;
    private StringBuilder builder;
    private String localityName;
   
    public String getLocalityName()
    {
        return this.localityName;
    }
   
    @Override
    public void characters(char[] ch, int start, int length)
           throws SAXException {
        super.characters(ch, start, length);
        if (this.inLocalityName && !this.finished)
        {
            if ((ch[start] != '\n') && (ch[start] != ' '))
            {
                builder.append(ch, start, length);
            }
        }
    }

    @Override
    public void endElement(String uri, String localName, String name)
            throws SAXException
    {
        super.endElement(uri, localName, name);
       
        if (!this.finished)
        {
            if (localName.equalsIgnoreCase("LocalityName"))
            {
                this.localityName = builder.toString();
                this.finished = true;
            }
           
            if (builder != null)
            {
                builder.setLength(0);
            }
        }
    }

    @Override
    public void startDocument() throws SAXException
    {
        super.startDocument();
        builder = new StringBuilder();
    }

    @Override
    public void startElement(String uri, String localName, String name, Attributes attributes) throws SAXException
    {
        super.startElement(uri, localName, name, attributes);
       
        if (localName.equalsIgnoreCase("LocalityName"))
        {
            this.inLocalityName = true;
        }
    }
}

Open in new window

The XML output looks like this...
<?xml version="1.0"?>
<AddressDetails xmlns="urn:oasis:names:tc:ciq:xsdschema:xAL:2.0" Accuracy="8">
	<Country>
		<CountryNameCode>US</CountryNameCode>
		<CountryName>USA</CountryName>
		<AdministrativeArea>
			<AdministrativeAreaName>CA</AdministrativeAreaName>
			<SubAdministrativeArea>
				<SubAdministrativeAreaName>Santa Clara</SubAdministrativeAreaName>
				<Locality>
					<LocalityName>Mountain View</LocalityName>
					<Thoroughfare>
						<ThoroughfareName>1600 Amphitheatre Pkwy</ThoroughfareName>
					</Thoroughfare>
					<PostalCode>
						<PostalCodeNumber>94043</PostalCodeNumber>
					</PostalCode>
				</Locality>
			</SubAdministrativeArea>
		</AdministrativeArea>
	</Country>
</AddressDetails>

Open in new window

What I'd like to do is to get both localityName and countryNameCode at the same time...  
What I am not able to find is 'what' variable contains the whole XML string and how this GoogleReverseGeocodeXmlHandler class works since I don't see anything like a constructor and whatnot...

Thank you very much...  :)

CyanBlue
Avatar of CyanBlue
CyanBlue
Flag of United States of America image

ASKER

My attempt was to call it twice like this where the handler.getLocalityName() somehow becomes null...
   localityName = handler.getCountryNameCode();
   localityName += " : " + handler.getLocalityName();

I've also attached my attempt on the GoogleReverseGeocodeXmlHandler class below...

Thanks...

CyanBlue
package com.example.geocoding;

import org.xml.sax.Attributes;
import org.xml.sax.SAXException;
import org.xml.sax.helpers.DefaultHandler;

public class GoogleReverseGeocodeXmlHandler extends DefaultHandler 
{
	private boolean finished = false;
	
	private StringBuilder builder1;
	private String countryNameCode;
	private boolean inCountryNameCode = false;
	
	private StringBuilder builder2;
	private String localityName;
	private boolean inLocalityName = false;
	
	public String getCountryNameCode()
	{
		return this.countryNameCode;
	}
	
	public String getLocalityName()
	{
		return this.localityName;
	}
	
	@Override
	public void characters(char[] ch, int start, int length)
			throws SAXException {
		super.characters(ch, start, length);
		
		if (this.inCountryNameCode && !this.finished)
		{
			if ((ch[start] != '\n') && (ch[start] != ' '))
			{
				builder1.append(ch, start, length);
			}
		}
		
		if (this.inLocalityName && !this.finished)
		{
			if ((ch[start] != '\n') && (ch[start] != ' '))
			{
				builder2.append(ch, start, length);
			}
		}
	}
	
	@Override
	public void endElement(String uri, String localName, String name)
			throws SAXException 
	{
		super.endElement(uri, localName, name);
		
		if (!this.finished)
		{
			if (localName.equalsIgnoreCase("CountryNameCode"))
			{
				this.countryNameCode = builder1.toString();
				this.finished = true;
			}
			
			if (builder1 != null)
			{
				builder1.setLength(0);
			}
			
			if (localName.equalsIgnoreCase("LocalityName"))
			{
				this.localityName = builder2.toString();
				this.finished = true;
			}
			
			if (builder2 != null)
			{
				builder2.setLength(0);
			}
		}
	}
	
	@Override
	public void startDocument() throws SAXException 
	{
		super.startDocument();
		builder1 = new StringBuilder();
		builder2 = new StringBuilder();
	}
	
	@Override
	public void startElement(String uri, String localName, String name, Attributes attributes) throws SAXException
	{
		super.startElement(uri, localName, name, attributes);
		
		if (localName.equalsIgnoreCase("CountryNameCode"))
		{
			this.inCountryNameCode = true;
		}
		
		if (localName.equalsIgnoreCase("LocalityName"))
		{
			this.inLocalityName = true;
		}
	}
}

Open in new window

ASKER CERTIFIED SOLUTION
Avatar of CEHJ
CEHJ
Flag of United Kingdom of Great Britain and Northern Ireland image

Link to home
membership
This solution is only available to members.
To access this solution, you must be a member of Experts Exchange.
Start Free Trial
Awesome...  Now I understand(sorta) how those methods works and all...  Appreciate it...  ;)

CyanBlue
:)