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