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