package com.twasyl.slideshowfx.engine.template; import com.twasyl.slideshowfx.engine.AbstractEngine; import com.twasyl.slideshowfx.engine.EngineException; import com.twasyl.slideshowfx.engine.template.configuration.SlideElementTemplate; import com.twasyl.slideshowfx.engine.template.configuration.SlideTemplate; import com.twasyl.slideshowfx.engine.template.configuration.TemplateConfiguration; import com.twasyl.slideshowfx.utils.JSONHelper; import com.twasyl.slideshowfx.utils.ZipUtils; import com.twasyl.slideshowfx.utils.beans.Pair; import io.vertx.core.json.JsonArray; import io.vertx.core.json.JsonObject; import java.io.*; import java.util.ArrayList; import java.util.Arrays; import java.util.Base64; import java.util.HashSet; import java.util.logging.Logger; import static com.twasyl.slideshowfx.engine.template.configuration.TemplateConfiguration.*; import static com.twasyl.slideshowfx.global.configuration.GlobalConfiguration.getDefaultCharset; /** * This class is used to managed the templates provided by SlideshowFX. * The extension of a template is {@code sfxt}. * * @author Thierry Wasylczenko * @version 1.1 * @since SlideshowFX 1.0 */ public class TemplateEngine extends AbstractEngine<TemplateConfiguration> { private static final Logger LOGGER = Logger.getLogger(TemplateEngine.class.getName()); /** * The default extension for template archives. Value is {@value #DEFAULT_ARCHIVE_EXTENSION}. */ public static final String DEFAULT_ARCHIVE_EXTENSION = "sfxt"; /** * The default value, containing the dot, for presentation archives. */ public static final String DEFAULT_DOTTED_ARCHIVE_EXTENSION = ".".concat(DEFAULT_ARCHIVE_EXTENSION); public TemplateEngine() { super(DEFAULT_ARCHIVE_EXTENSION, "template-config.json"); } @Override public boolean checkConfiguration() throws EngineException { return false; } @Override public TemplateConfiguration readConfiguration(Reader reader) throws NullPointerException, IOException { if(reader == null) throw new NullPointerException("The configuration reader can not be null"); TemplateConfiguration templateConfiguration = new TemplateConfiguration(); final JsonObject configuration = JSONHelper.readFromReader(reader); final JsonObject templateJson = configuration.getJsonObject(TEMPLATE); templateConfiguration.setName(templateJson.getString(TEMPLATE_NAME)); LOGGER.fine("[Template configuration] name = " + templateConfiguration.getName()); templateConfiguration.setFile(new File(getWorkingDirectory(), templateJson.getString(TEMPLATE_FILE))); LOGGER.fine("[Template configuration] file = " + templateConfiguration.getFile().getAbsolutePath()); templateConfiguration.setJsObject(templateJson.getString(JS_OBJECT)); LOGGER.fine("[Template configuration] jsObject = " + templateConfiguration.getJsObject()); templateConfiguration.setSfxServerObject("sfxServer"); LOGGER.fine("[Template configuration] server object = " + templateConfiguration.getSfxServerObject()); templateConfiguration.setResourcesDirectory(new File(getWorkingDirectory(), templateJson.getString(TEMPLATE_RESOURCES_DIRECTORY))); LOGGER.fine("[Template configuration] resources-directory = " + templateConfiguration.getResourcesDirectory().getAbsolutePath()); templateConfiguration.setContentDefinerMethod("slideshowFXSetField"); LOGGER.fine("[Template configuration] content definer method = " + templateConfiguration.getContentDefinerMethod()); templateConfiguration.setGetCurrentSlideMethod("slideshowFXGetCurrentSlide"); LOGGER.fine("[Template configuration] content definer method = " + templateConfiguration.getGetCurrentSlideMethod()); templateConfiguration.setGotoSlideMethod("slideshowFXGotoSlide"); LOGGER.fine("[Template configuration] goto slide method = " + templateConfiguration.getGotoSlideMethod()); templateConfiguration.setUpdateCodeSnippetConsoleMethod("updateCodeSnippetConsole"); LOGGER.fine("[Template configuration] update code snippet console method = " + templateConfiguration.getUpdateCodeSnippetConsoleMethod()); // Settings the default variables templateConfiguration.setDefaultVariables(new HashSet<>()); JsonArray defaultVariablesJson = templateJson.getJsonArray(TEMPLATE_DEFAULT_VARIABLES); if(defaultVariablesJson != null) { LOGGER.fine("Reading default variables"); defaultVariablesJson.forEach(variable -> { final JsonObject variableJson = (JsonObject) variable; templateConfiguration.getDefaultVariables().add( new Pair<>( variableJson.getString(TEMPLATE_DEFAULT_VARIABLE_NAME), new String(Base64.getDecoder().decode(variableJson.getString(TEMPLATE_DEFAULT_VARIABLE_VALUE)), getDefaultCharset()) )); }); } // Setting the slides templateConfiguration.setSlideTemplates(new ArrayList<SlideTemplate>()); JsonObject slidesJson = templateJson.getJsonObject(SLIDES); if (slidesJson != null) { LOGGER.fine("Reading slide's configuration"); JsonObject slidesConfigurationJson = slidesJson.getJsonObject(SLIDES_CONFIGURATION); templateConfiguration.setSlidesTemplateDirectory(new File(this.getWorkingDirectory(), slidesConfigurationJson.getString(SLIDES_TEMPLATE_DIRECTORY))); LOGGER.fine("[Slide's configuration] templateConfiguration directory = " + templateConfiguration.getSlidesTemplateDirectory().getAbsolutePath()); templateConfiguration.setSlidesPresentationDirectory(new File(this.getWorkingDirectory(), slidesConfigurationJson.getString(SLIDES_PRESENTATION_DIRECTORY))); LOGGER.fine("[Slide's configuration] presentation directory = " + templateConfiguration.getSlidesPresentationDirectory().getAbsolutePath()); templateConfiguration.setSlidesThumbnailDirectory(new File(this.getWorkingDirectory(), slidesConfigurationJson.getString(SLIDES_THUMBNAIL_DIRECTORY))); LOGGER.fine("[Slide's configuration] slides thumbnail directory = " + templateConfiguration.getSlidesThumbnailDirectory().getAbsolutePath()); templateConfiguration.setSlideIdPrefix(slidesConfigurationJson.getString(SLIDE_ID_PREFIX)); LOGGER.fine("[Slide's configuration] slideIdPrefix = " + templateConfiguration.getSlideIdPrefix()); templateConfiguration.setSlidesContainer(slidesConfigurationJson.getString(SLIDES_CONTAINER)); LOGGER.fine("[Slide's configuration] slidesContainer = " + templateConfiguration.getSlidesContainer()); slidesJson.getJsonArray(SLIDES_DEFINITION) .forEach(slideJson -> { Number number; final SlideTemplate slideTemplate = new SlideTemplate(); slideTemplate.setId((((number = ((JsonObject) slideJson).getInteger(TemplateConfiguration.SLIDE_ID))) != null) ? number.intValue() : -1); LOGGER.fine("[Slide definition] id = " + slideTemplate.getId()); slideTemplate.setName(((JsonObject) slideJson).getString(SLIDE_NAME)); LOGGER.fine("[Slide definition] name = " + slideTemplate.getName()); slideTemplate.setFile(new File(templateConfiguration.getSlidesTemplateDirectory(), ((JsonObject) slideJson).getString(SLIDE_FILE))); LOGGER.fine("[Slide definition] file = " + slideTemplate.getFile().getAbsolutePath()); /* final JsonArray dynamicIdsJson = ((JsonObject) slideJson).getJsonArray("dynamic-ids"); if (dynamicIdsJson != null && dynamicIdsJson.size() > 0) { slideTemplate.setDynamicIds(new String[dynamicIdsJson.size()]); for (int index = 0; index < dynamicIdsJson.size(); index++) { slideTemplate.getDynamicIds()[index] = dynamicIdsJson.get(index); } }*/ final JsonArray dynamicAttributesJson = ((JsonObject) slideJson).getJsonArray(SLIDE_DYNAMIC_ATTRIBUTES); if (dynamicAttributesJson != null && dynamicAttributesJson.size() > 0) { slideTemplate.setDynamicAttributes(new DynamicAttribute[dynamicAttributesJson.size()]); DynamicAttribute dynamicAttribute; JsonObject dynamicAttributeJson; for (int index = 0; index < dynamicAttributesJson.size(); index++) { dynamicAttribute = new DynamicAttribute(); dynamicAttributeJson = dynamicAttributesJson.getJsonObject(index); dynamicAttribute.setAttribute(dynamicAttributeJson.getString(DYNAMIC_ATTRIBUTE)); dynamicAttribute.setPromptMessage(dynamicAttributeJson.getString(DYNAMIC_ATTRIBUTE_PROMPT_MESSAGE)); dynamicAttribute.setTemplateExpression(dynamicAttributeJson.getString(DYNAMIC_ATTRIBUTE_TEMPLATE_EXPRESSION)); slideTemplate.getDynamicAttributes()[index] = dynamicAttribute; } } final JsonArray elementsJson = ((JsonObject) slideJson).getJsonArray(SLIDE_ELEMENTS); if(elementsJson != null && elementsJson.size() > 0) { slideTemplate.setElements(new SlideElementTemplate[elementsJson.size()]); SlideElementTemplate element; JsonObject elementJson; for (int index = 0; index < elementsJson.size(); index++) { element = new SlideElementTemplate(); elementJson = elementsJson.getJsonObject(index); element.setId(elementJson.getInteger(SLIDE_ELEMENT_ID).intValue()); element.setHtmlId(elementJson.getString(SLIDE_ELEMENT_HTML_ID)); element.setDefaultContent(elementJson.getString(SLIDE_ELEMENT_DEFAULT_CONTENT)); slideTemplate.getElements()[index] = element; } } templateConfiguration.getSlideTemplates().add(slideTemplate); }); } else { LOGGER.fine("No slide's configuration found"); } return templateConfiguration; } @Override public void writeConfiguration(final Writer writer) throws NullPointerException, IOException { if(writer == null) throw new NullPointerException("The configuration to write into can not be null"); if (this.configuration != null) { final JsonObject configurationJson = new JsonObject() .put(TEMPLATE, new JsonObject() .put(TEMPLATE_NAME, this.configuration.getName() == null ? "" : this.configuration.getName()) .put(TEMPLATE_FILE, this.configuration.getFile() == null ? "" : this.relativizeFromWorkingDirectory(this.configuration.getFile())) .put(JS_OBJECT, this.configuration.getJsObject() == null ? "" : this.configuration.getJsObject()) .put(TEMPLATE_RESOURCES_DIRECTORY, this.configuration.getResourcesDirectory() == null ? "" : this.relativizeFromWorkingDirectory(this.configuration.getResourcesDirectory())) .put(TEMPLATE_DEFAULT_VARIABLES, new JsonArray()) .put(SLIDES, new JsonObject() .put(SLIDES_CONFIGURATION, new JsonObject() .put(SLIDES_CONTAINER, this.configuration.getSlidesContainer() == null ? "" : this.configuration.getSlidesContainer()) .put(SLIDE_ID_PREFIX, this.configuration.getSlideIdPrefix() == null ? "" : this.configuration.getSlideIdPrefix()) .put(SLIDES_TEMPLATE_DIRECTORY, this.configuration.getSlidesTemplateDirectory() == null ? "" : this.relativizeFromWorkingDirectory(this.configuration.getSlidesTemplateDirectory())) .put(SLIDES_PRESENTATION_DIRECTORY, this.configuration.getSlidesPresentationDirectory() == null ? "" : this.relativizeFromWorkingDirectory(this.configuration.getSlidesTemplateDirectory())) .put(SLIDES_THUMBNAIL_DIRECTORY, this.configuration.getSlidesThumbnailDirectory() == null ? "" : this.relativizeFromWorkingDirectory(this.configuration.getSlidesThumbnailDirectory()))) .put(SLIDES_DEFINITION, new JsonArray()))); final JsonArray defaultVariablesJson = configurationJson.getJsonObject(TEMPLATE) .getJsonArray(TEMPLATE_DEFAULT_VARIABLES); this.configuration.getDefaultVariables() .forEach(variable -> { defaultVariablesJson.add(new JsonObject() .put(TEMPLATE_DEFAULT_VARIABLE_NAME, variable.getKey()) .put(TEMPLATE_DEFAULT_VARIABLE_VALUE, Base64.getEncoder().encodeToString(variable.getValue().getBytes(getDefaultCharset())))); }); final JsonArray slidesDefinitionJson = configurationJson.getJsonObject(TEMPLATE) .getJsonObject(SLIDES) .getJsonArray(SLIDES_DEFINITION); this.configuration.getSlideTemplates() .forEach(slideTemplate -> { final JsonObject jsonObject = new JsonObject() .put(SLIDE_ID, slideTemplate.getId()) .put(SLIDE_NAME, slideTemplate.getName() == null ? "" : slideTemplate.getName()) .put(SLIDE_FILE, slideTemplate.getFile() == null ? "" : slideTemplate.getFile().getName()) .put(SLIDE_DYNAMIC_IDS, new JsonArray()) .put(SLIDE_DYNAMIC_ATTRIBUTES, new JsonArray()) .put(SLIDE_ELEMENTS, new JsonArray()); /* if(slideTemplate.getDynamicIds() != null && slideTemplate.getDynamicIds().length > 0) { final JsonArray array = jsonObject.getJsonArray("dynamic-ids"); Arrays.stream(slideTemplate.getDynamicIds()) .forEach(id -> array.addString(id)); } */ if(slideTemplate.getDynamicAttributes() != null && slideTemplate.getDynamicAttributes().length > 0) { final JsonArray array = jsonObject.getJsonArray(SLIDE_DYNAMIC_ATTRIBUTES); Arrays.stream(slideTemplate.getDynamicAttributes()) .forEach(attribute -> { array.add(new JsonObject() .put(DYNAMIC_ATTRIBUTE, attribute.getAttribute()) .put(DYNAMIC_ATTRIBUTE_TEMPLATE_EXPRESSION, attribute.getTemplateExpression()) .put(DYNAMIC_ATTRIBUTE_PROMPT_MESSAGE, attribute.getPromptMessage())); }); } if(slideTemplate.getElements() != null && slideTemplate.getElements().length > 0) { final JsonArray array = jsonObject.getJsonArray(SLIDE_ELEMENTS); Arrays.stream(slideTemplate.getElements()) .forEach(element -> { array.add(new JsonObject() .put(SLIDE_ELEMENT_ID, element.getId()) .put(SLIDE_ELEMENT_HTML_ID, element.getHtmlId()) .put(SLIDE_ELEMENT_DEFAULT_CONTENT, element.getDefaultContent())); }); } slidesDefinitionJson.add(jsonObject); }); JSONHelper.writeObject(configurationJson, writer); } } @Override public void loadArchive(File file) throws IllegalArgumentException, NullPointerException, IOException, IllegalAccessException { if(file == null) throw new NullPointerException("The archive file can not be null"); if(!file.exists()) throw new FileNotFoundException("The archive file does not exist"); if(!file.canRead()) throw new IllegalAccessException("The archive file can not be read"); if(!file.getName().endsWith(this.getArchiveExtension())) throw new IllegalArgumentException("The extension of the archive is not valid"); this.setArchive(file); this.setWorkingDirectory(this.generateWorkingDirectory()); ZipUtils.unzip(this.getArchive(), this.getWorkingDirectory()); final TemplateConfiguration configuration = this.readConfiguration(); this.setConfiguration(configuration); } @Override public synchronized void saveArchive(File file) throws IllegalArgumentException, IOException { if(file == null) throw new NullPointerException("The destination archive can not be null"); if(!file.getName().endsWith(this.getArchiveExtension())) throw new IllegalArgumentException("The file does not have the correct extension"); // this.writeConfiguration(); ZipUtils.zip(this.getWorkingDirectory(), file); } }