001package jmri.jmrit.logixng;
002
003import java.io.PrintWriter;
004import java.util.List;
005import java.util.Locale;
006
007import org.apache.commons.lang3.mutable.MutableInt;
008
009import jmri.Manager;
010import jmri.jmrit.logixng.Base.PrintTreeSettings;
011
012/**
013 * Manager for LogixNG modules
014 * 
015 * @author Dave Duchamp       Copyright (C) 2007
016 * @author Daniel Bergqvist   Copyright (C) 2020
017 */
018public interface ModuleManager extends Manager<Module> {
019
020    /**
021     * Create a new Module if the Module does not exist.
022     *
023     * @param systemName the system name
024     * @param userName   the user name
025     * @param socketType the socket type
026     * @return a new Module or null if unable to create
027     * @throws IllegalArgumentException when needed
028     */
029    Module createModule(String systemName, String userName,
030            FemaleSocketManager.SocketType socketType)
031            throws IllegalArgumentException;
032    
033    /**
034     * For use with User GUI, to allow the auto generation of systemNames, where
035     * the user can optionally supply a username.
036     *
037     * @param userName the user name
038     * @param socketType the socket type
039     * @return a new Module or null if unable to create
040     * @throws IllegalArgumentException when needed
041     */
042    Module createModule(String userName, FemaleSocketManager.SocketType socketType)
043            throws IllegalArgumentException;
044    
045    /**
046     * Locate via user name, then system name if needed. Does not create a new
047     * one if nothing found
048     *
049     * @param name User name or system name to match
050     * @return null if no match found
051     */
052    Module getModule(String name);
053    
054    /** {@inheritDoc} */
055    @Override
056    Module getByUserName(String name);
057    
058    /** {@inheritDoc} */
059    @Override
060    Module getBySystemName(String name);
061    
062    /**
063     * Create a new system name for a Module.
064     * @return a new system name
065     */
066    String getAutoSystemName();
067    
068    /**
069     * Resolve all the Module trees.
070     * <P>
071     * This method ensures that everything in the Module tree has a pointer
072     * to its parent.
073     * 
074     * @param errors a list of potential errors
075     * @return true if success, false otherwise
076     */
077    boolean resolveAllTrees(List<String> errors);
078
079    /**
080     * Setup all Modules. This method is called after a configuration file is
081     * loaded.
082     */
083    void setupAllModules();
084
085    /*.*
086     * Activate all Modules, starts Module processing by connecting all
087     * inputs that are included the ConditionalNGs in this Module.
088     * <p>
089     * A Module must be activated before it will calculate any of its
090     * ConditionalNGs.
091     *./
092    void activateAllModules();
093*/    
094    /**
095     * Delete Module by removing it from the manager. The Module must first
096     * be deactivated so it stops processing.
097     *
098     * @param x the Module to delete
099     */
100    void deleteModule(Module x);
101
102    /*.*
103     * Support for loading Modules in a disabled state
104     * 
105     * @param s true if Module should be disabled when loaded
106     *./
107    void setLoadDisabled(boolean s);
108*/    
109    /**
110     * Print the tree to a stream.
111     * 
112     * @param settings settings for what to print
113     * @param writer the stream to print the tree to
114     * @param indent the indentation of each level
115     * @param lineNumber the line number
116     */
117    void printTree(
118            PrintTreeSettings settings,
119            PrintWriter writer,
120            String indent,
121            MutableInt lineNumber);
122    
123    /**
124     * Print the tree to a stream.
125     * 
126     * @param settings settings for what to print
127     * @param locale The locale to be used
128     * @param writer the stream to print the tree to
129     * @param indent the indentation of each level
130     * @param lineNumber the line number
131     */
132    void printTree(
133            PrintTreeSettings settings,
134            Locale locale,
135            PrintWriter writer,
136            String indent,
137            MutableInt lineNumber);
138    
139    /**
140     * Test if parameter is a properly formatted system name.
141     * <P>
142     * This method should only be used by the managers of the Module system.
143     *
144     * @param subSystemNamePrefix the sub system prefix
145     * @param systemName the system name
146     * @return enum indicating current validity, which might be just as a prefix
147     */
148    static NameValidity validSystemNameFormat(String subSystemNamePrefix, String systemName) {
149        // System names with digits. :AUTO: is generated system names
150        if (systemName.matches(subSystemNamePrefix+"(:AUTO:)?\\d+")) {
151            return NameValidity.VALID;
152            
153        // System names with dollar sign allow any characters in the name
154        } else if (systemName.matches(subSystemNamePrefix+"\\$.+")) {
155            return NameValidity.VALID;
156            
157        // System names with :JMRI: belongs to JMRI itself
158        } else if (systemName.matches(subSystemNamePrefix+":JMRI:.+")) {
159            return NameValidity.VALID;
160            
161        // System names with :JMRI-LIB: belongs to software that uses JMRI as a lib
162        } else if (systemName.matches(subSystemNamePrefix+":JMRI-LIB:.+")) {
163            return NameValidity.VALID;
164            
165        // Other system names are not valid
166        } else {
167//            LoggerFactory.getLogger(Module_Manager.class)
168//                    .warn("system name {} is invalid for sub system prefix {}",
169//                            systemName, subSystemNamePrefix);
170            return NameValidity.INVALID;
171        }
172    }
173    
174    /**
175     * {@inheritDoc}
176     * 
177     * The sub system prefix for the DigitalActionManager is
178     * {@link #getSystemNamePrefix() } and "DA";
179     */
180    @Override
181    default String getSubSystemNamePrefix() {
182        return getSystemNamePrefix() + "M";
183    }
184    
185}