eionet.cr.web.action.HarvestSourceActionBean.java Source code

Java tutorial

Introduction

Here is the source code for eionet.cr.web.action.HarvestSourceActionBean.java

Source

/*
 * The contents of this file are subject to the Mozilla Public
 * License Version 1.1 (the "License"); you may not use this file
 * except in compliance with the License. You may obtain a copy of
 * the License at http://www.mozilla.org/MPL/
 *
 * Software distributed under the License is distributed on an "AS
 * IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
 * implied. See the License for the specific language governing
 * rights and limitations under the License.
 *
 * The Original Code is Content Registry 2.0.
 *
 * The Initial Owner of the Original Code is European Environment
 * Agency.  Portions created by Tieto Eesti are Copyright
 * (C) European Environment Agency.  All Rights Reserved.
 *
 * Contributor(s):
 * Jaanus Heinlaid, Tieto Eesti
 */
package eionet.cr.web.action;

import java.net.MalformedURLException;
import java.net.URL;
import java.util.ArrayList;
import java.util.LinkedHashMap;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;

import javax.servlet.http.HttpServletResponse;

import net.sourceforge.stripes.action.DefaultHandler;
import net.sourceforge.stripes.action.ForwardResolution;
import net.sourceforge.stripes.action.HandlesEvent;
import net.sourceforge.stripes.action.RedirectResolution;
import net.sourceforge.stripes.action.Resolution;
import net.sourceforge.stripes.action.StreamingResolution;
import net.sourceforge.stripes.action.UrlBinding;
import net.sourceforge.stripes.validation.SimpleError;
import net.sourceforge.stripes.validation.ValidationMethod;

import org.apache.commons.lang.StringUtils;
import org.quartz.SchedulerException;

import eionet.cr.config.GeneralConfig;
import eionet.cr.dao.DAOException;
import eionet.cr.dao.DAOFactory;
import eionet.cr.dao.FolderDAO;
import eionet.cr.dao.HarvestSourceDAO;
import eionet.cr.dataset.CreateDataset;
import eionet.cr.dto.HarvestDTO;
import eionet.cr.dto.HarvestSourceDTO;
import eionet.cr.dto.TripleDTO;
import eionet.cr.harvest.CurrentHarvests;
import eionet.cr.harvest.HarvestException;
import eionet.cr.harvest.scheduled.UrgentHarvestQueue;
import eionet.cr.harvest.util.RDFMediaTypes;
import eionet.cr.util.FolderUtil;
import eionet.cr.util.Pair;
import eionet.cr.util.URLUtil;
import eionet.cr.web.action.factsheet.FactsheetActionBean;
import eionet.cr.web.action.source.ViewSourceActionBean;
import eionet.cr.web.util.RDFGenerator;

/**
 * Controller for adding new harvest source and for exporting source triples.
 *
 * @author altnyris
 */
@UrlBinding("/source.action")
public class HarvestSourceActionBean extends AbstractActionBean {

    /** */
    public static final List<String> MEDIA_TYPES;

    /** */
    private HarvestSourceDTO harvestSource;
    private List<HarvestDTO> harvests;

    /** */
    private List<TripleDTO> sampleTriples;

    /** */
    private int intervalMultiplier;
    private static LinkedHashMap<Integer, String> intervalMultipliers;

    /** */
    private static final List<Pair<String, String>> tabs;
    private String selectedTab = "view";

    /** */
    private String urlBefore;

    /** */
    private enum ExportType {
        FILE, HOMESPACE
    };

    /** */
    private List<String> folders;
    private String exportType;
    private String datasetName;
    private String folder;
    private boolean overwriteDataset;

    private boolean schemaSource;

    /** */
    static {
        tabs = new LinkedList<Pair<String, String>>();
        tabs.add(new Pair<String, String>("view", "View"));
        tabs.add(new Pair<String, String>("sampleTriples", "Sample triples"));
        tabs.add(new Pair<String, String>("history", "History"));

        intervalMultipliers = new LinkedHashMap<Integer, String>();
        intervalMultipliers.put(new Integer(1), "minutes");
        intervalMultipliers.put(new Integer(60), "hours");
        intervalMultipliers.put(new Integer(1440), "days");
        intervalMultipliers.put(new Integer(10080), "weeks");

        MEDIA_TYPES = new ArrayList<String>();
        MEDIA_TYPES.add(null);
        MEDIA_TYPES.addAll(RDFMediaTypes.collection());
        MEDIA_TYPES.add("application/rss+xml");
        MEDIA_TYPES.add("application/atom+xml");
        MEDIA_TYPES.add("application/octet-stream");
        MEDIA_TYPES.add("text/plain");
    }

    /**
     *
     * @return HarvestSourceDTO
     */
    public HarvestSourceDTO getHarvestSource() {
        return harvestSource;
    }

    /**
     *
     * @param harvestSource
     */
    public void setHarvestSource(HarvestSourceDTO harvestSource) {
        this.harvestSource = harvestSource;
    }

    /**
     *
     * @return List<HarvestDTO>
     */
    public List<HarvestDTO> getHarvests() {
        return harvests;
    }

    /**
     *
     * @return Resolution
     * @throws DAOException
     */
    @DefaultHandler
    @HandlesEvent("view")
    public Resolution view() throws DAOException {
        return new RedirectResolution(ViewSourceActionBean.class).addParameter("uri", harvestSource.getUrl());
    }

    /**
     *
     * @return Resolution
     * @throws DAOException
     * @throws SchedulerException
     * @throws HarvestException
     * @throws MalformedURLException
     */
    public Resolution add() throws DAOException, SchedulerException, HarvestException, MalformedURLException {

        Resolution resolution = new ForwardResolution("/pages/addsource.jsp");
        if (isUserLoggedIn()) {
            if (isPostRequest()) {

                if (validateAddEdit()) {

                    // create new harvest source
                    boolean isSparqlEndpoint = false;
                    HarvestSourceDTO hSourceDTO = getHarvestSource();
                    if (hSourceDTO != null) {

                        isSparqlEndpoint = hSourceDTO.isSparqlEndpoint();

                        // escape spaces in URLs
                        if (hSourceDTO.getUrl() != null) {
                            hSourceDTO.setUrl(URLUtil.escapeIRI(hSourceDTO.getUrl()));
                        }

                        hSourceDTO.setOwner(getUserName());
                        // All Schema sources are also Priority sources
                        if (schemaSource) {
                            hSourceDTO.setPrioritySource(true);
                        }
                        // Add/remove source into/from inferencing ruleset
                        manageRuleset(hSourceDTO.getUrl());
                    }
                    factory.getDao(HarvestSourceDAO.class).addSource(hSourceDTO);

                    // set up the resolution
                    resolution = new ForwardResolution(HarvestSourcesActionBean.class);

                    // schedule urgent harvest, unless explicitly requested not to
                    if (!isSparqlEndpoint && getContext().getRequestParameter("dontHarvest") == null) {

                        UrgentHarvestQueue.addPullHarvest(getHarvestSource().getUrl());
                        addSystemMessage("Harvest source successfully created and scheduled for urgent harvest!");
                    } else {
                        addSystemMessage("Harvest source successfully created!");
                    }
                }
            }
        } else {
            addWarningMessage(getBundle().getString("not.logged.in"));
        }

        return resolution;
    }

    /**
     *
     * @param url
     * @throws DAOException
     */
    private void manageRuleset(String url) throws DAOException {

        if (GeneralConfig.isUseInferencing()) {
            boolean isAlreadyInRuleset = factory.getDao(HarvestSourceDAO.class).isSourceInInferenceRule(url);
            if (schemaSource && !isAlreadyInRuleset) {
                factory.getDao(HarvestSourceDAO.class).addSourceIntoInferenceRule(url);
            } else if (!schemaSource && isAlreadyInRuleset) {
                factory.getDao(HarvestSourceDAO.class).removeSourceFromInferenceRule(url);
            }
        }
    }

    /**
     *
     * @return Resolution
     */
    public Resolution export() throws DAOException {

        Resolution resolution = new ForwardResolution("/pages/export.jsp");

        // process further only if exportType has been specified
        if (!StringUtils.isBlank(exportType)) {

            // process further only if source URL has been specified
            if (harvestSource != null && !StringUtils.isBlank(harvestSource.getUrl())) {

                // if exporting to file, generate and stream RDF into servlet
                // response
                if (ExportType.FILE.toString().equals(exportType)) {

                    resolution = (new StreamingResolution("application/rdf+xml") {

                        @Override
                        public void stream(HttpServletResponse response) throws Exception {
                            RDFGenerator.generate(harvestSource.getUrl(), response.getOutputStream());
                        }
                    }).setFilename("rdf.xml");
                } else if (ExportType.HOMESPACE.toString().equals(exportType)) {
                    try {
                        // If datasetName not provided, then extract it from source url
                        if (StringUtils.isBlank(datasetName)) {
                            datasetName = StringUtils.substringAfterLast(harvestSource.getUrl(), "/");
                        }
                        // Construct dataset uri
                        if (!StringUtils.isBlank(datasetName) && !StringUtils.isBlank(folder)) {
                            String dataset = folder + "/" + StringUtils.replace(datasetName, " ", "%20");

                            List<String> selectedFiles = new ArrayList<String>();
                            selectedFiles.add(harvestSource.getUrl());

                            CreateDataset cd = new CreateDataset(null, getUser());
                            cd.create(datasetName, dataset, folder, selectedFiles, overwriteDataset, null);

                            return new RedirectResolution(FactsheetActionBean.class).addParameter("uri", dataset);
                        }
                    } catch (Exception e) {
                        throw new DAOException(e.getMessage(), e);
                    }
                } else {
                    throw new IllegalArgumentException("Unknown export type: " + exportType);
                }
            }
        } else if (getUser() != null) {
            folders = FolderUtil.getUserAccessibleFolders(getUser());
        }

        return resolution;
    }

    /**
     * @throws DAOException
     */
    @ValidationMethod(on = { "export" })
    public void validateSaveEvent() throws DAOException {

        // the below validation is relevant only when exported to HOMESPACE
        if (exportType == null || ExportType.FILE.toString().equals(exportType)) {
            return;
        }

        // for all the above POST events, user must be authorized
        if (getUser() == null) {
            addGlobalValidationError("User not logged in!");
            return;
        }

        // no folder selected
        if (StringUtils.isBlank(folder)) {
            addGlobalValidationError("Folder not selected!");
            return;
        }

        // Check if file already exists
        // If datasetName not provided, then extract it from source url
        if (StringUtils.isBlank(datasetName)) {
            datasetName = StringUtils.substringAfterLast(harvestSource.getUrl(), "/");
        }
        if (!overwriteDataset && !StringUtils.isBlank(datasetName) && !StringUtils.isBlank(folder)) {
            String datasetUri = folder + "/" + StringUtils.replace(datasetName, " ", "%20");
            boolean exists = DAOFactory.get().getDao(FolderDAO.class).fileOrFolderExists(datasetUri);
            if (exists) {
                addGlobalValidationError(
                        "File named \"" + datasetName + "\" already exists in folder \"" + folder + "\"!");
            }
        }

        folders = FolderUtil.getUserAccessibleFolders(getUser());

        // if any validation errors were set above, make sure the right resolution is returned
        if (hasValidationErrors()) {
            Resolution resolution = new ForwardResolution("/pages/export.jsp");
            getContext().setSourcePageResolution(resolution);
        }
    }

    /**
     *
     * @return boolean
     */
    public boolean validateAddEdit() {

        if (isPostRequest()) {

            String urlString = harvestSource.getUrl();
            if (StringUtils.isBlank(urlString)) {
                addGlobalValidationError(new SimpleError("URL missing!"));
            } else {
                try {
                    URL url = new URL(urlString);
                    if (url.getRef() != null) {
                        addGlobalValidationError(new SimpleError("URL with a fragment part not allowed!"));
                    }

                    if (!StringUtils.equals(urlBefore, urlString)
                            && URLUtil.isNotExisting(urlString, harvestSource.isSparqlEndpoint())) {
                        addGlobalValidationError(new SimpleError("There is no resource existing behind this URL!"));
                    }

                    Integer intervalMinutes = harvestSource.getIntervalMinutes();
                    if (intervalMinutes != null) {
                        if (intervalMinutes.intValue() < 0 || intervalMultiplier < 0) {
                            addGlobalValidationError(new SimpleError("Harvest interval must be >= 0"));
                        } else {
                            harvestSource.setIntervalMinutes(
                                    Integer.valueOf(intervalMinutes.intValue() * intervalMultiplier));
                        }
                    } else {
                        harvestSource.setIntervalMinutes(Integer.valueOf(0));
                    }
                } catch (MalformedURLException e) {
                    addGlobalValidationError(new SimpleError("Invalid URL!"));
                }
            }
        }

        return getContext().getValidationErrors() == null || getContext().getValidationErrors().isEmpty();
    }

    /**
     * @return the sampleTriples
     */
    public List<TripleDTO> getSampleTriples() {
        return sampleTriples;
    }

    /**
     * @param intervalMultiplier the intervalMultiplier to set
     */
    public void setIntervalMultiplier(int intervalMultiplier) {
        this.intervalMultiplier = intervalMultiplier;
    }

    /**
     *
     * @return Map<Integer,String>
     */
    public Map<Integer, String> getIntervalMultipliers() {

        return intervalMultipliers;
    }

    /**
     *
     * @return int
     */
    public int getSelectedIntervalMultiplier() {
        return getIntervalMultipliers().keySet().iterator().next().intValue();
    }

    /**
     *
     * @return String
     */
    public String getIntervalMinutesDisplay() {

        String result = "";
        if (harvestSource != null && harvestSource.getIntervalMinutes() != null) {
            result = getMinutesDisplay(harvestSource.getIntervalMinutes().intValue());
        }

        return result;
    }

    /**
     *
     * @param minutes
     * @return
     */
    private static String getMinutesDisplay(int minutes) {

        int days = minutes / 1440;
        minutes = minutes - (days * 1440);
        int hours = minutes / 60;
        minutes = minutes - (hours * 60);

        StringBuffer buf = new StringBuffer();
        if (days > 0) {
            buf.append(days).append(days == 1 ? " day" : " days");
        }
        if (hours > 0) {
            buf.append(buf.length() > 0 ? ", " : "").append(hours).append(hours == 1 ? " hour" : " hours");
        }
        if (minutes > 0) {
            buf.append(buf.length() > 0 ? ", " : "").append(minutes).append(minutes == 1 ? " minute" : " minutes");
        }

        return buf.toString();
    }

    /**
     * Returns all the valid media types.
     *
     * @return
     */
    public List<String> getMediaTypes() {
        return MEDIA_TYPES;
    }

    /**
     * @return the tabs
     */
    public List<Pair<String, String>> getTabs() {
        return HarvestSourceActionBean.tabs;
    }

    /**
     * @return the selectedTab
     */
    public String getSelectedTab() {
        return selectedTab;
    }

    /**
     * @param selectedTab the selectedTab to set
     */
    public void setSelectedTab(String selectedTab) {
        this.selectedTab = selectedTab;
    }

    /**
     * @return the exportType
     */
    public String getExportType() {
        return exportType;
    }

    /**
     * @param exportType the exportType to set
     */
    public void setExportType(String exportType) {
        this.exportType = exportType;
    }

    public boolean isSchemaSource() {
        return schemaSource;
    }

    public void setSchemaSource(boolean schemaSource) {
        this.schemaSource = schemaSource;
    }

    /**
     *
     * @return boolean
     */
    public boolean isCurrentlyHarvested() {
        String uri = harvestSource == null ? null : harvestSource.getUrl();
        return uri == null ? false : (CurrentHarvests.contains(uri) || UrgentHarvestQueue.isInQueue(uri));
    }

    /**
     * @param urlBefore the urlBefore to set
     */
    public void setUrlBefore(String urlBefore) {
        this.urlBefore = urlBefore;
    }

    public String getDatasetName() {
        return datasetName;
    }

    public void setDatasetName(String datasetName) {
        this.datasetName = datasetName;
    }

    public boolean getOverwriteDataset() {
        return overwriteDataset;
    }

    public void setOverwriteDataset(boolean overwriteDataset) {
        this.overwriteDataset = overwriteDataset;
    }

    public List<String> getFolders() {
        return folders;
    }

    public void setFolders(List<String> folders) {
        this.folders = folders;
    }

    public String getFolder() {
        return folder;
    }

    public void setFolder(String folder) {
        this.folder = folder;
    }
}