Project

General

Profile

1 87 jones
/**
2 203 jones
 *  '$RCSfile$'
3
 *    Purpose: A Class that transforms an XML text document
4
 *             into a another type using XSL
5
 *  Copyright: 2000 Regents of the University of California and the
6
 *             National Center for Ecological Analysis and Synthesis
7
 *    Authors: Matt Jones
8 349 jones
 *    Release: @release@
9 87 jones
 *
10 1929 brooke
 * '$Author$'
11
 * '$Date$'
12 203 jones
 * '$Revision$'
13 669 jones
 *
14
 * This program is free software; you can redistribute it and/or modify
15
 * it under the terms of the GNU General Public License as published by
16
 * the Free Software Foundation; either version 2 of the License, or
17
 * (at your option) any later version.
18
 *
19
 * This program is distributed in the hope that it will be useful,
20
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
21
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
22
 * GNU General Public License for more details.
23
 *
24
 * You should have received a copy of the GNU General Public License
25
 * along with this program; if not, write to the Free Software
26
 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
27 87 jones
 */
28
29
package edu.ucsb.nceas.metacat;
30
31
import java.io.*;
32
import java.net.URL;
33
import java.net.MalformedURLException;
34
import java.sql.*;
35 1688 tao
import java.util.Enumeration;
36 1664 tao
import java.util.Hashtable;
37 87 jones
import java.util.Stack;
38
39 906 berkley
import javax.xml.transform.TransformerFactory;
40
import javax.xml.transform.Transformer;
41
import javax.xml.transform.stream.StreamSource;
42
import javax.xml.transform.stream.StreamResult;
43
import javax.xml.transform.TransformerException;
44
import javax.xml.transform.TransformerConfigurationException;
45
46 2663 sgarg
import org.apache.log4j.Logger;
47 906 berkley
import org.apache.xerces.parsers.DOMParser;
48
import org.w3c.dom.Attr;
49
import org.w3c.dom.NamedNodeMap;
50
import org.w3c.dom.NodeList;
51
import org.w3c.dom.Document;
52
import org.w3c.dom.Node;
53
import org.w3c.dom.NodeList;
54
import org.w3c.dom.DocumentType;
55
import org.xml.sax.SAXException;
56
import org.xml.sax.InputSource;
57
import org.apache.xerces.dom.DocumentTypeImpl;
58
import org.apache.xpath.XPathAPI;
59
import org.w3c.dom.NamedNodeMap;
60
61
/*
62 87 jones
import oracle.xml.parser.v2.XSLStylesheet;
63
import oracle.xml.parser.v2.XSLException;
64 832 jones
import oracle.xml.parser.v2.XMLParseException;
65 87 jones
import oracle.xml.parser.v2.XSLProcessor;
66
import oracle.xml.parser.v2.XMLDocument;
67
import oracle.xml.parser.v2.DOMParser;
68 906 berkley
*/
69 832 jones
import org.w3c.dom.Document;
70
import org.w3c.dom.Node;
71
import org.w3c.dom.Element;
72
import org.xml.sax.SAXException;
73 87 jones
74 2896 sgarg
import java.util.Properties;
75 2893 sgarg
76 2912 harris
77 1716 berkley
/**
78 87 jones
 * A Class that transforms XML documents utitlizing XSL style sheets
79
 */
80
public class DBTransform {
81
82 1217 tao
  //private Connection	conn = null;
83 832 jones
  private MetaCatUtil   util = null;
84
  private String 	configDir = null;
85
  private String	defaultStyle = null;
86 2663 sgarg
  private Logger logMetacat = Logger.getLogger(DBTransform.class);
87
88 87 jones
  /**
89
   * construct a DBTransform instance.
90
   *
91
   * Generally, one calls transformXMLDocument() after constructing the instance
92
   *
93
   * @param conn the database connection from which to lookup the public ids
94
   */
95 1716 berkley
  public DBTransform()
96
                  throws IOException,
97
                         SQLException,
98 87 jones
                         ClassNotFoundException
99
  {
100 1217 tao
    //this.conn = conn;
101 832 jones
    util = new MetaCatUtil();
102
    configDir = util.getOption("config-dir");
103
    defaultStyle = util.getOption("default-style");
104 87 jones
  }
105 1716 berkley
106 87 jones
  /**
107 1716 berkley
   * @see transformXMLDocument(String doc, String sourceType,
108
   *            String targetType, String qformat, PrintWriter pw,
109
   *            String sessionid)
110
   */
111
  public void transformXMLDocument(String doc, String sourceType,
112 1717 berkley
                String targetType, String qformat, PrintWriter pw,
113
                Hashtable param)
114 1716 berkley
  {
115 1717 berkley
    transformXMLDocument(doc, sourceType, targetType, qformat, pw, param, null);
116 1716 berkley
  }
117
118 2088 tao
   /**
119
   * @see transformXMLDocument(String doc, String sourceType,
120
   *            String targetType, String qFormat, StringWriter pw
121
   *            String sessionid)
122
   */
123
  public void transformXMLDocument(String doc, String sourceType,
124
                String targetType, String qFormat, StringWriter pw)
125
  {
126
    transformXMLDocument(doc, sourceType, targetType, qFormat, pw, null);
127
  }
128
129
130 1716 berkley
  /**
131 87 jones
   * Transform an XML document using the stylesheet reference from the db
132
   *
133
   * @param doc the document to be transformed
134
   * @param sourcetype the document type of the source
135
   * @param targettype the target document type
136 832 jones
   * @param qformat the name of the style set to use
137
   * @param pw the PrintWriter to which output is printed
138 1664 tao
   * @param params some parameters for eml2 transformation
139 87 jones
   */
140 1716 berkley
  public void transformXMLDocument(String doc, String sourceType,
141
                                   String targetType, String qformat,
142
                                   PrintWriter pw, Hashtable param,
143
                                   String sessionid)
144 1664 tao
 {
145 1716 berkley
146 87 jones
    // Look up the stylesheet for this type combination
147 941 tao
    String xslSystemId = getStyleSystemId(qformat, sourceType, targetType);
148 2088 tao
    if (xslSystemId != null)
149
    {
150
      try
151
      {// Create a stylesheet from the system id that was found
152
        doc = removeDOCTYPE(doc);
153
        StringReader xml = new StringReader(doc);
154
        StreamResult result = new StreamResult(pw);
155
        doTransform(xml, result, xslSystemId, param, qformat, sessionid);
156 87 jones
157 2088 tao
      }
158
      catch (Exception e)
159
      {
160 941 tao
        pw.println(xslSystemId + "Error transforming document in " +
161 675 berkley
                   "DBTransform.transformXMLDocument: " +
162 87 jones
                   e.getMessage());
163 1716 berkley
164 87 jones
      }
165 2088 tao
    }
166
    else
167
    {
168 1716 berkley
      // No stylesheet registered form this document type, so just return the
169 87 jones
      // XML stream we were passed
170 100 jones
      pw.print(doc);
171 87 jones
    }
172
  }
173 1716 berkley
174 941 tao
  /**
175 1716 berkley
   * Transform an XML document to StringWriter using the stylesheet reference
176 941 tao
   * from the db
177
   * @param doc the document to be transformed
178
   * @param sourceType the document type of the source
179
   * @param targetType the target document type
180
   * @param qFormat the name of the style set to use
181
   * @param pw the StringWriter to which output will be stored
182
   */
183
  public void transformXMLDocument(String doc, String sourceType,
184 1716 berkley
                String targetType, String qFormat, StringWriter pw,
185 2088 tao
                String sessionid)
186
  {
187 941 tao
188
    // Look up the stylesheet for this type combination
189
    String xslSystemId = getStyleSystemId(qFormat, sourceType, targetType);
190 2088 tao
    if (xslSystemId != null)
191
    {
192 941 tao
      // Create a stylesheet from the system id that was found
193 2088 tao
      try
194
      {
195 1903 tao
        doc = removeDOCTYPE(doc);
196 2088 tao
        StringReader xml = new StringReader(doc);
197
        StreamResult result = new StreamResult(pw);
198
        doTransform(xml, result, xslSystemId, null, qFormat, sessionid);
199
      }
200
      catch (Exception e)
201
      {
202 2663 sgarg
        logMetacat.error(xslSystemId + "Error transforming document in " +
203 941 tao
                   "DBTransform.transformXMLDocument: " +
204 2663 sgarg
                   e.getMessage());
205 1716 berkley
206 941 tao
      }
207 2088 tao
    }
208
    else
209
    {
210 1716 berkley
      // No stylesheet registered form this document type, so just return the
211 941 tao
      // XML stream we were passed
212 950 tao
      pw.write(doc);
213 941 tao
    }
214
  }
215 1716 berkley
216 906 berkley
  /**
217 2088 tao
   * Method to do transform for a string reader
218
   * @param doc the document to be transformed
219
   * @param sourcetype the document type of the source
220
   * @param targettype the target document type
221
   * @param qformat the name of the style set to use
222
   * @param pw the PrintWriter to which output is printed
223
   * @param params some parameters for eml2 transformation
224 1716 berkley
   */
225 2088 tao
   public void transformXMLDocument(StringReader docContent, String sourceType,
226
                                   String targetType, String qformat,
227
                                   PrintWriter pw, Hashtable param,
228
                                   String sessionid)
229
   {
230
     // Look up the stylesheet for this type combination
231
    String xslSystemId = getStyleSystemId(qformat, sourceType, targetType);
232
    if (xslSystemId != null)
233
    {
234
      try
235
      {// Create a stylesheet from the system id that was found
236
        StreamResult result = new StreamResult(pw);
237
        doTransform(docContent, result, xslSystemId, param, qformat, sessionid);
238
239
      }
240
      catch (Exception e)
241
      {
242
        pw.println(xslSystemId + "Error transforming document in " +
243
                   "DBTransform.transformXMLDocument: " +
244
                   e.getMessage());
245
246
      }
247
    }
248
    else
249
    {
250
      // No stylesheet registered form this document type, so just return the
251
      // XML stream we were passed
252
      pw.print(docContent);
253
    }
254
   }
255
256
  /*
257
   * Method to do transfer
258
   */
259
  private void doTransform(StringReader docContent, StreamResult resultOutput,
260
                           String xslSystemId, Hashtable param,
261
                           String qformat, String sessionid)
262
                          throws Exception
263 1716 berkley
  {
264 2088 tao
    if (xslSystemId != null)
265
    {
266
        TransformerFactory tFactory = TransformerFactory.newInstance();
267
        Transformer transformer = tFactory.newTransformer(
268
                                  new StreamSource(xslSystemId));
269
        transformer.setParameter("qformat", qformat);
270 2663 sgarg
        logMetacat.warn("qformat: "+qformat);
271 2893 sgarg
272
        if (MetaCatUtil.skinconfigs.containsKey(qformat)){
273 2896 sgarg
        	Properties skinOptions = (Properties)MetaCatUtil.skinconfigs.get(qformat);
274 2897 sgarg
275
			if(skinOptions.getProperty("lsidauthority") != null){
276
        		transformer.setParameter("lsidauthority", skinOptions.getProperty("lsidauthority"));
277
			}
278
279
			if(skinOptions.getProperty("registryurl") != null){
280
           		transformer.setParameter("registryurl", skinOptions.getProperty("registryurl"));
281
			}
282
283
			if(skinOptions.getProperty("registryname") != null){
284
           		transformer.setParameter("registryname", skinOptions.getProperty("registryname"));
285
      		}
286
		}
287 2893 sgarg
288 2088 tao
        if(sessionid != null)
289
        {
290
          transformer.setParameter("sessid", sessionid);
291
        }
292
        // Set up parameter for transformation
293
        if ( param != null)
294
        {
295
          Enumeration en = param.keys();
296
          while (en.hasMoreElements())
297
          {
298
            String key =(String)en.nextElement();
299
            String value = ((String[])(param.get(key)))[0];
300 2668 sgarg
            logMetacat.info(key+" : "+value);
301 2088 tao
            transformer.setParameter(key, value);
302
          }
303
        }
304
        StreamSource xml = new StreamSource(docContent);
305
        transformer.transform(xml,resultOutput);
306
    }
307
  }//doTransform
308
309
310 1716 berkley
  /**
311 906 berkley
   * gets the content of a tag in a given xml file with the given path
312
   * @param f the file to parse
313
   * @param path the path to get the content from
314
   */
315 1716 berkley
  public static NodeList getPathContent(File f, String path)
316 906 berkley
  {
317
    if(f == null)
318
    {
319
      return null;
320
    }
321 1716 berkley
322 906 berkley
    DOMParser parser = new DOMParser();
323
    InputSource in;
324
    FileInputStream fs;
325 1716 berkley
326 906 berkley
    try
327 1716 berkley
    {
328 906 berkley
      fs = new FileInputStream(f);
329
      in = new InputSource(fs);
330
    }
331
    catch(FileNotFoundException fnf)
332
    {
333
      fnf.printStackTrace();
334
      return null;
335
    }
336 1716 berkley
337 906 berkley
    try
338
    {
339
      parser.parse(in);
340
      fs.close();
341
    }
342
    catch(Exception e1)
343
    {
344 1716 berkley
      System.err.println("File: " + f.getPath() + " : parse threw: " +
345 906 berkley
                         e1.toString());
346
      return null;
347
    }
348 1716 berkley
349 906 berkley
    Document doc = parser.getDocument();
350 1716 berkley
351 906 berkley
    try
352
    {
353
      NodeList docNodeList = XPathAPI.selectNodeList(doc, path);
354
      return docNodeList;
355
    }
356
    catch(Exception se)
357
    {
358 1716 berkley
      System.err.println("file: " + f.getPath() + " : parse threw: " +
359 906 berkley
                         se.toString());
360
      return null;
361
    }
362
  }
363 87 jones
364
  /**
365
   * Lookup a stylesheet reference from the db catalog
366
   *
367 832 jones
   * @param qformat    the named style-set format
368
   * @param sourcetype the document type of the source
369
   * @param targettype the document type of the target
370
   */
371 1716 berkley
  public String getStyleSystemId(String qformat, String sourcetype,
372 832 jones
                String targettype) {
373
    String systemId = null;
374
375
    if ((qformat == null) || (qformat.equals("html"))) {
376
      qformat = defaultStyle;
377
    }
378
379
    // Load the style-set map for this qformat into a DOM
380
    try {
381 906 berkley
      boolean breakflag = false;
382 1929 brooke
      String filename = configDir + "/" + qformat + "/" + qformat + ".xml";
383 2663 sgarg
      logMetacat.warn("Trying style-set file: " + filename);
384 906 berkley
      File f = new File(filename);
385
      NodeList nlDoctype = getPathContent(f, "/style-set/doctype");
386
      NodeList nlDefault = getPathContent(f, "/style-set/default-style");
387
      Node nDefault = nlDefault.item(0);
388
      systemId = nDefault.getFirstChild().getNodeValue(); //set the default
389 1716 berkley
390 906 berkley
      for(int i=0; i<nlDoctype.getLength(); i++)
391
      { //look for the right sourcetype
392
        Node nDoctype = nlDoctype.item(i);
393
        NamedNodeMap atts = nDoctype.getAttributes();
394
        Node nAtt = atts.getNamedItem("publicid");
395
        String doctype = nAtt.getFirstChild().getNodeValue();
396
        if(doctype.equals(sourcetype))
397
        { //found the right sourcetype now we need to get the target type
398
          NodeList nlChildren = nDoctype.getChildNodes();
399
          for(int j=0; j<nlChildren.getLength(); j++)
400
          {
401
            Node nChild = nlChildren.item(j);
402
            String childName = nChild.getNodeName();
403
            if(childName.equals("target"))
404
            {
405
              NamedNodeMap childAtts = nChild.getAttributes();
406
              Node nTargetPublicId = childAtts.getNamedItem("publicid");
407
              String target = nTargetPublicId.getFirstChild().getNodeValue();
408
              if(target.equals(targettype))
409
              { //we found the right target type
410
                NodeList nlTarget = nChild.getChildNodes();
411
                for(int k=0; k<nlTarget.getLength(); k++)
412
                {
413
                  Node nChildText = nlTarget.item(k);
414
                  if(nChildText.getNodeType() == Node.TEXT_NODE)
415
                  { //get the text from the target node
416
                    systemId = nChildText.getNodeValue();
417
                    breakflag = true;
418
                    break;
419
                  }
420
                }
421 832 jones
              }
422
            }
423 1716 berkley
424 906 berkley
            if(breakflag)
425
            {
426
              break;
427
            }
428 832 jones
          }
429
        }
430 1716 berkley
431 906 berkley
        if(breakflag)
432
        {
433
          break;
434
        }
435 832 jones
      }
436
    }
437 906 berkley
    catch(Exception e)
438
    {
439
      System.out.println("Error parsing style-set file: " + e.getMessage());
440
      e.printStackTrace();
441
    }
442 832 jones
443
    // Return the system ID for this particular source document type
444 2663 sgarg
    logMetacat.info("style system id is: "+systemId);
445 832 jones
    return systemId;
446
  }
447
448 1896 tao
 /* Method to modified the system id of xml input -- make sure it
449
    points to system id in xml_catalog table
450
  */
451 2088 tao
  private void modifiedXmlStreamSource(StreamSource xml, String publicId)
452 1896 tao
                                       throws Exception
453
  {
454
    // make sure the xml is not null
455
    if (xml == null || publicId == null)
456
    {
457
      return;
458 87 jones
    }
459 2663 sgarg
    logMetacat.info("public id of input stream is " +publicId);
460 1896 tao
    // Get system id from xml_catalog table
461
    String systemId = DBEntityResolver.getDTDSystemID(publicId);
462 2663 sgarg
    logMetacat.info("system id of input stream from xml_catalog"
463
                               +"table is " +systemId);
464 1896 tao
    //set system id to input stream
465
    xml.setSystemId(systemId);
466 87 jones
  }
467 2088 tao
468 1903 tao
  /*
469
   * removes the DOCTYPE element and its contents from a Sting
470 2088 tao
   * used to avoid problems with incorrect SystemIDs
471 1903 tao
   */
472 2088 tao
  private String removeDOCTYPE(String in) {
473 1903 tao
    String ret = "";
474
    int startpos = in.indexOf("<!DOCTYPE");
475
    if (startpos>-1) {
476 2088 tao
      int stoppos = in.indexOf(">", startpos + 8);
477 1903 tao
      ret = in.substring(0,startpos) + in.substring(stoppos+1,in.length());
478
    } else {
479
      return in;
480
    }
481 2088 tao
    return ret;
482 1903 tao
  }
483 99 jones
484
  /**
485
   * the main routine used to test the transform utility.
486
   *
487 184 jones
   * Usage: java DBTransform
488 99 jones
   */
489
  static public void main(String[] args) {
490 1716 berkley
491 184 jones
     if (args.length > 0)
492 99 jones
     {
493
        System.err.println("Wrong number of arguments!!!");
494 184 jones
        System.err.println("USAGE: java DBTransform");
495 99 jones
        return;
496
     } else {
497
        try {
498 1716 berkley
499 99 jones
          // Open a connection to the database
500 1217 tao
          /*MetaCatUtil   util = new MetaCatUtil();
501
          Connection dbconn = util.openDBConnection();*/
502 99 jones
503
          // Create a test document
504
          StringBuffer testdoc = new StringBuffer();
505
          testdoc.append("<?xml version=\"1.0\"?>");
506
          testdoc.append("<eml-dataset><metafile_id>NCEAS-0001</metafile_id>");
507
          testdoc.append("<dataset_id>DS001</dataset_id>");
508
          testdoc.append("<title>My test doc</title></eml-dataset>");
509
510
          // Transform the document to the new doctype
511 1217 tao
          DBTransform dbt = new DBTransform();
512 1716 berkley
          dbt.transformXMLDocument(testdoc.toString(),
513
                                   "-//NCEAS//eml-dataset//EN",
514
                                   "-//W3C//HTML//EN",
515 832 jones
                                   "knb",
516 1664 tao
                                   new PrintWriter(System.out), null);
517 99 jones
518
        } catch (Exception e) {
519
          System.err.println("EXCEPTION HANDLING REQUIRED");
520
          System.err.println(e.getMessage());
521
          e.printStackTrace(System.err);
522
        }
523
     }
524
  }
525 1716 berkley
526 184 jones
  private void dbg(int position) {
527 99 jones
    System.err.println("Debug flag: " + position);
528
  }
529
530 87 jones
}