001package jmri.jmrit.symbolicprog; 002 003import java.io.IOException; 004import java.util.HashMap; 005import java.util.List; 006import java.util.Set; 007import jmri.InstanceInitializer; 008import jmri.implementation.AbstractInstanceInitializer; 009import jmri.jmrit.XmlFile; 010import org.jdom2.Element; 011import org.jdom2.JDOMException; 012import org.openide.util.lookup.ServiceProvider; 013import org.slf4j.Logger; 014import org.slf4j.LoggerFactory; 015 016// try to limit the JDOM to this class, so that others can manipulate... 017/** 018 * Represents a set of standard names and aliases in memory. 019 * <p> 020 * This class doesn't provide tools for defining the names and aliases; that's 021 * done manually, or at least not done here, to create the file. 022 * <p> 023 * This automatically initializes from the default file if requested 024 * from the InstanceManager. 025 * 026 * @author Bob Jacobsen Copyright (C) 2001 027 */ 028public class NameFile extends XmlFile { 029 030 public Set<String> names() { 031 return _nameHash.keySet(); 032 } 033 034 // hold names in a HashMap 035 protected HashMap<String, Element> _nameHash = new HashMap<>(); 036 037 public Element elementFromName(String name) { 038 return _nameHash.get(name); 039 } 040 041 /** 042 * Check to see if a name is present in the file. 043 * 044 * @param name the name to check 045 * @return true if present; false otherwise 046 */ 047 public boolean checkName(String name) { 048 return (elementFromName(name) != null); 049 } 050 051 /** 052 * Read the contents of a NameFile XML file into this object. Note that this 053 * does not clear any existing entries. 054 * @param name File name to read 055 * @throws JDOMException if the file can't be parsed 056 * @throws IOException from underlying IO operations 057 */ 058 void readFile(String name) throws org.jdom2.JDOMException, java.io.IOException { 059 if (log.isDebugEnabled()) { 060 log.debug("readFile {}", name); 061 } 062 063 // read file, find root 064 Element root = rootFromName(name); 065 // decode type, invoke proper processing routine 066 readNames(root); 067 } 068 069 void readNames(Element root) { 070 071 List<Element> l = root.getChildren("definition"); 072 if (log.isDebugEnabled()) { 073 log.debug("readNames sees {} direct children", l.size()); 074 } 075 for (int i = 0; i < l.size(); i++) { 076 // handle each entry 077 Element el = l.get(i); 078 storeDefinition(el); 079 } 080 // now recurse with "definitiongroup" children 081 l = root.getChildren("definitiongroup"); 082 if (log.isDebugEnabled()) { 083 log.debug("readNames sees {} groups", l.size()); 084 } 085 for (int i = 0; i < l.size(); i++) { 086 // handle each entry 087 Element el = l.get(i); 088 readNames(el); 089 } 090 091 } 092 093 void storeDefinition(Element el) { 094 String name = el.getAttribute("item").getValue(); 095 _nameHash.put(name, el); 096 } 097 098 /** 099 * Get the filename for the default file, including location. This is here 100 * to allow easy override in tests. 101 * 102 * @return the default filename 103 */ 104 protected static String defaultNameFilename() { 105 return fileLocation + nameFileName; 106 } 107 108 static String fileLocation = ""; 109 static String nameFileName = "names.xml"; 110 111 @ServiceProvider(service = InstanceInitializer.class) 112 public static class Initializer extends AbstractInstanceInitializer { 113 114 @Override 115 public <T> Object getDefault(Class<T> type) { 116 if (type.equals(NameFile.class)) { 117 if (log.isDebugEnabled()) { 118 log.debug("NameFile creating instance"); 119 } 120 // create and load 121 NameFile instance = new NameFile(); 122 try { 123 instance.readFile(defaultNameFilename()); 124 } catch (IOException | JDOMException e) { 125 log.error("Exception during name file reading: {}", e.getMessage()); 126 } 127 log.debug("NameFile returns instance {}", instance); 128 return instance; 129 } 130 return super.getDefault(type); 131 } 132 133 @Override 134 public Set<Class<?>> getInitalizes() { 135 Set<Class<?>> set = super.getInitalizes(); 136 set.add(NameFile.class); 137 return set; 138 } 139 140 } 141 142 private final static Logger log = LoggerFactory.getLogger(NameFile.class); 143}