nl.mpi.oai.harvester.cycle.EndpointAdapter.java Source code

Java tutorial

Introduction

Here is the source code for nl.mpi.oai.harvester.cycle.EndpointAdapter.java

Source

/*
 * Copyright (C) 2015, The Max Planck Institute for
 * Psycholinguistics.
 *
 * This program is free software: you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation, version 3 of the License.
 *
 * This program is distributed in the hope that it will be useful, but
 * WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 * General Public License for more details.
 *
 * A copy of the GNU General Public License is included in the file
 * LICENSE-gpl-3.0.txt. If that file is missing, see
 * <http://www.gnu.org/licenses/>.
 */

package nl.mpi.oai.harvester.cycle;

import nl.mpi.oai.harvester.generated.EndpointType;
import nl.mpi.oai.harvester.generated.OverviewType;
import nl.mpi.oai.harvester.generated.ScenarioType;
import org.joda.time.DateTime;
import org.joda.time.DateTimeZone;

import javax.xml.datatype.DatatypeConfigurationException;
import javax.xml.datatype.DatatypeFactory;
import javax.xml.datatype.XMLGregorianCalendar;
import java.math.BigDecimal;
import java.util.logging.Level;
import java.util.logging.Logger;

/**
 * <br> Access to endpoint properties <br><br>
 *
 * An endpoint adapter is an object providing access to endpoint properties
 * stored as XML elements. To access a desired attribute, invoke the designated
 * method on the adapter object. <br><br>
 *
 * This class depends on JAXB to generate types representing the XML harvest
 * cycle file. When an adapter method needs to obtain an endpoint attribute,
 * it will invoke a corresponding method on the EndpointType object. The class
 * also depends on the JAXB factory for creating endpoint elements and the
 * elements enclosed in them.
 *
 * @author Kees Jan van de Looij (Max Planck Institute for Psycholinguistics)
 */
class EndpointAdapter implements Endpoint {

    // the endpoint referenced by the URI supplied to the constructor
    private EndpointType endpointType;

    // overview marshalling object
    private XMLOverview xmlOverview;

    /**
     * Create a default endpoint
     *
     * @param endpointURI the URI identifying the endpoint
     * @param group       the group the endpoint belongs to
     */
    private EndpointType CreateDefault(String endpointURI, String group) {

        /* Because of the constructor, the factory is in place. Ask it to
           create a new endpoint.
         */
        endpointType = xmlOverview.factory.createEndpointType();

        // create the endpoint fields, and set them to default values
        endpointType.setBlock(Boolean.FALSE);
        endpointType.setIncremental(Boolean.TRUE);
        endpointType.setURI(endpointURI);
        endpointType.setGroup(group);

        // save the newly created endpoint to the overview
        xmlOverview.save();

        return endpointType;
    }

    /**
     * Look for the endpoint in the cycle, use an URI as the as the key
     *
     * @param endpointURI the URI identifying the endpoint
     * @return            null if the cycle does not contain the endpoint,
     *                    the intended endpoint otherwise
     */
    private EndpointType FindEndpoint(String endpointURI) {

        // assume the endpoint is not there
        endpointType = null;

        // iterate over the elements in the harvested element
        Boolean found = false;

        // JAXB representation of the overview
        OverviewType overviewType = xmlOverview.overviewType;

        for (int i = 0; i < overviewType.getEndpoint().size() && !found; i++) {
            endpointType = overviewType.getEndpoint().get(i);
            if (endpointType.getURI().compareTo(endpointURI) == 0) {
                found = true;
            }
        }

        if (found) {
            return endpointType;
        } else {
            return null;
        }
    }

    /**
     * Associate the adapter with a URI, a group, an cycle, and a factory <br><br>
     *
     * Precondition: endpointURI, group, xmlOverview fields are in place <br><br>
     *
     * In case the constructor cannot find the endpoint URI specified in the
     * cycle elements, it will create a new endpoint and add to the endpoints
     * already present in the cycle. <br><br>
     *
     * @param endpointURI  the URI of the endpoint the cycle should attempt to
     *                     harvest
     * @param group        the group the endpoint belongs to
     * @param xmlOverview  overview marshalling object
     *
     */
    EndpointAdapter(String endpointURI, String group, String scenario, XMLOverview xmlOverview) {

        // remember the cycle, remember the factory
        this.xmlOverview = xmlOverview;

        // look for the endpoint in the cycle
        endpointType = FindEndpoint(endpointURI);

        if (endpointType == null) {
            // if it is not in the cycle, create a default endpoint
            endpointType = CreateDefault(endpointURI, group);

            // and add it to the cycle
            xmlOverview.overviewType.getEndpoint().add(endpointType);
        }

        if (scenario != null) {
            if (scenario.equals("ListPrefixes"))
                endpointType.setScenario(ScenarioType.LIST_PREFIXES);
            else if (scenario.equals("ListIdentifiers"))
                endpointType.setScenario(ScenarioType.LIST_IDENTIFIERS);
            else if (scenario.equals("ListRecords"))
                endpointType.setScenario(ScenarioType.LIST_RECORDS);
        }
    }

    @Override
    public String getURI() {

        // the endpoint URI is in place because of the constructor precondition
        return endpointType.getURI();
    }

    @Override
    public String getGroup() {

        // try to get attribute, use boolean reference type to check for null
        String group = endpointType.getGroup();
        if (group == null) {
            // set default group, the empty string
            endpointType.setGroup("");
            return "";
        } else {
            return group;
        }
    }

    @Override
    public boolean blocked() {

        // try to get attribute, use boolean reference type to check for null
        Boolean blocked = endpointType.isBlock();

        if (blocked == null) {
            // attribute not XML cycle element, add it to it
            endpointType.setBlock(false);
            return false;
        } else {
            return blocked;
        }
    }

    @Override
    public boolean retry() {

        // try to get attribute, use boolean reference type to check for null
        Boolean retry = endpointType.isRetry();

        if (retry == null) {
            // attribute not XML cycle element, add it to it
            endpointType.setRetry(false);
            return false;
        } else {
            return retry;
        }

    }

    @Override
    public boolean allowIncrementalHarvest() {

        // try to get attribute, use boolean reference type to check for null
        Boolean allow = endpointType.isIncremental();

        if (allow == null) {
            // attribute not XML cycle element, add it to it
            endpointType.setIncremental(false);
            return false;
        } else {
            return allow;
        }
    }

    @Override
    public boolean allowRefresh() {

        // try to get attribute, use boolean reference type to check for null
        Boolean allow = endpointType.isRefresh();

        if (allow == null) {
            // attribute not XML cycle element, add it to it
            endpointType.setRefresh(false);
            return false;
        } else {
            return allow;
        }
    }

    @Override
    public CycleProperties.Scenario getScenario() {

        // try to get attribute
        ScenarioType scenarioType = endpointType.getScenario();

        if (scenarioType == null) {
            // look for a global scenario
            scenarioType = this.xmlOverview.overviewType.getScenario();
        }
        if (scenarioType == null) {
            // fall back to default
            endpointType.setScenario(ScenarioType.LIST_IDENTIFIERS);
            return CycleProperties.Scenario.ListIdentifiers;
        } else {
            switch (scenarioType) {
            case LIST_PREFIXES:
                return CycleProperties.Scenario.ListPrefixes;
            case LIST_IDENTIFIERS:
                return CycleProperties.Scenario.ListIdentifiers;
            default:
                return CycleProperties.Scenario.ListRecords;
            }
        }
    }

    // zero epoch time in the UTC zone
    final DateTime zeroUTC = new DateTime("1970-01-01T00:00:00.000+00:00", DateTimeZone.UTC);

    @Override
    public DateTime getAttemptedDate() {

        XMLGregorianCalendar XMLDate;
        XMLDate = endpointType.getAttempted();

        if (XMLDate == null) {
            /* Since there is no default value for this property, there is no
               need to set the date in the overview now. Return the zero epoch
               date in the UTC zone.
             */
            return zeroUTC;
        } else {
            // convert XMLGregorianCalendar to DateTime
            return new DateTime(XMLDate.toString(), DateTimeZone.UTC);
        }
    }

    @Override
    public DateTime getHarvestedDate() {

        XMLGregorianCalendar XMLDate;
        XMLDate = endpointType.getHarvested();

        if (XMLDate == null) {
            /* Since there is no default value for this property, there is no
               need to set the date in the overview now. Return the zero epoch
               date in the UTC zone.
             */
            return zeroUTC;
        } else {
            // convert XMLGregorianCalendar to DateTime
            return new DateTime(XMLDate.toString(), DateTimeZone.UTC);
        }
    }

    @Override
    public void doneHarvesting(Boolean done) {

        /* Store the current date in a XMLGregorianCalendar object. Note: at
           the XML level, the date will be represented in ISO8601 format.
         */
        XMLGregorianCalendar xmlGregorianCalendar;

        try {
            // get current time in the UTC zone
            DateTime dateTime = new DateTime(DateTimeZone.UTC);

            // create XML calendar
            xmlGregorianCalendar = DatatypeFactory.newInstance().newXMLGregorianCalendar();

            // set the date related fields
            xmlGregorianCalendar.setDay(dateTime.getDayOfMonth());
            xmlGregorianCalendar.setMonth(dateTime.getMonthOfYear());
            xmlGregorianCalendar.setYear(dateTime.getYear());

            // set the calendar to UTC, this zone sets off 0 minutes from UTC
            xmlGregorianCalendar.setTimezone(0);

            // set the time related fields
            xmlGregorianCalendar.setHour(dateTime.getHourOfDay());
            xmlGregorianCalendar.setMinute(dateTime.getMinuteOfHour());
            xmlGregorianCalendar.setSecond(dateTime.getSecondOfMinute());

            // represent milliseconds as a fraction of a second
            BigDecimal s = BigDecimal.valueOf(dateTime.getMillisOfSecond());
            s = s.divide(BigDecimal.valueOf(1000));

            xmlGregorianCalendar.setFractionalSecond(s);

            // set the property representing the date of the attempt
            endpointType.setAttempted(xmlGregorianCalendar);

            if (done) {
                // successful attempt, also set attribute representing this
                endpointType.setHarvested(xmlGregorianCalendar);
            }

            xmlOverview.save();

        } catch (DatatypeConfigurationException e) {
            // report the error, we cannot continue
            Logger.getLogger(EndpointAdapter.class.getName()).log(Level.SEVERE, null, endpointType);
        }
    }

    @Override
    public long getCount() {

        // try to get attribute, use long reference type to check for null
        Long count = endpointType.getCount();

        if (count == null) {
            // attribute not XML cycle element, add it to it
            endpointType.setCount((long) 0);
            return 0;
        } else {
            return count;
        }
    }

    @Override
    public void setCount(long count) {

        // update the count
        endpointType.setCount(count);
        // update the overview
        xmlOverview.save();
    }

    @Override
    public long getIncrement() {

        // try to get attribute, use long reference type to check for null
        Long increment = endpointType.getIncrement();

        if (increment == null) {
            // attribute not XML cycle element, add it to it
            endpointType.setIncrement(0l);
            return 0;
        } else {
            return increment;
        }
    }

    @Override
    public void setIncrement(long increment) {

        // update the increment
        endpointType.setIncrement(increment);
        // update the overview
        xmlOverview.save();
    }
}