import java.io.IOException;
import java.io.File;
import java.net.URL;
import java.util.HashSet;
import org.apache.commons.digester3.Digester;
import org.apache.commons.digester3.ObjectCreateRule;
import org.xml.sax.Attributes;

public class PrintMillionCities {

  public static class CityCollection extends HashSet<City>  {
      public void addCity(City c) {
        if (c.population > 1000000) this.add(c); System.out.println("ADD TO COLL " + c.name);}
  }
  public static void listCities(CityCollection cities) {
      for (City c : cities) {
         System.out.println(c.name + " " + c.country + " " + c.population); }
  }

  public static class City {
    String name;
    String country = null;
    int population = -1;
    public void setName(String name) { this.name = name; }
    public void setCountry(String code) { this.country = code; }
    // note: all PCDATA/CDATA values are strings!
    public void makePopulation(String pop) {
	System.out.println("***");
        this.population = new Integer(pop); }
  }
  // continue next page

  public static void main(String[] args) {
    File res = new File("mondial.xml");
    final Digester digester = new Digester();
    digester.push(new CityCollection());
    System.out.println("INIT: " + digester.peek());

    digester.addBeanPropertySetter("mondial/country/city/name");

    digester.addCallMethod("mondial/country/city/population", "makePopulation", 1);
    digester.addCallParam("mondial/country/city/population", 0);

    //digester.addObjectCreate("mondial/country/city", City.class);
    
    digester.addRule("mondial/country/city", new ObjectCreateRule(City.class){
            // at begin() by default put new City instance on stack,
            // overwrite end() method to print city object's data:
            public void begin(String namespace, String name, Attributes attrs) throws Exception {
                super.begin(namespace,name,attrs);
		System.out.println("BEGIN: " + digester.peek() + digester.peek(1) + ((City)(digester.peek())).name); }
            public void end(String namespace, String name) throws Exception {
                System.out.println("END: " + ((City)(digester.peek())).population + ((City)(digester.peek())).country + ((City)(digester.peek())).name);
		if (((City)digester.peek()).population > 1000000)
		    System.out.println("END: " + ((City)(digester.peek())).name); // <<<<<<<<<<<<<<<<<<<<<
                super.end(namespace,name); 
                System.out.println("ENDEND: " + digester.peek()); }
       } );
    // wird (bei endElement) zuerst verarbeitet, vor dem 
    digester.addSetNext("mondial/country/city", "addCity");
    
    // note: reacts only on cities as direct children of countries
    // */city would take all cities,
    // country//city and country/*/city are not allowed;
    digester.addSetProperties("mondial/country/city", "country", "country");

    try {
        digester.setValidating(false);
        final CityCollection cities = digester.parse(res);
        System.out.println("####  now listing cities #### ");
        listCities(cities);
      } catch (Exception e) { e.printStackTrace(); }
  }
}
