Package org.fcrepo.server.oai

Source Code of org.fcrepo.server.oai.FedoraOAIProvider

/* The contents of this file are subject to the license and copyright terms
* detailed in the license directory at the root of the source tree (also
* available online at http://fedora-commons.org/license/).
*/
package org.fcrepo.server.oai;

import java.text.SimpleDateFormat;

import java.util.ArrayList;
import java.util.Date;
import java.util.HashSet;
import java.util.Iterator;
import java.util.List;
import java.util.Set;

import org.fcrepo.common.Constants;
import org.fcrepo.oai.BadResumptionTokenException;
import org.fcrepo.oai.CannotDisseminateFormatException;
import org.fcrepo.oai.DateGranularitySupport;
import org.fcrepo.oai.DeletedRecordSupport;
import org.fcrepo.oai.Header;
import org.fcrepo.oai.IDDoesNotExistException;
import org.fcrepo.oai.NoMetadataFormatsException;
import org.fcrepo.oai.NoRecordsMatchException;
import org.fcrepo.oai.NoSetHierarchyException;
import org.fcrepo.oai.OAIProvider;
import org.fcrepo.oai.Record;
import org.fcrepo.oai.RepositoryException;
import org.fcrepo.oai.SimpleHeader;
import org.fcrepo.oai.SimpleMetadataFormat;
import org.fcrepo.oai.SimpleRecord;
import org.fcrepo.oai.SimpleResumptionToken;
import org.fcrepo.oai.SimpleSetInfo;
import org.fcrepo.server.errors.ServerException;
import org.fcrepo.server.errors.UnknownSessionTokenException;
import org.fcrepo.server.search.Condition;
import org.fcrepo.server.search.FieldSearch;
import org.fcrepo.server.search.FieldSearchQuery;
import org.fcrepo.server.search.FieldSearchResult;
import org.fcrepo.server.search.ObjectFields;
import org.fcrepo.server.utilities.DCFields;




/**
* Simple FieldSearch-based OAI provider.
*
* @author Chris Wilper
*/
public class FedoraOAIProvider
        implements Constants, OAIProvider {

    private final String m_repositoryName;

    private final String m_repositoryDomainName;

    private final String m_localname;

    private final String m_relpath;

    private final Set m_adminEmails;

    private final Set<String> m_descriptions;

    private final List<SimpleSetInfo> m_setInfos;

    private final long m_maxSets;

    private final long m_maxRecords;

    private final long m_maxHeaders;

    private final FieldSearch m_fieldSearch;

    private final Set<SimpleMetadataFormat> m_formats;

    private static Set s_emptySet = new HashSet();

    private static String[] s_headerFields =
            new String[] {"pid", "dcmDate"};

    private static String[] s_headerAndDCFields =
            new String[] {"pid", "dcmDate", "title", "creator",
                    "subject", "description", "publisher", "contributor",
                    "date", "type", "format", "identifier", "source",
                    "language", "relation", "coverage", "rights"};

    public FedoraOAIProvider(String repositoryName,
                             String repositoryDomainName,
                             String localname,
                             String relpath,
                             Set adminEmails,
                             Set friendBaseURLs,
                             String namespaceID,
                             long maxSets,
                             long maxRecords,
                             long maxHeaders,
                             FieldSearch fieldSearch) {
        m_repositoryName = repositoryName;
        m_repositoryDomainName = repositoryDomainName;
        m_localname = localname;
        m_relpath = relpath;
        m_adminEmails = adminEmails;
        m_maxSets = maxSets;
        m_maxRecords = maxRecords;
        m_maxHeaders = maxHeaders;
        m_fieldSearch = fieldSearch;
        m_descriptions = new HashSet<String>();
        StringBuffer buf = new StringBuffer();
        buf.append("      <oai-identifier xmlns=\"" + OAI_IDENTIFIER.uri
                + "\"\n");
        buf.append("          xmlns:xsi=\"" + XSI.uri + "\"\n");
        buf.append("          xsi:schemaLocation=\"" + OAI_IDENTIFIER.uri
                + "\n");
        buf.append("          " + OAI_IDENTIFIER2_0.xsdLocation + "\">\n");
        buf.append("        <scheme>oai</scheme>\n");
        buf.append("        <repositoryIdentifier>" + m_repositoryDomainName
                + "</repositoryIdentifier>\n");
        buf.append("        <delimiter>:</delimiter>\n");
        buf.append("        <sampleIdentifier>oai:" + m_repositoryDomainName
                + ":" + namespaceID + ":7654</sampleIdentifier>\n");
        buf.append("      </oai-identifier>");
        m_descriptions.add(buf.toString());
        if (friendBaseURLs != null && friendBaseURLs.size() > 0) {
            buf = new StringBuffer();
            buf.append("      <friends xmlns=\"" + OAI_FRIENDS.uri + "\"\n");
            buf.append("          xmlns:xsi=\"" + XSI.uri + "\"\n");
            buf.append("          xsi:schemaLocation=\"" + OAI_FRIENDS.uri
                    + "\n");
            buf.append("          " + OAI_FRIENDS2_0.xsdLocation + "\">\n");
            Iterator iter = friendBaseURLs.iterator();
            while (iter.hasNext()) {
                buf.append("        <baseURL>" + (String) iter.next()
                        + "</baseURL>\n");
            }
            buf.append("      </friends>");
            m_descriptions.add(buf.toString());
        }
        m_formats = new HashSet<SimpleMetadataFormat>();
        m_formats.add(new SimpleMetadataFormat("oai_dc",
                                               OAI_DC2_0.xsdLocation,
                                               OAI_DC.uri));
        m_setInfos = new ArrayList<SimpleSetInfo>();
    }

    public String getRepositoryName() {
        return m_repositoryName;
    }

    public String getBaseURL(String protocol, String port) {
        return protocol + "://" + m_localname + ":" + port + m_relpath;
    }

    public String getProtocolVersion() {
        return "2.0";
    }

    public Date getEarliestDatestamp() {
        return new Date();
    }

    public DeletedRecordSupport getDeletedRecordSupport() {
        return DeletedRecordSupport.NO;
    }

    public DateGranularitySupport getDateGranularitySupport() {
        return DateGranularitySupport.SECONDS;
    }

    public Set getAdminEmails() {
        return m_adminEmails;
    }

    public Set getSupportedCompressionEncodings() {
        return s_emptySet;
    }

    public Set getDescriptions() {
        return m_descriptions;
    }

    public Record getRecord(String identifier, String metadataPrefix)
            throws CannotDisseminateFormatException, IDDoesNotExistException,
            RepositoryException {
        if (!metadataPrefix.equals("oai_dc")) {
            throw new CannotDisseminateFormatException("Repository does not provide that format in OAI-PMH responses.");
        }
        String pid = getPID(identifier);
        List l = null;
        try {
            //FIXME: use maxResults from... config instead of hardcoding 100?
            l =
                    m_fieldSearch
                            .findObjects(s_headerAndDCFields,
                                         100,
                                         new FieldSearchQuery(Condition
                                                 .getConditions("pid='"
                                                         + pid
                                                         + "' dcmDate>'2000-01-01'")))
                            .objectFieldsList();
        } catch (ServerException se) {
            throw new RepositoryException(se.getClass().getName() + ": "
                    + se.getMessage());
        }
        if (l.size() > 0) {
            ObjectFields f = (ObjectFields) l.get(0);
            return new SimpleRecord(getHeader(f), getDCXML(f), s_emptySet);
        } else {
            // see if it exists
            try {
                l =
                        m_fieldSearch
                                .findObjects(new String[] {"pid"},
                                             1,
                                             new FieldSearchQuery(Condition
                                                     .getConditions("pid='"
                                                             + pid + "'")))
                                .objectFieldsList();
            } catch (ServerException se) {
                throw new RepositoryException(se.getClass().getName() + ": "
                        + se.getMessage());
            }
            if (l.size() == 0) {
                throw new IDDoesNotExistException("The provided id does not match any item in the repository.");
            } else {
                throw new CannotDisseminateFormatException("The item doesn't even have dc_oai metadata.");
            }
        }
    }

    public List getRecords(Date from,
                           Date until,
                           String metadataPrefix,
                           String set) throws CannotDisseminateFormatException,
            NoRecordsMatchException, NoSetHierarchyException,
            RepositoryException {
        if (!metadataPrefix.equals("oai_dc")) {
            throw new CannotDisseminateFormatException("Repository does not provide that format in OAI-PMH responses.");
        }
        List l = null;
        FieldSearchResult fsr;
        try {
            fsr =
                    m_fieldSearch
                            .findObjects(s_headerAndDCFields,
                                         (int) getMaxRecords(),
                                         new FieldSearchQuery(Condition
                                                 .getConditions("dcmDate>'2000-01-01'"
                                                         + getDatePart(from,
                                                                       until))));
            l = fsr.objectFieldsList();
        } catch (ServerException se) {
            throw new RepositoryException(se.getClass().getName() + ": "
                    + se.getMessage());
        }
        if (l.size() == 0) {
            throw new NoRecordsMatchException("No records match the given criteria.");
        }
        ArrayList<Object> ret = new ArrayList<Object>();
        for (int i = 0; i < l.size(); i++) {
            ObjectFields f = (ObjectFields) l.get(i);
            ret.add(new SimpleRecord(getHeader(f), getDCXML(f), s_emptySet));
        }
        if (fsr.getToken() != null) {
            // add resumptionToken stuff
            ret.add(new SimpleResumptionToken(fsr.getToken(), fsr
                    .getExpirationDate(), fsr.getCompleteListSize(), fsr
                    .getCursor()));
        }
        return ret;
    }

    private Header getHeader(ObjectFields f) {
        String identifier = "oai:" + m_repositoryDomainName + ":" + f.getPid();
        Date datestamp = f.getDCMDate();
        HashSet<String> setSpecs = new HashSet<String>();
        return new SimpleHeader(identifier, datestamp, setSpecs, true);
    }

    private String getDCXML(DCFields dc) {
        return dc.getAsXML();
    }

    public List getRecords(String resumptionToken)
            throws CannotDisseminateFormatException, NoRecordsMatchException,
            NoSetHierarchyException, BadResumptionTokenException,
            RepositoryException {
        // this is the exact same as the other getRecords, except for the FieldSearch call,
        // and the fact that we re-throw UnknownSessionTokenException
        // as a BadResumptionTokenException
        List l = null;
        FieldSearchResult fsr;
        try {
            fsr = m_fieldSearch.resumeFindObjects(resumptionToken);
            l = fsr.objectFieldsList();
        } catch (UnknownSessionTokenException uste) {
            throw new BadResumptionTokenException("Not a known resumptionToken.");
        } catch (ServerException se) {
            throw new RepositoryException(se.getClass().getName() + ": "
                    + se.getMessage());
        }
        if (l.size() == 0) {
            throw new NoRecordsMatchException("No records match the given criteria.");
        }
        ArrayList<Object> ret = new ArrayList<Object>();
        for (int i = 0; i < l.size(); i++) {
            ObjectFields f = (ObjectFields) l.get(i);
            ret.add(new SimpleRecord(getHeader(f), getDCXML(f), s_emptySet));
        }
        if (fsr.getToken() != null) {
            ret.add(new SimpleResumptionToken(fsr.getToken(), fsr
                    .getExpirationDate(), fsr.getCompleteListSize(), fsr
                    .getCursor()));
        }
        return ret;
    }

    private String getDatePart(Date from, Date until) {
        if (from == null && until == null) {
            return "";
        }
        StringBuffer out = new StringBuffer();
        // Note OAI only support ISO8601 dates to the seconds
        // and Fedora stores dates down to the millisecond level.
        // This should not matter since OAI requests specify
        // date ranges (from-until), and as long as the requests
        // are always in the same units, subsequent requests can pick
        // up at the last end-point in time (in seconds) without
        // concern for millisecond granularity.
        SimpleDateFormat formatter =
                new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss");
        if (from != null) {
            out.append(" dcmDate>='");
            out.append(formatter.format(from));
            out.append("'");
        }
        if (until != null) {
            out.append(" dcmDate<='");
            out.append(formatter.format(until));
            out.append("'");
        }
        return out.toString();
    }

    public List getHeaders(Date from,
                           Date until,
                           String metadataPrefix,
                           String set) throws CannotDisseminateFormatException,
            NoRecordsMatchException, NoSetHierarchyException,
            RepositoryException {
        if (!metadataPrefix.equals("oai_dc")) {
            throw new CannotDisseminateFormatException("Repository does not provide that format in OAI-PMH responses.");
        }
        List l = null;
        FieldSearchResult fsr;
        try {
            fsr =
                    m_fieldSearch
                            .findObjects(s_headerFields,
                                         (int) getMaxHeaders(),
                                         new FieldSearchQuery(Condition
                                                 .getConditions("dcmDate>'2000-01-01'"
                                                         + getDatePart(from,
                                                                       until))));
            l = fsr.objectFieldsList();
        } catch (ServerException se) {
            throw new RepositoryException(se.getClass().getName() + ": "
                    + se.getMessage());
        }
        if (l.size() == 0) {
            throw new NoRecordsMatchException("No records match the given criteria.");
        }
        ArrayList<Object> ret = new ArrayList<Object>();
        for (int i = 0; i < l.size(); i++) {
            ObjectFields f = (ObjectFields) l.get(i);
            String identifier =
                    "oai:" + m_repositoryDomainName + ":" + f.getPid();
            Date datestamp = f.getDCMDate();
            HashSet<String> setSpecs = new HashSet<String>();

            ret.add(new SimpleHeader(identifier, datestamp, setSpecs, true));
        }
        if (fsr.getToken() != null) {
            ret.add(new SimpleResumptionToken(fsr.getToken(), fsr
                    .getExpirationDate(), fsr.getCompleteListSize(), fsr
                    .getCursor()));
        }
        return ret;
    }

    public List getHeaders(String resumptionToken)
            throws CannotDisseminateFormatException, NoRecordsMatchException,
            NoSetHierarchyException, BadResumptionTokenException,
            RepositoryException {
        // this is the exact same as the other getHeaders, except for the FieldSearch call,
        // and the fact that we re-throw UnknownSessionTokenException
        // as a BadResumptionTokenException
        List l = null;
        FieldSearchResult fsr;
        try {
            fsr = m_fieldSearch.resumeFindObjects(resumptionToken);
            l = fsr.objectFieldsList();
        } catch (UnknownSessionTokenException uste) {
            throw new BadResumptionTokenException("Not a known resumptionToken.");
        } catch (ServerException se) {
            throw new RepositoryException(se.getClass().getName() + ": "
                    + se.getMessage());
        }
        if (l.size() == 0) {
            throw new NoRecordsMatchException("No records match the given criteria.");
        }
        ArrayList<Object> ret = new ArrayList<Object>();
        for (int i = 0; i < l.size(); i++) {
            ObjectFields f = (ObjectFields) l.get(i);
            String identifier =
                    "oai:" + m_repositoryDomainName + ":" + f.getPid();
            Date datestamp = f.getDCMDate();
            HashSet<String> setSpecs = new HashSet<String>();
            ret.add(new SimpleHeader(identifier, datestamp, setSpecs, true));
        }
        if (fsr.getToken() != null) {
            ret.add(new SimpleResumptionToken(fsr.getToken(), fsr
                    .getExpirationDate(), fsr.getCompleteListSize(), fsr
                    .getCursor()));
        }
        return ret;
    }

    public List getSets() throws NoSetHierarchyException, RepositoryException {
        return m_setInfos;
    }

    public List getSets(String resumptionToken)
            throws BadResumptionTokenException, NoSetHierarchyException,
            RepositoryException {
        // no resumptionTokens are currently used on getSets since it's always so small
        throw new BadResumptionTokenException("Not a known resumptionToken.");
    }

    private String getPID(String id) throws IDDoesNotExistException {
        if (!id.startsWith("oai:" + m_repositoryDomainName + ":")) {
            throw new IDDoesNotExistException("For this repository, all identifiers in OAI requests should begin with oai:"
                    + m_repositoryDomainName + ":");
        }
        if (id.indexOf("'") != -1) {
            throw new IDDoesNotExistException("For this repository, no identifiers contain the apostrophe character.");
        }
        return id.substring(4 + m_repositoryDomainName.length() + 1);
    }

    public Set getMetadataFormats(String id) throws NoMetadataFormatsException,
            IDDoesNotExistException, RepositoryException {
        if (id == null) {
            return m_formats;
        }
        String pid = getPID(id);
        List l = null;
        try {
            l =
                    m_fieldSearch
                            .findObjects(new String[] {"pid"},
                                         1,
                                         new FieldSearchQuery(Condition
                                                 .getConditions("pid='"
                                                         + pid
                                                         + "' dcmDate>'2000-01-01'")))
                            .objectFieldsList();
        } catch (ServerException se) {
            throw new RepositoryException(se.getClass().getName() + ": "
                    + se.getMessage());
        }
        if (l.size() > 0) {
            return m_formats;
        }
        try {
            l =
                    m_fieldSearch.findObjects(new String[] {"pid"},
                                              1,
                                              new FieldSearchQuery(Condition
                                                      .getConditions("pid='"
                                                              + pid + "'")))
                            .objectFieldsList();
        } catch (ServerException se) {
            throw new RepositoryException(se.getClass().getName() + ": "
                    + se.getMessage());
        }
        if (l.size() > 0) {
            throw new NoMetadataFormatsException("The item doesn't even have dc_oai metadata.");
        } else {
            throw new IDDoesNotExistException("The provided id does not match any item in the repository.");
        }
    }

    public long getMaxSets() throws RepositoryException {
        return m_maxSets;
    }

    public long getMaxRecords() throws RepositoryException {
        return m_maxRecords;
    }

    public long getMaxHeaders() throws RepositoryException {
        return m_maxHeaders;
    }

}
TOP

Related Classes of org.fcrepo.server.oai.FedoraOAIProvider

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.