1 package org.lcsim.recon.tracking.trflayer; 2 import java.util.*; 3 import org.lcsim.recon.tracking.trfutil.Assert; 4 5 /** 6 * A detector is a collection of named layers. It provides a method 7 * for retrieving any of these layers by name. 8 *<p> 9 * This class is intended for use as a base class. It is not abstract 10 * but the constructor is protected. Similarly, there are no public 11 * methods for adding, modifying or removing layers or subdetectors. 12 * A subclass is expected to call methods to add a single layer or 13 * all the layers from another detector. Typically these calls would 14 * be made in the constructor. 15 *<p> 16 * The return status for each change is zero if the change was 17 * successful. After all changes, is_ok() may be called to verify 18 * internal consistency. 19 *<p> 20 * The layer names must be unique. New names are checked for uniqueness 21 * each time a layer is added. 22 * 23 *@author Norman A. Graf 24 *@version 1.0 25 * 26 **/ 27 28 public class Detector 29 { 30 31 // enums 32 private static final int UNCHECKED = 0; 33 private static final int CHECKED_OK = 1; 34 private static final int CHECKED_BAD = 2; 35 // Flags for assertions. 36 // If set false, assertion will fail. 37 private static boolean CHECK_SIZE_MISMATCH = false; 38 39 // static methods 40 41 // 42 43 /** 44 *Return the type name. 45 * 46 * @return String representation of class type 47 *Included for completeness with C++ version 48 */ 49 public static String typeName() 50 { return "Detector"; } 51 52 // 53 54 /** 55 *Return the type. 56 * 57 * @return String representation of class type 58 *Included for completeness with C++ version 59 */ 60 public static String staticType() 61 { return typeName(); } 62 63 // attributes 64 65 // List of layer names in original order. 66 private List _names; 67 68 // Map layer names to layers. 69 private Map _layermap; 70 71 // Check status. 72 // Set by method check. 73 private int _check; 74 75 // methods 76 77 // Check internal status. 78 // Note that if _check is set to CHECKED_BAD, it is not changed. 79 // Return nonzero for error. 80 private void check() 81 { 82 // This checks the detector for internal consistency and sets the 83 // status accordingly. 84 // Presently, the status is inherently good, so no check is needed. 85 86 // Bad check stays bad. 87 if ( _check == CHECKED_BAD ) return; 88 89 // Check that the list of names and map have the same size. 90 // There is a logic error if this fails. 91 if ( _names.size() != _layermap.size() ) 92 { 93 Assert.assertTrue( CHECK_SIZE_MISMATCH ); 94 _check = CHECKED_BAD; 95 } 96 97 // All tests passed. 98 _check = CHECKED_OK; 99 } 100 101 // methods 102 103 // Default constructor. 104 protected Detector() 105 { 106 _check = UNCHECKED; 107 _names = new ArrayList(); 108 _layermap = new HashMap(); 109 } 110 111 // Return the map of layers indexed by name. 112 protected Map layerMap() 113 { return _layermap; } 114 115 // Add a named layer. 116 // 117 // Return 0 for success. 118 // 119 // Return nonzero and do not add layer if the name duplicates 120 // a known name. 121 // 122 protected int addLayer(String name, Layer lyr) 123 { 124 // Set unchecked. 125 if ( _check == CHECKED_OK ) _check = UNCHECKED; 126 127 // Check name does not already appear in map. 128 if ( isAssigned(name) ) return 11; 129 130 // Add layer. 131 _names.add(name); 132 _layermap.put(name, lyr); 133 134 return 0; 135 136 } 137 138 // Add a subdetector. 139 // 140 // Return 0 for success. 141 // 142 // Return nonzero and add no layers if any of the subdetector 143 // layer names duplicate those here. 144 // 145 protected int addSubdetector( Detector subdet) 146 { 147 // Set unchecked. 148 if ( _check == CHECKED_OK ) _check = UNCHECKED; 149 150 // Exit if the subdetector does not check ok. 151 if ( ! subdet.isOk() ) return 21; 152 153 // Fetch the subdetector names and layer map. 154 List subnames = subdet.layerNames(); 155 Map sublayermap = subdet.layerMap(); 156 157 // Check that the names are unique. 158 159 for ( Iterator iname=subnames.iterator(); iname.hasNext(); ) 160 if ( isAssigned( (String) iname.next()) ) return 22; 161 162 // Add the layers from each subdetector. 163 _names.addAll( subnames ); 164 _layermap.putAll( sublayermap ); 165 166 // The check status will reflect that of the added layers. 167 return 0; 168 169 } 170 171 // methods 172 173 174 // 175 176 /** 177 *Return the type. 178 * 179 * @return String representation of class type 180 *Included for completeness with C++ version 181 */ 182 public String genericType() 183 { return staticType(); } 184 185 // 186 187 /** 188 * Return the type. 189 * 190 * @return String representation of class type 191 *Included for completeness with C++ version 192 */ 193 public String type() 194 { return staticType(); } 195 196 // 197 198 /** 199 *Return whether the check status is ok. 200 * If the status has not been checked, this will dos so. 201 * 202 * @return true if check status is ok 203 */ 204 public boolean isOk() 205 { 206 if ( _check == UNCHECKED ) check(); 207 return _check == CHECKED_OK; 208 } 209 210 // 211 212 /** 213 *Return the list of layer names. 214 * 215 * @return List of layer names 216 */ 217 public List layerNames() 218 { return _names; } 219 220 // 221 222 /** 223 *Print the layers. 224 * 225 */ 226 public void printLayers() 227 { 228 System.out.println(toString()); 229 } 230 231 232 /** 233 *output stream 234 * 235 * @return String representation of class 236 */ 237 public String toString() 238 { 239 240 // Fetch list of layer names (including subdetectors) 241 List names = layerNames(); 242 243 // header 244 int size = names.size(); 245 StringBuffer sb = new StringBuffer( getClass().getName()+" has " + size + " layer"); 246 if ( size != 1 ) sb.append("s"); 247 if ( size > 0 ) sb.append(":"); 248 else sb.append("."); 249 250 // Loop over layers. 251 252 for ( Iterator iname=names.iterator(); iname.hasNext(); ) 253 { 254 String name = (String) iname.next(); 255 sb.append("\n"+name + ": " + layer(name)); 256 } 257 return sb.toString(); 258 } 259 260 // 261 262 /** 263 *Return whether a name has been assigned. 264 * 265 * @param name String name of detector 266 * @return true if name is assigned 267 */ 268 public boolean isAssigned(String name) 269 { 270 return _layermap.containsKey(name); 271 } 272 273 // 274 275 /** 276 *Return a layer. 277 * Throw exception or crash if name is unrecognized. 278 * To avoid crash, first check with is_assigned(). 279 * 280 * @param name String name of detector 281 * @return Layer with name name 282 */ 283 public Layer layer(String name) 284 { 285 if ( _layermap.containsKey(name)) 286 { 287 return (Layer)_layermap.get(name); 288 } 289 else 290 { 291 throw new IllegalArgumentException("Detector does not contain Layer "+name); 292 } 293 294 } 295 296 297 //Don't care? 298 // Register layers with ObjTable. 299 // Returns the number of layers which could not be registered and were 300 // not already registered with the same name and address. Normally 301 // this should be zero. 302 // public int register_with_objtable() 303 // { 304 // return 137; 305 // } 306 307 }