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