001package jmri.jmrix.openlcb; 002 003import java.util.*; 004 005import javax.annotation.Nonnull; 006 007import jmri.StringIO; 008import jmri.jmrix.can.CanSystemConnectionMemo; 009 010/** 011 * Implement a StringIOManager for OpenLCB StringIOs. 012 * 013 * @author Bob Jacobsen Copyright (C) 2024 014 * @author Daniel Bergqvist Copyright (C) 2020 015 */ 016public class OlcbStringIOManager extends jmri.managers.AbstractStringIOManager { 017 018 // Whether we accumulate partially loaded objects in pendingStringIOs. 019 private boolean isLoading = false; 020 // Turnouts that are being loaded from XML. 021 private final ArrayList<OlcbStringIO> pendingStringIOs = new ArrayList<>(); 022 023 public OlcbStringIOManager(CanSystemConnectionMemo memo) { 024 super(memo); 025 } 026 027 /** 028 * {@inheritDoc} 029 */ 030 @Override 031 @Nonnull 032 public CanSystemConnectionMemo getMemo() { 033 return (CanSystemConnectionMemo) memo; 034 } 035 036 @Override 037 @Nonnull 038 public StringIO provideStringIO(@Nonnull String sName) throws IllegalArgumentException { 039 String name = sName.substring(getSystemPrefix().length()+1); 040 return new OlcbStringIO(getSystemPrefix(), name, (CanSystemConnectionMemo) memo); 041 } 042 043 /** {@inheritDoc} */ 044 @Override 045 @Nonnull 046 public StringIO provide(@Nonnull String name) throws IllegalArgumentException { 047 return provideStringIO(name); 048 } 049 050 @Override 051 @Nonnull 052 public StringIO createNewStringIO(String sName, String uName) { 053 String name = sName.substring(getSystemPrefix().length()+1); // plus one for type letter 054 var s = new OlcbStringIO(getSystemPrefix(), name, (CanSystemConnectionMemo) memo); 055 if (uName != null) s.setUserName(uName); 056 synchronized (pendingStringIOs) { 057 if (isLoading) { 058 pendingStringIOs.add(s); 059 } else { 060 s.finishLoad(); 061 } 062 } 063 return s; 064 } 065 066 /** 067 * This function is invoked before an XML load is started. We defer initialization of the 068 * newly created Sensors until finishLoad because the feedback type might be changing as we 069 * are parsing the XML. 070 */ 071 public void startLoad() { 072 log.debug("StringIO manager : start load"); 073 synchronized (pendingStringIOs) { 074 isLoading = true; 075 } 076 } 077 078 /** 079 * This function is invoked after the XML load is complete and all Sensors are instantiated 080 * and their feedback type is read in. We use this hook to finalize the construction of the 081 * OpenLCB objects whose instantiation was deferred until the feedback type was known. 082 */ 083 public void finishLoad() { 084 log.debug("StringIO manager : finish load"); 085 synchronized (pendingStringIOs) { 086 pendingStringIOs.forEach(OlcbStringIO::finishLoad); 087 pendingStringIOs.clear(); 088 isLoading = false; 089 } 090 } 091 092 /** {@inheritDoc} */ 093 @Override 094 public String getEntryToolTip() { 095 return Bundle.getMessage("AddStringIOEntryToolTip"); 096 } 097 098 /** 099 * Validates to OpenLCB format. 100 * {@inheritDoc} 101 */ 102 @Override 103 @Nonnull 104 public String validateSystemNameFormat(@Nonnull String name, @Nonnull java.util.Locale locale) throws jmri.NamedBean.BadSystemNameException { 105 name = super.validateSystemNameFormat(name,locale); 106 name = OlcbAddress.validateSystemNameFormat(name,locale,getSystemNamePrefix(), (CanSystemConnectionMemo) memo); 107 return name; 108 } 109 110 private static final org.slf4j.Logger log = org.slf4j.LoggerFactory.getLogger(OlcbStringIOManager.class); 111}