/*******************************************************************************
* This file is part of OpenNMS(R).
*
* Copyright (C) 2010-2011 The OpenNMS Group, Inc.
* OpenNMS(R) is Copyright (C) 1999-2011 The OpenNMS Group, Inc.
*
* OpenNMS(R) is a registered trademark of The OpenNMS Group, Inc.
*
* OpenNMS(R) is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published
* by the Free Software Foundation, either version 3 of the License,
* or (at your option) any later version.
*
* OpenNMS(R) is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with OpenNMS(R). If not, see:
* http://www.gnu.org/licenses/
*
* For more information contact:
* OpenNMS(R) Licensing <license@opennms.org>
* http://www.opennms.org/
* http://www.opennms.com/
*******************************************************************************/
/**
* <p>LocationMonitorState class.</p>
*
* @author ranger
* @version $Id: $
* @since 1.8.1
*/
package org.opennms.features.poller.remote.gwt.client;
import java.io.Serializable;
import java.util.Collection;
import java.util.HashSet;
import java.util.Set;
import java.util.TreeSet;
import com.google.gwt.user.client.rpc.IsSerializable;
public class LocationMonitorState implements Serializable, IsSerializable {
private static final long serialVersionUID = -7846127073655210004L;
private Set<GWTLocationMonitor> m_monitorsStarted = new HashSet<GWTLocationMonitor>();
private Set<GWTLocationMonitor> m_monitorsStopped = new HashSet<GWTLocationMonitor>();
private Set<GWTLocationMonitor> m_monitorsDisconnected = new HashSet<GWTLocationMonitor>();
private Collection<GWTLocationSpecificStatus> m_locationStatuses;
private Set<String> m_serviceNames = new HashSet<String>();
private Set<Integer> m_serviceIds = new HashSet<Integer>();
private StatusDetails m_statusDetails;
/**
* <p>Constructor for LocationMonitorState.</p>
*/
public LocationMonitorState() { }
/**
* <p>Constructor for LocationMonitorState.</p>
*
* @param statuses a {@link java.util.Collection} object.
*/
public LocationMonitorState(Collection<GWTLocationSpecificStatus> statuses) {
initializeStatuses(statuses);
}
/**
* <p>Constructor for LocationMonitorState.</p>
*
* @param monitors a {@link java.util.Collection} object.
* @param statuses a {@link java.util.Collection} object.
*/
public LocationMonitorState(Collection<GWTLocationMonitor> monitors, Collection<GWTLocationSpecificStatus> statuses) {
initializeStatuses(statuses);
initializeMonitors(monitors);
}
/**
* <p>getStatusDetails</p>
*
* @return a {@link org.opennms.features.poller.remote.gwt.client.StatusDetails} object.
*/
public StatusDetails getStatusDetails() {
if (m_statusDetails == null) {
m_statusDetails = getStatusDetailsUncached();
}
return m_statusDetails;
}
private void initializeMonitors(Collection<GWTLocationMonitor> monitors) {
for (GWTLocationMonitor monitor : monitors) {
handleMonitor(monitor);
}
}
private void initializeStatuses(Collection<GWTLocationSpecificStatus> statuses) {
if (statuses != null) {
for (final GWTLocationSpecificStatus status : statuses) {
handleMonitor(status.getLocationMonitor());
m_serviceNames.add(status.getMonitoredService().getServiceName());
m_serviceIds.add(status.getMonitoredService().getId());
}
m_locationStatuses = statuses;
}
}
private void handleMonitor(final GWTLocationMonitor monitor) {
if (m_monitorsStarted.contains(monitor) || m_monitorsStopped.contains(monitor) || m_monitorsDisconnected.contains(monitor)) {
return;
}
final String statusText = monitor.getStatus();
if (statusText.equalsIgnoreCase("CONFIG_CHANGED")
|| statusText.equalsIgnoreCase("STARTED")) {
m_monitorsStarted.add(monitor);
} else if (statusText.equalsIgnoreCase("DISCONNECTED")) {
m_monitorsDisconnected.add(monitor);
} else if (statusText.equalsIgnoreCase("REGISTERED")
|| statusText.equalsIgnoreCase("PAUSED")
|| statusText.equalsIgnoreCase("STOPPED")) {
m_monitorsStopped.add(monitor);
} else {
throw new RuntimeException("unknown monitor status: " + statusText);
}
}
/**
* <p>allMonitorsStarted</p>
*
* @return a boolean.
*/
public boolean allMonitorsStarted() {
if (m_monitorsStarted.size() == 0) {
return false;
}
if (m_monitorsStopped.size() > 0) {
return false;
}
if (m_monitorsDisconnected.size() > 0) {
return false;
}
return true;
}
/**
* <p>atLeastOneMonitorStarted</p>
*
* @return a boolean.
*/
public boolean atLeastOneMonitorStarted() {
if (m_monitorsStarted.size() > 0) {
return true;
}
return false;
}
/**
* <p>allButOneMonitorsDisconnected</p>
*
* @return a boolean.
*/
public boolean allButOneMonitorsDisconnected() {
if (m_monitorsDisconnected.size() == 0) {
return false;
}
if (m_monitorsStarted.size() > 1) {
return false;
}
if (m_monitorsStarted.size() == 0) {
return false;
}
return true;
}
/**
* <p>allMonitorsDisconnected</p>
*
* @return a boolean.
*/
public boolean allMonitorsDisconnected() {
if (m_monitorsDisconnected.size() == 0) {
return false;
}
if (m_monitorsStarted.size() > 0) {
return false;
}
if (m_monitorsStopped.size() > 0) {
return false;
}
return true;
}
/**
* <p>noMonitorsStarted</p>
*
* @return a boolean.
*/
public boolean noMonitorsStarted() {
if (m_monitorsStarted.size() == 0) {
return true;
}
return false;
}
/**
* <p>getMonitorsStarted</p>
*
* @return a int.
*/
public int getMonitorsStarted() {
return m_monitorsStarted.size();
}
/**
* <p>getMonitorsStopped</p>
*
* @return a int.
*/
public int getMonitorsStopped() {
return m_monitorsStopped.size();
}
/**
* <p>getMonitorsDisconnected</p>
*
* @return a int.
*/
public int getMonitorsDisconnected() {
return m_monitorsDisconnected.size();
}
/**
* <p>getServices</p>
*
* @return a {@link java.util.Collection} object.
*/
public Collection<GWTMonitoredService> getServices() {
final Set<GWTMonitoredService> services = new TreeSet<GWTMonitoredService>();
for (final GWTLocationSpecificStatus status : m_locationStatuses) {
services.add(status.getMonitoredService());
}
return services;
}
/**
* <p>getServicesDown</p>
*
* @return a {@link java.util.Collection} object.
*/
public Collection<String> getServicesDown() {
final Set<String> servicesDown = new HashSet<String>();
for (final GWTLocationSpecificStatus status : m_locationStatuses) {
final GWTMonitoredService service = status.getMonitoredService();
final GWTPollResult result = status.getPollResult();
if (result.isDown()) {
servicesDown.add(service.getServiceName());
}
}
return servicesDown;
}
/**
* <p>getMonitorsWithServicesDown</p>
*
* @return a {@link java.util.Collection} object.
*/
public Collection<GWTLocationMonitor> getMonitorsWithServicesDown() {
final Set<GWTLocationMonitor> monitors = new HashSet<GWTLocationMonitor>();
for (final GWTLocationSpecificStatus status : m_locationStatuses) {
final GWTPollResult result = status.getPollResult();
if (result.isDown()) {
monitors.add(status.getLocationMonitor());
}
}
return monitors;
}
public boolean noMonitorsExist() {
return (
m_monitorsStopped.size() == 0 &&
m_monitorsDisconnected.size() == 0 &&
m_monitorsStarted.size() == 0
);
}
private StatusDetails getStatusDetailsUncached() {
// white/uninitialized: If no monitors exist for a location
if (noMonitorsExist()) {
return StatusDetails.unknown("No monitors exist for this location.");
}
// white/uninitialized: if no monitors have reported in
if (m_locationStatuses == null || m_locationStatuses.size() == 0) {
return StatusDetails.unknown("No monitors have reported in for this location.");
}
// orange/disconnected: all monitors are disconnected
if (allMonitorsDisconnected()) {
return StatusDetails.disconnected("All monitors have disconnected.");
}
// grey/stopped: If no monitors are started for a location
if (noMonitorsStarted()) {
return StatusDetails.stopped("No monitors are started for this location.");
}
// yellow/marginal: If all but 1 non-stopped monitors are disconnected
if (allButOneMonitorsDisconnected()) {
return StatusDetails.marginal("Only 1 monitor is started, the rest are disconnected.");
}
Set<Integer> anyDown = new HashSet<Integer>();
Set<Integer> services = new HashSet<Integer>();
Set<Integer> servicesDown = new HashSet<Integer>();
for (Integer serviceId : m_serviceIds) {
boolean serviceAllDown = true;
boolean foundService = false;
for (GWTLocationSpecificStatus status : m_locationStatuses) {
final GWTMonitoredService monitoredService = status.getMonitoredService();
if (monitoredService.getId().equals(serviceId)) {
foundService = true;
services.add(serviceId);
final GWTPollResult pollResult = status.getPollResult();
if (pollResult.getStatus().equalsIgnoreCase("down")) {
anyDown.add(serviceId);
} else {
serviceAllDown = false;
}
}
}
if (foundService && serviceAllDown) {
servicesDown.add(serviceId);
}
}
if (servicesDown.size() > 0) {
if (servicesDown.size() == services.size()) {
// red/down: If all started monitors report "down" for all services
return StatusDetails.down("All services are down on all started monitors.");
} else {
// red/down: If all started monitors report "down" for the same service
if (servicesDown.size() == 1) {
return StatusDetails.down(getServiceName(servicesDown.iterator().next()) + " has been reported down by all monitors.");
} else {
return StatusDetails.down("The following services are reported down by all monitors: " + getServiceNames(servicesDown) + ".");
}
}
}
// yellow/marginal: If some (but not all) started monitors report "down" for the same service
if (anyDown.size() > 0) {
return StatusDetails.marginal("The following services are reported down by at least one monitor: " + getServiceNames(anyDown) + ".");
}
return StatusDetails.up();
}
private String getServiceNames(Set<Integer> serviceIds) {
StringBuilder buf = new StringBuilder();
boolean first = true;
for(Integer serviceId : serviceIds) {
if (first) {
first = false;
} else {
buf.append(", ");
}
buf.append(getServiceName(serviceId));
}
return buf.toString();
}
private String getServiceName(Integer serviceId) {
for(GWTLocationSpecificStatus status : m_locationStatuses) {
if (serviceId.equals(status.getMonitoredService().getId())) {
return status.getMonitoredService().getServiceName();
}
}
return null;
}
/**
* <p>toString</p>
*
* @return a {@link java.lang.String} object.
*/
public String toString() {
return "LocationMonitorState[started=" + m_monitorsStarted + ",stopped=" + m_monitorsStopped + ",disconnected=" + m_monitorsDisconnected + ",statuses="+m_locationStatuses+",services="+m_serviceNames+"]";
}
}