1   package org.daisy.pipeline.common.saxon.impl;
2   
3   import java.math.BigDecimal;
4   
5   import static com.xmlcalabash.util.XProcMessageListenerHelper.parseNumber;
6   
7   import net.sf.saxon.expr.XPathContext;
8   import net.sf.saxon.lib.ExtensionFunctionCall;
9   import net.sf.saxon.lib.ExtensionFunctionDefinition;
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.value.EmptySequence;
14  import net.sf.saxon.value.SequenceType;
15  
16  import org.daisy.common.messaging.MessageAppender;
17  import org.daisy.common.messaging.MessageBuilder;
18  
19  import org.osgi.service.component.annotations.Component;
20  
21  @Component(
22  	name = "pf:progress",
23  	service = { ExtensionFunctionDefinition.class }
24  )
25  @SuppressWarnings("serial")
26  public class ProgressDefinition extends ExtensionFunctionDefinition {
27  	
28  	private static final StructuredQName funcname = new StructuredQName("pf",
29  			"http://www.daisy.org/ns/pipeline/functions", "progress");
30  	
31  	public StructuredQName getFunctionQName() {
32  		return funcname;
33  	}
34  	
35  	public SequenceType[] getArgumentTypes() {
36  		return new SequenceType[] {
37  			SequenceType.SINGLE_STRING
38  		};
39  	}
40  	
41  	public SequenceType getResultType(SequenceType[] suppliedArgumentTypes) {
42  		return SequenceType.EMPTY_SEQUENCE;
43  	}
44  	
45  	private static final Sequence VOID = EmptySequence.getInstance();
46  	
47  	public ExtensionFunctionCall makeCallExpression() {
48  		return new ExtensionFunctionCall() {
49  			public Sequence call(XPathContext context, Sequence[] arguments) throws XPathException {
50  				try {
51  					BigDecimal portion = parseNumber(arguments[0].head().getStringValue());
52  					MessageAppender activeBlock = MessageAppender.getActiveBlock();
53  					MessageBuilder m = new MessageBuilder().withProgress(portion);
54  					// we need an active block otherwise we have no place to send the progress info to
55  					if (activeBlock != null)
56  						activeBlock.append(m).close();
57  					return VOID; }
58  				catch (ArithmeticException e) {
59  					// probably divided by null, ignore progress info
60  					return VOID; }
61  				catch (Throwable e) {
62  					throw new XPathException("Unexpected error in pf:progress", e); }
63  			}
64  		};
65  	}
66  }