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}