All Downloads are FREE. Search and download functionalities are using the official Maven repository.

com.lyncode.xoai.dataprovider.parameters.OAICompiledRequest Maven / Gradle / Ivy

/**
 * Copyright 2012 Lyncode
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     client://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package com.lyncode.xoai.dataprovider.parameters;

import com.lyncode.builder.Builder;
import com.lyncode.xoai.dataprovider.exceptions.BadArgumentException;
import com.lyncode.xoai.dataprovider.exceptions.DuplicateDefinitionException;
import com.lyncode.xoai.dataprovider.exceptions.IllegalVerbException;
import com.lyncode.xoai.dataprovider.exceptions.UnknownParameterException;
import com.lyncode.xoai.exceptions.InvalidResumptionTokenException;
import com.lyncode.xoai.model.oaipmh.ResumptionToken;
import com.lyncode.xoai.services.api.DateProvider;
import com.lyncode.xoai.services.api.ResumptionTokenFormat;
import com.lyncode.xoai.services.impl.SimpleResumptionTokenFormat;
import com.lyncode.xoai.services.impl.UTCDateProvider;
import org.apache.log4j.LogManager;
import org.apache.log4j.Logger;
import org.hamcrest.Description;
import org.hamcrest.Matcher;
import org.hamcrest.TypeSafeMatcher;

import java.text.ParseException;
import java.util.Calendar;
import java.util.Collection;
import java.util.Date;

import static com.lyncode.xoai.dataprovider.parameters.OAIRequest.Parameter.*;
import static com.lyncode.xoai.model.oaipmh.Verb.Type;
import static org.hamcrest.CoreMatchers.*;

/**
 * @author Development @ Lyncode
 * @version 3.1.0
 */
public class OAICompiledRequest {
    private static Logger log = LogManager.getLogger(OAICompiledRequest.class);
    public static OAICompiledRequest compile (OAIRequest request) throws BadArgumentException, InvalidResumptionTokenException, UnknownParameterException, IllegalVerbException, DuplicateDefinitionException {
        return new OAICompiledRequest(request);
    }
    public static OAICompiledRequest compile (OAIRequest request, ResumptionTokenFormat formatter) throws BadArgumentException, InvalidResumptionTokenException, UnknownParameterException, IllegalVerbException, DuplicateDefinitionException {
        return new OAICompiledRequest(request, formatter);
    }
    public static OAICompiledRequest compile (Builder request) throws BadArgumentException, InvalidResumptionTokenException, UnknownParameterException, IllegalVerbException, DuplicateDefinitionException {
        return new OAICompiledRequest(request.build());
    }
    public static OAICompiledRequest compile (Builder request, ResumptionTokenFormat formatter) throws BadArgumentException, InvalidResumptionTokenException, UnknownParameterException, IllegalVerbException, DuplicateDefinitionException {
        return new OAICompiledRequest(request.build(), formatter);
    }

    private static DateProvider dateProvider = new UTCDateProvider();

    private Type verbType;
    private ResumptionToken.Value resumptionToken = null;
    private String identifier;
    private String metadataPrefix;
    private String set;
    private Date until;
    private Date from;

    private OAICompiledRequest(OAIRequest request)
            throws IllegalVerbException, BadArgumentException,
            UnknownParameterException, DuplicateDefinitionException, InvalidResumptionTokenException {
        this(request, new SimpleResumptionTokenFormat());
    }

    private OAICompiledRequest(OAIRequest request, ResumptionTokenFormat resumptionTokenFormat)
            throws IllegalVerbException, BadArgumentException,
            UnknownParameterException, DuplicateDefinitionException, InvalidResumptionTokenException {

        Collection parameterNames = request.getParameterNames();
        if (isTrueThat(parameterNames, not(hasItem(equalTo("verb")))))
            throw new IllegalVerbException("No verb provided");

        for (String parameterName : parameterNames)
            if (isTrueThat(parameterName, not(in("verb", "from", "until", "metadataPrefix", "identifier", "set", "resumptionToken"))))
                throw new UnknownParameterException("Unknown parameter '" + parameterName + "'");

        String until = request.getString(Until);
        String from = request.getString(From);
        if (isTrueThat(until, is(not(nullValue())))
                && isTrueThat(from, is(not(nullValue())))
                && from.length() != until.length())
            throw new BadArgumentException("Distinct granularities provided for until and from parameters");


        this.verbType = request.getVerb();
        this.from = request.getDate(From);
        this.until = request.getDate(Until);
        this.metadataPrefix = request.getString(MetadataPrefix);
        this.set = request.getString(Set);
        this.identifier = request.getString(Identifier);

        if (request.has(ResumptionToken))
            this.resumptionToken = resumptionTokenFormat.parse(request.getString(ResumptionToken));
        else
            this.resumptionToken = new ResumptionToken.Value();


        this.validate();
        this.loadResumptionToken(this.resumptionToken);
    }

    private Matcher in(final String... possibilities) {
        return new TypeSafeMatcher() {
            @Override
            protected boolean matchesSafely(String item) {
                for (String possibility : possibilities)
                    if (possibility.equals(item))
                        return true;

                return false;
            }

            @Override
            public void describeTo(Description description) {
                description.appendText("in");
            }
        };
    }

    private  boolean isTrueThat(T value, Matcher matcher) {
        return matcher.matches(value);
    }

    public boolean hasResumptionToken() {
        return this.resumptionToken != null && !this.resumptionToken.isEmpty();
    }

    public String getIdentifier() {
        return identifier;
    }

    public boolean hasIdentifier() {
        return (this.identifier != null);
    }

    public String getMetadataPrefix() {
        return metadataPrefix;
    }

    public boolean hasMetadataPrefix() {
        return (this.metadataPrefix != null);
    }

    public String getSet() {
        return set;
    }

    public boolean hasSet() {
        return (this.set != null);
    }

    public boolean hasFrom() {
        return (this.from != null);
    }

    public boolean hasUntil() {
        return (this.until != null);
    }

    private Date getDate(String date, String param) throws BadArgumentException {
        if (date == null) return null;
        try {
            return dateProvider.parse(date);
        } catch (ParseException e) {
            throw new BadArgumentException("The " + param
                    + " parameter given is not valid");
        }
    }

    public Date getFrom() {
        return from;
    }

    public ResumptionToken.Value getResumptionToken() {
        return resumptionToken;
    }

    public Date getUntil() {
        return until;
    }

    public Type getVerbType() {
        return verbType;
    }

    private void validate() throws IllegalVerbException, BadArgumentException {
        if (this.hasResumptionToken()) {
            if (this.hasFrom() || this.hasSet() || this.hasUntil()
                    || this.hasMetadataPrefix())
                throw new BadArgumentException(
                        "ResumptionToken cannot be sent together with from, until, metadataPrefix or set parameters");
        }

        switch (this.getVerbType()) {
            case Identify:
                if (this.hasIdentifier() || this.hasResumptionToken()
                        || this.hasSet() || this.hasMetadataPrefix()
                        || this.hasFrom() || this.hasUntil())
                    throw new BadArgumentException(
                            "Identify verb does not accept any extra parameter");
                break;
            case ListMetadataFormats:
                if (this.hasResumptionToken() || this.hasSet()
                        || this.hasMetadataPrefix() || this.hasFrom()
                        || this.hasUntil())
                    throw new BadArgumentException(
                            "ListMetadataFormats verb only accepts one optional parameter - identifier");
                break;
            case ListSets:
                if (this.hasIdentifier() || this.hasSet()
                        || this.hasMetadataPrefix() || this.hasFrom()
                        || this.hasUntil())
                    throw new BadArgumentException(
                            "ListSets verb only accepts one optional parameter - resumptionTokenResolver");
                break;
            case GetRecord:
                if (!this.hasIdentifier() || !this.hasMetadataPrefix()
                        || this.hasSet() || this.hasFrom() || this.hasUntil())
                    throw new BadArgumentException(
                            "GetRecord verb requires the use of the parameters - identifier and metadataPrefix");
                if (this.hasResumptionToken())
                    throw new BadArgumentException(
                            "GetRecord verb does not accept the resumptionTokenResolver parameter. It requires the use of the parameters - identifier and metadataPrefix");
                break;
            case ListIdentifiers:
                if (!this.hasResumptionToken() && !this.hasMetadataPrefix())
                    throw new BadArgumentException(
                            "ListIdentifiers verb must receive the metadataPrefix parameter");
                if (this.hasIdentifier())
                    throw new BadArgumentException(
                            "ListIdentifiers verb does not accept the identifier parameter");
                if (this.hasFrom() && this.hasUntil())
                    this.validateDates();
                break;
            case ListRecords:
                if (!this.hasResumptionToken() && !this.hasMetadataPrefix())
                    throw new BadArgumentException(
                            "ListRecords verb must receive the metadataPrefix parameter");
                if (this.hasIdentifier())
                    throw new BadArgumentException(
                            "ListRecords verb does not accept the identifier parameter");
                if (this.hasFrom() && this.hasUntil())
                    this.validateDates();
                break;
        }
    }

    private void validateDates() throws BadArgumentException {
        Calendar from = Calendar.getInstance();
        Calendar until = Calendar.getInstance();

        from.setTime(this.from);
        until.setTime(this.until);

        if (from.after(until)) throw new BadArgumentException("The 'from' date must be less then the 'until' one");
    }

    private void loadResumptionToken(ResumptionToken.Value resumptionToken) {
        if (resumptionToken.hasFrom())
            this.from = resumptionToken.getFrom();
        if (resumptionToken.hasMetadataPrefix())
            this.metadataPrefix = resumptionToken.getMetadataPrefix();
        if (resumptionToken.hasSetSpec())
            this.set = resumptionToken.getSetSpec();
        if (resumptionToken.hasUntil())
            this.until = resumptionToken.getUntil();
    }

    public ResumptionToken.Value extractResumptionToken() {
        return new ResumptionToken.Value().withOffset(0)
                .withMetadataPrefix(this.metadataPrefix)
                .withSetSpec(this.set)
                .withFrom(this.from)
                .withUntil(this.until);
    }
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy