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