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

public class GetMillionCities2 {

  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 = null;
    String country = null;
    int population = -1;
    public void setName(String n) { if (name == null) name = n; }
    public void setCountry(String code) { this.country = code; }
    // note: all PCDATA/CDATA values are strings!
    public void setPopulation(String pop) { this.population = new Integer(pop); }
  }
  // continue next page



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

    // digester.addObjectCreate("*/city", City.class);
    digester.addRule("*/city", new ObjectCreateRule(City.class){
      public void begin(String namespace, String name, Attributes attrs) throws Exception {
          digester.push(new City());  // equivalent: super.begin(namespace, name, attrs);
          System.out.println("BEGIN: " + digester.peek() + digester.peek(1)); }
      public void end(String namespace, String name) throws Exception {
          System.out.println("END: " + digester.peek());
          // if (((City)digester.peek()).population > 1000000) {...}
          digester.pop();  // equivalent: super.end(namespace,name);
          System.out.println("ENDEND: " + digester.peek()); }
    } );

    // digester.addSetNext("*/city", "addCity");
    digester.addRule("*/city", new Rule(){
	    public void begin(String namespace, String name, Attributes attrs) throws Exception {}
      public void end(String namespace, String name) throws Exception {
          System.out.println("ADD: " + digester.peek(0) + digester.peek(1));
          ((CityCollection)(digester.peek(1))).addCity((City)digester.peek(0)); }
    } );

    digester.addSetProperties("*/city", "country", "country");
    digester.addBeanPropertySetter("*/city/name");
    digester.addCallMethod("*/city/population", "setPopulation", 1);
    digester.addCallParam("*/city/population", 0);

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

