BodyBuilder.java

  1. package fr.sii.ogham.email.message.fluent;

  2. import fr.sii.ogham.core.message.content.Content;
  3. import fr.sii.ogham.core.message.content.MultiTemplateContent;
  4. import fr.sii.ogham.core.message.fluent.SingleContentBuilder;
  5. import fr.sii.ogham.core.resource.path.ResourcePath;
  6. import fr.sii.ogham.core.template.context.Context;
  7. import fr.sii.ogham.email.message.Email;

  8. /**
  9.  * Fluent API to build a content based on:
  10.  * <ul>
  11.  * <li>Either a single string</li>
  12.  * <li>Or a single template string</li>
  13.  * <li>Or a single template loaded from a path</li>
  14.  * <li>Or two templates (HTML and text) loaded from a path</li>
  15.  * </ul>
  16.  *
  17.  * @author AurĂ©lien Baudet
  18.  *
  19.  * @since 3.0.0
  20.  */
  21. public class BodyBuilder {
  22.     private final Email parent;
  23.     private final SingleContentBuilder<Email> singleBuilder;
  24.     private Content content;

  25.     /**
  26.      * Initializes with the parent to go back to.
  27.      *
  28.      * @param parent
  29.      *            the parent instance
  30.      */
  31.     public BodyBuilder(Email parent) {
  32.         super();
  33.         this.parent = parent;
  34.         this.singleBuilder = new SingleContentBuilder<>(parent);
  35.     }

  36.     /**
  37.      * Set the content directly as a simple string.
  38.      *
  39.      * <p>
  40.      * The body will have only one part (only one main body and no alternative
  41.      * body). It can be either HTML or textual.
  42.      *
  43.      * <p>
  44.      * If this method is called several times, only the last value is used.
  45.      *
  46.      * <p>
  47.      * If any other method of this class was called before calling this method,
  48.      * only the value of this method is used.
  49.      *
  50.      * @param content
  51.      *            the content as a string
  52.      * @return the instance for fluent chaining
  53.      */
  54.     public Email string(String content) {
  55.         return singleBuilder.string(content);
  56.     }

  57.     /**
  58.      * Set the content using a template (directly provided as a string). The
  59.      * template contains variables that are evaluated against the bean object.
  60.      *
  61.      * <p>
  62.      * The body will have only one part (only one main body and no alternative
  63.      * body). It can be either HTML or textual.
  64.      *
  65.      * <p>
  66.      * If this method is called several times, only the last value is used.
  67.      *
  68.      * <p>
  69.      * If any other method of this class was called before calling this method,
  70.      * only the value of this method is used.
  71.      *
  72.      * @param template
  73.      *            the template directly provided as a string
  74.      * @param bean
  75.      *            the object that contains the variables that are referenced in
  76.      *            the template
  77.      * @return the instance for fluent chaining
  78.      */
  79.     public Email templateString(String template, Object bean) {
  80.         return singleBuilder.templateString(template, bean);
  81.     }

  82.     /**
  83.      * Set the content using a template (directly provided as a string). The
  84.      * template contains variables that are evaluated against the evaluation
  85.      * context. The context contains at least the values of the variables but
  86.      * can also contain additional information for parsing the template.
  87.      *
  88.      * <p>
  89.      * The body will have only one part (only one main body and no alternative
  90.      * body). It can be either HTML or textual.
  91.      *
  92.      * <p>
  93.      * If this method is called several times, only the last value is used.
  94.      *
  95.      * <p>
  96.      * If any other method of this class was called before calling this method,
  97.      * only the value of this method is used.
  98.      *
  99.      * @param template
  100.      *            the template directly provided as a string
  101.      * @param context
  102.      *            contains at least the variables that are referenced in the
  103.      *            template and may contain additional information to parse the
  104.      *            template
  105.      * @return the instance for fluent chaining
  106.      */
  107.     public Email templateString(String template, Context context) {
  108.         return singleBuilder.templateString(template, context);
  109.     }

  110.     /**
  111.      * Set the content using template(s) loaded from a path. The template(s)
  112.      * contain variables that are evaluated against the bean object.
  113.      *
  114.      * <p>
  115.      * This method lets you provide both main body and alternative body using a
  116.      * single path (without extension). For example:
  117.      *
  118.      * You have two templates:
  119.      * <ul>
  120.      * <li>A textual template located at
  121.      * <code>/templates/email/register.txt</code> in the classpath</li>
  122.      * <li>An HTML template located at
  123.      * <code>/templates/email/register.html</code> in the classpath</li>
  124.      * </ul>
  125.      *
  126.      * You can reference both templates with the same model:
  127.      *
  128.      * <pre>
  129.      * {@code .template("/templates/email/register", new RegistrationContext(...))}
  130.      * </pre>
  131.      *
  132.      * Both templates will be parsed using the same evaluation context. The HTML
  133.      * template will be used as the main body and the textual template will be
  134.      * used as the alternative body (when the email client can't read the HTML
  135.      * body).
  136.      *
  137.      * <p>
  138.      * <strong>NOTE:</strong> the extensions varies according to template engine
  139.      * that is used to parse the template.
  140.      *
  141.      * <p>
  142.      * This method is really convenient as if one template is missing (for
  143.      * example, you have only written the HTML template but not the textual
  144.      * template already), the found template is used as the main body (and the
  145.      * email won't have the alternative part). This way you can later add the
  146.      * missing template without changing your code.
  147.      *
  148.      * <p>
  149.      * If this method is called several times, only the last value is used.
  150.      *
  151.      * <p>
  152.      * If any other method of this class was called before calling this method,
  153.      * only the value of this method is used.
  154.      *
  155.      * @param templatePath
  156.      *            the path to the template
  157.      * @param bean
  158.      *            the object that contains the variables that are referenced in
  159.      *            the template
  160.      * @return the instance for fluent chaining
  161.      */
  162.     public Email template(String templatePath, Object bean) {
  163.         this.content = new MultiTemplateContent(templatePath, bean);
  164.         return parent;
  165.     }

  166.     /**
  167.      * Set the content using template(s) loaded from a path. The template(s)
  168.      * contain variables that are evaluated against the bean object.
  169.      *
  170.      * <p>
  171.      * This method lets you provide both main body and alternative body using a
  172.      * single path (without extension). For example:
  173.      *
  174.      * You have two templates:
  175.      * <ul>
  176.      * <li>A textual template located at
  177.      * <code>/templates/email/register.txt</code> in the classpath</li>
  178.      * <li>An HTML template located at
  179.      * <code>/templates/email/register.html</code> in the classpath</li>
  180.      * </ul>
  181.      *
  182.      * You can reference both templates with the same model:
  183.      *
  184.      * <pre>
  185.      * {@code .template("/templates/email/register", new RegistrationContext(...))}
  186.      * </pre>
  187.      *
  188.      * Both templates will be parsed using the same evaluation context. The HTML
  189.      * template will be used as the main body and the textual template will be
  190.      * used as the alternative body (when the email client can't read the HTML
  191.      * body).
  192.      *
  193.      * <p>
  194.      * <strong>NOTE:</strong> the extensions varies according to template engine
  195.      * that is used to parse the template.
  196.      *
  197.      * <p>
  198.      * This method is really convenient as if one template is missing (for
  199.      * example, you have only written the HTML template but not the textual
  200.      * template already), the found template is used as the main body (and the
  201.      * email won't have the alternative part). This way you can later add the
  202.      * missing template without changing your code.
  203.      *
  204.      * <p>
  205.      * If this method is called several times, only the last value is used.
  206.      *
  207.      * <p>
  208.      * If any other method of this class was called before calling this method,
  209.      * only the value of this method is used.
  210.      *
  211.      * @param templatePath
  212.      *            the path to the template
  213.      * @param bean
  214.      *            the object that contains the variables that are referenced in
  215.      *            the template
  216.      * @return the instance for fluent chaining
  217.      */
  218.     public Email template(ResourcePath templatePath, Object bean) {
  219.         this.content = new MultiTemplateContent(templatePath, bean);
  220.         return parent;
  221.     }

  222.     /**
  223.      * Set the content using template(s) loaded from a path. The template(s)
  224.      * contain variables that are evaluated against the evaluation context. The
  225.      * context contains at least the values of the variables but can also
  226.      * contain additional information for parsing the template.
  227.      *
  228.      * <p>
  229.      * This method lets you provide both main body and alternative body using a
  230.      * single path (without extension). For example:
  231.      *
  232.      * You have two templates:
  233.      * <ul>
  234.      * <li>A textual template located at
  235.      * <code>/templates/email/register.txt</code> in the classpath</li>
  236.      * <li>An HTML template located at
  237.      * <code>/templates/email/register.html</code> in the classpath</li>
  238.      * </ul>
  239.      *
  240.      * You can reference both templates with the same model:
  241.      *
  242.      * <pre>
  243.      * {@code .template("/templates/email/register", new RegistrationContext(...))}
  244.      * </pre>
  245.      *
  246.      * Both templates will be parsed using the same evaluation context. The HTML
  247.      * template will be used as the main body and the textual template will be
  248.      * used as the alternative body (when the email client can't read the HTML
  249.      * body).
  250.      *
  251.      * <p>
  252.      * <strong>NOTE:</strong> the extensions varies according to template engine
  253.      * that is used to parse the template.
  254.      *
  255.      * <p>
  256.      * This method is really convenient as if one template is missing (for
  257.      * example, you have only written the HTML template but not the textual
  258.      * template already), the found template is used as the main body (and the
  259.      * email won't have the alternative part). This way you can later add the
  260.      * missing template without changing your code.
  261.      *
  262.      * <p>
  263.      * If this method is called several times, only the last value is used.
  264.      *
  265.      * <p>
  266.      * If any other method of this class was called before calling this method,
  267.      * only the value of this method is used.
  268.      *
  269.      * @param templatePath
  270.      *            the path to the template
  271.      * @param context
  272.      *            contains at least the variables that are referenced in the
  273.      *            template and may contain additional information to parse the
  274.      *            template
  275.      * @return the instance for fluent chaining
  276.      */
  277.     public Email template(String templatePath, Context context) {
  278.         this.content = new MultiTemplateContent(templatePath, context);
  279.         return parent;
  280.     }

  281.     /**
  282.      * Set the content using template(s) loaded from a path. The template(s)
  283.      * contain variables that are evaluated against the evaluation context. The
  284.      * context contains at least the values of the variables but can also
  285.      * contain additional information for parsing the template.
  286.      *
  287.      * <p>
  288.      * This method lets you provide both main body and alternative body using a
  289.      * single path (without extension). For example:
  290.      *
  291.      * You have two templates:
  292.      * <ul>
  293.      * <li>A textual template located at
  294.      * <code>/templates/email/register.txt</code> in the classpath</li>
  295.      * <li>An HTML template located at
  296.      * <code>/templates/email/register.html</code> in the classpath</li>
  297.      * </ul>
  298.      *
  299.      * You can reference both templates with the same model:
  300.      *
  301.      * <pre>
  302.      * {@code .template("/templates/email/register", new RegistrationContext(...))}
  303.      * </pre>
  304.      *
  305.      * Both templates will be parsed using the same evaluation context. The HTML
  306.      * template will be used as the main body and the textual template will be
  307.      * used as the alternative body (when the email client can't read the HTML
  308.      * body).
  309.      *
  310.      * <p>
  311.      * <strong>NOTE:</strong> the extensions varies according to template engine
  312.      * that is used to parse the template.
  313.      *
  314.      * <p>
  315.      * This method is really convenient as if one template is missing (for
  316.      * example, you have only written the HTML template but not the textual
  317.      * template already), the found template is used as the main body (and the
  318.      * email won't have the alternative part). This way you can later add the
  319.      * missing template without changing your code.
  320.      *
  321.      * <p>
  322.      * If this method is called several times, only the last value is used.
  323.      *
  324.      * <p>
  325.      * If any other method of this class was called before calling this method,
  326.      * only the value of this method is used.
  327.      *
  328.      * @param templatePath
  329.      *            the path to the template
  330.      * @param context
  331.      *            contains at least the variables that are referenced in the
  332.      *            template and may contain additional information to parse the
  333.      *            template
  334.      * @return the instance for fluent chaining
  335.      */
  336.     public Email template(ResourcePath templatePath, Context context) {
  337.         this.content = new MultiTemplateContent(templatePath, context);
  338.         return parent;
  339.     }

  340.     /**
  341.      * Build the final {@link Content}.
  342.      *
  343.      * {@link #template(ResourcePath, Context)} method (and variants) preempts
  344.      * any call to {@link #string(String)},
  345.      * {@link #templateString(String, Context)} and
  346.      * {@link #templateString(String, Object)}.
  347.      *
  348.      * @return the built content
  349.      */
  350.     public Content build() {
  351.         if (content != null) {
  352.             return content;
  353.         }
  354.         return singleBuilder.build();
  355.     }
  356. }