001package jmri.managers.configurexml; 002 003import java.util.List; 004import java.util.SortedSet; 005 006import jmri.Block; 007import jmri.EntryPoint; 008import jmri.InstanceManager; 009import jmri.Section; 010import jmri.SectionManager; 011 012import org.jdom2.DataConversionException; 013import org.jdom2.Element; 014import org.slf4j.Logger; 015import org.slf4j.LoggerFactory; 016 017/** 018 * Provides the functionality for persistence of a SectionManager. 019 * 020 * @author Dave Duchamp Copyright (c) 2008 021 */ 022public class DefaultSectionManagerXml extends jmri.managers.configurexml.AbstractNamedBeanManagerConfigXML { 023 024 public DefaultSectionManagerXml() { 025 } 026 027 /** 028 * Implementation for storing the contents of a SectionManager. 029 * 030 * @param o Object to store, of type SectionManager 031 * @return Element containing the complete info 032 */ 033 @Override 034 public Element store(Object o) { 035 Element sections = new Element("sections"); 036 setStoreElementClass(sections); 037 SectionManager sctm = (SectionManager) o; 038 if (sctm != null) { 039 SortedSet<Section> sctList = sctm.getNamedBeanSet(); 040 // don't return an element if there are no Sections to include 041 if (sctList.isEmpty()) { 042 return null; 043 } 044 045 // store the Sections 046 for (Section x : sctList) { 047 if (x == null) { 048 log.error("Memory null during store, skipped"); 049 break; 050 } 051 String sName = x.getSystemName(); 052 log.debug("Section system name is {}", sName); 053 054 if (x.getSectionType() != Section.DYNAMICADHOC) { 055 Element elem = new Element("section"); 056 elem.addContent(new Element("systemName").addContent(sName)); 057 058 // As a work-around for backward compatibility, store systemName and username as attribute. 059 // TODO Remove this in e.g. JMRI 4.11.1 and then update all the loadref comparison files 060 elem.setAttribute("systemName", sName); 061 String uname = x.getUserName(); 062 if (uname != null && !uname.isEmpty()) { 063 elem.setAttribute("userName", uname); 064 } 065 066 // store common part 067 storeCommon(x, elem); 068 069 String txt = "userdefined"; 070 if (x.getSectionType() == Section.SIGNALMASTLOGIC) { 071 txt = "signalmastlogic"; 072 } 073 elem.setAttribute("creationtype", txt); 074 txt = x.getForwardStoppingSensorName(); 075 if ((txt != null) && (!txt.isEmpty())) { 076 elem.setAttribute("fstopsensorname", txt); 077 } 078 txt = x.getReverseStoppingSensorName(); 079 if ((txt != null) && (!txt.isEmpty())) { 080 elem.setAttribute("rstopsensorname", txt); 081 } 082 txt = x.getForwardBlockingSensorName(); 083 if ((txt != null) && (!txt.isEmpty())) { 084 elem.setAttribute("fsensorname", txt); 085 } 086 txt = x.getReverseBlockingSensorName(); 087 if ((txt != null) && (!txt.isEmpty())) { 088 elem.setAttribute("rsensorname", txt); 089 } 090 if (x.getSectionType() == Section.USERDEFINED) { 091 // save child block entries 092 int index = 0; 093 Block b = x.getBlockBySequenceNumber(index); 094 Element bElem; 095 while (b != null) { 096 bElem = new Element("blockentry"); 097 bElem.setAttribute("sName", b.getSystemName()); 098 bElem.setAttribute("order", Integer.toString(index)); 099 elem.addContent(bElem); 100 index++; 101 b = x.getBlockBySequenceNumber(index); 102 } 103 // save child entry points 104 List<EntryPoint> epList = x.getEntryPointList(); 105 Element epElem; 106 int i = 0; 107 for (EntryPoint ep : epList) { 108 if (ep != null) { 109 epElem = new Element("entrypoint"); 110 // add some protection against a reading problem 111 if (ep.getFromBlock() == null) { 112 log.error("Unexpected null getFromBlock while storing ep {} in Section {}, skipped", i, sName); 113 break; 114 } 115 epElem.setAttribute("fromblock", ep.getFromBlock().getSystemName()); 116 if (ep.getBlock() == null) { 117 log.error("Unexpected null getBlock while storing ep {} in Section {}, skipped", i, sName); 118 break; 119 } 120 epElem.setAttribute("toblock", ep.getBlock().getSystemName()); 121 epElem.setAttribute("direction", Integer.toString(ep.getDirection())); 122 epElem.setAttribute("fixed", "" + (ep.isFixed() ? "yes" : "no")); 123 epElem.setAttribute("fromblockdirection", "" + ep.getFromBlockDirection()); 124 elem.addContent(epElem); 125 i++; 126 } 127 } 128 } 129 sections.addContent(elem); 130 } 131 } 132 } 133 return (sections); 134 } 135 136 /** 137 * Subclass provides implementation to create the correct top element, 138 * including the type information. Default implementation is to use the 139 * local class here. 140 * 141 * @param sections The top-level element being created 142 */ 143 public void setStoreElementClass(Element sections) { 144 sections.setAttribute("class", "jmri.configurexml.SectionManagerXml"); 145 } 146 147 @Override 148 public void load(Element element, Object o) { 149 log.error("Invalid method called"); 150 } 151 152 /** 153 * Create a SectionManager object of the correct class, then register and 154 * fill it. 155 * 156 * @param sharedSections Top level Element to unpack. 157 * @param perNodeSections Per-node Element to unpack. 158 * @return true if successful 159 */ 160 @Override 161 public boolean load(Element sharedSections, Element perNodeSections) { 162 // load individual Sections 163 loadSections(sharedSections, perNodeSections); 164 return true; 165 } 166 167 /** 168 * Utility method to load the individual Section objects. If there's no 169 * additional info needed for a specific Section type, invoke this with the 170 * parent of the set of Section elements. 171 * 172 * @param sharedSections Element containing the Section elements to load. 173 * @param perNodeSections Per-node Element containing the Section elements 174 * to load. 175 */ 176 public void loadSections(Element sharedSections, Element perNodeSections) { 177 List<Element> sectionList = sharedSections.getChildren("section"); 178 log.debug("Found {} Sections", sectionList.size()); 179 SectionManager sctm = InstanceManager.getDefault(jmri.SectionManager.class); 180 sctm.setPropertyChangesSilenced("beans", true); 181 182 for (Element s : sectionList) { 183 String sysName = getSystemName(s); 184 String userName = getUserName(s); 185 Section x; 186 try { 187 x = sctm.createNewSection(sysName, userName); 188 } 189 catch (IllegalArgumentException ex){ 190 log.error("Unable to create Section {} {}",sysName,ex.getMessage()); 191 continue; 192 } 193 // load common part 194 loadCommon(x, (s)); 195 196 if (s.getAttribute("creationtype") != null) { 197 String creationType = s.getAttribute("creationtype").getValue(); 198 if (creationType.equals("userdefined")) { 199 x.setSectionType(Section.USERDEFINED); 200 } else if (creationType.equals("signalmastlogic")) { 201 x.setSectionType(Section.SIGNALMASTLOGIC); 202 } 203 } 204 if (s.getAttribute("fsensorname") != null) { 205 String forName = s.getAttribute("fsensorname").getValue(); 206 x.delayedSetForwardBlockingSensorName(forName); 207 } 208 if (s.getAttribute("rsensorname") != null) { 209 String revName = s.getAttribute("rsensorname").getValue(); 210 x.delayedSetReverseBlockingSensorName(revName); 211 } 212 if (s.getAttribute("fstopsensorname") != null) { 213 String forName = s.getAttribute("fstopsensorname").getValue(); 214 x.delayedSetForwardStoppingSensorName(forName); 215 } 216 if (s.getAttribute("rstopsensorname") != null) { 217 String revName = s.getAttribute("rstopsensorname").getValue(); 218 x.delayedSetReverseStoppingSensorName(revName); 219 } 220 221 // load block entry children 222 List<Element> sectionBlockList = s.getChildren("blockentry"); 223 for (Element elem : sectionBlockList) { 224 x.delayedAddBlock(elem.getAttribute("sName").getValue()); 225 // insert code here to verify sequence number if needed in the future 226 } 227 228 // load entry point children 229 List<Element> sectionEntryPointList = s.getChildren("entrypoint"); 230 for (Element elem : sectionEntryPointList) { 231 String blockName = elem.getAttribute("toblock").getValue(); 232 String fromBlockName = elem.getAttribute("fromblock").getValue(); 233 String fromBlockDirection = ""; 234 if (elem.getAttribute("fromblockdirection") != null) { 235 fromBlockDirection = elem.getAttribute("fromblockdirection").getValue(); 236 } 237 EntryPoint ep = new EntryPoint(blockName, fromBlockName, fromBlockDirection); 238 try { 239 ep.setDirection(elem.getAttribute("direction").getIntValue()); 240 } catch (DataConversionException e) { 241 log.error("Data Conversion Exception when loading direction of entry point - ", e); 242 } 243 boolean fixed = true; 244 if (elem.getAttribute("fixed").getValue().equals("no")) { 245 fixed = false; 246 } 247 ep.setFixed(fixed); 248 if (ep.isForwardType()) { 249 x.addToForwardList(ep); 250 } else if (ep.isReverseType()) { 251 x.addToReverseList(ep); 252 } 253 } 254 } 255 sctm.setPropertyChangesSilenced("beans", false); 256 } 257 258 @Override 259 public int loadOrder() { 260 return InstanceManager.getDefault(jmri.SectionManager.class).getXMLOrder(); 261 } 262 263 private final static Logger log = LoggerFactory.getLogger(DefaultSectionManagerXml.class); 264 265}