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 349 jones
 *    Release: @release@
9 145 bojilova
 *
10 203 jones
 *   '$Author$'
11
 *     '$Date$'
12
 * '$Revision$'
13 145 bojilova
 */
14
15
package edu.ucsb.nceas.metacat;
16
17
import java.net.*;
18
import java.sql.*;
19
20 147 bojilova
/**
21 185 jones
 * A class that generates an Accession Number and will check a submitted
22
 * accession number for uniqueness and register it into the db connection
23 147 bojilova
 */
24 145 bojilova
public class AccessionNumber  {
25
26 171 bojilova
    /**
27 185 jones
     * Get an accession number from the user, check it for uniqueness
28
     * and register it into new db connection. If no accession number is
29
     * provided by the user, generate one from the database and return it.
30
     *
31 171 bojilova
     * @param accNumber - accession # if provided or null if not
32
     * @param action - INSERT, UPDATE or DELETE.
33
     * When "INSERT" and accession # provided is not unique, get next one.
34
     * If it is unique, use it.
35
     * When "INSERT" and accession # is null, get a new one.
36
     * When "UPDATE", accession # is required.
37
     * When "DELETE", accession # is required.
38
     */
39 421 bojilova
    public String generate (String accNumber, String action)
40 203 jones
        throws AccessionNumberException, SQLException, ClassNotFoundException
41 160 bojilova
    {
42 145 bojilova
43 160 bojilova
        String globalName = null;
44
        String localId = null;
45
46 185 jones
        // Open a connection to the database
47
        MetaCatUtil   util = new MetaCatUtil();
48 160 bojilova
49 185 jones
        String defaultGlobalName = util.getOption("defaultGlobalName");
50
        String sep = util.getOption("accNumberSeparator");
51 160 bojilova
52
        try {
53
            // Open a new connection to the database
54 185 jones
            Connection conn = util.openDBConnection();
55 160 bojilova
            conn.setAutoCommit(true);
56
57
            // split the acc # in 2 parts - global name & local id
58
            if ( accNumber != null ) {
59
                globalName = getGlobalName(accNumber, sep);
60
                localId = getLocalId(accNumber, sep);
61
            }
62
63
            // register unique acc #
64 203 jones
            if ( action.equals("INSERT")) {
65 160 bojilova
                if ( accNumber == null )
66 203 jones
                  return put(conn, defaultGlobalName, null, sep);
67 160 bojilova
                else
68 203 jones
                  return put(conn, globalName, localId, sep);
69
            } else if ( action.equals("UPDATE") || action.equals("DELETE")) {
70
                if ( accNumber == null ) {
71
                  throw (new AccessionNumberException("Accession number is " +
72
                         "required."));
73
                } else if (!accNumberIsCurrent(conn, accNumber)) {
74
                  throw (new AccessionNumberException("Document " +
75
                         "not found for accession #: " + accNumber));
76
                } else {
77
                  return (globalName + sep + localId);
78
                }
79
            }
80
81 171 bojilova
            conn.close();
82 160 bojilova
83 203 jones
        } catch (StringIndexOutOfBoundsException siobe) {
84
            MetaCatUtil.debugMessage(
85
                       "Error on AccessionNumber.generate(): " +
86
                       siobe.getMessage());
87
            throw (new AccessionNumberException("Accession number invalid, " +
88
                   "expecting character \'" + sep + "'."));
89 160 bojilova
        } catch (SQLException e) {
90 204 jones
            System.err.println(
91 168 jones
                       "Error on AccessionNumber.genAccessionNumber(): " +
92
                       e.getMessage());
93 160 bojilova
            throw e;
94
        }
95
96 203 jones
        throw (new AccessionNumberException("Fatal Error in " +
97
               "accession number generation: "));
98 145 bojilova
    }
99 160 bojilova
100 171 bojilova
    /** put unique accession # into db connection */
101 421 bojilova
    private String put (Connection conn, String globalName,
102 168 jones
                String localId, String sep)
103 160 bojilova
                throws SQLException
104
    {
105
106
        Integer l = null;
107
        try {
108
            if ( localId == null )
109
                l = new Integer(get(conn, globalName) + 1);
110 203 jones
            else if ( accNumberUsed(conn, globalName, localId) )
111 160 bojilova
                l = new Integer(get(conn, globalName) + 1);
112
            else
113
                l = new Integer(localId);
114
115
            // insert globalName & l
116
            PreparedStatement pstmt;
117 168 jones
            pstmt = conn.prepareStatement(
118
                    "INSERT INTO xml_acc_numbers (global_name, local_id) " +
119
                    "VALUES (?, ?)");
120 160 bojilova
            pstmt.setString(1,globalName);
121
            pstmt.setString(2,l.toString());
122
            pstmt.execute();
123
124 171 bojilova
            pstmt.close();
125
126 160 bojilova
        } catch (SQLException e) {
127 204 jones
            System.err.println(
128 168 jones
                   "Error on AccessionNumber.put(conn, globalName, localId): "
129
                   + e.getMessage());
130 160 bojilova
            throw e;
131
        }
132
        return globalName + sep + l;
133
    }
134
135 203 jones
    /** check for existence of Accesssion Number xml_acc_numbers table */
136 421 bojilova
    private boolean accNumberUsed(Connection conn, String globalName,
137 203 jones
                String localId) throws SQLException {
138 145 bojilova
139 203 jones
      boolean hasAccNumber = false;
140 145 bojilova
141 203 jones
      try {
142
        PreparedStatement pstmt;
143
        pstmt = conn.prepareStatement(
144
                "SELECT 'x' FROM xml_acc_numbers " +
145
                "WHERE global_name LIKE ? AND local_id = ?");
146
        pstmt.setString(1,globalName);
147
        pstmt.setString(2,localId);
148
        pstmt.execute();
149
        ResultSet rs = pstmt.getResultSet();
150
        hasAccNumber = rs.next();
151
        pstmt.close();
152 145 bojilova
153 203 jones
      } catch (SQLException e) {
154 204 jones
        System.err.println("Error on AccessionNumber.unique(globalName, " +
155 203 jones
                           "localId): " + e.getMessage());
156
        throw e;
157
      }
158 145 bojilova
159 203 jones
      return hasAccNumber;
160 145 bojilova
    }
161
162 203 jones
    /** check for existence of Accesssion Number in xml_documents table */
163 421 bojilova
    private boolean accNumberIsCurrent(
164 203 jones
                Connection conn, String accNumber) throws SQLException {
165
166
      boolean hasCurrentAccNumber = false;
167
168
      try {
169
        PreparedStatement pstmt;
170
        pstmt = conn.prepareStatement(
171
                "SELECT 'x' FROM xml_documents " +
172
                "WHERE docid LIKE ?");
173
        pstmt.setString(1, accNumber);
174
        pstmt.execute();
175
        ResultSet rs = pstmt.getResultSet();
176
        hasCurrentAccNumber = rs.next();
177
        pstmt.close();
178
179
      } catch (SQLException e) {
180 204 jones
        System.err.println(
181 203 jones
          "Error on AccessionNumber.accNumberIsCurrent(globalName, " +
182
          "localId): " + e.getMessage());
183
        throw e;
184
      }
185
      return hasCurrentAccNumber;
186
    }
187
188 171 bojilova
    /** get the last in order local ID by a given global name */
189 421 bojilova
    private int get (Connection conn, String globalName)
190 160 bojilova
                throws SQLException
191
    {
192 145 bojilova
        try {
193
            PreparedStatement pstmt;
194 168 jones
            pstmt = conn.prepareStatement(
195
                    "SELECT max(local_id) FROM xml_acc_numbers " +
196
                    "WHERE global_name LIKE ?");
197 145 bojilova
            pstmt.setString(1,globalName);
198
            pstmt.execute();
199
            ResultSet rs = pstmt.getResultSet();
200
            boolean hasLocalId = rs.next();
201
202
            if (hasLocalId)
203
                return rs.getInt(1);
204
205
            pstmt.close();
206
        } catch (SQLException e) {
207 204 jones
            System.err.println(
208 168 jones
                   "Error on AccessionNumber.get(): " + e.getMessage());
209 160 bojilova
            throw e;
210 145 bojilova
        }
211
212 160 bojilova
        return 0;
213 145 bojilova
    }
214
215
216
    // get the global part of the accession number
217 421 bojilova
    private String getGlobalName (String accNumber, String sep)
218 145 bojilova
        throws StringIndexOutOfBoundsException {
219
220 160 bojilova
        return accNumber.substring(0, accNumber.lastIndexOf(sep));
221 145 bojilova
    }
222
223
    // get the local part of the accession number
224 421 bojilova
    private String getLocalId (String accNumber, String sep)
225 145 bojilova
        throws StringIndexOutOfBoundsException {
226
227 160 bojilova
        return accNumber.substring(accNumber.lastIndexOf(sep)+1);
228 145 bojilova
    }
229 203 jones
}
230 145 bojilova
231 203 jones
/**
232
 * '$Log$
233 421 bojilova
 * 'Revision 1.11  2000/08/14 20:53:33  jones
234
 * 'Added "release" keyword to all metacat source files so that the release
235
 * 'number will be evident in software distributions.
236
 * '
237 349 jones
 * 'Revision 1.10  2000/06/27 04:31:07  jones
238
 * 'Fixed bugs associated with the new UPDATE and DELETE functions of
239
 * 'DBWriter.  There were problematic interactions between some static
240
 * 'variables used in DBEntityResolver and the way in which the
241
 * 'Servlet objects are re-used across multiple client invocations.
242
 * '
243
 * 'Generally cleaned up error reporting.  Now all errors and success
244
 * 'results are reported as XML documents from MetaCatServlet.  Need
245
 * 'to make the command line tools do the same.
246
 * '
247 204 jones
 * 'Revision 1.9  2000/06/26 10:35:04  jones
248
 * 'Merged in substantial changes to DBWriter and associated classes and to
249
 * 'the MetaCatServlet in order to accomodate the new UPDATE and DELETE
250
 * 'functions.  The command line tools and the parameters for the
251
 * 'servlet have changed substantially.
252
 * '
253 203 jones
 * 'Revision 1.8.2.5  2000/06/26 08:38:01  jones
254
 * 'Added DELETE feature to DBWriter.  Now takes an action "DELETE" and a
255
 * 'docid and will move the record from the xml_documents table to the
256
 * 'xml_revisions table.
257
 * 'Modified option parsing to support option symbols on command line.
258
 * '
259
 * 'Revision 1.8.2.4  2000/06/25 23:11:40  jones
260
 * 'Documentation update
261
 * '
262
 * 'Revision 1.8.2.3  2000/06/25 23:08:31  jones
263
 * 'Minor change to excpetion handling
264
 * ''
265
 */