/**
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.apache.ambari.server.orm.entities;
import java.util.ArrayList;
import java.util.Collections;
import java.util.EnumSet;
import java.util.HashSet;
import java.util.List;
import java.util.Objects;
import java.util.Set;
import javax.persistence.Basic;
import javax.persistence.CascadeType;
import javax.persistence.CollectionTable;
import javax.persistence.Column;
import javax.persistence.ElementCollection;
import javax.persistence.Entity;
import javax.persistence.EntityManager;
import javax.persistence.EnumType;
import javax.persistence.Enumerated;
import javax.persistence.FetchType;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import javax.persistence.JoinColumn;
import javax.persistence.Lob;
import javax.persistence.ManyToMany;
import javax.persistence.NamedQueries;
import javax.persistence.NamedQuery;
import javax.persistence.OneToMany;
import javax.persistence.PreRemove;
import javax.persistence.Table;
import javax.persistence.TableGenerator;
import org.apache.ambari.server.state.AlertState;
import com.google.common.collect.ImmutableSet;
/**
* The {@link AlertTargetEntity} class represents audience that will receive
* dispatches when an alert is triggered.
*/
@Entity
@Table(name = "alert_target")
@TableGenerator(
name = "alert_target_id_generator",
table = "ambari_sequences",
pkColumnName = "sequence_name",
valueColumnName = "sequence_value",
pkColumnValue = "alert_target_id_seq",
initialValue = 0)
@NamedQueries({
@NamedQuery(
name = "AlertTargetEntity.findAll",
query = "SELECT alertTarget FROM AlertTargetEntity alertTarget"),
@NamedQuery(
name = "AlertTargetEntity.findAllGlobal",
query = "SELECT alertTarget FROM AlertTargetEntity alertTarget WHERE alertTarget.isGlobal = 1"),
@NamedQuery(
name = "AlertTargetEntity.findByName",
query = "SELECT alertTarget FROM AlertTargetEntity alertTarget WHERE alertTarget.targetName = :targetName"),
@NamedQuery(
name = "AlertTargetEntity.findByIds",
query = "SELECT alertTarget FROM AlertTargetEntity alertTarget WHERE alertTarget.targetId IN :targetIds") })
public class AlertTargetEntity {
@Id
@GeneratedValue(strategy = GenerationType.TABLE, generator = "alert_target_id_generator")
@Column(name = "target_id", nullable = false, updatable = false)
private Long targetId;
@Column(length = 1024)
private String description;
@Column(name = "notification_type", nullable = false, length = 64)
private String notificationType;
@Lob
@Basic
@Column(length = 32672)
private String properties;
@Column(name = "target_name", unique = true, nullable = false, length = 255)
private String targetName;
@Column(name = "is_global", nullable = false, length = 1)
private Short isGlobal = Short.valueOf((short) 0);
@Column(name = "is_enabled", nullable = false, length = 1)
private Short isEnabled = Short.valueOf((short) 1);
/**
* Bi-directional many-to-many association to {@link AlertGroupEntity}
*/
@ManyToMany(
fetch = FetchType.EAGER,
mappedBy = "alertTargets",
cascade = { CascadeType.MERGE, CascadeType.REFRESH })
private Set<AlertGroupEntity> alertGroups;
/**
* Gets the alert states that this target will be notified for. If this is
* either empty or {@code null}, then it is implied that all alert states are
* of interest to the target. A target without an alert states does not make
* sense which is why the absence of states implies all states.
*/
@Enumerated(value = EnumType.STRING)
@ElementCollection(targetClass = AlertState.class)
@CollectionTable(name = "alert_target_states", joinColumns = @JoinColumn(name = "target_id"))
@Column(name = "alert_state")
private Set<AlertState> alertStates = EnumSet.allOf(AlertState.class);
/**
* Bi-directional one-to-many association to {@link AlertNoticeEntity}.
*/
@OneToMany(cascade = CascadeType.REMOVE, mappedBy = "alertTarget")
private List<AlertNoticeEntity> alertNotices;
/**
* Gets the unique ID of this alert target.
*
* @return the ID of the target (never {@code null}).
*/
public Long getTargetId() {
return targetId;
}
/**
* Sets the unique ID of this alert target.
*
* @param targetId
* the ID of the alert target (not {@code null}).
*/
public void setTargetId(Long targetId) {
this.targetId = targetId;
}
/**
* Gets the description of this alert target.
*
* @return the description or {@code null} if none.
*/
public String getDescription() {
return description;
}
/**
* Sets the description for this alert target.
*
* @param description
* the description or {@code null} for none.
*/
public void setDescription(String description) {
this.description = description;
}
/**
* @return
*/
public String getNotificationType() {
return notificationType;
}
/**
* @param notificationType
*/
public void setNotificationType(String notificationType) {
this.notificationType = notificationType;
}
/**
* @return
*/
public String getProperties() {
return properties;
}
/**
* @param properties
*/
public void setProperties(String properties) {
this.properties = properties;
}
/**
* Gets the name of this alert target.
*
* @return the alert target name (never {@code null}).
*/
public String getTargetName() {
return targetName;
}
/**
* Gets whether the alert target is a global target and will receive
* notifications triggered for any alert group.
*
* @return the isGlobal {@code} if the target is global.
*/
public boolean isGlobal() {
return isGlobal == 0 ? false : true;
}
/**
* Sets whether the alert target is a global target and will receive
* notifications triggered for any alert group.
*
* @param isGlobal
* {@code} if the target is global.
*/
public void setGlobal(boolean isGlobal) {
this.isGlobal = isGlobal ? (short) 1 : (short) 0;
}
/**
* Gets whether the alert target is enabled. Targets which are not enabled
* will not receive notifications.
*
* @return the {@code true} if the target is enabled.
*/
public boolean isEnabled() {
return isEnabled == 0 ? false : true;
}
/**
* Sets whether the alert target is enabled. Targets which are not enabled
* will not receive notifications.
*
* @param isEnabled
* {@code} if the target is enabled.
*/
public void setEnabled(boolean isEnabled) {
this.isEnabled = isEnabled ? (short) 1 : (short) 0;
}
/**
* Gets the alert states that will cause a triggered alert to be sent to this
* target. A target may be associated with a group where an alert has changed
* state, but if that new state is not of interest to the target, it will not
* be sent.
*
* @return the set of alert states or {@code null} or empty to imply all.
*/
public Set<AlertState> getAlertStates() {
return alertStates;
}
/**
* Sets the alert states that will cause a triggered alert to be sent to this
* target. A target may be associated with a group where an alert has changed
* state, but if that new state is not of interest to the target, it will not
* be sent.
*
* @param alertStates
* the set of alert states or {@code null} or empty to imply all.
*/
public void setAlertStates(Set<AlertState> alertStates) {
this.alertStates = alertStates;
}
/**
* Sets the name of this alert target.
*
* @param targetName
* the name (not {@code null}).
*/
public void setTargetName(String targetName) {
this.targetName = targetName;
}
/**
* Gets an immutable set of the alert groups that this target is associated
* with.
*
* @return the groups that will send to this target when an alert in that
* group is received, or an empty set for none.
*/
public Set<AlertGroupEntity> getAlertGroups() {
if (null == alertGroups) {
return Collections.emptySet();
}
return ImmutableSet.copyOf(alertGroups);
}
/**
* Sets all of the groups that are associated with this target.
*
* @param alertGroups
* the groups, or {@code null} if there are none.
*/
public void setAlertGroups(Set<AlertGroupEntity> alertGroups) {
Set<AlertGroupEntity> groups = getAlertGroups();
for (AlertGroupEntity group : groups) {
group.removeAlertTarget(this);
}
this.alertGroups = alertGroups;
if (null != alertGroups) {
for (AlertGroupEntity group : alertGroups) {
group.addAlertTarget(this);
}
}
}
/**
* Adds the specified alert group to the groups that this target is associated
* with. This is used to complement the JPA bidirectional association.
*
* @param alertGroup
*/
protected void addAlertGroup(AlertGroupEntity alertGroup) {
if (null == alertGroups) {
alertGroups = new HashSet<>();
}
alertGroups.add(alertGroup);
}
/**
* Removes the specified alert group to the groups that this target is
* associated with. This is used to complement the JPA bidirectional
* association.
*
* @param alertGroup
*/
protected void removeAlertGroup(AlertGroupEntity alertGroup) {
if (null != alertGroups) {
alertGroups.remove(alertGroup);
}
}
/**
* Adds the specified notice to the notices that have been sent out for this
* target.
*
* @param notice
* the notice.
*/
protected void addAlertNotice(AlertNoticeEntity notice) {
if (null == alertNotices) {
alertNotices = new ArrayList<>();
}
alertNotices.add(notice);
}
public List<AlertNoticeEntity> getAlertNotices() {
return alertNotices;
}
public void setAlertNotices(List<AlertNoticeEntity> alertNotices) {
this.alertNotices = alertNotices;
}
/**
* Called before {@link EntityManager#remove(Object)} for this entity, removes
* the non-owning relationship between targets and groups.
*/
@PreRemove
public void preRemove() {
Set<AlertGroupEntity> groups = getAlertGroups();
if (!groups.isEmpty()) {
for (AlertGroupEntity group : groups) {
group.removeAlertTarget(this);
}
}
}
/**
* {@inheritDoc}
*/
@Override
public boolean equals(Object object) {
if (this == object) {
return true;
}
if (object == null || getClass() != object.getClass()) {
return false;
}
AlertTargetEntity that = (AlertTargetEntity) object;
// use the unique ID if it exists
if( null != targetId ){
return Objects.equals(targetId, that.targetId);
}
return Objects.equals(targetId, that.targetId) &&
Objects.equals(targetName, that.targetName) &&
Objects.equals(notificationType, that.notificationType) &&
Objects.equals(isEnabled, that.isEnabled) &&
Objects.equals(description, that.description) &&
Objects.equals(isGlobal, that.isGlobal);
}
/**
* {@inheritDoc}
*/
@Override
public int hashCode() {
// use the unique ID if it exists
if (null != targetId) {
return targetId.hashCode();
}
return Objects.hash(targetId, targetName, notificationType, isEnabled, description, isGlobal);
}
/**
* {@inheritDoc}
*/
@Override
public String toString() {
StringBuilder buffer = new StringBuilder();
buffer.append(getClass().getSimpleName());
buffer.append("{");
buffer.append("id=").append(targetId);
buffer.append(", name=").append(targetName);
buffer.append("}");
return buffer.toString();
}
}