void chain(StringTokenizer st) {
   if (iNext != null) {
     iNext.chain(st);
   } else {
     iNext = new Zone(iName, st);
   }
 }
  public void parseDataFile(BufferedReader in) throws IOException {
    Zone zone = null;
    String line;
    while ((line = in.readLine()) != null) {
      String trimmed = line.trim();
      if (trimmed.length() == 0 || trimmed.charAt(0) == '#') {
        continue;
      }

      int index = line.indexOf('#');
      if (index >= 0) {
        line = line.substring(0, index);
      }

      // System.out.println(line);

      StringTokenizer st = new StringTokenizer(line, " \t");

      if (Character.isWhitespace(line.charAt(0)) && st.hasMoreTokens()) {
        if (zone != null) {
          // Zone continuation
          zone.chain(st);
        }
        continue;
      } else {
        if (zone != null) {
          iZones.add(zone);
        }
        zone = null;
      }

      if (st.hasMoreTokens()) {
        String token = st.nextToken();
        if (token.equalsIgnoreCase("Rule")) {
          Rule r = new Rule(st);
          RuleSet rs = iRuleSets.get(r.iName);
          if (rs == null) {
            rs = new RuleSet(r);
            iRuleSets.put(r.iName, rs);
          } else {
            rs.addRule(r);
          }
        } else if (token.equalsIgnoreCase("Zone")) {
          zone = new Zone(st);
        } else if (token.equalsIgnoreCase("Link")) {
          iLinks.add(st.nextToken());
          iLinks.add(st.nextToken());
        } else {
          System.out.println("Unknown line: " + line);
        }
      }
    }

    if (zone != null) {
      iZones.add(zone);
    }
  }