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