1   package org.daisy.pipeline.file.saxon.impl;
2   
3   import java.net.URI;
4   import java.net.URISyntaxException;
5   
6   import net.sf.saxon.expr.XPathContext;
7   import net.sf.saxon.lib.ExtensionFunctionCall;
8   import net.sf.saxon.lib.ExtensionFunctionDefinition;
9   import net.sf.saxon.om.Item;
10  import net.sf.saxon.om.Sequence;
11  import net.sf.saxon.om.StructuredQName;
12  import net.sf.saxon.trans.XPathException;
13  import net.sf.saxon.type.BuiltInAtomicType;
14  import net.sf.saxon.value.BooleanValue;
15  import net.sf.saxon.value.SequenceType;
16  import net.sf.saxon.value.StringValue;
17  
18  import static org.daisy.pipeline.file.FileUtils.normalizeURI;
19  
20  import org.osgi.service.component.annotations.Component;
21  
22  @Component(
23  	name = "pf:normalize-uri",
24  	service = { ExtensionFunctionDefinition.class }
25  )
26  @SuppressWarnings("serial")
27  public class NormalizeURI extends ExtensionFunctionDefinition {
28  
29  	private static final StructuredQName funcname = new StructuredQName(
30  		"pf",
31  		"http://www.daisy.org/ns/pipeline/functions",
32  		"normalize-uri");
33  
34  	@Override
35  	public SequenceType[] getArgumentTypes() {
36  		return new SequenceType[] {
37  			SequenceType.OPTIONAL_STRING,
38  			SequenceType.SINGLE_BOOLEAN
39  		};
40  	}
41  
42  	@Override
43  	public int getMinimumNumberOfArguments() {
44  		return 1;
45  	}
46  
47  	@Override
48  	public int getMaximumNumberOfArguments() {
49  		return 2;
50  	}
51  
52  	@Override
53  	public StructuredQName getFunctionQName() {
54  		return funcname;
55  	}
56  
57  	@Override
58  	public SequenceType getResultType(SequenceType[] arg0) {
59  		return SequenceType.SINGLE_STRING;
60  	}
61  
62  	@Override
63  	public ExtensionFunctionCall makeCallExpression() {
64  		return new ExtensionFunctionCall() {
65  
66  			@SuppressWarnings({ "unchecked", "rawtypes" })
67  			public Sequence call(XPathContext context, Sequence[] arguments) throws XPathException {
68  				try {
69  					URI uri; {
70  						Item i = arguments[0].head();
71  						try {
72  							uri = new URI(i != null ? i.getStringValue().trim() : "");
73  						} catch (URISyntaxException e) {
74  							throw new XPathException("Not a valid URI: " + i, e);
75  						}
76  					}
77  					boolean fragment = arguments.length > 1 ? ((BooleanValue)arguments[1]).getBooleanValue() : true;
78  					return new StringValue(normalizeURI(uri, !fragment).toASCIIString(), BuiltInAtomicType.STRING);
79  				} catch (XPathException e) {
80  					throw e;
81  				} catch (Throwable e) {
82  					throw new XPathException("Unexpected error in pf:normalize-uri", e);
83  				}
84  			}
85  		};
86  	}
87  }