blob: bef2ca50a0624c28589bbd4c73942749120c1b4f [file] [log] [blame]
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. The ASF licenses this file to You
* under the Apache License, Version 2.0 (the "License"); you may not
* use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License. For additional information regarding
* copyright in this work, please see the NOTICE file in the top level
* directory of this distribution.
*/
package org.apache.roller.weblogger.business.themes;
import org.apache.commons.lang3.StringUtils;
import org.apache.roller.weblogger.pojos.TemplateRendition.RenditionType;
import org.apache.roller.weblogger.pojos.TemplateRendition.TemplateLanguage;
import org.apache.roller.weblogger.pojos.ThemeTemplate.ComponentType;
import org.jdom2.Document;
import org.jdom2.Element;
import org.jdom2.JDOMException;
import org.jdom2.input.SAXBuilder;
import java.io.IOException;
import java.io.InputStream;
import java.util.List;
/**
* The parser for theme xml descriptors.
*
* This class unmarshalls a theme descriptor into a set of objects.
*/
public class ThemeMetadataParser {
/**
* Unmarshall the given input stream into our defined
* set of Java objects.
**/
public ThemeMetadata unmarshall(InputStream instream)
throws ThemeParsingException, IOException, JDOMException {
if(instream == null) {
throw new IOException("InputStream is null!");
}
ThemeMetadata theme = new ThemeMetadata();
SAXBuilder builder = new SAXBuilder();
Document doc = builder.build(instream);
// start at root and get theme id, name, description and author
Element root = doc.getRootElement();
theme.setId(root.getChildText("id"));
theme.setName(root.getChildText("name"));
theme.setDescription(root.getChildText("description"));
theme.setAuthor(root.getChildText("author"));
// dual-theme (standard & mobile) or one-theme-fits-all?
theme.setDualTheme("true".equalsIgnoreCase(root.getChildText("dualTheme")));
// if either id or name is null then throw a parsing exception
if(StringUtils.isEmpty(theme.getId()) || StringUtils.isEmpty(theme.getName())) {
throw new ThemeParsingException("'id' and 'name' are required theme elements");
}
// now grab the preview image path
Element previewImage = root.getChild("preview-image");
if (previewImage != null) {
theme.setPreviewImage(previewImage.getAttributeValue("path"));
} else {
throw new ThemeParsingException("No preview image specified");
}
// grab the stylesheet if it exists
Element stylesheet = root.getChild("stylesheet");
if (stylesheet != null) {
theme.setStylesheet(elementToStylesheet(stylesheet));
}
// now grab the static resources
List<Element> resources = root.getChildren("resource");
for (Element resource : resources) {
theme.addResource(resource.getAttributeValue("path"));
}
// now grab the templates
boolean weblogActionTemplate = false;
List<Element> templates = root.getChildren("template");
for (Element template : templates) {
ThemeMetadataTemplate tmpl = elementToTemplateMetadata(template);
theme.addTemplate(tmpl);
if(ComponentType.WEBLOG.equals(tmpl.getAction())) {
weblogActionTemplate = true;
}
}
// make sure all required elements are present and values are valid
// check that there is a template with action='weblog'
if(!weblogActionTemplate) {
throw new ThemeParsingException("did not find a template of action = 'weblog'");
}
return theme;
}
private ThemeMetadataTemplate elementToTemplateMetadata(Element element)
throws ThemeParsingException {
ThemeMetadataTemplate template = new ThemeMetadataTemplate();
template.setName(element.getChildText("name"));
template.setDescription(element.getChildText("description"));
template.setLink(element.getChildText("link"));
template.setContentType(element.getChildText("contentType"));
String actionString = element.getAttributeValue("action");
if (StringUtils.isEmpty(actionString)) {
throw new ThemeParsingException("Template must contain an 'action' element");
} else {
try {
template.setAction(ComponentType.valueOf(actionString.toUpperCase()));
} catch (IllegalArgumentException e) {
throw new ThemeParsingException("Unknown template action value '" + actionString + "'");
}
}
//parsing template code segment
List<Element> renditionList = element.getChildren("rendition");
for (Element renditionElement : renditionList) {
ThemeMetadataTemplateRendition rendition = new ThemeMetadataTemplateRendition();
String renditionValue = renditionElement.getAttributeValue("type");
if (renditionValue != null) {
try {
rendition.setType(RenditionType.valueOf(renditionValue.toUpperCase()));
} catch (IllegalArgumentException e) {
throw new ThemeParsingException("Invalid rendition type " + renditionValue + " found.");
}
} else {
// default to standard if type not provided, as most templates are single-rendition
rendition.setType(RenditionType.STANDARD);
}
String templateString = renditionElement.getChildText("templateLanguage");
if (StringUtils.isEmpty(templateString)) {
throw new ThemeParsingException("rendition must contain a 'templateLanguage' element");
} else {
try {
rendition.setTemplateLang(TemplateLanguage.valueOf(templateString.toUpperCase()));
} catch (IllegalArgumentException e) {
throw new ThemeParsingException("Unknown templateLanguage value '" + templateString + "'");
}
}
rendition.setContentsFile(renditionElement.getChildText("contentsFile"));
if (StringUtils.isEmpty(rendition.getContentsFile())) {
throw new ThemeParsingException("Rendition must contain a 'contentsFile' element");
}
template.addTemplateRendition(rendition);
}
String navbar = element.getChildText("navbar");
if ("true".equalsIgnoreCase(navbar)) {
template.setNavbar(true);
}
String hidden = element.getChildText("hidden");
if ("true".equalsIgnoreCase(hidden)) {
template.setHidden(true);
}
// validate template
if (StringUtils.isEmpty(template.getName())) {
throw new ThemeParsingException("templates must contain a 'name' element");
}
return template;
}
private ThemeMetadataTemplate elementToStylesheet(Element element)
throws ThemeParsingException {
ThemeMetadataTemplate template = new ThemeMetadataTemplate();
template.setName(element.getChildText("name"));
template.setDescription(element.getChildText("description"));
template.setLink(element.getChildText("link"));
template.setContentType(element.getChildText("contentType"));
template.setAction(ComponentType.STYLESHEET);
// parsing rendition segment
List<Element> renditionList = element.getChildren("rendition");
for (Element renditionElement : renditionList) {
ThemeMetadataTemplateRendition rendition = new ThemeMetadataTemplateRendition();
String renditionValue = renditionElement.getAttributeValue("type");
if (renditionValue != null) {
try {
rendition.setType(RenditionType.valueOf(renditionValue.toUpperCase()));
} catch (IllegalArgumentException e) {
throw new ThemeParsingException("Invalid rendition type " + renditionValue + " found.");
}
} else {
// default to standard if type not provided, as most templates are single-rendition
rendition.setType(RenditionType.STANDARD);
}
String templateString = renditionElement.getChildText("templateLanguage");
if (StringUtils.isEmpty(templateString)) {
throw new ThemeParsingException("rendition must contain a 'templateLanguage' element");
} else {
try {
rendition.setTemplateLang(TemplateLanguage.valueOf(templateString.toUpperCase()));
} catch (IllegalArgumentException e) {
throw new ThemeParsingException("Unknown templateLanguage value '" + templateString + "'");
}
}
rendition.setContentsFile(renditionElement.getChildText("contentsFile"));
if (StringUtils.isEmpty(rendition.getContentsFile())) {
throw new ThemeParsingException("stylesheet must contain a 'contentsFile' element");
}
template.addTemplateRendition(rendition);
}
// validate template
if(StringUtils.isEmpty(template.getName())) {
throw new ThemeParsingException("stylesheet must contain a 'name' element");
}
if(StringUtils.isEmpty(template.getLink())) {
throw new ThemeParsingException("stylesheet must contain a 'link' element");
}
return template;
}
}