001package jmri.managers.configurexml;
002
003import java.util.List;
004import java.util.SortedSet;
005import jmri.InstanceManager;
006import jmri.Meter;
007import jmri.MeterManager;
008import jmri.configurexml.JmriConfigureXmlException;
009import org.jdom2.Element;
010import org.slf4j.Logger;
011import org.slf4j.LoggerFactory;
012
013/**
014 * Provides the basic load and store functionality for configuring
015 * MeterManagers, working with AbstractMeterManagers.
016 * <p>
017 * This class cannot create Meters, so the meters must either be already
018 * created, for example by the connections, in which case this class only
019 * updates the data of the meter, for example its user name.
020 * Or this class is overridden by a class that knows how to create the meters.
021 *
022 * @author Bob Jacobsen      Copyright (C) 2002, 2008
023 * @author Daniel Bergqvist  Copyright (C) 2020
024 */
025public class AbstractMeterManagerXml extends AbstractNamedBeanManagerConfigXML {
026
027    public AbstractMeterManagerXml() {
028    }
029
030    /**
031     * Default implementation for storing the contents of a MeterManager.
032     *
033     * @param o Object to store, of type MeterManager
034     * @return Element containing the complete info
035     */
036    @Override
037    public Element store(Object o) {
038        Element meters = new Element("meters");
039        setStoreElementClass(meters);
040        MeterManager mm = (MeterManager) o;
041        if (mm != null) {
042            SortedSet<Meter> memList = mm.getNamedBeanSet();
043            // don't return an element if there are no meters to include
044            if (memList.isEmpty()) {
045                return null;
046            }
047            // store the meters
048            for (Meter m : memList) {
049                String mName = m.getSystemName();
050                log.debug("system name is {}", mName);
051
052                Element elem = new Element("meter");
053                elem.addContent(new Element("systemName").addContent(mName));
054
055                // store common part
056                storeCommon(m, elem);
057
058                log.debug("store Meter {}", mName);
059                meters.addContent(elem);
060            }
061        }
062        return meters;
063    }
064
065    /**
066     * Subclass provides implementation to create the correct top element,
067     * including the type information. Default implementation is to use the
068     * local class here.
069     *
070     * @param meters The top-level element being created
071     */
072    public void setStoreElementClass(Element meters) {
073        meters.setAttribute("class", this.getClass().getName());  // NOI18N
074    }
075
076    /**
077     * Create a MeterManager object of the correct class, then register and
078     * fill it.
079     *
080     * @param sharedMeters  Shared top level Element to unpack.
081     * @param perNodeMemories Per-node top level Element to unpack.
082     * @return true if successful
083     * @throws jmri.configurexml.JmriConfigureXmlException if error during load.
084     */
085    @Override
086    public boolean load(Element sharedMeters, Element perNodeMemories) throws JmriConfigureXmlException {
087        loadMeters(sharedMeters);
088        return true;
089    }
090
091    /**
092     * Utility method to load the individual Meter objects. If there's no
093     * additional info needed for a specific Meter type, invoke this with the
094     * parent of the set of Meter elements.
095     *
096     * @param meters Element containing the Meter elements to load.
097     */
098    public void loadMeters(Element meters) {
099        List<Element> meterList = meters.getChildren("meter");
100        log.debug("Found {} Meter objects", meterList.size());
101        MeterManager mm = InstanceManager.getDefault(MeterManager.class);
102
103        for (Element el : meterList) {
104            String sysName = getSystemName(el);
105            if (sysName == null) {
106                log.warn("unexpected null in systemName {}", (el));
107                break;
108            }
109
110            String userName = getUserName(el);
111
112            checkNameNormalization(sysName, userName, mm);
113
114            log.debug("get Meter: ({})({})", sysName, (userName == null ? "<null>" : userName));
115            Meter m = mm.getBySystemName(sysName);
116            if (m != null) {
117                m.setUserName(userName);
118                // load common parts
119                loadCommon(m, el);
120            } else {
121                log.debug("Meter ({}) does not exists and cannot be created", sysName);
122            }
123        }
124    }
125
126    @Override
127    public int loadOrder() {
128        return InstanceManager.getDefault(MeterManager.class).getXMLOrder();
129    }
130
131    private final static Logger log = LoggerFactory.getLogger(AbstractMeterManagerXml.class);
132
133}