package fr.jcgay.notification;
import com.google.common.annotations.VisibleForTesting;
import fr.jcgay.notification.configuration.ChosenNotifiers;
import fr.jcgay.notification.configuration.ConfigurationReader;
import fr.jcgay.notification.configuration.OperatingSystem;
import fr.jcgay.notification.notifier.DoNothingNotifier;
import org.slf4j.Logger;
import java.util.Properties;
import java.util.Set;
import static org.slf4j.LoggerFactory.getLogger;
/**
* Fluent builder to create a {@link fr.jcgay.notification.Notifier}. <br />
*
* You'll need a configuration file (by default: {@code {user.home}/.send-notification}
* to select and configure a {@link fr.jcgay.notification.Notifier}. <br />
* This file must be property based (example):
* <pre>{@code
* notifier.implementation = pushbullet
* notifier.message.short = true
* notifier.pushbullet.apikey = 1234
* }</pre>
*
* Then to create a notifier you can use:
* <pre>{@code
* Notifier notifier = new SendNotification()
* .setApplication(application)
* .initNotifier();
* }</pre>
*/
public class SendNotification {
private static final Logger LOGGER = getLogger(SendNotification.class);
private final NotifierProvider provider;
private ConfigurationReader configuration;
private Application application;
private ChosenNotifiers chosenNotifiers;
private Properties additionalConfiguration;
SendNotification(ConfigurationReader configuration, OperatingSystem currentOs) {
this(configuration, new NotifierProvider(currentOs));
}
SendNotification(ConfigurationReader configuration, NotifierProvider provider) {
this.configuration = configuration;
this.provider = provider;
}
public SendNotification() {
this(ConfigurationReader.atPath(System.getProperty("user.home") + "/.send-notification"), new OperatingSystem());
}
@VisibleForTesting
DiscoverableNotifier chooseNotifier() {
Properties properties = configuration.get();
mergeConfigurations(properties);
maySetNotifierFromPropertyConfiguration(properties);
if (chosenNotifiers != null) {
LOGGER.debug("Notifications will be send to: {} for application: {}.", chosenNotifiers, application);
return provider.byName(chosenNotifiers, properties, application);
}
return defaultNotifier(properties);
}
/**
* Build a {@link fr.jcgay.notification.Notifier}.
*
* @return notifier based on provided configuration.
*/
public Notifier initNotifier() {
return chooseNotifier().init();
}
/**
* Define application.
*
* @param application {@link fr.jcgay.notification.Application} we want to send notification from.
*
* @return fluent builder.
*/
public SendNotification setApplication(Application application) {
this.application = application;
return this;
}
/**
* Choose a {@link fr.jcgay.notification.Notifier} implementation when you don't want to
* rely on property file configuration.
*
* @param chosenNotifier a notifier name to instantiate.
*
* @return fluent builder.
*/
public SendNotification setChosenNotifier(String chosenNotifier) {
this.chosenNotifiers = ChosenNotifiers.from(chosenNotifier);
return this;
}
/**
* Change the path where the configuration will be read from. <br />
* Default one is: {@code {user.home}/.send-notification}
*
* @param configurationPath a file path for configuration file.
*
* @return fluent builder.
*/
public SendNotification setConfigurationPath(String configurationPath) {
this.configuration = ConfigurationReader.atPath(configurationPath);
return this;
}
/**
* Add properties that will override existing ones (read from the configuration file).
*
* @param additionalConfiguration configuration (key/value) as {@link java.util.Properties}.
*
* @return fluent builder.
*/
public SendNotification addConfigurationProperties(Properties additionalConfiguration) {
this.additionalConfiguration = additionalConfiguration;
return this;
}
private DiscoverableNotifier defaultNotifier(Properties properties) {
Set<DiscoverableNotifier> all = provider.available(properties, application);
for (DiscoverableNotifier candidate : all) {
boolean isAvailable = candidate.tryInit();
LOGGER.debug("{} is available ? {}.", candidate, isAvailable);
if (isAvailable) {
return candidate;
}
}
return DoNothingNotifier.doNothing();
}
private void mergeConfigurations(Properties properties) {
if (additionalConfiguration != null && !additionalConfiguration.isEmpty()) {
LOGGER.debug("Overriding previous configuration with: {}.", additionalConfiguration);
properties.putAll(additionalConfiguration);
}
}
private void maySetNotifierFromPropertyConfiguration(Properties properties) {
String candidate = (String) properties.get("notifier.implementation");
if (chosenNotifiers == null && candidate != null) {
chosenNotifiers = ChosenNotifiers.from(candidate);
}
}
}