001/* 002 * #%L 003 * Netarchivesuite - common 004 * %% 005 * Copyright (C) 2005 - 2014 The Royal Danish Library, the Danish State and University Library, 006 * the National Library of France and the Austrian National Library. 007 * %% 008 * This program is free software: you can redistribute it and/or modify 009 * it under the terms of the GNU Lesser General Public License as 010 * published by the Free Software Foundation, either version 2.1 of the 011 * License, or (at your option) any later version. 012 * 013 * This program is distributed in the hope that it will be useful, 014 * but WITHOUT ANY WARRANTY; without even the implied warranty of 015 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 016 * GNU General Lesser Public License for more details. 017 * 018 * You should have received a copy of the GNU General Lesser Public 019 * License along with this program. If not, see 020 * <http://www.gnu.org/licenses/lgpl-2.1.html>. 021 * #L% 022 */ 023 024package dk.netarkivet.common.distribute.arcrepository; 025 026import java.util.Collection; 027import java.util.Collections; 028import java.util.HashMap; 029import java.util.HashSet; 030import java.util.List; 031import java.util.Map; 032import java.util.Set; 033 034import dk.netarkivet.common.CommonSettings; 035import dk.netarkivet.common.distribute.ChannelID; 036import dk.netarkivet.common.distribute.Channels; 037import dk.netarkivet.common.exceptions.ArgumentNotValid; 038import dk.netarkivet.common.exceptions.UnknownID; 039import dk.netarkivet.common.utils.Settings; 040import dk.netarkivet.common.utils.StringTree; 041 042/** 043 * This class encapsulates the bitarchive or checksum replicas. It guarantees that there is only one Replica object per 044 * replica id/name. 045 */ 046public class Replica { 047 /** The id of this replica. */ 048 private final String id; 049 /** The name of this replica. */ 050 private final String name; 051 /** The type of this replica (checksum or bitarchive). */ 052 private final ReplicaType type; 053 /** 054 * List of the replicas we know of. This list is initialized by the "first" call to initializeKnownReplicasList(). 055 */ 056 private static Map<String, Replica> knownReplicas; 057 058 /** 059 * Private constructor that makes a new Replica object. These will all be stored in the knownReplicas map. 060 * 061 * @param repId Id of the replica (e.g. One) 062 * @param repName Name of the replica (e.g. ReplicaOne) 063 * @param repType Type of the replica (e.g. biarchive) 064 */ 065 private Replica(String repId, String repName, ReplicaType repType) { 066 this.id = repId; 067 this.name = repName; 068 this.type = repType; 069 } 070 071 /** 072 * Initialize the list of known replicas from settings. This must be called before using known, but after settings 073 * are loaded. 074 */ 075 private static synchronized void initializeKnownReplicasList() { 076 if (knownReplicas == null) { 077 String[] replicaIds = Settings.getAll(CommonSettings.REPLICA_IDS); 078 knownReplicas = new HashMap<String, Replica>(replicaIds.length); 079 StringTree<String> replicas = Settings.getTree(CommonSettings.REPLICAS_SETTINGS); 080 List<StringTree<String>> replicaList = replicas.getSubTrees(CommonSettings.REPLICA_TAG); 081 for (StringTree<String> replicaTree : replicaList) { 082 String replicaId = replicaTree.getValue(CommonSettings.REPLICAID_TAG); 083 knownReplicas.put( 084 replicaId, 085 new Replica(replicaId, replicaTree.getValue(CommonSettings.REPLICANAME_TAG), ReplicaType 086 .fromSetting(replicaTree.getValue(CommonSettings.REPLICATYPE_TAG)))); 087 } 088 } 089 } 090 091 /** 092 * Get an object representing the replica with the given id. 093 * 094 * @param id The given name of an replica 095 * @return an object representing the replica with the given id 096 * @throws UnknownID if no replica is known with the given id 097 */ 098 public static Replica getReplicaFromId(String id) { 099 ArgumentNotValid.checkNotNullOrEmpty(id, "String id"); 100 initializeKnownReplicasList(); 101 if (!knownReplicas.containsKey(id)) { 102 throw new UnknownID("Can't find replica with id '" + id + "', only know of " + knownReplicas.keySet()); 103 } 104 return knownReplicas.get(id); 105 } 106 107 /** 108 * Get an object representing the replica with the given name. 109 * 110 * @param name The given name of an replica 111 * @return an object representing the replica with the given name 112 * @throws UnknownID if no replica is known with the given name 113 */ 114 public static Replica getReplicaFromName(String name) { 115 ArgumentNotValid.checkNotNullOrEmpty(name, "String name"); 116 initializeKnownReplicasList(); 117 // Note that this null value will never be returned. 118 // will always be replaced by non-null value OR the method 119 // will throw an UnknownID exception. 120 Replica resRep = null; 121 boolean found = false; 122 for (Replica rep : knownReplicas.values()) { 123 found = rep.getName().equals(name); 124 if (found) { 125 resRep = rep; 126 break; 127 } 128 } 129 if (!found) { 130 throw new UnknownID("Can't find replica with name '" + name + "', only know of names for " + 131 knownReplicas.keySet()); 132 } 133 return resRep; 134 } 135 136 /** 137 * Check, if a given name is a replica name. 138 * 139 * @param name a given name 140 * @return true, if the given name is a replica name, false otherwise 141 */ 142 public static boolean isKnownReplicaName(String name) { 143 ArgumentNotValid.checkNotNullOrEmpty(name, "String name"); 144 initializeKnownReplicasList(); 145 boolean found = false; 146 for (String s : knownReplicas.keySet()) { 147 found = knownReplicas.get(s).getName().equals(name); 148 if (found) { 149 break; 150 } 151 } 152 return found; 153 } 154 155 /** 156 * Check, if a given id is a replica id. 157 * 158 * @param id a given id 159 * @return true, if the given id is a replica id, false otherwise 160 */ 161 public static boolean isKnownReplicaId(String id) { 162 ArgumentNotValid.checkNotNullOrEmpty(id, "String id"); 163 initializeKnownReplicasList(); 164 boolean found = false; 165 for (String s : knownReplicas.keySet()) { 166 found = s.equals(id); 167 if (found) { 168 break; 169 } 170 } 171 return found; 172 } 173 174 /** 175 * Get all known replicas. 176 * 177 * @return A unmodifiable view of the currently known replicas. 178 */ 179 public static Collection<Replica> getKnown() { 180 initializeKnownReplicasList(); 181 return Collections.unmodifiableCollection(knownReplicas.values()); 182 } 183 184 /** 185 * Get all known replicas as ids. 186 * 187 * @return all known replicas as ids 188 */ 189 public static String[] getKnownIds() { 190 initializeKnownReplicasList(); 191 String[] knownIds = new String[knownReplicas.keySet().size()]; 192 int index = 0; 193 for (String s : knownReplicas.keySet()) { 194 knownIds[index] = s; 195 index++; 196 } 197 return knownIds; 198 } 199 200 /** 201 * Get the id of all known replicas as a string set. 202 * 203 * @return The id of all known replicas as a string set. 204 */ 205 public static Set<String> getKnownIdsAsSet() { 206 initializeKnownReplicasList(); 207 return knownReplicas.keySet(); 208 } 209 210 /** 211 * Get names of all known replicas as string array. 212 * 213 * @return The names of all known replicas as a string array. 214 */ 215 public static String[] getKnownNames() { 216 initializeKnownReplicasList(); 217 String[] knownNames = new String[knownReplicas.keySet().size()]; 218 int index = 0; 219 for (String s : knownReplicas.keySet()) { 220 knownNames[index] = knownReplicas.get(s).getName(); 221 ++index; 222 } 223 return knownNames; 224 } 225 226 /** 227 * Get the names of all known replicas as a string set. 228 * 229 * @return The names of all known replicas as a string set. 230 */ 231 public static Set<String> getKnownNamesAsSet() { 232 initializeKnownReplicasList(); 233 Set<String> res = new HashSet<String>(knownReplicas.size()); 234 for (Replica rep : knownReplicas.values()) { 235 res.add(rep.getName()); 236 } 237 return res; 238 } 239 240 /** 241 * Get the type of this replica. 242 * 243 * @return The type of this replica (bitarchive or checksum). 244 */ 245 public ReplicaType getType() { 246 return type; 247 } 248 249 /** 250 * Get the id of this replica. 251 * 252 * @return The id of this replica (also used in queues). 253 */ 254 public String getId() { 255 return id; 256 } 257 258 /** 259 * Get the name of this replica. 260 * 261 * @return The name of this replica is known as in interface. 262 */ 263 public String getName() { 264 return name; 265 } 266 267 /** 268 * Get the identification channel that corresponds to this replica. Please do not parse its name! 269 * 270 * @return The BaMon ChannelID of this replica. 271 */ 272 public ChannelID getIdentificationChannel() { 273 // This is the channel used by the connected replicas in the 274 // ArcRepository. 275 if (type == ReplicaType.BITARCHIVE) { 276 return Channels.getBaMonForReplica(id); 277 } else if (type == ReplicaType.CHECKSUM) { 278 return Channels.getTheCrForReplica(id); 279 } else { 280 throw new UnknownID("No channel for replica " + toString()); 281 } 282 } 283 284 /** 285 * Returns a human-readable representation of the object. 286 * 287 * @return An arbitrary string version of the object. Do not depend on its format. 288 */ 289 public String toString() { 290 return type.toString() + "Replica (" + id + ") " + name; 291 } 292 293}