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: tao $'
11
 *     '$Date: 2003-03-19 15:26:44 -0800 (Wed, 19 Mar 2003) $'
12
 * '$Revision: 1496 $'
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.Stack;
36

    
37
import javax.xml.transform.TransformerFactory;
38
import javax.xml.transform.Transformer;
39
import javax.xml.transform.stream.StreamSource;
40
import javax.xml.transform.stream.StreamResult;
41
import javax.xml.transform.TransformerException;
42
import javax.xml.transform.TransformerConfigurationException;
43

    
44
import org.apache.xerces.parsers.DOMParser;
45
import org.w3c.dom.Attr;
46
import org.w3c.dom.NamedNodeMap;
47
import org.w3c.dom.NodeList;
48
import org.w3c.dom.Document;
49
import org.w3c.dom.Node;
50
import org.w3c.dom.NodeList;
51
import org.w3c.dom.DocumentType;
52
import org.xml.sax.SAXException;
53
import org.xml.sax.InputSource;
54
import org.apache.xerces.dom.DocumentTypeImpl;
55
import org.apache.xpath.XPathAPI;
56
import org.w3c.dom.NamedNodeMap;
57

    
58
/*
59
import oracle.xml.parser.v2.XSLStylesheet;
60
import oracle.xml.parser.v2.XSLException;
61
import oracle.xml.parser.v2.XMLParseException;
62
import oracle.xml.parser.v2.XSLProcessor;
63
import oracle.xml.parser.v2.XMLDocument;
64
import oracle.xml.parser.v2.DOMParser;
65
*/
66
import org.w3c.dom.Document;
67
import org.w3c.dom.Node;
68
import org.w3c.dom.Element;
69
import org.xml.sax.SAXException;
70

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

    
76
  //private Connection	conn = null;
77
  private MetaCatUtil   util = null;
78
  private String 	configDir = null;
79
  private String	defaultStyle = null;
80

    
81
  /**
82
   * construct a DBTransform instance.
83
   *
84
   * Generally, one calls transformXMLDocument() after constructing the instance
85
   *
86
   * @param conn the database connection from which to lookup the public ids
87
   */
88
  public DBTransform() 
89
                  throws IOException, 
90
                         SQLException, 
91
                         ClassNotFoundException
92
  {
93
    //this.conn = conn;
94
    util = new MetaCatUtil();
95
    configDir = util.getOption("config-dir");
96
    defaultStyle = util.getOption("default-style");
97
  }
98
  
99
  /**
100
   * Transform an XML document using the stylesheet reference from the db
101
   *
102
   * @param doc the document to be transformed
103
   * @param sourcetype the document type of the source
104
   * @param targettype the target document type
105
   * @param qformat the name of the style set to use
106
   * @param pw the PrintWriter to which output is printed
107
   */
108
  public void transformXMLDocument(String doc, String sourceType, 
109
                String targetType, String qformat, PrintWriter pw) {
110
    
111
    // Look up the stylesheet for this type combination
112
    String xslSystemId = getStyleSystemId(qformat, sourceType, targetType);
113

    
114
    if (xslSystemId != null) {
115
      // Create a stylesheet from the system id that was found
116
      try {
117
        TransformerFactory tFactory = TransformerFactory.newInstance();
118
        Transformer transformer = tFactory.newTransformer(
119
                                  new StreamSource(xslSystemId));
120
        transformer.setParameter("qformat", qformat);
121
        MetaCatUtil.debugMessage("qformat: "+qformat, 30);
122
        transformer.transform(new StreamSource(new StringReader(doc)), 
123
                              new StreamResult(pw));
124
      } catch (Exception e) {
125
        pw.println(xslSystemId + "Error transforming document in " +
126
                   "DBTransform.transformXMLDocument: " +
127
                   e.getMessage());
128
       
129
      }
130
    } else {
131
      // No stylesheet registered form this document type, so just return the 
132
      // XML stream we were passed
133
      pw.print(doc);
134
    }
135
  }
136
  
137
  /**
138
   * Transform an XML document to StringWriter using the stylesheet reference 
139
   * from the db
140
   * @param doc the document to be transformed
141
   * @param sourceType the document type of the source
142
   * @param targetType the target document type
143
   * @param qFormat the name of the style set to use
144
   * @param pw the StringWriter to which output will be stored
145
   */
146
  public void transformXMLDocument(String doc, String sourceType,
147
                String targetType, String qFormat, StringWriter pw) {
148

    
149
    // Look up the stylesheet for this type combination
150
    String xslSystemId = getStyleSystemId(qFormat, sourceType, targetType);
151

    
152
    if (xslSystemId != null) {
153
      // Create a stylesheet from the system id that was found
154
      try {
155
        TransformerFactory tFactory = TransformerFactory.newInstance();
156
        Transformer transformer = tFactory.newTransformer(
157
                                  new StreamSource(xslSystemId));
158
        transformer.setParameter("qFormat", qFormat);
159
        transformer.transform(new StreamSource(new StringReader(doc)),
160
                              new StreamResult(pw));
161
      } catch (Exception e) {
162
        util.debugMessage(xslSystemId + "Error transforming document in " +
163
                   "DBTransform.transformXMLDocument: " +
164
                   e.getMessage(), 30);
165
       
166
      }
167
    } else {
168
      // No stylesheet registered form this document type, so just return the 
169
      // XML stream we were passed
170
      pw.write(doc);
171
    }
172
  }
173
  
174
  /**
175
   * gets the content of a tag in a given xml file with the given path
176
   * @param f the file to parse
177
   * @param path the path to get the content from
178
   */
179
  public static NodeList getPathContent(File f, String path) 
180
  {
181
    if(f == null)
182
    {
183
      return null;
184
    }
185
   
186
    DOMParser parser = new DOMParser();
187
    InputSource in;
188
    FileInputStream fs;
189
    
190
    try
191
    { 
192
      fs = new FileInputStream(f);
193
      in = new InputSource(fs);
194
    }
195
    catch(FileNotFoundException fnf)
196
    {
197
      fnf.printStackTrace();
198
      return null;
199
    }
200
    
201
    try
202
    {
203
      parser.parse(in);
204
      fs.close();
205
    }
206
    catch(Exception e1)
207
    {
208
      System.err.println("File: " + f.getPath() + " : parse threw: " + 
209
                         e1.toString());
210
      return null;
211
    }
212
    
213
    Document doc = parser.getDocument();
214
    
215
    try
216
    {
217
      NodeList docNodeList = XPathAPI.selectNodeList(doc, path);
218
      return docNodeList;
219
    }
220
    catch(Exception se)
221
    {
222
      System.err.println("file: " + f.getPath() + " : parse threw: " + 
223
                         se.toString());
224
      return null;
225
    }
226
  }
227

    
228
  /**
229
   * Lookup a stylesheet reference from the db catalog
230
   *
231
   * @param qformat    the named style-set format
232
   * @param sourcetype the document type of the source
233
   * @param targettype the document type of the target
234
   */
235
  public String getStyleSystemId(String qformat, String sourcetype, 
236
                String targettype) {
237
    String systemId = null;
238

    
239
    if ((qformat == null) || (qformat.equals("html"))) {
240
      qformat = defaultStyle;
241
    }
242

    
243
    // Load the style-set map for this qformat into a DOM
244
    try {
245
      boolean breakflag = false;
246
      String filename = configDir + "/" + qformat + ".xml";       
247
      util.debugMessage("Trying style-set file: " + filename, 30);
248
      File f = new File(filename);
249
      NodeList nlDoctype = getPathContent(f, "/style-set/doctype");
250
      NodeList nlDefault = getPathContent(f, "/style-set/default-style");
251
      Node nDefault = nlDefault.item(0);
252
      systemId = nDefault.getFirstChild().getNodeValue(); //set the default
253
      
254
      for(int i=0; i<nlDoctype.getLength(); i++)
255
      { //look for the right sourcetype
256
        Node nDoctype = nlDoctype.item(i);
257
        NamedNodeMap atts = nDoctype.getAttributes();
258
        Node nAtt = atts.getNamedItem("publicid");
259
        String doctype = nAtt.getFirstChild().getNodeValue();
260
        if(doctype.equals(sourcetype))
261
        { //found the right sourcetype now we need to get the target type
262
          NodeList nlChildren = nDoctype.getChildNodes();
263
          for(int j=0; j<nlChildren.getLength(); j++)
264
          {
265
            Node nChild = nlChildren.item(j);
266
            String childName = nChild.getNodeName();
267
            if(childName.equals("target"))
268
            {
269
              NamedNodeMap childAtts = nChild.getAttributes();
270
              Node nTargetPublicId = childAtts.getNamedItem("publicid");
271
              String target = nTargetPublicId.getFirstChild().getNodeValue();
272
              if(target.equals(targettype))
273
              { //we found the right target type
274
                NodeList nlTarget = nChild.getChildNodes();
275
                for(int k=0; k<nlTarget.getLength(); k++)
276
                {
277
                  Node nChildText = nlTarget.item(k);
278
                  if(nChildText.getNodeType() == Node.TEXT_NODE)
279
                  { //get the text from the target node
280
                    systemId = nChildText.getNodeValue();
281
                    breakflag = true;
282
                    break;
283
                  }
284
                }
285
              }
286
            }
287
            
288
            if(breakflag)
289
            {
290
              break;
291
            }
292
          }
293
        }
294
        
295
        if(breakflag)
296
        {
297
          break;
298
        }
299
      }
300
    }
301
    catch(Exception e)
302
    {
303
      System.out.println("Error parsing style-set file: " + e.getMessage());
304
      e.printStackTrace();
305
    }
306

    
307
    // Return the system ID for this particular source document type
308
    MetaCatUtil.debugMessage("style system id is: "+systemId, 30);
309
    return systemId;
310
  }
311

    
312
  /**
313
   * Lookup a stylesheet reference from the db catalog
314
   *
315
   * @param objecttype the type of the object we want to retrieve
316
   * @param sourcetype the document type of the source
317
   * @param targettype the document type of the target
318
   */
319
  public String getSystemId(String objecttype, String sourcetype, 
320
                String targettype) {
321

    
322
    // Look up the System ID of a particular object
323
    PreparedStatement pstmt = null;
324
    String the_system_id = null;
325
    DBConnection dbConn = null;
326
    int serialNumber = -1;
327
    try {
328
      dbConn=DBConnectionPool.
329
                  getDBConnection("DBTransform.getSystemId");
330
      serialNumber=dbConn.getCheckOutSerialNumber();
331
      pstmt =
332
        dbConn.prepareStatement("SELECT system_id " +
333
                "FROM xml_catalog " +
334
                "WHERE entry_type = ? " +
335
                "AND source_doctype = ? " +
336
                "AND target_doctype = ? ");
337
      // Bind the values to the query
338
      pstmt.setString(1, objecttype);
339
      pstmt.setString(2, sourcetype);
340
      pstmt.setString(3, targettype);
341
      pstmt.execute();
342
      try {
343
        ResultSet rs = pstmt.getResultSet();
344
        try {
345
          boolean tableHasRows = rs.next();
346
          if (tableHasRows) {
347
            try {
348
              the_system_id = rs.getString(1);
349
            } catch (SQLException e) {
350
              System.out.println("Error with getString in " + 
351
                                 "DBTransform.getSystemId: " + e.getMessage());                
352
            }
353
          } else {
354
            the_system_id = null; 
355
          }
356
        } catch (SQLException e) {
357
          System.err.println("Error with next in DBTransform.getSystemId: " + 
358
                              e.getMessage());
359
          return ("Error with next: " + e.getMessage());
360
        }
361
      } catch (SQLException e) {
362
        System.err.println("Error with getrset in DBTransform.getSystemId: " + 
363
                            e.getMessage());
364
        return ("Error with getrset: " + e.getMessage());
365
      }
366
      pstmt.close();
367
    } catch (SQLException e) {
368
      System.err.println("Error getting id in DBTransform.getSystemId: " + 
369
                          e.getMessage());
370
      return ("Error getting id in DBTransform.getSystemId:: " + 
371
               e.getMessage());
372
    }
373
    finally
374
    {
375
      try
376
      {
377
        pstmt.close();
378
      }//try
379
      catch (SQLException sqlE)
380
      {
381
        MetaCatUtil.debugMessage("Error in DBTransform.getSystemId: "
382
                                   +sqlE.getMessage(), 30);
383
      }//catch
384
      finally
385
      {
386
        DBConnectionPool.returnDBConnection(dbConn, serialNumber);
387
      }//finally
388
    }//finally
389
    return the_system_id;
390
  }
391

    
392
  /**
393
   * the main routine used to test the transform utility.
394
   *
395
   * Usage: java DBTransform
396
   */
397
  static public void main(String[] args) {
398
     
399
     if (args.length > 0)
400
     {
401
        System.err.println("Wrong number of arguments!!!");
402
        System.err.println("USAGE: java DBTransform");
403
        return;
404
     } else {
405
        try {
406
                    
407
          // Open a connection to the database
408
          /*MetaCatUtil   util = new MetaCatUtil();
409
          Connection dbconn = util.openDBConnection();*/
410

    
411
          // Create a test document
412
          StringBuffer testdoc = new StringBuffer();
413
          testdoc.append("<?xml version=\"1.0\"?>");
414
          testdoc.append("<eml-dataset><metafile_id>NCEAS-0001</metafile_id>");
415
          testdoc.append("<dataset_id>DS001</dataset_id>");
416
          testdoc.append("<title>My test doc</title></eml-dataset>");
417

    
418
          // Transform the document to the new doctype
419
          DBTransform dbt = new DBTransform();
420
          dbt.transformXMLDocument(testdoc.toString(), 
421
                                   "-//NCEAS//eml-dataset//EN", 
422
                                   "-//W3C//HTML//EN", 
423
                                   "knb",
424
                                   new PrintWriter(System.out));
425

    
426
        } catch (Exception e) {
427
          System.err.println("EXCEPTION HANDLING REQUIRED");
428
          System.err.println(e.getMessage());
429
          e.printStackTrace(System.err);
430
        }
431
     }
432
  }
433
  
434
  private void dbg(int position) {
435
    System.err.println("Debug flag: " + position);
436
  }
437

    
438
}
(24-24/54)