source: MDService2/trunk/MDService2/src/eu/clarin/cmdi/mdservice/action/MDTransformer.java

Last change on this file was 1495, checked in by vronk, 13 years ago

started cleaning up code, adding inline-documentation;
also changes to output method in xsl (xhtml)

File size: 12.2 KB
RevLine 
[466]1package eu.clarin.cmdi.mdservice.action;
2
3import java.io.BufferedInputStream;
[1429]4import java.io.BufferedReader;
[466]5import java.io.ByteArrayInputStream;
6import java.io.ByteArrayOutputStream;
7import java.io.File;
8import java.io.FileInputStream;
9import java.io.IOException;
10import java.io.InputStream;
[1429]11import java.io.InputStreamReader;
[466]12import java.io.OutputStream;
13import java.io.Reader;
14import java.io.StringReader;
[690]15import java.io.StringWriter;
[1429]16import java.io.Writer;
[466]17import java.net.URL;
[879]18import java.util.HashMap;
19import java.util.Iterator;
20import java.util.Map;
21import java.util.Set;
[466]22
[690]23import javax.xml.parsers.DocumentBuilder;
24import javax.xml.parsers.DocumentBuilderFactory;
25import javax.xml.parsers.ParserConfigurationException;
[1429]26//import javax.xml.transform.ErrorListener;
[690]27import javax.xml.transform.OutputKeys;
[466]28import javax.xml.transform.Transformer;
[690]29import javax.xml.transform.TransformerConfigurationException;
[466]30import javax.xml.transform.TransformerException;
31import javax.xml.transform.TransformerFactory;
[690]32import javax.xml.transform.TransformerFactoryConfigurationError;
33import javax.xml.transform.dom.DOMSource;
[466]34import javax.xml.transform.stream.StreamResult;
35import javax.xml.transform.stream.StreamSource;
36
[1429]37//import ognl.IntHashMap.Entry;
[879]38
[1429]39import net.sf.saxon.event.MessageEmitter;
40import net.sf.saxon.event.MessageWarner;
41
[690]42import org.w3c.dom.Document;
43import org.w3c.dom.Element;
44import org.w3c.dom.Node;
45import org.w3c.dom.NodeList;
46
[1429]47//import com.icl.saxon.*;
48//import com.icl.saxon.FeatureKeys;
49//import com.icl.saxon.Loader;
50//import com.icl.saxon.output.Emitter;
51
52
[466]53/**
[1495]54 * Helper class, encapsulating the xsl-transformations handling.
55 * The contract is, that the requester passes a key, which can be resolved to a xsl-script (momentary mapped in properties: Admin.getConfig())
56 *
57 * Bad things happen, if the key or the appropriate xsl-file do not exist - well the client gets a diagnostic message.
[466]58 *   
59 *
60 * @author vronk
61 *
62 */
63
64public class MDTransformer {
65
66        private URL srcFile ;
[879]67        private HashMap<String,String> params;
[466]68               
[1495]69        // don't use singleton!! Bad things happen
70        // private MDTransformer singleton;
[466]71        TransformerFactory tfactory ; 
72       
73        public MDTransformer () {               
74                tfactory = TransformerFactory.newInstance();   
75        }
76       
77       
[501]78        public URL getSrcFile() {
79                return srcFile;
80        }
81
82        public void setSrcFile(URL srcFile) {
83                this.srcFile = srcFile;
84        }
85
[1495]86        /**
87         * This serves the caller (mainly GenericProxyAction.prepare())
88         * to provide/fill the request parameters.
89         * They then get translated to stylesheet-parameters (in SetTransformerParameters()).
90         * @return
91         */
[879]92        public void setParams(HashMap<String,String> params){
93                this.params = params;
94        }
95       
[1495]96       
[879]97        public HashMap<String,String> getParams(){
98                return this.params;
99        }
[466]100        /**
[1495]101         * get the path to the transform-xsl file from properties, based on the key (aka format-parameter)
[466]102         * @param key
103         * @return
[1488]104         * @throws NoStylesheetException - if no matching entry in properties could be found
[466]105         */
[1488]106        private String getXSLPath (String key) throws NoStylesheetException {           
[466]107                String xslpath = "";
108                String xslfilename= Admin.getConfig().getProperty("xsl." + key);
109               
110                if (xslfilename!=null) {                       
111                        xslpath =  Admin.getConfig().getProperty("scripts.path") + xslfilename;
[1488]112                } else {
113                        throw new NoStylesheetException("No Stylesheet found for format-key: " + key);
114                }
[466]115                Admin.notifyUser("xslfile:" + xslpath);
116                return xslpath;
117        }
118
[1495]119        /**
120         * Tries to load the stylesheet based on the key.
121         * This is done in two steps:
122         * 1. try to resolve the key to a path
123         * 2. get the xsl-file as a stream (and establish it as StreamSource)
124         *
125         * @param key The key identifying the stylesheet for the transformation as passed by GenericProxyAction.
126         * @return the stylesheet to be applied (as StreamSource)
127         * @throws NoStylesheetException If the stylesheet could not be located
128         */
[1488]129        private StreamSource getXSLStreamSource (String key) throws NoStylesheetException{             
[466]130               
131                InputStream xslstream;
132                                       
133                //URL myURL = new URL (getXSLPath(key));
134                //xslstream = myURL.openStream();
135                String xslPath = getXSLPath(key);
136                xslstream = this.getClass().getClassLoader().getResourceAsStream(xslPath);
137                StreamSource streamSource = new StreamSource(xslstream);
138
139                streamSource.setSystemId(this.getClass().getClassLoader().getResource(xslPath).toString());
[1495]140                return streamSource ;   
[466]141               
142        }
[690]143       
[879]144        public String getTranskey(){
145                return params.get("format");
146        }
[1495]147
148        /**
149         * Makes the request-parameters available in the stylesheets
150         * by translating them to stylesheet-parameters
151         * @param transformer
152         */
[879]153        public void SetTransformerParameters(Transformer transformer){
154               
155                Set<Map.Entry<String,String>> set = params.entrySet();
156                Iterator<Map.Entry<String,String>> i = set.iterator();
157
158            while(i.hasNext()){
159              Map.Entry<String,String> e = (Map.Entry<String,String>)i.next();
160              transformer.setParameter((String)e.getKey(), (String)e.getValue());
161            }
162        }
163       
[466]164        /**
165         * The main method for transforming, applies the appropriate (based on the transkey) stylesheet on the xml-stream
166         * and writes the result into the output stream.   
167         * @param in InpuStream with xml 
168         * @param transkey this defines the stylesheet to use and is also passed to the stylesheet as "format"-parameter
169         * @param out the stream to write the output to
170         * @throws TransformerException
171         * @throws IOException
[1488]172         * @throws NoStylesheetException
[879]173         */
[1488]174        public void transformXML (InputStream in, OutputStream out ) throws TransformerException, IOException, NoStylesheetException {
[879]175        //public void transformXML (InputStream in, String transkey, String cols, String startRecord, String maximumRecords, String lang, String q, String repositoryURI, OutputStream out ) throws TransformerException, IOException {
[466]176       
[1429]177                        System.setProperty("javax.xml.transform.TransformerFactory", "net.sf.saxon.TransformerFactoryImpl");
[466]178                // Create a transform factory instance.
179                TransformerFactory tfactory = TransformerFactory.newInstance();
180                //OutputStream os = new ByteArrayOutputStream();
181                StreamResult stream = new StreamResult(out);
182               
183                // Create a transformer for the stylesheet.
184                        //String xslpath = getXSLPath(transkey);               
185                Transformer transformer = tfactory.newTransformer(
[879]186                                                                        getXSLStreamSource(getTranskey()));
187                SetTransformerParameters(transformer);
[1429]188               
189                //MessageWarner gg = new net.sf.saxon.event.MessageWarner();
190                MessageEmitter me = new net.sf.saxon.event.MessageEmitter();
191                StringWriter w = new StringWriter();
192                me.setWriter(w);
193               ((net.sf.saxon.Controller)transformer).setMessageEmitter(me);//new net.sf.saxon.event.MessageWarner());
[1495]194
[1429]195               
[466]196                if (srcFile!=null) {
[582]197                       
[466]198                        File f = new File(srcFile.getPath());
[582]199                           
[466]200                        //Admin.notifyUser("src:" + srcFile.getFile());
201                        //Admin.notifyUser("fpath:" + f.getAbsolutePath());
[501]202                        String root_uri =  srcFile.toString();
[466]203                        String xsrcfile =  srcFile.getFile();
204                        if  (srcFile.getProtocol().equals("file")) {
205                                root_uri = "file:///" + f.getParent().replace('\\', '/');
206                                xsrcfile = "file:///" + f.getPath().replace('\\', '/');
207                        } 
[849]208                        // TODO repository-path -removed, bad formating
209                        String[] xsrcfiles = xsrcfile.split("&repository=");
210                        String[] root_uris = root_uri.split("&repository=");
211                        xsrcfile = xsrcfiles[0];
212                        root_uri = root_uris[0];
213                        ///
214                       
[466]215                        Admin.notifyUser("root_uri:" +  root_uri );
[795]216                        Admin.notifyUser("xsrcfile:" +  xsrcfile );
[1431]217                       
[466]218                        transformer.setParameter("root_uri", root_uri );
219                        transformer.setParameter("src_file", xsrcfile);
[501]220                } else {
221                        Admin.notifyUser("transformXML(): srcFile not set!!");                         
[466]222                }
[501]223                //
[466]224                StreamSource src =new StreamSource();                   
225                src.setInputStream(in);
226                // Transform the source XML to out-stream
227                transformer.transform(src, stream );
[1429]228               
229                // Write <xsl:message>
230                writeXslMessages(w);
231                ///Admin.notifyUser(w.getBuffer().toString());         
[1495]232   }
[466]233       
[1429]234
[466]235        /**
236         * just a wrapper for the main method translating the output-stream into a input-stream (expected by the Controller-Actions to return as response)
237         * @param xmlStream the source xml stream
238         * @param transkey
239         * @return result-stream (converted to InputStream)
240         * @throws IOException
241         * @throws InterruptedException
242         * @throws TransformerException
[1488]243         * @throws NoStylesheetException
[466]244         */
[1488]245        public InputStream transformXML ( InputStream xmlStream) throws IOException, InterruptedException, TransformerException, NoStylesheetException {
[879]246        //public InputStream transformXML ( InputStream xmlStream, String transkey, String cols, String startRecord, String maximumRecords, String lang, String q, String repositoryURI) throws IOException, InterruptedException, TransformerException {
[690]247               
248                ByteArrayOutputStream out = new ByteArrayOutputStream();
[1495]249                transformXML(xmlStream, out);           
[690]250            InputStream transformedStream = new ByteArrayInputStream(out.toByteArray());
251            return transformedStream;
252        }
253       
254        /**
[466]255         * another wrapper for the main method allowing to directly pass a URL to the source-xml   
256         * @param xmlFile URL of the source-file   
257         * @param transkey
258         * @return the result-stream (already converted to an InputStream)
259         * @throws TransformerException
260         * @throws IOException
[1488]261         * @throws NoStylesheetException
[466]262         */
[1488]263        public InputStream transformXML (URL xmlFile ) throws IOException, InterruptedException, TransformerException, NoStylesheetException {
[879]264        //public InputStream transformXML (URL xmlFile, String transkey ) throws IOException, InterruptedException, TransformerException {
[466]265                srcFile= xmlFile;
266                InputStream  xmlStream =
267             new BufferedInputStream(new FileInputStream(xmlFile.getPath()));
268           
[879]269                return transformXML ( xmlStream); 
[466]270        }
271
272
273        /**
[1495]274         * this is for xml-data present as string (primarily the query string present as XCQL).
[466]275         * if xml in a file or a stream, use the other methods
[1495]276         * @param xml xml-data as string
[466]277         * @param transkey
278         * @return
[1488]279         * @throws NoStylesheetException
[1429]280         * @throws IOException
[466]281         */
[1488]282        public String transformXML (String xml) throws NoStylesheetException {
[879]283        //public String transformXML (String xml, String transkey ) {
[466]284                String result="";
285                try {
286                // Create a transform factory instance.
287                        System.setProperty("javax.xml.transform.TransformerFactory", "net.sf.saxon.TransformerFactoryImpl");
[1429]288                        //System.setProperty("javax.xml.transform.TransformerFactory", "com.icl.saxon.TransformerFactoryImpl");
[466]289                TransformerFactory tfactory = TransformerFactory.newInstance();
290                OutputStream os = new ByteArrayOutputStream();
291                StreamResult stream = new StreamResult(os);
292                // Create a transformer for the stylesheet.
[500]293                Transformer transformer = tfactory.newTransformer(
[879]294                                                getXSLStreamSource(getTranskey()));
[1495]295
[1429]296                MessageEmitter me = new net.sf.saxon.event.MessageEmitter();
297                StringWriter w = new StringWriter();
298                me.setWriter(w);
299                ((net.sf.saxon.Controller)transformer).setMessageEmitter(me);//new net.sf.saxon.event.MessageWarner());
[466]300
301                // Transform the source XML to System.out.
302                StreamSource src =new StreamSource();       
303                Reader reader  = new StringReader(xml);
304                src.setReader(reader);
305               
306                transformer.transform(src, stream );
307                                    //  new StreamResult(new File("Simple2.out")));
[1429]308             // Write <xsl:message>
309                writeXslMessages(w);
310                 
[466]311                result = os.toString(); 
312               
313                        } catch (TransformerException e) {
314                                e.printStackTrace();
315                        }
316                       
317                        return result;
318        }
319
[1495]320        private void writeXslMessages(StringWriter w){
321       
322        byte[] bytes = w.getBuffer().toString().getBytes();
323        InputStream is =  new ByteArrayInputStream(bytes);
324        BufferedReader br = new BufferedReader(new InputStreamReader(is));
325        String s;
326                try {
327                        while ((s = br.readLine()) != null){
328                        Admin.notifyUser(s);
329                }
330                } catch (IOException e) {
331                        // TODO Auto-generated catch block
332                        e.printStackTrace();
333                }
334        }
[690]335       
[879]336        public static HashMap<String,String> createParamsMap(String transkey){
337                HashMap<String,String> hm = new HashMap<String,String>();
338               
339            if (transkey != null){
340                        hm.put("format", transkey);
341            }
342            return hm;
343        }
[466]344}
Note: See TracBrowser for help on using the repository browser.