/*
* Copyright 2012 Nodeable Inc
*
* Licensed 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 com.streamreduce.core.model;
import com.google.code.morphia.annotations.Entity;
import com.google.code.morphia.annotations.Id;
import com.google.code.morphia.annotations.Index;
import com.google.code.morphia.annotations.PrePersist;
import com.streamreduce.core.event.EventId;
import org.bson.types.ObjectId;
import javax.validation.constraints.NotNull;
import java.util.Date;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Map;
import java.util.Set;
/**
* Simple object to describe an event in Nodeable.
*/
@Entity(value = "eventStream", noClassnameStored = true)
@Index("accountId, targetId, timestamp")
public class Event {
@Id
private ObjectId id;
@NotNull
private Long timestamp;
@NotNull
private EventId eventId;
private ObjectId accountId;
private ObjectId userId;
private ObjectId targetId;
private Map<String, Object> metadata;
@PrePersist
public void defaultTimeStamp() {
// Set the timestamp if missing
if (timestamp == null) {
timestamp = new Date().getTime();
}
// Remove metadata entries with null values
if (metadata != null) {
Set<String> badKeys = new HashSet<>();
// Simple fix for SOBA-1281
for (Map.Entry<String, Object> entry : metadata.entrySet()) {
if (entry.getValue() == null) {
badKeys.add(entry.getKey());
}
}
for (String key : badKeys) {
metadata.remove(key);
}
}
}
public ObjectId getId() {
return id;
}
public void setId(ObjectId id) {
this.id = id;
}
public Long getTimestamp() {
return timestamp;
}
public void setTimestamp(Long timestamp) {
this.timestamp = timestamp;
}
public EventId getEventId() {
return eventId;
}
public void setEventId(EventId eventId) {
this.eventId = eventId;
}
public ObjectId getAccountId() {
return accountId;
}
public void setAccountId(ObjectId accountId) {
this.accountId = accountId;
}
public ObjectId getUserId() {
return userId;
}
public void setUserId(ObjectId userId) {
this.userId = userId;
}
public ObjectId getTargetId() {
return targetId;
}
public void setTargetId(ObjectId targetId) {
this.targetId = targetId;
}
public Map<String, Object> getMetadata() {
return metadata;
}
public void setMetadata(Map<String, Object> metadata) {
this.metadata = metadata;
}
@Override
public String toString() {
StringBuilder userText = new StringBuilder();
StringBuilder targetText = new StringBuilder();
StringBuilder accountText = new StringBuilder();
Map<String, Object> eventMetadata = getMetadata();
if (eventMetadata != null) {
if (getUserId() != null) {
userText.append(getUserId())
.append(" (")
.append(eventMetadata.get("sourceUsername"))
.append(": ")
.append(eventMetadata.get("sourceAlias"))
.append(")");
} else {
userText.append("null (Automated event)");
}
if (getTargetId() != null) {
String targetType = (String)getMetadata().get("targetType");
targetText.append(getTargetId())
.append(" (")
.append(targetType)
.append(": ")
.append(targetType.equals(Account.class.getSimpleName()) ?
eventMetadata.get("targetName") :
eventMetadata.get("targetAlias"))
.append(")");
} else {
targetText.append("null (Automated event)");
}
if (getAccountId() != null) {
accountText.append(getAccountId())
.append(" (")
.append(eventMetadata.get("accountName"))
.append(")");
} else {
accountText.append("null (Automated event)");
}
return "[EVENT] " + getEventId() + " triggered by " + userText.toString() + " on " +
targetText.toString() + " in account " + accountText.toString() + " at " +
(getTimestamp() != null ? new Date(getTimestamp()) : new Date());
} else {
return super.toString();
}
}
public static class Builder {
private boolean isBuilt = false;
private Event event;
public Builder() {
this.event = new Event();
event.setMetadata(new HashMap<String, Object>());
}
public Builder accountId(ObjectId accountId) {
checkIsBuilt();
event.setAccountId(accountId);
return this;
}
public Builder actorId(ObjectId actorId) {
checkIsBuilt();
event.setUserId(actorId);
return this;
}
public Builder context(Map<String, Object> context) {
checkIsBuilt();
if (context != null) {
event.setMetadata(context);
}
return this;
}
public Builder targetId(ObjectId targetId) {
checkIsBuilt();
event.setTargetId(targetId);
return this;
}
public Builder eventId(EventId eventId) {
checkIsBuilt();
event.setEventId(eventId);
return this;
}
private void checkIsBuilt() {
if (isBuilt) {
throw new IllegalStateException("The object cannot be modified/rebuilt after built.");
}
}
public Event build() {
checkIsBuilt();
isBuilt = true;
event.setTimestamp(new Date().getTime());
return event;
}
}
}