BodyBuilder.java
package fr.sii.ogham.email.message.fluent;
import fr.sii.ogham.core.message.content.Content;
import fr.sii.ogham.core.message.content.MultiTemplateContent;
import fr.sii.ogham.core.message.fluent.SingleContentBuilder;
import fr.sii.ogham.core.resource.path.ResourcePath;
import fr.sii.ogham.core.template.context.Context;
import fr.sii.ogham.email.message.Email;
/**
* Fluent API to build a content based on:
* <ul>
* <li>Either a single string</li>
* <li>Or a single template string</li>
* <li>Or a single template loaded from a path</li>
* <li>Or two templates (HTML and text) loaded from a path</li>
* </ul>
*
* @author Aurélien Baudet
*
* @since 3.0.0
*/
public class BodyBuilder {
private final Email parent;
private final SingleContentBuilder<Email> singleBuilder;
private Content content;
/**
* Initializes with the parent to go back to.
*
* @param parent
* the parent instance
*/
public BodyBuilder(Email parent) {
super();
this.parent = parent;
this.singleBuilder = new SingleContentBuilder<>(parent);
}
/**
* Set the content directly as a simple string.
*
* <p>
* The body will have only one part (only one main body and no alternative
* body). It can be either HTML or textual.
*
* <p>
* If this method is called several times, only the last value is used.
*
* <p>
* If any other method of this class was called before calling this method,
* only the value of this method is used.
*
* @param content
* the content as a string
* @return the instance for fluent chaining
*/
public Email string(String content) {
return singleBuilder.string(content);
}
/**
* Set the content using a template (directly provided as a string). The
* template contains variables that are evaluated against the bean object.
*
* <p>
* The body will have only one part (only one main body and no alternative
* body). It can be either HTML or textual.
*
* <p>
* If this method is called several times, only the last value is used.
*
* <p>
* If any other method of this class was called before calling this method,
* only the value of this method is used.
*
* @param template
* the template directly provided as a string
* @param bean
* the object that contains the variables that are referenced in
* the template
* @return the instance for fluent chaining
*/
public Email templateString(String template, Object bean) {
return singleBuilder.templateString(template, bean);
}
/**
* Set the content using a template (directly provided as a string). The
* template contains variables that are evaluated against the evaluation
* context. The context contains at least the values of the variables but
* can also contain additional information for parsing the template.
*
* <p>
* The body will have only one part (only one main body and no alternative
* body). It can be either HTML or textual.
*
* <p>
* If this method is called several times, only the last value is used.
*
* <p>
* If any other method of this class was called before calling this method,
* only the value of this method is used.
*
* @param template
* the template directly provided as a string
* @param context
* contains at least the variables that are referenced in the
* template and may contain additional information to parse the
* template
* @return the instance for fluent chaining
*/
public Email templateString(String template, Context context) {
return singleBuilder.templateString(template, context);
}
/**
* Set the content using template(s) loaded from a path. The template(s)
* contain variables that are evaluated against the bean object.
*
* <p>
* This method lets you provide both main body and alternative body using a
* single path (without extension). For example:
*
* You have two templates:
* <ul>
* <li>A textual template located at
* <code>/templates/email/register.txt</code> in the classpath</li>
* <li>An HTML template located at
* <code>/templates/email/register.html</code> in the classpath</li>
* </ul>
*
* You can reference both templates with the same model:
*
* <pre>
* {@code .template("/templates/email/register", new RegistrationContext(...))}
* </pre>
*
* Both templates will be parsed using the same evaluation context. The HTML
* template will be used as the main body and the textual template will be
* used as the alternative body (when the email client can't read the HTML
* body).
*
* <p>
* <strong>NOTE:</strong> the extensions varies according to template engine
* that is used to parse the template.
*
* <p>
* This method is really convenient as if one template is missing (for
* example, you have only written the HTML template but not the textual
* template already), the found template is used as the main body (and the
* email won't have the alternative part). This way you can later add the
* missing template without changing your code.
*
* <p>
* If this method is called several times, only the last value is used.
*
* <p>
* If any other method of this class was called before calling this method,
* only the value of this method is used.
*
* @param templatePath
* the path to the template
* @param bean
* the object that contains the variables that are referenced in
* the template
* @return the instance for fluent chaining
*/
public Email template(String templatePath, Object bean) {
this.content = new MultiTemplateContent(templatePath, bean);
return parent;
}
/**
* Set the content using template(s) loaded from a path. The template(s)
* contain variables that are evaluated against the bean object.
*
* <p>
* This method lets you provide both main body and alternative body using a
* single path (without extension). For example:
*
* You have two templates:
* <ul>
* <li>A textual template located at
* <code>/templates/email/register.txt</code> in the classpath</li>
* <li>An HTML template located at
* <code>/templates/email/register.html</code> in the classpath</li>
* </ul>
*
* You can reference both templates with the same model:
*
* <pre>
* {@code .template("/templates/email/register", new RegistrationContext(...))}
* </pre>
*
* Both templates will be parsed using the same evaluation context. The HTML
* template will be used as the main body and the textual template will be
* used as the alternative body (when the email client can't read the HTML
* body).
*
* <p>
* <strong>NOTE:</strong> the extensions varies according to template engine
* that is used to parse the template.
*
* <p>
* This method is really convenient as if one template is missing (for
* example, you have only written the HTML template but not the textual
* template already), the found template is used as the main body (and the
* email won't have the alternative part). This way you can later add the
* missing template without changing your code.
*
* <p>
* If this method is called several times, only the last value is used.
*
* <p>
* If any other method of this class was called before calling this method,
* only the value of this method is used.
*
* @param templatePath
* the path to the template
* @param bean
* the object that contains the variables that are referenced in
* the template
* @return the instance for fluent chaining
*/
public Email template(ResourcePath templatePath, Object bean) {
this.content = new MultiTemplateContent(templatePath, bean);
return parent;
}
/**
* Set the content using template(s) loaded from a path. The template(s)
* contain variables that are evaluated against the evaluation context. The
* context contains at least the values of the variables but can also
* contain additional information for parsing the template.
*
* <p>
* This method lets you provide both main body and alternative body using a
* single path (without extension). For example:
*
* You have two templates:
* <ul>
* <li>A textual template located at
* <code>/templates/email/register.txt</code> in the classpath</li>
* <li>An HTML template located at
* <code>/templates/email/register.html</code> in the classpath</li>
* </ul>
*
* You can reference both templates with the same model:
*
* <pre>
* {@code .template("/templates/email/register", new RegistrationContext(...))}
* </pre>
*
* Both templates will be parsed using the same evaluation context. The HTML
* template will be used as the main body and the textual template will be
* used as the alternative body (when the email client can't read the HTML
* body).
*
* <p>
* <strong>NOTE:</strong> the extensions varies according to template engine
* that is used to parse the template.
*
* <p>
* This method is really convenient as if one template is missing (for
* example, you have only written the HTML template but not the textual
* template already), the found template is used as the main body (and the
* email won't have the alternative part). This way you can later add the
* missing template without changing your code.
*
* <p>
* If this method is called several times, only the last value is used.
*
* <p>
* If any other method of this class was called before calling this method,
* only the value of this method is used.
*
* @param templatePath
* the path to the template
* @param context
* contains at least the variables that are referenced in the
* template and may contain additional information to parse the
* template
* @return the instance for fluent chaining
*/
public Email template(String templatePath, Context context) {
this.content = new MultiTemplateContent(templatePath, context);
return parent;
}
/**
* Set the content using template(s) loaded from a path. The template(s)
* contain variables that are evaluated against the evaluation context. The
* context contains at least the values of the variables but can also
* contain additional information for parsing the template.
*
* <p>
* This method lets you provide both main body and alternative body using a
* single path (without extension). For example:
*
* You have two templates:
* <ul>
* <li>A textual template located at
* <code>/templates/email/register.txt</code> in the classpath</li>
* <li>An HTML template located at
* <code>/templates/email/register.html</code> in the classpath</li>
* </ul>
*
* You can reference both templates with the same model:
*
* <pre>
* {@code .template("/templates/email/register", new RegistrationContext(...))}
* </pre>
*
* Both templates will be parsed using the same evaluation context. The HTML
* template will be used as the main body and the textual template will be
* used as the alternative body (when the email client can't read the HTML
* body).
*
* <p>
* <strong>NOTE:</strong> the extensions varies according to template engine
* that is used to parse the template.
*
* <p>
* This method is really convenient as if one template is missing (for
* example, you have only written the HTML template but not the textual
* template already), the found template is used as the main body (and the
* email won't have the alternative part). This way you can later add the
* missing template without changing your code.
*
* <p>
* If this method is called several times, only the last value is used.
*
* <p>
* If any other method of this class was called before calling this method,
* only the value of this method is used.
*
* @param templatePath
* the path to the template
* @param context
* contains at least the variables that are referenced in the
* template and may contain additional information to parse the
* template
* @return the instance for fluent chaining
*/
public Email template(ResourcePath templatePath, Context context) {
this.content = new MultiTemplateContent(templatePath, context);
return parent;
}
/**
* Build the final {@link Content}.
*
* {@link #template(ResourcePath, Context)} method (and variants) preempts
* any call to {@link #string(String)},
* {@link #templateString(String, Context)} and
* {@link #templateString(String, Object)}.
*
* @return the built content
*/
public Content build() {
if (content != null) {
return content;
}
return singleBuilder.build();
}
}