Project

General

Profile

« Previous | Next » 

Revision 5282

Added by Matt Jones over 14 years ago

Added initial support for arbitrary string identifiers in metacat (referred to as a guid). The new identifier table is used to map arbitrary string identifiers to Metacat's current docid format (referred to as the localId). Added a new IdentifierManager class to manage this table, adding new mappings as objects are added to the system. Modified the MetacatTest service to utilize this mapping table to look up a localId from a guid. IdentiferManagerTest is working with these guids now, as is the MetacatTest service get() method, but other parts of the system are unaware of them (e.g., create, update, delete operations are unaware, and no mapping is created when new documents are created). As a consequence, the MetacatRestClientTest is not working (although it also had lots of hardcoded dependencies that need to be fixed as well).

View differences:

test/edu/ucsb/nceas/metacattest/IdentifierManagerTest.java
1
/**
2
 *  '$RCSfile$'
3
 *  Copyright: 2010 Regents of the University of California and the
4
 *             National Center for Ecological Analysis and Synthesis
5
 *
6
 *   '$Author: jones $'
7
 *     '$Date: 2010-02-03 17:58:12 -0900 (Wed, 03 Feb 2010) $'
8
 * '$Revision: 5211 $'
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.metacattest;
26

  
27
import java.sql.SQLException;
28

  
29
import edu.ucsb.nceas.MCTestCase;
30
import edu.ucsb.nceas.metacat.IdentifierManager;
31
import edu.ucsb.nceas.metacat.McdbDocNotFoundException;
32
import edu.ucsb.nceas.metacat.client.MetacatAuthException;
33
import edu.ucsb.nceas.metacat.client.MetacatInaccessibleException;
34
import edu.ucsb.nceas.metacat.database.DBConnectionPool;
35

  
36
public class IdentifierManagerTest extends MCTestCase {
37
    private String badGuid = "test:testIdThatDoesNotExist";
38
    
39
    /**
40
     * Initialize the connection to metacat, and insert a document to be 
41
     * used for testing with a known docid.
42
     */
43
    public void setUp() {
44
        
45
        metacatConnectionNeeded = true;
46
        try {
47
            DBConnectionPool pool = DBConnectionPool.getInstance();
48
        } catch (SQLException e2) {
49
            fail(e2.getMessage());
50
        }
51
        
52
        try {
53
            super.setUp();
54
        } catch (Exception e1) {
55
            fail(e1.getMessage());
56
        }
57
    }
58

  
59
    /** Test that IM instances can be created. */
60
    public void testGetInstance() {
61
        IdentifierManager im = IdentifierManager.getInstance();
62
        assertNotNull(im);
63
    }
64

  
65
    /** Test that known LocalId's can be looked up from GUIDs. */
66
    public void testGetLocalId() {
67
        IdentifierManager im = IdentifierManager.getInstance();
68
        String docid = insertTestDocument();
69
        String goodGuid = "test:" + docid;
70
        im.createMapping(goodGuid, docid);
71
        String idReturned;
72
        try {
73
            idReturned = im.getLocalId(goodGuid);
74
            assertEquals(docid, idReturned);
75
        } catch (McdbDocNotFoundException e) {
76
            fail(e.getMessage());
77
        }
78
    }
79
    
80
    /** Test that unknown LocalId's return the proper exception. */
81
    public void testGetLocalIdNotFound() {
82
        IdentifierManager im = IdentifierManager.getInstance();
83
        String idReturned;
84
        try {
85
            idReturned = im.getLocalId(badGuid);
86
            fail("Failed: getLocalID() should have returned an document not " + 
87
                 "found exception but did not.");
88
        } catch (McdbDocNotFoundException e) {
89
            assertNotNull(e);
90
        }
91
    }
92
    
93
    /** 
94
     * Test that an identifier is present in the system when it should
95
     *  be, and that it is not present when it shouldn't be. 
96
     */
97
    public void testIdentifierExists() {
98
        IdentifierManager im = IdentifierManager.getInstance();
99
        String docid = insertTestDocument();
100
        im.createMapping("test:"+docid, docid);
101
        String goodGuid = "test:" + docid;
102
        assertTrue(im.identifierExists(goodGuid));
103
        assertFalse(im.identifierExists(badGuid));
104
    }
105
    
106
    /**
107
     * Test that we are able to create mappings from guids to localIds, and that
108
     * improperly formatted docids generate the proper exceptions.
109
     */
110
    public void testCreateMapping() {
111
        IdentifierManager im = IdentifierManager.getInstance();
112
        String docid = insertTestDocument();
113
        im.createMapping("test:"+docid, docid);
114
        try {
115
            assertEquals(im.getLocalId("test:"+docid), docid);
116
        } catch (McdbDocNotFoundException e) {
117
            fail("createMapping failed to create proper localId from guid.");
118
        }
119
    }
120

  
121
    /** Insert a test document, returning the docid that was used. */
122
    private String insertTestDocument() {
123
        String accessBlock = getAccessBlock("public", true, true,
124
                false, false, false);
125
        String emldoc = getTestEmlDoc("Test identifier manager", EML2_1_0, null,
126
                null, "http://fake.example.com/somedata", null,
127
                accessBlock, null, null,
128
                null, null);
129
        String docid = generateDocumentId() + ".1";
130
        try {
131
            m.login(username, password);
132
            String response = insertDocumentId(docid, emldoc, true, false);
133
        } catch (MetacatAuthException e) {
134
            fail(e.getMessage());
135
        } catch (MetacatInaccessibleException e) {
136
            fail(e.getMessage());
137
        }
138
        return docid;
139
    }
140
}
0 141

  
test/edu/ucsb/nceas/metacattest/restservice/MetacatRestClientTest.java
78 78
    private static final String DOCID = "docid";
79 79
    private static final String DATAID = "dataid";
80 80
    
81
    private static final String public_doc_id = "serhan.3.1";
81
    private static final String public_doc_id = "doi:12345.5/playing/in/dirt/rev1";
82 82
    private static final String authorized_doc_id = "serhan.4.2";
83 83
    private static final String notexisting_doc_id = "serhan.1.1";
84 84
    private static final String ecogridQueryFile= "test/restfiles/ecogrid_query.xml";
src/edu/ucsb/nceas/metacat/restservice/ResourceHandler.java
36 36
import org.apache.log4j.Logger;
37 37

  
38 38
import edu.ucsb.nceas.metacat.DBUtil;
39
import edu.ucsb.nceas.metacat.IdentifierManager;
40
import edu.ucsb.nceas.metacat.McdbDocNotFoundException;
39 41
import edu.ucsb.nceas.metacat.MetacatHandler;
40 42
import edu.ucsb.nceas.metacat.util.RequestUtil;
41 43
import edu.ucsb.nceas.metacat.util.SessionData;
......
414 416
    /**
415 417
     * Earthgrid API > Query Service > Get Function : calls MetacatHandler > handleReadAction
416 418
     * 
417
     * @param objectId ID of data object to be read
419
     * @param guid ID of data object to be read
418 420
     */
419
    private void getObject(String objectId) {
420
        params.put("docid", new String[] { objectId });
421
    private void getObject(String guid) {
422
        // Look up the localId for this global identifier
423
        IdentifierManager im = IdentifierManager.getInstance();
424
        String localId = "";
425
        try {
426
            localId = im.getLocalId(guid);
427
        } catch (McdbDocNotFoundException e) {
428
            // Need to return the proper DataONE exception
429
        }
430
        
431
        // Now use that localId to read the object and return it
432
        params.put("docid", new String[] { localId });
421 433
        handler.handleReadAction(params, request, response, username, password,
422 434
                groupNames);
423 435
    }
......
501 513

  
502 514
        if (action.equals(FUNCTION_NAME_UPDATE)
503 515
                || action.equals(FUNCTION_NAME_INSERT)) {
516
            //
517
            // WARNING: This should not be a Reader if we are inserting data
518
            // Nor should it be read into a String
519
            // so this seems like a latent bug to me (MBJ; 16Mar2010)
504 520
            BufferedReader reader = request.getReader();
505 521
            StringBuffer buffer = new StringBuffer();
506 522
            String line = null;
src/edu/ucsb/nceas/metacat/client/rest/MetacatRest.java
54 54
	 */
55 55

  
56 56
	/** API OBJECTS Resource which handles with document operations*/
57
	public static final String RESOURCE_OBJECTS = "objects";
57
	public static final String RESOURCE_OBJECTS = "object";
58 58
	/** API SESSION Resource which handles with user session operations*/
59 59
	public static final String RESOURCE_SESSION = "session";
60 60
	/** API IDENTIFIER Resource which controls object unique identifier operations*/
src/edu/ucsb/nceas/metacat/IdentifierManager.java
1
/**
2
 *  '$RCSfile$'
3
 *  Copyright: 2010 Regents of the University of California and the
4
 *             National Center for Ecological Analysis and Synthesis
5
 *
6
 *   '$Author: jones $'
7
 *     '$Date: 2010-02-03 17:58:12 -0900 (Wed, 03 Feb 2010) $'
8
 * '$Revision: 5211 $'
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;
26

  
27
import java.sql.PreparedStatement;
28
import java.sql.ResultSet;
29
import java.sql.SQLException;
30

  
31
import org.apache.log4j.Logger;
32

  
33
import edu.ucsb.nceas.metacat.database.DBConnection;
34
import edu.ucsb.nceas.metacat.database.DBConnectionPool;
35

  
36
/**
37
 * Manage the relationship between Metacat local identifiers (LocalIDs) that are
38
 * codified as the (docid, rev) pair with globally uniqe string identifiers
39
 * (GUIDs) that are opaque strings.  This class provides methods to manage these
40
 * identifiers, and to search for and look up LocalIDs based on their GUID and
41
 * vice versa. IdentifierManager is a singleton.
42
 * 
43
 * @author Matthew Jones
44
 */
45
public class IdentifierManager {
46
    
47
    /**
48
     * The single instance of the manager that is always returned.
49
     */
50
    private static IdentifierManager self = null;
51
    private Logger logMetacat = Logger.getLogger(EventLog.class);
52

  
53
    /**
54
     * A private constructor that initializes the class when getInstance() is
55
     * called.
56
     */
57
    private IdentifierManager()
58
    {
59
    }
60

  
61
    /**
62
     * Return the single instance of the manager after initializing it if it
63
     * wasn't previously initialized.
64
     * 
65
     * @return the single IdentifierManager instance
66
     */
67
    public static IdentifierManager getInstance()
68
    {
69
        if (self == null) {
70
            self = new IdentifierManager();
71
        }
72
        return self;
73
    }
74
    
75
    /**
76
     * Lookup a GUID from the database, and return the associated LocalID. If
77
     * the identifier is not found, throw an exception.
78
     * 
79
     * @param guid the global identifier to look up
80
     * @return String containing the corresponding LocalId
81
     * @throws McdbDocNotFoundException if the identifier is not found
82
     */
83
    public String getLocalId(String guid) throws McdbDocNotFoundException
84
    {
85
        String db_guid = "";
86
        String docid = "";
87
        int rev = 0;
88
        
89
        String query = "select guid, docid, rev from identifier where guid = ?";
90
        
91
        DBConnection dbConn = null;
92
        int serialNumber = -1;
93
        try {
94
            // Get a database connection from the pool
95
            dbConn = DBConnectionPool.getDBConnection("Identifier.getLocalId");
96
            serialNumber = dbConn.getCheckOutSerialNumber();
97
            
98
            // Execute the insert statement
99
            PreparedStatement stmt = dbConn.prepareStatement(query);
100
            stmt.setString(1, guid);
101
            ResultSet rs = stmt.executeQuery();
102
            if (rs.next()) {
103
                db_guid = rs.getString(1);
104
                docid = rs.getString(2);
105
                rev = rs.getInt(3);
106
                assert(db_guid.equals(guid));
107
            } else {
108
                throw new McdbDocNotFoundException("Document not found:" + guid);
109
            }
110
            stmt.close();
111
        } catch (SQLException e) {
112
            logMetacat.error("Error while looking up the local identifier: " 
113
                    + e.getMessage());
114
        } finally {
115
            // Return database connection to the pool
116
            DBConnectionPool.returnDBConnection(dbConn, serialNumber);
117
        }
118
        return docid + "." + rev;
119
    }
120
    
121
    /**
122
     * Determine if an identifier exists already, returning true if so.
123
     * 
124
     * @param guid the global identifier to look up
125
     * @return boolean true if the identifier exists
126
     */
127
    public boolean identifierExists(String guid)
128
    {
129
        boolean idExists = false;
130
        try {
131
            String id = getLocalId(guid);
132
            if (id != null) {
133
                idExists = true;
134
            }
135
        } catch (McdbDocNotFoundException e) {
136
            idExists = false;
137
        }
138
        return idExists;
139
    }
140
    
141
    /**
142
     * Create a mapping between two identifiers, one representing an 
143
     * unconstrained, globally unique string (guid), and one a localId 
144
     * in the Metacat docid format (scope.id.revision). 
145
     * This mapping allows one to find the global id (guid) from the localId.
146
     * 
147
     * @param guid the global string identifier to be mapped
148
     * @param localId the local identifier to be mapped
149
     */
150
    public void createMapping(String guid, String localId)
151
    {   
152
        int serialNumber = -1;
153
        DBConnection dbConn = null;
154
        try {
155

  
156
            // Parse the localId into scope and rev parts
157
            AccessionNumber acc = new AccessionNumber(localId, "NOACTION");
158
            String docid = acc.getDocid();
159
            int rev = (new Integer(acc.getRev()).intValue());
160

  
161
            // Get a database connection from the pool
162
            dbConn = 
163
                DBConnectionPool.getDBConnection("Identifier.createMapping");
164
            serialNumber = dbConn.getCheckOutSerialNumber();
165

  
166
            // Execute the insert statement
167
            String query = "insert into identifier (guid, docid, rev) values (?, ?, ?)";            
168
            PreparedStatement stmt = dbConn.prepareStatement(query);
169
            stmt.setString(1, guid);
170
            stmt.setString(2, docid);
171
            stmt.setInt(3, rev);
172
            int rows = stmt.executeUpdate();
173

  
174
            stmt.close();
175
        } catch (SQLException e) {
176
            logMetacat.error("SQL error while creating a mapping to the local identifier: " 
177
                    + e.getMessage());
178
        } catch (NumberFormatException e) {
179
            logMetacat.error("NumberFormat error while creating a mapping to the local identifier: " 
180
                    + e.getMessage());
181
        } catch (AccessionNumberException e) {
182
            logMetacat.error("AccessionNumber error while creating a mapping to the local identifier: " 
183
                    + e.getMessage());
184
        } finally {
185
            // Return database connection to the pool
186
            DBConnectionPool.returnDBConnection(dbConn, serialNumber);
187
        }
188
    }
189
}
0 190

  
src/edu/ucsb/nceas/metacat/McdbDocNotFoundException.java
37 37
  // String sto stroe which docid couldn't find
38 38
  private String unfoundDocId = null;
39 39
  private String unfoundRevision = null;
40
  
40 41
  /**
41 42
   * Create a new McdbDocNotFoundException.
42 43
   */
......
59 60
  }
60 61

  
61 62
  /**
63
   * Create a new exception but only set the message.
64
   * @param message a message giving information about why the document was not found
65
   */
66
  public McdbDocNotFoundException(String message) {
67
      super(message);
68
  }
69
  
70
  /**
62 71
   * Create a new McdbDocNotFoundException.
63 72
   *
64 73
   * @param e The exception to tunnel inside this exception

Also available in: Unified diff