1   package org.daisy.pipeline.braille.pef.calabash.impl;
2   
3   import java.io.File;
4   import java.io.FileOutputStream;
5   import java.io.OutputStream;
6   import java.io.OutputStreamWriter;
7   import java.net.URI;
8   import java.util.Map;
9   import java.util.NoSuchElementException;
10  
11  import net.sf.saxon.s9api.QName;
12  import net.sf.saxon.s9api.SaxonApiException;
13  import net.sf.saxon.s9api.XdmNode;
14  
15  import org.daisy.braille.utils.pef.TextHandler;
16  import org.daisy.common.xproc.calabash.XProcStep;
17  import org.daisy.common.xproc.calabash.XProcStepProvider;
18  import org.daisy.common.xproc.XProcMonitor;
19  import org.daisy.dotify.api.table.Table;
20  import org.daisy.dotify.api.table.TableCatalogService;
21  import org.daisy.pipeline.braille.common.Query;
22  import static org.daisy.pipeline.braille.common.Query.util.query;
23  import org.daisy.pipeline.braille.pef.TableRegistry;
24  
25  import com.xmlcalabash.core.XProcException;
26  import com.xmlcalabash.core.XProcRuntime;
27  import com.xmlcalabash.io.ReadablePipe;
28  import com.xmlcalabash.io.WritablePipe;
29  import com.xmlcalabash.library.DefaultStep;
30  import com.xmlcalabash.runtime.XAtomicStep;
31  
32  import org.osgi.service.component.annotations.Component;
33  import org.osgi.service.component.annotations.Reference;
34  import org.osgi.service.component.annotations.ReferenceCardinality;
35  import org.osgi.service.component.annotations.ReferencePolicy;
36  
37  import org.slf4j.Logger;
38  import org.slf4j.LoggerFactory;
39  
40  public class Text2PEFStep extends DefaultStep implements XProcStep {
41  	
42  	private ReadablePipe source = null;
43  	private WritablePipe result = null;
44  	
45  	private static final QName _temp_dir = new QName("temp-dir");
46  	private static final QName _table = new QName("table");
47  	private static final QName _title = new QName("title");
48  	private static final QName _creator = new QName("creator");
49  	private static final QName _duplex = new QName("duplex");
50  	
51  	private final TableCatalogService tableCatalog;
52  	private final TableRegistry tableRegistry;
53  	
54  	private Text2PEFStep(XProcRuntime runtime,
55  	                     XAtomicStep step,
56  	                     TableCatalogService tableCatalog,
57  	                     TableRegistry tableRegistry) {
58  		super(runtime, step);
59  		this.tableCatalog = tableCatalog;
60  		this.tableRegistry = tableRegistry;
61  	}
62  	
63  	@Override
64  	public void setInput(String port, ReadablePipe pipe) {
65  		source = pipe;
66  	}
67  		
68  	@Override
69  	public void setOutput(String port, WritablePipe pipe) {
70  		result = pipe;
71  	}
72  	
73  	@Override
74  	public void reset() {
75  		source.resetReader();
76  		result.resetWriter();
77  	}
78  	
79  	@Override
80  	public void run() throws SaxonApiException {
81  		super.run();
82  		try {
83  			
84  			Query tableQuery = query(getOption(_table).getString());
85  			Table table = null;
86  			try {
87  				table = tableRegistry.get(tableQuery).iterator().next(); }
88  			catch (NoSuchElementException e) {
89  				throw new XProcException(step, "Could not find a table for query: " + tableQuery); }
90  			
91  			File tempDir = new File(new URI(getOption(_temp_dir).getString()));
92  			XdmNode text = source.read();
93  			
94  			// Write text document to file
95  			File textFile = File.createTempFile("text2pef.", ".txt", tempDir);
96  			OutputStream textStream = new FileOutputStream(textFile);
97  			OutputStreamWriter writer = new OutputStreamWriter(textStream, "UTF-8");
98  			writer.write(text.getStringValue());
99  			writer.close();
100 			
101 			// Parse text to PEF
102 			File pefFile = File.createTempFile("text2pef.", ".pef", tempDir);
103 			TextHandler.Builder b = new TextHandler.Builder(textFile, pefFile, tableCatalog);
104 			b.title(getOption(_title, ""));
105 			b.author(getOption(_creator, ""));
106 			b.duplex(getOption(_duplex, false));
107 			b.converterId(table.getIdentifier());
108 			TextHandler handler = b.build();
109 			handler.parse();
110 			textFile.delete();
111 			
112 			// Read PEF document
113 			XdmNode pef = runtime.getProcessor().newDocumentBuilder().build(pefFile);
114 			pefFile.delete();
115 			result.write(pef); }
116 		
117 		catch (Throwable e) {
118 			throw XProcStep.raiseError(e, step); }
119 	}
120 	
121 	@Component(
122 		name = "pef:text2pef",
123 		service = { XProcStepProvider.class },
124 		property = { "type:String={http://www.daisy.org/ns/2008/pef}text2pef" }
125 	)
126 	public static class Provider implements XProcStepProvider {
127 		
128 		@Override
129 		public XProcStep newStep(XProcRuntime runtime, XAtomicStep step, XProcMonitor monitor, Map<String,String> properties) {
130 			return new Text2PEFStep(runtime, step, tableCatalog, tableRegistry);
131 		}
132 		
133 		private TableCatalogService tableCatalog;
134 		
135 		@Reference(
136 			name = "TableCatalog",
137 			unbind = "-",
138 			service = TableCatalogService.class,
139 			cardinality = ReferenceCardinality.MANDATORY,
140 			policy = ReferencePolicy.STATIC
141 		)
142 		public void setTableCatalog(TableCatalogService catalog) {
143 			tableCatalog = catalog;
144 		}
145 		
146 		@Reference(
147 			name = "TableRegistry",
148 			unbind = "-",
149 			service = TableRegistry.class,
150 			cardinality = ReferenceCardinality.MANDATORY,
151 			policy = ReferencePolicy.STATIC
152 		)
153 		protected void bindTableRegistry(TableRegistry registry) {
154 			tableRegistry = registry;
155 		}
156 		
157 		private TableRegistry tableRegistry;
158 		
159 	}
160 	
161 	private static final Logger logger = LoggerFactory.getLogger(Text2PEFStep.class);
162 	
163 }