Project

General

Profile

1 145 bojilova
/**
2 203 jones
 *  '$RCSfile$'
3
 *    Purpose: A class that gets Accession Number, check for uniqueness
4
 *             and register it into db
5
 *  Copyright: 2000 Regents of the University of California and the
6
 *             National Center for Ecological Analysis and Synthesis
7
 *    Authors: Jivka Bojilova, Matt Jones
8 145 bojilova
 *
9 203 jones
 *   '$Author$'
10
 *     '$Date$'
11
 * '$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 145 bojilova
 */
27
28
package edu.ucsb.nceas.metacat;
29
30 2768 jones
import java.sql.PreparedStatement;
31
import java.sql.ResultSet;
32
import java.sql.SQLException;
33 145 bojilova
34 5015 daigle
import edu.ucsb.nceas.metacat.database.DBConnection;
35
import edu.ucsb.nceas.metacat.database.DBConnectionPool;
36 5030 daigle
import edu.ucsb.nceas.metacat.properties.PropertyService;
37 4080 daigle
import edu.ucsb.nceas.utilities.PropertyNotFoundException;
38 747 bojilova
39 147 bojilova
/**
40 459 bojilova
 * (on insert of XML document)
41 2246 sgarg
 * Generates a unique Accession Number or if provided check it
42
 * for uniqueness and register it into the db connection
43 459 bojilova
 * (on update or delete of XML document)
44
 * Check for existance of provided Accession Number
45 2246 sgarg
 *
46 147 bojilova
 */
47 145 bojilova
public class AccessionNumber  {
48 2246 sgarg
49 618 bojilova
  private String sitecode = null;
50 459 bojilova
  private String sep = null;
51 779 bojilova
  private String docid = null;
52
  private String rev = null;
53 2246 sgarg
54 4080 daigle
    /**
55
	 * Construct an AccessionNumber
56
	 */
57
	private AccessionNumber() throws AccessionNumberException {
58
		try {
59 4212 daigle
			this.sitecode = PropertyService.getProperty("document.sitecode");
60
			this.sep = PropertyService.getProperty("document.accNumSeparator");
61 4080 daigle
		} catch (PropertyNotFoundException pnfe) {
62
			throw new AccessionNumberException("Could not retrieve property "
63
					+ "in constructor: " + pnfe.getMessage());
64
		}
65
	}
66
67 2246 sgarg
  /**
68 4080 daigle
	 * NEW - WHEN CLIENT ALWAYS PROVIDE ACCESSION NUMBER INCLUDING REV IN IT
69
	 * Construct an AccessionNumber
70
	 *
71
	 * @param conn
72
	 *            the db connection to read Accession number from
73
	 * @param accnum
74
	 *            the accession number to be checked for validness
75
	 */
76 2246 sgarg
  public AccessionNumber (String accnum, String action)
77 954 tao
           throws AccessionNumberException, SQLException, NumberFormatException
78
 {
79 1215 tao
    this();
80 779 bojilova
81
    this.rev = null;
82
    this.docid = accnum;
83
    if ( accnum != null ) {
84
      int firstIndex = accnum.indexOf(this.sep);
85
      int lastIndex = accnum.lastIndexOf(this.sep);
86
      if ( firstIndex != lastIndex ) {
87
        //this docid contains a revision number
88
        this.rev = accnum.substring(lastIndex + 1);
89
        this.docid = accnum.substring(0, lastIndex);
90
      }
91
    }
92 2246 sgarg
93 779 bojilova
    // INSERT
94
    if ( action.equals("INSERT")) {
95
96 2253 sgarg
        if(rev != null){
97
            try {
98
                Integer.parseInt(rev);
99
            }
100
            catch (java.lang.NumberFormatException e) {
101
                throw new AccessionNumberException(
102
                    "Revision number is required");
103
            }
104
        }
105
106 779 bojilova
      // check accession number for validness
107
      if ( docid == null ) {
108 2253 sgarg
        throw new AccessionNumberException("Accession number is required");
109 779 bojilova
110
      // rev is not provided; throw an exception to prevent the insertion
111
      } else if ( rev == null ) {
112
        throw new AccessionNumberException
113 2253 sgarg
                  ("Revision number is required");
114 779 bojilova
115
      // docid is used; throw an exception to prevent the insertion
116
      } else if ( accNumberUsed(docid) ) {
117
        throw new AccessionNumberException
118 2253 sgarg
                  ("Accession number " + docid + " is already in use");
119 2246 sgarg
120 779 bojilova
      // rev is <> 1; throw an exception to prevent the insertion
121 1054 tao
      } /*else if ( !rev.equals("1")) {
122 2253 sgarg
        throw new AccessionNumberException("Revision number must be 1");
123 1054 tao
      }*/
124 2246 sgarg
125 779 bojilova
    // UPDATE or DELETE
126
    } else if ( action.equals("UPDATE") || action.equals("DELETE")) {
127
      String l_rev = "";
128
129 2246 sgarg
      int reversionNumber = 1;
130
131
      if(rev != null){
132 2253 sgarg
          try{
133
              reversionNumber = Integer.parseInt(rev);
134
          } catch (java.lang.NumberFormatException e){
135
              throw new AccessionNumberException(
136
                      "Revision number is required");
137
          }
138 2246 sgarg
      }
139
140 779 bojilova
      // Accession# is not provided; throw an exception to prevent the action
141
      if ( docid == null ) {
142 2253 sgarg
        throw new AccessionNumberException("Accession number is required");
143 779 bojilova
144
      // rev is not provided; throw an exception to prevent the action
145
      } else if ( rev == null ) {
146
        throw new AccessionNumberException
147 2253 sgarg
                  ("Revision number is required");
148 779 bojilova
149 5189 daigle
      // Accession# is not current (not in xml_documents or xml_revisions); throw an exception
150 779 bojilova
      } else if ( !accNumberIsCurrent(docid) ) {
151
        throw new AccessionNumberException
152
                  ("Document not found for Accession number " + docid);
153
154 954 tao
      //Revision number is less than or equal the recent one; throw a exception
155 779 bojilova
      } else if ( action.equals("UPDATE") &&
156 954 tao
                  reversionNumber <= getLastRevisionNumber(docid) ) {
157 779 bojilova
        throw new AccessionNumberException
158 5350 berkley
                 ("Next revision number can't be less than or equal to "
159 954 tao
                                              + getLastRevisionNumber(docid));
160 779 bojilova
161
      // Revision number is not the recent one; throw an exception
162 2246 sgarg
      } else if ( action.equals("DELETE") &&
163 779 bojilova
                  !rev.equals(l_rev = getLastRevision(docid)) ) {
164
        throw new AccessionNumberException
165
                  ("Last revision number is "+ l_rev);
166
      }
167
    }
168
  }
169
170 459 bojilova
  /** check for existence of Accesssion Number xml_acc_numbers table */
171 2164 tao
  public static boolean accNumberUsed ( String accNumber )
172 576 bojilova
                  throws SQLException {
173 2246 sgarg
174 459 bojilova
    boolean hasAccNumber = false;
175 1215 tao
    DBConnection conn = null;
176
    int serialNumber = -1;
177 9491 tao
    PreparedStatement pstmt = null;
178
    ResultSet rs = null;
179 2246 sgarg
180 459 bojilova
    try {
181 9491 tao
182 1215 tao
      //check out DBConnection
183
      conn=DBConnectionPool.getDBConnection("AccessionNumber.accNumberUsed");
184
      serialNumber=conn.getCheckOutSerialNumber();
185 459 bojilova
      pstmt = conn.prepareStatement(
186 2246 sgarg
                "SELECT 'x' FROM xml_documents " +
187 770 bojilova
                "WHERE docid = ? " +
188 576 bojilova
                "UNION " +
189
                "SELECT 'x' FROM xml_revisions " +
190 770 bojilova
                "WHERE docid = ?");
191 576 bojilova
      pstmt.setString(1,accNumber);
192
      pstmt.setString(2,accNumber);
193 459 bojilova
      pstmt.execute();
194 9491 tao
      rs = pstmt.getResultSet();
195 459 bojilova
      hasAccNumber = rs.next();
196 9491 tao
      //pstmt.close();
197 2246 sgarg
198 459 bojilova
    } catch (SQLException e) {
199 576 bojilova
      throw new SQLException
200
      ("Error on AccessionNumber.accNumberUsed(accNumber): " + e.getMessage());
201 1215 tao
    }
202
    finally
203
    {
204 9491 tao
       try {
205
           if(rs != null) {
206
               rs.close();
207
           }
208
           if(pstmt != null) {
209
               pstmt.close();
210
           }
211
       } finally {
212
           DBConnectionPool.returnDBConnection(conn, serialNumber);
213
       }
214
215 1215 tao
    }
216 2246 sgarg
217 459 bojilova
    return hasAccNumber;
218 2246 sgarg
  }
219
220 5189 daigle
  // Check for existence of Accesssion Number in xml_documents or xml_revisions
221
  // table.  We check xml_revisions because document may have been deleted, which
222
  // will remove it from xml_documents, but a revision still exists.
223 4684 daigle
  private boolean accNumberIsCurrent(String accNumber) throws SQLException {
224 2246 sgarg
225 459 bojilova
    boolean hasCurrentAccNumber = false;
226 1215 tao
    DBConnection conn = null;
227
    int serialNumber = -1;
228 9491 tao
    ResultSet rs = null;
229
    PreparedStatement pstmt = null;
230 459 bojilova
    try {
231 9491 tao
232 1215 tao
      //check out DBConnection
233
      conn=DBConnectionPool.getDBConnection("AccessionNumber.accNumberIsCurre");
234
      serialNumber=conn.getCheckOutSerialNumber();
235 459 bojilova
      pstmt = conn.prepareStatement(
236 2246 sgarg
                "SELECT 'x' FROM xml_documents " +
237 770 bojilova
                "WHERE docid = ?");
238 459 bojilova
      pstmt.setString(1, accNumber);
239
      pstmt.execute();
240 9491 tao
      rs = pstmt.getResultSet();
241 459 bojilova
      hasCurrentAccNumber = rs.next();
242 5186 tao
      if(!hasCurrentAccNumber)
243
      {
244
        //need to look xml_revision table;
245
        pstmt = conn.prepareStatement(
246
            "SELECT 'x' FROM xml_revisions " +
247
            "WHERE docid = ?");
248
        pstmt.setString(1, accNumber);
249
        pstmt.execute();
250
        rs = pstmt.getResultSet();
251
        hasCurrentAccNumber = rs.next();
252
      }
253 9491 tao
      //pstmt.close();
254 2246 sgarg
255 459 bojilova
    } catch (SQLException e) {
256
      throw new SQLException(
257
          "Error on AccessionNumber.accNumberIsCurrent(String accNumber): " +
258
          e.getMessage());
259 1215 tao
    }
260
    finally
261
    {
262 9491 tao
263
       try {
264
           if(rs != null) {
265
               rs.close();
266
           }
267
           if(pstmt != null) {
268
               pstmt.close();
269
           }
270
       } finally {
271
           DBConnectionPool.returnDBConnection(conn, serialNumber);
272
       }
273
274 1215 tao
    }
275 2246 sgarg
276 459 bojilova
    return hasCurrentAccNumber;
277 2246 sgarg
  }
278 203 jones
279 734 bojilova
  // get the recent revision number for docid
280
  private String getLastRevision(String docid) throws SQLException
281
  {
282
    String rev = "";
283 1215 tao
    DBConnection conn = null;
284
    int serialNumber = -1;
285 9491 tao
    PreparedStatement pstmt = null;
286
    ResultSet rs = null;
287 734 bojilova
    try {
288 9491 tao
289 1215 tao
      //check out DBConnection
290
      conn=DBConnectionPool.getDBConnection("AccessionNumber.getLastRevision");
291
      serialNumber=conn.getCheckOutSerialNumber();
292 734 bojilova
      pstmt = conn.prepareStatement
293 6595 leinfelder
              ("SELECT rev FROM xml_documents WHERE docid = ?");
294
      pstmt.setString(1, docid);
295 734 bojilova
      pstmt.execute();
296
297 9491 tao
      rs = pstmt.getResultSet();
298 734 bojilova
      boolean hasRow = rs.next();
299
      rev = rs.getString(1);
300 9491 tao
      //pstmt.close();
301 2246 sgarg
302 734 bojilova
    } catch (SQLException e) {
303
      throw new SQLException(
304
      "Error on AccessionNumber.getLastRevision(): " + e.getMessage());
305
    }
306 1215 tao
    finally
307
    {
308 9491 tao
        try {
309
            if(rs != null) {
310
                rs.close();
311
            }
312
            if(pstmt != null) {
313
                pstmt.close();
314
            }
315
        } finally {
316
            DBConnectionPool.returnDBConnection(conn,serialNumber);
317
        }
318
319 1215 tao
    }
320 734 bojilova
321
    return rev;
322
  }
323 2246 sgarg
324 954 tao
  /**
325
    * Get last revision number from database for a docid
326
    * The return value is integer because we want compare it to there new one
327
    * @param docid <sitecode>.<uniqueid> part of Accession Number
328
    */
329
  private int getLastRevisionNumber(String docId) throws SQLException
330
  {
331
    int rev = 1;
332 1215 tao
    DBConnection conn =null;
333
    int serialNumber = -1;
334 9491 tao
    PreparedStatement pStmt = null;
335
    ResultSet rs = null;
336 954 tao
    try {
337 9491 tao
338 1215 tao
      //check out DBConnection
339
      conn=DBConnectionPool.getDBConnection("AccessionNumber.getLastRevisionN");
340
      serialNumber=conn.getCheckOutSerialNumber();
341 2246 sgarg
342 954 tao
      pStmt = conn.prepareStatement
343 6595 leinfelder
              ("SELECT rev FROM xml_documents WHERE docid = ? ");
344
      pStmt.setString(1, docId);
345 954 tao
      pStmt.execute();
346 734 bojilova
347 9491 tao
      rs = pStmt.getResultSet();
348 954 tao
      boolean hasRow = rs.next();
349 5186 tao
      if(hasRow)
350
      {
351
        rev = rs.getInt(1);
352
      }
353 9491 tao
      //pStmt.close();
354 2246 sgarg
355 954 tao
    } catch (SQLException e) {
356
      throw new SQLException(
357
      "Error on AccessionNumber.getLastRevision(): " + e.getMessage());
358
    }
359 1215 tao
    finally
360
    {
361 9491 tao
        try {
362
            if(rs != null) {
363
                rs.close();
364
            }
365
            if(pStmt != null) {
366
                pStmt.close();
367
            }
368
        } finally {
369
            DBConnectionPool.returnDBConnection(conn,serialNumber);
370
        }
371
372 1215 tao
    }
373 954 tao
    return rev;
374
  }
375 2246 sgarg
376 779 bojilova
  /**
377
   * returns the docid encoded in this accession number
378
   */
379
  public String getDocid() {
380
381
    return this.docid;
382
  }
383
384
  /**
385
   * returns the revision number encoded in this accession number
386
   */
387
  public String getRev()
388
  {
389
    return this.rev;
390
  }
391 2246 sgarg
392 203 jones
}