AutofillSubjectBuilder.java
package fr.sii.ogham.email.builder;
import fr.sii.ogham.core.builder.Builder;
import fr.sii.ogham.core.builder.configuration.ConfigurationValueBuilder;
import fr.sii.ogham.core.builder.configuration.ConfigurationValueBuilderHelper;
import fr.sii.ogham.core.builder.configurer.Configurer;
import fr.sii.ogham.core.builder.context.BuildContext;
import fr.sii.ogham.core.builder.env.EnvironmentBuilder;
import fr.sii.ogham.core.builder.filler.AbstractAutofillDefaultValueBuilder;
import fr.sii.ogham.core.filler.MessageFiller;
import fr.sii.ogham.core.filler.SubjectFiller;
import fr.sii.ogham.core.subject.provider.FirstSupportingSubjectProvider;
import fr.sii.ogham.core.subject.provider.HtmlTitleSubjectProvider;
import fr.sii.ogham.core.subject.provider.MultiContentSubjectProvider;
import fr.sii.ogham.core.subject.provider.SubjectProvider;
import fr.sii.ogham.core.subject.provider.TextPrefixSubjectProvider;
import fr.sii.ogham.email.message.Email;
/**
* Configures how to handle missing {@link Email} subject: if no subject is
* explicitly defined on the {@link Email}, Ogham will use the result of this
* builder configuration to provide a default subject.
*
* Default subject can be provided by:
* <ul>
* <li>Using HTML {@code <title>} header tag as subject</li>
* <li>Using first line text if prefixed</li>
* <li>Using a property value</li>
* </ul>
*
* @author Aurélien Baudet
*
*/
public class AutofillSubjectBuilder extends AbstractAutofillDefaultValueBuilder<AutofillSubjectBuilder, AutofillEmailBuilder, String> implements Builder<MessageFiller> {
private final ConfigurationValueBuilderHelper<AutofillSubjectBuilder, Boolean> enableHtmlTitleValueBuilder;
private final ConfigurationValueBuilderHelper<AutofillSubjectBuilder, String> firstLinePrefixValueBuilder;
private SubjectProvider customProvider;
/**
* Initializes with the parent builder and the {@link EnvironmentBuilder}.
* The parent builder is used when calling the {@link #and()} method. The
* {@link EnvironmentBuilder} is used by {@link #build()} method to evaluate
* property values.
*
* @param parent
* the parent builder
* @param buildContext
* for property resolution
*/
public AutofillSubjectBuilder(AutofillEmailBuilder parent, BuildContext buildContext) {
super(AutofillSubjectBuilder.class, parent, String.class, buildContext);
enableHtmlTitleValueBuilder = buildContext.newConfigurationValueBuilder(myself, Boolean.class);
firstLinePrefixValueBuilder = buildContext.newConfigurationValueBuilder(myself, String.class);
}
/**
* Enable/disable using HTML {@code <title>} tag to provide a subject on the
* {@link Email} if none was explicitly defined.
*
* <p>
* The value set using this method takes precedence over any property and
* default value configured using {@link #htmlTitle()}.
*
* <pre>
* .htmlTitle(false)
* .htmlTitle()
* .properties("${custom.property.high-priority}", "${custom.property.low-priority}")
* .defaultValue(true)
* </pre>
*
* <pre>
* .htmlTitle(false)
* .htmlTitle()
* .properties("${custom.property.high-priority}", "${custom.property.low-priority}")
* .defaultValue(true)
* </pre>
*
* In both cases, {@code htmlTitle(false)} is used.
*
* <p>
* If this method is called several times, only the last value is used.
*
* <p>
* If {@code null} value is set, it is like not setting a value at all. The
* property/default value configuration is applied.
*
* @param enable
* enable (true) or disable (false) extraction of HTML title to be used as subject of the email
* @return this instance for fluent chaining
*/
public AutofillSubjectBuilder htmlTitle(Boolean enable) {
enableHtmlTitleValueBuilder.setValue(enable);
return this;
}
/**
* Enable/disable using HTML {@code <title>} tag to provide a subject on the
* {@link Email} if none was explicitly defined.
*
* <p>
* This method is mainly used by {@link Configurer}s to register some property keys and/or a default value.
* The aim is to let developer be able to externalize its configuration (using system properties, configuration file or anything else).
* If the developer doesn't configure any value for the registered properties, the default value is used (if set).
*
* <pre>
* .htmlTitle()
* .properties("${custom.property.high-priority}", "${custom.property.low-priority}")
* .defaultValue(true)
* </pre>
*
* <p>
* Non-null value set using {@link #htmlTitle(Boolean)} takes
* precedence over property values and default value.
*
* <pre>
* .htmlTitle(false)
* .htmlTitle()
* .properties("${custom.property.high-priority}", "${custom.property.low-priority}")
* .defaultValue(true)
* </pre>
*
* The value {@code false} is used regardless of the value of the properties
* and default value.
*
* <p>
* See {@link ConfigurationValueBuilder} for more information.
*
*
* @return the builder to configure property keys/default value
*/
public ConfigurationValueBuilder<AutofillSubjectBuilder, Boolean> htmlTitle() {
return enableHtmlTitleValueBuilder;
}
/**
* Uses first line of text template to define the email subject (only if a
* prefix is defined).
*
* <p>
* The value set using this method takes precedence over any property and
* default value configured using {@link #text()}.
*
* <pre>
* .text("MyPrefix:")
* .text()
* .properties("${custom.property.high-priority}", "${custom.property.low-priority}")
* .defaultValue("Subject:")
* </pre>
*
* <pre>
* .text("MyPrefix:")
* .text()
* .properties("${custom.property.high-priority}", "${custom.property.low-priority}")
* .defaultValue("Subject:")
* </pre>
*
* In both cases, {@code text("MyPrefix:")} is used.
*
* <p>
* If this method is called several times, only the last value is used.
*
* <p>
* If {@code null} value is set, it is like not setting a value at all. The
* property/default value configuration is applied.
*
* @param firstLinePrefix
* the prefix used to indicate that subject should be extracted
* @return this instance for fluent chaining
*/
public AutofillSubjectBuilder text(String firstLinePrefix) {
firstLinePrefixValueBuilder.setValue(firstLinePrefix);
return this;
}
/**
* Uses first line of text template to define the email subject (only if a
* prefix is defined).
*
* <p>
* This method is mainly used by {@link Configurer}s to register some property keys and/or a default value.
* The aim is to let developer be able to externalize its configuration (using system properties, configuration file or anything else).
* If the developer doesn't configure any value for the registered properties, the default value is used (if set).
*
* <pre>
* .text()
* .properties("${custom.property.high-priority}", "${custom.property.low-priority}")
* .defaultValue("Subject:")
* </pre>
*
* <p>
* Non-null value set using {@link #text(String)} takes
* precedence over property values and default value.
*
* <pre>
* .text("MyPrefix:")
* .text()
* .properties("${custom.property.high-priority}", "${custom.property.low-priority}")
* .defaultValue("Subject:")
* </pre>
*
* The value {@code "MyPrefix:"} is used regardless of the value of the properties
* and default value.
*
* <p>
* See {@link ConfigurationValueBuilder} for more information.
*
*
* @return the builder to configure property keys/default value
*/
public ConfigurationValueBuilder<AutofillSubjectBuilder, String> text() {
return firstLinePrefixValueBuilder;
}
/**
* Extension point to provide any additional subject provider. See
* {@link SubjectProvider} for more information.
*
* If defined, any previously defined configuration is not used.
*
* Only one provider can be defined. So you may need to register a
* {@link FirstSupportingSubjectProvider} with the list of your custom
* providers.
*
* @param provider
* the provider to use
* @return this instance for fluent chaining
*/
public AutofillSubjectBuilder provider(SubjectProvider provider) {
customProvider = provider;
return myself;
}
@Override
public MessageFiller build() {
return buildContext.register(new SubjectFiller(buildProvider()));
}
private SubjectProvider buildProvider() {
if (customProvider != null) {
return customProvider;
}
FirstSupportingSubjectProvider provider = buildContext.register(new FirstSupportingSubjectProvider());
String prefix = firstLinePrefixValueBuilder.getValue();
if (prefix != null) {
provider.addProvider(buildContext.register(new TextPrefixSubjectProvider(prefix)));
}
boolean htmlTitle = enableHtmlTitleValueBuilder.getValue(false);
if (htmlTitle) {
provider.addProvider(buildContext.register(new HtmlTitleSubjectProvider()));
}
SubjectProvider multiContentProvider = buildContext.register(new MultiContentSubjectProvider(provider));
provider.addProvider(multiContentProvider);
return provider;
}
}