001package jmri.managers.configurexml; 002 003import java.util.List; 004import java.util.SortedSet; 005 006import jmri.InstanceManager; 007import jmri.Memory; 008import jmri.MemoryManager; 009import jmri.configurexml.JmriConfigureXmlException; 010import jmri.configurexml.LoadAndStorePreferences; 011import jmri.jmrit.roster.RosterEntry; 012 013import org.jdom2.Element; 014import org.slf4j.Logger; 015import org.slf4j.LoggerFactory; 016 017/** 018 * Provides the abstract base and store functionality for configuring 019 * MemoryManagers, working with AbstractMemoryManagers. 020 * <p> 021 * Also serves as base class for {@link jmri.configurexml.BlockManagerXml} persistence. 022 * <p> 023 * Typically, a subclass will just implement the load(Element memories) class, 024 * relying on implementation here to load the individual Memory objects. Note 025 * that these are stored explicitly, so the resolution mechanism doesn't need to 026 * see *Xml classes for each specific Memory or AbstractMemory subclass at store 027 * time. 028 * 029 * @author Bob Jacobsen Copyright: Copyright (c) 2002, 2008 030 */ 031public abstract class AbstractMemoryManagerConfigXML extends AbstractNamedBeanManagerConfigXML { 032 033 public AbstractMemoryManagerConfigXML() { 034 } 035 036 /** 037 * Default implementation for storing the contents of a MemoryManager. 038 * 039 * @param o Object to store, of type MemoryManager 040 * @return Element containing the complete info 041 */ 042 @Override 043 public Element store(Object o) { 044 Element memories = new Element("memories"); 045 setStoreElementClass(memories); 046 MemoryManager mm = (MemoryManager) o; 047 if (mm != null) { 048 SortedSet<Memory> memList = mm.getNamedBeanSet(); 049 // don't return an element if there are no memories to include 050 if (memList.isEmpty()) { 051 return null; 052 } 053 // store the memories 054 for (Memory m : memList) { 055 String mName = m.getSystemName(); 056 log.debug("system name is {}", mName); 057 058 Element elem = new Element("memory"); 059 elem.addContent(new Element("systemName").addContent(mName)); 060 061 // store common part 062 storeCommon(m, elem); 063 064 var loadAndStorePreferences = InstanceManager.getDefault(LoadAndStorePreferences.class); 065 // store value if non-null; null values omitted 066 if (! (loadAndStorePreferences.isExcludeMemoryIMCURRENTTIME() 067 && mName.equals("IMCURRENTTIME")) ) { 068 Object obj = m.getValue(); 069 if (obj != null) { 070 if (obj instanceof RosterEntry) { 071 String valueClass = obj.getClass().getName(); 072 String value = ((RosterEntry) obj).getId(); 073 elem.setAttribute("value", value); 074 elem.setAttribute("valueClass", valueClass); 075 } else { 076 String value = obj.toString(); 077 elem.setAttribute("value", value); 078 } 079 } 080 } 081 082 log.debug("store Memory {}", mName); 083 memories.addContent(elem); 084 } 085 } 086 return memories; 087 } 088 089 /** 090 * Subclass provides implementation to create the correct top element, 091 * including the type information. Default implementation is to use the 092 * local class here. 093 * 094 * @param memories The top-level element being created 095 */ 096 abstract public void setStoreElementClass(Element memories); 097 098 /** 099 * Create a MemoryManager object of the correct class, then register and 100 * fill it. 101 * 102 * @param sharedMemories Shared top level Element to unpack. 103 * @param perNodeMemories Per-node top level Element to unpack. 104 * @return true if successful 105 * @throws jmri.configurexml.JmriConfigureXmlException if error during load. 106 */ 107 @Override 108 abstract public boolean load(Element sharedMemories, Element perNodeMemories) throws JmriConfigureXmlException; 109 110 /** 111 * Utility method to load the individual Memory objects. If there's no 112 * additional info needed for a specific Memory type, invoke this with the 113 * parent of the set of Memory elements. 114 * 115 * @param memories Element containing the Memory elements to load. 116 */ 117 public void loadMemories(Element memories) { 118 List<Element> memoryList = memories.getChildren("memory"); 119 log.debug("Found {} Memory objects", memoryList.size()); 120 MemoryManager mm = InstanceManager.memoryManagerInstance(); 121 122 for (Element el : memoryList) { 123 String sysName = getSystemName(el); 124 if (sysName == null) { 125 log.warn("unexpected null in systemName {}", (el)); 126 break; 127 } 128 129 String userName = getUserName(el); 130 131 checkNameNormalization(sysName, userName, mm); 132 133 log.debug("create Memory: ({})({})", sysName, (userName == null ? "<null>" : userName)); 134 Memory m = mm.newMemory(sysName, userName); 135 if (el.getAttribute("value") != null) { 136 loadValue(el, m); 137 } 138 // load common parts 139 loadCommon(m, el); 140 } 141 } 142 143 @Override 144 public int loadOrder() { 145 return InstanceManager.memoryManagerInstance().getXMLOrder(); 146 } 147 148 private void loadValue(Element memory, Memory m) { 149 String value = memory.getAttribute("value").getValue(); 150 if (memory.getAttribute("valueClass") != null) { 151 String adapter = memory.getAttribute("valueClass").getValue(); 152 if (adapter.equals("jmri.jmrit.roster.RosterEntry")) { 153 RosterEntry re = jmri.jmrit.roster.Roster.getDefault().getEntryForId(value); 154 m.setValue(re); 155 return; 156 } 157 } 158 m.setValue(value); 159 } 160 161 private final static Logger log = LoggerFactory.getLogger(AbstractMemoryManagerConfigXML.class); 162 163}