Project

General

Profile

1
/**
2
 *  '$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
 *
9
 *   '$Author: leinfelder $'
10
 *     '$Date: 2011-11-02 20:40:12 -0700 (Wed, 02 Nov 2011) $'
11
 * '$Revision: 6595 $'
12
 *
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
 */
27

    
28
package edu.ucsb.nceas.metacat;
29

    
30
import java.sql.PreparedStatement;
31
import java.sql.ResultSet;
32
import java.sql.SQLException;
33

    
34
import edu.ucsb.nceas.metacat.database.DBConnection;
35
import edu.ucsb.nceas.metacat.database.DBConnectionPool;
36
import edu.ucsb.nceas.metacat.properties.PropertyService;
37
import edu.ucsb.nceas.utilities.PropertyNotFoundException;
38

    
39
/**
40
 * (on insert of XML document)
41
 * Generates a unique Accession Number or if provided check it
42
 * for uniqueness and register it into the db connection
43
 * (on update or delete of XML document)
44
 * Check for existance of provided Accession Number
45
 *
46
 */
47
public class AccessionNumber  {
48

    
49
  private String sitecode = null;
50
  private String sep = null;
51
  private String docid = null;
52
  private String rev = null;
53

    
54
    /**
55
	 * Construct an AccessionNumber
56
	 */
57
	private AccessionNumber() throws AccessionNumberException {
58
		try {
59
			this.sitecode = PropertyService.getProperty("document.sitecode");
60
			this.sep = PropertyService.getProperty("document.accNumSeparator");
61
		} catch (PropertyNotFoundException pnfe) {
62
			throw new AccessionNumberException("Could not retrieve property "
63
					+ "in constructor: " + pnfe.getMessage());
64
		}
65
	}
66

    
67
  /**
68
	 * 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
  public AccessionNumber (String accnum, String action)
77
           throws AccessionNumberException, SQLException, NumberFormatException
78
 {
79
    this();
80

    
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

    
93
    // INSERT
94
    if ( action.equals("INSERT")) {
95

    
96
        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
      // check accession number for validness
107
      if ( docid == null ) {
108
        throw new AccessionNumberException("Accession number is required");
109

    
110
      // rev is not provided; throw an exception to prevent the insertion
111
      } else if ( rev == null ) {
112
        throw new AccessionNumberException
113
                  ("Revision number is required");
114

    
115
      // docid is used; throw an exception to prevent the insertion
116
      } else if ( accNumberUsed(docid) ) {
117
        throw new AccessionNumberException
118
                  ("Accession number " + docid + " is already in use");
119

    
120
      // rev is <> 1; throw an exception to prevent the insertion
121
      } /*else if ( !rev.equals("1")) {
122
        throw new AccessionNumberException("Revision number must be 1");
123
      }*/
124

    
125
    // UPDATE or DELETE
126
    } else if ( action.equals("UPDATE") || action.equals("DELETE")) {
127
      String l_rev = "";
128

    
129
      int reversionNumber = 1;
130

    
131
      if(rev != null){
132
          try{
133
              reversionNumber = Integer.parseInt(rev);
134
          } catch (java.lang.NumberFormatException e){
135
              throw new AccessionNumberException(
136
                      "Revision number is required");
137
          }
138
      }
139

    
140
      // Accession# is not provided; throw an exception to prevent the action
141
      if ( docid == null ) {
142
        throw new AccessionNumberException("Accession number is required");
143

    
144
      // rev is not provided; throw an exception to prevent the action
145
      } else if ( rev == null ) {
146
        throw new AccessionNumberException
147
                  ("Revision number is required");
148

    
149
      // Accession# is not current (not in xml_documents or xml_revisions); throw an exception
150
      } else if ( !accNumberIsCurrent(docid) ) {
151
        throw new AccessionNumberException
152
                  ("Document not found for Accession number " + docid);
153

    
154
      //Revision number is less than or equal the recent one; throw a exception
155
      } else if ( action.equals("UPDATE") &&
156
                  reversionNumber <= getLastRevisionNumber(docid) ) {
157
        throw new AccessionNumberException
158
                 ("Next revision number can't be less than or equal to "
159
                                              + getLastRevisionNumber(docid));
160

    
161
      // Revision number is not the recent one; throw an exception
162
      } else if ( action.equals("DELETE") &&
163
                  !rev.equals(l_rev = getLastRevision(docid)) ) {
164
        throw new AccessionNumberException
165
                  ("Last revision number is "+ l_rev);
166
      }
167
    }
168
  }
169

    
170
  /** check for existence of Accesssion Number xml_acc_numbers table */
171
  public static boolean accNumberUsed ( String accNumber )
172
                  throws SQLException {
173

    
174
    boolean hasAccNumber = false;
175
    DBConnection conn = null;
176
    int serialNumber = -1;
177

    
178
    try {
179
      PreparedStatement pstmt = null;
180
      //check out DBConnection
181
      conn=DBConnectionPool.getDBConnection("AccessionNumber.accNumberUsed");
182
      serialNumber=conn.getCheckOutSerialNumber();
183
      pstmt = conn.prepareStatement(
184
                "SELECT 'x' FROM xml_documents " +
185
                "WHERE docid = ? " +
186
                "UNION " +
187
                "SELECT 'x' FROM xml_revisions " +
188
                "WHERE docid = ?");
189
      pstmt.setString(1,accNumber);
190
      pstmt.setString(2,accNumber);
191
      pstmt.execute();
192
      ResultSet rs = pstmt.getResultSet();
193
      hasAccNumber = rs.next();
194
      pstmt.close();
195

    
196
    } catch (SQLException e) {
197
      throw new SQLException
198
      ("Error on AccessionNumber.accNumberUsed(accNumber): " + e.getMessage());
199
    }
200
    finally
201
    {
202
      DBConnectionPool.returnDBConnection(conn, serialNumber);
203
    }
204

    
205
    return hasAccNumber;
206
  }
207

    
208
  // Check for existence of Accesssion Number in xml_documents or xml_revisions
209
  // table.  We check xml_revisions because document may have been deleted, which 
210
  // will remove it from xml_documents, but a revision still exists.
211
  private boolean accNumberIsCurrent(String accNumber) throws SQLException {
212

    
213
    boolean hasCurrentAccNumber = false;
214
    DBConnection conn = null;
215
    int serialNumber = -1;
216

    
217
    try {
218
      PreparedStatement pstmt = null;
219
      //check out DBConnection
220
      conn=DBConnectionPool.getDBConnection("AccessionNumber.accNumberIsCurre");
221
      serialNumber=conn.getCheckOutSerialNumber();
222
      pstmt = conn.prepareStatement(
223
                "SELECT 'x' FROM xml_documents " +
224
                "WHERE docid = ?");
225
      pstmt.setString(1, accNumber);
226
      pstmt.execute();
227
      ResultSet rs = pstmt.getResultSet();
228
      hasCurrentAccNumber = rs.next();
229
      if(!hasCurrentAccNumber)
230
      {
231
        //need to look xml_revision table;
232
        pstmt = conn.prepareStatement(
233
            "SELECT 'x' FROM xml_revisions " +
234
            "WHERE docid = ?");
235
        pstmt.setString(1, accNumber);
236
        pstmt.execute();
237
        rs = pstmt.getResultSet();
238
        hasCurrentAccNumber = rs.next();
239
      }
240
      pstmt.close();
241

    
242
    } catch (SQLException e) {
243
      throw new SQLException(
244
          "Error on AccessionNumber.accNumberIsCurrent(String accNumber): " +
245
          e.getMessage());
246
    }
247
    finally
248
    {
249
      DBConnectionPool.returnDBConnection(conn, serialNumber);
250
    }
251

    
252
    return hasCurrentAccNumber;
253
  }
254

    
255
  // get the recent revision number for docid
256
  private String getLastRevision(String docid) throws SQLException
257
  {
258
    String rev = "";
259
    DBConnection conn = null;
260
    int serialNumber = -1;
261

    
262
    try {
263
      PreparedStatement pstmt = null;
264
      //check out DBConnection
265
      conn=DBConnectionPool.getDBConnection("AccessionNumber.getLastRevision");
266
      serialNumber=conn.getCheckOutSerialNumber();
267
      pstmt = conn.prepareStatement
268
              ("SELECT rev FROM xml_documents WHERE docid = ?");
269
      pstmt.setString(1, docid);
270
      pstmt.execute();
271

    
272
      ResultSet rs = pstmt.getResultSet();
273
      boolean hasRow = rs.next();
274
      rev = rs.getString(1);
275
      pstmt.close();
276

    
277
    } catch (SQLException e) {
278
      throw new SQLException(
279
      "Error on AccessionNumber.getLastRevision(): " + e.getMessage());
280
    }
281
    finally
282
    {
283
      DBConnectionPool.returnDBConnection(conn,serialNumber);
284
    }
285

    
286
    return rev;
287
  }
288

    
289
  /**
290
    * Get last revision number from database for a docid
291
    * The return value is integer because we want compare it to there new one
292
    * @param docid <sitecode>.<uniqueid> part of Accession Number
293
    */
294
  private int getLastRevisionNumber(String docId) throws SQLException
295
  {
296
    int rev = 1;
297
    DBConnection conn =null;
298
    int serialNumber = -1;
299

    
300
    try {
301
      PreparedStatement pStmt = null;
302
      //check out DBConnection
303
      conn=DBConnectionPool.getDBConnection("AccessionNumber.getLastRevisionN");
304
      serialNumber=conn.getCheckOutSerialNumber();
305

    
306
      pStmt = conn.prepareStatement
307
              ("SELECT rev FROM xml_documents WHERE docid = ? ");
308
      pStmt.setString(1, docId);
309
      pStmt.execute();
310

    
311
      ResultSet rs = pStmt.getResultSet();
312
      boolean hasRow = rs.next();
313
      if(hasRow)
314
      {
315
        rev = rs.getInt(1);
316
      }     
317
      pStmt.close();
318

    
319
    } catch (SQLException e) {
320
      throw new SQLException(
321
      "Error on AccessionNumber.getLastRevision(): " + e.getMessage());
322
    }
323
    finally
324
    {
325
      DBConnectionPool.returnDBConnection(conn,serialNumber);
326
    }
327
    return rev;
328
  }
329

    
330
  /**
331
   * returns the docid encoded in this accession number
332
   */
333
  public String getDocid() {
334

    
335
    return this.docid;
336
  }
337

    
338
  /**
339
   * returns the revision number encoded in this accession number
340
   */
341
  public String getRev()
342
  {
343
    return this.rev;
344
  }
345

    
346
}
(1-1/64)