001package jmri.jmrix.openlcb; 002 003import java.util.ArrayList; 004import java.util.List; 005import javax.annotation.Nonnull; 006import jmri.BooleanPropertyDescriptor; 007import jmri.Light; 008import jmri.NamedBean; 009import jmri.NamedBeanPropertyDescriptor; 010import jmri.managers.AbstractLightManager; 011import jmri.jmrix.can.CanSystemConnectionMemo; 012 013/** 014 * 015 * @author jcollell 016 */ 017public class OlcbLightManager extends AbstractLightManager { 018 019 public OlcbLightManager(CanSystemConnectionMemo memo) { 020 super(memo); 021 } 022 023 // Whether we accumulate partially loaded lights in pendingLights. 024 private boolean isLoading = false; 025 // Lights that are being loaded from XML. 026 private final ArrayList<OlcbLight> pendingLights = new ArrayList<>(); 027 028 /** 029 * {@inheritDoc} 030 */ 031 @Override 032 @Nonnull 033 public CanSystemConnectionMemo getMemo() { 034 return (CanSystemConnectionMemo) memo; 035 } 036 037 @Override 038 @Nonnull 039 public List<NamedBeanPropertyDescriptor<?>> getKnownBeanProperties() { 040 List<NamedBeanPropertyDescriptor<?>> l = new ArrayList<>(); 041 l.add(new BooleanPropertyDescriptor(OlcbUtils.PROPERTY_IS_AUTHORITATIVE, OlcbLight 042 .DEFAULT_IS_AUTHORITATIVE) { 043 @Override 044 public String getColumnHeaderText() { 045 return Bundle.getMessage("OlcbStateAuthHeader"); 046 } 047 048 @Override 049 public boolean isEditable(NamedBean bean) { 050 return OlcbUtils.isOlcbBean(bean); 051 } 052 }); 053 l.add(new BooleanPropertyDescriptor(OlcbUtils.PROPERTY_LISTEN, OlcbLight 054 .DEFAULT_LISTEN) { 055 @Override 056 public String getColumnHeaderText() { 057 return Bundle.getMessage("OlcbStateListenHeader"); 058 } 059 060 @Override 061 public boolean isEditable(NamedBean bean) { 062 return OlcbUtils.isOlcbBean(bean); 063 } 064 }); 065 return l; 066 } 067 068 /** 069 * Internal method to invoke the factory, after all the logic for returning 070 * an existing method has been invoked. 071 * 072 * @return never null 073 */ 074 @Override 075 @Nonnull 076 protected Light createNewLight(@Nonnull String systemName, String userName) throws IllegalArgumentException { 077 String addr = systemName.substring(getSystemPrefix().length() + 1); 078 OlcbLight l = new OlcbLight(getSystemPrefix(), addr, (CanSystemConnectionMemo)memo); 079 l.setUserName(userName); 080 synchronized (pendingLights) { 081 if (isLoading) { 082 pendingLights.add(l); 083 } else { 084 l.finishLoad(); 085 } 086 } 087 return l; 088 } 089 090 /** 091 * This function is invoked before an XML load is started. We defer initialization of the 092 * newly created lights until finishLoad because the feedback type might be changing as we 093 * are parsing the XML. 094 */ 095 public void startLoad() { 096 synchronized (pendingLights) { 097 isLoading = true; 098 } 099 } 100 101 /** 102 * This function is invoked after the XML load is complete and all lights are instantiated 103 * and their feedback type is read in. We use this hook to finalize the construction of the 104 * OpenLCB objects whose instantiation was deferred until the feedback type was known. 105 */ 106 public void finishLoad() { 107 synchronized (pendingLights) { 108 for (OlcbLight l : pendingLights) { 109 l.finishLoad(); 110 } 111 pendingLights.clear(); 112 isLoading = false; 113 } 114 } 115 116 @Override 117 public boolean allowMultipleAdditions(@Nonnull String systemName) { 118 return false; 119 } 120 121 @Override 122 public boolean validSystemNameConfig(@Nonnull String address) throws IllegalArgumentException { 123 124 if (address.startsWith("+") || address.startsWith("-")) { 125 return false; 126 } 127 try { 128 OlcbAddress.validateSystemNameFormat(address,java.util.Locale.getDefault(),getSystemNamePrefix(), (CanSystemConnectionMemo)memo); 129 } 130 catch ( jmri.NamedBean.BadSystemNameException ex ){ 131 throw new IllegalArgumentException(ex.getMessage()); 132 } 133 return true; 134 } 135 136 /** 137 * Validates to OpenLCB format. 138 * {@inheritDoc} 139 */ 140 @Override 141 @Nonnull 142 public String validateSystemNameFormat(@Nonnull String name, @Nonnull java.util.Locale locale) throws jmri.NamedBean.BadSystemNameException { 143 super.validateSystemNameFormat(name,locale); 144 name = OlcbAddress.validateSystemNameFormat(name,locale,getSystemNamePrefix(), (CanSystemConnectionMemo) memo); 145 return name; 146 } 147 148 /** 149 * {@inheritDoc} 150 */ 151 @Override 152 public String getEntryToolTip() { 153 return Bundle.getMessage("AddLightEntryToolTip"); 154 } 155}