KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > dspace > content > MetadataSchema


1 /*
2  * MetadataSchema.java
3  *
4  * Version: $Revision: 1.2 $
5  *
6  * Date: $Date: 2006/05/26 14:17:01 $
7  *
8  * Copyright (c) 2002-2005, Hewlett-Packard Company and Massachusetts
9  * Institute of Technology. All rights reserved.
10  *
11  * Redistribution and use in source and binary forms, with or without
12  * modification, are permitted provided that the following conditions are
13  * met:
14  *
15  * - Redistributions of source code must retain the above copyright
16  * notice, this list of conditions and the following disclaimer.
17  *
18  * - Redistributions in binary form must reproduce the above copyright
19  * notice, this list of conditions and the following disclaimer in the
20  * documentation and/or other materials provided with the distribution.
21  *
22  * - Neither the name of the Hewlett-Packard Company nor the name of the
23  * Massachusetts Institute of Technology nor the names of their
24  * contributors may be used to endorse or promote products derived from
25  * this software without specific prior written permission.
26  *
27  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
28  * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
29  * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
30  * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
31  * HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
32  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
33  * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
34  * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
35  * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR
36  * TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE
37  * USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
38  * DAMAGE.
39  */

40 package org.dspace.content;
41
42 import java.io.IOException JavaDoc;
43 import java.sql.Connection JavaDoc;
44 import java.sql.PreparedStatement JavaDoc;
45 import java.sql.ResultSet JavaDoc;
46 import java.sql.SQLException JavaDoc;
47 import java.util.HashMap JavaDoc;
48 import java.util.ArrayList JavaDoc;
49 import java.util.List JavaDoc;
50
51 import org.apache.log4j.Logger;
52 import org.dspace.authorize.AuthorizeException;
53 import org.dspace.authorize.AuthorizeManager;
54 import org.dspace.core.Context;
55 import org.dspace.core.LogManager;
56 import org.dspace.storage.rdbms.DatabaseManager;
57 import org.dspace.storage.rdbms.TableRow;
58 import org.dspace.storage.rdbms.TableRowIterator;
59
60 /**
61  * Class representing a schema in DSpace.
62  * <p>
63  * The schema object exposes a name which can later be used to generate
64  * namespace prefixes in RDF or XML, e.g. the core DSpace Dublin Core schema
65  * would have a name of <code>'dc'</code>.
66  * </p>
67  *
68  * @author Martin Hald
69  * @version $Revision: 1.2 $
70  * @see org.dspace.content.MetadataValue, org.dspace.content.MetadataField
71  */

72 public class MetadataSchema
73 {
74     /** log4j logger */
75     private static Logger log = Logger.getLogger(MetadataSchema.class);
76
77     /** Numeric Identifier of built-in Dublin Core schema. */
78     public static final int DC_SCHEMA_ID = 1;
79
80     /** Short Name of built-in Dublin Core schema. */
81     public static final String JavaDoc DC_SCHEMA = "dc";
82
83     /** The row in the table representing this type */
84     private TableRow row;
85
86     private int schemaID;
87     private String JavaDoc namespace;
88     private String JavaDoc name;
89
90     // cache of schema by ID (Integer)
91
private static HashMap JavaDoc id2schema = null;
92
93     // cache of schema by short name
94
private static HashMap JavaDoc name2schema = null;
95
96
97     /**
98      * Default constructor.
99      */

100     public MetadataSchema()
101     {
102     }
103
104     /**
105      * Object constructor.
106      *
107      * @param schemaID database key ID number
108      * @param namespace XML namespace URI
109      * @param name short name of schema
110      */

111     public MetadataSchema(int schemaID, String JavaDoc namespace, String JavaDoc name)
112     {
113         this.schemaID = schemaID;
114         this.namespace = namespace;
115         this.name = name;
116     }
117
118     /**
119      * Immutable object constructor for creating a new schema.
120      *
121      * @param namespace XML namespace URI
122      * @param name short name of schema
123      */

124     public MetadataSchema(String JavaDoc namespace, String JavaDoc name)
125     {
126         this.namespace = namespace;
127         this.name = name;
128     }
129
130     /**
131      * Constructor for loading the metadata schema from the database.
132      *
133      * @param row table row object from which to populate this schema.
134      */

135     public MetadataSchema(TableRow row)
136     {
137         if (row != null)
138         {
139             this.schemaID = row.getIntColumn("metadata_schema_id");
140             this.namespace = row.getStringColumn("namespace");
141             this.name = row.getStringColumn("short_id");
142             this.row = row;
143         }
144     }
145
146     /**
147      * Get the schema namespace.
148      *
149      * @return namespace String
150      */

151     public String JavaDoc getNamespace()
152     {
153         return namespace;
154     }
155
156     /**
157      * Set the schema namespace.
158      *
159      * @param namespace XML namespace URI
160      */

161     public void setNamespace(String JavaDoc namespace)
162     {
163         this.namespace = namespace;
164     }
165
166     /**
167      * Get the schema name.
168      *
169      * @return name String
170      */

171     public String JavaDoc getName()
172     {
173         return name;
174     }
175
176     /**
177      * Set the schema name.
178      *
179      * @param name short name of schema
180      */

181     public void setName(String JavaDoc name)
182     {
183         this.name = name;
184     }
185
186     /**
187      * Get the schema record key number.
188      *
189      * @return schema record key
190      */

191     public int getSchemaID()
192     {
193         return schemaID;
194     }
195
196     /**
197      * Creates a new metadata schema in the database, out of this object.
198      *
199      * @param context
200      * DSpace context object
201      * @throws SQLException
202      * @throws AuthorizeException
203      * @throws NonUniqueMetadataException
204      */

205     public void create(Context context) throws SQLException JavaDoc,
206             AuthorizeException, NonUniqueMetadataException
207     {
208         // Check authorisation: Only admins may create metadata schemas
209
if (!AuthorizeManager.isAdmin(context))
210         {
211             throw new AuthorizeException(
212                     "Only administrators may modify the metadata registry");
213         }
214
215         // Ensure the schema name is unique
216
if (!uniqueShortName(context, name))
217         {
218             throw new NonUniqueMetadataException("Please make the name " + name
219                     + " unique");
220         }
221         
222         // Ensure the schema namespace is unique
223
if (!uniqueNamespace(context, namespace))
224         {
225             throw new NonUniqueMetadataException("Please make the namespace " + namespace
226                     + " unique");
227         }
228
229
230         // Create a table row and update it with the values
231
row = DatabaseManager.create(context, "MetadataSchemaRegistry");
232         row.setColumn("namespace", namespace);
233         row.setColumn("short_id", name);
234         DatabaseManager.update(context, row);
235
236         // invalidate our fast-find cache.
237
decache();
238
239         // Remember the new row number
240
this.schemaID = row.getIntColumn("metadata_schema_id");
241
242         log
243                 .info(LogManager.getHeader(context, "create_metadata_schema",
244                         "metadata_schema_id="
245                                 + row.getIntColumn("metadata_schema_id")));
246     }
247
248     /**
249      * Get the schema object corresponding to this namespace URI.
250      *
251      * @param context DSpace context
252      * @param namespace namespace URI to match
253      * @return metadata schema object or null if none found.
254      * @throws SQLException
255      */

256     public static MetadataSchema findByNamespace(Context context,
257             String JavaDoc namespace) throws SQLException JavaDoc
258     {
259         // Grab rows from DB
260
TableRowIterator tri = DatabaseManager.queryTable(context,"MetadataSchemaRegistry",
261                 "SELECT * FROM MetadataSchemaRegistry WHERE namespace= ? ",
262                 namespace);
263
264         TableRow row = null;
265         if (tri.hasNext())
266         {
267             row = tri.next();
268         }
269
270         // close the TableRowIterator to free up resources
271
tri.close();
272
273         if (row == null)
274         {
275             return null;
276         }
277         else
278         {
279             return new MetadataSchema(row);
280         }
281     }
282
283     /**
284      * Update the metadata schema in the database.
285      *
286      * @param context DSpace context
287      * @throws SQLException
288      * @throws AuthorizeException
289      * @throws NonUniqueMetadataException
290      */

291     public void update(Context context) throws SQLException JavaDoc,
292             AuthorizeException, NonUniqueMetadataException
293     {
294         // Check authorisation: Only admins may update the metadata registry
295
if (!AuthorizeManager.isAdmin(context))
296         {
297             throw new AuthorizeException(
298                     "Only administrators may modify the metadata registry");
299         }
300
301         // Ensure the schema name is unique
302
if (!uniqueShortName(context, name))
303         {
304             throw new NonUniqueMetadataException("Please make the name " + name
305                     + " unique");
306         }
307
308         // Ensure the schema namespace is unique
309
if (!uniqueNamespace(context, namespace))
310         {
311             throw new NonUniqueMetadataException("Please make the namespace " + namespace
312                     + " unique");
313         }
314         
315         row.setColumn("namespace", getNamespace());
316         row.setColumn("short_id", getName());
317         DatabaseManager.update(context, row);
318
319         decache();
320
321         log.info(LogManager.getHeader(context, "update_metadata_schema",
322                 "metadata_schema_id=" + getSchemaID() + "namespace="
323                         + getNamespace() + "name=" + getName()));
324     }
325
326     /**
327      * Delete the metadata schema.
328      *
329      * @param context DSpace context
330      * @throws SQLException
331      * @throws AuthorizeException
332      */

333     public void delete(Context context) throws SQLException JavaDoc, AuthorizeException
334     {
335         // Check authorisation: Only admins may create DC types
336
if (!AuthorizeManager.isAdmin(context))
337         {
338             throw new AuthorizeException(
339                     "Only administrators may modify the metadata registry");
340         }
341
342         log.info(LogManager.getHeader(context, "delete_metadata_schema",
343                 "metadata_schema_id=" + getSchemaID()));
344
345         DatabaseManager.delete(context, row);
346     }
347
348     /**
349      * Return all metadata schemas.
350      *
351      * @param context DSpace context
352      * @return array of metadata schemas
353      * @throws SQLException
354      */

355     public static MetadataSchema[] findAll(Context context) throws SQLException JavaDoc
356     {
357         List JavaDoc schemas = new ArrayList JavaDoc();
358
359         // Get all the metadataschema rows
360
TableRowIterator tri = DatabaseManager.queryTable(context, "MetadataSchemaRegistry",
361                         "SELECT * FROM MetadataSchemaRegistry ORDER BY metadata_schema_id");
362
363         // Make into DC Type objects
364
while (tri.hasNext())
365         {
366             schemas.add(new MetadataSchema(tri.next()));
367         }
368         // close the TableRowIterator to free up resources
369
tri.close();
370
371         // Convert list into an array
372
MetadataSchema[] typeArray = new MetadataSchema[schemas.size()];
373         return (MetadataSchema[]) schemas.toArray(typeArray);
374     }
375
376     /**
377      * Return true if and only if the passed name appears within the allowed
378      * number of times in the current schema.
379      *
380      * @param context DSpace context
381      * @param namespace namespace URI to match
382      * @return true of false
383      * @throws SQLException
384      */

385     private boolean uniqueNamespace(Context context, String JavaDoc namespace)
386             throws SQLException JavaDoc
387     {
388         Connection JavaDoc con = context.getDBConnection();
389         TableRow reg = DatabaseManager.row("MetadataSchemaRegistry");
390         
391         String JavaDoc query = "SELECT COUNT(*) FROM " + reg.getTable() + " " +
392                 "WHERE metadata_schema_id != ? " +
393                 "AND namespace= ? ";
394         PreparedStatement JavaDoc statement = con.prepareStatement(query);
395         statement.setInt(1,schemaID);
396         statement.setString(2,namespace);
397         
398         ResultSet JavaDoc rs = statement.executeQuery();
399
400         int count = 0;
401         if (rs.next())
402         {
403             count = rs.getInt(1);
404         }
405
406         return (count == 0);
407     }
408
409     /**
410      * Return true if and only if the passed name is unique.
411      *
412      * @param context DSpace context
413      * @param name short name of schema
414      * @return true of false
415      * @throws SQLException
416      */

417     private boolean uniqueShortName(Context context, String JavaDoc name)
418             throws SQLException JavaDoc
419     {
420         Connection JavaDoc con = context.getDBConnection();
421         TableRow reg = DatabaseManager.row("MetadataSchemaRegistry");
422         
423         String JavaDoc query = "SELECT COUNT(*) FROM " + reg.getTable() + " " +
424                 "WHERE metadata_schema_id != ? " +
425                 "AND short_id = ? ";
426         
427         PreparedStatement JavaDoc statement = con.prepareStatement(query);
428         statement.setInt(1,schemaID);
429         statement.setString(2,name);
430         
431         ResultSet JavaDoc rs = statement.executeQuery();
432
433         int count = 0;
434         if (rs.next())
435         {
436             count = rs.getInt(1);
437         }
438
439         return (count == 0);
440     }
441
442     /**
443      * Get the schema corresponding with this numeric ID.
444      * The ID is a database key internal to DSpace.
445      *
446      * @param context
447      * context, in case we need to read it in from DB
448      * @param id
449      * the schema ID
450      * @return the metadata schema object
451      * @throws SQLException
452      */

453     public static MetadataSchema find(Context context, int id)
454             throws SQLException JavaDoc
455     {
456         initCache(context);
457         Integer JavaDoc iid = new Integer JavaDoc(id);
458
459         // sanity check
460
if (!id2schema.containsKey(iid))
461             return null;
462
463         return (MetadataSchema) id2schema.get(iid);
464     }
465
466     /**
467      * Get the schema corresponding with this short name.
468      *
469      * @param context
470      * context, in case we need to read it in from DB
471      * @param shortName
472      * the short name for the schema
473      * @return the metadata schema object
474      * @throws SQLException
475      */

476     public static MetadataSchema find(Context context, String JavaDoc shortName)
477         throws SQLException JavaDoc
478     {
479         // If we are not passed a valid schema name then return
480
if (shortName == null)
481             return null;
482
483         initCache(context);
484
485         if (!name2schema.containsKey(shortName))
486             return null;
487
488         return (MetadataSchema) name2schema.get(shortName);
489     }
490
491     // invalidate the cache e.g. after something modifies DB state.
492
private static void decache()
493     {
494         id2schema = null;
495         name2schema = null;
496     }
497
498     // load caches if necessary
499
private static void initCache(Context context) throws SQLException JavaDoc
500     {
501         if (id2schema != null && name2schema != null)
502             return;
503
504         log.info("Loading schema cache for fast finds");
505         id2schema = new HashMap JavaDoc();
506         name2schema = new HashMap JavaDoc();
507
508         TableRowIterator tri = DatabaseManager.queryTable(context,"MetadataSchemaRegistry",
509                 "SELECT * from MetadataSchemaRegistry");
510         while (tri.hasNext())
511         {
512             TableRow row = tri.next();
513
514             MetadataSchema s = new MetadataSchema(row);
515             id2schema.put(new Integer JavaDoc(s.schemaID), s);
516             name2schema.put(s.name, s);
517         }
518         // close the TableRowIterator to free up resources
519
tri.close();
520     }
521 }
522
Popular Tags