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.isExcludeMemoryContents() )) { 067 if (! (loadAndStorePreferences.isExcludeMemoryIMCURRENTTIME() 068 && mName.equals("IMCURRENTTIME")) ) { 069 Object obj = m.getValue(); 070 if (obj != null) { 071 if (obj instanceof RosterEntry) { 072 String valueClass = obj.getClass().getName(); 073 String value = ((RosterEntry) obj).getId(); 074 elem.setAttribute("value", value); 075 elem.setAttribute("valueClass", valueClass); 076 } else { 077 String value = obj.toString(); 078 elem.setAttribute("value", value); 079 } 080 } 081 } 082 } 083 084 log.debug("store Memory {}", mName); 085 memories.addContent(elem); 086 } 087 } 088 return memories; 089 } 090 091 /** 092 * Subclass provides implementation to create the correct top element, 093 * including the type information. Default implementation is to use the 094 * local class here. 095 * 096 * @param memories The top-level element being created 097 */ 098 abstract public void setStoreElementClass(Element memories); 099 100 /** 101 * Create a MemoryManager object of the correct class, then register and 102 * fill it. 103 * 104 * @param sharedMemories Shared top level Element to unpack. 105 * @param perNodeMemories Per-node top level Element to unpack. 106 * @return true if successful 107 * @throws jmri.configurexml.JmriConfigureXmlException if error during load. 108 */ 109 @Override 110 abstract public boolean load(Element sharedMemories, Element perNodeMemories) throws JmriConfigureXmlException; 111 112 /** 113 * Utility method to load the individual Memory objects. If there's no 114 * additional info needed for a specific Memory type, invoke this with the 115 * parent of the set of Memory elements. 116 * 117 * @param memories Element containing the Memory elements to load. 118 */ 119 public void loadMemories(Element memories) { 120 List<Element> memoryList = memories.getChildren("memory"); 121 log.debug("Found {} Memory objects", memoryList.size()); 122 MemoryManager mm = InstanceManager.memoryManagerInstance(); 123 124 for (Element el : memoryList) { 125 String sysName = getSystemName(el); 126 if (sysName == null) { 127 log.warn("unexpected null in systemName {}", (el)); 128 break; 129 } 130 131 String userName = getUserName(el); 132 133 checkNameNormalization(sysName, userName, mm); 134 135 log.debug("create Memory: ({})({})", sysName, (userName == null ? "<null>" : userName)); 136 Memory m = mm.newMemory(sysName, userName); 137 if (el.getAttribute("value") != null) { 138 loadValue(el, m); 139 } 140 // load common parts 141 loadCommon(m, el); 142 } 143 } 144 145 @Override 146 public int loadOrder() { 147 return InstanceManager.memoryManagerInstance().getXMLOrder(); 148 } 149 150 private void loadValue(Element memory, Memory m) { 151 String value = memory.getAttribute("value").getValue(); 152 if (memory.getAttribute("valueClass") != null) { 153 String adapter = memory.getAttribute("valueClass").getValue(); 154 if (adapter.equals("jmri.jmrit.roster.RosterEntry")) { 155 RosterEntry re = jmri.jmrit.roster.Roster.getDefault().getEntryForId(value); 156 m.setValue(re); 157 return; 158 } 159 } 160 m.setValue(value); 161 } 162 163 private final static Logger log = LoggerFactory.getLogger(AbstractMemoryManagerConfigXML.class); 164 165}