001package jmri.jmrit.logix;
002
003import java.beans.PropertyChangeEvent;
004import java.beans.PropertyChangeListener;
005import java.beans.PropertyChangeSupport;
006
007import java.util.*;
008
009import javax.annotation.Nonnull;
010import javax.annotation.OverridingMethodsMustInvokeSuper;
011
012/**
013 * Basic implementation of a PortalManager.
014 * <p>
015 * Note that this does not enforce any particular system naming convention.
016 * <p>
017 * Note this is an 'after thought' manager. Portals have been in use since 2009.
018 * Their use has now expanded well beyond what was expected. A Portal factory is
019 * needed for development to continue.
020 *
021 * Portal system names will be numbers and they will not be shown to users. The
022 * UI will treat Portal names as it does now as user names.
023 *
024 * <hr>
025 * This file is part of JMRI.
026 * <p>
027 * JMRI is free software; you can redistribute it and/or modify it under the
028 * terms of version 2 of the GNU General Public License as published by the Free
029 * Software Foundation. See the "COPYING" file for a copy of this license.
030 * <p>
031 * JMRI is distributed in the hope that it will be useful, but WITHOUT ANY
032 * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
033 * A PARTICULAR PURPOSE. See the GNU General Public License for more details.
034 *
035 * @author Pete Cressman Copyright (C) 2014
036 */
037public class PortalManager implements jmri.InstanceManagerAutoDefault, PropertyChangeListener {
038
039    private final PropertyChangeSupport pcs = new PropertyChangeSupport(this);
040    private final ArrayList<Portal> _nameList = new ArrayList<>();          // stores Portal in loaded order
041    private final HashMap<String, Portal> _portalMap = new HashMap<>(); // stores portal by current name
042
043    public PortalManager() {
044        // no setup currently required
045    }
046
047    public int getPortalCount() {
048        return _nameList.size();
049    }
050
051    public Portal getPortal(int idx) {
052        return _nameList.get(idx);
053    }
054
055    public int getIndexOf(Portal portal) {
056        return _nameList.indexOf(portal);
057    }
058
059    public Portal getPortal(String name) {
060        return _portalMap.get(name);
061    }
062
063    public Collection<Portal> getPortalSet() {
064        return Collections.unmodifiableCollection(_nameList);
065    }
066
067    /*
068     * Create a new Portal with a given user name.
069     *
070     * @return null if a Portal with the same userName already exists,
071     * or if an empty userName was requested
072     */
073    public Portal createNewPortal(@Nonnull String userName) {
074        java.util.Objects.requireNonNull(userName, "Name cannot be null");
075        // Check that Portal does not already exist
076        Portal portal;
077        if (userName.trim().length() > 0) {
078            portal = _portalMap.get(userName);
079            if (portal != null) {
080                return null;
081            }
082        } else {  // must have a user name for backward compatibility
083            return null;
084        }
085        // Portal does not exist, create a new Portal
086        portal = new Portal(userName);
087        // save in the maps
088        _nameList.add(portal);
089        _portalMap.put(userName, portal);
090        pcs.firePropertyChange("numPortals", null, _nameList.size());
091        // listen for name and state changes to forward
092        portal.addPropertyChangeListener(this);
093        return portal;
094    }
095
096    public Portal providePortal(String name) {
097        if (name == null || name.trim().length() == 0) {
098            return null;
099        }
100        Portal portal = getPortal(name);
101        if (portal == null) {
102            portal = createNewPortal(name);
103        }
104        return portal;
105    }
106
107    private synchronized void deletePortal(Portal portal) {
108        String name = portal.getName();
109        _nameList.remove(portal);
110        _portalMap.remove(name);
111        pcs.firePropertyChange("numPortals", portal, _nameList.size());
112    }
113
114    @OverridingMethodsMustInvokeSuper
115    public synchronized void addPropertyChangeListener(PropertyChangeListener l) {
116        pcs.addPropertyChangeListener(l);
117    }
118
119    @OverridingMethodsMustInvokeSuper
120    public synchronized void removePropertyChangeListener(PropertyChangeListener l) {
121        pcs.removePropertyChangeListener(l);
122    }
123
124    @Override
125    public void propertyChange(PropertyChangeEvent e) {
126        if (!(e.getSource() instanceof Portal)) {
127            return;
128        }
129        Portal portal = (Portal)e.getSource();
130        String propertyName = e.getPropertyName();
131        log.debug("property = {}", propertyName);
132        if (propertyName.equals("portalDelete")) {
133            deletePortal(portal);
134        }
135    }
136
137    private static final org.slf4j.Logger log = org.slf4j.LoggerFactory.getLogger(PortalManager.class);
138
139}