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.util.ArrayList; 25 import java.util.HashMap; 26 import java.util.LinkedList; 27 import java.util.List; 28 import java.util.Map; 29 import java.util.Set; 30 import java.util.TreeMap; 31 import java.util.TreeSet; 32 33 /** 34 * <code>Mappings</code> generates two Maps and a List which are used by 35 * javazic BackEnd. 36 * 37 * @since 1.4 38 */ 39 class Mappings { 40 // All aliases specified by Link statements. It's alias name to 41 // real name mappings. 42 private Map<String,String> aliases; 43 44 private List<Integer> rawOffsetsIndex; 45 46 private List<Set<String>> rawOffsetsIndexTable; 47 48 // Zone names to be excluded from rawOffset table. Those have GMT 49 // offsets to change some future time. 50 private List<String> excludeList; 51 52 /** 53 * Constructor creates some necessary instances. 54 */ 55 Mappings() { 56 aliases = new TreeMap<String,String>(); 57 rawOffsetsIndex = new LinkedList<Integer>(); 58 rawOffsetsIndexTable = new LinkedList<Set<String>>(); 59 } 60 61 /** 62 * Generates aliases and rawOffsets tables. 63 * @param zi a Zoneinfo containing Zones 64 */ 65 void add(Zoneinfo zi) { 66 Map<String,Zone> zones = zi.getZones(); 67 68 for (String zoneName : zones.keySet()) { 69 Zone zone = zones.get(zoneName); 70 String zonename = zone.getName(); 71 int rawOffset = zone.get(zone.size()-1).getGmtOffset(); 72 73 // If the GMT offset of this Zone will change in some 74 // future time, this Zone is added to the exclude list. 75 boolean isExcluded = false; 76 for (int i = 0; i < zone.size(); i++) { 77 ZoneRec zrec = zone.get(i); 78 if ((zrec.getGmtOffset() != rawOffset) 79 && (zrec.getUntilTime(0) > Time.getCurrentTime())) { 80 if (excludeList == null) { 81 excludeList = new ArrayList<String>(); 82 } 83 excludeList.add(zone.getName()); 84 isExcluded = true; 85 break; 86 } 87 } 88 89 if (!rawOffsetsIndex.contains(new Integer(rawOffset))) { 90 // Find the index to insert this raw offset zones 91 int n = rawOffsetsIndex.size(); 92 int i; 93 for (i = 0; i < n; i++) { 94 if (rawOffsetsIndex.get(i) > rawOffset) { 95 break; 96 } 97 } 98 rawOffsetsIndex.add(i, rawOffset); 99 100 Set<String> perRawOffset = new TreeSet<String>(); 101 if (!isExcluded) { 102 perRawOffset.add(zonename); 103 } 104 rawOffsetsIndexTable.add(i, perRawOffset); 105 } else if (!isExcluded) { 106 int i = rawOffsetsIndex.indexOf(new Integer(rawOffset)); 107 Set<String> perRawOffset = rawOffsetsIndexTable.get(i); 108 perRawOffset.add(zonename); 109 } 110 } 111 112 Map<String,String> a = zi.getAliases(); 113 // If there are time zone names which refer to any of the 114 // excluded zones, add those names to the excluded list. 115 if (excludeList != null) { 116 for (String zoneName : a.keySet()) { 117 String realname = a.get(zoneName); 118 if (excludeList.contains(realname)) { 119 excludeList.add(zoneName); 120 } 121 } 122 } 123 aliases.putAll(a); 124 } 125 126 /** 127 * Adds valid aliases to one of per-RawOffset table and removes 128 * invalid aliases from aliases List. Aliases referring to 129 * excluded zones are not added to a per-RawOffset table. 130 */ 131 void resolve() { 132 int index = rawOffsetsIndexTable.size(); 133 List<String> toBeRemoved = new ArrayList<String>(); 134 for (String key : aliases.keySet()) { 135 boolean validname = false; 136 for (int j = 0; j < index; j++) { 137 Set<String> perRO = rawOffsetsIndexTable.get(j); 138 boolean isExcluded = (excludeList == null) ? 139 false : excludeList.contains(key); 140 141 if ((perRO.contains(aliases.get(key)) || isExcluded) 142 && Zone.isTargetZone(key)) { 143 validname = true; 144 if (!isExcluded) { 145 perRO.add(key); 146 Main.info("Alias <"+key+"> added to the list."); 147 } 148 break; 149 } 150 } 151 152 if (!validname) { 153 Main.info("Alias <"+key+"> removed from the list."); 154 toBeRemoved.add(key); 155 } 156 } 157 158 // Remove zones, if any, from the list. 159 for (String key : toBeRemoved) { 160 aliases.remove(key); 161 } 162 // Eliminate any alias-to-alias mappings. For example, if 163 // there are A->B and B->C, A->B is changed to A->C. 164 Map<String, String> newMap = new HashMap<String, String>(); 165 for (String key : aliases.keySet()) { 166 String realid = aliases.get(key); 167 String leaf = realid; 168 while (aliases.get(leaf) != null) { 169 leaf = aliases.get(leaf); 170 } 171 if (!realid.equals(leaf)) { 172 newMap.put(key, leaf); 173 } 174 } 175 aliases.putAll(newMap); 176 } 177 178 Map<String,String> getAliases() { 179 return(aliases); 180 } 181 182 List<Integer> getRawOffsetsIndex() { 183 return(rawOffsetsIndex); 184 } 185 186 List<Set<String>> getRawOffsetsIndexTable() { 187 return(rawOffsetsIndexTable); 188 } 189 190 List<String> getExcludeList() { 191 return excludeList; 192 } 193 }