Project

General

Profile

1
/**
2
 *  '$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
 *    Release: @release@
9
 *
10
 *   '$Author: berkley $'
11
 *     '$Date: 2003-07-02 12:04:35 -0700 (Wed, 02 Jul 2003) $'
12
 * '$Revision: 1716 $'
13
 *
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
 */
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
import java.util.Enumeration;
36
import java.util.Hashtable;
37
import java.util.Stack;
38

    
39
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
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
import oracle.xml.parser.v2.XSLStylesheet;
62
import oracle.xml.parser.v2.XSLException;
63
import oracle.xml.parser.v2.XMLParseException;
64
import oracle.xml.parser.v2.XSLProcessor;
65
import oracle.xml.parser.v2.XMLDocument;
66
import oracle.xml.parser.v2.DOMParser;
67
*/
68
import org.w3c.dom.Document;
69
import org.w3c.dom.Node;
70
import org.w3c.dom.Element;
71
import org.xml.sax.SAXException;
72

    
73
/**
74
 * A Class that transforms XML documents utitlizing XSL style sheets
75
 */
76
public class DBTransform {
77

    
78
  //private Connection	conn = null;
79
  private MetaCatUtil   util = null;
80
  private String 	configDir = null;
81
  private String	defaultStyle = null;
82

    
83
  /**
84
   * construct a DBTransform instance.
85
   *
86
   * Generally, one calls transformXMLDocument() after constructing the instance
87
   *
88
   * @param conn the database connection from which to lookup the public ids
89
   */
90
  public DBTransform()
91
                  throws IOException,
92
                         SQLException,
93
                         ClassNotFoundException
94
  {
95
    //this.conn = conn;
96
    util = new MetaCatUtil();
97
    configDir = util.getOption("config-dir");
98
    defaultStyle = util.getOption("default-style");
99
  }
100

    
101
  /**
102
   * @see transformXMLDocument(String doc, String sourceType,
103
   *            String targetType, String qformat, PrintWriter pw,
104
   *            String sessionid)
105
   */
106
  public void transformXMLDocument(String doc, String sourceType,
107
                String targetType, String qformat, PrintWriter pw)
108
  {
109
    transformXMLDocument(doc, sourceType, targetType, qformat, pw, null);
110
  }
111

    
112
  /**
113
   * Transform an XML document using the stylesheet reference from the db
114
   *
115
   * @param doc the document to be transformed
116
   * @param sourcetype the document type of the source
117
   * @param targettype the target document type
118
   * @param qformat the name of the style set to use
119
   * @param pw the PrintWriter to which output is printed
120
   * @param params some parameters for eml2 transformation
121
   */
122
  public void transformXMLDocument(String doc, String sourceType,
123
                                   String targetType, String qformat,
124
                                   PrintWriter pw, Hashtable param,
125
                                   String sessionid)
126
 {
127

    
128
    // Look up the stylesheet for this type combination
129
    String xslSystemId = getStyleSystemId(qformat, sourceType, targetType);
130

    
131
    if (xslSystemId != null) {
132
      // Create a stylesheet from the system id that was found
133
      try {
134
        TransformerFactory tFactory = TransformerFactory.newInstance();
135
        Transformer transformer = tFactory.newTransformer(
136
                                  new StreamSource(xslSystemId));
137
        //transformer.setParameter("qformat", qformat);
138
        //MetaCatUtil.debugMessage("qformat: "+qformat, 30);
139

    
140
        if(sessionid != null)
141
        {
142
          transformer.setParameter("sessid", sessionid);
143
        }
144

    
145
        // Set up parameter for transformation
146
        if ( param != null)
147
        {
148
          Enumeration en = param.keys();
149
          while (en.hasMoreElements())
150
          {
151
            String key =(String)en.nextElement();
152
            String value = ((String[])(param.get(key)))[0];
153
            MetaCatUtil.debugMessage(key+" : "+value, 30);
154
            transformer.setParameter(key, value);
155
          }
156
        }
157

    
158
        transformer.transform(new StreamSource(new StringReader(doc)),
159
                              new StreamResult(pw));
160
      } catch (Exception e) {
161
        pw.println(xslSystemId + "Error transforming document in " +
162
                   "DBTransform.transformXMLDocument: " +
163
                   e.getMessage());
164

    
165
      }
166
    } else {
167
      // No stylesheet registered form this document type, so just return the
168
      // XML stream we were passed
169
      pw.print(doc);
170
    }
171
  }
172

    
173
  /**
174
   * Transform an XML document to StringWriter using the stylesheet reference
175
   * 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
                String targetType, String qFormat, StringWriter pw,
184
                String sessionid) {
185

    
186
    // Look up the stylesheet for this type combination
187
    String xslSystemId = getStyleSystemId(qFormat, sourceType, targetType);
188

    
189
    if (xslSystemId != null) {
190
      // Create a stylesheet from the system id that was found
191
      try {
192
        TransformerFactory tFactory = TransformerFactory.newInstance();
193
        Transformer transformer = tFactory.newTransformer(
194
                                  new StreamSource(xslSystemId));
195
        if(sessionid != null)
196
        {
197
          transformer.setParameter("sessid", sessionid);
198
        }
199
        transformer.setParameter("qFormat", qFormat);
200
        transformer.transform(new StreamSource(new StringReader(doc)),
201
                              new StreamResult(pw));
202
      } catch (Exception e) {
203
        util.debugMessage(xslSystemId + "Error transforming document in " +
204
                   "DBTransform.transformXMLDocument: " +
205
                   e.getMessage(), 30);
206

    
207
      }
208
    } else {
209
      // No stylesheet registered form this document type, so just return the
210
      // XML stream we were passed
211
      pw.write(doc);
212
    }
213
  }
214

    
215
  /**
216
   * @see transformXMLDocument(String doc, String sourceType,
217
   *            String targetType, String qFormat, StringWriter pw
218
   *            String sessionid)
219
   */
220
  public void transformXMLDocument(String doc, String sourceType,
221
                String targetType, String qFormat, StringWriter pw)
222
  {
223
    transformXMLDocument(doc, sourceType, targetType, qFormat, pw, null);
224
  }
225

    
226
  /**
227
   * gets the content of a tag in a given xml file with the given path
228
   * @param f the file to parse
229
   * @param path the path to get the content from
230
   */
231
  public static NodeList getPathContent(File f, String path)
232
  {
233
    if(f == null)
234
    {
235
      return null;
236
    }
237

    
238
    DOMParser parser = new DOMParser();
239
    InputSource in;
240
    FileInputStream fs;
241

    
242
    try
243
    {
244
      fs = new FileInputStream(f);
245
      in = new InputSource(fs);
246
    }
247
    catch(FileNotFoundException fnf)
248
    {
249
      fnf.printStackTrace();
250
      return null;
251
    }
252

    
253
    try
254
    {
255
      parser.parse(in);
256
      fs.close();
257
    }
258
    catch(Exception e1)
259
    {
260
      System.err.println("File: " + f.getPath() + " : parse threw: " +
261
                         e1.toString());
262
      return null;
263
    }
264

    
265
    Document doc = parser.getDocument();
266

    
267
    try
268
    {
269
      NodeList docNodeList = XPathAPI.selectNodeList(doc, path);
270
      return docNodeList;
271
    }
272
    catch(Exception se)
273
    {
274
      System.err.println("file: " + f.getPath() + " : parse threw: " +
275
                         se.toString());
276
      return null;
277
    }
278
  }
279

    
280
  /**
281
   * Lookup a stylesheet reference from the db catalog
282
   *
283
   * @param qformat    the named style-set format
284
   * @param sourcetype the document type of the source
285
   * @param targettype the document type of the target
286
   */
287
  public String getStyleSystemId(String qformat, String sourcetype,
288
                String targettype) {
289
    String systemId = null;
290

    
291
    if ((qformat == null) || (qformat.equals("html"))) {
292
      qformat = defaultStyle;
293
    }
294

    
295
    // Load the style-set map for this qformat into a DOM
296
    try {
297
      boolean breakflag = false;
298
      String filename = configDir + "/" + qformat + ".xml";
299
      util.debugMessage("Trying style-set file: " + filename, 30);
300
      File f = new File(filename);
301
      NodeList nlDoctype = getPathContent(f, "/style-set/doctype");
302
      NodeList nlDefault = getPathContent(f, "/style-set/default-style");
303
      Node nDefault = nlDefault.item(0);
304
      systemId = nDefault.getFirstChild().getNodeValue(); //set the default
305

    
306
      for(int i=0; i<nlDoctype.getLength(); i++)
307
      { //look for the right sourcetype
308
        Node nDoctype = nlDoctype.item(i);
309
        NamedNodeMap atts = nDoctype.getAttributes();
310
        Node nAtt = atts.getNamedItem("publicid");
311
        String doctype = nAtt.getFirstChild().getNodeValue();
312
        if(doctype.equals(sourcetype))
313
        { //found the right sourcetype now we need to get the target type
314
          NodeList nlChildren = nDoctype.getChildNodes();
315
          for(int j=0; j<nlChildren.getLength(); j++)
316
          {
317
            Node nChild = nlChildren.item(j);
318
            String childName = nChild.getNodeName();
319
            if(childName.equals("target"))
320
            {
321
              NamedNodeMap childAtts = nChild.getAttributes();
322
              Node nTargetPublicId = childAtts.getNamedItem("publicid");
323
              String target = nTargetPublicId.getFirstChild().getNodeValue();
324
              if(target.equals(targettype))
325
              { //we found the right target type
326
                NodeList nlTarget = nChild.getChildNodes();
327
                for(int k=0; k<nlTarget.getLength(); k++)
328
                {
329
                  Node nChildText = nlTarget.item(k);
330
                  if(nChildText.getNodeType() == Node.TEXT_NODE)
331
                  { //get the text from the target node
332
                    systemId = nChildText.getNodeValue();
333
                    breakflag = true;
334
                    break;
335
                  }
336
                }
337
              }
338
            }
339

    
340
            if(breakflag)
341
            {
342
              break;
343
            }
344
          }
345
        }
346

    
347
        if(breakflag)
348
        {
349
          break;
350
        }
351
      }
352
    }
353
    catch(Exception e)
354
    {
355
      System.out.println("Error parsing style-set file: " + e.getMessage());
356
      e.printStackTrace();
357
    }
358

    
359
    // Return the system ID for this particular source document type
360
    MetaCatUtil.debugMessage("style system id is: "+systemId, 30);
361
    return systemId;
362
  }
363

    
364
  /**
365
   * Lookup a stylesheet reference from the db catalog
366
   *
367
   * @param objecttype the type of the object we want to retrieve
368
   * @param sourcetype the document type of the source
369
   * @param targettype the document type of the target
370
   */
371
  public String getSystemId(String objecttype, String sourcetype,
372
                String targettype) {
373

    
374
    // Look up the System ID of a particular object
375
    PreparedStatement pstmt = null;
376
    String the_system_id = null;
377
    DBConnection dbConn = null;
378
    int serialNumber = -1;
379
    try {
380
      dbConn=DBConnectionPool.
381
                  getDBConnection("DBTransform.getSystemId");
382
      serialNumber=dbConn.getCheckOutSerialNumber();
383
      pstmt =
384
        dbConn.prepareStatement("SELECT system_id " +
385
                "FROM xml_catalog " +
386
                "WHERE entry_type = ? " +
387
                "AND source_doctype = ? " +
388
                "AND target_doctype = ? ");
389
      // Bind the values to the query
390
      pstmt.setString(1, objecttype);
391
      pstmt.setString(2, sourcetype);
392
      pstmt.setString(3, targettype);
393
      pstmt.execute();
394
      try {
395
        ResultSet rs = pstmt.getResultSet();
396
        try {
397
          boolean tableHasRows = rs.next();
398
          if (tableHasRows) {
399
            try {
400
              the_system_id = rs.getString(1);
401
            } catch (SQLException e) {
402
              System.out.println("Error with getString in " +
403
                                 "DBTransform.getSystemId: " + e.getMessage());
404
            }
405
          } else {
406
            the_system_id = null;
407
          }
408
        } catch (SQLException e) {
409
          System.err.println("Error with next in DBTransform.getSystemId: " +
410
                              e.getMessage());
411
          return ("Error with next: " + e.getMessage());
412
        }
413
      } catch (SQLException e) {
414
        System.err.println("Error with getrset in DBTransform.getSystemId: " +
415
                            e.getMessage());
416
        return ("Error with getrset: " + e.getMessage());
417
      }
418
      pstmt.close();
419
    } catch (SQLException e) {
420
      System.err.println("Error getting id in DBTransform.getSystemId: " +
421
                          e.getMessage());
422
      return ("Error getting id in DBTransform.getSystemId:: " +
423
               e.getMessage());
424
    }
425
    finally
426
    {
427
      try
428
      {
429
        pstmt.close();
430
      }//try
431
      catch (SQLException sqlE)
432
      {
433
        MetaCatUtil.debugMessage("Error in DBTransform.getSystemId: "
434
                                   +sqlE.getMessage(), 30);
435
      }//catch
436
      finally
437
      {
438
        DBConnectionPool.returnDBConnection(dbConn, serialNumber);
439
      }//finally
440
    }//finally
441
    return the_system_id;
442
  }
443

    
444
  /**
445
   * the main routine used to test the transform utility.
446
   *
447
   * Usage: java DBTransform
448
   */
449
  static public void main(String[] args) {
450

    
451
     if (args.length > 0)
452
     {
453
        System.err.println("Wrong number of arguments!!!");
454
        System.err.println("USAGE: java DBTransform");
455
        return;
456
     } else {
457
        try {
458

    
459
          // Open a connection to the database
460
          /*MetaCatUtil   util = new MetaCatUtil();
461
          Connection dbconn = util.openDBConnection();*/
462

    
463
          // Create a test document
464
          StringBuffer testdoc = new StringBuffer();
465
          testdoc.append("<?xml version=\"1.0\"?>");
466
          testdoc.append("<eml-dataset><metafile_id>NCEAS-0001</metafile_id>");
467
          testdoc.append("<dataset_id>DS001</dataset_id>");
468
          testdoc.append("<title>My test doc</title></eml-dataset>");
469

    
470
          // Transform the document to the new doctype
471
          DBTransform dbt = new DBTransform();
472
          dbt.transformXMLDocument(testdoc.toString(),
473
                                   "-//NCEAS//eml-dataset//EN",
474
                                   "-//W3C//HTML//EN",
475
                                   "knb",
476
                                   new PrintWriter(System.out), null);
477

    
478
        } catch (Exception e) {
479
          System.err.println("EXCEPTION HANDLING REQUIRED");
480
          System.err.println(e.getMessage());
481
          e.printStackTrace(System.err);
482
        }
483
     }
484
  }
485

    
486
  private void dbg(int position) {
487
    System.err.println("Debug flag: " + position);
488
  }
489

    
490
}
(26-26/57)