org.jaqpot.core.service.resource.DatasetResource.java Source code

Java tutorial

Introduction

Here is the source code for org.jaqpot.core.service.resource.DatasetResource.java

Source

/*
 *
 * JAQPOT Quattro
 *
 * JAQPOT Quattro and the components shipped with it (web applications and beans)
 * are licensed by GPL v3 as specified hereafter. Additional components may ship
 * with some other licence as will be specified therein.
 *
 * Copyright (C) 2014-2015 KinkyDesign (Charalampos Chomenidis, Pantelis Sopasakis)
 *
 * 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, either version 3 of the License, or
 * (at your option) any later version.
 *
 * 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.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program.  If not, see <http://www.gnu.org/licenses/>.
 * 
 * Source code:
 * The source code of JAQPOT Quattro is available on github at:
 * https://github.com/KinkyDesign/JaqpotQuattro
 * All source files of JAQPOT Quattro that are stored on github are licensed
 * with the aforementioned licence. 
 */
package org.jaqpot.core.service.resource;

import com.wordnik.swagger.annotations.Api;
import com.wordnik.swagger.annotations.ApiOperation;
import com.wordnik.swagger.annotations.ApiParam;
import com.wordnik.swagger.annotations.ApiResponse;
import com.wordnik.swagger.annotations.ApiResponses;
import java.net.URI;
import java.net.URISyntaxException;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Optional;
import java.util.UUID;
import java.util.concurrent.CancellationException;
import java.util.concurrent.ExecutionException;
import java.util.logging.Level;
import java.util.logging.Logger;
import java.util.stream.Collectors;
import javax.ejb.EJB;
import javax.inject.Inject;
import javax.validation.constraints.NotNull;
import javax.ws.rs.BadRequestException;
import javax.ws.rs.Consumes;
import javax.ws.rs.DELETE;
import javax.ws.rs.FormParam;
import javax.ws.rs.GET;
import javax.ws.rs.HeaderParam;
import javax.ws.rs.InternalServerErrorException;
import javax.ws.rs.NotFoundException;
import javax.ws.rs.POST;
import javax.ws.rs.Path;
import javax.ws.rs.PathParam;
import javax.ws.rs.Produces;
import javax.ws.rs.QueryParam;
import javax.ws.rs.client.Client;
import javax.ws.rs.client.Entity;
import javax.ws.rs.core.Context;
import javax.ws.rs.core.MediaType;
import javax.ws.rs.core.Response;
import javax.ws.rs.core.SecurityContext;
import org.apache.commons.validator.routines.UrlValidator;
import org.jaqpot.core.data.AlgorithmHandler;
import org.jaqpot.core.data.DatasetHandler;
import org.jaqpot.core.data.ModelHandler;
import org.jaqpot.core.data.ReportHandler;
import org.jaqpot.core.data.UserHandler;
import org.jaqpot.core.model.MetaInfo;
import org.jaqpot.core.model.Model;
import org.jaqpot.core.model.Report;
import org.jaqpot.core.model.User;
import org.jaqpot.core.model.builder.MetaInfoBuilder;
import org.jaqpot.core.model.dto.dataset.DataEntry;
import org.jaqpot.core.model.dto.dataset.Dataset;
import org.jaqpot.core.model.dto.jpdi.TrainingRequest;
import org.jaqpot.core.model.facades.UserFacade;
import org.jaqpot.core.model.factory.DatasetFactory;
import org.jaqpot.core.model.util.ROG;
import org.jaqpot.core.service.annotations.Authorize;
import org.jaqpot.core.service.annotations.UnSecure;
import org.jaqpot.core.service.client.jpdi.JPDIClient;
import org.jaqpot.core.service.exceptions.QuotaExceededException;

/**
 *
 * @author Charalampos Chomenidis
 * @author Pantelis Sopasakis
 */
@Path("dataset")
@Api(value = "/dataset", description = "Dataset API")
@Produces({ "application/json", "text/uri-list" })
@Authorize
public class DatasetResource {

    private static final Logger LOG = Logger.getLogger(DatasetResource.class.getName());

    @EJB
    DatasetHandler datasetHandler;

    @EJB
    UserHandler userHandler;

    @EJB
    ModelHandler modelHandler;

    @EJB
    AlgorithmHandler algorithmHandler;

    @EJB
    ReportHandler reportHandler;

    @Inject
    @UnSecure
    Client client;

    @Inject
    JPDIClient jpdiClient;

    @Context
    SecurityContext securityContext;

    @GET
    @Produces({ MediaType.APPLICATION_JSON, "text/uri-list" })
    @ApiOperation(value = "Finds all Datasets", notes = "Finds all Datasets in the DB of Jaqpot and returns them in a list. Results can be obtained "
            + "either in the form of a URI list or as a JSON list as specified by the Accept HTTP header. "
            + "In the latter case, a list will be returned containing only the IDs of the datasets, their metadata "
            + "and their ontological classes. The parameter max, which specifies the maximum number of IDs to be "
            + "listed is limited to 500; if the client specifies a larger value, an HTTP Warning Header will be "
            + "returned (RFC 2616) with code P670.", response = Dataset.class, responseContainer = "List", position = 1)
    @ApiResponses(value = {
            @ApiResponse(code = 200, message = "Datasets found and are listed in the response body"),
            @ApiResponse(code = 401, message = "You are not authorized to access this resource"),
            @ApiResponse(code = 403, message = "This request is forbidden (e.g., no authentication token is provided)"),
            @ApiResponse(code = 500, message = "Internal server error - this request cannot be served.") })
    public Response listDatasets(
            @ApiParam(value = "Authorization token") @HeaderParam("subjectid") String subjectId,
            @ApiParam(value = "start", defaultValue = "0") @QueryParam("start") Integer start,
            @ApiParam(value = "max - the server imposes an upper limit of 500 on this "
                    + "parameter.", defaultValue = "10") @QueryParam("max") Integer max) {
        start = start != null ? start : 0;
        if (max == null || max > 500) {
            max = 500;
        }
        String creator = securityContext.getUserPrincipal().getName();
        return Response.ok(datasetHandler.listMetaOfCreator(creator, start, max)).status(Response.Status.OK)
                .header("total", datasetHandler.countAllOfCreator(creator)).build();

    }

    @GET
    @Produces({ "text/csv", MediaType.APPLICATION_JSON })
    @Path("/{id}")
    @ApiOperation(value = "Finds Dataset by Id", notes = "Finds specified Dataset", response = Dataset.class)
    public Response getDataset(@ApiParam(value = "Authorization token") @HeaderParam("subjectid") String subjectId,
            @PathParam("id") String id, @QueryParam("rowStart") Integer rowStart,
            @QueryParam("rowMax") Integer rowMax, @QueryParam("colStart") Integer colStart,
            @QueryParam("colMax") Integer colMax, @QueryParam("stratify") String stratify,
            @QueryParam("seed") Long seed, @QueryParam("folds") Integer folds,
            @QueryParam("target_feature") String targetFeature) {
        Dataset dataset = datasetHandler.find(id, rowStart, rowMax, colStart, colMax, stratify, seed, folds,
                targetFeature);
        if (dataset == null) {
            throw new NotFoundException("Could not find Dataset with id:" + id);
        }
        return Response.ok(dataset).build();
    }

    @GET
    @Path("/featured")
    @Produces({ MediaType.APPLICATION_JSON, "text/uri-list" })
    @ApiOperation(value = "Finds all Datasets", notes = "Finds Featured Datasets in the DB of Jaqpot and returns them in a list. Results can be obtained "
            + "either in the form of a URI list or as a JSON list as specified by the Accept HTTP header. "
            + "In the latter case, a list will be returned containing only the IDs of the datasets, their metadata "
            + "and their ontological classes. The parameter max, which specifies the maximum number of IDs to be "
            + "listed is limited to 500; if the client specifies a larger value, an HTTP Warning Header will be "
            + "returned (RFC 2616) with code P670.", response = Dataset.class, responseContainer = "List", position = 1)
    @ApiResponses(value = {
            @ApiResponse(code = 200, message = "Datasets found and are listed in the response body"),
            @ApiResponse(code = 401, message = "You are not authorized to access this resource"),
            @ApiResponse(code = 403, message = "This request is forbidden (e.g., no authentication token is provided)"),
            @ApiResponse(code = 500, message = "Internal server error - this request cannot be served.") })
    public Response listFeaturedDatasets(
            @ApiParam(value = "Authorization token") @HeaderParam("subjectid") String subjectId,
            @ApiParam(value = "start", defaultValue = "0") @QueryParam("start") Integer start,
            @ApiParam(value = "max - the server imposes an upper limit of 500 on this "
                    + "parameter.", defaultValue = "10") @QueryParam("max") Integer max) {
        start = start != null ? start : 0;
        boolean doWarnMax = false;
        if (max == null || max > 500) {
            max = 500;
        }
        return Response.ok(datasetHandler.findFeatured(start, max)).status(Response.Status.OK)
                .header("total", datasetHandler.countFeatured()).build();

    }

    @GET
    @Produces(MediaType.APPLICATION_JSON)
    @Path("/{id}/features")
    @ApiOperation(value = "Finds Dataset by Id", notes = "Finds specified Dataset", response = Dataset.class)
    public Response getDatasetFeatures(
            @ApiParam(value = "Authorization token") @HeaderParam("subjectid") String subjectId,
            @PathParam("id") String id) {
        Dataset dataset = datasetHandler.find(id);
        if (dataset == null) {
            throw new NotFoundException("Could not find Dataset with id:" + id);
        }
        return Response.ok(dataset.getFeatures()).build();
    }

    @GET
    @Produces(MediaType.APPLICATION_JSON)
    @Path("/{id}/meta")
    @ApiOperation(value = "Finds Dataset by Id", notes = "Finds specified Dataset", response = Dataset.class)
    public Response getDatasetMeta(
            @ApiParam(value = "Authorization token") @HeaderParam("subjectid") String subjectId,
            @PathParam("id") String id) {
        Dataset dataset = datasetHandler.find(id);
        dataset.setDataEntry(new ArrayList<>());
        if (dataset == null) {
            throw new NotFoundException("Could not find Dataset with id:" + id);
        }
        return Response.ok(dataset).build();
    }

    @POST
    @Consumes(MediaType.APPLICATION_JSON)
    @Produces({ "text/uri-list", MediaType.APPLICATION_JSON })
    @ApiOperation(value = "Creates a new Dataset", notes = "The new Dataset created will be assigned on a random generated Id", response = Dataset.class)
    public Response createDataset(
            @ApiParam(value = "Authorization token") @HeaderParam("subjectid") String subjectId, Dataset dataset)
            throws URISyntaxException, QuotaExceededException {

        User user = userHandler.find(securityContext.getUserPrincipal().getName());
        long datasetCount = datasetHandler.countAllOfCreator(user.getId());
        int maxAllowedDatasets = new UserFacade(user).getMaxDatasets();

        if (datasetCount > maxAllowedDatasets) {
            LOG.info(String.format("User %s has %d datasets while maximum is %d", user.getId(), datasetCount,
                    maxAllowedDatasets));
            throw new QuotaExceededException("Dear " + user.getId()
                    + ", your quota has been exceeded; you already have " + datasetCount + " datasets. "
                    + "No more than " + maxAllowedDatasets + " are allowed with your subscription.");
        }

        ROG randomStringGenerator = new ROG(true);
        dataset.setId(randomStringGenerator.nextString(14));
        dataset.setFeatured(Boolean.FALSE);
        if (dataset.getMeta() == null) {
            dataset.setMeta(new MetaInfo());
        }
        dataset.getMeta().setCreators(new HashSet<>(Arrays.asList(securityContext.getUserPrincipal().getName())));
        dataset.setVisible(Boolean.TRUE);
        datasetHandler.create(dataset);

        return Response.created(new URI(dataset.getId())).entity(dataset).build();

    }

    @POST
    @Path("/empty")
    @Produces({ "text/uri-list", MediaType.APPLICATION_JSON })
    @ApiOperation(value = "Creates a new empty Dataset", notes = "The new empty Dataset created will be assigned on a random generated Id", response = Dataset.class)
    public Response createEmptyDataset(
            @ApiParam(value = "Authorization token") @HeaderParam("subjectid") String subjectId,
            @FormParam("title") String title, @FormParam("description") String description)
            throws URISyntaxException, QuotaExceededException {

        User user = userHandler.find(securityContext.getUserPrincipal().getName());
        long datasetCount = datasetHandler.countAllOfCreator(user.getId());
        int maxAllowedDatasets = new UserFacade(user).getMaxDatasets();

        if (datasetCount > maxAllowedDatasets) {
            LOG.info(String.format("User %s has %d datasets while maximum is %d", user.getId(), datasetCount,
                    maxAllowedDatasets));
            throw new QuotaExceededException("Dear " + user.getId()
                    + ", your quota has been exceeded; you already have " + datasetCount + " datasets. "
                    + "No more than " + maxAllowedDatasets + " are allowed with your subscription.");
        }

        Dataset emptyDataset = DatasetFactory.createEmpty(0);
        ROG randomStringGenerator = new ROG(true);
        emptyDataset.setId(randomStringGenerator.nextString(14));
        emptyDataset.setFeatured(Boolean.FALSE);
        emptyDataset.setMeta(MetaInfoBuilder.builder().addTitles(title).addDescriptions(description).build());

        emptyDataset.getMeta()
                .setCreators(new HashSet<>(Arrays.asList(securityContext.getUserPrincipal().getName())));
        emptyDataset.setVisible(Boolean.TRUE);
        datasetHandler.create(emptyDataset);

        return Response.created(new URI(emptyDataset.getId())).entity(emptyDataset).build();
    }

    @POST
    @Path("/merge")
    @ApiOperation(value = "Merges Datasets")
    public Response mergeDatasets(@FormParam("dataset_uris") String datasetURIs,
            @HeaderParam("subjectid") String subjectId) throws URISyntaxException, QuotaExceededException {

        User user = userHandler.find(securityContext.getUserPrincipal().getName());
        long datasetCount = datasetHandler.countAllOfCreator(user.getId());
        int maxAllowedDatasets = new UserFacade(user).getMaxDatasets();

        if (datasetCount > maxAllowedDatasets) {
            LOG.info(String.format("User %s has %d datasets while maximum is %d", user.getId(), datasetCount,
                    maxAllowedDatasets));
            throw new QuotaExceededException("Dear " + user.getId()
                    + ", your quota has been exceeded; you already have " + datasetCount + " datasets. "
                    + "No more than " + maxAllowedDatasets + " are allowed with your subscription.");
        }

        String[] datasets = datasetURIs.split(",");
        Dataset dataset = null;
        for (String datasetURI : datasets) {
            Dataset d = client.target(datasetURI).request().accept(MediaType.APPLICATION_JSON)
                    .header("subjectid", subjectId).get(Dataset.class);
            dataset = DatasetFactory.mergeRows(dataset, d);
        }
        ROG randomStringGenerator = new ROG(true);
        dataset.setId(randomStringGenerator.nextString(14));
        dataset.setFeatured(Boolean.FALSE);
        dataset.setVisible(true);
        if (dataset.getMeta() == null) {
            dataset.setMeta(new MetaInfo());
        }
        dataset.getMeta().setCreators(new HashSet<>(Arrays.asList(securityContext.getUserPrincipal().getName())));

        datasetHandler.create(dataset);

        return Response.created(new URI(dataset.getId())).entity(dataset).build();

    }

    @DELETE
    @Path("/{id}")
    @ApiOperation("Deletes dataset")
    @Authorize
    public Response deleteDataset(
            @ApiParam(value = "Authorization token") @HeaderParam("subjectid") String subjectId,
            @PathParam("id") String id) {
        Dataset ds = datasetHandler.find(id);
        if (ds == null) {
            throw new NotFoundException("Dataset with id:" + id + " was not found on the server.");
        }
        String userName = securityContext.getUserPrincipal().getName();
        if (!ds.getMeta().getCreators().contains(userName)) {
            return Response.status(Response.Status.FORBIDDEN)
                    .entity("You cannot delete a Dataset that was not created by you.").build();
        }
        datasetHandler.remove(ds);
        return Response.ok().build();
    }

    @POST
    @Path("/{id}/qprf")
    @ApiOperation("Creates QPRF Report")
    @Authorize
    public Response createQPRFReport(
            @ApiParam(value = "Authorization token") @HeaderParam("subjectid") String subjectId,
            @PathParam("id") String id, @FormParam("substance_uri") String substanceURI,
            @FormParam("title") String title, @FormParam("description") String description)
            throws QuotaExceededException {

        User user = userHandler.find(securityContext.getUserPrincipal().getName());
        long reportCount = reportHandler.countAllOfCreator(user.getId());
        int maxAllowedReports = new UserFacade(user).getMaxReports();

        if (reportCount > maxAllowedReports) {
            LOG.info(String.format("User %s has %d algorithms while maximum is %d", user.getId(), reportCount,
                    maxAllowedReports));
            throw new QuotaExceededException("Dear " + user.getId()
                    + ", your quota has been exceeded; you already have " + reportCount + " reports. "
                    + "No more than " + maxAllowedReports + " are allowed with your subscription.");
        }

        Dataset ds = datasetHandler.find(id);
        if (ds == null) {
            throw new NotFoundException("Dataset with id:" + id + " was not found on the server.");
        }
        if (ds.getByModel() == null || ds.getByModel().isEmpty()) {
            throw new BadRequestException("Selected dataset was not produced by a valid model.");
        }
        Model model = modelHandler.find(ds.getByModel());
        if (model == null) {
            throw new BadRequestException("Selected dataset was not produced by a valid model.");
        }
        String datasetURI = model.getDatasetUri();
        if (datasetURI == null || datasetURI.isEmpty()) {
            throw new BadRequestException(
                    "The model that created this dataset does not point to a valid training dataset.");
        }
        Dataset trainingDS = client.target(datasetURI).request().accept(MediaType.APPLICATION_JSON)
                .header("subjectid", subjectId).get(Dataset.class);
        if (trainingDS == null) {
            throw new BadRequestException(
                    "The model that created this dataset does not point to a valid training dataset.");
        }

        if (model.getTransformationModels() != null) {
            for (String transModelURI : model.getTransformationModels()) {
                Model transModel = modelHandler.find(transModelURI.split("model/")[1]);
                if (transModel == null) {
                    throw new NotFoundException(
                            "Transformation model with id:" + transModelURI + " was not found.");
                }
                try {
                    trainingDS = jpdiClient
                            .predict(trainingDS, transModel, trainingDS.getMeta(), UUID.randomUUID().toString())
                            .get();
                } catch (InterruptedException ex) {
                    LOG.log(Level.SEVERE, "JPDI Training procedure interupted", ex);
                    throw new InternalServerErrorException("JPDI Training procedure interupted", ex);
                } catch (ExecutionException ex) {
                    LOG.log(Level.SEVERE, "Training procedure execution error", ex.getCause());
                    throw new InternalServerErrorException("JPDI Training procedure error", ex.getCause());
                } catch (CancellationException ex) {
                    throw new InternalServerErrorException("Procedure was cancelled");
                }
            }
        }

        List<String> retainableFeatures = new ArrayList<>(model.getIndependentFeatures());
        retainableFeatures.addAll(model.getDependentFeatures());

        trainingDS.getDataEntry().parallelStream().forEach(dataEntry -> {
            dataEntry.getValues().keySet().retainAll(retainableFeatures);
        });

        DataEntry dataEntry = ds.getDataEntry().stream()
                .filter(de -> de.getCompound().getURI().equals(substanceURI)).findFirst()
                .orElseThrow(() -> new BadRequestException(""));

        trainingDS.getDataEntry().add(dataEntry);
        trainingDS.getMeta().setCreators(new HashSet<>(Arrays.asList(user.getId())));

        Map<String, Object> parameters = new HashMap<>();

        UrlValidator urlValidator = new UrlValidator();
        if (urlValidator.isValid(substanceURI)) {
            Dataset structures = client.target(substanceURI + "/structures").request()
                    .accept(MediaType.APPLICATION_JSON).header("subjectid", subjectId).get(Dataset.class);
            List<Map<String, String>> structuresList = structures.getDataEntry().stream().map(de -> {
                String compound = de.getCompound().getURI();
                String casrn = Optional.ofNullable(de.getValues().get(
                        "https://apps.ideaconsult.net/enmtest/feature/http%3A%2F%2Fwww.opentox.org%2Fapi%2F1.1%23CASRNDefault"))
                        .orElse("").toString();
                String einecs = Optional.ofNullable(de.getValues().get(
                        "https://apps.ideaconsult.net/enmtest/feature/http%3A%2F%2Fwww.opentox.org%2Fapi%2F1.1%23EINECSDefault"))
                        .orElse("").toString();
                String iuclid5 = Optional.ofNullable(de.getValues().get(
                        "https://apps.ideaconsult.net/enmtest/feature/http%3A%2F%2Fwww.opentox.org%2Fapi%2F1.1%23IUCLID5_UUIDDefault"))
                        .orElse("").toString();
                String inchi = Optional.ofNullable(de.getValues().get(
                        "https://apps.ideaconsult.net/enmtest/feature/http%3A%2F%2Fwww.opentox.org%2Fapi%2F1.1%23InChI_stdDefault"))
                        .orElse("").toString();
                String reach = Optional.ofNullable(de.getValues().get(
                        "https://apps.ideaconsult.net/enmtest/feature/http%3A%2F%2Fwww.opentox.org%2Fapi%2F1.1%23REACHRegistrationDateDefault"))
                        .orElse("").toString();
                String iupac = Optional.ofNullable(de.getValues().get(
                        "https://apps.ideaconsult.net/enmtest/feature/http%3A%2F%2Fwww.opentox.org%2Fapi%2F1.1%23IUPACNameDefault"))
                        .orElse("").toString();

                Map<String, String> structuresMap = new HashMap<>();
                structuresMap.put("Compound", compound);
                structuresMap.put("CasRN", casrn);
                structuresMap.put("EC number", einecs);
                structuresMap.put("REACH registration date", reach);
                structuresMap.put("IUCLID 5 Reference substance UUID", iuclid5);
                structuresMap.put("Std. InChI", inchi);
                structuresMap.put("IUPAC name", iupac);

                return structuresMap;
            }).collect(Collectors.toList());
            parameters.put("structures", structuresList);
        } else {
            List<Map<String, String>> structuresList = new ArrayList<>();
            Map<String, String> structuresMap = new HashMap<>();
            structuresMap.put("Compound", "");
            structuresMap.put("CasRN", "");
            structuresMap.put("EC number", "");
            structuresMap.put("REACH registration date", "");
            structuresMap.put("IUCLID 5 Reference substance UUID", "");
            structuresMap.put("Std. InChI", "");
            structuresMap.put("IUPAC name", "");
            structuresList.add(structuresMap);
            parameters.put("structures", structuresList);
        }

        parameters.put("predictedFeature", model.getPredictedFeatures().stream().findFirst()
                .orElseThrow(() -> new BadRequestException("Model does not have a valid predicted feature")));

        parameters.put("algorithm", algorithmHandler.find(model.getAlgorithm().getId()));
        parameters.put("substanceURI", substanceURI);
        if (model.getLinkedModels() != null && !model.getLinkedModels().isEmpty()) {
            Model doa = modelHandler.find(model.getLinkedModels().get(0).split("model/")[1]);
            if (doa != null) {
                parameters.put("doaURI", doa.getPredictedFeatures().get(0));
                parameters.put("doaMethod", doa.getAlgorithm().getId());
            }
        }
        TrainingRequest request = new TrainingRequest();

        request.setDataset(trainingDS);
        request.setParameters(parameters);
        request.setPredictionFeature(model.getDependentFeatures().stream().findFirst()
                .orElseThrow(() -> new BadRequestException("Model does not have a valid prediction feature")));

        Report report = client.target("http://147.102.82.32:8094/pws/qprf").request()
                .header("Content-Type", MediaType.APPLICATION_JSON).accept(MediaType.APPLICATION_JSON)
                .post(Entity.json(request), Report.class);

        report.setMeta(MetaInfoBuilder.builder().addTitles(title).addDescriptions(description)
                .addCreators(securityContext.getUserPrincipal().getName()).build());
        report.setId(new ROG(true).nextString(15));
        report.setVisible(Boolean.TRUE);
        reportHandler.create(report);

        return Response.ok(report).build();
    }

    @POST
    @Path("/{id}/qprf-dummy")
    @ApiOperation("Creates QPRF Report")
    @Authorize
    public Response createQPRFReportDummy(
            @ApiParam(value = "Authorization token") @HeaderParam("subjectid") String subjectId,
            @PathParam("id") String id, @FormParam("substance_uri") String substanceURI,
            @FormParam("title") String title, @FormParam("description") String description) {

        Dataset ds = datasetHandler.find(id);
        if (ds == null) {
            throw new NotFoundException("Dataset with id:" + id + " was not found on the server.");
        }
        if (ds.getByModel() == null || ds.getByModel().isEmpty()) {
            throw new BadRequestException("Selected dataset was not produced by a valid model.");
        }
        Model model = modelHandler.find(ds.getByModel());
        if (model == null) {
            throw new BadRequestException("Selected dataset was not produced by a valid model.");
        }
        String datasetURI = model.getDatasetUri();
        if (datasetURI == null || datasetURI.isEmpty()) {
            throw new BadRequestException(
                    "The model that created this dataset does not point to a valid training dataset.");
        }
        Dataset trainingDS = client.target(datasetURI).request().accept(MediaType.APPLICATION_JSON)
                .header("subjectid", subjectId).get(Dataset.class);
        if (trainingDS == null) {
            throw new BadRequestException(
                    "The model that created this dataset does not point to a valid training dataset.");
        }

        if (model.getTransformationModels() != null) {
            for (String transModelURI : model.getTransformationModels()) {
                Model transModel = modelHandler.find(transModelURI.split("model/")[1]);
                if (transModel == null) {
                    throw new NotFoundException(
                            "Transformation model with id:" + transModelURI + " was not found.");
                }
                try {
                    trainingDS = jpdiClient
                            .predict(trainingDS, transModel, trainingDS.getMeta(), UUID.randomUUID().toString())
                            .get();
                } catch (InterruptedException ex) {
                    LOG.log(Level.SEVERE, "JPDI Training procedure interupted", ex);
                    throw new InternalServerErrorException("JPDI Training procedure interupted", ex);
                } catch (ExecutionException ex) {
                    LOG.log(Level.SEVERE, "Training procedure execution error", ex.getCause());
                    throw new InternalServerErrorException("JPDI Training procedure error", ex.getCause());
                } catch (CancellationException ex) {
                    throw new InternalServerErrorException("Procedure was cancelled");
                }
            }
        }

        List<String> retainableFeatures = new ArrayList<>(model.getIndependentFeatures());
        retainableFeatures.addAll(model.getDependentFeatures());

        trainingDS.getDataEntry().parallelStream().forEach(dataEntry -> {
            dataEntry.getValues().keySet().retainAll(retainableFeatures);
        });

        DataEntry dataEntry = ds.getDataEntry().stream()
                .filter(de -> de.getCompound().getURI().equals(substanceURI)).findFirst()
                .orElseThrow(() -> new BadRequestException(""));

        trainingDS.getDataEntry().add(dataEntry);

        Map<String, Object> parameters = new HashMap<>();

        UrlValidator urlValidator = new UrlValidator();
        if (urlValidator.isValid(substanceURI)) {
            Dataset structures = client.target(substanceURI + "/structures").request()
                    .accept(MediaType.APPLICATION_JSON).header("subjectid", subjectId).get(Dataset.class);
            List<Map<String, String>> structuresList = structures.getDataEntry().stream().map(de -> {
                String compound = de.getCompound().getURI();
                String casrn = Optional.ofNullable(de.getValues().get(
                        "https://apps.ideaconsult.net/enmtest/feature/http%3A%2F%2Fwww.opentox.org%2Fapi%2F1.1%23CASRNDefault"))
                        .orElse("").toString();
                String einecs = Optional.ofNullable(de.getValues().get(
                        "https://apps.ideaconsult.net/enmtest/feature/http%3A%2F%2Fwww.opentox.org%2Fapi%2F1.1%23EINECSDefault"))
                        .orElse("").toString();
                String iuclid5 = Optional.ofNullable(de.getValues().get(
                        "https://apps.ideaconsult.net/enmtest/feature/http%3A%2F%2Fwww.opentox.org%2Fapi%2F1.1%23IUCLID5_UUIDDefault"))
                        .orElse("").toString();
                String inchi = Optional.ofNullable(de.getValues().get(
                        "https://apps.ideaconsult.net/enmtest/feature/http%3A%2F%2Fwww.opentox.org%2Fapi%2F1.1%23InChI_stdDefault"))
                        .orElse("").toString();
                String reach = Optional.ofNullable(de.getValues().get(
                        "https://apps.ideaconsult.net/enmtest/feature/http%3A%2F%2Fwww.opentox.org%2Fapi%2F1.1%23REACHRegistrationDateDefault"))
                        .orElse("").toString();
                String iupac = Optional.ofNullable(de.getValues().get(
                        "https://apps.ideaconsult.net/enmtest/feature/http%3A%2F%2Fwww.opentox.org%2Fapi%2F1.1%23IUPACNameDefault"))
                        .orElse("").toString();

                Map<String, String> structuresMap = new HashMap<>();
                structuresMap.put("Compound", compound);
                structuresMap.put("CasRN", casrn);
                structuresMap.put("EC number", einecs);
                structuresMap.put("REACH registration date", reach);
                structuresMap.put("IUCLID 5 Reference substance UUID", iuclid5);
                structuresMap.put("Std. InChI", inchi);
                structuresMap.put("IUPAC name", iupac);

                return structuresMap;
            }).collect(Collectors.toList());
            parameters.put("structures", structuresList);
        } else {
            List<Map<String, String>> structuresList = new ArrayList<>();
            Map<String, String> structuresMap = new HashMap<>();
            structuresMap.put("Compound", "");
            structuresMap.put("CasRN", "");
            structuresMap.put("EC number", "");
            structuresMap.put("REACH registration date", "");
            structuresMap.put("IUCLID 5 Reference substance UUID", "");
            structuresMap.put("Std. InChI", "");
            structuresMap.put("IUPAC name", "");
            structuresList.add(structuresMap);
            parameters.put("structures", structuresList);
        }

        parameters.put("predictedFeature", model.getPredictedFeatures().stream().findFirst()
                .orElseThrow(() -> new BadRequestException("Model does not have a valid predicted feature")));

        parameters.put("algorithm", algorithmHandler.find(model.getAlgorithm().getId()));
        parameters.put("substanceURI", substanceURI);
        if (model.getLinkedModels() != null && !model.getLinkedModels().isEmpty()) {
            Model doa = modelHandler.find(model.getLinkedModels().get(0).split("model/")[1]);
            if (doa != null) {
                parameters.put("doaURI", doa.getPredictedFeatures().get(0));
                parameters.put("doaMethod", doa.getAlgorithm().getId());
            }
        }
        TrainingRequest request = new TrainingRequest();

        request.setDataset(trainingDS);
        request.setParameters(parameters);
        request.setPredictionFeature(model.getDependentFeatures().stream().findFirst()
                .orElseThrow(() -> new BadRequestException("Model does not have a valid prediction feature")));

        return Response.ok(request).build();
        //        Report report = client.target("http://147.102.82.32:8094/pws/qprf")
        //                .request()
        //                .header("Content-Type", MediaType.APPLICATION_JSON)
        //                .accept(MediaType.APPLICATION_JSON)
        //                .post(Entity.json(request), Report.class);
        //
        //        report.setMeta(MetaInfoBuilder.builder()
        //                .addTitles(title)
        //                .addDescriptions(description)
        //                .addCreators(securityContext.getUserPrincipal().getName())
        //                .build()
        //        );
        //        report.setId(new ROG(true).nextString(15));
        //        report.setVisible(Boolean.TRUE);
        //        reportHandler.create(report);
        //
        //        return Response.ok(report).build();
    }
}