1 package org.daisy.pipeline.braille.css.saxon.impl;
2
3 import java.util.ArrayList;
4 import java.util.List;
5
6 import javax.xml.namespace.QName;
7
8 import net.sf.saxon.expr.XPathContext;
9 import net.sf.saxon.lib.ExtensionFunctionCall;
10 import net.sf.saxon.lib.ExtensionFunctionDefinition;
11 import net.sf.saxon.om.Item;
12 import net.sf.saxon.om.NodeInfo;
13 import net.sf.saxon.om.Sequence;
14 import net.sf.saxon.om.StructuredQName;
15 import net.sf.saxon.s9api.XdmNode;
16 import net.sf.saxon.trans.XPathException;
17 import net.sf.saxon.value.BooleanValue;
18 import net.sf.saxon.value.EmptySequence;
19 import net.sf.saxon.value.QNameValue;
20 import net.sf.saxon.value.SequenceExtent;
21 import net.sf.saxon.value.SequenceType;
22
23 import org.daisy.braille.css.BrailleCSSParserFactory.Context;
24 import org.daisy.braille.css.InlineStyle;
25 import org.daisy.common.saxon.SaxonOutputValue;
26 import org.daisy.pipeline.braille.css.impl.BrailleCssSerializer;
27 import org.daisy.pipeline.braille.css.impl.BrailleCssTreeBuilder.Style;
28
29 import org.osgi.service.component.annotations.Component;
30
31 import org.slf4j.Logger;
32 import org.slf4j.LoggerFactory;
33
34 @Component(
35 name = "css:parse-stylesheet",
36 service = { ExtensionFunctionDefinition.class }
37 )
38 public class ParseStylesheetDefinition extends ExtensionFunctionDefinition {
39
40 private static final String XMLNS_CSS = "http://www.daisy.org/ns/pipeline/braille-css";
41
42 private static final StructuredQName funcname = new StructuredQName("css", XMLNS_CSS, "parse-stylesheet");
43
44 private static final QName PAGE = new QName("page");
45 private static final QName VOLUME = new QName("volume");
46 private static final QName HYPHENATION_RESOURCE = new QName("hyphenation-resource");
47 private static final QName VENDOR_RULE = new QName("vendor-rule");
48
49 public StructuredQName getFunctionQName() {
50 return funcname;
51 }
52
53 @Override
54 public int getMinimumNumberOfArguments() {
55 return 1;
56 }
57
58 @Override
59 public int getMaximumNumberOfArguments() {
60 return 3;
61 }
62
63 public SequenceType[] getArgumentTypes() {
64 return new SequenceType[] {
65 SequenceType.OPTIONAL_STRING,
66 SequenceType.SINGLE_BOOLEAN,
67 SequenceType.OPTIONAL_QNAME,
68 };
69 }
70
71 public SequenceType getResultType(SequenceType[] suppliedArgumentTypes) {
72 return SequenceType.NODE_SEQUENCE;
73 }
74
75 public ExtensionFunctionCall makeCallExpression() {
76 return new ExtensionFunctionCall() {
77 public Sequence call(XPathContext context, Sequence[] arguments) throws XPathException {
78 if (arguments.length == 0)
79 return EmptySequence.getInstance();
80 Item arg = arguments[0].head();
81 if (arg == null)
82 return EmptySequence.getInstance();
83 boolean deep = arguments.length > 1
84 ? ((BooleanValue)arguments[1]).getBooleanValue()
85 : false;
86 Context styleCtxt = Context.ELEMENT; {
87 if (arguments.length > 2) {
88 Item i = arguments[2].head();
89 if (i != null) {
90 QName qn = ((QNameValue)i).toJaxpQName();
91 if (qn.equals(PAGE))
92 styleCtxt = Context.PAGE;
93 else if (qn.equals(VOLUME))
94 styleCtxt = Context.VOLUME;
95 else if (qn.equals(HYPHENATION_RESOURCE))
96 styleCtxt = Context.HYPHENATION_RESOURCE;
97 else if (qn.equals(VENDOR_RULE))
98 styleCtxt = Context.VENDOR_RULE;
99 else
100 throw new RuntimeException(); }}}
101 List<NodeInfo> result = new ArrayList<>();
102 try {
103 Style style = Style.of(new InlineStyle(arg.getStringValue(), styleCtxt));
104 BrailleCssSerializer.toXml(
105 style,
106 new SaxonOutputValue(
107 item -> {
108 if (item instanceof XdmNode)
109 result.add(((XdmNode)item).getUnderlyingNode());
110 else
111 throw new RuntimeException();
112 },
113 context.getConfiguration()
114 ).asXMLStreamWriter(),
115 deep);
116 } catch (Exception e) {
117 logger.error("Error happened while parsing " + arg, e);
118 }
119 return new SequenceExtent(result);
120 }
121 };
122 }
123
124 private static final Logger logger = LoggerFactory.getLogger(ParseStylesheetDefinition.class);
125
126 }