1 /*
   2  * Copyright (c) 2000, 2018, Oracle and/or its affiliates. All rights reserved.
   3  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
   4  *
   5  * This code is free software; you can redistribute it and/or modify it
   6  * under the terms of the GNU General Public License version 2 only, as
   7  * published by the Free Software Foundation.
   8  *
   9  * This code is distributed in the hope that it will be useful, but WITHOUT
  10  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
  11  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
  12  * version 2 for more details (a copy is included in the LICENSE file that
  13  * accompanied this code).
  14  *
  15  * You should have received a copy of the GNU General Public License version
  16  * 2 along with this work; if not, write to the Free Software Foundation,
  17  * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
  18  *
  19  * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
  20  * or visit www.oracle.com if you need additional information or have any
  21  * questions.
  22  */
  23 
  24 import java.io.BufferedReader;
  25 import java.io.FileReader;
  26 import java.io.FileNotFoundException;
  27 import java.io.IOException;
  28 import java.util.ArrayList;
  29 import java.util.HashMap;
  30 import java.util.HashSet;
  31 import java.util.List;
  32 import java.util.Map;
  33 import java.util.Set;
  34 import java.util.StringTokenizer;
  35 
  36 /**
  37  * Zone holds information corresponding to a "Zone" part of a time
  38  * zone definition file.
  39  *
  40  * @since 1.4
  41  */
  42 class Zone {
  43     // zone name (e.g., "America/Los_Angeles")
  44     private String name;
  45 
  46     // zone records
  47     private List<ZoneRec> list;
  48 
  49     // target zone names for this compilation
  50     private static Set<String> targetZones;
  51 
  52     /**
  53      * Constructs a Zone with the specified zone name.
  54      * @param name the zone name
  55      */
  56     Zone(String name) {
  57         this.name = name;
  58         list = new ArrayList<ZoneRec>();
  59     }
  60 
  61     /**
  62      * Reads time zone names to be generated, called "target zone
  63      * name", from the specified text file and creats an internal hash
  64      * table to keep those names. It's assumed that one text line
  65      * contains a zone name or comments if it starts with
  66      * '#'. Comments can't follow a zone name in a single line.
  67      * @param fileName the text file name
  68      */
  69     static void readZoneNames(String fileName) {
  70         if (fileName == null) {
  71             return;
  72         }
  73         BufferedReader in = null;
  74         try {
  75             FileReader fr = new FileReader(fileName);
  76             in = new BufferedReader(fr);
  77         } catch (FileNotFoundException e) {
  78             Main.panic("can't open file: " + fileName);
  79         }
  80         targetZones = new HashSet<String>();
  81         String line;
  82 
  83         try {
  84             while ((line = in.readLine()) != null) {
  85                 line = line.trim();
  86                 if (line.length() == 0 || line.charAt(0) == '#') {
  87                     continue;
  88                 }
  89                 if (!targetZones.add(line)) {
  90                     Main.warning("duplicated target zone name: " + line);
  91                 }
  92             }
  93             in.close();
  94         } catch (IOException e) {
  95             Main.panic("IO error: "+e.getMessage());
  96         }
  97     }
  98 
  99     /**
 100      * Determines whether the specified zone is one of the target zones.
 101      * If no target zones are specified, this method always returns
 102      * true for any zone name.
 103      * @param zoneName the zone name
 104      * @return true if the specified name is a target zone.
 105      */
 106     static boolean isTargetZone(String zoneName) {
 107         if (targetZones == null) {
 108             return true;
 109         }
 110         return targetZones.contains(zoneName);
 111     }
 112 
 113     /**
 114      * Forces to add "MET" to the target zone table. This is because
 115      * there is a conflict between Java zone name "WET" and Olson zone
 116      * name.
 117      */
 118     static void addMET() {
 119         if (targetZones != null) {
 120             targetZones.add("MET");
 121         }
 122     }
 123 
 124     /**
 125      * @return the zone name
 126      */
 127     String getName() {
 128         return name;
 129     }
 130 
 131     /**
 132      * Adds the specified zone record to the zone record list.
 133      */
 134     void add(ZoneRec rec) {
 135         list.add(rec);
 136     }
 137 
 138     /**
 139      * @param index the index at which the zone record in the list is returned.
 140      * @return the zone record specified by the index.
 141      */
 142     ZoneRec get(int index) {
 143         return list.get(index);
 144     }
 145 
 146     /**
 147      * @return the size of the zone record list
 148      */
 149     int size() {
 150         return list.size();
 151     }
 152 
 153     /**
 154      * Resolves the reference to a rule in each zone record.
 155      * @param zi the Zoneinfo object with which the rule reference is
 156      * resolved.
 157      */
 158     void resolve(Zoneinfo zi) {
 159         for (int i = 0; i < list.size(); i++) {
 160             ZoneRec rec = list.get(i);
 161             rec.resolve(zi);
 162         }
 163     }
 164 }