001package jmri.jmrit.logixng;
002
003import java.io.PrintWriter;
004import java.util.Locale;
005import java.util.Map;
006
007import org.apache.commons.lang3.mutable.MutableInt;
008
009import jmri.Manager;
010import jmri.jmrit.logixng.Base.PrintTreeSettings;
011
012/**
013 * Manager for LogixNG
014 *
015 * @author Dave Duchamp       Copyright (C) 2007
016 * @author Daniel Bergqvist   Copyright (C) 2018
017 */
018public interface LogixNG_Manager extends Manager<LogixNG> {
019
020    /**
021     * This property is fired when the {@link #setupAllLogixNGs()} method is completed.
022     */
023    public static final String PROPERTY_SETUP = "LogixNG_Setup";
024
025    /**
026     * This is the name of the error handling module.
027     */
028    public static final String ERROR_HANDLING_MODULE_NAME = "IQM:JMRI:ErrorHandlingModule";
029
030    /**
031     * Create a new LogixNG if the LogixNG does not exist.
032     *
033     * @param systemName the system name
034     * @param userName   the user name
035     * @return a new LogixNG or null if unable to create
036     * @throws IllegalArgumentException when needed
037     */
038    LogixNG createLogixNG(String systemName, String userName)
039            throws IllegalArgumentException;
040
041    /**
042     * Create a new LogixNG if the LogixNG does not exist.
043     *
044     * @param systemName the system name
045     * @param userName   the user name
046     * @param inline     true if this LogixNG is an inline LogixNG
047     * @return a new LogixNG or null if unable to create
048     * @throws IllegalArgumentException when needed
049     */
050    LogixNG createLogixNG(String systemName, String userName, boolean inline)
051            throws IllegalArgumentException;
052
053    /**
054     * For use with User GUI, to allow the auto generation of systemNames, where
055     * the user can optionally supply a username.
056     *
057     * @param userName the user name
058     * @return a new LogixNG or null if unable to create
059     * @throws IllegalArgumentException when needed
060     */
061    LogixNG createLogixNG(String userName)
062            throws IllegalArgumentException;
063
064    /**
065     * For use with User GUI, to allow the auto generation of systemNames, where
066     * the user can optionally supply a username.
067     *
068     * @param userName  the user name
069     * @param inline    true if this LogixNG is an inline LogixNG
070     * @return a new LogixNG or null if unable to create
071     * @throws IllegalArgumentException when needed
072     */
073    LogixNG createLogixNG(String userName, boolean inline)
074            throws IllegalArgumentException;
075
076    /**
077     * Locate via user name, then system name if needed. Does not create a new
078     * one if nothing found
079     *
080     * @param name User name or system name to match
081     * @return null if no match found
082     */
083    LogixNG getLogixNG(String name);
084
085    /** {@inheritDoc} */
086    @Override
087    LogixNG getByUserName(String name);
088
089    /** {@inheritDoc} */
090    @Override
091    LogixNG getBySystemName(String name);
092
093    /**
094     * Create a new system name for a LogixNG.
095     * @return a new system name
096     */
097    String getAutoSystemName();
098
099    /**
100     * Should the LogixNGs be disabled when the configuration file is loaded?
101     * @param value true if they should be disabled, false otherwise.
102     */
103    void setLoadDisabled(boolean value);
104
105    /**
106     * Should the LogixNGs be started when the configuration file is loaded?
107     * @param value true if they should be started, false otherwise.
108     */
109    void startLogixNGsOnLoad(boolean value);
110
111    /**
112     * Should the LogixNGs not be started when the configuration file is loaded?
113     * @return true if they should be started, false otherwise.
114     */
115    boolean isStartLogixNGsOnLoad();
116
117    /**
118     * Setup all LogixNGs. This method is called after a configuration file is
119     * loaded.
120     */
121    void setupAllLogixNGs();
122
123    /**
124     * Activate all LogixNGs, starts LogixNG processing by connecting all
125     * inputs that are included the ConditionalNGs in this LogixNG.
126     * <p>
127     * A LogixNG must be activated before it will calculate any of its
128     * ConditionalNGs.
129     */
130    void activateAllLogixNGs();
131
132    /**
133     * Activate all LogixNGs, starts LogixNG processing by connecting all
134     * inputs that are included the ConditionalNGs in this LogixNG.
135     * <p>
136     * A LogixNG must be activated before it will calculate any of its
137     * ConditionalNGs.
138     *
139     * @param runDelayed true if execute() should run on LogixNG thread delayed,
140     *                   false otherwise.
141     * @param runOnSeparateThread true if the activation should run on a
142     *                            separate thread, false otherwise
143     */
144    void activateAllLogixNGs(boolean runDelayed, boolean runOnSeparateThread);
145
146    /**
147     * DeActivate all LogixNGs, stops LogixNG processing by disconnecting all
148     * inputs that are included the ConditionalNGs in this LogixNG.
149     * <p>
150     * A LogixNG must be activated before it will calculate any of its
151     * ConditionalNGs.
152     */
153    void deActivateAllLogixNGs();
154
155    /**
156     * Is LogixNGs active?
157     * @return true if LogixNGs are active, false otherwise
158     */
159    boolean isActive();
160
161    /**
162     * Delete LogixNG by removing it from the manager. The LogixNG must first
163     * be deactivated so it stops processing.
164     *
165     * @param x the LogixNG to delete
166     */
167    void deleteLogixNG(LogixNG x);
168
169    /**
170     * Print the tree to a stream.
171     *
172     * @param writer the stream to print the tree to
173     * @param indent the indentation of each level
174     * @param lineNumber the line number
175     */
176    default void printTree(
177            PrintWriter writer,
178            String indent,
179            MutableInt lineNumber) {
180
181        printTree(new PrintTreeSettings(), writer, indent, lineNumber);
182    }
183
184    /**
185     * Print the tree to a stream.
186     *
187     * @param settings settings for what to print
188     * @param writer the stream to print the tree to
189     * @param indent the indentation of each level
190     * @param lineNumber the line number
191     */
192    void printTree(
193            PrintTreeSettings settings,
194            PrintWriter writer,
195            String indent,
196            MutableInt lineNumber);
197
198    /**
199     * Print the tree to a stream.
200     *
201     * @param locale The locale to be used
202     * @param writer the stream to print the tree to
203     * @param indent the indentation of each level
204     * @param lineNumber the line number
205     */
206    default void printTree(
207            Locale locale,
208            PrintWriter writer,
209            String indent,
210            MutableInt lineNumber) {
211
212        printTree(new PrintTreeSettings(), locale, writer, indent, lineNumber);
213    }
214
215    /**
216     * Print the tree to a stream.
217     *
218     * @param settings settings for what to print
219     * @param locale The locale to be used
220     * @param writer the stream to print the tree to
221     * @param indent the indentation of each level
222     * @param lineNumber the line number
223     */
224    void printTree(
225            PrintTreeSettings settings,
226            Locale locale,
227            PrintWriter writer,
228            String indent,
229            MutableInt lineNumber);
230
231    /**
232     * Test if parameter is a properly formatted system name.
233     * <P>
234     * This method should only be used by the managers of the LogixNG system.
235     *
236     * @param subSystemNamePrefix the sub system prefix
237     * @param systemName the system name
238     * @return enum indicating current validity, which might be just as a prefix
239     */
240    static NameValidity validSystemNameFormat(String subSystemNamePrefix, String systemName) {
241        // System names with digits. :AUTO: is generated system names
242        if (systemName.matches(subSystemNamePrefix+"(:AUTO:)?\\d+")) {
243            return NameValidity.VALID;
244
245        // System names with dollar sign allow any characters in the name
246        } else if (systemName.matches(subSystemNamePrefix+"\\$.+")) {
247            return NameValidity.VALID;
248
249        // System names with :JMRI: belongs to JMRI itself
250        } else if (systemName.matches(subSystemNamePrefix+":JMRI:.+")) {
251            return NameValidity.VALID;
252
253        // System names with :JMRI-LIB: belongs to software that uses JMRI as a lib
254        } else if (systemName.matches(subSystemNamePrefix+":JMRI-LIB:.+")) {
255            return NameValidity.VALID;
256
257        // Other system names are not valid
258        } else {
259//            LoggerFactory.getLogger(LogixNG_Manager.class)
260//                    .warn("system name {} is invalid for sub system prefix {}",
261//                            systemName, subSystemNamePrefix);
262            return NameValidity.INVALID;
263        }
264    }
265
266    /**
267     * Get the clipboard
268     * @return the clipboard
269     */
270    Clipboard getClipboard();
271
272    /**
273     * Register a manager for later retrieval by getManager()
274     * @param manager the manager
275     */
276    void registerManager(Manager<? extends MaleSocket> manager);
277
278    /**
279     * Get manager by class name
280     * @param className the class name of the manager
281     * @return the manager
282     */
283    Manager<? extends MaleSocket> getManager(String className);
284
285    /**
286     * Register a task to be run when setup LogixNGs
287     * @param task the task
288     */
289    void registerSetupTask(Runnable task);
290
291    /**
292     * Executes a LogixNG Module.
293     * Note that the module must be a Digital Action Module.
294     * @param module     The module to be executed
295     * @param parameter  The parameter. The module must have exactly one parameter.
296     * @throws IllegalArgumentException If module is null or if module is not a
297     *                   DigitalActionModule.
298     */
299    void executeModule(Module module, Object parameter)
300            throws IllegalArgumentException;
301
302    /**
303     * Executes a LogixNG Module.
304     * Note that the module must be a Digital Action Module.
305     * @param module      The module to be executed
306     * @param parameters  The parameters
307     * @throws IllegalArgumentException If module or parameters is null or if module
308     *                    is not a DigitalActionModule.
309     */
310    void executeModule(Module module, Map<String, Object> parameters)
311            throws IllegalArgumentException;
312
313    /**
314     * Get the female socket of the error handling module.
315     * @return the socket.
316     */
317    FemaleSocket getErrorHandlingModuleSocket();
318
319    /**
320     * Is the error handling module enabled?
321     * It's enabled if it exists and the root socket is connected.
322     * @return true if it's in use, false otherwise.
323     */
324    boolean isErrorHandlingModuleEnabled();
325
326}