CCM NG: First part of Theme Utility functions
git-svn-id: https://svn.libreccm.org/ccm/ccm_ng@5210 8810af33-2d31-482b-a856-94f89814c4dfpull/2/head
parent
c48ab80922
commit
c20ddb0934
|
|
@ -202,6 +202,16 @@
|
||||||
<version>0.9.11</version>
|
<version>0.9.11</version>
|
||||||
</dependency>
|
</dependency>
|
||||||
|
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.glassfish</groupId>
|
||||||
|
<artifactId>javax.json</artifactId>
|
||||||
|
</dependency>
|
||||||
|
|
||||||
|
<dependency>
|
||||||
|
<groupId>net.sf.saxon</groupId>
|
||||||
|
<artifactId>Saxon-HE</artifactId>
|
||||||
|
</dependency>
|
||||||
|
|
||||||
<dependency>
|
<dependency>
|
||||||
<groupId>org.primefaces</groupId>
|
<groupId>org.primefaces</groupId>
|
||||||
<artifactId>primefaces</artifactId>
|
<artifactId>primefaces</artifactId>
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,340 @@
|
||||||
|
/*
|
||||||
|
* Copyright (C) 2018 LibreCCM Foundation.
|
||||||
|
*
|
||||||
|
* This library is free software; you can redistribute it and/or
|
||||||
|
* modify it under the terms of the GNU Lesser General Public
|
||||||
|
* License as published by the Free Software Foundation; either
|
||||||
|
* version 2.1 of the License, or (at your option) any later version.
|
||||||
|
*
|
||||||
|
* This library is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||||
|
* Lesser General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU Lesser General Public
|
||||||
|
* License along with this library; if not, write to the Free Software
|
||||||
|
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
|
||||||
|
* MA 02110-1301 USA
|
||||||
|
*/
|
||||||
|
package org.libreccm.theming.utils;
|
||||||
|
|
||||||
|
import com.fasterxml.jackson.databind.ObjectMapper;
|
||||||
|
import com.fasterxml.jackson.dataformat.xml.JacksonXmlModule;
|
||||||
|
import com.fasterxml.jackson.dataformat.xml.XmlMapper;
|
||||||
|
import org.apache.logging.log4j.LogManager;
|
||||||
|
import org.apache.logging.log4j.Logger;
|
||||||
|
import org.libreccm.theming.ThemeInfo;
|
||||||
|
import org.libreccm.theming.ThemeProvider;
|
||||||
|
import org.libreccm.theming.Themes;
|
||||||
|
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.io.InputStream;
|
||||||
|
import java.util.HashMap;
|
||||||
|
import java.util.Locale;
|
||||||
|
import java.util.Map;
|
||||||
|
import java.util.Objects;
|
||||||
|
import java.util.Optional;
|
||||||
|
import java.util.Properties;
|
||||||
|
import java.util.logging.Level;
|
||||||
|
|
||||||
|
import javax.enterprise.context.RequestScoped;
|
||||||
|
import javax.inject.Inject;
|
||||||
|
import javax.json.Json;
|
||||||
|
import javax.json.JsonObject;
|
||||||
|
import javax.json.JsonReader;
|
||||||
|
import javax.xml.stream.XMLInputFactory;
|
||||||
|
import javax.xml.stream.XMLStreamException;
|
||||||
|
import javax.xml.stream.XMLStreamReader;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Methods for reading configuration options from the theme. Most themes have
|
||||||
|
* some configuration options. The class provides several methods for reading
|
||||||
|
* settings from different file formats. The following formats are currently
|
||||||
|
* supported:
|
||||||
|
*
|
||||||
|
* <ul>
|
||||||
|
* <li>Java Properties files</li>
|
||||||
|
* <li>JSON files</li>
|
||||||
|
* <li>XML files</li>
|
||||||
|
* </ul>
|
||||||
|
*
|
||||||
|
* For property files and JSON files it is expected that the name of the setting
|
||||||
|
* is the key. For XML files the following simple format is expected:
|
||||||
|
*
|
||||||
|
* <pre>
|
||||||
|
* <settings>
|
||||||
|
* <setting key="nameOfSetting">value of setting</setting>
|
||||||
|
* <setting key="anotherSetting">value of setting</setting>
|
||||||
|
* ...
|
||||||
|
* </settings/>
|
||||||
|
* </pre>
|
||||||
|
*
|
||||||
|
* The file type is determined by the file extension of the file to read.
|
||||||
|
*
|
||||||
|
* @author <a href="mailto:jens.pelzetter@googlemail.com">Jens Pelzetter</a>
|
||||||
|
*/
|
||||||
|
@RequestScoped
|
||||||
|
public class SettingsUtils {
|
||||||
|
|
||||||
|
private static final Logger LOGGER = LogManager
|
||||||
|
.getLogger(SettingsUtils.class);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Retrieve the value of a setting.
|
||||||
|
*
|
||||||
|
* @param fromTheme The theme from which the setting is read.
|
||||||
|
* @param themeProvider The provider of the the theme.
|
||||||
|
* @param filePath The path of the settings file relative to the root
|
||||||
|
* directory of the theme.
|
||||||
|
* @param settingName The name of the setting.
|
||||||
|
*
|
||||||
|
* @return The value of the setting as String.
|
||||||
|
*/
|
||||||
|
public String getSetting(final ThemeInfo fromTheme,
|
||||||
|
final ThemeProvider themeProvider,
|
||||||
|
final String filePath,
|
||||||
|
final String settingName) {
|
||||||
|
|
||||||
|
return getSetting(fromTheme,
|
||||||
|
themeProvider,
|
||||||
|
filePath,
|
||||||
|
settingName,
|
||||||
|
null);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Retrieve the value of a setting. If the provided file does not have a
|
||||||
|
* value for the setting the provided default value is used.
|
||||||
|
*
|
||||||
|
* @param fromTheme The theme from which the setting is read.
|
||||||
|
* @param themeProvider The provider of the theme.
|
||||||
|
* @param filePath The path of the settings file relative to the root
|
||||||
|
* directory of the theme.
|
||||||
|
* @param settingName The name of the setting.
|
||||||
|
* @param defaultValue The default value for the setting.
|
||||||
|
*
|
||||||
|
* @return The value of the setting as String. If the provided file has no
|
||||||
|
* value for the setting the provided default value is used.
|
||||||
|
*/
|
||||||
|
public String getSetting(final ThemeInfo fromTheme,
|
||||||
|
final ThemeProvider themeProvider,
|
||||||
|
final String filePath,
|
||||||
|
final String settingName,
|
||||||
|
final String defaultValue) {
|
||||||
|
|
||||||
|
Objects.requireNonNull(fromTheme);
|
||||||
|
Objects.requireNonNull(themeProvider);
|
||||||
|
Objects.requireNonNull(filePath);
|
||||||
|
Objects.requireNonNull(settingName);
|
||||||
|
|
||||||
|
if (filePath.isEmpty() || filePath.matches("\\s*")) {
|
||||||
|
throw new IllegalArgumentException(
|
||||||
|
"The path of the settings file can't be empty.");
|
||||||
|
}
|
||||||
|
|
||||||
|
if (settingName.isEmpty() || settingName.matches("\\s*")) {
|
||||||
|
throw new IllegalArgumentException(
|
||||||
|
"The name of the settings file can't be empty.");
|
||||||
|
}
|
||||||
|
|
||||||
|
final Optional<InputStream> fileInputStream = themeProvider
|
||||||
|
.getThemeFileAsStream(fromTheme.getName(),
|
||||||
|
fromTheme.getVersion(),
|
||||||
|
filePath);
|
||||||
|
if (!fileInputStream.isPresent()) {
|
||||||
|
LOGGER.warn(
|
||||||
|
"Configuration file \"{}\" was not found in theme \"{}\".",
|
||||||
|
filePath,
|
||||||
|
fromTheme.getName());
|
||||||
|
return defaultValue;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (filePath.toLowerCase(Locale.ROOT).endsWith(".properties")) {
|
||||||
|
return getSettingFromPropertiesFile(fileInputStream.get(),
|
||||||
|
settingName)
|
||||||
|
.orElse(defaultValue);
|
||||||
|
} else if (filePath.toLowerCase(Locale.ROOT).endsWith(".xml")) {
|
||||||
|
return getSettingFromXmlFile(fileInputStream.get(), settingName)
|
||||||
|
.orElse(defaultValue);
|
||||||
|
} else if (filePath.toLowerCase(Locale.ROOT).endsWith(".json")) {
|
||||||
|
return getSettingFromJsonFile(fileInputStream.get(), settingName)
|
||||||
|
.orElse(defaultValue);
|
||||||
|
} else {
|
||||||
|
throw new IllegalArgumentException(
|
||||||
|
"The file path must point to file in a supported format. "
|
||||||
|
+ "Supported formats are \".properties\", \".xml\" and \".json\".");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Retrieve the boolean value of a setting. This method reads the value of a
|
||||||
|
* setting using null null null null null null null null null null null null
|
||||||
|
* null null null null null null null null null null {@link #getSetting(java.lang.String, java.lang.String, java.lang.String, java.lang.String)
|
||||||
|
* and converts it into a {@code boolean} value using
|
||||||
|
* {@link Boolean#parseBoolean(java.lang.String)}.
|
||||||
|
*
|
||||||
|
* @param fromTheme The name of the theme from which the setting is
|
||||||
|
* read.
|
||||||
|
* @param themeProvider The provider of the theme.
|
||||||
|
* @param filePath The path of the settings file relative to the root
|
||||||
|
* directory of the theme.
|
||||||
|
* @param settingName The name of the setting.
|
||||||
|
* @param defaultValue The default value.
|
||||||
|
*
|
||||||
|
* @return The value of the setting as {@code boolean} or the default value
|
||||||
|
* if the configuration file has no value for the setting.
|
||||||
|
*/
|
||||||
|
public boolean getSettingAsBoolean(final ThemeInfo fromTheme,
|
||||||
|
final ThemeProvider themeProvider,
|
||||||
|
final String filePath,
|
||||||
|
final String settingName,
|
||||||
|
final boolean defaultValue) {
|
||||||
|
|
||||||
|
final String result = getSetting(fromTheme,
|
||||||
|
themeProvider,
|
||||||
|
filePath,
|
||||||
|
settingName,
|
||||||
|
Boolean.toString(defaultValue));
|
||||||
|
return Boolean.parseBoolean(result);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Retrieve the value of setting and convert it to a {@code long} value.
|
||||||
|
* This method reads the value using
|
||||||
|
* {@link #getSetting(java.lang.String, java.lang.String, java.lang.String, java.lang.String)}
|
||||||
|
* and converts the value to a value of type {@code long} using
|
||||||
|
* {@link Long#parseLong(java.lang.String)}.
|
||||||
|
*
|
||||||
|
*
|
||||||
|
* @param fromTheme The name of the theme from which the setting is
|
||||||
|
* read.
|
||||||
|
* @param themeProvider The provider of the theme.
|
||||||
|
* @param filePath The path of the settings file relative to the root
|
||||||
|
* directory of the theme.
|
||||||
|
* @param settingName The name of the setting.
|
||||||
|
* @param defaultValue The default value.
|
||||||
|
*
|
||||||
|
* @return The value of the setting as {@code boolean} or the default value
|
||||||
|
* if the configuration file has no value for the setting.
|
||||||
|
*
|
||||||
|
* @throws NumberFormatException If the the value can't be converted into a
|
||||||
|
* {@code long} value.
|
||||||
|
*/
|
||||||
|
public long getSettingAsLong(final ThemeInfo fromTheme,
|
||||||
|
final ThemeProvider themeProvider,
|
||||||
|
final String filePath,
|
||||||
|
final String settingName,
|
||||||
|
final long defaultValue) {
|
||||||
|
|
||||||
|
final String result = getSetting(fromTheme,
|
||||||
|
themeProvider,
|
||||||
|
filePath,
|
||||||
|
settingName,
|
||||||
|
Long.toString(defaultValue));
|
||||||
|
return Long.parseLong(result);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Retrieve the value of setting and convert it to a {@code double} value.
|
||||||
|
* This method reads the value using
|
||||||
|
* {@link #getSetting(java.lang.String, java.lang.String, java.lang.String, java.lang.String)}
|
||||||
|
* and converts the value to a value of type {@code double} using
|
||||||
|
* {@link Long#parseLong(java.lang.String)}.
|
||||||
|
*
|
||||||
|
*
|
||||||
|
* @param fromTheme The name of the theme from which the setting is
|
||||||
|
* read.
|
||||||
|
* @param themeProvider The provider of the theme.
|
||||||
|
* @param filePath The path of the settings file relative to the root
|
||||||
|
* directory of the theme.
|
||||||
|
* @param settingName The name of the setting.
|
||||||
|
* @param defaultValue The default value.
|
||||||
|
*
|
||||||
|
* @return The value of the setting as {@code boolean} or the default value
|
||||||
|
* if the configuration file has no value for the setting.
|
||||||
|
*
|
||||||
|
* @throws NumberFormatException If the the value can't be converted into a
|
||||||
|
* {@code double} value.
|
||||||
|
*/
|
||||||
|
public double getSettingAsDouble(final ThemeInfo fromTheme,
|
||||||
|
final ThemeProvider themeProvider,
|
||||||
|
final String filePath,
|
||||||
|
final String settingName,
|
||||||
|
final double defaultValue) {
|
||||||
|
|
||||||
|
final String result = getSetting(fromTheme,
|
||||||
|
themeProvider,
|
||||||
|
filePath,
|
||||||
|
settingName,
|
||||||
|
settingName);
|
||||||
|
return Double.parseDouble(result);
|
||||||
|
}
|
||||||
|
|
||||||
|
private Optional<String> getSettingFromJsonFile(
|
||||||
|
final InputStream fileInputStream,
|
||||||
|
final String settingName) {
|
||||||
|
|
||||||
|
final JsonReader jsonReader = Json.createReader(fileInputStream);
|
||||||
|
final JsonObject settings = jsonReader.readObject();
|
||||||
|
final String result = settings.getString(settingName);
|
||||||
|
|
||||||
|
return Optional.ofNullable(result);
|
||||||
|
}
|
||||||
|
|
||||||
|
private Optional<String> getSettingFromPropertiesFile(
|
||||||
|
final InputStream fileInputStream,
|
||||||
|
final String settingName) {
|
||||||
|
|
||||||
|
final Properties settings = new Properties();
|
||||||
|
try {
|
||||||
|
settings.load(fileInputStream);
|
||||||
|
} catch (IOException ex) {
|
||||||
|
LOGGER.warn("Failed to load setting file.");
|
||||||
|
return Optional.empty();
|
||||||
|
}
|
||||||
|
|
||||||
|
if (settings.containsKey(settingName)) {
|
||||||
|
return Optional.of(settings.getProperty(settingName));
|
||||||
|
} else {
|
||||||
|
return Optional.empty();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private Optional<String> getSettingFromXmlFile(
|
||||||
|
final InputStream fileInputStream,
|
||||||
|
final String settingName) {
|
||||||
|
|
||||||
|
final Map<String, String> settings;
|
||||||
|
// = new HashMap<>();
|
||||||
|
// final XMLInputFactory xmlInputFactory = XMLInputFactory.newFactory();
|
||||||
|
// final XMLStreamReader xmlStreamReader;
|
||||||
|
// try {
|
||||||
|
// xmlStreamReader = xmlInputFactory
|
||||||
|
// .createXMLStreamReader(fileInputStream);
|
||||||
|
// } catch (XMLStreamException ex) {
|
||||||
|
// LOGGER.error("Failed to read XML settings file.");
|
||||||
|
// return Optional.empty();
|
||||||
|
// }
|
||||||
|
//
|
||||||
|
// while
|
||||||
|
|
||||||
|
final JacksonXmlModule xmlModule = new JacksonXmlModule();
|
||||||
|
final ObjectMapper mapper = new XmlMapper(xmlModule);
|
||||||
|
try {
|
||||||
|
settings = mapper
|
||||||
|
.reader()
|
||||||
|
.withRootName("settings")
|
||||||
|
.readValue(fileInputStream);
|
||||||
|
} catch (IOException ex) {
|
||||||
|
LOGGER.error("Failed to read Xfinal XML settings file.");
|
||||||
|
return Optional.empty();
|
||||||
|
}
|
||||||
|
|
||||||
|
if (settings.containsKey(settingName)) {
|
||||||
|
return Optional.of(settings.get(settingName));
|
||||||
|
} else {
|
||||||
|
return Optional.empty();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,25 @@
|
||||||
|
/*
|
||||||
|
* Copyright (C) 2018 LibreCCM Foundation.
|
||||||
|
*
|
||||||
|
* This library is free software; you can redistribute it and/or
|
||||||
|
* modify it under the terms of the GNU Lesser General Public
|
||||||
|
* License as published by the Free Software Foundation; either
|
||||||
|
* version 2.1 of the License, or (at your option) any later version.
|
||||||
|
*
|
||||||
|
* This library is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||||
|
* Lesser General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU Lesser General Public
|
||||||
|
* License along with this library; if not, write to the Free Software
|
||||||
|
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
|
||||||
|
* MA 02110-1301 USA
|
||||||
|
*/
|
||||||
|
/**
|
||||||
|
* This package provides several utility methods/functions for themes.
|
||||||
|
* They are implemented as static methods. The implementations of the
|
||||||
|
* {@link org.libreccm.theming.ThemeProcessor} interface are responsible for
|
||||||
|
* making the functions available in the the templates they process.
|
||||||
|
*/
|
||||||
|
package org.libreccm.theming.utils;
|
||||||
|
|
@ -40,10 +40,22 @@ import javax.xml.parsers.ParserConfigurationException;
|
||||||
import static org.libreccm.theming.ThemeConstants.*;
|
import static org.libreccm.theming.ThemeConstants.*;
|
||||||
|
|
||||||
import com.fasterxml.jackson.databind.SerializationFeature;
|
import com.fasterxml.jackson.databind.SerializationFeature;
|
||||||
|
import net.sf.saxon.Configuration;
|
||||||
|
import net.sf.saxon.TransformerFactoryImpl;
|
||||||
|
import net.sf.saxon.expr.XPathContext;
|
||||||
|
import net.sf.saxon.lib.ExtensionFunctionCall;
|
||||||
|
import net.sf.saxon.lib.ExtensionFunctionDefinition;
|
||||||
|
import net.sf.saxon.om.Item;
|
||||||
|
import net.sf.saxon.om.Sequence;
|
||||||
|
import net.sf.saxon.om.StructuredQName;
|
||||||
|
import net.sf.saxon.trans.XPathException;
|
||||||
|
import net.sf.saxon.value.SequenceType;
|
||||||
|
import net.sf.saxon.value.StringValue;
|
||||||
import org.apache.logging.log4j.LogManager;
|
import org.apache.logging.log4j.LogManager;
|
||||||
import org.apache.logging.log4j.Logger;
|
import org.apache.logging.log4j.Logger;
|
||||||
import org.libreccm.theming.ProcessesThemes;
|
import org.libreccm.theming.ProcessesThemes;
|
||||||
import org.libreccm.theming.manifest.ThemeTemplate;
|
import org.libreccm.theming.manifest.ThemeTemplate;
|
||||||
|
import org.libreccm.theming.utils.SettingsUtils;
|
||||||
|
|
||||||
import java.io.ByteArrayInputStream;
|
import java.io.ByteArrayInputStream;
|
||||||
import java.io.InputStream;
|
import java.io.InputStream;
|
||||||
|
|
@ -54,6 +66,7 @@ import java.io.UnsupportedEncodingException;
|
||||||
import java.nio.charset.StandardCharsets;
|
import java.nio.charset.StandardCharsets;
|
||||||
import java.util.Optional;
|
import java.util.Optional;
|
||||||
|
|
||||||
|
import javax.inject.Inject;
|
||||||
import javax.xml.transform.ErrorListener;
|
import javax.xml.transform.ErrorListener;
|
||||||
import javax.xml.transform.Result;
|
import javax.xml.transform.Result;
|
||||||
import javax.xml.transform.Transformer;
|
import javax.xml.transform.Transformer;
|
||||||
|
|
@ -78,6 +91,9 @@ public class XsltThemeProcessor implements ThemeProcessor {
|
||||||
private static final Logger LOGGER = LogManager
|
private static final Logger LOGGER = LogManager
|
||||||
.getLogger(XsltThemeProcessor.class);
|
.getLogger(XsltThemeProcessor.class);
|
||||||
|
|
||||||
|
@Inject
|
||||||
|
private SettingsUtils settingsUtils;
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public String process(final Map<String, Object> page,
|
public String process(final Map<String, Object> page,
|
||||||
final ThemeInfo theme,
|
final ThemeInfo theme,
|
||||||
|
|
@ -160,7 +176,16 @@ public class XsltThemeProcessor implements ThemeProcessor {
|
||||||
|
|
||||||
final StreamSource xslFileStreamSource = new StreamSource(reader);
|
final StreamSource xslFileStreamSource = new StreamSource(reader);
|
||||||
final TransformerFactory transformerFactory = TransformerFactory
|
final TransformerFactory transformerFactory = TransformerFactory
|
||||||
.newInstance();
|
.newInstance(TransformerFactoryImpl.class.getName(),
|
||||||
|
getClass().getClassLoader());
|
||||||
|
final TransformerFactoryImpl transformerFactoryImpl
|
||||||
|
= (TransformerFactoryImpl) transformerFactory;
|
||||||
|
final Configuration configuration = transformerFactoryImpl
|
||||||
|
.getConfiguration();
|
||||||
|
configuration.registerExtensionFunction(new Greeter());
|
||||||
|
configuration
|
||||||
|
.registerExtensionFunction(
|
||||||
|
new GetSettingFunctionDefinition(theme, themeProvider));
|
||||||
final Transformer transformer;
|
final Transformer transformer;
|
||||||
try {
|
try {
|
||||||
transformer = transformerFactory.newTransformer(xslFileStreamSource);
|
transformer = transformerFactory.newTransformer(xslFileStreamSource);
|
||||||
|
|
@ -212,4 +237,126 @@ public class XsltThemeProcessor implements ThemeProcessor {
|
||||||
return resultWriter.toString();
|
return resultWriter.toString();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private class GetSettingFunctionDefinition extends ExtensionFunctionDefinition {
|
||||||
|
|
||||||
|
private final ThemeInfo theme;
|
||||||
|
private final ThemeProvider themeProvider;
|
||||||
|
|
||||||
|
public GetSettingFunctionDefinition(final ThemeInfo themeInfo,
|
||||||
|
final ThemeProvider themeProvider) {
|
||||||
|
this.theme = themeInfo;
|
||||||
|
this.themeProvider = themeProvider;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public StructuredQName getFunctionQName() {
|
||||||
|
return new StructuredQName("ccm",
|
||||||
|
"http://xmlns.libreccm.org",
|
||||||
|
"getSetting");
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public SequenceType[] getArgumentTypes() {
|
||||||
|
return new SequenceType[]{SequenceType.SINGLE_STRING,
|
||||||
|
SequenceType.SINGLE_STRING,
|
||||||
|
SequenceType.SINGLE_STRING};
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int getMinimumNumberOfArguments() {
|
||||||
|
return 2;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int getMaximumNumberOfArguments() {
|
||||||
|
return 3;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public SequenceType getResultType(final SequenceType[] sts) {
|
||||||
|
return SequenceType.SINGLE_STRING;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public ExtensionFunctionCall makeCallExpression() {
|
||||||
|
|
||||||
|
return new ExtensionFunctionCall() {
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Sequence call(final XPathContext xPathContext,
|
||||||
|
final Sequence[] arguments)
|
||||||
|
throws XPathException {
|
||||||
|
|
||||||
|
final String result;
|
||||||
|
final String filePath = ((Item) arguments[0])
|
||||||
|
.getStringValue();
|
||||||
|
final String settingName = ((Item) arguments[1])
|
||||||
|
.getStringValue();
|
||||||
|
switch (arguments.length) {
|
||||||
|
case 2:
|
||||||
|
result = settingsUtils.getSetting(theme,
|
||||||
|
themeProvider,
|
||||||
|
filePath,
|
||||||
|
settingName);
|
||||||
|
break;
|
||||||
|
case 3:
|
||||||
|
final String defaultValue = ((Item) arguments[2])
|
||||||
|
.getStringValue();
|
||||||
|
result = settingsUtils.getSetting(theme,
|
||||||
|
themeProvider,
|
||||||
|
filePath,
|
||||||
|
settingName,
|
||||||
|
defaultValue);
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
throw new UnexpectedErrorException(
|
||||||
|
"Illegal number of arguments.");
|
||||||
|
}
|
||||||
|
|
||||||
|
return StringValue.makeStringValue(result);
|
||||||
|
}
|
||||||
|
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
private class Greeter extends ExtensionFunctionDefinition {
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public StructuredQName getFunctionQName() {
|
||||||
|
return new StructuredQName("ccm",
|
||||||
|
"http://xmlns.libreccm.org",
|
||||||
|
"greet");
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public SequenceType[] getArgumentTypes() {
|
||||||
|
return new SequenceType[]{SequenceType.SINGLE_STRING};
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public SequenceType getResultType(final SequenceType[] sts) {
|
||||||
|
return SequenceType.SINGLE_STRING;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public ExtensionFunctionCall makeCallExpression() {
|
||||||
|
return new ExtensionFunctionCall() {
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Sequence call(final XPathContext xPathContext,
|
||||||
|
final Sequence[] arguments)
|
||||||
|
throws XPathException {
|
||||||
|
|
||||||
|
final String name = arguments[0].toString();
|
||||||
|
return StringValue
|
||||||
|
.makeStringValue(String.format("Hello %s.", name));
|
||||||
|
}
|
||||||
|
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -26,6 +26,23 @@
|
||||||
</p>
|
</p>
|
||||||
<xsl:value-of disable-output-escaping="true" select="./text" />
|
<xsl:value-of disable-output-escaping="true" select="./text" />
|
||||||
|
|
||||||
|
<h2>Example of Saxon Extension Function</h2>
|
||||||
|
<pre>
|
||||||
|
<xsl:value-of select="ccm:greet('John')" />
|
||||||
|
</pre>
|
||||||
|
|
||||||
|
<h2>Example of Theme Utils</h2>
|
||||||
|
<dl>
|
||||||
|
<dt>
|
||||||
|
<code>getSetting</code>
|
||||||
|
</dt>
|
||||||
|
<dd>
|
||||||
|
<code>
|
||||||
|
<xsl:value-of select="ccm:getSetting('settings.properties', 'example.setting', 'n/a')" />
|
||||||
|
</code>
|
||||||
|
</dd>
|
||||||
|
</dl>
|
||||||
|
|
||||||
</xsl:template>
|
</xsl:template>
|
||||||
|
|
||||||
</xsl:stylesheet>
|
</xsl:stylesheet>
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1 @@
|
||||||
|
example.setting=Properties from the theme.
|
||||||
6
pom.xml
6
pom.xml
|
|
@ -548,6 +548,12 @@
|
||||||
</dependency>
|
</dependency>
|
||||||
<!-- Apache Commons libraries end -->
|
<!-- Apache Commons libraries end -->
|
||||||
|
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.glassfish</groupId>
|
||||||
|
<artifactId>javax.json</artifactId>
|
||||||
|
<version>1.1.2</version>
|
||||||
|
</dependency>
|
||||||
|
|
||||||
<dependency>
|
<dependency>
|
||||||
<groupId>net.sf.saxon</groupId>
|
<groupId>net.sf.saxon</groupId>
|
||||||
<artifactId>Saxon-HE</artifactId>
|
<artifactId>Saxon-HE</artifactId>
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue