Project

General

Profile

1
/**
2
 *  '$RCSfile: XSLTransform.java,v $'
3
 *  Copyright: 2003 Regents of the University of California and the
4
 *             National Center for Ecological Analysis and Synthesis
5
 *
6
 *   '$Author: jones $'
7
 *     '$Date: 2003/08/18 20:27:03 $'
8
 * '$Revision: 1.4 $'
9
 *
10
 * This program is free software; you can redistribute it and/or modify
11
 * it under the terms of the GNU General Public License as published by
12
 * the Free Software Foundation; either version 2 of the License, or
13
 * (at your option) any later version.
14
 *
15
 * This program is distributed in the hope that it will be useful,
16
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
17
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
18
 * GNU General Public License for more details.
19
 *
20
 * You should have received a copy of the GNU General Public License
21
 * along with this program; if not, write to the Free Software
22
 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
23
 */
24

    
25
package edu.ucsb.nceas.metacat.util;
26

    
27
import java.io.*;
28
import java.sql.PreparedStatement;
29
import java.sql.ResultSet;
30
import java.sql.SQLException;
31
import java.text.SimpleDateFormat;
32
import java.util.Enumeration;
33
import java.util.Hashtable;
34
import java.util.Vector;
35

    
36
import org.apache.log4j.Logger;
37

    
38
import edu.ucsb.nceas.metacat.DocumentImpl;
39
import edu.ucsb.nceas.metacat.DocumentImplWrapper;
40
import edu.ucsb.nceas.metacat.McdbException;
41
import edu.ucsb.nceas.metacat.database.DBConnection;
42
import edu.ucsb.nceas.metacat.database.DBConnectionPool;
43
import edu.ucsb.nceas.metacat.properties.PropertyService;
44
import edu.ucsb.nceas.metacat.service.XMLSchemaService;
45

    
46
import javax.xml.transform.TransformerFactory;
47
import javax.xml.transform.Transformer;
48
import javax.xml.transform.stream.StreamSource;
49
import javax.xml.transform.stream.StreamResult;
50
import javax.xml.transform.TransformerException;
51
import javax.xml.transform.TransformerConfigurationException;
52
import javax.xml.transform.URIResolver;
53

    
54
import org.ecoinformatics.eml.EMLParser;
55

    
56

    
57
/**
58
 * A Class that transforms older eml version to newer eml version utitlizing XSL style sheets. 
59
 */
60
public class EMLVersionsTransformer {
61
	
62
	private static org.apache.log4j.Logger logMetacat = Logger.getLogger(EMLVersionsTransformer.class);
63
	private static String eml210StyleFile = null;
64
	static{
65
		try
66
		{
67
			eml210StyleFile =PropertyService.getProperty("application.deployDir")+"/"+PropertyService
68
			.getProperty("application.context")+ "/style/common/eml201to210.xsl"; //eml201to210.xsl place
69
		}
70
		catch(Exception e)
71
		{
72
			logMetacat.warn("Couldn't get eml201to210.xsl stylesheet");
73
		}
74
	}
75
	private static String DOT = ".";
76
	private static int CAP = 100000; // How many documents you want to transform.
77

    
78
    /**
79
     * Public constructor because all methods are static and do not need 
80
     * an instance.
81
     */
82
    public EMLVersionsTransformer() 
83
    {
84
    	
85
    }
86
    
87
    /**
88
     * Method to upgrade old versions of eml to new version
89
     */
90
    public void upgrade()
91
    {
92
    	upgradeEML200ToEML210();
93
    }
94
    
95
    /*
96
     * Upgrade every eml200 or eml210 documents into eml210
97
     */
98
    private  void upgradeEML200ToEML210()
99
    {
100
    	Vector list = getEML2DocList();
101
    	if(list != null)
102
    	{
103
    		// Choose the smaller value between the size of vector and CAP
104
    		int size = list.size();
105
    		if (size > CAP)
106
    		{
107
    			size = CAP;
108
    		}
109
    		for(int i=0; i<size; i++)
110
    		{
111
    			OwnerAndDocid pair = (OwnerAndDocid)list.elementAt(i);
112
    			String docid = pair.getDocid();
113
    			String owner = pair.getOwner();
114
    			try
115
    			{
116
    				handleSingleEML200Document(docid, owner);
117
    				try
118
    				{
119
    					Thread.sleep(5000);
120
    				}
121
    				catch(Exception e)
122
    				{
123
    					logMetacat.warn("Couldn't sleep 5 seconds");
124
    				}
125
    			}
126
    			catch(Exception e)
127
    			{
128
    				logMetacat.warn("The docid "+docid+" with owner "+owner+" couldn't be transformed to eml-2.1.0 since "+e.getMessage());
129
    				transformErrorLog("The docid "+docid+" with owner "+owner+" couldn't be transformed to eml-2.1.0 since "+e.getMessage());
130
    			}
131
    		}
132
    	}
133
    }
134
    
135
    /*
136
     * Handle single eml201 or eml 200 document: read the document, transform it to eml210 document 
137
     * then save it to 210 document into metacat
138
     */
139
    private  void handleSingleEML200Document(String docidWithRev, String owner) throws Exception
140
    {
141
    	DocumentImpl docImpl = new DocumentImpl(docidWithRev);
142
    	String eml200Content = docImpl.toString();
143
    	StringReader eml200Source= new StringReader(eml200Content);
144
    	//PipedWriter eml210OutputAfterTransform = new PipedWriter();
145
    	//PipedReader eml210SourceForNewDoc = new PipedReader();
146
    	//eml210SourceForNewDoc.connect(eml210OutputAfterTransform);
147
    	StringWriter strWriter = new StringWriter();
148
    	String newId = increaseRevisionNumber(docidWithRev);
149
    	if(newId != null)
150
    	{
151
    	     transformEML200ToEML210(eml200Source, eml210StyleFile,  strWriter, newId);
152
    	     String eml210Content = strWriter.toString();
153
    	     String rule = DocumentImpl.EML210;
154
             // using emlparser to check id validation
155
             EMLParser parser = new EMLParser(eml210Content);
156
             DocumentImplWrapper documentWrapper = new DocumentImplWrapper(rule, true, true);
157
//             StringReader xml = new StringReader(eml210Content);
158
             String  doAction = "UPDATE";
159
             String pub = null;
160
             String []groups = null;
161
             DBConnection dbconn = null;
162
             StringReader dtd = null;
163
             int serialNumber = -1;
164
             String formatId = null;
165
             try
166
             {
167
            	 dbconn = DBConnectionPool
168
                 .getDBConnection("EMLVersionsTransformer.handleSingleEML200Document");
169
                  serialNumber = dbconn.getCheckOutSerialNumber();
170
                  String schemaLocation = XMLSchemaService.getInstance().getNameSpaceAndLocationStringWithoutFormatId();
171
                  documentWrapper.write(dbconn, eml210Content, pub, dtd,
172
                          doAction, newId, owner, groups, null, schemaLocation);
173
                  logMetacat.warn("Doc "+docidWithRev+" was transformed to eml210 with new id "+newId);
174
                  transformLog("Doc "+docidWithRev+" was transformed to eml210 with new id "+newId);
175
             }
176
             catch(Exception e)
177
             {
178
            	 throw e;
179
             }
180
             finally
181
             {
182
            	 // Return db connection
183
                 DBConnectionPool.returnDBConnection(dbconn, serialNumber);
184
             }
185
    	}
186
    	else
187
    	{
188
    		logMetacat.warn("Couldn't increase docid "+docidWithRev+"'s revision");
189
    	}
190
    }
191

    
192
    /*
193
     * Transform single eml201 (Reader) to eml 210 (Writer)
194
     */
195
    private static void transformEML200ToEML210(Reader reader, String xslfile, Writer writer, String packageid) throws Exception{    
196
        	Hashtable param = null;
197
            if (packageid != null)
198
            {
199
            	param = new Hashtable();
200
            	param.put("package-id", packageid);
201
            }
202
            EMLVersionsTransformer.transform(reader, xslfile, writer, param);
203
         
204
    }
205

    
206

    
207
    /*
208
     * Transform an XML document using an XSLT stylesheet to another format,
209
     * probably HTML or another XML document format.
210
     *
211
     * @param doc the document to be transformed
212
     * @param xslSystemId the system location of the stylesheet
213
     * @param pw the PrintWriter to which output is printed
214
     * @param params some parameters for inclusion to the transformation
215
     */
216
    private static void transform(Reader doc, String xslSystemId,
217
        Writer pw, Hashtable param) throws Exception
218
    {
219
        
220
            StreamSource xslSource = 
221
                new StreamSource(xslSystemId);
222
            xslSource.setSystemId(xslSystemId);
223
            // Create a stylesheet from the system id that was found
224
            TransformerFactory tFactory = TransformerFactory.newInstance();
225
            Transformer transformer = tFactory.newTransformer(xslSource);
226

    
227
            // Set up parameters for transformation
228
            if ( param != null) {
229
                Enumeration en = param.keys();
230
                while (en.hasMoreElements()) {
231
                    String key =(String)en.nextElement();
232
                    String value = ((String)(param.get(key)));
233
                    transformer.setParameter(key, value);
234
                }
235
            }
236

    
237
            // Run the transform engine
238
            StreamSource ss = new StreamSource(doc);
239
            StreamResult sr = new StreamResult(pw);
240
            transformer.transform(ss, sr);
241
        
242
    }
243
    
244
    /*
245
     * Get list of document (docid and owner) which type is eml200 or eml201. 
246
     * The docid in the list will have revision number too.
247
     */
248
    private Vector getEML2DocList()
249
    {
250
    	Vector list = new Vector();
251
    	 DBConnection dbconn = null;
252
         int serialNumber = -1;
253
         String sql = "select docid, rev, user_owner from xml_documents where doctype like 'eml://ecoinformatics.org/eml-2.0.1' or doctype like 'eml://ecoinformatics.org/eml-2.0.0'";
254
         PreparedStatement pstmt = null;
255
         try {
256
             dbconn = DBConnectionPool
257
                     .getDBConnection("EMLVersionsTransformer.getEML2DocList");
258
             serialNumber = dbconn.getCheckOutSerialNumber();
259
             pstmt = dbconn.prepareStatement(sql.toString());
260
             pstmt.execute();
261
             ResultSet rs = pstmt.getResultSet();
262
             boolean tableHasRows = rs.next();
263
             while (tableHasRows) {
264
                 String docidWithoutRev = rs.getString(1);
265
                 int rev = rs.getInt(2);
266
                 String owner = rs.getString(3);
267
                 String docidWithRev = docidWithoutRev+DOT+rev;
268
                 logMetacat.info("The docid "+docidWithRev+" with owner "+owner+" will be added into list which will be transformed to eml-2.1.0");
269
                 OwnerAndDocid pair = new OwnerAndDocid(owner, docidWithRev);;
270
                 list.add(pair);
271
                 tableHasRows = rs.next();
272
             }
273
             pstmt.close();
274

    
275
        
276
        } catch (SQLException e) {
277
             logMetacat.error("error in DocumentImpl.getDocumentInfo: "
278
                + e.getMessage());
279
             e.printStackTrace(System.out);
280
        } finally {
281
            try {
282
                 pstmt.close();
283
            } catch (SQLException ee) {
284
              logMetacat.error(
285
                    "error in DocumentImple.getDocumentInfo: "
286
                            + ee.getMessage());
287
           } finally {
288
              DBConnectionPool.returnDBConnection(dbconn, serialNumber);
289
        }
290
      }
291
      return list;
292
    }
293
    
294
    /*
295
     * Increase revision number for the given docid. tao.1.1 will be tao.1.2. null will be returned
296
     * if couldn't increase it.
297
     */
298
    private static String increaseRevisionNumber(String docidWithRev)
299
    {
300
    	String newid = null;
301
    	try
302
    	{
303
    	  if (docidWithRev != null)
304
    	  {
305
    		int index = docidWithRev.lastIndexOf(DOT);
306
    		if (index != -1)
307
    		{
308
    			String firstTwoParts = docidWithRev.substring(0,index);
309
    			String revStr = docidWithRev.substring(index+1);
310
    			Integer revObj = new Integer(revStr);
311
    			int rev = revObj.intValue();
312
    			rev= rev+1;
313
    			newid = firstTwoParts+DOT+rev;
314
    		}
315
    	  }
316
    	}
317
    	catch(Exception e)
318
    	{
319
    		logMetacat.warn("Couldn't increase revision number since "+e.getMessage());
320
    	}
321
    	return newid;
322
    }
323
    
324
    
325
    /*
326
	 * Method for writing transformation messages to a log file specified in
327
	 * metacat.properties
328
	 */
329
	private static void transformLog(String message) {
330
		try {
331
			FileOutputStream fos = 
332
				new FileOutputStream(PropertyService.getProperty("replication.logdir")
333
					+ "/transform.log", true);
334
			PrintWriter pw = new PrintWriter(fos);
335
			SimpleDateFormat formatter = new SimpleDateFormat("yy-MM-dd HH:mm:ss");
336
			java.util.Date localtime = new java.util.Date();
337
			String dateString = formatter.format(localtime);
338
			dateString += " :: " + message;
339
			// time stamp each entry
340
			pw.println(dateString);
341
			pw.flush();
342
		} catch (Exception e) {
343
			logMetacat.warn("error writing to transform log from "
344
					+ "EMLVersionTransformer.transformlLog: " + e.getMessage());
345
			// e.printStackTrace(System.out);
346
		}
347
	}
348

    
349
  /*
350
	 * Method for writing transform messages to a log file specified in
351
	 * metacat.properties
352
	 */
353
  private static void transformErrorLog(String message)
354
  {
355
    try
356
    {
357
    	FileOutputStream fos = 
358
			new FileOutputStream(PropertyService.getProperty("replication.logdir")
359
				+ "/transformerror.log", true);
360
      PrintWriter pw = new PrintWriter(fos);
361
      SimpleDateFormat formatter = new SimpleDateFormat ("yy-MM-dd HH:mm:ss");
362
      java.util.Date localtime = new java.util.Date();
363
      String dateString = formatter.format(localtime);
364
      dateString += " :: " + message;
365
      //time stamp each entry
366
      pw.println(dateString);
367
      pw.flush();
368
    }
369
    catch(Exception e)
370
    {
371
      logMetacat.warn("error writing to transforming error log from " +
372
                         "EMLVersionTransformer.transformErrorLog: " + e.getMessage());
373
      //e.printStackTrace(System.out);
374
    }
375
  }
376
    
377
    /*
378
     * Class reprents a document's docid and its owner 
379
     * @author tao
380
     *
381
     */
382
    class OwnerAndDocid{
383
    	private String owner = null;
384
    	private String docidWithRev = null;
385
    	
386
    	public OwnerAndDocid(String owner, String docidWithRev)
387
    	{
388
    		this.owner = owner;
389
    		this.docidWithRev = docidWithRev;
390
    	}
391
    	
392
    	public String getOwner()
393
    	{
394
    		return owner;
395
    	}
396
    	
397
    	public String getDocid()
398
    	{
399
    		return docidWithRev;
400
    	}
401
    }
402
    
403

    
404
  
405
}
406

    
(7-7/18)