001package jmri.managers;
002
003import java.io.File;
004import java.net.URISyntaxException;
005import java.util.ArrayList;
006import java.util.List;
007
008import javax.annotation.CheckForNull;
009import javax.annotation.Nonnull;
010
011import jmri.Manager;
012import jmri.SignalGroup;
013import jmri.SignalGroupManager;
014import jmri.implementation.DefaultSignalGroup;
015import jmri.jmrix.internal.InternalSystemConnectionMemo;
016import jmri.util.FileUtil;
017
018import org.slf4j.Logger;
019import org.slf4j.LoggerFactory;
020
021/**
022 * Default implementation of a SignalGroupManager.
023 * <p>
024 * This loads automatically the first time used.
025 *
026 * @author Bob Jacobsen Copyright (C) 2009, 2018
027 */
028public class DefaultSignalGroupManager extends AbstractManager<SignalGroup>
029        implements SignalGroupManager {
030
031    public DefaultSignalGroupManager(InternalSystemConnectionMemo memo) {
032        super(memo);
033
034        // load when created, which will generally
035        // be the first time referenced
036        //load();
037    }
038
039    @Override
040    public int getXMLOrder() {
041        return Manager.SIGNALGROUPS;
042    }
043
044    @Override
045    public char typeLetter() {
046        return 'G'; // according to JMRI: Names and Naming
047    }
048
049    /** {@inheritDoc} */
050    @CheckForNull
051    @Override
052    public SignalGroup getSignalGroup(@Nonnull String name) {
053        SignalGroup t = getByUserName(name);
054        if (t != null) {
055            return t;
056        }
057
058        return getBySystemName(name);
059    }
060
061    /** {@inheritDoc} */
062    @CheckForNull
063    @Override
064    public SignalGroup getBySystemName(@Nonnull String key) {
065        return _tsys.get(key);
066    }
067
068    /** {@inheritDoc} */
069    @CheckForNull
070    @Override
071    public SignalGroup getByUserName(@Nonnull String key) {
072        return _tuser.get(key);
073    }
074
075    /**
076     * {@inheritDoc}
077     *
078     * Keep autostring in line with {@link #newSignalGroupWithUserName(String)},
079     * {@link #getSystemPrefix()} and {@link #typeLetter()}
080     */
081    @Override
082    @Nonnull
083    public SignalGroup provideSignalGroup(@Nonnull String systemName, String userName) throws IllegalArgumentException {
084        log.debug("provideGroup({})", systemName);
085        SignalGroup r;
086        if ( userName!=null ) {
087            r = getByUserName(userName);
088            if (r != null) {
089                return r;
090            }
091        }
092        r = getBySystemName(systemName);
093        if (r != null) {
094            return r;
095        }
096        // Group does not exist, create a new signal group
097        r = new DefaultSignalGroup(systemName, userName);
098        // save in the maps
099        register(r);
100
101        // Keep track of the last created auto system name
102        updateAutoNumber(systemName);
103
104        return r;
105    }
106
107    /**
108     * {@inheritDoc}
109     *
110     * Keep autostring in line with {@link #provideSignalGroup(String, String)},
111     * {@link #getSystemPrefix()} and {@link #typeLetter()}
112     */
113    @Nonnull
114    @Override
115    public SignalGroup newSignalGroupWithUserName(@Nonnull String userName) {
116        return provideSignalGroup(getAutoSystemName(), userName);
117    }
118
119    List<String> getListOfNames() {
120        List<String> retval = new ArrayList<>();
121        // first locate the signal system directory
122        // and get names of systems
123        File signalDir;
124        File[] files = new File[0];
125        try {
126            signalDir = new File(FileUtil.findURL("xml/signals", FileUtil.Location.INSTALLED).toURI());
127            files = signalDir.listFiles();
128        } catch (URISyntaxException | NullPointerException ex) {
129            log.error("No signals are defined.", ex);
130        }
131        if (files == null) { // not a directory
132            return retval; // empty, but not null
133        }
134        for (File file : files) {
135            if (file.isDirectory()) {
136                // check that there's an aspects.xml file
137                File aspects = new File(file.getPath() + File.separator + "aspects.xml");
138                if (aspects.exists()) {
139                    log.debug("found system: {}", file.getName());
140                    retval.add(file.getName());
141                }
142            }
143        }
144        return retval;
145    }
146
147    @Override
148    public void deleteSignalGroup(SignalGroup s) {
149        deregister(s);
150    }
151
152    @Override
153    @Nonnull
154    public String getBeanTypeHandled(boolean plural) {
155        return Bundle.getMessage(plural ? "BeanNameSignalGroups" : "BeanNameSignalGroup");
156    }
157
158    /**
159     * {@inheritDoc}
160     */
161    @Override
162    public Class<SignalGroup> getNamedBeanClass() {
163        return SignalGroup.class;
164    }
165
166    private final static Logger log = LoggerFactory.getLogger(DefaultSignalGroupManager.class);
167
168}