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