/*
* RHQ Management Platform
* Copyright (C) 2005-2008 Red Hat, Inc.
* All rights reserved.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License, version 2, as
* published by the Free Software Foundation, and/or the GNU Lesser
* General Public License, version 2.1, also as published by the Free
* Software Foundation.
*
* This program 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 and the GNU Lesser General Public License
* for more details.
*
* You should have received a copy of the GNU General Public License
* and the GNU Lesser General Public License along with this program;
* if not, write to the Free Software Foundation, Inc.,
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/
package org.rhq.core.domain.alert.notification;
import java.io.Serializable;
import javax.persistence.CascadeType;
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.FetchType;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import javax.persistence.JoinColumn;
import javax.persistence.ManyToOne;
import javax.persistence.NamedQueries;
import javax.persistence.NamedQuery;
import javax.persistence.OneToOne;
import javax.persistence.SequenceGenerator;
import javax.persistence.Table;
import org.jetbrains.annotations.NotNull;
import org.rhq.core.domain.alert.AlertDefinition;
import org.rhq.core.domain.configuration.Configuration;
import org.rhq.core.domain.configuration.Property;
@Entity
@NamedQueries( {
@NamedQuery(name = AlertNotification.DELETE_BY_ID, query = "DELETE FROM AlertNotification an WHERE an.id IN ( :ids )"),
@NamedQuery(name = AlertNotification.QUERY_DELETE_BY_RESOURCES, query = "DELETE FROM AlertNotification an WHERE an.alertDefinition IN ( SELECT ad FROM AlertDefinition ad WHERE ad.resource.id IN ( :resourceIds ) )"),
@NamedQuery(name = AlertNotification.QUERY_DELETE_ORPHANED, query = "DELETE FROM AlertNotification an WHERE an.alertDefinition IS NULL"),
@NamedQuery(name = AlertNotification.QUERY_CLEANSE_PARAMETER_VALUE_FOR_ALERT_SENDER, query = "" //
+ "UPDATE Property property" //
+ " SET stringValue = (" //
+ " concat(" //
+ " substring(" //
+ " stringValue," //
+ " 0," //
+ " locate(:paramValue,stringValue)" //
+ " )," //
+ " substring(" //
+ " stringValue," //
+ " locate(:paramValue,stringValue)+length(:paramValue)-1," //
+ " length(stringValue)-(locate(:paramValue,stringValue)+length(:paramValue)-2)" //
+ " )" //
+ " )" //
+ " )" //
+ " WHERE id IN (" //
+ " SELECT notifParam.id" //
+ " FROM AlertNotification notif" //
+ " JOIN notif.configuration.properties notifParam" //
+ " WHERE notif.senderName = :senderName" //
+ " AND notifParam.name = :propertyName" //
+ " AND locate(:paramValue,notifParam.stringValue) <> 0" //
+ ")"
),
@NamedQuery(name = AlertNotification.QUERY_UPDATE_PARAMETER_FOR_NOTIFICATIONS, query = "" //
+ " UPDATE Property property" //
+ " SET stringValue = :propertyValue" //
+ " WHERE id IN ( "
+ " SELECT notifParam.id" //
+ " FROM AlertNotification notif" //
+ " JOIN notif.configuration.properties notifParam" //
+ " WHERE notif.id IN ( :alertNotificationIds )" //
+ " AND notifParam.name = :propertyName" //
+ ")"
)})
@SequenceGenerator(allocationSize = org.rhq.core.domain.util.Constants.ALLOCATION_SIZE, name = "RHQ_ALERT_NOTIFICATION_ID_SEQ", sequenceName = "RHQ_ALERT_NOTIFICATION_ID_SEQ")
@Table(name = "RHQ_ALERT_NOTIFICATION")
public class AlertNotification implements Serializable {
private static final long serialVersionUID = 1L;
public static final String DELETE_BY_ID = "AlertNotification.deleteById";
public static final String QUERY_DELETE_BY_RESOURCES = "AlertNotification.deleteByResources";
public static final String QUERY_DELETE_ORPHANED = "AlertNotification.deleteOrphaned";
public static final String QUERY_DELETE_BY_ROLE_ID = "AlertNotification.deleteByRoleId";
public static final String QUERY_CLEANSE_PARAMETER_VALUE_FOR_ALERT_SENDER = "AlertNotification.cleanseParameterValueForAlertSender";
public static final String QUERY_UPDATE_PARAMETER_FOR_NOTIFICATIONS = "AlertNotification.updateParameterForNotifications";
@Column(name = "ID", nullable = false)
@GeneratedValue(strategy = GenerationType.AUTO, generator = "RHQ_ALERT_NOTIFICATION_ID_SEQ")
@Id
private int id;
@JoinColumn(name = "ALERT_DEFINITION_ID")
@ManyToOne
private AlertDefinition alertDefinition;
@JoinColumn(name = "SENDER_CONFIG_ID", referencedColumnName = "ID")
@OneToOne(cascade = { CascadeType.ALL }, fetch = FetchType.EAGER)
private Configuration configuration;
@JoinColumn(name = "EXTRA_CONFIG_ID", referencedColumnName = "ID")
@OneToOne(cascade = { CascadeType.ALL }, fetch = FetchType.EAGER)
private Configuration extraConfiguration;
@Column(name = "SENDER_NAME")
private String senderName;
protected AlertNotification() {
} // JPA spec
/**
* @param sender the type of alert sender for this {@link AlertNotification}
* @param configuration the custom data required for runtime configuration; it must be a new configuration object
* and not already persisted; in other words, the {@link Configuration} object as well as its
* {@link Property} children must have ids of 0.
*/
public AlertNotification(String sender, Configuration configuration) {
setSenderName(sender);
setConfiguration(configuration);
}
public AlertNotification(AlertNotification source) {
this.configuration = source.configuration.deepCopy(false);
if (source.extraConfiguration != null) {
this.extraConfiguration = source.extraConfiguration.deepCopy(false);
} else {
this.extraConfiguration = null;
}
this.senderName = source.senderName;
}
public AlertNotification(String sender) {
this.senderName = sender;
}
public int getId() {
return id;
}
@NotNull
public AlertDefinition getAlertDefinition() {
return alertDefinition;
}
public void setAlertDefinition(AlertDefinition alertDefinition) {
if (alertDefinition == null) {
throw new IllegalArgumentException("alertDefinition must be non-null.");
}
this.alertDefinition = alertDefinition;
}
public void prepareForOrphanDelete() {
this.alertDefinition = null;
}
public String getSenderName() {
return senderName;
}
public void setSenderName(String senderName) {
this.senderName = senderName;
}
/**
* The configuration containing the properties that each individual alert sender requires.
* The properties in this configuration should match the property definitions defined
* in the alert server plugin descriptor.
*
* @return the configuration for the alert notification (properties included in this
* configuration will be specific to the sender type).
*/
public Configuration getConfiguration() {
return configuration;
}
public void setConfiguration(Configuration configuration) {
if (configuration == null) {
throw new IllegalArgumentException("configuration must be non-null");
}
this.configuration = configuration;
}
/**
* These are extra configuration property values that a particular sender instance might need.
* These are only used/needed for specific alert implementations. One example where extra config is used
* is for the "resource operation" alert sender. If a particular notification uses this "resource operation"
* sender (where {@link #getConfiguration()} will include things like the operation name that is to be invoked),
* its possible that the selected operation to invoke requires parameters to be passed to it. The user can
* enter this "extra" data and those extra properties (that is, the configuration properties to be passed to the
* operation as parametesr) will be stored here.
*
* @return extra configuration properties or <code>null</code> if not set
*/
public Configuration getExtraConfiguration() {
return extraConfiguration;
}
public void setExtraConfiguration(Configuration extraConfiguration) {
// extra configuration can be null
this.extraConfiguration = extraConfiguration;
}
@Override
public String toString() {
final StringBuilder sb = new StringBuilder();
sb.append("AlertNotification");
sb.append("{id=").append(id);
sb.append(", senderName='").append(senderName).append('\'');
sb.append('}');
return sb.toString();
}
@Override
public int hashCode() {
final int prime = 31;
int result = 1;
result = prime * result + id;
return result;
}
@Override
public boolean equals(Object obj) {
if (this == obj) {
return true;
}
if (obj == null) {
return false;
}
if (!(obj instanceof AlertNotification)) {
return false;
}
AlertNotification other = (AlertNotification) obj;
if (id != other.id) {
return false;
}
return true;
}
public boolean equalsData(AlertNotification other) {
if (other == null) {
return false;
}
boolean results = compare(configuration, other.configuration);
if (results) {
results = compare(extraConfiguration, other.extraConfiguration);
}
return results;
}
private boolean compare(Configuration first, Configuration second) {
if (first == null) {
return (second == null);
}
return first.equals(second);
}
}