001package jmri.implementation;
002
003import edu.umd.cs.findbugs.annotations.SuppressFBWarnings;
004import java.util.List;
005import jmri.AddressedProgrammer;
006import jmri.Programmer;
007import org.jdom2.Element;
008import org.slf4j.Logger;
009import org.slf4j.LoggerFactory;
010
011/**
012 * Utility to load a specific ProgrammerFacade from an XML element.
013 *
014 * @author Bob Jacobsen Copyright (C) 2013
015 */
016public class ProgrammerFacadeSelector {
017
018    /**
019     * Add facades specified in an XML decoder definition element to the front
020     * of a programmer.
021     *
022     * @param element    Contains "capability" elements that define the Facades
023     * @param programmer Programmer implementation to decorate
024     * @param allowCache Passed to facades that optionally cache
025     * @param baseProg   The original underlying programmer, less any facades
026     * @return the programmer with added facades
027     */
028    @SuppressFBWarnings(value = "BC_UNCONFIRMED_CAST",
029            justification = "cast is checked by conditional surrounding the code block")  // NOI18N
030    public static Programmer loadFacadeElements(
031            Element element, Programmer programmer, boolean allowCache, Programmer baseProg) {
032        // iterate over any facades and add them
033        List<Element> facades = element.getChildren("capability");
034        if (log.isDebugEnabled()) {
035            log.debug("Found {} capability elements", facades.size());
036        }
037        for (Element facade : facades) {
038            String fname = facade.getChild("name").getText();
039            if (log.isDebugEnabled()) {
040                log.debug("Process capability facade: {}", fname);
041            }
042
043            List<Element> parameters = facade.getChildren("parameter");
044            if (log.isDebugEnabled()) {
045                log.debug("Found {} capability parameters", facades.size());
046            }
047            for (Element parameter : parameters) {
048                String pname = parameter.getAttributeValue("name");
049                String pval = parameter.getText();
050                log.debug("Found parameter name=\"{}\", value=\"{}\" ", pname, pval);
051            }
052
053            switch (fname) {
054                case "High Access via Double Index": {
055                    String top = parameters.get(0).getText();
056                    String addrCVhigh = parameters.get(1).getText();
057                    String addrCVlow = parameters.get(2).getText();
058                    String valueCV = parameters.get(3).getText();
059                    String modulo = parameters.get(4).getText();
060                    jmri.implementation.AddressedHighCvProgrammerFacade pf
061                            = new jmri.implementation.AddressedHighCvProgrammerFacade(programmer, top, addrCVhigh, addrCVlow, valueCV, modulo);
062                    log.debug("new programmer '{}' {}", fname, pf);
063                    programmer = pf; // to go around and see if there are more
064                    break;
065                }
066                case "High Access via Partial Index": {
067                    String top = parameters.get(0).getText();
068                    String addrCV = parameters.get(1).getText();
069                    String factor = parameters.get(2).getText();
070                    String modulo = parameters.get(3).getText();
071                    jmri.implementation.OffsetHighCvProgrammerFacade pf
072                            = new jmri.implementation.OffsetHighCvProgrammerFacade(programmer, top, addrCV, factor, modulo);
073                    log.debug("new programmer '{}' {}", fname, pf);
074                    programmer = pf; // to go around and see if there are more
075                    break;
076                }
077                case "High Access via Partial Index with Reset": {
078                    String top = parameters.get(0).getText();
079                    String addrCV = parameters.get(1).getText();
080                    String factor = parameters.get(2).getText();
081                    String modulo = parameters.get(3).getText();
082                    String indicator = parameters.get(4).getText();
083                    jmri.implementation.ResettingOffsetHighCvProgrammerFacade pf
084                            = new jmri.implementation.ResettingOffsetHighCvProgrammerFacade(programmer, top, addrCV, factor, modulo, indicator);
085                    log.debug("new programmer '{}' {}", fname, pf);
086                    programmer = pf; // to go around and see if there are more
087                    break;
088                }
089                case "Indexed CV access": {
090                    String PI = parameters.get(0).getText();
091                    String SI = (parameters.size() > 1) ? parameters.get(1).getText() : null;
092                    boolean cvFirst = (parameters.size() > 2) ? (!parameters.get(2).getText().equals("false")) : true;
093                    boolean skipDupIndexWrite = (parameters.size() > 3) ? (parameters.get(3).getText().equals("false") ? false : allowCache) : allowCache; // if not present, use default
094                    jmri.implementation.MultiIndexProgrammerFacade pf
095                            = new jmri.implementation.MultiIndexProgrammerFacade(programmer, PI, SI, cvFirst, skipDupIndexWrite);
096                    log.debug("new programmer '{}' {}", fname, pf);
097                    programmer = pf; // to go around and see if there are more
098                    break;
099                }
100                case "TCS 4 CV access": {
101                    jmri.implementation.TwoIndexTcsProgrammerFacade pf
102                            = new jmri.implementation.TwoIndexTcsProgrammerFacade(programmer);
103                    log.debug("new programmer '{}' {}", fname, pf);
104                    programmer = pf; // to go around and see if there are more
105                    break;
106                }
107                case "Ops Mode Accessory Programming":
108                    if (AddressedProgrammer.class.isAssignableFrom(baseProg.getClass())) {  // create if relevant to current mode, otherwise silently ignore
109                        String addrType = "decoder";
110                        int delay = 500;
111                        for (Element x : parameters) {
112                            switch (x.getAttributeValue("name")) {
113                                case "Address Type":
114                                    addrType = x.getText();
115                                    break;
116                                case "Delay":
117                                    delay = Integer.parseInt(x.getText());
118                                    break;
119                                default:
120                                    log.error("Unknown parameter \"{}\" for \"{}\"", fname, x.getText());
121                                    break;
122                            }
123                        }
124                        log.debug("\"{}\": addrType=\"{}\", delay=\"{}\", baseProg=\"{}\"", fname, addrType, delay, baseProg);
125
126                        jmri.implementation.AccessoryOpsModeProgrammerFacade pf
127                                = new jmri.implementation.AccessoryOpsModeProgrammerFacade(programmer, addrType, delay, (AddressedProgrammer) baseProg);
128                        log.debug("new programmer '{}' {}", fname, pf);
129                        programmer = pf; // to go around and see if there are more
130                    }
131                    break;
132                case "Ops Mode Delayed Programming":
133                    if (AddressedProgrammer.class.isAssignableFrom(baseProg.getClass())) {  // create if relevant to current mode, otherwise silently ignore
134                        int delay = 500;
135                        for (Element x : parameters) {
136                            switch (x.getAttributeValue("name")) {
137                                case "Delay":
138                                    delay = Integer.parseInt(x.getText());
139                                    break;
140                                default:
141                                    log.error("Unknown parameter \"{}\" for \"{}\"", fname, x.getText());
142                                    break;
143                            }
144                        }
145                        log.debug("\"{}\": delay=\"{}\"", fname, delay);
146                        jmri.implementation.OpsModeDelayedProgrammerFacade pf
147                                = new jmri.implementation.OpsModeDelayedProgrammerFacade(programmer, delay);
148                        log.debug("new programmer '{}' {}", fname, pf);
149                        programmer = pf; // to go around and see if there are more
150                    }
151                    break;
152                default:
153                    log.error("Cannot create programmer capability named: \"{}\"", fname);
154                    break;
155            }
156        }
157
158        return programmer;
159    }
160
161    private final static Logger log = LoggerFactory.getLogger(ProgrammerFacadeSelector.class);
162}