1   package org.daisy.pipeline.braille.pef.saxon.impl;
2   
3   import java.util.NoSuchElementException;
4   
5   import net.sf.saxon.expr.XPathContext;
6   import net.sf.saxon.lib.ExtensionFunctionCall;
7   import net.sf.saxon.lib.ExtensionFunctionDefinition;
8   import net.sf.saxon.om.Sequence;
9   import net.sf.saxon.om.StructuredQName;
10  import net.sf.saxon.trans.XPathException;
11  import net.sf.saxon.value.SequenceType;
12  import net.sf.saxon.value.StringValue;
13  
14  import org.daisy.dotify.api.table.Table;
15  import org.daisy.pipeline.braille.common.Query;
16  import static org.daisy.pipeline.braille.common.Query.util.mutableQuery;
17  import static org.daisy.pipeline.braille.common.Query.util.query;
18  import org.daisy.pipeline.braille.pef.TableRegistry;
19  
20  import org.osgi.service.component.annotations.Component;
21  import org.osgi.service.component.annotations.Reference;
22  import org.osgi.service.component.annotations.ReferenceCardinality;
23  import org.osgi.service.component.annotations.ReferencePolicy;
24  
25  import org.slf4j.Logger;
26  import org.slf4j.LoggerFactory;
27  
28  @Component(
29  	name = "pef:encode",
30  	service = { ExtensionFunctionDefinition.class }
31  )
32  @SuppressWarnings("serial")
33  public class EncodeDefinition extends ExtensionFunctionDefinition {
34  	
35  	private static final StructuredQName funcname = new StructuredQName("pef",
36  			"http://www.daisy.org/ns/2008/pef", "encode");
37  	
38  	@Reference(
39  		name = "TableRegistry",
40  		unbind = "-",
41  		service = TableRegistry.class,
42  		cardinality = ReferenceCardinality.MANDATORY,
43  		policy = ReferencePolicy.STATIC
44  	)
45  	protected void bindTableRegistry(TableRegistry registry) {
46  		tableRegistry = registry;
47  	}
48  	
49  	private TableRegistry tableRegistry;
50  	private final Query fallbackQuery = mutableQuery()
51  		.add("id", "org.daisy.braille.impl.table.DefaultTableProvider.TableType.EN_US");
52  	
53  	@Override
54  	public StructuredQName getFunctionQName() {
55  		return funcname;
56  	}
57  	
58  	@Override
59  	public int getMinimumNumberOfArguments() {
60  		return 2;
61  	}
62  	
63  	@Override
64  	public int getMaximumNumberOfArguments() {
65  		return 2;
66  	}
67  	
68  	@Override
69  	public SequenceType[] getArgumentTypes() {
70  		return new SequenceType[] {
71  				SequenceType.SINGLE_STRING,
72  				SequenceType.SINGLE_STRING};
73  	}
74  	
75  	@Override
76  	public SequenceType getResultType(SequenceType[] suppliedArgumentTypes) {
77  		return SequenceType.SINGLE_STRING;
78  	}
79  	
80  	@Override
81  	public ExtensionFunctionCall makeCallExpression() {
82  		return new ExtensionFunctionCall() {
83  			public Sequence call(XPathContext context, Sequence[] arguments) throws XPathException {
84  				try {
85  					Query tableQuery = query(arguments[0].head().getStringValue());
86  					String braille = arguments[1].head().getStringValue();
87  					Table table;
88  					try {
89  						table = tableRegistry.get(tableQuery).iterator().next(); }
90  					catch (NoSuchElementException e) {
91  						try {
92  							table = tableRegistry.get(fallbackQuery).iterator().next(); }
93  						catch (NoSuchElementException e2) {
94  							throw new XPathException("Could not find a table for query: " + tableQuery); }}
95  					return new StringValue(table.newBrailleConverter().toText(braille)); }
96  				catch (XPathException e) {
97  					throw e; }
98  				catch (Throwable e) {
99  					throw new XPathException("Unexpected error in pef:encode", e); }
100 			}
101 		};
102 	}
103 	
104 	private static final Logger logger = LoggerFactory.getLogger(EncodeDefinition.class);
105 	
106 }