<commit_before>package fi.nls.oskari.map.analysis.service;

import fi.nls.oskari.analysis.AnalysisHelper;
import fi.nls.oskari.domain.User;
import fi.nls.oskari.domain.map.analysis.Analysis;
import fi.nls.oskari.domain.map.analysis.AnalysisStyle;
import fi.nls.oskari.log.LogFactory;
import fi.nls.oskari.log.Logger;
import fi.nls.oskari.map.analysis.domain.AnalysisLayer;
import fi.nls.oskari.map.analysis.domain.AnalysisMethodParams;
import fi.nls.oskari.util.ConversionHelper;
import fi.nls.oskari.util.IOHelper;
import fi.nls.oskari.util.JSONHelper;
import fi.nls.oskari.util.PropertyUtil;
import org.json.JSONException;
import org.json.JSONObject;

import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;

public class AnalysisDataService {
    private static final String ANALYSIS_INPUT_TYPE_GS_VECTOR = "gs_vector";

    public static final String ANALYSIS_GEOMETRY_FIELD = "geometry";

    private static final String NUMERIC_FIELD_TYPE = "numeric";
    private static final String STRING_FIELD_TYPE = "string";

    private static final Logger log = LogFactory
            .getLogger(AnalysisDataService.class);

    private static final AnalysisStyleDbService styleService = new AnalysisStyleDbServiceIbatisImpl();
    private static final AnalysisDbService analysisService = new AnalysisDbServiceIbatisImpl();
    private static final TransformationService transformationService = new TransformationService();

    public Analysis storeAnalysisData(final String featureset,
                                      AnalysisLayer analysislayer, String json, User user) {

        final String wfsURL = PropertyUtil.get("geoserver.wfs.url");
        final String wpsUser = PropertyUtil.get("geoserver.wms.user");
        final String wpsUserPass = PropertyUtil.get("geoserver.wms.pass");

        final AnalysisStyle style = new AnalysisStyle();
        final Analysis analysis = new Analysis();

        try {
            // Insert style row
            final JSONObject stylejs = JSONHelper
                    .createJSONObject(analysislayer.getStyle());
            style.populateFromJSON(stylejs);
        } catch (JSONException e) {
            log.debug("Unable to get AnalysisLayer style JSON", e);
        }
        // FIXME: do we really want to insert possibly empty style??
        log.debug("Adding style", style);
        styleService.insertAnalysisStyleRow(style);

        try {
            // Insert analysis row
            // --------------------
            analysis.setAnalyse_json(json.toString());
            analysis.setLayer_id(analysislayer.getId());
            analysis.setName(analysislayer.getName());
            analysis.setStyle_id(style.getId());
            analysis.setUuid(user.getUuid());
            if(analysislayer.getOverride_sld() != null && !analysislayer.getOverride_sld().isEmpty()) analysis.setOverride_SLD(analysislayer.getOverride_sld());
            log.debug("Adding analysis row", analysis);
            analysisService.insertAnalysisRow(analysis);

            // Add analysis_data rows via WFS-T
            // ----------------------------------

            // Convert featureset (wps) to wfs-t
            // ----------------------------------
            final AnalysisMethodParams params = analysislayer
                    .getAnalysisMethodParams();
            final String geometryProperty = transformationService.stripNamespace(params.getGeom());
            // FIXME: wpsToWfst populates fields list AND returns the wfst
            // payload
            // this should be refactored so it returns an object with the fields
            // list and the payload
            // and remove the fields parameter from call
            List<String> fields = new ArrayList<String>();
            final String wfst = transformationService.wpsFeatureCollectionToWfst(featureset, analysis.getUuid(),
                    analysis.getId(), fields, analysislayer.getFieldtypeMap(), geometryProperty, params.getResponsePrefix());
            log.debug("Produced WFS-T:\n" + wfst);

            final String response = IOHelper.httpRequestAction(wfsURL, wfst,
                    wpsUser, wpsUserPass, null, null, "application/xml");
            log.debug("Posted WFS-T, got", response);

            // If exceptions, return null
            // Check, if exception result set
            if (response.indexOf("ows:Exception") > -1) return null;

            // Check, if any inserted data
            if (response.indexOf("totalInserted>0") > -1) return null;


            // Update col mapping and WPS layer Id into analysis table
            // ---------------------------------------
            // if analysis in analysis - fix field names to original
            if (analysislayer.getInputType().equals(
                    ANALYSIS_INPUT_TYPE_GS_VECTOR)) {
                if (analysislayer.getInputAnalysisId() != null) {
                    fields = this.SwapAnalysisInAnalysisFields(fields,
                            analysislayer.getInputAnalysisId());
                }
            }
            analysis.setCols(fields);

            log.debug("Update analysis row", analysis);
            int updrows = analysisService.updateAnalysisCols(analysis);
            log.debug("Updated rows", updrows);

        } catch (Exception e) {
            log
                    .debug(
                            "Unable to transform WPS to WFS-T or to store analysis data",
                            e);
            return null;
        }

        return analysis;
    }

    /**
     * Merge analyses to one new analyse
     *
     * @param analysislayer data for new analyse
     * @param json          params of executed analyse
     * @param user
     * @return Analysis (stored analysis)
     */

    public Analysis mergeAnalysisData(AnalysisLayer analysislayer, String json, User user) {

        final AnalysisStyle style = new AnalysisStyle();
        Analysis analysis = null;

        try {
            // Insert style row
            final JSONObject stylejs = JSONHelper
                    .createJSONObject(analysislayer.getStyle());
            style.populateFromJSON(stylejs);
        } catch (JSONException e) {
            log.debug("Unable to get AnalysisLayer style JSON", e);
        }
        // FIXME: do we really want to insert possibly empty style??
        log.debug("Adding style", style);
        styleService.insertAnalysisStyleRow(style);
        // Get analysis Ids for to merge
        List<Long> ids = analysislayer.getMergeAnalysisIds();
        // at least two layers must be  for merge
        if (ids.size() < 2) return null;

        try {
            // Insert analysis row - use old for seed
            analysis = analysisService.getAnalysisById(ids.get(0));
            // --------------------
            analysis.setAnalyse_json(json.toString());
            analysis.setLayer_id(analysislayer.getId());
            analysis.setName(analysislayer.getName());
            analysis.setStyle_id(style.getId());
            analysis.setUuid(user.getUuid());
            analysis.setOld_id(ids.get(0));
            log.debug("Adding analysis row", analysis);
            analysisService.insertAnalysisRow(analysis);

            // Merge analysis_data
            // ----------------------------------
            log.debug("Merge analysis_data rows", analysis);
            analysisService.mergeAnalysis(analysis, ids);
<commit_msg>Added a shortcut method for getting analysis from database<commit_after>package fi.nls.oskari.map.analysis.service;

import fi.nls.oskari.analysis.AnalysisHelper;
import fi.nls.oskari.domain.User;
import fi.nls.oskari.domain.map.analysis.Analysis;
import fi.nls.oskari.domain.map.analysis.AnalysisStyle;
import fi.nls.oskari.log.LogFactory;
import fi.nls.oskari.log.Logger;
import fi.nls.oskari.map.analysis.domain.AnalysisLayer;
import fi.nls.oskari.map.analysis.domain.AnalysisMethodParams;
import fi.nls.oskari.util.ConversionHelper;
import fi.nls.oskari.util.IOHelper;
import fi.nls.oskari.util.JSONHelper;
import fi.nls.oskari.util.PropertyUtil;
import org.json.JSONException;
import org.json.JSONObject;

import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;

public class AnalysisDataService {
    private static final String ANALYSIS_INPUT_TYPE_GS_VECTOR = "gs_vector";

    public static final String ANALYSIS_GEOMETRY_FIELD = "geometry";

    private static final String NUMERIC_FIELD_TYPE = "numeric";
    private static final String STRING_FIELD_TYPE = "string";

    private static final Logger log = LogFactory
            .getLogger(AnalysisDataService.class);

    private static final AnalysisStyleDbService styleService = new AnalysisStyleDbServiceIbatisImpl();
    private static final AnalysisDbService analysisService = new AnalysisDbServiceIbatisImpl();
    private static final TransformationService transformationService = new TransformationService();

    public Analysis storeAnalysisData(final String featureset,
                                      AnalysisLayer analysislayer, String json, User user) {

        final String wfsURL = PropertyUtil.get("geoserver.wfs.url");
        final String wpsUser = PropertyUtil.get("geoserver.wms.user");
        final String wpsUserPass = PropertyUtil.get("geoserver.wms.pass");

        final AnalysisStyle style = new AnalysisStyle();
        final Analysis analysis = new Analysis();

        try {
            // Insert style row
            final JSONObject stylejs = JSONHelper
                    .createJSONObject(analysislayer.getStyle());
            style.populateFromJSON(stylejs);
        } catch (JSONException e) {
            log.debug("Unable to get AnalysisLayer style JSON", e);
        }
        // FIXME: do we really want to insert possibly empty style??
        log.debug("Adding style", style);
        styleService.insertAnalysisStyleRow(style);

        try {
            // Insert analysis row
            // --------------------
            analysis.setAnalyse_json(json.toString());
            analysis.setLayer_id(analysislayer.getId());
            analysis.setName(analysislayer.getName());
            analysis.setStyle_id(style.getId());
            analysis.setUuid(user.getUuid());
            if(analysislayer.getOverride_sld() != null && !analysislayer.getOverride_sld().isEmpty()) analysis.setOverride_SLD(analysislayer.getOverride_sld());
            log.debug("Adding analysis row", analysis);
            analysisService.insertAnalysisRow(analysis);

            // Add analysis_data rows via WFS-T
            // ----------------------------------

            // Convert featureset (wps) to wfs-t
            // ----------------------------------
            final AnalysisMethodParams params = analysislayer
                    .getAnalysisMethodParams();
            final String geometryProperty = transformationService.stripNamespace(params.getGeom());
            // FIXME: wpsToWfst populates fields list AND returns the wfst
            // payload
            // this should be refactored so it returns an object with the fields
            // list and the payload
            // and remove the fields parameter from call
            List<String> fields = new ArrayList<String>();
            final String wfst = transformationService.wpsFeatureCollectionToWfst(featureset, analysis.getUuid(),
                    analysis.getId(), fields, analysislayer.getFieldtypeMap(), geometryProperty, params.getResponsePrefix());
            log.debug("Produced WFS-T:\n" + wfst);

            final String response = IOHelper.httpRequestAction(wfsURL, wfst,
                    wpsUser, wpsUserPass, null, null, "application/xml");
            log.debug("Posted WFS-T, got", response);

            // If exceptions, return null
            // Check, if exception result set
            if (response.indexOf("ows:Exception") > -1) return null;

            // Check, if any inserted data
            if (response.indexOf("totalInserted>0") > -1) return null;


            // Update col mapping and WPS layer Id into analysis table
            // ---------------------------------------
            // if analysis in analysis - fix field names to original
            if (analysislayer.getInputType().equals(
                    ANALYSIS_INPUT_TYPE_GS_VECTOR)) {
                if (analysislayer.getInputAnalysisId() != null) {
                    fields = this.SwapAnalysisInAnalysisFields(fields,
                            analysislayer.getInputAnalysisId());
                }
            }
            analysis.setCols(fields);

            log.debug("Update analysis row", analysis);
            int updrows = analysisService.updateAnalysisCols(analysis);
            log.debug("Updated rows", updrows);

        } catch (Exception e) {
            log
                    .debug(
                            "Unable to transform WPS to WFS-T or to store analysis data",
                            e);
            return null;
        }

        return analysis;
    }

    public Analysis getAnalysisById(long id) {
        return analysisService.getAnalysisById(id);
    }

    /**
     * Merge analyses to one new analyse
     *
     * @param analysislayer data for new analyse
     * @param json          params of executed analyse
     * @param user
     * @return Analysis (stored analysis)
     */
    public Analysis mergeAnalysisData(AnalysisLayer analysislayer, String json, User user) {

        final AnalysisStyle style = new AnalysisStyle();
        Analysis analysis = null;

        try {
            // Insert style row
            final JSONObject stylejs = JSONHelper
                    .createJSONObject(analysislayer.getStyle());
            style.populateFromJSON(stylejs);
        } catch (JSONException e) {
            log.debug("Unable to get AnalysisLayer style JSON", e);
        }
        // FIXME: do we really want to insert possibly empty style??
        log.debug("Adding style", style);
        styleService.insertAnalysisStyleRow(style);
        // Get analysis Ids for to merge
        List<Long> ids = analysislayer.getMergeAnalysisIds();
        // at least two layers must be  for merge
        if (ids.size() < 2) return null;

        try {
            // Insert analysis row - use old for seed
            analysis = getAnalysisById(ids.get(0));
            // --------------------
            analysis.setAnalyse_json(json.toString());
            analysis.setLayer_id(analysislayer.getId());
            analysis.setName(analysislayer.getName());
            analysis.setStyle_id(style.getId());
            analysis.setUuid(user.getUuid());
            analysis.setOld_id(ids.get(0));
            log.debug("Adding analysis row", analysis);
            analysisService.insertAnalysisRow(analysis);

            // Merge analysis_data
            // ----------------------------------
            log.debug("Merge analysis_data rows", analysis);
            analysisService.mergeAnalysis(analysis, ids);

{'fraction_non_alphanumeric': 0.11235138705416116, 'fraction_numerical': 0.0007926023778071334, 'mean_word_length': 2.1032998565279772, 'pattern_counts': {'":': 0, '<': 11, '<?xml version=': 0, '>': 15, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 2}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 2, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '3440659', 'n_tokens_mistral': 3796, 'n_tokens_neox': 3716, 'n_words': 954}