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.dataone.service.types.v1.Checksum;
55
import org.ecoinformatics.eml.EMLParser;
56

    
57

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

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

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

    
208

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

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

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

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

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

    
406
  
407
}
408

    
(7-7/18)