001package jmri;
002
003import javax.annotation.CheckForNull;
004import javax.annotation.CheckReturnValue;
005import javax.annotation.Nonnull;
006
007/**
008 * Interface for obtaining Lights.
009 * <p>
010 * This doesn't have a "new" method, as Lights are separately implemented,
011 * instead of being system-specific.
012 * <p>
013 * Based on SignalHeadManager.java
014 * <hr>
015 * This file is part of JMRI.
016 * <p>
017 * JMRI is free software; you can redistribute it and/or modify it under the
018 * terms of version 2 of the GNU General Public License as published by the Free
019 * Software Foundation. See the "COPYING" file for a copy of this license.
020 * <p>
021 * JMRI is distributed in the hope that it will be useful, but WITHOUT ANY
022 * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
023 * A PARTICULAR PURPOSE. See the GNU General Public License for more details.
024 *
025 * @author Dave Duchamp Copyright (C) 2004
026 */
027public interface LightManager extends ProvidingManager<Light>, NameIncrementingManager {
028
029    /**
030     * Get the Light with the user name, then system name if needed; if that fails, create a
031     * new Light.
032     * If the name is a valid system name, it will be used for the new Light.
033     * Otherwise, the {@link Manager#makeSystemName} method will attempt to turn it
034     * into a valid system name.
035     * <p>This provides the same function as {@link ProvidingManager#provide}
036     * which has a more generic form.
037     *
038     * @param name User name, system name, or address which can be promoted to
039     *             system name
040     * @return Never null under normal circumstances
041     */
042    @Nonnull
043    Light provideLight(@Nonnull String name) throws IllegalArgumentException;
044
045    /** {@inheritDoc} */
046    @Override
047    @Nonnull
048    default Light provide(@Nonnull String name) throws IllegalArgumentException { return provideLight(name); }
049
050    /** {@inheritDoc} */
051    @Override
052    void dispose();
053
054    /**
055     * Get an existing Light or return null if it doesn't exist.
056     * <p>
057     * Locates via user name, then system name if needed.
058     * @param name User name, system name, or address which can be promoted to
059     *             system name
060     * @return Light, or null if no existing Light.
061     */
062    @CheckReturnValue
063    @CheckForNull
064    Light getLight(@Nonnull String name);
065
066    /**
067     * Return a Light with the specified user or system name.
068     * Lookup Light by UserName, then Provide New Light by SystemName.
069     * Note that
070     * two calls with the same arguments will get the same instance; there is
071     * only one Light object representing a given physical Light and therefore
072     * only one with a specific system or user name.
073     * <p>
074     * This will always return a valid object reference; a new object will be
075     * created if necessary. In that case:
076     * <ul>
077     * <li>If a null reference is given for user name, no user name will be
078     * associated with the Light object created; a valid system name must be
079     * provided
080     * <li>If both names are provided, the system name defines the hardware
081     * access of the desired sensor, and the user address is associated with it.
082     * The system name must be valid.
083     * </ul>
084     * Note that it is possible to make an inconsistent request if both
085     * addresses are provided, but the given values are associated with
086     * different objects. This is a problem, and we don't have a good solution
087     * except to issue warnings. This will mostly happen if you're creating
088     * Lights when you should be looking them up.
089     *
090     * @param systemName the desired system name
091     * @param userName   the desired user name
092     * @return requested Light object (never null)
093     * @throws IllegalArgumentException if cannot create the Light due to e.g.
094     *                                  an illegal name or name that can't be
095     *                                  parsed.
096     */
097    @Nonnull
098    Light newLight(@Nonnull String systemName, @CheckForNull String userName) throws IllegalArgumentException;
099
100    /**
101     * Locate a Light by its user name.
102     *
103     * @param s the user name
104     * @return the light or null if not found
105     */
106    @CheckReturnValue
107    @CheckForNull
108    @Override
109    Light getByUserName(@Nonnull String s);
110
111    /**
112     * Locate a Light by its system name.
113     *
114     * @param s the system name
115     * @return the light or null if not found
116     */
117    @CheckReturnValue
118    @CheckForNull
119    @Override
120    Light getBySystemName(@Nonnull String s);
121
122    /**
123     * Test if parameter is a valid system name for current configuration.
124     *
125     * @param systemName the system name
126     * @return true if valid; false otherwise
127     */
128    @CheckReturnValue
129    default boolean validSystemNameConfig(@Nonnull String systemName){
130        try {
131            validateSystemNameFormat(systemName);
132            return true;
133        } catch (jmri.NamedBean.BadSystemNameException ex) {
134            return false;
135        }
136    }
137
138    /**
139     * Convert the system name to a normalized alternate name.
140     * <p>
141     * This routine is to allow testing to ensure that two Lights with alternate
142     * names that refer to the same output bit are not created.
143     * <p>
144     * This routine is implemented in AbstractLightManager to return "". If a
145     * system implementation has alternate names, the system specific Light
146     * Manager should override this routine and supply the alternate name.
147     *
148     * @param systemName the system name to convert
149     * @return an alternate name
150     */
151    @CheckReturnValue
152    @Nonnull
153    String convertSystemNameToAlternate(@Nonnull String systemName);
154
155    /**
156     * Activate the control mechanism for each Light controlled by this
157     * LightManager. Note that some Lights don't require any activation. The
158     * activateLight method in AbstractLight.java determines what needs to be
159     * done for each Light.
160     */
161    void activateAllLights();
162
163    /**
164     * Test if system in the given name can support a variable light.
165     *
166     * @param systemName the system name
167     * @return true if variable lights are supported; false otherwise
168     */
169    @CheckReturnValue
170    boolean supportsVariableLights(@Nonnull String systemName);
171
172    /**
173     * Get a system name for a given hardware address and system prefix.
174     *
175     * @param curAddress desired hardware address
176     * @param prefix     system prefix used in system name, excluding Bean type-letter.
177     * @return the complete Light system name for the prefix and current
178     *         address
179     * @throws jmri.JmriException if unable to create a system name for the
180     *                            given address, possibly due to invalid address
181     *                            format
182     */
183    @Nonnull
184    String createSystemName(@Nonnull String curAddress, @Nonnull String prefix) throws JmriException;
185
186}