1   package org.daisy.pipeline.braille.pef.calabash.impl;
2   
3   import java.io.File;
4   import java.io.FileOutputStream;
5   import java.io.InputStreamReader;
6   import java.io.LineNumberReader;
7   import java.io.OutputStream;
8   import java.io.StringReader;
9   import java.net.URI;
10  import java.util.Map;
11  
12  import javax.xml.transform.stream.StreamSource;
13  
14  import org.daisy.common.xproc.calabash.XProcStep;
15  import org.daisy.common.xproc.calabash.XProcStepProvider;
16  import org.daisy.common.xproc.XProcMonitor;
17  
18  import org.osgi.service.component.annotations.Component;
19  
20  import org.slf4j.Logger;
21  import org.slf4j.LoggerFactory;
22  
23  import com.xmlcalabash.core.XProcException;
24  import com.xmlcalabash.core.XProcRuntime;
25  import com.xmlcalabash.io.ReadablePipe;
26  import com.xmlcalabash.io.WritablePipe;
27  import com.xmlcalabash.library.DefaultStep;
28  import com.xmlcalabash.runtime.XAtomicStep;
29  
30  import net.sf.saxon.s9api.QName;
31  import net.sf.saxon.s9api.SaxonApiException;
32  import net.sf.saxon.s9api.Serializer;
33  import net.sf.saxon.s9api.XdmNode;
34  
35  public class ValidateStep extends DefaultStep implements XProcStep {
36  		
37  	private static final QName _assert_valid = new QName("assert-valid");
38  	private static final QName _temp_dir = new QName("temp-dir");
39  	
40  	private ReadablePipe source = null;
41  	private WritablePipe result = null;
42  	private WritablePipe validationStatus = null;
43  	
44  	private ValidateStep(XProcRuntime runtime, XAtomicStep step) {
45  		super(runtime, step);
46  	}
47  	
48  	@Override
49  	public void setInput(String port, ReadablePipe pipe) {
50  		source = pipe;
51  	}
52  	
53  	@Override
54  	public void setOutput(String port, WritablePipe pipe) {
55  		if ("validation-status".equals(port)) {
56  			validationStatus = pipe;
57  		} else {
58  			result = pipe;
59  		}
60  	}
61  	
62  	@Override
63  	public void reset() {
64  		source.resetReader();
65  		result.resetWriter();
66  		validationStatus.resetWriter();
67  	}
68  	
69  	@Override
70  	public void run() throws SaxonApiException {
71  		super.run();
72  		try {
73  			
74  			boolean assertValid = true;
75  			if (getOption(_assert_valid) != null)
76  				assertValid = getOption(_assert_valid).getBoolean();
77  			File tempDir = new File(new URI(getOption(_temp_dir).getString()));
78  			XdmNode pef = source.read();
79  
80  			// FIXME: PEFValidator has moved to dotify.task.impl and should be created through the
81  			// streamline API.
82  			logger.warn("Skipping PEF validation (currently not supported)");
83  			boolean valid = true;
84  			
85  			// Write PEF document to file
86  			/*File pefFile = File.createTempFile("validate.", ".pef", tempDir);
87  			OutputStream pefStream = new FileOutputStream(pefFile);
88  			Serializer serializer = runtime.getProcessor().newSerializer();
89  			serializer.setOutputStream(pefStream);
90  			serializer.setCloseOnCompletion(true);
91  			serializer.serializeNode(pef);
92  			serializer.close();
93  			pefStream.close();
94  			
95  			PEFValidator validator = new PEFValidator();
96  			boolean valid = validator.validate(pefFile.toURI().toURL());
97  			InputStreamReader is = new InputStreamReader(validator.getReportStream());
98  			LineNumberReader lnr = new LineNumberReader(is);
99  			String line;
100 			while ((line=lnr.readLine())!=null) {
101 				logger.info(line);
102 			}*/
103 			
104 			if (assertValid && !valid)
105 				throw new RuntimeException("PEF document is invalid.");
106 			
107 			if (validationStatus!=null) {
108 				String validationXML = "<d:validation-status xmlns:d=\"http://www.daisy.org/ns/pipeline/data\" result=\""+(valid?"ok":"error")+"\"/>";
109 				XdmNode validationResult = runtime.getProcessor().newDocumentBuilder()
110 					.build(
111 						new StreamSource(
112 							new StringReader(validationXML)));
113 				validationStatus.write(validationResult);
114 			}
115 			result.write(pef);
116 
117 		} catch (Throwable e) {
118 			throw XProcStep.raiseError(e, step);
119 		}
120 	}
121 	
122 	@Component(
123 		name = "pef:validate",
124 		service = { XProcStepProvider.class },
125 		property = { "type:String={http://www.daisy.org/ns/2008/pef}validate" }
126 	)
127 	public static class Provider implements XProcStepProvider {
128 		
129 		@Override
130 		public XProcStep newStep(XProcRuntime runtime, XAtomicStep step, XProcMonitor monitor, Map<String,String> properties) {
131 			return new ValidateStep(runtime, step);
132 		}
133 	}
134 	
135 	private static final Logger logger = LoggerFactory.getLogger(ValidateStep.class);
136 	
137 }