com.intuit.wasabi.email.impl.EmailTextProcessorImpl Maven / Gradle / Ivy
/*******************************************************************************
* Copyright 2016 Intuit
*
* 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.intuit.wasabi.email.impl;
import com.google.inject.Inject;
import com.intuit.wasabi.authenticationobjects.UserInfo;
import com.intuit.wasabi.authorizationobjects.Role;
import com.intuit.wasabi.authorizationobjects.UserRole;
import com.intuit.wasabi.authorizationobjects.UserRoleList;
import com.intuit.wasabi.email.EmailLinksList;
import com.intuit.wasabi.email.EmailTextProcessor;
import com.intuit.wasabi.email.TextTemplates;
import com.intuit.wasabi.eventlog.EventLogEventType;
import com.intuit.wasabi.eventlog.events.*;
import com.intuit.wasabi.exceptions.EventLogException;
import com.intuit.wasabi.exceptions.WasabiEmailException;
import com.intuit.wasabi.experimentobjects.Application;
import com.intuit.wasabi.experimentobjects.Bucket;
import com.intuit.wasabi.experimentobjects.ExperimentBase;
import com.intuit.wasabi.repository.AuthorizationRepository;
import org.apache.commons.validator.routines.EmailValidator;
import org.slf4j.Logger;
import org.stringtemplate.v4.ST;
import java.util.*;
import static com.intuit.wasabi.email.WasabiEmailFields.*;
import static com.intuit.wasabi.email.TextTemplates.*;
import static org.slf4j.LoggerFactory.getLogger;
/**
* Implementation of the {@link EmailTextProcessor}
*/
public class EmailTextProcessorImpl implements EmailTextProcessor {
/* need this for getting the admins to an experiment */
private AuthorizationRepository authorizationRepository;
private final static Logger LOGGER = getLogger(EmailTextProcessorImpl.class);
@Inject
public EmailTextProcessorImpl(final AuthorizationRepository authorizationRepository) {
this.authorizationRepository = authorizationRepository;
}
/**
* {@inheritDoc}
*/
@Override
public Set getAddressees(EventLogEvent event) {
Set addressants = new HashSet<>();
EventLogEventType type = event.getType();
switch (type) {
case BUCKET_CHANGED:
case BUCKET_CREATED:
case EXPERIMENT_CHANGED:
case EXPERIMENT_CREATED:
addressants.addAll(getExperimentAddressor((ExperimentEvent) event));
break;
case SIMPLE_EVENT:
default:
throw new IllegalArgumentException("Can not handle EventType: " + type.toString());
}
return addressants;
}
/**
* {@inheritDoc}
*/
@Override
public Set getAddressees(Application.Name app) {
return getAdminEmails(app);
}
/**
* {@inheritDoc}
*/
@Override
public String getMessage(Application.Name app, UserInfo.Username username, EmailLinksList links) {
ST appAccess = new ST(APP_ACCESS);
Map variables = new HashMap<>();
put(variables, APPLICATION_NAME, String.valueOf(app));
put(variables, USER_NAME, String.valueOf(username));
put(variables, EMAIL_LINKS, links.toString());
return replaceVariablesInTemplate(variables, appAccess);
}
/**
* {@inheritDoc}
*/
@Override
public String getSubject(Application.Name app) {
return "A User requests access to your Application";
}
/**
* {@inheritDoc}
*/
@Override
public String getSubject(EventLogEvent event) {
EventLogEventType type = event.getType();
String subject;
switch (type) {
case BUCKET_CHANGED:
case BUCKET_CREATED:
subject = "Experiment Bucket Update";
break;
case EXPERIMENT_CHANGED:
subject = "Experiment Changed";
break;
case EXPERIMENT_CREATED:
subject = "Experiment Created";
break;
case SIMPLE_EVENT:
default:
throw new IllegalArgumentException("Can not handle EventType: " + type.toString());
}
return subject;
}
/**
* {@inheritDoc}
*/
@Override
public String getMessage(EventLogEvent event) {
EventLogEventType type = event.getType();
String message = "";
switch (type) {
case BUCKET_CHANGED:
message = getBucketChangedMessage((BucketChangeEvent) event);
break;
case BUCKET_CREATED:
message = getBucketCreatedMessage((BucketCreateEvent) event);
break;
case EXPERIMENT_CHANGED:
message = getExperimentChangedMessage((ExperimentChangeEvent) event);
break;
case EXPERIMENT_CREATED:
message = getExperimentCreatedMessage((ExperimentCreateEvent) event);
break;
case SIMPLE_EVENT:
default:
throw new IllegalArgumentException("Can not handle EventType: " + type.toString());
}
return message;
}
/**
* The addressors for a given experiment are the administrators of the application the
* experiment belongs to.
*
* @param event the {@link ExperimentEvent} to be processed
* @return a list of the email-addresses of the addressors
*/
private Collection extends String> getExperimentAddressor(ExperimentEvent event) {
Set adressors;
ExperimentBase exp = event.getExperiment();
if (exp != null) {
adressors = getAdminEmails(exp.getApplicationName());
} else {
throw new EventLogException("An ExperimentEvent was recorded without having an Experiment!");
}
return adressors;
}
/**
* Returns the email adresses of the experiment admins.
*
* @param appName the application we want the admins from
* @return a set of their valid email addresses
*/
private Set getAdminEmails(Application.Name appName) {
Set adressors = new HashSet<>();
UserRoleList usersRoles = authorizationRepository.getApplicationUsers(appName);
for (UserRole user : usersRoles.getRoleList()) {
if (user.getRole() == Role.ADMIN) {
String email = user.getUserEmail();
if (EmailValidator.getInstance().isValid(email)) {
adressors.add(email);
} else {
LOGGER.warn("\"" + email + "\" is not a valid email address for one of the administrators of " + appName);
}
}
}
//no admins, no email!
if (adressors.isEmpty()) {
throw new WasabiEmailException("No Admins with an valid email registered for this Application");
}
return adressors;
}
/**
* This method finds the right attributes to set. The set fields can be found
* in the {@link TextTemplates}.
*
* @param expEvent an {@link ExperimentChangeEvent} that represents the changes
* @return the message for the email
*/
private String getExperimentChangedMessage(ExperimentChangeEvent expEvent) {
ST template = new ST(EXPERIMENT_CHANGED);
Map variables = new HashMap<>();
ExperimentBase exp = expEvent.getExperiment();
put(variables, EXPERIMENT_LABEL, exp.getLabel());
put(variables, EXPERIMENT_ID, String.valueOf(exp.getID()));
put(variables, APPLICATION_NAME, String.valueOf(exp.getApplicationName()));
put(variables, USER_NAME, getUserRepresentation(expEvent.getUser()));
put(variables, FIELD_NAME, expEvent.getPropertyName());
if (expEvent.getPropertyName() != null && "sampling_percent".equalsIgnoreCase(expEvent.getPropertyName())) {
put(variables, FIELD_BEFORE, String.valueOf(((double) Math.round(Double.parseDouble(expEvent.getBefore()) * 10000d) / 10000d) * 100).concat("%"));
put(variables, FIELD_AFTER, String.valueOf(((double) Math.round(Double.parseDouble(expEvent.getAfter()) * 10000d) / 10000d) * 100).concat("%"));
} else {
put(variables, FIELD_BEFORE, expEvent.getBefore());
put(variables, FIELD_AFTER, expEvent.getAfter());
}
return replaceVariablesInTemplate(variables, template);
}
/**
* This method finds the right attributes to set. The set fields can be found
* in the {@link TextTemplates}.
*
* @param expEvent an {@link ExperimentCreateEvent} that represents the created experiment
* @return the message for the email
*/
private String getExperimentCreatedMessage(ExperimentCreateEvent expEvent) {
ST template = new ST(EXPERIMENT_CREATED);
Map variables = new HashMap<>();
ExperimentBase exp = expEvent.getExperiment();
put(variables, EXPERIMENT_LABEL, exp.getLabel());
put(variables, EXPERIMENT_ID, String.valueOf(exp.getID()));
put(variables, APPLICATION_NAME, String.valueOf(exp.getApplicationName()));
put(variables, USER_NAME, getUserRepresentation(expEvent.getUser()));
return replaceVariablesInTemplate(variables, template);
}
/**
* This method finds the right attributes to set. The set fields can be found
* in the {@link TextTemplates}.
*
* @param buckEvent an {@link BucketCreateEvent} that represents the changes
* @return the message for the email
*/
private String getBucketCreatedMessage(BucketCreateEvent buckEvent) {
ST template = new ST(BUCKET_CREATED);
Map variables = new HashMap<>();
Bucket buck = buckEvent.getBucket();
ExperimentBase exp = buckEvent.getExperiment();
put(variables, EXPERIMENT_LABEL, exp.getLabel());
put(variables, BUCKET_NAME, buck.getLabel().toString());
put(variables, APPLICATION_NAME, String.valueOf(exp.getApplicationName()));
put(variables, USER_NAME, getUserRepresentation(buckEvent.getUser()));
return replaceVariablesInTemplate(variables, template);
}
/**
* This method finds the right attributes to set. The set fields can be found
* in the {@link TextTemplates}.
*
* @param buckEvent an {@link BucketChangeEvent} that represents the changes
* @return the message for the email
*/
private String getBucketChangedMessage(BucketChangeEvent buckEvent) {
ST template = new ST(BUCKET_CHANGE);
Map variables = new HashMap<>();
Bucket buck = buckEvent.getBucket();
ExperimentBase exp = buckEvent.getExperiment();
put(variables, EXPERIMENT_LABEL, exp.getLabel());
put(variables, BUCKET_NAME, buck.getLabel().toString());
put(variables, APPLICATION_NAME, String.valueOf(exp.getApplicationName()));
put(variables, USER_NAME, getUserRepresentation(buckEvent.getUser()));
put(variables, FIELD_NAME, buckEvent.getPropertyName());
if (buckEvent.getPropertyName() != null && "allocation".equalsIgnoreCase(buckEvent.getPropertyName())) {
put(variables, FIELD_BEFORE, String.valueOf(((double) Math.round(Double.parseDouble(buckEvent.getBefore()) * 10000d) / 10000d) * 100).concat("%"));
put(variables, FIELD_AFTER, String.valueOf(((double) Math.round(Double.parseDouble(buckEvent.getAfter()) * 10000d) / 10000d) * 100).concat("%"));
} else {
put(variables, FIELD_BEFORE, buckEvent.getBefore());
put(variables, FIELD_AFTER, buckEvent.getAfter());
}
return replaceVariablesInTemplate(variables, template);
}
/**
* Just a little helper method that safes me from writing to many String.valueOf() ..
*
* @param variables parameter set for the email template
* @param key the enum value
* @param value the value to that field
*/
private void put(Map variables, Object key, Object value) {
variables.put(String.valueOf(key), String.valueOf(value));
}
/**
* Gives the user representation as a {@link String} that is shown in the email.
*
* @param user the user we want the representation for
* @return the users full name and email
*/
private String getUserRepresentation(UserInfo user) {
String userRep = "nobody";
if (user == null) {
LOGGER.debug("User was null for a given email - setting her to " + userRep);
} else {
userRep = user.getFirstName() + " " + user.getLastName() + " <" + user.getEmail() + ">";
}
return userRep;
}
/**
* Replaces the values in a template to a complete message.
*
* @param variables values to be replaced
* @param template template for message generation
* @return the complete message
*/
private String replaceVariablesInTemplate(Map variables, ST template) {
if (variables != null) {
for (String key : variables.keySet()) {
String representation = variables.get(key) == null ? "null" : variables.get(key);
template.add(key, representation);
}
}
return template.render();
}
}
© 2015 - 2025 Weber Informatics LLC | Privacy Policy