Package org.dspace.content

Source Code of org.dspace.content.MetadataSchema

/*
* MetadataSchema.java
*
* Version: $Revision: 3761 $
*
* Date: $Date: 2009-05-07 04:18:02 +0000 (Thu, 07 May 2009) $
*
* Copyright (c) 2002-2009, The DSpace Foundation.  All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
* met:
*
* - Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
*
* - Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* - Neither the name of the DSpace Foundation nor the names of its
* contributors may be used to endorse or promote products derived from
* this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
* BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
* OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR
* TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE
* USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
* DAMAGE.
*/
package org.dspace.content;

import java.io.IOException;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.HashMap;
import java.util.ArrayList;
import java.util.List;

import org.apache.log4j.Logger;
import org.dspace.authorize.AuthorizeException;
import org.dspace.authorize.AuthorizeManager;
import org.dspace.core.Context;
import org.dspace.core.LogManager;
import org.dspace.storage.rdbms.DatabaseManager;
import org.dspace.storage.rdbms.TableRow;
import org.dspace.storage.rdbms.TableRowIterator;

/**
* Class representing a schema in DSpace.
* <p>
* The schema object exposes a name which can later be used to generate
* namespace prefixes in RDF or XML, e.g. the core DSpace Dublin Core schema
* would have a name of <code>'dc'</code>.
* </p>
*
* @author Martin Hald
* @version $Revision: 3761 $
* @see org.dspace.content.MetadataValue, org.dspace.content.MetadataField
*/
public class MetadataSchema
{
    /** log4j logger */
    private static Logger log = Logger.getLogger(MetadataSchema.class);

    /** Numeric Identifier of built-in Dublin Core schema. */
    public static final int DC_SCHEMA_ID = 1;

    /** Short Name of built-in Dublin Core schema. */
    public static final String DC_SCHEMA = "dc";

    /** The row in the table representing this type */
    private TableRow row;

    private int schemaID;
    private String namespace;
    private String name;

    // cache of schema by ID (Integer)
    private static HashMap id2schema = null;

    // cache of schema by short name
    private static HashMap name2schema = null;


    /**
     * Default constructor.
     */
    public MetadataSchema()
    {
    }

    /**
     * Object constructor.
     *
     * @param schemaID  database key ID number
     * @param namespace  XML namespace URI
     * @param name  short name of schema
     */
    public MetadataSchema(int schemaID, String namespace, String name)
    {
        this.schemaID = schemaID;
        this.namespace = namespace;
        this.name = name;
    }

    /**
     * Immutable object constructor for creating a new schema.
     *
     * @param namespace  XML namespace URI
     * @param name  short name of schema
     */
    public MetadataSchema(String namespace, String name)
    {
        this.namespace = namespace;
        this.name = name;
    }

    /**
     * Constructor for loading the metadata schema from the database.
     *
     * @param row table row object from which to populate this schema.
     */
    public MetadataSchema(TableRow row)
    {
        if (row != null)
        {
            this.schemaID = row.getIntColumn("metadata_schema_id");
            this.namespace = row.getStringColumn("namespace");
            this.name = row.getStringColumn("short_id");
            this.row = row;
        }
    }

    /**
     * Get the schema namespace.
     *
     * @return namespace String
     */
    public String getNamespace()
    {
        return namespace;
    }

    /**
     * Set the schema namespace.
     *
     * @param namespace  XML namespace URI
     */
    public void setNamespace(String namespace)
    {
        this.namespace = namespace;
    }

    /**
     * Get the schema name.
     *
     * @return name String
     */
    public String getName()
    {
        return name;
    }

    /**
     * Set the schema name.
     *
     * @param name  short name of schema
     */
    public void setName(String name)
    {
        this.name = name;
    }

    /**
     * Get the schema record key number.
     *
     * @return schema record key
     */
    public int getSchemaID()
    {
        return schemaID;
    }

    /**
     * Creates a new metadata schema in the database, out of this object.
     *
     * @param context
     *            DSpace context object
     * @throws SQLException
     * @throws AuthorizeException
     * @throws NonUniqueMetadataException
     */
    public void create(Context context) throws SQLException,
            AuthorizeException, NonUniqueMetadataException
    {
        // Check authorisation: Only admins may create metadata schemas
        if (!AuthorizeManager.isAdmin(context))
        {
            throw new AuthorizeException(
                    "Only administrators may modify the metadata registry");
        }

        // Ensure the schema name is unique
        if (!uniqueShortName(context, name))
        {
            throw new NonUniqueMetadataException("Please make the name " + name
                    + " unique");
        }
       
        // Ensure the schema namespace is unique
        if (!uniqueNamespace(context, namespace))
        {
            throw new NonUniqueMetadataException("Please make the namespace " + namespace
                    + " unique");
        }


        // Create a table row and update it with the values
        row = DatabaseManager.create(context, "MetadataSchemaRegistry");
        row.setColumn("namespace", namespace);
        row.setColumn("short_id", name);
        DatabaseManager.update(context, row);

        // invalidate our fast-find cache.
        decache();

        // Remember the new row number
        this.schemaID = row.getIntColumn("metadata_schema_id");

        log
                .info(LogManager.getHeader(context, "create_metadata_schema",
                        "metadata_schema_id="
                                + row.getIntColumn("metadata_schema_id")));
    }

    /**
     * Get the schema object corresponding to this namespace URI.
     *
     * @param context DSpace context
     * @param namespace namespace URI to match
     * @return metadata schema object or null if none found.
     * @throws SQLException
     */
    public static MetadataSchema findByNamespace(Context context,
            String namespace) throws SQLException
    {
        // Grab rows from DB
        TableRowIterator tri = DatabaseManager.queryTable(context,"MetadataSchemaRegistry",
                "SELECT * FROM MetadataSchemaRegistry WHERE namespace= ? ",
                namespace);

        TableRow row = null;
        try
        {
            if (tri.hasNext())
            {
                row = tri.next();
            }
        }
        finally
        {
            // close the TableRowIterator to free up resources
            if (tri != null)
                tri.close();
        }

        if (row == null)
        {
            return null;
        }
        else
        {
            return new MetadataSchema(row);
        }
    }

    /**
     * Update the metadata schema in the database.
     *
     * @param context DSpace context
     * @throws SQLException
     * @throws AuthorizeException
     * @throws NonUniqueMetadataException
     */
    public void update(Context context) throws SQLException,
            AuthorizeException, NonUniqueMetadataException
    {
        // Check authorisation: Only admins may update the metadata registry
        if (!AuthorizeManager.isAdmin(context))
        {
            throw new AuthorizeException(
                    "Only administrators may modify the metadata registry");
        }

        // Ensure the schema name is unique
        if (!uniqueShortName(context, name))
        {
            throw new NonUniqueMetadataException("Please make the name " + name
                    + " unique");
        }

        // Ensure the schema namespace is unique
        if (!uniqueNamespace(context, namespace))
        {
            throw new NonUniqueMetadataException("Please make the namespace " + namespace
                    + " unique");
        }
       
        row.setColumn("namespace", getNamespace());
        row.setColumn("short_id", getName());
        DatabaseManager.update(context, row);

        decache();

        log.info(LogManager.getHeader(context, "update_metadata_schema",
                "metadata_schema_id=" + getSchemaID() + "namespace="
                        + getNamespace() + "name=" + getName()));
    }

    /**
     * Delete the metadata schema.
     *
     * @param context DSpace context
     * @throws SQLException
     * @throws AuthorizeException
     */
    public void delete(Context context) throws SQLException, AuthorizeException
    {
        // Check authorisation: Only admins may create DC types
        if (!AuthorizeManager.isAdmin(context))
        {
            throw new AuthorizeException(
                    "Only administrators may modify the metadata registry");
        }

        log.info(LogManager.getHeader(context, "delete_metadata_schema",
                "metadata_schema_id=" + getSchemaID()));

        DatabaseManager.delete(context, row);
    }

    /**
     * Return all metadata schemas.
     *
     * @param context DSpace context
     * @return array of metadata schemas
     * @throws SQLException
     */
    public static MetadataSchema[] findAll(Context context) throws SQLException
    {
        List schemas = new ArrayList();

        // Get all the metadataschema rows
        TableRowIterator tri = DatabaseManager.queryTable(context, "MetadataSchemaRegistry",
                        "SELECT * FROM MetadataSchemaRegistry ORDER BY metadata_schema_id");

        try
        {
            // Make into DC Type objects
            while (tri.hasNext())
            {
                schemas.add(new MetadataSchema(tri.next()));
            }
        }
        finally
        {
            // close the TableRowIterator to free up resources
            if (tri != null)
                tri.close();
        }

        // Convert list into an array
        MetadataSchema[] typeArray = new MetadataSchema[schemas.size()];
        return (MetadataSchema[]) schemas.toArray(typeArray);
    }

    /**
     * Return true if and only if the passed name appears within the allowed
     * number of times in the current schema.
     *
     * @param context DSpace context
     * @param namespace namespace URI to match
     * @return true of false
     * @throws SQLException
     */
    private boolean uniqueNamespace(Context context, String namespace)
            throws SQLException
    {
        int count = 0;
        Connection con = context.getDBConnection();
        PreparedStatement statement = null;
        ResultSet rs = null;

        try
        {
            TableRow reg = DatabaseManager.row("MetadataSchemaRegistry");

            String query = "SELECT COUNT(*) FROM " + reg.getTable() + " " +
                    "WHERE metadata_schema_id != ? " +
                    "AND namespace= ? ";

            statement = con.prepareStatement(query);
            statement.setInt(1,schemaID);
            statement.setString(2,namespace);

            rs = statement.executeQuery();

            if (rs.next())
            {
                count = rs.getInt(1);
            }
        }
        finally
        {
            if (rs != null)
            {
                try { rs.close(); } catch (SQLException sqle) { }
            }

            if (statement != null)
            {
                try { statement.close(); } catch (SQLException sqle) { }
            }
        }

        return (count == 0);
    }

    /**
     * Return true if and only if the passed name is unique.
     *
     * @param context DSpace context
     * @param name  short name of schema
     * @return true of false
     * @throws SQLException
     */
    private boolean uniqueShortName(Context context, String name)
            throws SQLException
    {
        int count = 0;
        Connection con = context.getDBConnection();
        PreparedStatement statement = null;
        ResultSet rs = null;

        try
        {
            TableRow reg = DatabaseManager.row("MetadataSchemaRegistry");

            String query = "SELECT COUNT(*) FROM " + reg.getTable() + " " +
                    "WHERE metadata_schema_id != ? " +
                    "AND short_id = ? ";

            statement = con.prepareStatement(query);
            statement.setInt(1,schemaID);
            statement.setString(2,name);

            rs = statement.executeQuery();

            if (rs.next())
            {
                count = rs.getInt(1);
            }
        }
        finally
        {
            if (rs != null)
            {
                try { rs.close(); } catch (SQLException sqle) { }
            }

            if (statement != null)
            {
                try { statement.close(); } catch (SQLException sqle) { }
            }
        }

        return (count == 0);
    }

    /**
     * Get the schema corresponding with this numeric ID.
     * The ID is a database key internal to DSpace.
     *
     * @param context
     *            context, in case we need to read it in from DB
     * @param id
     *            the schema ID
     * @return the metadata schema object
     * @throws SQLException
     */
    public static MetadataSchema find(Context context, int id)
            throws SQLException
    {
        initCache(context);
        Integer iid = new Integer(id);

        // sanity check
        if (!id2schema.containsKey(iid))
            return null;

        return (MetadataSchema) id2schema.get(iid);
    }

    /**
     * Get the schema corresponding with this short name.
     *
     * @param context
     *            context, in case we need to read it in from DB
     * @param shortName
     *            the short name for the schema
     * @return the metadata schema object
     * @throws SQLException
     */
    public static MetadataSchema find(Context context, String shortName)
        throws SQLException
    {
        // If we are not passed a valid schema name then return
        if (shortName == null)
            return null;

        initCache(context);

        if (!name2schema.containsKey(shortName))
            return null;

        return (MetadataSchema) name2schema.get(shortName);
    }

    // invalidate the cache e.g. after something modifies DB state.
    private static void decache()
    {
        id2schema = null;
        name2schema = null;
    }

    // load caches if necessary
    private static void initCache(Context context) throws SQLException
    {
        if (id2schema != null && name2schema != null)
            return;

        synchronized (MetadataSchema.class)
        {
            if (id2schema == null && name2schema == null)
            {
                log.info("Loading schema cache for fast finds");
                HashMap new_id2schema = new HashMap();
                HashMap new_name2schema = new HashMap();

                TableRowIterator tri = DatabaseManager.queryTable(context,"MetadataSchemaRegistry",
                        "SELECT * from MetadataSchemaRegistry");

                try
                {
                    while (tri.hasNext())
                    {
                        TableRow row = tri.next();

                        MetadataSchema s = new MetadataSchema(row);
                        new_id2schema.put(new Integer(s.schemaID), s);
                        new_name2schema.put(s.name, s);
                    }
                }
                finally
                {
                    // close the TableRowIterator to free up resources
                    if (tri != null)
                        tri.close();
                }

                id2schema = new_id2schema;
                name2schema = new_name2schema;
            }
        }
    }
}
TOP

Related Classes of org.dspace.content.MetadataSchema

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.