001package jmri.jmrit.logixng.implementation.configurexml;
002
003import java.lang.reflect.Constructor;
004import java.lang.reflect.InvocationTargetException;
005import java.util.HashMap;
006import java.util.List;
007import java.util.Map;
008
009import jmri.configurexml.ConfigXmlManager;
010import jmri.jmrit.logixng.*;
011import jmri.jmrit.logixng.configurexml.MaleSocketXml;
012
013import org.jdom2.Element;
014
015
016/**
017 * Provides the functionality for configuring ActionManagers
018 *
019 * @author Dave Duchamp Copyright (c) 2007
020 * @author Daniel Bergqvist Copyright (c) 2018
021 */
022public abstract class AbstractManagerXml extends jmri.managers.configurexml.AbstractNamedBeanManagerConfigXML {
023
024    private final Map<String, Class<?>> xmlClasses = new HashMap<>();
025    
026    
027    /**
028     * Store data for a MaleSocket
029     *
030     * @param maleSocket the socket to store
031     * @return Element containing the complete info
032     */
033    public Element storeMaleSocket(MaleSocket maleSocket) {
034        Element element = new Element("MaleSocket");
035        
036        Base m = maleSocket;
037        while (m instanceof MaleSocket) {
038            MaleSocket ms = (MaleSocket) m;
039            
040            try {
041                Element e = ConfigXmlManager.elementFromObject(ms);
042                if (e != null) {
043                    element.addContent(e);
044                } else {
045                    throw new RuntimeException("Cannot load xml configurator for " + ms.getClass().getName());
046                }
047            } catch (RuntimeException e) {
048                log.error("Error storing maleSocket: {}", e, e);
049            }
050            
051            m = ms.getObject();
052        }
053        
054        return (element);
055    }
056
057    /**
058     * Utility method to load the individual DigitalActionBean objects. If
059     * there's no additional info needed for a specific action type, invoke
060     * this with the parent of the set of DigitalActionBean elements.
061     *
062     * @param element Element containing the MaleSocket element to load.
063     * @param maleSocket the socket to load
064     */
065    public void loadMaleSocket(Element element, MaleSocket maleSocket) {
066        
067        Map<String, Map.Entry<MaleSocketXml, Element>> maleSocketXmlClasses = new HashMap<>();
068        
069        Element elementMaleSocket = element.getChild("MaleSocket");
070        if (elementMaleSocket == null) {
071            throw new IllegalArgumentException("maleSocket is null");
072        }
073        
074        List<Element> children = elementMaleSocket.getChildren();
075        log.debug("Found {} male sockets", children.size() );  // NOI18N
076        
077        for (Element e : children) {
078            
079            String className = e.getAttribute("class").getValue();
080//            log.error("className: " + className);
081            
082            Class<?> clazz = xmlClasses.get(className);
083            
084            if (clazz == null) {
085                try {
086                    clazz = Class.forName(className);
087                    xmlClasses.put(className, clazz);
088                } catch (ClassNotFoundException ex) {
089                    log.error("cannot load class {}", className, ex);
090                }
091            }
092            
093            if (clazz != null) {
094                Constructor<?> c = null;
095                try {
096                    c = clazz.getConstructor();
097                } catch (NoSuchMethodException | SecurityException ex) {
098                    log.error("cannot create constructor", ex);
099                }
100                
101                if (c != null) {
102                    try {
103                        MaleSocketXml o = (MaleSocketXml)c.newInstance();
104                        
105                        Map.Entry<MaleSocketXml, Element> entry =
106                                new HashMap.SimpleEntry<>(o, e);
107                        maleSocketXmlClasses.put(className, entry);
108                    } catch (InstantiationException | IllegalAccessException | IllegalArgumentException | InvocationTargetException ex) {
109                        log.error("cannot create object", ex);
110                    }
111                }
112            }
113        }
114        
115        Base m = maleSocket;
116        while (m instanceof MaleSocket) {
117            MaleSocket ms = (MaleSocket) m;
118            
119            String cName = ConfigXmlManager.adapterName(ms);
120            Map.Entry<MaleSocketXml, Element> entry = maleSocketXmlClasses.get(cName);
121            
122            try {
123                entry.getKey().load(entry.getValue(), ms);
124            } catch (RuntimeException ex) {
125                log.error("Error loading maleSocket: {}", ex, ex);
126            }
127
128            m = ms.getObject();
129        }
130        
131    }
132
133
134    private final static org.slf4j.Logger log = org.slf4j.LoggerFactory.getLogger(AbstractManagerXml.class);
135}