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