added template service, template management service bean, freemarker methods and template loading tests

added templating exception
changed embed configuration to have builders
enabled mocking of final classes for mockito
This commit is contained in:
Sheldan
2020-05-27 23:59:48 +02:00
parent f61cc8e1ff
commit f4edf7a77d
20 changed files with 951 additions and 32 deletions

View File

@@ -34,7 +34,11 @@ public class DurationMethod implements TemplateMethodModelEx {
if (arguments.size() != 1) {
throw new TemplateModelException("Incorrect parameters passed.");
}
Object wrappedObject = ((StringModel) arguments.get(0)).getWrappedObject();
Object o = arguments.get(0);
if(!(o instanceof StringModel)) {
throw new TemplateModelException("Passed object was not a StringModel.");
}
Object wrappedObject = ((StringModel) o).getWrappedObject();
if(!(wrappedObject instanceof Duration)) {
throw new TemplateModelException("Passed argument was not a duration object");
}

View File

@@ -20,15 +20,38 @@ public class SafeFieldIterations implements TemplateMethodModelEx {
@Override
public Object exec(List arguments) throws TemplateModelException {
List wrappedObject = (List) ((DefaultListAdapter) arguments.get(0)).getWrappedObject();
String appliedTemplate = ((SimpleScalar) arguments.get(1)).getAsString();
String nameTemplate = ((SimpleScalar) arguments.get(2)).getAsString();
String inline = ((SimpleScalar) arguments.get(3)).getAsString();
if(arguments.size() != 4) {
throw new TemplateModelException("Incorrect amount of parameters.");
}
Object adapterObject = arguments.get(0);
if(!(adapterObject instanceof DefaultListAdapter)) {
throw new TemplateModelException("Passed object was not a DefaultListAdapter.");
}
Object wrappedList = ((DefaultListAdapter) adapterObject).getWrappedObject();
if(!(wrappedList instanceof List)) {
throw new TemplateModelException("Passed object was not a List.");
}
List wrappedObject = (List) wrappedList;
Object templateParameter = arguments.get(1);
if(!(templateParameter instanceof SimpleScalar)) {
throw new TemplateModelException("Passed object for template was not a SimpleScalar.");
}
String appliedTemplate = ((SimpleScalar) templateParameter).getAsString();
Object fieldNameTemplateParameter = arguments.get(2);
if(!(fieldNameTemplateParameter instanceof SimpleScalar)) {
throw new TemplateModelException("Passed object for field name template was not a SimpleScalar.");
}
String fieldNameTemplate = ((SimpleScalar) fieldNameTemplateParameter).getAsString();
Object inlineParameter = arguments.get(3);
if(!(inlineParameter instanceof SimpleScalar)) {
throw new TemplateModelException("Passed object for inline was not a SimpleScalar.");
}
String inline = ((SimpleScalar) inlineParameter).getAsString();
List<StringBuilder> result = new ArrayList<>();
StringBuilder currentBuilder = new StringBuilder();
String firstEmbedTitle = service.renderTemplateWithMap(nameTemplate, getEmbedCountParameters(1, wrappedObject));
String firstEmbedTitle = service.renderTemplateWithMap(fieldNameTemplate, getEmbedCountParameters(1, wrappedObject));
currentBuilder.append(newFieldHeader(firstEmbedTitle, inline));
String finalClosingString = "\"}";
String closingString = finalClosingString + ",";
@@ -42,7 +65,7 @@ public class SafeFieldIterations implements TemplateMethodModelEx {
result.add(currentBuilder);
currentBuilder = new StringBuilder();
splitFieldCounts += 1;
String renderedName = service.renderTemplateWithMap(nameTemplate, getEmbedCountParameters(splitFieldCounts, wrappedObject));
String renderedName = service.renderTemplateWithMap(fieldNameTemplate, getEmbedCountParameters(splitFieldCounts, wrappedObject));
currentBuilder.append(newFieldHeader(renderedName, inline));
}
currentBuilder.append(s);
@@ -54,14 +77,14 @@ public class SafeFieldIterations implements TemplateMethodModelEx {
for (StringBuilder innerBuilder: result) {
bigBuilder.append(innerBuilder.toString());
}
return bigBuilder;
return bigBuilder.toString();
}
private String newFieldHeader(String name, String inline) {
return String.format("{ \"name\": \"%s\", \"inline\": \"%s\", \"value\": \"", name, inline);
}
private HashMap<String, Object> getEmbedCountParameters(Integer count, List objects) {
private HashMap<String, Object> getEmbedCountParameters(Integer count, List<? extends Object> objects) {
HashMap<String, Object> parameters = new HashMap<>();
parameters.put("count", count);
parameters.put("list", objects);

View File

@@ -1,6 +1,7 @@
package dev.sheldan.abstracto.templating.model;
import lombok.Builder;
import lombok.Getter;
import lombok.Setter;
@@ -9,6 +10,7 @@ import lombok.Setter;
*/
@Getter
@Setter
@Builder
public class EmbedAuthor {
/**
* The name used in the {@link net.dv8tion.jda.api.entities.MessageEmbed} author

View File

@@ -1,5 +1,6 @@
package dev.sheldan.abstracto.templating.model;
import lombok.Builder;
import lombok.Getter;
import lombok.Setter;
@@ -8,6 +9,7 @@ import lombok.Setter;
*/
@Setter
@Getter
@Builder
public class EmbedColor {
/**
* The red part of RGB

View File

@@ -1,5 +1,6 @@
package dev.sheldan.abstracto.templating.model;
import lombok.Builder;
import lombok.Getter;
import lombok.Setter;
@@ -12,6 +13,7 @@ import java.util.List;
*/
@Getter
@Setter
@Builder
public class EmbedConfiguration {
/**
* The {@link EmbedAuthor} object holding the configuration for the author of the {@link net.dv8tion.jda.api.entities.MessageEmbed}

View File

@@ -1,5 +1,6 @@
package dev.sheldan.abstracto.templating.model;
import lombok.Builder;
import lombok.Getter;
import lombok.Setter;
@@ -8,6 +9,7 @@ import lombok.Setter;
*/
@Getter
@Setter
@Builder
public class EmbedFooter {
/**
* The text which is going to be used as the footer text

View File

@@ -1,5 +1,6 @@
package dev.sheldan.abstracto.templating.model;
import lombok.Builder;
import lombok.Getter;
import lombok.Setter;
@@ -8,6 +9,7 @@ import lombok.Setter;
*/
@Getter
@Setter
@Builder
public class EmbedTitle {
/**
* The text which is going to be used as the title of the embed

View File

@@ -2,18 +2,20 @@ package dev.sheldan.abstracto.templating.service;
import com.google.gson.Gson;
import dev.sheldan.abstracto.templating.Templatable;
import dev.sheldan.abstracto.templating.exception.TemplatingException;
import dev.sheldan.abstracto.templating.model.*;
import freemarker.template.Configuration;
import freemarker.template.Template;
import freemarker.template.TemplateException;
import lombok.extern.slf4j.Slf4j;
import net.dv8tion.jda.api.EmbedBuilder;
import net.dv8tion.jda.api.entities.MessageEmbed;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import org.springframework.ui.freemarker.FreeMarkerTemplateUtils;
import java.awt.*;
import java.io.IOException;
import java.io.StringWriter;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
@@ -89,7 +91,7 @@ public class TemplateServiceBean implements TemplateService {
firstBuilder.setFooter(footer.getText(), footer.getIcon());
}
if(embedConfiguration.getFields() != null) {
createFieldsForEmbed(key, embedBuilders, embedConfiguration);
createFieldsForEmbed(embedBuilders, embedConfiguration);
}
firstBuilder.setTimestamp(embedConfiguration.getTimeStamp());
@@ -112,18 +114,14 @@ public class TemplateServiceBean implements TemplateService {
.build();
}
private void createFieldsForEmbed(String key, List<EmbedBuilder> embedBuilders, EmbedConfiguration configuration) {
private void createFieldsForEmbed(List<EmbedBuilder> embedBuilders, EmbedConfiguration configuration) {
for (int i = 0; i < configuration.getFields().size(); i++) {
EmbedField field = configuration.getFields().get(i);
if(field != null && field.getValue() != null) {
if(field.getValue().length() > MessageEmbed.VALUE_MAX_LENGTH) {
String substring = field.getValue().substring(MessageEmbed.VALUE_MAX_LENGTH);
field.setValue(field.getValue().substring(0, MessageEmbed.VALUE_MAX_LENGTH));
EmbedField secondPart = EmbedField.builder().inline(field.getInline()).name(field.getName() + " 2").value(substring).build();
configuration.getFields().add(i + 1, secondPart);
}
} else {
log.warn("Field {} in template {} is null.", i, key);
if(field != null && field.getValue() != null && field.getValue().length() > MessageEmbed.VALUE_MAX_LENGTH) {
String substring = field.getValue().substring(MessageEmbed.VALUE_MAX_LENGTH);
field.setValue(field.getValue().substring(0, MessageEmbed.VALUE_MAX_LENGTH));
EmbedField secondPart = EmbedField.builder().inline(field.getInline()).name(field.getName() + " 2").value(substring).build();
configuration.getFields().add(i + 1, secondPart);
}
}
double neededIndex = Math.ceil(configuration.getFields().size() / 25D) - 1;
@@ -161,10 +159,10 @@ public class TemplateServiceBean implements TemplateService {
@Override
public String renderTemplateWithMap(String key, HashMap<String, Object> parameters) {
try {
return FreeMarkerTemplateUtils.processTemplateIntoString(configuration.getTemplate(key), parameters);
return renderTemplateToString(key, parameters);
} catch (IOException | TemplateException e) {
log.warn("Failed to render template. ", e);
throw new RuntimeException(e);
throw new TemplatingException(e);
}
}
@@ -177,13 +175,28 @@ public class TemplateServiceBean implements TemplateService {
@Override
public String renderTemplate(String key, Object model) {
try {
return FreeMarkerTemplateUtils.processTemplateIntoString(configuration.getTemplate(key), model);
return renderTemplateToString(key, model);
} catch (IOException | TemplateException e) {
log.warn("Failed to render template. ", e);
throw new RuntimeException(e);
throw new TemplatingException(e);
}
}
/**
* Loads the given key as a template, and renders it, returns the result as a String
* @param key The key of the template to render
* @param model The parameters which are given to the template
* @return The rendered template in a String
* @throws freemarker.template.TemplateNotFoundException In case the template could not be found
* @throws TemplateException In case the rendering failed
*/
private String renderTemplateToString(String key, Object model) throws IOException, TemplateException {
StringWriter result = new StringWriter();
Template template = configuration.getTemplate(key);
template.process(model, result);
return result.toString();
}
/**
* Renders a simple template identified by key without any model. This will cause exceptions in case there are references to a model in the provided template.
* @param key The key of the template to be rendered