001package jmri.managers.configurexml; 002 003import java.util.ArrayList; 004import java.util.List; 005import java.util.SortedSet; 006 007import jmri.InstanceManager; 008import jmri.Section; 009import jmri.Transit; 010import jmri.TransitManager; 011import jmri.TransitSection; 012import jmri.TransitSectionAction; 013 014import org.jdom2.DataConversionException; 015import org.jdom2.Element; 016 017/** 018 * Provides the functionality for configuring a TransitManager. 019 * 020 * @author Dave Duchamp Copyright (c) 2008 021 */ 022public class DefaultTransitManagerXml extends jmri.managers.configurexml.AbstractNamedBeanManagerConfigXML { 023 024 public DefaultTransitManagerXml() { 025 } 026 027 /** 028 * Default implementation for storing the contents of a TransitManager. 029 * 030 * @param o Object to store, of type TransitManager 031 * @return Element containing the complete info 032 */ 033 @Override 034 public Element store(Object o) { 035 Element transits = new Element("transits"); 036 setStoreElementClass(transits); 037 TransitManager tm = (TransitManager) o; 038 if (tm != null) { 039 SortedSet<Transit> tstList = tm.getNamedBeanSet(); 040 // don't return an element if there are no Transits to include 041 if (tstList.isEmpty()) { 042 return null; 043 } 044 045 // store the Transit 046 for (Transit transit : tstList) { 047 String tstName = transit.getSystemName(); 048 log.debug("Transit system name is {}", tstName); 049 050 Element elem = new Element("transit"); 051 elem.addContent(new Element("systemName").addContent(tstName)); 052 053 // As a work-around for backward compatibility, store systemName and username as attribute. 054 // Remove this in e.g. JMRI 4.11.1 and then update all the loadref comparison files 055 elem.setAttribute("systemName", tstName); 056 String uName = transit.getUserName(); 057 if ((uName != null) && !uName.isEmpty()) { 058 elem.setAttribute("userName", uName); 059 } 060 061 ArrayList<TransitSection> tsList = transit.getTransitSectionList(); 062 if ( tsList.isEmpty() ){ 063 log.warn("Not Storing Transit \"{}\" as it has no TransitSections", transit.getDisplayName()); 064 continue; 065 } 066 067 // store common part 068 storeCommon(transit, elem); 069 070 // save child transitsection entries 071 Element tsElem; 072 for (TransitSection ts : tsList) { 073 if ((ts != null) && !ts.isTemporary()) { 074 tsElem = new Element("transitsection"); 075 Section tSection = ts.getSection(); 076 if (tSection != null) { 077 tsElem.setAttribute("sectionname", tSection.getSystemName()); 078 } else { 079 tsElem.setAttribute("sectionname", "null"); 080 } 081 tsElem.setAttribute("sequence", Integer.toString(ts.getSequenceNumber())); 082 tsElem.setAttribute("direction", Integer.toString(ts.getDirection())); 083 tsElem.setAttribute("alternate", "" + (ts.isAlternate() ? "yes" : "no")); 084 tsElem.setAttribute("safe", "" + (ts.isSafe() ? "yes" : "no")); 085 tsElem.setAttribute("stopallocatingsensor", ts.getStopAllocatingSensor()); 086 087 // save child TransitSectionAction entries if any 088 ArrayList<TransitSectionAction> tsaList = ts.getTransitSectionActionList(); 089 if (!tsaList.isEmpty()) { 090 Element tsaElem; 091 for (TransitSectionAction tsa : tsaList) { 092 if (tsa != null) { 093 tsaElem = new Element("transitsectionaction"); 094 tsaElem.setAttribute("whencode", Integer.toString(tsa.getWhenCode())); 095 tsaElem.setAttribute("whatcode", Integer.toString(tsa.getWhatCode())); 096 tsaElem.setAttribute("whendata", Integer.toString(tsa.getDataWhen())); 097 tsaElem.setAttribute("whenstring", tsa.getStringWhen()); 098 tsaElem.setAttribute("whatdata1", Integer.toString(tsa.getDataWhat1())); 099 tsaElem.setAttribute("whatdata2", Integer.toString(tsa.getDataWhat2())); 100 tsaElem.setAttribute("whatstring", tsa.getStringWhat()); 101 tsaElem.setAttribute("whatstring2", tsa.getStringWhat2()); 102 tsElem.addContent(tsaElem); 103 } 104 } 105 } 106 elem.addContent(tsElem); 107 } 108 } 109 transits.addContent(elem); 110 } 111 } 112 return (transits); 113 } 114 115 /** 116 * Subclass provides implementation to create the correct top element, 117 * including the type information. Default implementation is to use the 118 * local class here. 119 * 120 * @param transits The top-level element being created 121 */ 122 public void setStoreElementClass(Element transits) { 123 transits.setAttribute("class", "jmri.configurexml.TransitManagerXml"); 124 } 125 126 /** 127 * Create a TransitManager object of the correct class, then register and 128 * fill it. 129 * 130 * @param sharedTransits Top level Element to unpack. 131 * @param perNodeTransits Per-node top level Element to unpack. 132 * @return true if successful 133 */ 134 @Override 135 public boolean load(Element sharedTransits, Element perNodeTransits) { 136 // load individual Transits 137 loadTransits(sharedTransits, perNodeTransits); 138 return true; 139 } 140 141 /** 142 * Utility method to load the individual Transit objects. If there's no 143 * additional info needed for a specific Transit type, invoke this with the 144 * parent of the set of Transit elements. 145 * 146 * @param sharedTransits Element containing the Transit elements to load. 147 * @param perNodeTransits Per-node Element containing the Transit elements 148 * to load. 149 */ 150 public void loadTransits(Element sharedTransits, Element perNodeTransits) { 151 List<Element> transitList = sharedTransits.getChildren("transit"); 152 log.debug("Found {} transits", transitList.size()); 153 TransitManager tm = InstanceManager.getDefault(TransitManager.class); 154 tm.setPropertyChangesSilenced("beans", true); 155 156 for (Element tst : transitList) { 157 String sysName = getSystemName(tst); 158 String userName = getUserName(tst); 159 Transit x; 160 try { 161 x = tm.createNewTransit(sysName, userName); 162 } catch (IllegalArgumentException ex) { 163 log.error("Continuing following Exception: ", ex); 164 continue; // go to next Element 165 } 166 // load common part 167 loadCommon(x, tst); 168 169 // load transitsection children 170 List<Element> transitTransitSectionList = tst.getChildren("transitsection"); 171 for (Element elem : transitTransitSectionList) { 172 int seq = 0; 173 int dir = Section.UNKNOWN; 174 boolean alt = false; 175 boolean safe = false; 176 String sectionName = elem.getAttribute("sectionname").getValue(); 177 if (sectionName.equals("null")) { 178 log.warn("When loading configuration - missing Section in Transit {}", sysName); 179 } 180 try { 181 seq = elem.getAttribute("sequence").getIntValue(); 182 dir = elem.getAttribute("direction").getIntValue(); 183 } catch (DataConversionException e) { 184 log.error("Data Conversion Exception when loading direction of entry point - ", e); 185 } 186 if (elem.getAttribute("alternate").getValue().equals("yes")) { 187 alt = true; 188 } 189 if (elem.getAttribute("safe") != null) { 190 if (elem.getAttribute("safe").getValue().equals("yes")) { 191 safe = true; 192 } 193 } 194 String stopAllocatingSensor = ""; 195 if (elem.getAttribute("stopallocatingsensor") != null) { // may not exist 196 stopAllocatingSensor = elem.getAttribute("stopallocatingsensor").getValue(); 197 if (stopAllocatingSensor.equals("null")) { 198 log.warn("When loading configuration - missing Section in Transit {}", sysName); 199 stopAllocatingSensor = ""; 200 } 201 } 202 203 TransitSection ts = new TransitSection(sectionName, seq, dir, alt, safe, stopAllocatingSensor ); 204 x.addTransitSection(ts); 205 // load transitsectionaction children, if any 206 List<Element> transitTransitSectionActionList = elem. 207 getChildren("transitsectionaction"); 208 for (Element elemx : transitTransitSectionActionList) { 209 int tWhen = 1; 210 int tWhat = 1; 211 int tWhenData = 0; 212 String tWhenString = elemx.getAttribute("whenstring").getValue(); 213 int tWhatData1 = 0; 214 int tWhatData2 = 0; 215 String tWhatString = elemx.getAttribute("whatstring").getValue(); 216 String tWhatString2 = ""; 217 if (elemx.getAttribute("whatstring").getValue() != null) { 218 tWhatString2=elemx.getAttribute("whatstring").getValue(); 219 } 220 try { 221 tWhen = elemx.getAttribute("whencode").getIntValue(); 222 tWhat = elemx.getAttribute("whatcode").getIntValue(); 223 tWhenData = elemx.getAttribute("whendata").getIntValue(); 224 tWhatData1 = elemx.getAttribute("whatdata1").getIntValue(); 225 tWhatData2 = elemx.getAttribute("whatdata2").getIntValue(); 226 } catch (DataConversionException e) { 227 log.error("Data Conversion Exception when loading transit section action - ", e); 228 } 229 TransitSectionAction tsa = new TransitSectionAction(tWhen, tWhat, tWhenData, 230 tWhatData1, tWhatData2, tWhenString, tWhatString, tWhatString2); 231 ts.addAction(tsa); 232 } 233 } 234 } 235 tm.setPropertyChangesSilenced("beans", false); 236 } 237 238 @Override 239 public int loadOrder() { 240 return InstanceManager.getDefault(TransitManager.class).getXMLOrder(); 241 } 242 243 private final static org.slf4j.Logger log = org.slf4j.LoggerFactory.getLogger(DefaultTransitManagerXml.class); 244 245}