Skip to content

Commit

Permalink
Manually apply PR #186, extensible system property function
Browse files Browse the repository at this point in the history
  • Loading branch information
ndw committed Mar 4, 2018
1 parent 24319e6 commit 1679da3
Show file tree
Hide file tree
Showing 3 changed files with 189 additions and 101 deletions.
45 changes: 45 additions & 0 deletions src/main/java/com/xmlcalabash/core/XProcRuntime.java
Original file line number Diff line number Diff line change
Expand Up @@ -56,6 +56,7 @@
import com.xmlcalabash.util.StepErrorListener;
import com.xmlcalabash.util.TreeWriter;
import com.xmlcalabash.util.URIUtils;
import com.xmlcalabash.util.XProcSystemPropertySet;
import com.xmlcalabash.util.XProcURIResolver;
import net.sf.saxon.Configuration;
import net.sf.saxon.lib.ExtensionFunctionDefinition;
Expand Down Expand Up @@ -146,6 +147,7 @@ public class XProcRuntime {
private XProcConfigurer configurer = null;
private String htmlParser = null;
private Vector<XProcExtensionFunctionDefinition> exFuncs = new Vector<XProcExtensionFunctionDefinition>();
private Vector<XProcSystemPropertySet> systemPropertySets = new Vector<XProcSystemPropertySet>();

private Output profile = null;
private Hashtable<XStep,Calendar> profileHash = null;
Expand Down Expand Up @@ -266,6 +268,7 @@ else if (def instanceof ExtensionFunction)
}

htmlParser = config.htmlParser;
addSystemPropertySet(XProcSystemPropertySet.BUILTIN);

reset();

Expand Down Expand Up @@ -1108,4 +1111,46 @@ public void finish(XStep step) {
}
}
}

/**
* Registers an {@code XProcSystemPropertySet}.
* It will be consulted whenever the
* <a href="http://www.w3.org/TR/xproc/#f.system-property">{@code p:system-property}</a> function is evaluated.
*
* <p>The {@linkplain com.xmlcalabash.util.XProcSystemPropertySet#BUILTIN built-in}
* {@code XProcSystemPropertySet} is added automatically.
* Other property sets may be added with this method by applications using XML Calabash.</p>
*
* @see #getSystemProperty
* @param systemPropertySet The set of values to add.
*/
public void addSystemPropertySet(XProcSystemPropertySet systemPropertySet) {
systemPropertySets.add(systemPropertySet);
}

/**
* Looks up a <a href="http://www.w3.org/TR/xproc/#f.system-property">system property</a> by the given name.
* If no such system property is found, this method returns {@code null}.
*
* <p>This method consults {@linkplain com.xmlcalabash.util.XProcSystemPropertySet#BUILTIN the built-in}
* {@link com.xmlcalabash.util.XProcSystemPropertySet}, and any other
* {@code XProcSystemPropertySet}s that have been {@linkplain #addSystemPropertySet registered}.</p>
*
* @see #addSystemPropertySet
* @see com.xmlcalabash.util.XProcSystemPropertySet#systemProperty
* @param propertyName the name of the system property to look up
* @return the string value of that system property, or {@code null}
* @throws XProcException if any error occurs
*/
public String getSystemProperty(QName propertyName) throws XProcException {
synchronized (systemPropertySets) {
for (XProcSystemPropertySet propSet : systemPropertySets) {
String value = propSet.systemProperty(this, propertyName);
if (value != null)
return value;
}
}

return null;
}
}
163 changes: 62 additions & 101 deletions src/main/java/com/xmlcalabash/functions/SystemProperty.java
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@
import net.sf.saxon.om.Sequence;
import net.sf.saxon.om.SequenceIterator;
import net.sf.saxon.om.StructuredQName;
import net.sf.saxon.s9api.QName;
import net.sf.saxon.trans.XPathException;
import net.sf.saxon.tree.iter.SingletonIterator;
import net.sf.saxon.value.StringValue;
Expand All @@ -25,37 +26,37 @@
public class SystemProperty extends XProcExtensionFunctionDefinition {
private static StructuredQName funcname = new StructuredQName("p", XProcConstants.NS_XPROC, "system-property");

protected SystemProperty() {
// you can't call this one
}
protected SystemProperty() {
// you can't call this one
}

public SystemProperty(XProcRuntime runtime) {
registry.registerRuntime(this, runtime);
}
public SystemProperty(XProcRuntime runtime) {
registry.registerRuntime(this, runtime);
}

public StructuredQName getFunctionQName() {
return funcname;
}
public StructuredQName getFunctionQName() {
return funcname;
}

public int getMinimumNumberOfArguments() {
return 1;
}
public int getMinimumNumberOfArguments() {
return 1;
}

public int getMaximumNumberOfArguments() {
return 1;
}
public int getMaximumNumberOfArguments() {
return 1;
}

public SequenceType[] getArgumentTypes() {
return new SequenceType[]{SequenceType.SINGLE_STRING};
}
public SequenceType[] getArgumentTypes() {
return new SequenceType[]{SequenceType.SINGLE_STRING};
}

public SequenceType getResultType(SequenceType[] suppliedArgumentTypes) {
return SequenceType.SINGLE_STRING;
}
public SequenceType getResultType(SequenceType[] suppliedArgumentTypes) {
return SequenceType.SINGLE_STRING;
}

public ExtensionFunctionCall makeCallExpression() {
return new SystemPropertyCall(this);
}
public ExtensionFunctionCall makeCallExpression() {
return new SystemPropertyCall(this);
}

private class SystemPropertyCall extends ExtensionFunctionCall {
private StaticContext staticContext = null;
Expand All @@ -65,85 +66,45 @@ public SystemPropertyCall(XProcExtensionFunctionDefinition def) {
xdef = def;
}

public void supplyStaticContext(StaticContext context, int locationId, Expression[] arguments) throws XPathException {
staticContext = context;
}
public void supplyStaticContext(StaticContext context, int locationId, Expression[] arguments) throws XPathException {
staticContext = context;
}

public Sequence call(XPathContext xPathContext, Sequence[] sequences) throws XPathException {
StructuredQName propertyName = null;

XProcRuntime runtime = registry.getRuntime(xdef);
XStep step = runtime.getXProcData().getStep();
// FIXME: this can't be the best way to do this...
// FIXME: And what, exactly, is this even supposed to be doing!?
if (step != null && !(step instanceof XCompoundStep)) {
throw XProcException.dynamicError(23);
}

try {
String lexicalQName = sequences[0].head().getStringValue();
propertyName = StructuredQName.fromLexicalQName(
lexicalQName,
false,
false,
staticContext.getNamespaceResolver());
} catch (XPathException e) {
if (e.getErrorCodeLocalPart()==null || e.getErrorCodeLocalPart().equals("FOCA0002")
|| e.getErrorCodeLocalPart().equals("FONS0004")) {
e.setErrorCode("XTDE1390");
}
throw e;
}

String uri = propertyName.getURI();
String local = propertyName.getLocalPart();
String value = "";

if (uri.equals(XProcConstants.NS_XPROC)) {
if ("episode".equals(local)) {
value = runtime.getEpisode();
} else if ("language".equals(local)) {
value = runtime.getLanguage();
} else if ("product-name".equals(local)) {
value = runtime.getProductName();
} else if ("product-version".equals(local)) {
value = runtime.getProductVersion();
} else if ("vendor".equals(local)) {
value = runtime.getVendor();
} else if ("vendor-uri".equals(local)) {
value = runtime.getVendorURI();
} else if ("version".equals(local)) {
value = runtime.getXProcVersion();
} else if ("xpath-version".equals(local)) {
value = runtime.getXPathVersion();
} else if ("psvi-supported".equals(local)) {
value = runtime.getPSVISupported() ? "true" : "false";
}
} else if (uri.equals(XProcConstants.NS_CALABASH_EX)) {
if ("transparent-json".equals(local)) {
value = runtime.transparentJSON() ? "true" : "false";
} else if ("json-flavor".equals(local)) {
value = runtime.jsonFlavor();
} else if ("general-values".equals(local)) {
value = runtime.getAllowGeneralExpressions() ? "true" : "false";
} else if ("allow-text-results".equals(local)) {
value = runtime.getAllowTextResults() ? "true" : "false";
} else if ("xpointer-on-text".equals(local)) {
value = runtime.getAllowXPointerOnText() ? "true" : "false";
} else if ("use-xslt-1.0".equals(local) || "use-xslt-10".equals(local)) {
value = runtime.getUseXslt10Processor() ? "true" : "false";
} else if ("html-serializer".equals(local)) {
value = runtime.getHtmlSerializer() ? "true" : "false";
} else if ("saxon-version".equals(local)) {
value = runtime.getConfiguration().getProcessor().getSaxonProductVersion();
} else if ("saxon-edition".equals(local)) {
value = runtime.getConfiguration().saxonProcessor;
}
}

return new StringValue(value);
}
}
QName propertyName = null;

XProcRuntime runtime = registry.getRuntime(xdef);
XStep step = runtime.getXProcData().getStep();
// FIXME: this can't be the best way to do this...
// FIXME: And what, exactly, is this even supposed to be doing!?
if (step != null && !(step instanceof XCompoundStep)) {
throw XProcException.dynamicError(23);
}

try {
String lexicalQName = sequences[0].head().getStringValue();
StructuredQName qpropertyName = StructuredQName.fromLexicalQName(
lexicalQName,
false,
false,
staticContext.getNamespaceResolver());
propertyName = new QName(qpropertyName);
} catch (XPathException e) {
if (e.getErrorCodeLocalPart()==null || e.getErrorCodeLocalPart().equals("FOCA0002")
|| e.getErrorCodeLocalPart().equals("FONS0004")) {
e.setErrorCode("XTDE1390");
}
throw e;
}

String value = runtime.getSystemProperty(propertyName);
if (value == null) {
value = "";
}

return new StringValue(value);
}
}
}

//
Expand Down
82 changes: 82 additions & 0 deletions src/main/java/com/xmlcalabash/util/XProcSystemPropertySet.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,82 @@
package com.xmlcalabash.util;

import com.xmlcalabash.core.XProcConstants;
import com.xmlcalabash.core.XProcException;
import com.xmlcalabash.core.XProcRuntime;
import net.sf.saxon.s9api.QName;

/**
* Used to resolve XProc <a href="http://www.w3.org/TR/xproc/#f.system-property">system properties</a>.
* One of these is built into XML Calabash, but more can be added by applications using it.
* See PR #186
*/
public interface XProcSystemPropertySet {
/**
* Looks up a <a href="http://www.w3.org/TR/xproc/#f.system-property">system property</a> by the given name.
* If this {@code XProcSystemPropertySet} does not have any such system property, this method returns {@code null}.
*
* @param runtime the XProc runtime in which the call was made
* @param propertyName the name of the system property to look up
* @return the string value of that system property, or {@code null}
* @throws XProcException if any error occurs
*/
String systemProperty(XProcRuntime runtime, QName propertyName) throws XProcException;

/**
* The built-in system property set. It will answer the system properties <a href="http://www.w3.org/TR/xproc/#f.system-property">listed in the XProc specification</a>, and a number of system properties specific to XML Calabash.
*/
XProcSystemPropertySet BUILTIN = new XProcSystemPropertySet() {
@Override
public String systemProperty(XProcRuntime runtime, QName propertyName) throws XProcException {
String uri = propertyName.getNamespaceURI();
String local = propertyName.getLocalName();

if (uri.equals(XProcConstants.NS_XPROC)) {
if ("episode".equals(local)) {
return runtime.getEpisode();
} else if ("language".equals(local)) {
return runtime.getLanguage();
} else if ("product-name".equals(local)) {
return runtime.getProductName();
} else if ("product-version".equals(local)) {
return runtime.getProductVersion();
} else if ("vendor".equals(local)) {
return runtime.getVendor();
} else if ("vendor-uri".equals(local)) {
return runtime.getVendorURI();
} else if ("version".equals(local)) {
return runtime.getXProcVersion();
} else if ("xpath-version".equals(local)) {
return runtime.getXPathVersion();
} else if ("psvi-supported".equals(local)) {
return runtime.getPSVISupported() ? "true" : "false";
} else {
return null;
}
} else if (uri.equals(XProcConstants.NS_CALABASH_EX)) {
if ("transparent-json".equals(local)) {
return runtime.transparentJSON() ? "true" : "false";
} else if ("json-flavor".equals(local)) {
return runtime.jsonFlavor();
} else if ("general-values".equals(local)) {
return runtime.getAllowGeneralExpressions() ? "true" : "false";
} else if ("xpointer-on-text".equals(local)) {
return runtime.getAllowXPointerOnText() ? "true" : "false";
} else if ("use-xslt-1.0".equals(local) || "use-xslt-10".equals(local)) {
return runtime.getUseXslt10Processor() ? "true" : "false";
} else if ("html-serializer".equals(local)) {
return runtime.getHtmlSerializer() ? "true" : "false";
} else if ("saxon-version".equals(local)) {
return runtime.getConfiguration().getProcessor().getSaxonProductVersion();
} else if ("saxon-edition".equals(local)) {
return runtime.getConfiguration().saxonProcessor;
} else {
return null;
}
} else {
return null;
}
}
};
}

0 comments on commit 1679da3

Please sign in to comment.