1 /* 2 * Copyright (c) 2000, 2012, 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. Oracle designates this 8 * particular file as subject to the "Classpath" exception as provided 9 * by Oracle in the LICENSE file that accompanied this code. 10 * 11 * This code is distributed in the hope that it will be useful, but WITHOUT 12 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 13 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 14 * version 2 for more details (a copy is included in the LICENSE file that 15 * accompanied this code). 16 * 17 * You should have received a copy of the GNU General Public License version 18 * 2 along with this work; if not, write to the Free Software Foundation, 19 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 20 * 21 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA 22 * or visit www.oracle.com if you need additional information or have any 23 * questions. 24 */ 25 26 import java.util.ArrayList; 27 import java.util.HashMap; 28 import java.util.LinkedList; 29 import java.util.List; 30 import java.util.Map; 31 import java.util.Set; 32 import java.util.TreeMap; 33 import java.util.TreeSet; 34 35 /** 36 * <code>Mappings</code> generates two Maps and a List which are used by 37 * javazic BackEnd. 38 * 39 * @since 1.4 40 */ 41 class Mappings { 42 // All aliases specified by Link statements. It's alias name to 43 // real name mappings. 44 private Map<String,String> aliases; 45 46 private List<Integer> rawOffsetsIndex; 47 48 private List<Set<String>> rawOffsetsIndexTable; 49 50 // Zone names to be excluded from rawOffset table. Those have GMT 51 // offsets to change some future time. 52 private List<String> excludeList; 53 54 /** 55 * Constructor creates some necessary instances. 56 */ 57 Mappings() { 58 aliases = new TreeMap<String,String>(); 59 rawOffsetsIndex = new LinkedList<Integer>(); 60 rawOffsetsIndexTable = new LinkedList<Set<String>>(); 61 } 62 63 /** 64 * Generates aliases and rawOffsets tables. 65 * @param zi a Zoneinfo containing Zones 66 */ 67 void add(Zoneinfo zi) { 68 Map<String,Zone> zones = zi.getZones(); 69 70 for (String zoneName : zones.keySet()) { 71 Zone zone = zones.get(zoneName); 72 String zonename = zone.getName(); 73 int rawOffset = zone.get(zone.size()-1).getGmtOffset(); 74 75 // If the GMT offset of this Zone will change in some 76 // future time, this Zone is added to the exclude list. 77 boolean isExcluded = false; 78 for (int i = 0; i < zone.size(); i++) { 79 ZoneRec zrec = zone.get(i); 80 if ((zrec.getGmtOffset() != rawOffset) 81 && (zrec.getUntilTime(0) > Time.getCurrentTime())) { 82 if (excludeList == null) { 83 excludeList = new ArrayList<String>(); 84 } 85 excludeList.add(zone.getName()); 86 isExcluded = true; 87 break; 88 } 89 } 90 91 if (!rawOffsetsIndex.contains(new Integer(rawOffset))) { 92 // Find the index to insert this raw offset zones 93 int n = rawOffsetsIndex.size(); 94 int i; 95 for (i = 0; i < n; i++) { 96 if (rawOffsetsIndex.get(i) > rawOffset) { 97 break; 98 } 99 } 100 rawOffsetsIndex.add(i, rawOffset); 101 102 Set<String> perRawOffset = new TreeSet<String>(); 103 if (!isExcluded) { 104 perRawOffset.add(zonename); 105 } 106 rawOffsetsIndexTable.add(i, perRawOffset); 107 } else if (!isExcluded) { 108 int i = rawOffsetsIndex.indexOf(new Integer(rawOffset)); 109 Set<String> perRawOffset = rawOffsetsIndexTable.get(i); 110 perRawOffset.add(zonename); 111 } 112 } 113 114 Map<String,String> a = zi.getAliases(); 115 // If there are time zone names which refer to any of the 116 // excluded zones, add those names to the excluded list. 117 if (excludeList != null) { 118 for (String zoneName : a.keySet()) { 119 String realname = a.get(zoneName); 120 if (excludeList.contains(realname)) { 121 excludeList.add(zoneName); 122 } 123 } 124 } 125 aliases.putAll(a); 126 } 127 128 /** 129 * Adds valid aliases to one of per-RawOffset table and removes 130 * invalid aliases from aliases List. Aliases referring to 131 * excluded zones are not added to a per-RawOffset table. 132 */ 133 void resolve() { 134 int index = rawOffsetsIndexTable.size(); 135 List<String> toBeRemoved = new ArrayList<String>(); 136 for (String key : aliases.keySet()) { 137 boolean validname = false; 138 for (int j = 0; j < index; j++) { 139 Set<String> perRO = rawOffsetsIndexTable.get(j); 140 boolean isExcluded = (excludeList == null) ? 141 false : excludeList.contains(key); 142 143 if ((perRO.contains(aliases.get(key)) || isExcluded) 144 && Zone.isTargetZone(key)) { 145 validname = true; 146 if (!isExcluded) { 147 perRO.add(key); 148 Main.info("Alias <"+key+"> added to the list."); 149 } 150 break; 151 } 152 } 153 154 if (!validname) { 155 Main.info("Alias <"+key+"> removed from the list."); 156 toBeRemoved.add(key); 157 } 158 } 159 160 // Remove zones, if any, from the list. 161 for (String key : toBeRemoved) { 162 aliases.remove(key); 163 } 164 // Eliminate any alias-to-alias mappings. For example, if 165 // there are A->B and B->C, A->B is changed to A->C. 166 Map<String, String> newMap = new HashMap<String, String>(); 167 for (String key : aliases.keySet()) { 168 String realid = aliases.get(key); 169 String leaf = realid; 170 while (aliases.get(leaf) != null) { 171 leaf = aliases.get(leaf); 172 } 173 if (!realid.equals(leaf)) { 174 newMap.put(key, leaf); 175 } 176 } 177 aliases.putAll(newMap); 178 } 179 180 Map<String,String> getAliases() { 181 return(aliases); 182 } 183 184 List<Integer> getRawOffsetsIndex() { 185 return(rawOffsetsIndex); 186 } 187 188 List<Set<String>> getRawOffsetsIndexTable() { 189 return(rawOffsetsIndexTable); 190 } 191 192 List<String> getExcludeList() { 193 return excludeList; 194 } 195 }