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