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